小華的部落格: INT 15h/AX=E820h 程式範例

搜尋此網誌

網頁

星期四, 7月 24, 2008

INT 15h/AX=E820h 程式範例

昨天下午拿起了ACPI Spec , 把之前還沒實做的INT15h E820h 部份拿起來練習了一下。

由Google大神找到的文件中的說明中可以了解到INT15h E820h 的用途和歷史,下面就我找到的文件中截取ㄧ部份出來給各位參考,如果要看全文的可以透過連結去查看我找到的那篇文章!

Linux MemoryCapacity Detection

OS必須知道系統實體記憶體的數量,才能夠有效的使用和管理這些實體記憶體。所以在booting階段,我們必須通過某種手段來檢測和獲取實體記憶體的總量。

由於在booting階段的絕大部分時間裏,主機處於Real Mode下,而在RealMode下,我們通過正常手段能夠訪問的實體記憶體最大只能達到1M+64K(在A20Gate被打開的情況下,否則,最大只能訪問1M),所以我們無法直接通過記憶體訪問來獲取記憶體總量。因此,剩下的唯一手段就是通過BIOS中斷。

但不幸的是,通過BIOS中斷獲取記憶體容量並非在所有情況都可以完全工作。
獲取機器記憶體容量的方法一般來講有三種方法,這三種方法都是基於BIOS INT15h中斷,它們的名稱依此為88h,E801h,E820h。

其中,88h方法是在Intel80286出現的那天起就存在的,後續的PC及其兼容機為了保持向下相容,都繼續保留了這種方法。因此,這種方法在所有的IBMPC及其兼容機上都存在,所以看起來,booting只需要這種方法就可以獲取實體記憶體總量,其他兩種方法似乎沒有存在的必要。但事實上,這種方法存在一個重要的缺陷,由於這種方法是在16-bit時代就存在的,所以,它通過16-bit寄存器來保存記憶體容量作為返回值。但16-bit所能夠表示的最大值是64KB。由於這種方法的返回值是以KB為單位,所以它能夠表示的系統最大實體記憶體容量為64 MB。而對於今天的PC機來說,64MB已經是很低的記憶體配置了,大多數PC機的實際實體記憶體配置都大於64 MB。

另外,需要注意的是,由於這種方法出現於Intel80286時代,而80286的24-bit位址匯流排能夠訪問的最大位址為16MB,所以,儘管這種方法使用16-bit寄存器能夠表示的最大記憶體數量為64MB,但標準的BIOS只允許通過這種方法獲取最大16 MB的實體記憶體數量。

為了能夠獲取大於64MB的記憶體,就必須通過另外兩種方法的一種。但並非每一台PC機都實現了這兩種方法或這兩種方法之一。

當今流行的桌面作業系統在Booting階段進行記憶體檢測的方法都是採用這三種方法,比如Microsoft WindowsNT,Linux等。所以在某些不支持E820h,E801h的PC上,它們也最多只能檢測到64 MB或16MB實體記憶體(依賴於88h的最大返回值限制)。
但請不必過分擔心,對於絕大多數現代PC機來說,至少提供了這兩種方法的一種;而對於過去的PC機,又很少有超過64MB的配置。從這個意義上來說,這已經足夠了。

INT 15h, AX=E820h Query SystemAddress Map
E820h只能用在Real Mode下使用
這個中斷調用返回所有被安裝在主機上的RAM,以及被BIOS所保留的實體記憶體範圍的記憶體映象。

Reference
http://docs.huihoo.com/gnu_linux/own_os/booting-memory_check_6.htm
Acpi Spec 3.0b

底下是範例程式下載以及執行後的結果,我是用7-Zip 免費壓縮軟體壓縮的,所以請使用最新版WinRar或是7-Zip 才能解壓縮喔...

點我下載E820範例程式 <~~記得在DOS下跑喔...


BassLow BaseHigh SizeLow SizeHigh Type

------------------------------------------------------
00000000 0000 0009FC00 0000 1 AddressRangeMemory(EfiLoaderCode)
0009FC00 0000 00000400 0000 2 AddressRangeMemory(EfiLoaderData)
000E0000 0000 00020000 0000 2 AddressRangeMemory(EfiLoaderData)
00100000 0000 363E6000 0000 1 AddressRangeMemory(EfiLoaderCode)
364E6000 0000 00003000 0000 4 AddressRangeMemory(EfiBootServiceData)
364E9000 0000 01583000 0000 1 AddressRangeMemory(EfiLoaderCode)
37A6C000 0000 00053000 0000 2 AddressRangeMemory(EfiLoaderData)
37ABF000 0000 000C6000 0000 1 AddressRangeMemory(EfiLoaderCode)
37B85000 0000 0003A000 0000 4 AddressRangeMemory(EfiBootServiceData)
37BBF000 0000 00025000 0000 1 AddressRangeMemory(EfiLoaderCode)
37BE4000 0000 00013000 0000 3 AddressRangeMemory(EfiBootServiceCode)
37BF7000 0000 00009000 0000 1 AddressRangeMemory(EfiLoaderCode)
37C00000 0000 08400000 0000 2 AddressRangeMemory(EfiLoaderData)
F8000000 0000 04000000 0000 2 AddressRangeMemory(EfiLoaderData)
FEC00000 0000 00001000 0000 2 AddressRangeMemory(EfiLoaderData)
FED10000 0000 00004000 0000 2 AddressRangeMemory(EfiLoaderData)
FED18000 0000 00002000 0000 2 AddressRangeMemory(EfiLoaderData)
FED1C000 0000 00004000 0000 2 AddressRangeMemory(EfiLoaderData)
FEE00000 0000 00001000 0000 2 AddressRangeMemory(EfiLoaderData)
FFF00000 0000 00100000 0000 2 AddressRangeMemory(EfiLoaderData)

看的出來這台是1MB 的BIOS ROM吧 ...^^


Dump Memory map v1.0.0 by Harrison Hsieh

8 則留言:

匿名 提到...

請問一下,是如何計算出1MB的BIOS ROM空間?

匿名 提到...

目前在研究關於CPU Cx-state的問題..發現CPU 的 C-state一開啟USB copy file to SATA XP就會hang-up...請問您有哪些建議呢?

匿名 提到...

請問一下,是如何計算出1MB的BIOS ROM空間?
應該是看最下面那行
FFF00000 0000 00100000 0000 2 AddressRangeMemory(EfiLoaderData)

00100000大小是1MB
我有另一個問題問小華大大
使用你的範例程式所列出來的memory map
我怎麼知道哪些是被使用了或者是還沒被使用的?
Thx

匿名 提到...

我知道了
應該是看後面的TYPE
Value Name Description
1 AddressRangeMemory 這個內存段是一段可以被OS使用的RAM
2 AddressRangeReserved 這個地址段正在被使用,或者被系統保留,所以一定不要被OS使用
Other Undefined 保留為未來使用,任何其它值都必需被OS認為是AddressRangeReserved

抱歉沒做功課

小華的部落格 提到...

恩恩,沒錯! 是看後面的Type...

如果你是BIOS工程師,你會看到在做Memory test的時候會去參考那個type 來做一些記憶體的檢測動作!

匿名 提到...

可以給程式範例的原始碼參考看看嗎?

匿名 提到...

這裡有一份sample:
http://code.google.com/p/e820/source/browse/#svn%2Ftrunk

Unknown 提到...

您好,我想要跟您拿範例程式與原始碼觀看,上面的網址連進去後已經沒有檔案了