2008年7月7日 星期一

Linux Booting Process

圖片來源:http://www.linuxjournal.com/article/2239

1. 電源正常啟動後,x86 CPU 會先執行 0xFFFF0,也就是 BIOS ROM 的進入點。
由於 0xFFFF0 ~ 0xFFFFF 只有少的很可憐的 16 bytes,真正的 BIOS code 勢必要擺到其他位置,
所以在0xFFFF0 僅放置一個jmp指令,BIOS利用該指令跳到別處,執行BIOS程式。

2. BIOS 程式的第一個動作就是執行最基本的 POST(Power-On Self Test) 檢查,確保系統在開機當中可以正常運作。

3. 接下來BIOS將查找Video Card BIOS,一般Video Card BIOS的放置位置為0xc0000,系統BIOS調用該位置的初始程式以初始化顯示卡。之後,系統BIOS陸續調用其他設備的BIOS初始化程式,以初始化該設備。

4. 接下來系統BIOS會作Full POST :

1. Video Test: 初始化顯示卡插槽並測試顯示卡和顯示記憶體。
2. BIOS Identification: 顯示 BIOS 版本、製造商及日期。
3. Memory Test: 測試並顯示安裝的主記憶體總容量數。

以上是冷開機 (cold-start) 的檢查流程,若是暖開機 (warm-start) 則省略 Memory Test。

除了上述檢查之外,BIOS 還會讀取存 CMOS configuration 資料(ESCD, Extended System Configuration Data)。這些放在靠小電池維生的 64 bytes CMOS 當中的資料,紀錄著一些使用者可調變的系統資訊,也就是開機時按 Del 鍵進去調整的那堆東西。另外也會做一些額外的檢查,例如動態設定 IDE/ATA 裝置的參數等等,同時顯示在這個畫面當中。一切就緒之後,系統BIOS 會將整個系統資訊都顯示在螢幕上,表示開機動作大抵完成,接下來就準備交棒給下一個程式(一般是bootloader)了。

5.BIOS 所執行的最後一個動作就是交接,將執行權交給下一支程式,boot loader 也好,OS 也好,或者單純的一支小程式。這時會依設定的順序搜尋各開機磁碟裝置 (floppy disk, hard disk, CD-ROM, ...) 的 cylinder 0, head 0, sector 1 (對 hard disk 來說就是 Master Boot Record, MBR),並將該 512 bytes 載入至記憶體 0x0000:7C00 而 jmp 過去完成交接 (注意此時 CS:IP 為 0x0000:7C00 而不是 0x07C0:0000)。對於 MBR 而言,還要多檢查最後兩 bytes 為 0x55AA,才判定為有效的 MBR 並 jmp 過去完成交接;否則繼續搜尋下一個裝置,直到沒有裝置則顯示 "No boot device available" 之類的錯誤訊息。

6.MBR (is a 512-bytes image that contains one stage 1 bootloader)位於 hard disk 的 cylinder 0, head 0, sector 1,紀錄著 hard disk 的分割狀態,於開機時被載入至記憶體 0x0000:7C00。開始執行後,由程式依序搜尋 partition 並 check 是否為 active (80),若是,則將控制權繼續交給 active partition。為了避免覆蓋,通常 MBR 會事先將自己搬到 0x0000:0600 的位置,之後才將 partition 的 boot sector (contain one stage 2 bootloader)載入至記憶體 0x0000:7C00,再 jmp 過去完成交接。
(While each partition can have a boot sector, your hard disk will have only one master boot record the BIOS loads every time you start your machine. )

7. stage 2 bootloader作以下的事情:

(1) 將内核的 bootsect.S和setup.S載入到位置0x90000
(2) 將compressed kernel image載入到位置0x10000
(3) 由0x90200開始執行setup.S


8. setup.S做什麼事請參考如下:
setup.s is responsible for getting the system data from the BIOS,
and putting them into the appropriate places in system memory.
both setup.s and system has been loaded by the bootblock.

This code asks the bios for memory/disk/other parameters, and
puts them in a "safe" place: 0x90000-0x901FF, ie where the
boot-block used to be. It is then up to the protected mode
system to read them from there before the area is overwritten
for buffer-blocks.

最後真正进入保护模式,跳转到arch/i386/boot/compressed/head.S中的startup_32


9. head.S in the compressed directory is at 0x1000, and is in charge of “gunzipping” the kernel; it calls the function decompress_kernel, defined in compressed/misc.c, which in turns calls inflate which writes its output starting at address 0x100000 (1MB). High memory can now be accessed, because the processor is definitely out of its limited boot environment—the “real” mode.其程式大致步驟如下:

(1)段地址准備,在內核里都為BOOT_DS=GDT_ENTRY_BOOT_DS*8=(GDT_ENTRY_BOOT_CS + 1)*8=(2+1)*8

(2)拷貝壓縮的內核到緩存結尾以保證安全

(3)計算內核啟始地址

(4)將壓縮內核解壓

(5)跳轉到解壓后的內核執行



參考資料來源:

http://www.cs.nctu.edu.tw/~huangmc/works/web/Boot_x86/Boot_x86.html
http://www.linuxjournal.com/article/2239
http://blog.csdn.net/wukaiyu/archive/2007/08/31/1766792.aspx

沒有留言: