UEFI学习笔记(十一):SMBIOS的概述与访问
-
- 一、概述
- 二、SMBIOS结构
- 三、SMBIOS的访问
-
- [1、获取 SMBIOS 入口点](#1、获取 SMBIOS 入口点)
- 2、初始化和检查入口点
- [3、访问 SMBIOS 结构表](#3、访问 SMBIOS 结构表)
- [4、遍历 SMBIOS 结构](#4、遍历 SMBIOS 结构)
- 5、解析每个结构
- 6、输出信息
- 7、错误处理
一、概述
SMBIOS(System Management BIOS)是一种在计算机系统中用于管理和获取硬件信息的标准接口。它提供了一种结构化的方式,通过 BIOS 来传递有关系统硬件的详细信息,包括处理器、内存、主板、以及其他组件的信息。SMBIOS 数据结构以表的形式存在,通常在系统启动时由 BIOS 提供,操作系统可以通过读取这些表来获取所需的信息。SMBIOS 主要用于以下目的:
1、硬件信息获取:
操作系统和应用程序可以通过 SMBIOS 查询硬件信息,以便更好地管理系统资源。
2、系统管理:
系统管理软件可以利用 SMBIOS 提供的信息进行资产管理、系统监控和故障排除。
3、与固件的交互:
SMBIOS 使得操作系统能够与固件进行有效的交互,获取系统硬件配置的相关信息。
二、SMBIOS结构
可以通过基于表结构访问 SMBIOS 。先找到 Entry Point Structure ( EPS )表,然后通过 Entry Point Structure ( EPS )表的数据找到 SMBIOS 结构表。以下是 EPS 表的结构:
c
typedef struct {
UINT8 AnchorString[4]; //关键字 固定是"_SM_"
UINT8 EntryPointStructureChecksum; //校验和 用于校验数据
UINT8 EntryPointLength; //表结构长度 Entry Point Structure 表的长度
UINT8 MajorVersion; //Major版本号 用于判断SMBIOS 版本
UINT8 MinorVersion; //Minor版本号 用于判断SMBIOS 版本
UINT16 MaxStructureSize; //表结构大小
UINT8 EntryPointRevision; //EPS修正
UINT8 FormattedArea[5]; //格式区域 存放解释EPS修正的信息
UINT8 IntermediateAnchorString[5]; //关键字 固定为"_DMI_"
UINT8 IntermediateChecksum; //校验和 Intermediate Entry Point Structure (IEPS)的校验和
UINT16 TableLength; //结构表长度 SMBIOS 结构表的长度(总长度)
UINT32 TableAddress; //结构表地址 SMBIOS 结构表的真实内存位置
UINT16 NumberOfSmbiosStructures; //结构表个数 SMBIOS 结构表数目
UINT8 SmbiosBcdRevision; //Smbios BCD 修正
} SMBIOS_TABLE_ENTRY_POINT;
主要用于描述 SMBIOS 的入口点。这个结构包含了有关 SMBIOS 数据表的信息,并为系统提供了访问这些信息的方式。可以通过TableAddress访问到SMBIOS的首地址,然后访问表结构信息:
c
typedef union {
SMBIOS_STRUCTURE *Hdr;
SMBIOS_TABLE_TYPE0 *Type0;
SMBIOS_TABLE_TYPE1 *Type1;
SMBIOS_TABLE_TYPE2 *Type2;
SMBIOS_TABLE_TYPE3 *Type3;
SMBIOS_TABLE_TYPE4 *Type4;
SMBIOS_TABLE_TYPE5 *Type5;
SMBIOS_TABLE_TYPE6 *Type6;
SMBIOS_TABLE_TYPE7 *Type7;
SMBIOS_TABLE_TYPE8 *Type8;
SMBIOS_TABLE_TYPE9 *Type9;
SMBIOS_TABLE_TYPE10 *Type10;
SMBIOS_TABLE_TYPE11 *Type11;
SMBIOS_TABLE_TYPE12 *Type12;
SMBIOS_TABLE_TYPE13 *Type13;
SMBIOS_TABLE_TYPE14 *Type14;
SMBIOS_TABLE_TYPE15 *Type15;
SMBIOS_TABLE_TYPE16 *Type16;
SMBIOS_TABLE_TYPE17 *Type17;
SMBIOS_TABLE_TYPE18 *Type18;
SMBIOS_TABLE_TYPE19 *Type19;
SMBIOS_TABLE_TYPE20 *Type20;
SMBIOS_TABLE_TYPE21 *Type21;
SMBIOS_TABLE_TYPE22 *Type22;
SMBIOS_TABLE_TYPE23 *Type23;
SMBIOS_TABLE_TYPE24 *Type24;
SMBIOS_TABLE_TYPE25 *Type25;
SMBIOS_TABLE_TYPE26 *Type26;
SMBIOS_TABLE_TYPE27 *Type27;
SMBIOS_TABLE_TYPE28 *Type28;
SMBIOS_TABLE_TYPE29 *Type29;
SMBIOS_TABLE_TYPE30 *Type30;
SMBIOS_TABLE_TYPE31 *Type31;
SMBIOS_TABLE_TYPE32 *Type32;
SMBIOS_TABLE_TYPE33 *Type33;
SMBIOS_TABLE_TYPE34 *Type34;
SMBIOS_TABLE_TYPE35 *Type35;
SMBIOS_TABLE_TYPE36 *Type36;
SMBIOS_TABLE_TYPE37 *Type37;
SMBIOS_TABLE_TYPE38 *Type38;
SMBIOS_TABLE_TYPE39 *Type39;
SMBIOS_TABLE_TYPE40 *Type40;
SMBIOS_TABLE_TYPE41 *Type41;
SMBIOS_TABLE_TYPE42 *Type42;
SMBIOS_TABLE_TYPE43 *Type43;
SMBIOS_TABLE_TYPE126 *Type126;
SMBIOS_TABLE_TYPE127 *Type127;
UINT8 *Raw;
} SMBIOS_STRUCTURE_POINTER;
在 SMBIOS(System Management BIOS)中,类型 0 到类型 127 表示不同的结构,每种结构都包含特定的硬件和系统信息。例如:
类型 0:
BIOS 信息。包含 BIOS 制造商、版本、发布日期等信息。
类型 1:
系统信息。包含系统制造商、产品名称、版本、序列号等信息。
c
///
/// BIOS Information (Type 0).
///
typedef struct {
SMBIOS_STRUCTURE Hdr;
SMBIOS_TABLE_STRING Vendor;
SMBIOS_TABLE_STRING BiosVersion;
UINT16 BiosSegment;
SMBIOS_TABLE_STRING BiosReleaseDate;
UINT8 BiosSize;
MISC_BIOS_CHARACTERISTICS BiosCharacteristics;
UINT8 BIOSCharacteristicsExtensionBytes[2];
UINT8 SystemBiosMajorRelease;
UINT8 SystemBiosMinorRelease;
UINT8 EmbeddedControllerFirmwareMajorRelease;
UINT8 EmbeddedControllerFirmwareMinorRelease;
//
// Add for smbios 3.1.0
//
EXTENDED_BIOS_ROM_SIZE ExtendedBiosSize;
} SMBIOS_TABLE_TYPE0;
类型 2:
基本硬件信息。包含系统的硬件特性,如主板制造商、产品、版本等。
类型 3:
设备信息。包含设备的详细信息,如物理 ID 和设备类型。
类型 4:
内存信息。描述系统内存的详细信息,包括内存条的大小和速度。
...
...
第一个字段SMBIOS_STRUCTURE *Hdr可以访问到SMBIOS 中的一个结构头部
c
typedef struct {
SMBIOS_TYPE Type;
UINT8 Length;
SMBIOS_HANDLE Handle;
} SMBIOS_STRUCTURE;
Type:
这个字段表示 SMBIOS 结构的类型。每种类型的结构都有特定的格式和信息。例如,类型 0 代表 BIOS 信息,类型 1 代表系统信息等。
Length:
该字段表示整个 SMBIOS 结构的长度(以字节为单位),包括头部和后续数据。
Handle:
这个字段是一个句柄,通常用来唯一标识该结构实例。它在同一类型的结构之间是唯一的,可以用于查找或引用。
三、SMBIOS的访问
在smbiosview源码中,Smbios数据的访问流程如下:
1、获取 SMBIOS 入口点
使用特定的内存地址或系统调用获取 SMBIOS 表的入口点(Entry Point Structure, EPS)。
c
SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable;
SMBiosTable = NULL;
LibSmbios64BitGetEPS (&SMBiosTable);
2、初始化和检查入口点
检查获取到的 EPS 是否有效,验证其 AnchorString 字段是否为 SM,确保表的版本和长度符合预期。
c
if (CompareMem (SMBiosTable->AnchorString, SMBIOS_3_0_ANCHOR_STRING, SMBIOS_3_0_ANCHOR_STRING_LENGTH) == 0) {
...
}
3、访问 SMBIOS 结构表
使用 EPS 中的 TableAddress 字段访问 SMBIOS 结构表,此地址指向存储 SMBIOS 结构的内存区域。
4、遍历 SMBIOS 结构
根据 EPS 中的 NumberOfStructures 字段确定要遍历的结构数量。
使用循环逐个访问 SMBIOS 结构,读取每个结构的 Type、Length 和 Handle 字段,根据 Type 字段识别结构类型,并根据需要解析结构的特定信息。
c
for (Index = 0; Index < mNumberOfSmbios64BitStructures; Index++) {
//
// if reach the end of table, break..
//
if (Handle == INVALID_HANDLE) {
break;
}
//
// handle then point to the next!
//
if (LibGetSmbios64BitStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) {
break;
}
...
...
}
5、解析每个结构
根据 SMBIOS 结构的类型(例如类型 0 到类型 127),解析每种结构的数据。对不同类型的结构提取相应的信息,如系统制造商、产品名称等。
c
SmbiosPrintStructure (&SmbiosStruct, gShowType);
6、输出信息
解析完毕后,将所有结构的相关信息输出到控制台或保存到文件中,供用户查看。
7、错误处理
在整个流程中,包含错误处理机制,以应对内存访问错误或无效数据等问题,确保程序不会因为未处理的异常而崩溃。