最近事情太多,又有一段时间没做笔记了,有时候也在研究这个百敖的UIAPP框架和昆仑的UIAPP框架,思绪短时间内难理清,还是先写下SMBIOS的有关内容吧,本节主要以实践为主,仅做记录
这个protocol就是操作smbios内容的,smbios怎么加载的,这个就有待去了解了,而且代码本身大部分是做好的,来看下这个protocol的里面包含了什么
struct _EFI_SMBIOS_PROTOCOL {
EFI_SMBIOS_ADD Add;
EFI_SMBIOS_UPDATE_STRING UpdateString;
EFI_SMBIOS_REMOVE Remove;
EFI_SMBIOS_GET_NEXT GetNext;
UINT8 MajorVersion; ///< The major revision of the SMBIOS specification supported.
UINT8 MinorVersion; ///< The minor revision of the SMBIOS specification supported.
};
SMBIOS的操作给我的感觉就跟套公式一样的,咱们打开这个protocol:
// open the SMBIOS protocol
EFI_SMBIOS_PROTOCOL *Smbios;
Status = gBS->LocateProtocol (
&gEfiSmbiosProtocolGuid,
NULL,
(VOID**)&Smbios
);
if (EFI_ERROR (Status)) {
return Status;
}
打开之后,咱们使用里面的方法:
在SmbiosTablePublishEntry函数,也就是SMBIOS驱动的入口,一般逻辑是这样的,很多需要的type都会进行初始化,并通过一个void的指针去逐一的加载这些type,然后有些type可能需要写一些自己主板的特性,那么你再去单独加入更新,咱们以增加type21为例子,在打开smbios的protocol之后,咱们在它的下面新建一个函数:
Status= InstallType21Seructures(Smbios);
这个函数给我们的smbiostable新增了一个type,看下这个type的里面是啥:
typedef struct {
SMBIOS_STRUCTURE Hdr;
UINT8 Type; ///< The enumeration value from BUILTIN_POINTING_DEVICE_TYPE.
UINT8 Interface; ///< The enumeration value from BUILTIN_POINTING_DEVICE_INTERFACE.
UINT8 NumberOfButtons;
} SMBIOS_TABLE_TYPE21;
typedef struct {
SMBIOS_TYPE Type;
UINT8 Length;
SMBIOS_HANDLE Handle;
} SMBIOS_STRUCTURE;
通过上面的基础咱们就可以安装这个type,具体的值我瞎写的,有些值不在范围内它在系统内是反馈无效的,下面就是安装的过程,非常容易
EFI_STATUS InstallType21Seructures (IN EFI_SMBIOS_PROTOCOL *Smbios)
{
EFI_STATUS Status = EFI_SUCCESS;
SMBIOS_TABLE_TYPE21 *Type21Record;
EFI_SMBIOS_HANDLE BuiltSmbiosHandle;
Type21Record = NULL;
Type21Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE21) + 2);
if(Type21Record == NULL){
Status = EFI_OUT_OF_RESOURCES;
}
BuiltSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
Type21Record->Hdr.Type = SMBIOS_TYPE_BUILT_IN_POINTING_DEVICE;
Type21Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE21);
Type21Record->Hdr.Handle = 0;
Type21Record->Type = 21;
Type21Record->Interface=0;
Type21Record->NumberOfButtons=0;
Status = Smbios->Add (Smbios, NULL, &BuiltSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*)Type21Record);
FreePool (Type21Record);
return Status;
}
解释一下几个关键的内容,SMBIOS_TYPE_BUILT_IN_POINTING_DEVICE的值为21,SMBIOS_HANDLE_PI_RESERVED为0xFFFE,这个值不是随便写的,而是自动分配的一个编号,也就是说你取值为0xFFFE的时候,会自动给这个type分配编号,在什么smbios信息中,这个handle的值就是这么来的,写完后编译,我们进入系统查看一下,是否生成安装了type21
可以看到,一个新的type就这样生成了,有了这个type21,那么怎么去获取并修改它呢,咱们就以type1为例子,需要用到GetNext和UpdateString,一般如果你要提取smbiostable里面的新信息,使用前者就行,如果需要修改信息,那么两者都需要使用。
EFI_STATUS UpdateType1Seructures (IN EFI_SMBIOS_PROTOCOL *Smbios)
{
EFI_STATUS Status;
EFI_SMBIOS_HANDLE SmbiosHandle;
EFI_SMBIOS_TYPE SmbiosType;
EFI_SMBIOS_TABLE_HEADER *SmbiosHdr;
SMBIOS_STRUCTURE_POINTER p;
UINTN StringNum;
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
SmbiosType = SMBIOS_TYPE_SYSTEM_INFORMATION;
Status = Smbios->GetNext(Smbios, &SmbiosHandle, &SmbiosType, &SmbiosHdr, NULL);
if (!EFI_ERROR (Status)){
// update board version
p.Hdr = SmbiosHdr;
StringNum = p.Type1->ProductName;
Status = Smbios->UpdateString(Smbios,&SmbiosHandle,&StringNum, "Anthony-PC");
}
else{
return Status;
}
return Status;
}
编译,我们查看效果,Product Name是不是变成了我们想要的名称呢
如果我们的BIOS界面有需要用到这些信息,比如product name需要在BIOS界面下显示,应该如何操作呢,我们可以通过如下的代码形式进行;
EFI_SMBIOS_HANDLE SmbiosHandle;
EFI_SMBIOS_PROTOCOL *Smbios;
SMBIOS_TABLE_TYPE1 *Type1Record;
EFI_SMBIOS_TABLE_HEADER *Record;
Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios);
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
while (!EFI_ERROR(Status)) {
if (Record->Type == SMBIOS_TYPE_SYSTEM_INFORMATION) {
Type1Record = (SMBIOS_TABLE_TYPE1 *) Record;
StrIndex = Type1Record->ProductName;
GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString);
UiCustomizeFrontPageBanner (1, TRUE, &NewString);
HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NewString, NULL);
FreePool (NewString);
}
}
//其中GetOptionalStringByIndex函数如下,供代码理解
EFI_STATUS
GetOptionalStringByIndex (
IN CHAR8 *OptionalStrStart,
IN UINT8 Index,
OUT CHAR16 **String
)
{
UINTN StrSize;
if (Index == 0) {
*String = AllocateZeroPool (sizeof (CHAR16));
return EFI_SUCCESS;
}
StrSize = 0;
do {
Index--;
OptionalStrStart += StrSize;
StrSize = AsciiStrSize (OptionalStrStart);
} while (OptionalStrStart[StrSize] != 0 && Index != 0);
if ((Index != 0) || (StrSize == 1)) {
//
// Meet the end of strings set but Index is non-zero, or
// Find an empty string
//
*String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
} else {
*String = AllocatePool (StrSize * sizeof (CHAR16));
AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize);
}
return EFI_SUCCESS;
}
ok,smbios的一些内容的笔记就先做到这里