系統引導載入器的簡單實現

weixin_33912246發表於2017-11-16

在實現引導載入器之前,首先我們先了解下在開機之後系統是怎麼被引導的,這對於實現引導載入器來說是很重要的。只有知道原理,才能更好的實現嘛。

1 引導過程

1.1 當電源按鈕按下時

  當我們按下電源按鈕是到底發生了什麼?當這個按鈕被按下後,連線到這個按鈕的線纜會向主機板傳送一個電訊號,主機板簡單的把這個訊號轉發給電源(PSU )。這個訊號只包含1 位元資訊。如果是0 ,表示沒電(計算機關閉,主機板不活動)。如果是1 (活動訊號),意味著系統已經加電。當PSU 收到這個活動訊號,它開始向系統的其餘部分供電。當所有裝置都得到正確數量的供電時,就可以確定PSU會持續向它們供電而不發生大的問題。PSU會傳送一個“供電正常(power_good )”的訊號到主機板的基本輸入輸出系統 (BIOS) 。

1.2 BIOS自檢

  到那個BIOS 接收到“power_good ”訊號,BIOS 開始一個稱為POST(Power On Self Test 加電自檢) 的初始化過程。POST 通過測試確保供電正確,裝置已安裝 ( 如:鍵盤、滑鼠、USB 、串列埠等) ,並確保記憶體狀態良好 ( 通過檢測記憶體損傷) 。POST 向BIOS 交出控制權。POST 將BIOS 載入到記憶體的末尾( 可能是0xFFFFF0) 並且在記憶體的第一個位元組處放置一個跳轉指令。處理器指令指標 (CS:IP) 被設定為0 ,然後處理器得到控制權。什麼意思呢?處理器會在地址0x0 處開始執行指令。這裡,它是一條POST 程式放置的跳轉指令,這條指令跳轉到0xFFFFF0 處( 或者其他BIOS 被載入到的地址) ,然後處理器開始執行BIOS 。BIOS 得到控制權……

1.3 BIOS

  基本輸入輸出系統(BIOS) 會做一些工作。它建立一箇中斷向量表 (IVT), 並提供基本的中斷服務。BIOS 然後會做一些檢查以確保沒有硬體問題。BIOS 也提供一個設定的功能。BIOS 需要找到一個作業系統。根據您在BIOS設定中指定的引導順序,BIOS 執行0x19 號中斷來找出一個可引導裝置。如果沒有找到可引導裝置 (INT 0x19 返回了) ,BIOS 會嘗試引導順序列表中的下一個裝置。如果再沒有可供嘗試的裝置,BIOS 會列印一個類似於“作業系統未找到”的資訊,並停止系統的執行。

1.4 中斷與中斷向量表 (IVT)

  一箇中斷是可以被許多不同的程式呼叫的子程式。這些中斷被儲存在從地址0x0 開始的被稱為中斷向量表的空間中。比如,一個常見的中斷INT 0x21 被用於DOS 系統。

  注意:這兒沒有DOS !“只有”BIOS 設定的中斷才有效,沒有其他的!使用其他的中斷會導致系統執行不存在的程式,這將導致你的系統崩潰。

  注意:如果切換處理器模式到保護模式,IVT 會變得無效。這意味著,任何的中斷(無論軟硬體,包括BIOS )全都無效。 對於32 位作業系統,我們不得不這樣做

1.5 BIOS 0x19 中斷

  該中斷由BIOS 執行。它讀入磁碟的第一個扇區( 扇區(Sector ) 1, 磁頭(Head ) 0, 磁軌(Track ) 0) 。如果磁碟可引導,則引導扇區會被載入到0x7C00  INT 0x19 會跳轉到那裡,將控制權交給引導載入器。

1.6 引導扇區

  由0x19中斷讀取的第一個扇區正是引導扇區,裡面存放了引導載入器的程式碼。當被讀入記憶體0x7c00後,引導載入器就得到了控制權,開始執行載入系統。

1.7 為什麼要引導載入器

  為什麼不把作業系統的程式碼直接寫到第一個扇區,還要這麼麻煩先執行個引導載入器,再把系統載入到記憶體中,開始我也覺得直接把系統寫到第一個扇區更好,可後來發現其實不然。第二種方法就方便了,就像我們在操作檔案一樣的,可以隨時修改系統程式,而第一中我們還要再每次對系統程式修改後用dd命令寫入扇區,而且還要好好的計算大小,所以比較的麻煩,也比較容易出錯。

2 引導載入器的實現

  我的簡單引導載入器實現的程式碼比較簡單,就是從裝有FAT12檔案系統的軟盤(軟盤映象檔案)中讀取一個叫setup的可執行檔案,並最終執行這個SETUP程式,SETUP程式會在螢幕上列印preparing to load operating system...,如下圖所示:

2.1 製作裝有FAT12檔案系統的軟盤映象檔案

  首先製作一個空的1.44M的軟盤映象檔案:

dd if=/dev/zero of=bootsect.img bs=512 count=2880

  然後用“mkfs.msdos -F 12”命令格式化軟盤映象檔案為FAT12檔案系統

mkfs.msdos -F 12 bootsect.img

2.2 拷貝SETUP程式到軟盤映象中

  這個程式很簡單,就列印一條語句,主要是為了測試引導載入程式是否成功載入了SETUP程式,編譯可執行檔案後怎樣把它拷貝到軟盤映象中呢?這個其實很簡單,就像其它的檔案系統一樣,FAT12也可以掛載到linux中的某個目錄下,然後將SETUP程式拷貝到這個目錄下就可以了。具體操作為:

losetup /dev/loop5 bootsect.img 
mount /dev/loop5 floppy/
cp SETUP floppy/
umount floppy/
losetup -d /dev/loop5

  不過在我係統裡losetup -d /dev/loop5命令執行總是失敗,總是提示loop: can't delete device /dev/loop5: Device or resource busy,網上有人說是bug,具體什麼原因還不知道。

2.3 編寫引導載入程式

  引導載入器的思路其實很簡單,就是先載入FAT12檔案系統的根目錄所在的扇區到記憶體中,然後在根目錄中查詢檔名為SETUP的目錄項,找到後獲得SETUP所在的族號。再載入FAT12的FAT表。根據找到的族號來獲得SETUP在軟盤中的具體位置,並將其載入到記憶體中,如果SETUP檔案較大,一個族不夠,可以通過FAT表查詢一個族,再將下一個族載入到記憶體...,等全部載入SETUP到記憶體後,將控制權交給SETUP程式,然後SETUP程式就開始執行了,也就出現了上面圖中的內容。這裡的難點可能就是計算目錄項在軟盤中的位置、SETUP程式在軟盤中的位置。

2.4 拷貝引導載入程式到軟盤映象的第一個扇區

  對於編譯好了的引導載入程式怎樣拷貝到軟盤映象的第一個扇區來作為引導扇區呢?還是用linux的好工具dd,具體如下:

dd if=bootsect.img of=bootloader skip=1 seek=1 bs=512 count=2879

 

  bootsect.img為我們前面製作好的軟盤映象,bootloader為我們編譯好的引導載入程式。這條命令執行後bootloader就是我們的包含引導載入器的軟盤映象檔案了,可以作為虛擬機器的映象檔案來引導系統了(相當於我們這裡的SETUP程式)。在bochs中執行的畫面就是上面給出的圖,當然也可以在其他虛擬機器上執行,像wmware。

3 總結

  實現這個引導載入器,讓我學到了很多關於系統啟動的東西,如引導扇區的載入過程,FAT12檔案系統,軟盤映象的製作等。不過也發現了很多問題,特別是對彙編的不熟練,寫這個程式中間一直出現問題,但開始自己也不會除錯彙編程式,所以不知所措,後來才慢慢通過學習debug除錯,bochs除錯來慢慢解決的。不過深感還有很多東西要學習。

 

附件:bootloader和setup程式原始碼

相關文章