2. SMBIOS规范解读:3.x与2.x版本差异、Entry Point结构、Table结构、字符串引用机制
2.1 版本演进概述
SMBIOS规范从2.x演进到3.x,核心变化在于Entry Point结构、物理内存布局以及对大容量固件的支持。3.x版本解决了2.x版本在64位系统、大内存映射和固件体积膨胀方面的瓶颈。
| 对比维度 | SMBIOS 2.x | SMBIOS 3.x |
|---|---|---|
| Entry Point结构 | EPS位于F0000h–FFFFFh之间,固定15字节Anchor String "_SM_" | EPS可位于扩展BIOS区域或UEFI引导服务数据区,Anchor String "_SM3_" |
| Entry Point长度 | 31字节(含Intermediate EPS) | 24字节(精简结构,无Intermediate EPS) |
| Table最大地址 | 32位物理地址(4GB限制) | 64位物理地址(支持大内存映射) |
| Table Entry最大数量 | 受限于EPS中Structure Table Length(16位) | 支持更大Table,通过Table Maximum Size字段扩展 |
| 文档版本 | 2.8.x及之前 | 3.0.0及之后 |
2.2 Entry Point结构对比
2.2.1 SMBIOS 2.x Entry Point(31字节)
2.x Entry Point由两部分组成:EPS(Entry Point Structure)和Intermediate EPS。EPS位于物理地址F0000h–FFFFFh之间的2KB边界上,必须包含Anchor String "_SM_"。Intermediate EPS紧随其后,包含Table地址和长度信息。
// SMBIOS 2.x Entry Point 结构
struct SMBIOS2EntryPoint {
// EPS (15 bytes)
char AnchorString[4]; // "_SM_"
uint8_t Checksum; // EPS校验和
uint8_t EntryPointLength; // 0x1F (31)
uint8_t MajorVersion; // 主版本号
uint8_t MinorVersion; // 次版本号
uint16_t MaxStructureSize; // 最大结构大小
uint8_t EntryPointRevision; // 0x00
uint8_t FormattedArea[5]; // 保留
// Intermediate EPS (16 bytes)
char IntermediateAnchor[4]; // "_DMI_"
uint8_t IntermediateChecksum; // Intermediate EPS校验和
uint16_t StructureTableLength; // Table总长度
uint32_t StructureTableAddress; // Table物理地址(32位)
uint16_t NumberOfStructures; // 结构数量
uint8_t BCDRevision; // BCD格式版本
};
2.2.2 SMBIOS 3.x Entry Point(24字节)
3.x Entry Point取消了Intermediate EPS,所有信息集中在单一结构中。Anchor String变为"_SM3_",Table地址扩展为64位,并新增Table Maximum Size字段。
// SMBIOS 3.x Entry Point 结构
struct SMBIOS3EntryPoint {
char AnchorString[5]; // "_SM3_"
uint8_t Checksum; // EPS校验和
uint8_t EntryPointLength; // 0x18 (24)
uint8_t MajorVersion; // 主版本号
uint8_t MinorVersion; // 次版本号
uint8_t DocRev; // 文档修订号
uint8_t EntryPointRevision; // 0x01
uint8_t Reserved; // 保留
uint32_t TableMaximumSize; // Table最大尺寸(字节)
uint64_t TableAddress; // Table物理地址(64位)
};
2.3 Table结构
SMBIOS Table由一系列Structure Entry组成,每个Entry以Type、Length和Handle开头,后接结构体数据,最后以双零终止符结束。所有Entry在物理内存中连续排列,直到遇到Type=127的End-of-Table结构。
// SMBIOS Structure Entry 通用头部
struct SMBIOSStructureHeader {
uint8_t Type; // 结构类型(0–127)
uint8_t Length; // 结构体数据长度(不含字符串)
uint16_t Handle; // 唯一句柄
// 结构体数据...
// 字符串区域(以双零 \0\0 结束)
};
2.3.1 结构类型分类
| 类型范围 | 说明 | 示例 |
|---|---|---|
| 0–127 | 标准结构(由DMTF定义) | Type 0 (BIOS Information), Type 1 (System Information) |
| 128–255 | OEM/自定义结构 | 厂商自定义数据 |
| 127 | End-of-Table | 标记Table结束 |
2.4 字符串引用机制
SMBIOS结构体中的字符串字段不直接存储字符串内容,而是存储字符串索引(从1开始)。索引指向结构体末尾的字符串区域,该区域由一系列以\0结尾的ASCII字符串组成,最后以\0\0结束。
- 索引值 1 指向字符串区域中的第一个字符串。
- 索引值 2 指向第二个字符串,以此类推。
- 索引值 0 表示该字段为空(无字符串)。
- 字符串区域紧跟在结构体数据之后,从
header.Length偏移处开始。
2.4.1 字符串解析示例
假设一个Type 1(System Information)结构,其结构体数据长度为0x19(25字节),字符串区域包含以下内容:
偏移 0x19: "Dell Inc.\0" // 字符串1 (Manufacturer)
偏移 0x24: "PowerEdge R750\0" // 字符串2 (Product Name)
偏移 0x35: "2.1.0\0" // 字符串3 (Version)
偏移 0x3B: "\0\0" // 字符串区域结束
若结构体中 Manufacturer 字段值为 1,则指向 "Dell Inc.";ProductName 字段值为 2,则指向 "PowerEdge R750"。
2.5 Entry Point与Table关系图
下图展示了SMBIOS 3.x Entry Point与Table在物理内存中的布局关系,以及Table内部Structure Entry的串联方式。
2.6 字符串引用机制示意图
下图以Type 1结构为例,展示字符串索引如何指向字符串区域中的具体字符串。
2.7 版本迁移实战要点
- 扫描顺序: 优先扫描"_SM3_"(3.x),若未找到再扫描"_SM_"(2.x)。3.x Entry Point可能位于UEFI配置表或ACPI表中。
- 地址解析: 3.x使用64位TableAddress,解析时需使用uint64_t类型;2.x使用32位StructureTableAddress,注意地址转换。
- Table大小: 3.x通过TableMaximumSize字段获取Table最大尺寸,2.x通过StructureTableLength获取实际长度。
- 字符串解析: 无论2.x还是3.x,字符串引用机制完全一致,索引从1开始,0表示空。
- 校验和验证: 3.x仅需验证EPS的Checksum字段;2.x需要分别验证EPS和Intermediate EPS的校验和。