SMBIOS介绍(1):概述

时间:2023-02-11 11:44:04

转自:http://blog.csdn.net/zhoudaxia/article/details/5919699

   先介绍DMI。DMI是英文单词DesktopManagement Interface的缩写,也就是桌面管理界面,它含有关于系统硬件的配置信息。计算机每次启动时都对DMI数据进行校验,如果该数据出错或硬件有所变动,就会对机器进行检测,并把测试的数据写入BIOS芯片保存。所以如果我们在BIOS设置中禁止了BIOS芯片的刷新功能或者在主板使用跳线禁止了 BIOS芯片的刷新功能,那这台机器的DMI数据将不能被更新。如果你更换了硬件配置,那么在进行WINDOWS系统时,机器仍旧按老系统的配置进行工作。这样就不能充分发挥新添加硬件的性能,有时还会出现这样或那样的故障。

   SMBIOS(SystemManagement BIOS,SMBIOS)是主板或系统制造者以标准格式显示产品管理信息所需遵循的统一规范。DMI(Desktop Management Interface, DMI)就是帮助收集电脑系统信息的管理系统,DMI信息的收集必须在严格遵照SMBIOS规范的前提下进行。SMBIOS和DMI是由行业指导机构Desktop Management Task Force (DMTF)起草的开放性的技术标准,其中,DMI设计适用于任何的平台和操作系统。 DMI充当了管理工具和系统层之间接口的角色。它建立了标准的可管理系统更加方便了电脑厂商和用户对系统的了解。

DMI的主要组成部分是 Management Information Format (MIF)数据库。这个数据库包括了所有有关电脑系统和配件的信息。通过DMI,用户可以获取序列号、电脑厂商、串口信息以及其它系统配件信息。

   对于符合SMBIOS规范的计算机,可以通过访问SMBIOS的结构获得系统信息,共有两种办法可以访问:

   1. 通过即插即用功能接口访问SMBIOS结构,这个在SMBIOS2.0标准里定义了,从SMBIOS 2.1开始这个访问方法不再被推荐使用。

   2.基于表结构的方法,表内容是table entry point的数据,这个访问方法从SMBIOS 2.1以后开始被使用,从2.1开始,以后的版本都推荐使用这种访问方式。在2.1版本中允许支持这两种方法中的任意一种和两种都支持,但在2.2以后的版本,必须支持方法2。在最新的2.7.0版中第一种方法已经废弃。

   鉴于市场上计算机已经均支持SMBIOS2.3标准,所以只考虑方法2,基于表结构的访问方式。基于表结构访问SMBIOS的过程是先找到Entry Point Structure(EPS)表,然后通过Entry Point Structure(EPS)表的数据找到SMBIOS结构表。

   对于非EFI的系统,访问SMBIOS EPS表的操作过程如下:

   1.从物理内存0x000F0000-0x000FFFFF之间寻找关键字“ _SM_”。

   2.找到后再向后16个字节,看后面5个BYTE是否是关键字“_DMI_”,如果是,EPS表即找到。

   对于UEFI(是BIOS的下一代版本)系统,可能通过搜索EFI配置表中的SMBIOSGUID(SMBIOS_TABLE_GUID),然后使用指向SMBIOS的指针来定位EPS表。具体可参考UEFI规范。

   SMBIOS EPS表结构如下:

位置

名称

长度

描述

00H

关键字

4BYTE

固定是”_SM_”

04H

校验和

1BYTE

用于校验数据

05H

表结构长度

1BYTE

Entry Point Structure表的长度

06H

Major版本号

1BYTE

用于判断SMBIOS版本

07H

Minor版本号

1BYTE

用于判断SMBIOS版本

08H

表结构大小

2BYTE

用于即插即用接口方法获得数据表结构长度

0AH

EPS修正

1BYTE

 

0B-0FH

格式区域

5BYTE

存放解释EPS修正的信息

10H

关键字

5BYTE

固定为“_DMI_”

15H

校验和

1BYTE

Intermediate Entry Point Structure (IEPS)的校验和

16H

结构表长度

2BYTE

SMBIOS结构表的长度

18H

结构表地址

4BYTE

SMBIOS结构表的真实内存位置

1CH

结构表个数

2BYTE

SMBIOS结构表数目

1EH

Smbios BCD修正

1BYTE

 

    通过EPS表结构中16H以及18H处,得出数据表长度和数据表地址,即可通过地址访问SMBIOS数据结构表。从EPS表中的1CH处可得知数据表结构的总数,其中TYPE 0结构就是BIOSinformation,TYPE 1结构就是SYSTEM Information。

    每个结构的头部是相同的,格式如下:

位置

名称

长度

描述

00H

TYPE

1BYTE

结构的TYPE

01H

长度

1BYTE

本结构的长度,就此TYPE号的结构而言

02H

句柄

2BYTE

用于获得本SMBIOS结构,其值不定

    每个结构都分为格式区域和字符串区域,格式区域就是一些本结构的信息,字符串区域是紧随在格式区域后的一个区域。结构01H处标识的结构长度仅是格式区域的长度,字符串区域的长度是不固定的。有的结构有字符串区域,有的则没有。

    下面以TYPE 0(BIOSinformation)为例说明格式区域和字符串区域的关系。TYPE 0(BIOS information)格式区域如下:

位置

名称

长度

描述

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为此处读出数值

0AH

BIOS特征

8BYTE

Bios的功能支持特征,如PCI,PCMCIA,FLASH

12H

Bios特征扩展

不定

 

    紧随TYPE 0(BIOS information)结构区域之后,即在Bios特征扩展域后面的就是TYPE 0(BIOS information)字符串区域,一个例子如下所示:


    每个字符串都以00H作为结束标志,上面的例子中有三个字符串。如果我们要找下一个TYPE,因为最后一个字符串以00H结尾,而整个字符区域又以00H结尾,故只要在字符串区域找到连续的0000H即可。例如,一个带字符串域的完整BIOS Information例子如下:


   一个不带字符串域的完整BIOS Information例子:


   注意,当从EPS表中得到结构表的开始地址后,可以直接按结构来寻找相应的TYPE号,找到后直接读取就是该TYPE对应的结构的格式区域信息,然后向后移动结构区域长度(结构区域长度由该结构的01H处读出)个BYTE,即是该TYPE结构的字符串区域。

   由上面介绍可知,获得BIOS信息的办法就是:

   1.通过EPS表的12H和14H数据找到TYPE结构表,然后找到TYPE 0的内存地址(不一定是首个)。

   2.由TYPE 0结构区域中得出相应BIOS信息是否存在(存在则是上面所述的   01H,02H,03H依次排布,不存在则是相应的位置上为00H)。

   3.如存在信息,则从字符串区域中读取对应BIOS信息。

   获得其他类型的SMBIOS结构信息的方法类似,只是TYPE结构区域有所不同。

   相信大家都用过一些系统检测软件, 或者至少用过Windows优化大师里面的系统检测。实际上,应用程序程序就可以通过访问SMBIOS来获得这些信息。这里举一个例子,演示如何找到BIOS的版本号(BIOS Version)和电脑的厂商(Manufacturer)。不过我们不采用编程的方式,而是通过系统自带的debug命令来进行相关的操作。

   内存的物理地址区间0x000F0000-0x000FFFFF使用了32位中的20位,先要在这个区间内寻找关键字“ _SM_”,以定位到EPS表。我们要采用20位地址模式,即高位字左移12位,因此值0x000F0000表示为F000:0000,地址区间为F000:0000 - F000:FFFF。在cmd中输入 "debug", 回车, 这样就进入了debug环境,它的命令提示符为-, 以后出现在 - 后面的内容都为将要输入的命令。

   在地址区间内搜索关键字"_SM_"的起始地址:

-s f000:0 ffff '_SM_'

   以我的电脑为例, 响应可能是下面这样的:

-s f000:0 ffff '_SM_'

F000:6C00

   这个地址就是EPS表的起始地址。也有可能你的电脑会显示多个查找结果,不妨先随意选择一个进行下面的操作:

-d F000:6C00

   会打印该地址后面16*8个字节的内容,可能的响应:


   如果嫌显示的行数太少, 可以用-d继续打印后面的信息。注意到了吗,_SM_(其ASCII编码为5F 53 4D 5F),还有10H偏移处(即偏移16个字节)的_DMI_。如果你在上一步中有多个结果,那么只要某个结果通过d命令查看的结果符合这两个特征,我们就可以用它来继续下面的操作。至这一步,EPS已经找到了。

   EPS的偏移18H处的4字节为10 30 0E 00,是SMBIOS结构表的32位地址。这4个字节是从低字节到高字节,因为x86采用小端字节序,低字节存放的是高位的值,因此重新写成"高位 低位"的格式就是000E 3010,转换成20位格式就把高位左移12位,变成E000:3010 的形式。打印该地址处的内容:

-d e000:3010

可能的响应:


   首先,第一个字节 (零偏移处) 是 00,根据规范,这说明从这里开始的信息为TYPE 0 结构,也即BIOS信息区。第二个字节 (偏移 01H处) 是14,说明TYPE 0区域的基本大小是14H。根据规范,偏移02H处的两个字节为00 00,表示句柄。偏移04H处的字节为01,表示BIOS厂商这个字符串在Type 0字符串区域中的编号,即字符串区域中的第01个字符串就BIOS厂商。偏移05H 处的字节为02,表示BIOS版本字符串在字符串区域中的编号。偏移08H 处的字节为03,表示BIOS发布日期字符串在字符串区域中的编号。

    TYPE 0区的基本大小为14H,则偏移14H处是TYPE 0字符串区域的开始。偏移14H 处的值是4E(右面对应的ASCII 字符是N),这就是TYPE 0字符串区域的开始,它们是不包括在TYPE的大小计算中的。每个字符串不定长,由00H作为结束标志。熟悉 C/C++的人应该对这一标志符比较亲切吧。从第一个字符串依次编号为01,02...。第01个字符串为”NEC”(这里结束标志00前还插入了若干个控制字符20),是BIOS厂商,第02个字符串为"NOTE BIOS Version / 369A0600 ",是BIOS版本,第03个字符串为”09/10/2003”,是BIOS发布日期,这样我们的第一个目标BIOS版本就找到了。

整个字符串区的结束用00来标志,又根据字符串的结束符为00,所以找到 00 00,从00 00的下一个地址开始就是下一个信息区了。这个例子中,就是E000:3056 处,内容是 01,作为下一个区域的第一个字节,它标志着此TYPE的类型, 这里就是TYPE 1, 也即System Information。

根据与TYPE 0类似的方法, 我们从TYPE 1的偏移01H处得到TYPE 1的大小为19H, 而SMBIOS规范中说明,TYPE 1的偏移04H处即为Manufacturer字符串的编号,这里即为 01。转到TYPE 1的偏移19H处,即为TYPE 1的字符串区的开始,由于我们要找的信息编号为 01,所以从这里开始的信息"NEC Computers International" 即为厂商的信息。

SMBIOS支持在保护模式下工作,因此,在Windows中使用16位汇编进行程序编写将使得对物理内存进行访问变得非常容易。