跳转到内容

EFISTUB

来自 Arch Linux 中文维基

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分区挂载到/bootpacman 更新的内核就能直接使 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 有新的修复了问题的版本,可以考虑使用主板厂商推荐的工具刷入。
  • 此项可能已过时:一些固件 (尤其是 LenovoDell 笔记本电脑) 不会将 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

提示:

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)主板 (如在法国论坛上遇到的那样), 在系统启动时不会注意到引导条目发生的变化,除非是以另一个已存在的引导条目来启动系统。


参见