[OpenBMC] 简单解析 smbios-mdr

本文介绍了OpenBMC中的MDR(Managed Data Region)功能,它用于获取和解析SMBIOS表格,从而在Redfish的ProcessorCollection中展示CPU信息。SMBIOS数据可通过多种方式传递给BMC,包括MDRv1、MDRv2(Pull)、MDRv2(Push)和IPMI blobs。此外,文章还提到了CPU信息的验证过程,通过SMBIOS和EntityManagerConfig确保CPUID的合法性。
在EFI开发过程中,遇到 `Smbios->GetString` 未定义的问题,通常是因为使用的SMBIOS协议版本不兼容,或者未正确获取到 `EFI_SMBIOS_PROTOCOL` 接口。根据SMBIOS协议定义,`GetString` 是 `EFI_SMBIOS_PROTOCOL` 中用于获取字符串表中特定字符串的函数指针,其原型如下: ```c CHAR8 *(EFIAPI *GetString)(IN CONST EFI_SMBIOS_PROTOCOL *This, IN UINTN StringNumber); ``` 如果在代码中直接使用 `Smbios->GetString` 出现未定义错误,说明当前使用的 `EFI_SMBIOS_PROTOCOL` 接口指针可能未正确初始化,或者所使用的SMBIOS协议版本不支持该函数。 ### 解决方案 1. **确认是否正确获取了SMBIOS协议接口** 应通过 `gBS->LocateProtocol` 获取 `EFI_SMBIOS_PROTOCOL` 接口指针,确保其不为 NULL: ```c EFI_SMBIOS_PROTOCOL *Smbios; Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios); if (EFI_ERROR(Status)) { Print(L"Failed to locate SMBIOS protocol\n"); return Status; } ``` 2. **检查SMBIOS协议版本** `EFI_SMBIOS_PROTOCOL` 的版本由 `gEfiSmbiosProtocolGuid` 的版本号决定。确保使用的是支持 `GetString` 函数的SMBIOS协议版本(如SMBIOS 2.3或更高版本)。 3. **使用替代方式获取字符串** 如果 `GetString` 不可用,可以手动解析字符串表。SMBIOS记录的字符串存储在记录头之后,以双零(`\0\0`)结尾,每个字符串以单零(`\0`)分隔。可以通过遍历字符串表来获取指定索引的字符串: ```c CHAR8 *GetStringFromTable(EFI_SMBIOS_TABLE_HEADER *Record, UINTN StringIndex) { CHAR8 *String = (CHAR8 *)(Record + 1); UINTN i; for (i = 1; i < StringIndex; i++) { while (*String != '\0') { String++; } String++; } return String; } ``` 4. **确保编译环境支持SMBIOS协议** 在EDK II环境中,确保在 `INF` 文件中正确引用了 `gEfiSmbiosProtocolGuid` 和相关头文件,例如: ```ini [Protocols] gEfiSmbiosProtocolGuid ``` 并在代码中包含正确的头文件: ```c #include <Protocol/Smbios.h> ``` ### 示例:手动解析SMBIOS字符串 ```c EFI_STATUS EFIAPI UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_SMBIOS_PROTOCOL *Smbios; EFI_SMBIOS_HANDLE Handle; EFI_SMBIOS_TABLE_HEADER *Record; // 获取SMBIOS协议 Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios); if (EFI_ERROR(Status)) { Print(L"Failed to locate SMBIOS protocol\n"); return Status; } Handle = SMBIOS_HANDLE_PI_RESERVED; // 遍历SMBIOS记录 while ((Status = Smbios->GetNext(Smbios, &Handle, NULL, &Record)) == EFI_SUCCESS) { Print(L"SMBIOS Record Type: %d\n", Record->Type); if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) { SMBIOS_TABLE_TYPE0 *BiosInfo = (SMBIOS_TABLE_TYPE0 *)Record; CHAR8 *Vendor = Smbios->GetString(Smbios, BiosInfo->Vendor); CHAR8 *BiosVersion = Smbios->GetString(Smbios, BiosInfo->BiosVersion); Print(L" BIOS Vendor: %a\n", Vendor); Print(L" BIOS Version: %a\n", BiosVersion); } } return EFI_SUCCESS; } ```
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值