EFI 启动存根
一个 EFI 启动存根 (又名 EFI 存根) 是一个内核,它是一个 EFI 可执行文件,即可以直接从 UEFI 启动。
从历史上看,本文和 Debian Wiki 使用术语时将它们作为一个词 (EFISTUB 或 EFIStub)。
默认情况下,Arch Linux 内核是 EFI 启动存根。如果编译内核,通过设置 CONFIG_EFI_STUB=y
来激活它。有关更多信息,请参阅 EFI 启动存根。
在继续之前,你需要一个 EFI 系统分区 并选择如何挂载它。
启动 EFI 启动存根
esp/EFI/arch/initramfs-linux.img
中,则相应的 UEFI 格式化行应为 initrd=\EFI\arch\initramfs-linux.img
。在以下示例中,我们将假设所有内容都在 esp/
下。直接使用 UEFI
UEFI 旨在消除对 GRUB 等中间引导加载程序的需求。如果你的主板具有良好的 UEFI 实现,则可以将内核参数嵌入到 UEFI 启动项中,并让主板直接启动 Arch。你可以使用 efibootmgr 或 UEFI Shell v2 来修改主板的启动项。
efibootmgr
要使用 efibootmgr 创建将加载内核的启动项
# efibootmgr --create --disk /dev/sdX --part Y --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=block_device_identifier rw initrd=\initramfs-linux.img'
其中 /dev/sdX
和 Y
是 ESP 所在驱动器和分区号,root=
参数是你的 Linux 根分区。
如果省略,则 /dev/sda
上的第一个分区将用作 ESP。
请注意,引号中的 -u
/--unicode
参数只是内核参数的列表,因此你可能需要添加其他参数(例如用于挂起到磁盘)。
带有 LTS Linux 内核、NVME 存储、具有特定子卷的 BTRFS 文件系统以及在交换分区上休眠的示例
# 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 目前不支持编辑现有条目。
- 论坛帖子 带有内置引导加载程序的 Linux 内核? 也可能引起你的兴趣。
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 应用程序
> FS0: > \vmlinuz-linux root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw initrd=\initramfs-linux.img
在这种情况下,内核参数作为普通参数传递给 EFI 启动存根内核。
为了避免每次都记住所有内核参数,你可以将可执行命令保存到 EFI 系统分区上的 shell 脚本中,例如 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 分区的根目录中。
技巧与诀窍
带有备用 ramdisk 的启动项
在没有启动管理器的情况下,内核命令行在启动时不可更改。为了至少有一些备用可能性,例如使用 initramfs-linux-fallback.img
和/或在没有 Intel 微代码的情况下启动,只需使用 efibootmgr 创建另一个启动项,例如标记为 “Arch Linux fallback” 和所需的备用选项。
故障排除
在某些 Dell 系统上无法启动的存根
几代 Dell 固件错误地将参数传递给引导加载程序,从而导致 EFISTUB 解析空命令行,这通常意味着系统无法启动(请参阅完整的 linux-efi 线程)。
自 Linux 5.10 以来,已找到一种解决方法来纠正此行为(请参阅此 commit )。对于 Linux < 5.10,你可以使用 efi-packer,如 arch-efiboot,或不同的引导加载程序。
启动项的更改未应用
某些主板,例如 Haswell 时代的 ASUS 主板(在法国论坛上遇到的情况),除非系统使用另一个预先存在的启动项启动,否则不会注意到对启动项的更改。