1. 程式人生 > >系統引導加載器的簡單實現

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

位操作 地址 計算 中斷向量表 count 硬件 1.3 編寫 src

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

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程序源代碼

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