LinuxBoot介紹
這是 LinuxBoot 專案的官方「LinuxBoot 書籍」。這本書:
- 描述 LinuxBoot 項目
- 解釋為什麼要使用 LinuxBoot
- 描述組成 LinuxBoot 的元件
- 說明其他啟動系統(如 UEFI)與 LinuxBoot 的差異
- 指導您完成實作 LinuxBoot 所需的步驟
什麼是 LinuxBoot?
LinuxBoot 的想法是用 Linux 核心和基於社群的用戶空間(user-space) 取代專有或企業主導的後期啟動韌體。這個想法逐漸發展成為一個項目,多年來包括各種舉措,其總體目標是從晦澀複雜的韌體轉變為更簡單和開源的韌體。
The LinuxBoot project provides two reference implementations; linuxboot
and Heads. The linuxboot
build system outputs a boot payload consisting of a Linux kernel and an initramfs that contains a minimal Go user-space built using u-root.
Heads 構建系統更側重於本地證明(local attestation)、TPM DUK 密封/解封(seal/unseal)操作、基於 GPG 的安全措施、可重現構建(reproducible builds),並使用 BusyBox 提供更大的 Linux 工具套件,使其也可以用作修復環境(recovery environment)。
許多其他實作獨立於專案而存在:
- petitboot 屬於 OpenPOWER 項目,最初針對的是 PS3
- k-boot 由 BayLibre 於 2023 年使用 BusyBox 開發
- nmbl 由 RedHat 於 2024 年開發
- ZFSBootMenu
此外,過去也曾有許多類似的實作,其中包含一些已不再維護的專案:
- Alpha 版 MILO 於 2000 年之前就已啟動(請參閱什麼是 MILO?)
- kboot 由 Werner Almesberger 於 2005 年開發
這些專案都試圖將韌體的角色簡化為一個小型、固定功能的核心,其唯一目的是啟動一個儲存在快閃記憶體(flash)中的 Linux 核心(Linux kernel)。這個「最低必要」(bare essentials)的韌體會負責初始化硬體,接著啟動 Linux 核心,並讓使用者空間環境(user-space environment)在機器上運行。Go 是建議使用的使用者空間環境,但並非必須。
為什麼需要 LinuxBoot
有時候,韌體會包含驅動程式和工具程式(utilities)。這些元件可能存在漏洞,或是已無人維護,進而成為問題或資安風險的來源。LinuxBoot 以 Linux 驅動程式取代了供應商提供的專有閉源韌體驅動(proprietary, closed-source firmware drivers),讓開發 Linux 驅動與韌體驅動的工程師能專注於同一套驅動程式。如此一來,這些驅動程式將擁有更多的貢獻者 (contributors) 與審閱者(reviewers),又因為它們是 Linux 的一部分,能夠運用業界標準的開發流程與工具(standard industry coding infrastructure)來持續改善。最終,由於這些 Linux 驅動目前已在大量系統上長時間穩定運作(run around the clock at scale),其錯誤率也會相對較低。
LinuxBoot 的功能
LinuxBoot 以 Linux 應用程式取代了統一可擴充韌體介面(Unified Extensible Firmware Interface,UEFI)與其他韌體中大量的驅動程式執行環境(Driver Execution Environment,DXE)模組,特別是網路協定堆疊(network stack)和檔案系統(file system)模組。
LinuxBoot 將 Linux 核心(Linux kernel)作為快閃記憶體(flash ROM)中的驅動程式執行環境(Driver Execution Environment, DXE)啟動,而非傳統的 UEFI shell。接著,Linux 核心可透過隨附的基於 Go 的使用者空間(user-space)來載入運行時核心(runtime kernel)。LinuxBoot 的架構(paradigm)使得傳統的韌體應用程式(例如開機載入器、偵錯工具、診斷與錯誤偵測應用程式)能夠以跨架構、跨平台的可攜式 Linux 應用程式形式實作。
當 Linux 啟動時,它需要一個包含工具程式(utilities)的根檔案系統(root file system)。LinuxBoot 使用的其中一種根檔案系統是基於使用 Go 語言編寫的 u-root 標準工具程式(standard utilities)。下圖顯示了目前 UEFI 啟動過程的狀況,以及計畫中的 LinuxBoot 過渡流程。
使用 Go 使用者空間(user-space)環境和編譯器的好處
Go 是由 Google 創建的系統程式語言。Go 具有強類型(strong typing)、語言級別的並發支援(concurrency support)、透過通道(channels)進行進程間通訊(inter-process communication)、運行時類型安全性(runtime type safety)和其他保護措施、動態分配(dynamic allocation)和垃圾收集(garbage collection)以及閉包(closures)。Go 具有與 Java 類似的套件名稱符號(package name notation),使得可以清楚地確定給定程式需要哪些套件(packages)。
現代語言結構使 Go 成為比 C 更安全的語言。這種安全性對於網路連接的嵌入式系統至關重要,這些系統通常擁有用 C 編寫的網路工具程式,包括網頁伺服器、包含 sshd 的網路伺服器(network servers),以及提供命令解釋器存取的程式(本身以 C 編寫)。所有這些都證明容易受到互聯網成為攻擊頻繁環境的威脅。
即使是最熟練的程式設計師也會犯下 C 語言中無法恢復的錯誤,尤其是在網路連線系統上。目前,即使我們個人電腦、印表機和恆溫器中最低等級的韌體也是連網的。這些程式錯誤要麼在 Go 中不可能犯,要麼如果犯了,則會在運行時檢測到並導致程式退出。
在低階嵌入式韌體中使用像 Go 這樣的高級安全語言的理由,可能比用戶程式更為充分,因為在韌體層級的漏洞幾乎不可能被檢測和緩解。
在韌體等儲存受限的環境中使用 Go 的挑戰在於,高階語言特性會導致二進位檔案過大。即使是簡單的日期程式也約有 2 MiB。一個實現單一功能的 Go 二進位檔案大小是實現多個功能的 BusyBox 二進位檔案的兩倍。當前,典型的 BIOS 快閃記憶體(FLASH)大小為 16 MiB。將多個 Go 二進位檔案裝入單一 BIOS 快閃記憶體區塊是不切實際的。Go 編譯器速度非常快,且其速度顯示了只有在使用程式時進行編譯的解決方案。透過這種方式,您可以建立一個幾乎不含二進位檔案(除了 Go 編譯器本身)的根檔案系統。編譯後的程式和套件可儲存到基於 RAM 的檔案系統中。另一個解決方案是將所有程式編譯成一個 BusyBox 風格的程式。或者,程式可以透過網路獲取,但動態編譯 Go 或創建 BusyBox 程式是建議的解決方案。
在 UEFI 伺服器上使用 LinuxBoot 的好處
大多數伺服器韌體基於 Intel 的通用可擴展韌體介面 (UEFI)。與 UEFI 相比,LinuxBoot 具有以下優點:
可靠性
- 透過使用強化的 Linux 驅動程式取代未經充分測試的韌體驅動程式來提高啟動可靠性
- 近 20 年來,在軍事、消費性電子和超級電腦領域,可靠性和性能至關重要的領域,該實踐方法已得到驗證
- 容錯 - Linux 隔離程序** **(例如,當「pxeboot」發生災難性故障時,「diskboot」仍然可以運作)
安全性
- 將“Ring 0”引導程式(bootloaders)移至“Ring 3”
pxeboot
和diskboot
在使用者空間(user-space)進行解析和其他邏輯處理- Go 提供記憶體安全和類型安全(type safety)
- 有缺陷的解析器(parser)不太可能影響其他程式
- 核心安全性補丁(patches)可應用於韌體
靈活性
- 可與 coreboot、u-boot、OpenPOWER 抽象層 (OpenPOWER Abstraction Layer, OPAL)、SlimBootLoader、ARM 可信任韌體 (Arm Trusted Firmware, ATF) 搭配
- 可啟動多個作業系統(Linux、Berkeley UNIX(BSD)、XEN、Windows)
- 支援以下伺服器主機板:
- QEMU 模擬的 Q35 系統
- Intel S2600WF
- Dell R630
- Winterfell Open Compute node
- Leopard Open Compute node
- Tioga Pass Open Compute node
- Monolake Open Compute node(未經測試)
啟動速度
- 透過移除不必要的程式碼來提升啟動時間;通常能使啟動速度提高 20 倍
客製化
- 允許自訂 initramfs 運行時,支援特定環境的需求(包括裝置驅動程式和自訂執行檔)
工程生產力
- 編寫一次驅動程序,無需編寫兩次
- Linux 是 開放、可衡量、可重現且易於更新的
- Linux 已經為幾乎所有東西提供了驅動程式
- 核心(kernel)工程師=韌體工程師
- 了解 Linux 的工程師比了解 UEFI 的工程師多得多
- 減少建置時間
- initramfs 需要 30 秒
- 核心需要 15 秒(增量式)
- 大約 15 秒 重新包裝 bios 映像檔(使用 fiano/utk)
- 總計:約 1 分鐘 用於新的完整 BIOS 映像,可供測試
- 測試和除錯
diskboot
和pxeboot
已經有單元測試 (unit tests)- 使用 Linux 資源(如網路)使編寫測試更容易
- u-root 等開源專案遵循優秀的軟體實踐,例如對每個提交的變更執行自動化測試
- 更容易除錯的 Go 用戶空間(user-space)應用程式
- 使用 QEMU 中的核心進行測試