天天看點

SMBIOS介紹(1):概述

轉自: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)字元串區域,一個例子如下所示:

db ‘System BIOS Vendor Name’,0 ; 字元串以零結尾,第一個字元串:BIOS廠商db ‘4.04’,0 ; 第二個:BIOS版本db ‘00/00/0000’,0 ; 第三個:BIOS釋出日期db 0 ; 以0為整個字元中區域的結尾

    每個字元串都以00H作為結束标志,上面的例子中有三個字元串。如果我們要找下一個TYPE,因為最後一個字元串以00H結尾,而整個字元區域又以00H結尾,故隻要在字元串區域找到連續的0000H即可。例如,一個帶字元串域的完整BIOS Information例子如下:

BIOS_Info LABEL BYTEdb 0 ; Indicates BIOS Structure Typedb 13h ; Length of information in bytesdw ? ; Reserved for handledb 01h ; String 1 is the Vendor Namedb 02h ; String 2 is the BIOS versiondw 0E800h ; BIOS Starting Addressdb 03h ; String 3 is the BIOS Build Datedb 1 ; Size of BIOS ROM is 128K (64K * (1 + 1))dq BIOS_Char ; BIOS Characteristicsdb 0 ; BIOS Characteristics Extension Byte 1db ‘System BIOS Vendor Name’,0 ;db ‘4.04’,0 ;db ‘00/00/0000’,0 ;db 0 ; End of strings

   一個不帶字元串域的完整BIOS Information例子:

BIOS_Info LABEL BYTEdb 0 ; Indicates BIOS Structure Typedb 13h ; Length of information in bytesdw ? ; Reserved for handledb 00h ; No Vendor Name provideddb 00h ; No BIOS version provideddw 0E800h ; BIOS Starting Addressdb 00h ; No BIOS Build Date provideddb 1 ; Size of BIOS ROM is 128K (64K * (1 + 1))dq BIOS_Char ; BIOS Characteristicsdb 0 ; BIOS Characteristics Extension Byte 1dw 0000h ; Structure terminator

   注意,當從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 F000:6C00F000:6C00 5F 53 4D 5F 16 1F 02 1F-4B 01 00 00 00 00 00 00 _SM_....K.......F000:6C10 5F 44 4D 49 5F 3D 98 09-10 30 0E 00 3C 00 00 00 _DMI_=...0..<...F000:6C20 52 53 44 20 50 54 52 20-DE 4E 45 43 20 20 20 00 RSD PTR .NEC .F000:6C30 34 95 F7 0D 00 00 00 00-00 00 00 00 00 00 00 00 4...............F000:6C40 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................F000:6C50 24 46 53 58 56 0C F8 00-B1 00 E0 00 00 00 00 00 $FSXV...........F000:6C60 5F 33 32 5F 20 D7 0F 00-00 01 D6 00 00 00 00 00 _32_ ...........F000:6C70 24 50 44 4D 01 0B 1A 5D-88 00 F0 00 00 00 00 00 $PDM...]........

   如果嫌顯示的行數太少, 可以用-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

可能的響應:

-d e000:3010E000:3010 00 14 00 00 01 02 F5 E4-03 07 90 DF 99 7C 00 00 .............|..E000:3020 00 00 05 03 4E 45 43 20-20 20 20 20 00 4E 4F 54 ....NEC .NOTE000:3030 45 20 42 49 4F 53 20 56-65 72 73 69 6F 6E 20 2F E BIOS Version /E000:3040 33 36 39 41 30 36 30 30-20 00 30 39 2F 31 30 2F 369A0600 .09/10/E000:3050 32 30 30 33 00 00 01 19-01 00 01 02 03 04 8B B0 2003............E000:3060 DE 65 92 46 40 EB 86 FE-56 28 BD 80 79 13 06 4 E [email protected](..y..NE000:3070 45 43 20 43 6F 6D 70 75-74 65 72 73 20 49 6E 74 EC Computers IntE000:3080 65 72 6E 61 74 69 6F 6E-61 6C 00 50 43 2D 43 56 ernational.PC-CV

   首先,第一個位元組 (零偏移處) 是 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位彙編進行程式編寫将使得對實體記憶體進行通路變得非常容易。

繼續閱讀