2009年3月26日 星期四

●X86開機時的狀況

開機後,CPU重置,從位址FFFFFFF0取第一個命令,這個位址正好落在ROM BIOS中。該位址內容一定是一個JMP指令,系統便跳轉到該JMP指令所指的地方。
1‧而這裡之後我開始不明白了。JMP要跳轉到的位置是在高地址(4G末端)Flash Rom BIOS中還是在低地址(1M末端)的shadow BIOS呢?
2‧位於低地址(1M處)的(BIOS shadow)是從Flash BIOS拷貝而來呢,還是沒有任何拷貝過程僅僅利用位址映射到原Flash BIOS中的呢?
3‧無論是拷貝還是映射,記憶體位址空間上ROM BIOS映射區只有 0xF0000~0x100000之間的64KB。而ROM本身有可能大於2M。那映射的應該是原BIOS程式的一部分,那麼是哪一部分呢?對這個問題的回答需要闡明機關概念:
1.機器加電時,記憶體控制器還沒有初時化,記憶體是不可用。
2.機器加電時,對CPU的指令的解碼不是北橋,CPU發出的位址被傳遞到南橋並由FHW(Firmware Hub)解碼到BIOS ROM晶片(Flash)。在加電時一直到引導進程初,BIOS的E段(0xE0000~0xEFFFF)和F段(0xF0000~0xFFFFF)和4G記憶體頂端的對應段0xFFFE0000~0xFFFEFFFF和0xFFFF0000~0xFFFFFFFF都被FWH解碼到BIOS的ROM晶片的兩個64區域。即在啟動階段訪問0xE0000~0xEFFFF和0xFFFE0000~0xFFFEFFFF是同一個BIOS區域,訪問0xF0000~0xFFFFF和0xFFFF0000~0xFFFFFFFF是同一個BIOS區域。
3.機器加電時,CS段寄存器值為0xF000,EIP值為0x0000FFF0,但CPU的取的位址是段寄存器不可見的部分(影子寄存器)加上偏移部分,此時影子寄存器的值為0xFFFFFFF0。所以CPU執行的第一條指令是0xFFFFFFF0(復位向量),通常在BIOS ROM對應的指令是一個跳轉指令JMP F000:E05B,當取出跳轉完成後,由於CS段的影子寄存器刷新並重新載入,下一條指令位址是0xFE05B。不過這條指令仍然從BIOS ROM裡取得。
4.關於shadow BIOS,BIOS程式通常是壓縮的,在系統初始化階段,BIOS會解壓BIOS Image到RAM中,然後程式設計北橋控制器對0xE0000~0xFFFFF置為write only,這樣對該區域的寫被傳遞到DRAM裡,然後把解壓的BIOS拷貝到E段和F段。最後重新程式設計北橋控制器對0xE0000~0xFFFFF置為read only。對於PCI ROM BIOS,BIOS會把每個卡上的ROM拷貝到0xC0000~0xDFFFF然後執行他們的初時化代碼。5.BIOS ROM可以很大,但不都是可執行的,如含有ACPI Table等,開始解壓到0xE0000~0xFFFFF只是其中一部分,在啟動過程中還需要從BIOS ROM解壓代碼到RAM中,並覆蓋其中不需要的代碼。這個就好像BIOS ROM是硬碟(不過可用直接訪問),真正執行的代碼在RAM中一樣。硬碟可以很大但RAM小,這也就是程式的局部性原理。
這個網址也是相關議題的論述:X86 開機流程小記BIOS 探索之旅可以比較一下是否有差異點。

BIOS的幾個模組中有部分是壓縮的,有部分是 pure binary,純代碼和壓縮代部參雜在一起。
BIOS有部分是 routine 元件,它是 pure binary,其它就包括初始化(晶片組、DRAM等)模式,解壓routine元件、還有就是CPU 的微代碼update模式等等,提供BIOS運行期間的一些函式呼叫,解壓rontine的作用就是解壓壓縮組件,將它們放入相應的memory中。還有 一件重要的事情是,建立一個 interrupter vector 及 interrupt service routine。

bios啟動ram記憶體初始化前bios是否在rom中運行,這樣的話rom的地址會不會跟ram地址衝突?
北橋晶片有 Shadow RAM 功能,ROM 和 RAM 都會映射到同一段位址,但是根據讀寫信號的不同轉到 ROM 或者 RAM去。
第一條 long jmp 指令,也就成為 x86 pc 機的固有約定或者說是規範吧。

其實主要的原因是相容!追溯到最早 808X 系列處理器,8080 是 16 位 address bus, 8086 及 8088 改進為 20 進 address bus,整個 808X 系列處理就是整個 x86 架構的始祖。定址空間 00000 ~ FFFFFh 也就是 1M 的空間。
當時 IBM 決定使用 8086 處理作為 IBM PC 機,故事就從那裡開始,BIOS 這個名詞也就是 IBM 發明出來的,IBM 搞出來的 BIOS 定位在 8086 處理器的定址高端,也就是 F0000 到 FFFFF 區域。從 386 開始,address bus 增加到 32 條,定址範圍從 0 ~ FFFFFFFFh,BIOS 的定位也在 4G 的高端FFFF0000 ~ FFFFFFFFh,但為了相容,對 F0000 ~ FFFFF 的訪問被映射到 FFFF0000 ~ FFFFFFFFh,這是從理論上定義的。
從物理上來講,F0000 ~ FFFFFh 映射到 FFFF0000 ~ FFFFFFFFh 靠硬體來保證,在位址解碼時,F0000 ~ FFFFFh 與 FFFF0000 ~ FFFFFFFFh 會被解碼到同一個區域。現在的晶片組提供的廠商有很多,如:Intel,AMD,nvidia,VIA,SIS 等,它們的解碼實現方法可能會不同,但都要保證這個所謂的“別名”機制。
Intel 實現是:MCH 將 C_0000 ~ F_FFFF 這段區域定義為 PAM(Programed attribute memory),分 disable,read-only ,wirte-only,read/write 四種屬性,初始屬性是 disable,也即是無用,因此這段區域將被送去 ICH 解碼,FFE0_0000 ~ FFFF_FFFFh 的也被 ICH 解碼,ICH 轉交 LPC bridge 處理,它們被解碼為同一區域。
AMD 實現是:無論是 C_0000 ~ F_FFFF,還是 FFFC_0000 ~ FFFF_FFFF 最終結果都將送到 LPC bus 上的 FFFC_0000 ~ FFFF_FFFF 物理位址上。其它的廠商實現也大體這樣。

因此:long jmp 後,轉到 FE05B(jmp far ptr F000:E05B)執行,它將被映射到物理位址 FFFFE05B 上,這還是 BIOS 所在的 ROM 中。第一條指令的 FFFFFFF0 與 第二條的 FE05B 都是在 BIOS 的 ROM 上。
--> 閱讀更多...