OS開發筆記(2)——GRUB啟動流程

迷路的鹿1202發表於2024-12-06

GRUB如何突破真實模式的限制

BIOS與MBR引導機制

BIOS會在啟動時,檢查邏輯0扇區(即硬碟的第一個扇區)的結尾是否存在標誌 0x55, 0xaa,以此判斷該扇區是否可引導。按照傳統的MBR(Master Boot Record)引導流程,邏輯0扇區包含一個特殊的載入程式。這個程式的任務是檢查位於邏輯0扇區偏移 0x1BE 處的分割槽表。分割槽表最多可以記錄四個分割槽,這也是為什麼 MBR 分割槽的硬碟只能有四個主分割槽的原因。

在分割槽表中,每個分割槽可以有一個“可引導”標記。MBR載入程式會根據某種規則選取一個被標記為“可引導”的分割槽,將該分割槽的第一個扇區(稱為VBR,Volume Boot Record)載入到記憶體中(一般載入到地址 0x7C00 以保證相容性)。隨後,程式跳轉到VBR,由VBR負責載入並啟動該分割槽中的作業系統。

MBR和VBR的侷限性

然而,MBR和VBR的大小都僅有一個扇區,也就是512位元組,這對稍微複雜的載入程式來說已經不夠用。此外,在16位真實模式下,CPU的定址範圍最大隻有1MB(實際可用空間還小於1MB,需考慮BIOS和其他資料佔用)。因此,對於體積超過1MB或需要載入到1MB以上地址的核心檔案,MBR和VBR的能力不足。

16位的定址限制

切換到保護模式雖然可以突破1MB定址範圍的限制,但由於僅真實模式支援呼叫BIOS功能,在保護模式下無法直接呼叫BIOS來實現硬碟驅動和檔案系統管理。這就需要自行實現這些功能,極大地增加了載入程式的複雜度。為了避免在引導內再實現一邊磁碟驅動和檔案系統,我選擇了使用GRUB。

GRUB的解決方案

在GRUB中,將被稱為stage1.5階段的GRUB核心載入器(從磁碟啟動是diskboot,從光碟是cdboot等等)存放在存放磁碟中的某個空閒空間(預設是MBR後的一個扇區),一個定製的MBR載入程式(如 boot.S,編譯後生成 boot.img)負責載入這一階段的程式到記憶體中。

這時候就又出現一個問題,怎麼存放GRUB核心呢?GRUB提供了兩種方式:

  1. 使用磁碟未分配空間
    GRUB將包含核心功能的 core.img 寫入硬碟上未被分割槽表劃分的空閒空間。
  2. 基於檔案系統引導
    core.img 被當作一個普通檔案儲存在檔案系統中,由MBR程式載入到記憶體中。

GRUB如何找到core.img

如果採用基於檔案系統的方式,問題在於MBR程式如何知道 core.img 的具體位置。GRUB 的core.img 是透過grub-mkimage命令生成的,它由多個部分組成,包括:

  • diskboot:負責從磁碟載入 core.img 的第一部分,大小為一個扇區。
  • decompresser:用於解壓 grub-core,以支援壓縮後的儲存形式。
  • core:核心程式模組,可以根據需要載入各種功能擴充套件(grub模組)。

當執行 grub-install 時,工具會自動將 diskboot 的位置寫入 boot.img 中。diskboot 的末尾包含一個 blocklist,用於記錄 grub-core 的各個部分在磁碟上的位置。這樣,diskboot 可以順利載入完整的 grub-core

GRUB的引導過程

綜上,GRUB 2 的啟動流程如下:

  1. MBR引導
    BIOS 載入 MBR(即 boot.img),執行其中的載入程式。
  2. 載入diskboot
    MBR 程式根據記錄的位置載入 diskboot
  3. 載入並解壓grub-core
    diskboot 根據 blocklist 讀取並載入 grub-core,必要時解壓。
  4. 啟動作業系統核心
    grub-core 最終載入目標作業系統的核心檔案,並完成引導。

感想

稍微深入瞭解過GRUB後,感覺像是迷你核心一樣,功能這麼豐富。

相關文章