符合SMBIOS规范的计算机的系统信息获取方法
作者:ramble (如需转载请注明作者)
对于符合SMBIOS规范的计算机,可以通过访问SMBIOS的结构获得系统信息,共有两种办法可以访问:
1. 通过即插即用功能接口访问SMBIOS结构,这个在SMBIOS2.0标准里定义了,从SMBIOS 2.1开始这个访问方法不再被推荐使用。
2. 基于表结构的方法,表内容是table entry point的数据,这个访问方法从SMBIOS 2.1以后开始被使用,从2.1开始,以后的版本都推荐使用这种访问方式。在2.1版本中允许支持这两种方法中的任意一种和两种都支持,但在2.2已经以后的版本,必须支持方法2。
鉴于市场上计算机已经均支持SMBIOS2.3标准,所以只考虑方法2,基于表结构的访问方式。
基于表结构访问SMBIOS的过程是先找到Entry Point Structure(EPS)表,然后通过Entry Point Structure(EPS)表的数据找到SMBIOS数据表。
访问SMBIOS EPS表的操作过程如下:
1. 从物理内存0xF0000-0xFFFFF间寻找关键字“ _SM_”
2. 找到后再向后16个字节,看后面5个BYTE是否是关键字“_DMI_”,如果是,EPS表即找到。
注:按照SMBIOS规范说明,找到关键字”_SM_”后就可以确定此处就是EPS表结构,但我在实际操作中发现有为数不少的计算机的指定64K内存中有不只一个“_SM_”,所以不能仅用找到”_SM_”来确定,需要继续判断16个字节后是否是“_DMI_”。
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表结构中的12H以及14H处,得出数据表长度和数据表地址,即可通过地址访问结构表。从EPS表中的1CH处可得知结构表结构的总数,其中TYPE 0结构就是BIOS information,TYPE 1结构就是SYSTEM Information。
每个结构的头部是相同的,格式如下:
位置 | 名称 | 长度 | 描述 |
00H | TYPE号 | 1BYTE | 结构的TYPE号 |
01H | 长度 | 1BYTE | 本结构的长度,就此TYPE号的结构而言 |
02H | 句柄 | 2BYTE | 用于获得SMBIOS结构,使用方法未知 |
每个结构都分为格式区域和字符串区域,格式区域就是一些本结构的信息,字符串区域是紧随在格式区域后的一个区域。结构01H处标识的结构长度仅是格式区域的长度,字符串区域的长度是不固定的。
下面以TYPE 0(BIOS information)为例说明格式区域和字符串区域的关系
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 | 一般为04H,表示字符区第三个字符串 |
09H | BIOS rom size | 1BYTE | 计算方法为(n+1)×64K,n为此处读出数值 |
0AH | BIOS特征 | 8BYTE | Bios的功能支持特征,如PCI,PCMCIA,FLASH等 |
12H | Bios特征扩展 | 不定 |
|
紧随TYPE 0(BIOS information)结构区域之后的就是TYPE 0(BIOS information)字符串区域,如下所示:
db ‘System BIOS Vendor Name’,0 ; 字符串以零结尾,第一个字符串:卖方信息
db ‘4.04’,0 ; 第二个:BIOS版本
db ‘00/00/0000’,0 ; 第三个:发布日期
db 0 ; 以O为整个字符区域的结尾,所以要找下一个TYPE,只要在字符区域找到连续的OOOOH即可
注:当有EPS表中得到结构表的开始地址后,可以直接按结构来寻找相应的TYPE号,找到后直接读取就是该TYPE对应的结构的格式区域信息,然后向后移动结构区域长度(机构区域长度由该结构的O1H处读出)个BYTE,即是该TYPE机构的字符串区域。
由上面介绍可知,获得BIOS信息的办法就是:
1. 通过EPS表的12H和14H数据找到TYPE结构表,然后找到TYPE 0的内存地址。(不一定是首个)
2. 由TYPE 0结构区域中得出相应BIOS信息是否存在(存在则是上面所述的 01H,02H,03H依次排布,不存在则是相应的位置上为00H)。
3. 如存在信息,则从字符串区域中读取对应BIOS信息。
获得SYSTEM信息方法同上,只是TYPE结构区域有所不同,请参照SMBIOS Reference Specification