SMBIOS全拼System Management BIOS, 是通过系统固件传递管理信息的标准。应用在PC上,即是主板或系统制造厂商以标准格式显示产品信息所遵循的统一规范。
主板厂商或OEM厂商生产的PC,出厂前都会按照SMBIOS标准将相关信息写入BIOS中。比如OEM客制化信息等。
SMBIOS信息也会记录很多硬件信息, 比如CPU型号, 缓存, 内存大小等等
目前主流的访问方式都是基于表结构的访问方式。基于表结构访问SMBIOS的过程是先找到 Entry Point Structure (EPS)表,然后通过Entry Point Structure (EPS)表的数据找到SMBIOS结构表。
EPS分为两种:Original SMBIOS 2.1(32-bit) entry point / SMBIOS 3.0(64-bit) entry point
为了兼容已经存在的SMBIOS解析器,目前pc都会提供32-bit entry point,SMBIOS 2.1(32-bit) Entry Point查询方式:(软件为RW-Everything)
Entry Point Structure:
SMBIOS结构表的起始地址、总长度、个数都可以从EPS中获取到。每个表都有一个相同的4个byte的header格式,如下。
每个结构都分为格式区域和字符串区域,格式区域就是一些本结构的信息,字符串区域是紧随在格式区域后的一个区域。结构01h处标识的结构长度仅是格式区域的长度,字符串区域的长度是不固定的。每个字符串以00h结束,整个字符区域也以00h结束。
SMBIOS包含多个表结构,每个表的意义不同。从SMBIOS version 2.3开始要求包含一些基本的表结构,如Type0 BIOS Information、Type1 System Information、Type3 System Enclosure、Type4 Processor Information等。具体的structures和data,参见SMBIOS spec。
SMBIOS 3.0 (64-bit) Entry Point Structure
位置 | 名称 | 长度 | 描述 |
---|---|---|---|
00H | 关键字 | 5Byte | “_SM3_指定为五个ASCII字符(5F 53 4D 33 5F)。” |
05H | 校验和 | 1Byte | 用于校验数据,对于入口点长度字节,EPS中的值从偏移量00h开始求和。 |
06H | 表结构长度 | 1Byte | 入口点结构的长度,从锚定字符串字段开始,以字节为单位,目前为18h |
07H | Major 版本号 | 1Byte | 用于判断SMBIOS版本 |
08H | Minor 版本号 | 1Byte | 用于判断SMBIOS 版本 |
09H | 表结构大小 | 2Byte | 用于即插即用接口方法获得数据表结构长度 |
0AH | 入口点修改 | 1Byte | 在该结构中实现的EPS修订,并确定了0Bh及以上偏移量的格式如下:01h入口点基于SMBIOS 3.0定义;02h-FFh根据本规范保留分配 每修订01h定义偏移0Ch-17h |
0B | 预留区域 | 1Byte | 根据该规范保留为赋值,设置为0 |
0CH | 结构表最大尺寸 | DWORD | SMBIOS结构表的最大大小,由结构表地址指向,以字节为单位。实际大小保证小于或等于最大大小。 |
10H | 结构表地址 | QWORD | 只读SMBIOS结构表的64位物理起始地址,可以从任何64位地址开始。此区域包含全部打包在一起的SMBIOS结构。 |
Required structures and data
Type类型 | 名称 | 含义 |
---|---|---|
Type 0 | BIOS 信息 | 结构表中只有一个结构。BIOS Version和BIOS Release Date字符串是非空的;日期字段使用4位数字的年份(例如,1999)。所有其他字段反映完整的BIOS支持信息。 |
Type 1 | 系统信息 | 制造商和产品名称字符串是非空的。UUID字段标识系统的非零UUID值。“唤醒类型”字段标识唤醒源,不能为“未知”。结构表中只有一个结构。 |
Type 2 | 基板或模块单元信息 | 制造商、产品名、版本、序列号、资产标签、特征标志、基板在底架上的位置、底架句柄、基板类型、包含的对象句柄个数、包含的个各对象句柄。 |
Type 3 | 系统外围或底架 | 制造商、类型、版本、序列号、资产标签号、启动状态、供电电源状态、热量状态、安全状态、 OEM 定义信息、高度、电源线个数、包含的单元个数、包含的单元记录长度、包含的各个单元、 SKU 号。 |
Type 4 | 处理器信息 | 插座指示、处理器类型、处理器家族、制造商、 ID 、版本、电压伏特数、外部时钟频率 (MHz) 、最大速率 (MHz) 、当前速率、状态、处理器升级、 L1 级缓存信息结构的句柄、 L2 级缓存信息结构的句柄、 L3 级缓存信息结构的句柄、序列号、资产标签、部件号码、内核个数、激活的内核个数、线程个数、处理器特征、处理器家族 2 。 |
Type 7 | 高速缓存信息 | 插座指示、缓存配置、最大缓存容量、已安装的容量、支持的 SRAM 类型、当前 SRAM 类型、缓存速率、纠错类型、系统缓存类型、关联性。 |
Type 8 | 端口连接器信息 | 例如并口、串口、键盘、鼠标器端口等都属于端口连接器。包含的信息有内部引用指示符、内部连接器类型、外部引用指示符、外部引用类型、端口类型。 |
Type 9 | 系统插槽 | 插槽指示符、插槽类型、插槽数据总线宽度、当前是否在使用、插槽长度、插槽 ID 、插槽特征 1 、插槽牲 2 、段组编号、总线编号、设备 / 函数编号。 |
Type 11 | OEM 字符串 | 由 OEM 指定的描述字符串。 |
Type 12 | 系统配置选项 | 用来配置基板跳线和开关的信息字符串。 |
Type 13 | BIOS 语言信息 | 可安装的语言、标志位字节、保留的 15 字节、当前语言。这里的语言是指英语、法语、汉语等国家语言,而不是计算机编程语言。 |
Type 14 | 组相联 | 组名、本项的类型、本结构的句柄。级相联用于指明某些部件的布局或层次,例如指明两个 CPU 共享一个外部缓存系统。 |
Type 15 | 系统事件日志 | 事件日志存放在非易失性的存储单元中,占据固定长度的区域, 以 一个固定长度(和特定于厂商)的头部开始,后跟一个或多个可变长度的日志记录。应用程序可以通过周期性地读取系统事件日志结构(通过它的句柄)并在日志改 变标记中搜索日志的更新,以实现事件日志改变通知。 |
Type 16 | 物理存储器阵列 | 位置(系统板卡或附加板卡上)、存储功能、内存纠错、最大容量、存储错误信息句柄、存储设备数目、已扩展的最大容量。 |
Type 17 | 存储设备 | 用于描述物理存储器阵列中的单个存储设备。在物理存储器阵列中的句柄、存储错误信息句柄、存储总宽度、数据宽度、存储容量、形体尺寸、设备集、设备定位 器、记忆槽定位器、存储器类型、类型额外细节、速率、制造商、序列号、资产标签、部件号码、属性标志、已扩展的容量、已配置的存储时钟速率。 |
Type 18 | 32-bit 错误信息 | 错误类型、错误粒度、错误操作、特定于制造商的错误表现、存储阵列错误地址、设备错误地址、错误解析。 |
Type 19 | 存储阵列映射地址 | 起始地址、结束地址、存储阵列句柄、分区宽度、已扩展的起始地址、已扩展的结束地址。 |
Type 20 | 存储设备映射地址 | 起始地址、结束地址、存储设备句柄、存储阵列映射地址句柄、分区行位置、交叉位置、交叉的数据深度、已扩展的起始地址、已扩展的结束地址。 |
Type 21 | 内置指针设备 | 指针设备类型、接口类型、按钮个数。 |
Type 22 | 智能电池 | 位置、制造商、制造日期、序列号、设备名、设备化学属性、设计容量、设计电压伏特数、 SBDS 版本号、电池数据的最大错误百分比、 SBDS 序列号、 SBDS 制造日期、 SBDS 设备化学属性、设计容量倍增因子、特定于 OEM 的信息。 |
Type 32 | 系统引导信息 | 保留域 (00h) 、引导状态描述 (10 字节 ) 。引导状态描述主要有“没有检测到错误”、“没有可引导的媒介”、“操作系统载入失败”、“ BIOS 硬件检测失败”、“操作系统硬件检测失败”、“用户请求引导(通过一个按键)”、“违反系统安全”、“预先请求映像(通过 PXE 引导)”、“系统监控记时器激活,导致系统重启”,特定于厂商引导状态描述等。 |
Type 38 | IPMI 设备信息 | BMC 接口类型、 IPMI 规范修改版本、 I2C 从地址、 NV 存储设备地址、基地址、基地址修饰符 / 中断信息、中断号。 |
Type 126 | 不活动指示 | 用来表明某个 SMBIOS 结构当前不活动,因此不应用被上层的软件使用。它没有字符串区域,只有结构头部(即三个头部域类型、长度、句柄)。 |
Type 127 | 表格结束指示 | 表示整个 SMBIOS 结构表的结束。它也只有结构头部,没有字符串区域。 |
BIOS Information (Type 0) structure
位置 | 名称 | 长度 | 描述 |
---|---|---|---|
00H | TYPE号 | 1Byte | 结构的TYPE号,此处是0 |
01H | 长度 | 1Byte | TYPE 0格式区域长度,一般为14H,也有13H |
02H | 句柄 | 2Byte | 本结构的句柄,一般为0000H |
04H | BIOS厂商信息 | 1Byte | 此处是BIOS卖方信息,可能是OEM厂商名,一般为01H,代表紧随格式区域后的字符串区域的第二个字符串 |
05H | BIOS版本 | 1Byte | BIOS版本号,一般为02H,代表字符串区域的第二个字符 |
06H | BIOS开始地址段 | 2Byte | 用于计算机常驻BIOS镜像大小计算,方法为 (10000H-BIOS开始地址段) * 16 |
08H | BIOS发布日期 | 1Byte | 一般为03H,表示字符区第三个字符串表示字符区第三个字符串 |
09H | BIOS rom size | 1Byte | 计算方法为(n +1 )*64K ,n 为此处读出数值为(n +1 )×64K ,n 为此处读出数值 |
0AH | BIOS 特征 | 8Byte | Bios 的功能支持特征,如PCI,PCMCIA,FLASH 等 |
12H | BIOS 特征扩展 | 不定 | 为将来支持的功能预留的可选空间。当前的扩展字节数由偏移量1 - 12h中的长度表示。 |
14H | BIOS 版本主号 | 1Byte | 标识系统BIOS的主要版本;每次发布给定系统的System BIOS更新时,此字段或System BIOS Minor Release字段或两者都会更新。 |
15H | BIOS 版本从号 | 1Byte | 标识系统BIOS的小版本;例如,版本10.22的值是16h,版本2.1的值是01h。 |
16H | 内置控制器固件的版主号 | 1Byte | 确定嵌入式控制器固件的主要版本;例如,对于修订10.22,该值为0Ah,对于修订2.1,该值为02h。 |
17H | 内置控制器固件的版从号 | 1Byte | 如果系统没有可现场升级的嵌入式控制器固件,则取值为0FFh。 |
UEFI code中提供一个SmbiosDxe driver,为SMBIOS table提供接口函数,包括add、update、remove等function。Locate protocol后可以对SMBIOS table进行操作。
/**
Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.
@param ImageHandle Module's image handle
@param SystemTable Pointer of EFI_SYSTEM_TABLE
@retval EFI_SUCCESS Smbios protocol installed
@retval Other No protocol installed, unload driver.
**/
EFI_STATUS
EFIAPI
SmbiosDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
mPrivateData.Signature = SMBIOS_INSTANCE_SIGNATURE;
mPrivateData.Smbios.Add = SmbiosAdd;
mPrivateData.Smbios.UpdateString = SmbiosUpdateString;
mPrivateData.Smbios.Remove = SmbiosRemove;
mPrivateData.Smbios.GetNext = SmbiosGetNext;
mPrivateData.Smbios.MajorVersion = (UINT8) (PcdGet16 (PcdSmbiosVersion) >> 8);
mPrivateData.Smbios.MinorVersion = (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x00ff);
InitializeListHead (&mPrivateData.DataListHead);
InitializeListHead (&mPrivateData.AllocatedHandleListHead);
EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
//
// Make a new handle and install the protocol
//
mPrivateData.Handle = NULL;
Status = gBS->InstallProtocolInterface (
&mPrivateData.Handle,
&gEfiSmbiosProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPrivateData.Smbios
);
return Status;
}
Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);
ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_INFO, "The Smbios Table Version: %x.%x\n", mSmbios->MajorVersion, mSmbios->MinorVersion));
if (mSmbios->MajorVersion < 2 || (mSmbios->MajorVersion == 2 && mSmbios->MinorVersion < 7)){
mMaxLen = SMBIOS_STRING_MAX_LENGTH;
} else if (mSmbios->MajorVersion < 3) {
//
// Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
// However, the length of the entire structure table (including all strings) must be reported
// in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
// which is a WORD field limited to 65,535 bytes.
//
mMaxLen = SMBIOS_TABLE_MAX_LENGTH;
} else {
//
// SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
// Locate the end of string as long as possible.
//
mMaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;
}
UEFI spec在其配置表中提供了SMBIOS EPS table。通过在EFI Configuration Table中搜索SMBIOS_TABLE_GUID可以方便的得到EPS table,进而查找SMBIOS表。
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
*Table = gST->ConfigurationTable[Index].VendorTable;
return EFI_SUCCESS;
}
}