4. SMBIOS Type 1 (System Information):Manufacturer、Product Name、Version、Serial Number、UUID 的生成规则与填充实践
SMBIOS Type 1 是系统信息结构,它向操作系统和上层管理软件提供设备的基本身份标识。在嵌入式固件开发中,Type 1 的字段填充质量直接影响资产管理、远程运维和合规性审计。本章将深入解析五个核心字段的生成规则、填充策略与调试方法。
4.1 Type 1 结构总览
Type 1 结构位于 SMBIOS Entry Point 之后,通常作为第一个或第二个结构体出现。其结构定义如下:
| 偏移 | 长度 | 字段名 | 说明 |
|---|---|---|---|
| 00h | BYTE | Type | 固定为 0x01 |
| 01h | BYTE | Length | 结构体总长度(通常 27h) |
| 02h | WORD | Handle | 结构句柄,唯一标识 |
| 04h | BYTE | Manufacturer | 字符串索引 |
| 05h | BYTE | Product Name | 字符串索引 |
| 06h | BYTE | Version | 字符串索引 |
| 07h | BYTE | Serial Number | 字符串索引 |
| 08h | BYTE[16] | UUID | 16 字节二进制数据 |
| 18h | BYTE | Wake-up Type | 唤醒方式枚举 |
| 19h | BYTE | SKU Number | 字符串索引(可选) |
| 1Ah | BYTE | Family | 字符串索引(可选) |
关键提示:字符串索引值 0 表示该字段未使用(空字符串),索引值 1 表示指向结构体后的第一个字符串,索引值 2 表示第二个字符串,以此类推。字符串区域以双 NULL 结尾。
4.2 五个核心字段的生成规则
4.2.1 Manufacturer(制造商)
制造商字段应使用公司注册的法定名称,不可使用缩写或代号。常见规则:
- 标准名称:如 "Intel Corporation"、"Dell Inc."、"Huawei Technologies Co., Ltd."
- OEM 定制:ODM 厂商应填写品牌方名称,而非代工厂名称
- 长度限制:建议不超过 64 个 ASCII 字符,避免字符串区域溢出
4.2.2 Product Name(产品名称)
产品名称应唯一标识硬件平台,通常与产品标签一致:
- 主板级:如 "X11DPi-NT"、"B660M PRO RS"
- 整机级:如 "ThinkPad X1 Carbon Gen 11"、"PowerEdge R750"
- 嵌入式:如 "NVIDIA Jetson AGX Orin Developer Kit"
4.2.3 Version(版本号)
版本号反映硬件修订级别,常见格式:
- 数字版本:"1.0"、"2.1"、"Rev 3.0"
- 字母版本:"A01"、"B02"、"Rev C"
- 日期版本:"2024.03.15"(较少使用)
4.2.4 Serial Number(序列号)
序列号是设备唯一标识,生成规则最为严格:
- 唯一性:每台设备必须唯一,不可重复
- 格式:通常为字母数字组合,长度 8~32 字符
- 不可包含:空格、特殊字符(如 @#$%)、中文
- 生产写入:建议在产线烧录阶段写入 SPI Flash 的 NVRAM 区域
4.2.5 UUID(通用唯一标识符)
UUID 是 128 位全局唯一标识,遵循 RFC 4122 规范:
- 格式:16 字节二进制,以小端序存储(Intel 架构)
- 版本:推荐使用 UUID v4(随机)或 UUID v5(基于命名空间+名称的 SHA-1)
- 特殊值:全 0 表示未设置,全 1 表示不支持
- 持久性:同一设备生命周期内不可变更
常见陷阱:部分 BIOS 代码将 UUID 以大端序存储,导致 Windows 和 Linux 下读取的 UUID 字符串不一致。务必确认 CPU 架构的字节序,x86 使用小端序,ARM 通常也使用小端序。
4.3 字段填充实践
4.3.1 字符串索引填充流程
Type 1 的字符串字段通过索引指向结构体后的字符串区域。填充流程如下:
- 在内存中分配 Type 1 结构体(固定长度 27h)
- 在结构体后依次追加字符串:Manufacturer、Product Name、Version、Serial Number
- 每个字符串以 NULL 结尾,字符串区域以双 NULL 结束
- 将结构体中的索引字段设置为对应字符串的序号(从 1 开始)
// 示例:Type 1 字符串索引填充(C 语言伪代码)
typedef struct {
UINT8 Type; // 0x01
UINT8 Length; // 0x27
UINT16 Handle;
UINT8 Manufacturer; // 索引 1
UINT8 ProductName; // 索引 2
UINT8 Version; // 索引 3
UINT8 SerialNumber; // 索引 4
UINT8 UUID[16];
UINT8 WakeUpType;
UINT8 SKUNumber; // 索引 5
UINT8 Family; // 索引 6
} SMBIOS_TYPE1;
// 字符串区域布局(内存连续):
// [结构体 27h 字节]
// "Intel Corporation\0" // 索引 1
// "X11DPi-NT\0" // 索引 2
// "1.0\0" // 索引 3
// "SN202403150001\0" // 索引 4
// "SKU-12345\0" // 索引 5
// "Server\0" // 索引 6
// "\0" // 双 NULL 结束
4.3.2 UUID 字节序处理
UUID 在 SMBIOS 规范中定义为 16 字节二进制,但不同操作系统解析方式不同:
| 字段 | 字节偏移 | 长度 | 字节序 | 示例(小端序存储) |
|---|---|---|---|---|
| time_low | 0~3 | 4 字节 | 小端 | 0x12345678 → 78 56 34 12 |
| time_mid | 4~5 | 2 字节 | 小端 | 0x9ABC → BC 9A |
| time_hi_and_version | 6~7 | 2 字节 | 小端 | 0xDEF0 → F0 DE |
| clock_seq_hi_and_reserved | 8 | 1 字节 | 大端 | 0x12 → 12 |
| clock_seq_low | 9 | 1 字节 | 大端 | 0x34 → 34 |
| node | 10~15 | 6 字节 | 大端 | 0x112233445566 → 11 22 33 44 55 66 |
// UUID 小端序填充示例(x86 平台)
UINT8 UuidBuffer[16] = {
0x78, 0x56, 0x34, 0x12, // time_low (小端)
0xBC, 0x9A, // time_mid (小端)
0xF0, 0xDE, // time_hi_and_version (小端)
0x12, // clock_seq_hi_and_reserved
0x34, // clock_seq_low
0x11, 0x22, 0x33, 0x44, 0x55, 0x66 // node
};
// 对应 UUID 字符串:12345678-9ABC-DEF0-1234-112233445566
4.4 字段填充的 SVG 架构图
4.5 常见问题与调试方法
| 问题现象 | 可能原因 | 调试方法 |
|---|---|---|
| Manufacturer 显示乱码 | 字符串索引指向错误偏移 | 使用十六进制编辑器检查字符串区域起始位置 |
| UUID 全零 | UUID 生成算法未执行或 NVRAM 未初始化 | 检查固件中 UUID 生成逻辑的调用时机 |
| Serial Number 为空 | 产线烧录数据未正确写入 SPI Flash | 使用 SPI 编程器读取 NVRAM 区域验证 |
| Windows 和 Linux 下 UUID 不同 | 字节序处理不一致 | 确认固件使用小端序存储 UUID |
| Product Name 显示 "To be filled by O.E.M." | BIOS 代码未覆盖默认字符串 | 在固件配置表中添加产品名称字符串 |
4.6 调试命令速查
# Linux 下查看 Type 1 信息
dmidecode -t 1
# 输出示例:
# Handle 0x0001, DMI type 1, 27 bytes
# System Information
# Manufacturer: Intel Corporation
# Product Name: X11DPi-NT
# Version: 1.0
# Serial Number: SN202403150001
# UUID: 12345678-9ABC-DEF0-1234-112233445566
# Wake-up Type: Power Switch
# SKU Number: SKU-12345
# Family: Server
# Windows 下查看
wmic csproduct get name, vendor, version, identifyingnumber
# UEFI Shell 下查看
smbiosview -t 1
实战建议:在固件开发阶段,建议在 BIOS 启动早期(PEI 阶段)打印 Type 1 各字段的原始字节和字符串内容,便于快速定位填充错误。使用 Serial Debug 工具或 ITP 调试器可以实时捕获这些日志。