先介紹 DMI 。 DMI 是英文單詞 Desktop Management Interface 的縮寫,也就是桌面管理界面,它含有關於系統硬件的配置信息。計算機每次啓動時都對 DMI 數據進行校驗,如果該數據出錯或硬件有所變動,就會對機器進行檢測,並把測試的數據寫入 BIOS 芯片保存。所以如果我們在 BIOS 設置中禁止了 BIOS 芯片的刷新功能或者在主板使用跳線禁止了 BIOS 芯片的刷新功能,那這臺機器的 DMI 數據將不能被更新。如果你更換了硬件配置,那麼在進行 WINDOWS 系統時,機器仍舊按老系統的配置進行工作。這樣就不能充分發揮新添加硬件的性能,有時還會出現這樣或那樣的故障。
SMBIOS(System Management 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 配置表中的 SMBIOS GUID(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 結構就是 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 |
一般爲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 BYTE
- db 0 ; Indicates BIOS Structure Type
- db 13h ; Length of information in bytes
- dw ? ; Reserved for handle
- db 01h ; String 1 is the Vendor Name
- db 02h ; String 2 is the BIOS version
- dw 0E800h ; BIOS Starting Address
- db 03h ; String 3 is the BIOS Build Date
- db 1 ; Size of BIOS ROM is 128K (64K * (1 + 1))
- dq BIOS_Char ; BIOS Characteristics
- db 0 ; BIOS Characteristics Extension Byte 1
- db ‘System BIOS Vendor Name’,0 ;
- db ‘4.04’,0 ;
- db ‘00/00/0000’,0 ;
- db 0 ; End of strings
一個不帶字符串域的完整 BIOS Information 例子:
- BIOS_Info LABEL BYTE
- db 0 ; Indicates BIOS Structure Type
- db 13h ; Length of information in bytes
- dw ? ; Reserved for handle
- db 00h ; No Vendor Name provided
- db 00h ; No BIOS version provided
- dw 0E800h ; BIOS Starting Address
- db 00h ; No BIOS Build Date provided
- db 1 ; Size of BIOS ROM is 128K (64K * (1 + 1))
- dq BIOS_Char ; BIOS Characteristics
- db 0 ; BIOS Characteristics Extension Byte 1
- dw 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:6C00
- F000: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:3010
- E000: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 .NOT
- E000: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..N
- E000:3070 45 43 20 43 6F 6D 70 75-74 65 72 73 20 49 6E 74 EC Computers Int
- E000: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 位彙編進行程序編寫將使得對物理內存進行訪問變得非常容易。