EFI 啟動樁

在 x86 和 ARM 平臺上,核心 zImage/bzImage 可以偽裝成 PE/COFF 映象,從而說服 EFI 韌體載入器將其載入為 EFI 可執行檔案。 修改 bzImage 標頭的程式碼,以及韌體載入器跳轉到的 EFI 特定入口點,統稱為“EFI 啟動樁”,位於 arch/x86/boot/header.S 和 drivers/firmware/efi/libstub/x86-stub.c 中。 對於 ARM,EFI 樁在 arch/arm/boot/compressed/efi-header.S 和 drivers/firmware/efi/libstub/arm32-stub.c 中實現。 架構之間共享的 EFI 樁程式碼位於 drivers/firmware/efi/libstub 中。

對於 arm64,沒有壓縮核心支援,因此 Image 本身偽裝成 PE/COFF 映象,並且 EFI 樁被連結到核心中。 arm64 EFI 樁位於 drivers/firmware/efi/libstub/arm64.c 和 drivers/firmware/efi/libstub/arm64-stub.c 中。

透過使用 EFI 啟動樁,無需使用傳統的 EFI 啟動載入器(例如 grub 或 elilo)即可啟動 Linux 核心。 由於 EFI 啟動樁執行啟動載入器的工作,因此在某種意義上,它是啟動載入器。

EFI 啟動樁透過 CONFIG_EFI_STUB 核心選項啟用。

如何安裝 bzImage.efi

位於 arch/x86/boot/bzImage 中的 bzImage 必須複製到 EFI 系統分割槽 (ESP) 並重命名為副檔名“.efi”。 如果沒有副檔名,EFI 韌體載入器將拒絕執行它。 無法從通常的 Linux 檔案系統執行 bzImage.efi,因為 EFI 韌體不支援它們。 對於 ARM,arch/arm/boot/zImage 應複製到系統分割槽,並且可能不需要重新命名。 類似地,對於 arm64,arch/arm64/boot/Image 應該被複制,但不一定需要重新命名。

從 EFI shell 傳遞核心引數

核心的引數可以在 bzImage.efi 之後傳遞,例如

fs0:> bzImage.efi console=ttyS0 root=/dev/sda4

“initrd=” 選項

與大多數啟動載入器一樣,EFI 樁允許使用者使用“initrd=”選項指定多個 initrd 檔案。 這是唯一的 EFI 樁特定命令列引數,其他所有內容在啟動時都會傳遞給核心。

initrd 檔案的路徑必須是從 ESP 開頭的絕對路徑,相對路徑名稱不起作用。 此外,該路徑是 EFI 樣式的路徑,目錄元素必須用反斜槓 () 分隔。 例如,給定以下目錄佈局

fs0:>
      Kernels\
                      bzImage.efi
                      initrd-large.img

      Ramdisks\
                      initrd-small.img
                      initrd-medium.img

如果當前工作目錄是 fs0:Kernels,要使用 initrd-large.img 檔案啟動,則必須使用以下命令

fs0:\Kernels> bzImage.efi initrd=\Kernels\initrd-large.img

請注意 bzImage.efi 如何可以使用相對路徑指定。 這是因為我們正在執行的影像由 EFI shell 解釋,EFI shell 瞭解相對路徑,而命令列的其餘部分將傳遞給 bzImage.efi。

“dtb=” 選項

對於 ARM 和 arm64 架構,必須向核心提供裝置樹。 通常,韌體應透過 EFI CONFIGURATION TABLE 提供裝置樹。 但是,“dtb=”命令列選項可用於覆蓋韌體提供的裝置樹,或者在韌體無法提供裝置樹時提供一個。

請注意:韌體會在啟動核心之前將執行時配置資訊新增到裝置樹。 如果使用 dtb= 覆蓋裝置樹,則韌體提供的任何執行時資料都將丟失。 僅應將 dtb= 選項用作除錯工具,或者作為 EFI CONFIGURATION TABLE 中未提供裝置樹時的最後手段。

“dtb=” 的處理方式與上面描述的“initrd=”選項相同。