SMBIOS定制开发 - 第4节
4.1 Type 0 结构总览与字段布局
SMBIOS Type 0 是系统固件最核心的结构化描述块,它向操作系统和系统管理软件报告 BIOS 的基本身份、版本、发布日期以及一组标准化的特性位图。Type 0 结构在内存中的布局遵循 SMBIOS 2.x/3.x 规范,其头部固定为 4 字节的 Type/Length/Handle,随后是变长的字段区域。
| 偏移量 | 字段名称 | 长度(字节) | 说明 |
|---|---|---|---|
| 00h | Type | 1 | 固定为 0x00 |
| 01h | Length | 1 | 结构总长度(含头部) |
| 02h | Handle | 2 | 唯一标识符 |
| 04h | Vendor | 1 | 指向字符串表中厂商名称的索引 |
| 05h | BIOS Version | 1 | 指向字符串表中版本号的索引 |
| 06h | BIOS Starting Address Segment | 2 | BIOS 入口段地址(通常为 0xF000) |
| 08h | BIOS Release Date | 1 | 指向字符串表中发布日期的索引 |
| 09h | BIOS ROM Size | 1 | 以 64KB 为单位的 ROM 大小 |
| 0Ah | BIOS Characteristics | 8 | 64 位特性位图 |
| 12h | BIOS Characteristics Extension Bytes | 2 | 扩展特性字节(可选) |
| 14h | System BIOS Major Release | 1 | 主版本号(可选) |
| 15h | System BIOS Minor Release | 1 | 次版本号(可选) |
| 16h | Embedded Controller Firmware Major Release | 1 | EC 固件主版本(可选) |
| 17h | Embedded Controller Firmware Minor Release | 1 | EC 固件次版本(可选) |
4.2 核心字段详解
4.2.1 Vendor(厂商名称)
Vendor 字段是一个单字节索引,指向 SMBIOS 结构末尾的字符串表。该字符串应包含 BIOS 供应商的完整名称,例如 "American Megatrends Inc."、"Phoenix Technologies Ltd." 或 "Insyde Software Corp."。在定制开发中,如果基于开源固件(如 coreboot、TianoCore)构建,建议将 Vendor 设置为项目名称或公司名称。
4.2.2 BIOS Version(版本号)
BIOS Version 字段同样为字符串索引,其内容通常遵循厂商内部的版本命名规则,例如 "5.12"、"F.20"、"1.0.0.8" 或 "R1.2.3"。该版本号会被操作系统(如 Windows 系统信息、Linux dmidecode)直接读取并显示给用户。定制时,版本号应反映固件构建的迭代信息,建议采用 主版本.次版本.构建号 的格式。
4.2.3 BIOS Release Date(发布日期)
Release Date 字段的字符串格式必须为 mm/dd/yyyy(例如 "01/15/2025")。这是 SMBIOS 规范强制要求的格式,不符合此格式的日期字符串可能导致部分管理软件解析失败。在定制场景中,该日期通常与固件构建脚本的构建时间戳绑定,实现自动化更新。
4.2.4 BIOS Characteristics(64 位特性位图)
Characteristics 字段是 Type 0 中信息密度最高的部分,它使用 64 个比特位(8 字节)来描述 BIOS 所支持的功能特性。每个比特位对应一个特定的能力标志。下表列出了最常用的特性位及其含义:
| 位索引 | 特性名称 | 说明 |
|---|---|---|
| 0 | BIOS Characteristics Not Supported | 该位必须为 0,表示支持特性位图 |
| 1 | ISA Supported | 支持 ISA 总线 |
| 2 | MCA Supported | 支持微通道架构 |
| 3 | EISA Supported | 支持 EISA 总线 |
| 4 | PCI Supported | 支持 PCI 总线(现代系统必须置 1) |
| 5 | PC Card (PCMCIA) Supported | 支持 PC 卡 |
| 6 | Plug and Play Supported | 支持即插即用 |
| 7 | APM Supported | 支持高级电源管理 |
| 8 | BIOS Upgradable (Flash) | BIOS 可闪存升级 |
| 9 | BIOS Shadowing Allowed | 允许 BIOS 影子内存 |
| 10 | VLB Supported | 支持 VESA 局部总线 |
| 11 | ESCD Supported | 支持扩展系统配置数据 |
| 12 | Boot from CD Supported | 支持从 CD-ROM 启动 |
| 13 | Selectable Boot Supported | 支持可选择的启动设备 |
| 14 | BIOS ROM Is Socketed | BIOS ROM 为插槽式 |
| 15 | Boot from PC Card (PCMCIA) Supported | 支持从 PC 卡启动 |
| 16 | EDD Supported | 支持增强型磁盘驱动规范 |
| 17 | Int 13h - Japanese Floppy Supported | 支持日本软盘规格 |
| 18 | Int 13h - Japanese Floppy (Toshiba) Supported | 支持东芝软盘规格 |
| 19 | Int 13h - 5.25"/360KB Floppy Supported | 支持 5.25 英寸 360KB 软盘 |
| 20 | Int 13h - 5.25"/1.2MB Floppy Supported | 支持 5.25 英寸 1.2MB 软盘 |
| 21 | Int 13h - 3.5"/720KB Floppy Supported | 支持 3.5 英寸 720KB 软盘 |
| 22 | Int 13h - 3.5"/2.88MB Floppy Supported | 支持 3.5 英寸 2.88MB 软盘 |
| 23 | Int 13h - Print Screen Supported | 支持打印屏幕功能 |
| 24 | Int 13h - 8042 Keyboard Services Supported | 支持 8042 键盘服务 |
| 25 | Int 13h - Serial Services Supported | 支持串口服务 |
| 26 | Int 13h - Printer Services Supported | 支持打印机服务 |
| 27 | Int 13h - CGA/Mono Video Services Supported | 支持 CGA/单色视频服务 |
| 28 | NEC PC-98 Services Supported | 支持 NEC PC-98 服务 |
| 29-31 | Reserved | 保留位,必须为 0 |
4.3 定制场景与实战案例
4.3.1 场景一:基于 coreboot 的定制固件
在 coreboot 项目中,SMBIOS Type 0 的数据通常在 src/smbios/smbios.c 或设备树配置中定义。以下是一个典型的定制代码片段:
/* 在 coreboot 的 smbios.c 中设置 Type 0 字段 */
static int smbios_write_type0(unsigned long *current, int handle)
{
struct smbios_type0 *t = (struct smbios_type0 *)*current;
int len = sizeof(struct smbios_type0);
memset(t, 0, len);
t->type = SMBIOS_BIOS_INFORMATION;
t->length = len;
t->handle = handle;
/* 设置字符串索引 */
t->vendor = smbios_add_string("MyCompany Coreboot");
t->bios_version = smbios_add_string("4.21-1234-gabcdef");
t->bios_release_date = smbios_add_string("03/10/2025");
/* 设置特性位图:PCI + Flash + Boot from CD + Selectable Boot */
t->characteristics[0] = (1 << 4) | (1 << 8) | (1 << 12) | (1 << 13);
/* 设置 BIOS 起始段地址 */
t->bios_starting_address_segment = 0xF000;
/* 设置 ROM 大小:1MB = 16 * 64KB */
t->bios_rom_size = 16;
*current += len;
return len;
}
4.3.2 场景二:UEFI 固件中的 SMBIOS 动态更新
在 UEFI 环境中,可以通过 gEfiSmbiosProtocolGuid 在运行时动态修改 Type 0 字段。以下示例展示了如何在 DXE 驱动中更新 BIOS 版本号:
#include <Protocol/Smbios.h>
EFI_STATUS UpdateSmbiosType0Version(CHAR16 *NewVersion)
{
EFI_STATUS Status;
EFI_SMBIOS_PROTOCOL *Smbios;
EFI_SMBIOS_HANDLE SmbiosHandle;
SMBIOS_TABLE_ENTRY_POINT *EntryPoint;
SMBIOS_STRUCTURE_POINTER SmbiosStruct;
Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
if (EFI_ERROR(Status)) return Status;
/* 遍历所有 SMBIOS 结构,找到 Type 0 */
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
while (TRUE) {
Status = Smbios->GetNext(Smbios, &SmbiosHandle, NULL, &SmbiosStruct, NULL);
if (EFI_ERROR(Status)) break;
if (SmbiosStruct.Hdr->Type == 0) {
/* 此处简化处理:实际需要重新分配字符串表并更新索引 */
/* 真实场景中应调用 Smbios->Remove() 再 Add() */
break;
}
}
return EFI_SUCCESS;
}
Remove() 移除旧结构,再使用 Add() 添加新结构。字符串表也需要整体重建,因为字符串索引是相对于结构末尾的偏移量。4.4 Type 0 字段间的依赖关系
下图展示了 Type 0 各字段之间的数据依赖与引用关系,帮助理解字符串索引与特性位图在整体结构中的位置:
从上图可以清晰地看到:Vendor、Version、Release Date 三个字段通过索引值间接引用字符串表中的内容;Characteristics 位图独立描述功能特性;扩展字节则提供额外的版本信息。在定制时,修改字符串表内容后必须同步更新对应的索引值,否则会导致字符串错位。
4.5 定制开发中的常见陷阱与最佳实践
- 字符串表必须以双 NULL 结尾: SMBIOS 字符串表在最后一个字符串之后必须紧跟一个额外的 NULL 字节(即连续两个 NULL),表示字符串表结束。如果遗漏,SMBIOS 解析器会继续读取后续结构数据作为字符串,导致乱码。
- 日期格式严格性: 即使系统使用非美国英语区域,Release Date 也必须使用
mm/dd/yyyy格式。部分 Linux 发行版的 dmidecode 工具会尝试解析其他格式,但 Windows 系统信息工具只认标准格式。 - 特性位图与硬件能力匹配: 不要为了“看起来功能丰富”而随意设置特性位。例如,如果系统不支持 PCMCIA,却将位 5 置 1,可能导致操作系统加载错误的驱动程序或服务。
- BIOS ROM Size 的计算: 该字段的单位是 64KB。例如,2MB 的 SPI Flash 应设置为
32(2 * 1024 / 64 = 32)。如果设置为 0,表示大小未知。 - Handle 的唯一性: 每个 SMBIOS 结构的 Handle 必须在整个表中唯一。在动态添加 Type 0 时,建议使用
SMBIOS_HANDLE_PI_RESERVED让协议自动分配,或维护一个全局计数器。
dmidecode -t 0 可以快速验证 Type 0 的定制结果。如果输出显示乱码或字段缺失,首先检查字符串表是否以双 NULL 结尾,其次检查 Length 字段是否与实际结构大小一致。4.6 扩展字节与版本字段的定制
SMBIOS 2.4 及更高版本引入了 BIOS Characteristics Extension Bytes(偏移 12h-13h)以及四个版本字段(偏移 14h-17h)。这些字段在定制时同样重要:
| 扩展字节位 | 含义 | 定制建议 |
|---|---|---|
| Extension Byte 1, Bit 0 | ACPI Supported | 现代系统必须置 1 |
| Extension Byte 1, Bit 1 | USB Legacy Supported | 如果支持 USB 键盘/鼠标,置 1 |
| Extension Byte 1, Bit 2 | AGP Supported | 仅旧系统需要 |
| Extension Byte 1, Bit 3 | I2O Boot Supported | 通常置 0 |
| Extension Byte 1, Bit 4 | LS-120 SuperDisk Boot | 通常置 0 |
| Extension Byte 1, Bit 5 | ATAPI ZIP Drive Boot | 通常置 0 |
| Extension Byte 1, Bit 6 | 1394 Boot Supported | 通常置 0 |
| Extension Byte 1, Bit 7 | Smart Battery Supported | 如果支持智能电池,置 1 |
| Extension Byte 2, Bit 0 | BIOS Boot Specification Supported | 通常置 1 |
| Extension Byte 2, Bit 1 | Function key-initiated Network Service Boot | 如果支持网络启动热键,置 1 |
| Extension Byte 2, Bit 2-7 | Reserved | 必须为 0 |
版本字段(System BIOS Major/Minor Release、Embedded Controller Firmware Major/Minor Release)为可选字段,但如果存在,必须与 BIOS Version 字符串中的版本号保持一致。例如,如果 BIOS Version 字符串为 "5.12.345",则 Major Release 应为 5,Minor Release 应为 12。
dmidecode -t 0 | grep -E "Vendor|Version|Release|Characteristics|ROM Size"确保所有字段显示正确,且无乱码或空值。