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提供了兩種方式:
- 使用磁碟未分配空間
GRUB將包含核心功能的core.img
寫入硬碟上未被分割槽表劃分的空閒空間。 - 基於檔案系統引導
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 的啟動流程如下:
- MBR引導
BIOS 載入 MBR(即boot.img
),執行其中的載入程式。 - 載入diskboot
MBR 程式根據記錄的位置載入diskboot
。 - 載入並解壓grub-core
diskboot
根據blocklist
讀取並載入grub-core
,必要時解壓。 - 啟動作業系統核心
grub-core
最終載入目標作業系統的核心檔案,並完成引導。
感想
稍微深入瞭解過GRUB後,感覺像是迷你核心一樣,功能這麼豐富。