EFISTUB - Arch Linux 中文维基

跳至內容

# EFISTUB

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 EFI_boot_stub，最近一次同步於 2026-07-22，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- Arch 的啟動流程
- UEFI
- 統一內核映像

EFI boot stub (也稱為 EFI stub)是本身就為 EFI 可執行程序的內核，也就是說，它可以直接被 UEFI 引導啟動。

此前，本文和 Debian Wiki 曾將該術語拼寫為單個單詞 (EFISTUB 或 EFIStub).

默認情況下，Arch Linux提供的內核都是 EFI boot stubs。如果自行編譯內核，需將 `CONFIG_EFI_STUB` 配置為 `y` 以啟用它，詳見The EFI Boot Stub。

在繼續之前，需要一個 EFI 系統分區（ESP），並且選擇其掛載方式。

提示：

- 如果將ESP分區掛載到`/boot`，pacman 更新的內核就能直接使 UEFI 讀取。
- EFI boot stub也可以使用引導加載程序間接啟動:
  - 一些 UEFI 啟動管理器可以為 UEFI 引導提供額外選項或簡化過程
  - 這對於測試內核參數或有多個內核/作業系統且主板 UEFI 啟動菜單不易使用的情況尤為有用
  - 如果啟動管理器擁有內核和 initramfs 所在分區的文件系統的驅動（例如rEFInd），則無需將他們保存在 ESP 中。

## 另選方案：統一內核鏡像

統一內核鏡像 (UKI) 本身就是一個 EFI stub 內核,同時含有 initramfs 和啟動選項在單一文件中。下表列出了在它們被 UEFI 引導時，UKI 與非 UKI 的 EFI stub 的特性對比。

| UKI | 非 UKI 的 EFI stub
--- | --- | ---
initramfs | 包含在內 | 在單一文件中，存儲在 ESP 中
啟動選項 | 自身包包含在內含 | 存儲在 UEFI 變量中

當沒有問題時，UKI 更簡單，因為它只需要一個文件，並容納了所有啟動內核所必需的一切。然而，非 UKI 內核可以在不同的 initramfs 文件之間切換和嘗試不同的啟動選項。對於 UKI 來說，每次變動都會導致生成一個單獨的 UKI。

## 引導 EFI boot stub

注意：傳遞給內核 EFI boot stub 的 initramfs 路徑應當相對於 ESP 的根目錄，並使用反斜槓分隔路徑（遵循 EFI 標準）。例如，如果initramfs 在 `esp/EFI/arch/initramfs-linux.img`，則對應的 UEFI 格式行應為 `initrd=\EFI\arch\initramfs-linux.img`。在接下來的示例中將默認所有的文件都位於 `esp/` 目錄中.

### 直接使用 UEFI

UEFI 旨在擺脫對像 GRUB 這樣的中間引導加載程序的依賴. 如果你的主板有良好的 UEFI 實現，那麼可能直接將內核參數寫入 UEFI 引導項目以讓主板直接引導 Arch。可以使用 efibootmgr 或 UEFI Shell v2 以修改主板引導項目。

注意：

- 過時的UEFI 實現可能跟 Linux 內核有兼容性問題。如果設備的 UEFI 有新的修復了問題的版本，可以考慮使用主板廠商推薦的工具刷入。
- 此項可能已過時：一些固件 (尤其是 Lenovo 和 Dell 筆記本電腦) 不會將 NVRAM 中的引導項命令行參數傳給 EFI 可執行程序(詳見 Arch BBS 2014年的帖子)這種情況下，可以使用 UKI。

#### efibootmgr

使用 efibootmgr 添加加載內核的引導項

    # efibootmgr --create --disk /dev/block_device_name --part X --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=block_device_identifier rw initrd=\initramfs-linux.img'

其中，`block_device_name` 是塊設備名，`X` 是分區編號， `root=` 後的 `block_device_identifier` 是實際的 Linux 根目錄分區標識符。

注意：

- 有關支持的設備名稱格式，請參見內核參數。
- 有關如何獲取對應的值，請參見塊設備持久化命名。
- 有關具體示例，請參見塊設備持久化命名#內核參數。

注意：`-u`/`--unicode` 後的字符串是內核參數，可能還需要根據實際情況添加其它參數（如用於休眠到磁碟的參數）。

基於 LTS Linux 內核、NVMe 存儲、帶有特定子卷的 BTRFS 文件系統以及 Swap 分區休眠的示例：

    # efibootmgr --create \
     --disk /dev/nvme0n1 --part 1 \
     --label "EFISTUB Arch" \
     --loader /vmlinuz-linux-lts \
     --unicode 'root=UUID=01a40dd8-28f0-4636-be1e-aeed60c98095 resume=UUID=2d877d5d-4ca1-4d46-a3d6-b6ee94cbbd78 rw rootflags=subvol=@ loglevel=3 quiet initrd=\initramfs-linux-lts.img'

要獲取啟動項列表、設置引導順序或刪除啟動項，請參見 efibootmgr。

提示：

- kesboot-gitAUR 包可以簡易且自動地實現此過程，同時他還含有 pacman hook 可在執行軟體包操作時添加和移除 EFI 變量。
- https://github.com/de-arl/auto-UEFI-entry 是一個生成上述指令的 bash 輔助工具。
- 將創建引導項的命令保存到 Shell 腳本將非常方便，能讓後續修改（例如更改內核參數時）。在這個過程中，可以考慮將刪除舊啟動項自動化, 因為 efibootmgr 當前 不支持編輯現有引導項.
- 題為 The Linux kernel with built-in boot loader 的論壇帖子或許具有參考價值

#### bcfg

一些 UEFI的實現方式使得使用 efibootmgr 來成功修改 NVRAM 變得非常困難。如果 efibootmgr 無法成功創建相應的條目，那麼可以使用 UEFI Shell v2 中的bcfg命令來進行操作。 (即從Arch Linux的Live ISO鏡像中執行該命令)。

首先，需要找到您的 ESP分區 所使用的設備編號：

     Shell> map

在示例中`1`被用作設備編號。要列出 ESP分區 的內容，請執行以下操作：

     Shell> ls FS1:

要查看當前的啟動項，請執行以下操作：

    Shell> bcfg boot dump

要為你的內核添加一條記錄，請使用以下格式：

    Shell> bcfg boot add N FS1:\vmlinuz-linux "Arch Linux"

`N`是會在啟動菜單中添加該條目所在的位置。`0` 是第一個菜單項。已經存在的菜單項會被移動進去，而不會被刪除。

你可以直接添加內核選項：

     Shell> bcfg boot -opt N "root=/dev/sda2 initrd=\initramfs-linux.img"

或者通過在你的 ESP 分區上創建一個文件來實現：

    Shell> edit FS1:\options.txt

在文件中添加引導行。例如：

    root=/dev/sda2 rw initrd=\initramfs-linux.img

注意：在文件的每一行的開頭需要添加額外的空格。在行首有一個字節順序標記，它會覆蓋該位置上的任何字符，這會導致在啟動時出現錯誤。

按 `F2` 保存,然後按 `F3` 退出程序。

在之前的條目中添加這些選項：

    Shell> bcfg boot -opt N FS1:\options.txt

對於其他所有條目，都重複進行這個步驟。

若要刪除之前添加的項目，請執行以下操作：

    Shell> bcfg boot rm N

### 使用 UEFI Shell

如果你不想創建永久的啟動項，那麼可以從 UEFI Shell中啟動內核，因為 UEFI Shell本身就是一個普通的 UEFI 應用程式。

    > FS0:
    > \vmlinuz-linux root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw initrd=\initramfs-linux.img

在這種情況下，內核參數將會被作為普通參數傳遞給 EFI 啟動腳本內核。

為了避免每次都需要記住所有的內核參數，你可以將可執行命令保存到一個 shell 腳本中，例如保存在 EFI 系統分區中的`archlinux.nsh`腳本，然後運行它：

    > FS0:
    > archlinux

#### 使用 startup.nsh 腳本

一些 UEFI 實現在冷啟動過程中不會保留 EFI 變量（例如，在 6.1版本之前的 VirtualBox ），因此通過 UEFI 設置的所有選項都會在關機時丟失。

UEFI Shell 規範 2.0規定，ESP 分區根目錄下的 `startup.nsh` 腳本始終會被執行並且可以包含任意指令。在這些指令中，你可以設置用於引導加載的語句。請確保將 ESP 分區掛載在 `/boot`並創建一個包含內核引導語句的 `startup.nsh` 腳本，例如：

    vmlinuz-linux rw root=/dev/sdX [rootfs=myfs] [rootflags=myrootflags] \
     [kernel.flag=foo] [mymodule.flag=bar] \
     initrd=\initramfs-linux.img

這種方法適用於幾乎所有你在實際硬體中可能會遇到的 UEFI 版本。你可以將其作為最後的解決方案來使用。該腳本應該只包含一個長行代碼。括號中的內容是可選的，僅作為指導之用。類似 Shell 風格的換行符只是為了便於閱讀而設計的。FAT 文件系統使用反斜槓作為路徑分隔符，在這種情況下，反斜槓表示 initramfs 位於 ESP 分區的根目錄下。（對於其他設備，sd"X"代表的ESP分區設備或者編號都可能不同）

## 一些小提示和技巧

### 帶有啟動內存檔（ramdisk）的後備啟動項

如果沒有引導管理器，那麼內核命令行在啟動時是無法被修改的。為了至少提供一些後備方案，例如可以使用`initramfs-linux-fallback.img` 或者在不使用英特爾微碼的情況下啟動系統，只需使用 efibootmgr 創建一個額外的引導條目即可。這個引導條目的標籤可以命名例如「Arch Linux Fallback」，並設置所需的備用選項。

### 在ESP分區上的Archiso

可以將 Arch Linux 的 ISO 鏡像放置在 ESP 分區中，從而擁有一個恢復系統。截至 2026 年 7 月 1 日的版本發布時，鏡像的文件大小為 1.5G。

首先，下載 archlinux-YYYY.MM.DD-x86_64.iso。

接下來，在你的 ESP 目錄下創建一個用於 archiso 的目錄：

    # mkdir -p esp/EFI/archiso

提取 arch 目錄中的所有內容：

    # bsdtar -v -x --no-same-permissions --strip-components 1 -f archlinux-YYYY.MM.DD-x86_64.iso -C esp/EFI/archiso arch

在最後一步中，使用 `efibootmgr` 創建一個啟動項。請替換以下內容：

diskpath 是設備的路徑（例如：/dev/sda)）

`diskpart` 是分區編號

    # efibootmgr --create --disk diskpath \
    --part diskpart \
    --label "Arch (rescue system)" \
    --loader '\EFI\archiso\boot\x86_64\vmlinuz-linux' \
    --unicode 'archisobasedir=/EFI/archiso archisosearchfilename=/EFI/archiso/boot/x86_64/vmlinuz-linux initrd=\EFI\archiso\boot\x86_64\initramfs-linux.img'

現在你可以從 UEFI 啟動加載程序中選擇恢復系統了。

## 故障排除

一些主板，比如 Haswell 架構時代的華碩（ASUS）主板 (如在法國論壇上遇到的那樣), 在系統啟動時不會注意到引導條目發生的變化，除非是以另一個已存在的引導條目來啟動系統。

## 參見

- Linux 內核文檔——EFI 啟動腳本（The EFI Boot Stub）
- Linux 內核提交代碼 - x86 架構，efi：支持 EFI 啟動腳本功能（EFI Boot Stub支持）
- Rod·Smith的做法——使用內核的 EFI 加載器

分類：​

- 啟動加載程序
- 簡體中文

EFISTUB
新增話題