GRUB/技巧与窍门
替代安装方法
安装到外部 USB 驱动器
BIOS
假设你的 USB 驱动器的第一个分区是 FAT32 格式,且该分区为 /dev/sdy1
# mount --mkdir /dev/sdy1 /mnt/usb # grub-install --target=i386-pc --debug --boot-directory=/mnt/usb/boot /dev/sdy # grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg
建议备份 grub.cfg 的配置文件
# mkdir -p /mnt/usb/etc/default # cp /etc/default/grub /mnt/usb/etc/default # cp -a /etc/grub.d /mnt/usb/etc
# sync; umount /mnt/usb
EFI
对于可移动安装,你必须使用 --removable 并同时指定 --boot-directory 和 --efi-directory。[1]
# grub-install --target=x86_64-efi --bootloader-id=GRUB --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable
安装到分区或无分区磁盘
要将 grub 设置到分区引导扇区、无分区磁盘(也称为 superfloppy)或软盘,请运行(例如使用 /dev/sdaX 作为 /boot 分区):
# chattr -i /boot/grub/i386-pc/core.img # grub-install --target=i386-pc --debug --force /dev/sdaX # chattr +i /boot/grub/i386-pc/core.img
/dev/sdaX仅作示例使用。--target=i386-pc指示grub-install仅为 BIOS 系统安装。建议始终使用此选项以消除 grub-install 中的歧义。
你需要使用 --force 选项以允许使用块列表(blocklists),并且不应使用 --grub-setup=/bin/true(这类似于简单生成 core.img)。
grub-install 将会给出警告,这应该能让你了解此方法可能会出现什么问题
/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.
However, blocklists are UNRELIABLE and their use is discouraged.
若没有 --force,你可能会得到以下错误,且 grub-setup 将不会在分区引导扇区中设置其引导代码
/sbin/grub-setup: error: will not proceed with blocklists
加上 --force 后,你应该会得到
Installation finished. No error reported.
grub-setup 默认不允许这样做的原因是,对于分区或无分区磁盘,GRUB 依赖于分区引导扇区中的嵌入式块列表来定位 /boot/grub/i386-pc/core.img 文件和前缀目录 /boot/grub。每当分区中的文件系统被更改(文件被复制、删除等)时,core.img 的扇区位置可能会发生变化。更多信息,请参见 https://bugzilla.redhat.com/show_bug.cgi?id=728742 和 https://bugzilla.redhat.com/show_bug.cgi?id=730915。
解决此问题的方法是在 /boot/grub/i386-pc/core.img 上设置不可变(immutable)标志(使用上述提到的 chattr 命令),这样磁盘中 core.img 文件的扇区位置就不会被更改。仅当 GRUB 安装到分区引导扇区或无分区磁盘时,才需要对 /boot/grub/i386-pc/core.img 设置不可变标志;如果安装到 MBR 或只是简单生成不嵌入引导扇区的 core.img(如上所述),则不需要。
不幸的是,即使报告没有错误,创建的 grub.cfg 文件也不会包含正确的 UUID 以进行引导。请参见 https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604。为了修复这个问题,使用以下命令
# mount /dev/sdxY /mnt #Your root partition. # mount /dev/sdxZ /mnt/boot #Your boot partition (if you have one). # arch-chroot /mnt
现在,安装 linux,然后
# grub-mkconfig -o /boot/grub/grub.cfg
仅生成 core.img
要在 不 将任何 GRUB 引导扇区代码嵌入 MBR、MBR 后区域或分区引导扇区的情况下填充 /boot/grub 目录并生成 /boot/grub/i386-pc/core.img 文件,请在 grub-install 中添加 --grub-setup=/bin/true
# grub-install --target=i386-pc --grub-setup=/bin/true --debug /dev/sda
/dev/sda仅作示例使用。--target=i386-pc指示grub-install仅为 BIOS 系统安装。建议始终使用此选项以消除 grub-install 中的歧义。
然后,你可以从 GRUB Legacy 或 syslinux 将 GRUB 的 core.img 作为 Linux 内核或多重引导内核(multiboot kernel)进行链式加载(请参阅 Syslinux#Chainloading)。
GUI 配置工具
- grub-customizer — 用于 GRUB 或 BURG 的 GTK 定制工具
嵌入式(Drop-in)配置
自 GRUB 2.12-1 起,除了主配置文件 /etc/default/grub 外,grub-mkconfig 还会读取 /etc/default/grub.d/*.cfg 中的嵌入式配置片段(如果有)。自然地,它们的优先级高于主 /etc/default/grub 配置文件,并且会覆盖其设置,它们按字典序读取,以此类推。这是直接编辑 /etc/default/grub 的一种替代方案,所有关于编辑 /etc/default/grub 的提及都可以改为针对此文件夹下的嵌入式文件。
- 安装 GRUB 后,文件夹
/etc/default/grub.d不会默认存在,必须手动创建。 - 不要将
/etc/default/grub.d与/etc/grub.d混淆。
视觉配置
在 GRUB 中,默认可以更改菜单的外观。请确保在 /etc/default/grub 中初始化 GRUB 图形终端 gfxterm
GRUB_TERMINAL_OUTPUT="gfxterm"
设置帧缓冲区分辨率
GRUB 可以分别为 GRUB 本身(GFXMODE)和内核(GFXPAYLOAD)设置帧缓冲区。旧的 vga= 方法已被弃用。首选方法是编辑 /etc/default/grub 以设置宽度(像素)x 高度(像素)x 色彩深度
GRUB_GFXMODE=1024x768x32 GRUB_GFXPAYLOAD_LINUX=keep
可以指定多个分辨率,包括默认的 auto,因此建议将该行编辑为类似于 GRUB_GFXMODE=desired_resolution,fallback_such_as_1024x768,auto 的形式。有关更多信息,请参考 GRUB gfxmode 文档。gfxpayload 属性将确保内核保持该分辨率。
- 只能使用显卡通过 VESA BIOS 扩展 支持的模式。要查看支持的模式列表,请安装 hwinfo 并以 root 身份运行
hwinfo --framebuffer。或者,进入 GRUB 命令行并运行命令videoinfo。 - NVIDIA 专有驱动程序的早期版本(在 GeForce GTX 970 上测试,驱动:nvidia 370)接受
GRUB_GFXMODE的格式为widthxheight-depth(例如1920x1200-24,而非1920x1200x24)。这似乎不适用于较新的显卡和驱动程序。使用较新驱动程序的 Pascal 显卡(在 GeForce GTX 1060 和 nvidia 381.22 上测试)无法使用上述推荐格式,强行使用会导致严重问题,包括但不限于系统崩溃和死机。当前的驱动程序和显卡最好配置为标准的widthxheightxdepth格式。 - 进行更改后,请务必运行
grub-mkconfig -o /boot/grub/grub.cfg。
如果此方法对你不奏效,弃用的 vga= 方法仍然有效。只需将其添加到 /etc/default/grub 中 "GRUB_CMDLINE_LINUX_DEFAULT=" 行的旁边,例如:"GRUB_CMDLINE_LINUX_DEFAULT="quiet splash vga=792" 将为你提供 1024x768 的分辨率。
背景图片和位图字体
GRUB 支持 pf2 格式的背景图片和位图字体。grub 软件包中包含了 GNU Unifont 字体,文件名为 unicode.pf2,或者仅包含 ASCII 字符的版本,文件名为 ascii.pf2。运行 pacman -Ql grub | grep pf2 以获取文件路径。
支持的图像格式包括 JPEG、PNG 和 TGA(前提是加载了正确的模块)。支持的最大分辨率取决于你的硬件。
请确保已设置适当的 帧缓冲区分辨率。
编辑 /etc/default/grub 如下
GRUB_BACKGROUND="/boot/grub/myimage" #GRUB_THEME="/path/to/gfxtheme" GRUB_FONT="/path/to/font.pf2"
/boot/grub/myimage 会自动变成 grub.cfg 中的 /grub/myimage。重新生成 grub.cfg 以应用更改。如果成功添加了启动画面图片,用户在执行命令时会在终端中看到 "Found background image..."。如果没有看到这句话,说明图片信息可能没有被合并到 grub.cfg 文件中。
如果未显示图片,请检查
/etc/default/grub中的路径和文件名是否正确- 图片大小和格式是否合适(tga, png, 8-bit jpg)
- 图片是否以 RGB 模式保存,且未被索引(indexed)
/etc/default/grub中是否启用了控制台模式- 必须执行
grub-mkconfig命令,将背景图片信息写入/boot/grub/grub.cfg文件 grub-mkconfig脚本不会引用grub.cfg中的文件名,所以请确保文件名不包含空格
主题
以下是配置 GRUB 软件包中包含的 Starfield 主题的示例。
编辑 /etc/default/grub
GRUB_THEME="/usr/share/grub/themes/starfield/theme.txt"
重新生成 grub.cfg 以应用更改。如果主题配置成功,你会在终端中看到 Found theme: /usr/share/grub/themes/starfield/theme.txt。
使用主题时,通常不会显示启动画面图片。
如果主题路径可能无法访问(例如由于加密或分区不可用),请将其复制到 /boot/grub/themes/ 或使用 grub-install --themes=theme_names ... 安装。
菜单颜色
你可以在 GRUB 中设置菜单颜色。GRUB 可用的颜色可以在 GRUB 手册 中找到。这是一个示例
编辑 /etc/default/grub
GRUB_COLOR_NORMAL="light-blue/black" GRUB_COLOR_HIGHLIGHT="light-cyan/blue"
隐藏菜单
GRUB 的独特功能之一是隐藏/跳过菜单,并在需要时通过按住 Esc 键显示它。你还可以调整是否要显示超时计数器。
根据需要编辑 /etc/default/grub。以下是启用此功能需要添加的行,超时时间已设置为五秒并对用户显示
GRUB_TIMEOUT=5 GRUB_TIMEOUT_STYLE='countdown'
GRUB_TIMEOUT 是显示菜单前的等待秒数。
禁用帧缓冲区
使用 NVIDIA 专有驱动的用户可能希望禁用 GRUB 的帧缓冲区,因为它可能会导致二进制驱动出现问题。
要禁用帧缓冲区,请编辑 /etc/default/grub 并取消注释以下行
GRUB_TERMINAL_OUTPUT=console
如果你想在 GRUB 中保留帧缓冲区,另一个选择是在启动内核之前恢复到文本模式。为此,请修改 /etc/default/grub 中的变量
GRUB_GFXPAYLOAD_LINUX=text
语言
grub-mkconfig 使用 gettext 进行翻译。使用的语言由 Locale#Variables 决定。
LANGUAGE 变量中将区域设置放在 en_US 或 en 之后,grub-mkconfig 可能会选择该次要区域设置。这是因为 grub 使用 C 作为英语的默认区域设置,但并未明确将其命名或别名为 en_US 或 en。永久解决方案请参见 Locale#LANGUAGE: fallback locales。你可以在运行 grub-mkconfig 以特定语言生成配置时临时覆盖区域设置,例如英语(C 区域设置)
# LC_ALL=C grub-mkconfig -o /boot/grub/grub.cfg
通过 GRUB 直接引导 ISO9660 镜像文件
GRUB 支持通过回环设备(loopback devices)直接从 ISO 镜像引导,示例请参见 Multiboot USB drive#Using GRUB and loopback devices。
GRUB 菜单密码保护
/boot 位于未加密的分区上,他们只需修改 GRUB 配置文件即可轻松绕过此设置。参见 GRUB#Encrypted /boot 和 Security#Data-at-rest encryption。如果你想保护 GRUB,使任何人无法更改引导参数或使用命令行,你可以向 GRUB 的配置文件添加用户名和密码。为此,请运行命令 grub-mkpasswd-pbkdf2,然后输入并确认密码
$ grub-mkpasswd-pbkdf2
[...] PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.C8ABD3E93C4DFC83138B0C7A3D719BC650E6234310DA069E6FDB0DD4156313DA3D0D9BFFC2846C21D5A2DDA515114CF6378F8A064C94198D0618E70D23717E82.509BFA8A4217EAD0B33C87432524C0B6B64B34FBAD22D3E6E6874D9B101996C5F98AB1746FE7C7199147ECF4ABD8661C222EEEDB7D14A843261FFF2C07B1269A
然后,通过运行 chmod o-r /etc/grub.d/40_custom 来调整 /etc/grub.d/40_custom 的权限,使其仅 root 可读。接着按以下内容修改该文件
/etc/grub.d/40_custom
set superusers="username" password_pbkdf2 username password-hash
其中 password-hash 是由 grub-mkpasswd_pbkdf2 生成的以 grub.pbkdf2 开头的字符串。
使用 grub-mkconfig 重新生成配置文件。现在,访问 GRUB 命令行、引导参数以及 引导条目都需要指定的用户名和密码。后者可以通过遵循 #Password protection of GRUB edit and console options only 来规避。
如 GRUB 手册 的“Security”部分所述,可以通过配置更多用户来放宽此限制并进行进一步自定义。
仅对 GRUB 编辑和控制台选项进行密码保护
向菜单项添加 --unrestricted 将允许任何用户引导操作系统,同时防止用户编辑该条目并防止访问 grub 命令行控制台。只有超级用户或使用 --user 开关指定的用户才能编辑菜单项。
/boot/grub/grub.cfg
menuentry 'Arch Linux' --unrestricted --class arch --class gnu-linux --class os ...
为了使 Linux 条目成为 --unrestricted,可以修改 /etc/grub.d/10_linux 开头的 CLASS 变量。
/etc/grub.d/10_linux
CLASS="--class gnu-linux --class gnu --class os --unrestricted"
除非按住 Shift 键否则隐藏 GRUB
为了实现尽可能快的引导,GRUB 不必等待超时,可以在 GRUB 启动期间隐藏菜单,除非按住 Shift 键或按下 Esc 或 F4 键。
为此,你应该向 /etc/default/grub 添加以下行
GRUB_TIMEOUT=0 GRUB_TIMEOUT_STYLE=hidden
然后重新生成 grub 配置
# grub-mkconfig -o /boot/grub/grub.cfg
结合使用 UUID 和基础脚本
如果你喜欢使用 UUID 来避免不可靠的 BIOS 映射,或者对 GRUB 的语法感到困惑,这里有一个示例引导菜单项,它使用 UUID 和一个小脚本将 GRUB 指向系统的正确磁盘分区。你只需要用系统的正确 UUID 替换示例中的 UUID。该示例适用于具有引导分区和根分区的系统。如果你有其他分区,显然需要修改 GRUB 配置
menuentry "Arch Linux 64" {
# Set the UUIDs for your boot and root partition respectively
set the_boot_uuid=ece0448f-bb08-486d-9864-ac3271bd8d07
set the_root_uuid=c55da16f-e2af-4603-9e0b-03f5f565ec4a
# (Note: This may be the same as your boot partition)
# Get the boot/root devices and set them in the root and grub_boot variables
search --fs-uuid $the_root_uuid --set=root
search --fs-uuid $the_boot_uuid --set=grub_boot
# Check to see if boot and root are equal.
# If they are, then append /boot to $grub_boot (Since $grub_boot is actually the root partition)
if [ $the_boot_uuid == $the_root_uuid ] ; then
set grub_boot=($grub_boot)/boot
else
set grub_boot=($grub_boot)
fi
# $grub_boot now points to the correct location, so the following will properly find the kernel and initramfs
linux $grub_boot/vmlinuz-linux root=/dev/disk/by-uuid/$the_root_uuid ro
initrd $grub_boot/initramfs-linux.img
}
多重引导项
禁用子菜单
如果你安装了多个内核,例如 linux 和 linux-lts,默认情况下 grub-mkconfig 会将它们归类在一个子菜单中。如果你不喜欢这种行为,可以通过将以下行添加到 /etc/default/grub 来恢复为一个单一菜单
GRUB_DISABLE_SUBMENU=y
调用上一个引导项
GRUB 可以记住你上次引导的条目,并将其作为下次引导的默认条目。这在你拥有多个内核(例如当前的 Arch 内核和作为备份选项的 LTS 内核)或多个操作系统时非常有用。为此,编辑 /etc/default/grub 并更改 GRUB_DEFAULT 的值
GRUB_DEFAULT=saved
这确保 GRUB 将默认为保存的条目。要启用保存选定条目,请向 /etc/default/grub 添加以下行
GRUB_SAVEDEFAULT=true
如果 /boot 不是 btrfs 分区,此功能才能工作,因为 grub 无法写入 btrfs。但它会产生一条误导性错误消息:“sparse file not allowed. Press any key to continue.”。
/etc/grub.d/40_custom 或 /boot/grub/custom.cfg 中的 Windows)需要添加 savedefault。更改默认引导项
要更改默认选择的条目,请编辑 /etc/default/grub 并更改 GRUB_DEFAULT 的值
使用菜单标题
GRUB_DEFAULT='Advanced options for Arch Linux>Arch Linux, with Linux linux'
GRUB_DEFAULT 行上方添加 LANG=C,或者根据你所在区域设置中的正确标题设置 GRUB_DEFAULT 是个好主意。使用数字
GRUB_DEFAULT="1>2"
Grub 在 生成的菜单(即 /boot/grub/grub.cfg)中识别条目,从零开始计数。这意味着 0 为第一个条目(默认值),1 为第二个,依此类推。主菜单和子菜单条目由 > 分隔,两者都通过数字、标题或 ID 进行识别。
上面的示例引导主菜单中“Advanced options for Arch Linux”下的第三个条目。
使用 ID(如果生成 grub.cfg,请查看 --id 或 $menuentry_id_option 后的值)
GRUB_DEFAULT="gnulinux-advanced-39c666d6-c7fc-4fa6-8287-9540056f5a02>gnulinux-linux-zen-advanced-39c666d6-c7fc-4fa6-8287-9540056f5a02"
所有三种标识符方法的文档:https://gnu.net.cn/software/grub/manual/grub/html_node/default.html
仅引导非默认项一次
grub-reboot 命令对于仅引导非默认条目一次非常有帮助。GRUB 会加载第一个命令行参数传递的条目,当系统下次重启时,GRUB 会返回加载默认条目,供未来的所有引导使用。无需更改配置文件或在 GRUB 菜单中选择条目。
/etc/default/grub 中设置 GRUB_DEFAULT=saved(然后重新生成 grub.cfg),或者在手动创建 grub.cfg 的情况下,包含 set default="${saved_entry}" 行。播放启动音
你可以通过修改 GRUB_INIT_TUNE 变量,在引导期间(菜单出现之前)通过 PC 扬声器播放音调
GRUB_INIT_TUNE="tempo [note_pitch note_duration] [second_note_pitch second_note_duration] ..."
你可以通过创建链接的 /etc/grub.d/91_tune_demo 并重新运行 grub-mkconfig,添加 一个菜单条目 来播放这些常见的 GRUB_INIT_TUNE 样本中的每一个。
有关此方面的信息,你可以查看 info grub -n play,同时还存在一些 集合。
为早期引导手动配置核心镜像
如果你需要特殊的键盘布局或 GRUB 无法自动配置的其他复杂步骤以使 /boot 对 GRUB 环境可用,你可以自己生成核心镜像。在 UEFI 系统上,核心镜像是由固件在启动时加载的 grubx64.efi 文件。构建自己的核心镜像将允许你嵌入早期引导所需的任何模块,以及引导 GRUB 的配置脚本。
首先,以需要嵌入早期引导的 dvorak 键盘布局为例,以便在 UEFI 系统上输入加密 /boot 的密码
从生成的 /boot/grub/grub.cfg 文件中确定挂载加密 /boot 所需的模块。例如,在你的 menuentry 下,你应该看到类似于以下的内容
insmod diskfilter cryptodisk luks gcry_rijndael gcry_rijndael gcry_sha256 insmod ext2 cryptomount -u 1234abcdef1234abcdef1234abcdef set root='cryptouuid/1234abcdef1234abcdef1234abcdef'
记下所有这些模块:它们需要包含在核心镜像中。现在,创建一个包含你的键盘布局的 tarball。这将作为 memdisk 捆绑在核心镜像中
# grub-kbdcomp -o dvorak.gkb dvorak # tar cf memdisk.tar dvorak.gkb
现在创建一个要在 GRUB 核心镜像中使用的配置文件。其格式与常规 grub 配置相同,但只需包含几行即可在 /boot 分区上查找并加载主配置文件
early-grub.cfg
set root=(memdisk) set prefix=($root)/ terminal_input at_keyboard keymap /dvorak.gkb cryptomount -u 1234abcdef1234abcdef1234abcdef set root='cryptouuid/1234abcdef1234abcdef1234abcdef' set prefix=($root)/grub configfile grub.cfg
最后,生成核心镜像,列出在生成的 grub.cfg 中确定需要的所有模块,以及 early-grub.cfg 脚本中使用的任何模块。上面的示例需要 memdisk、tar、at_keyboard、keylayouts 和 configfile。
# grub-mkimage -c early-grub.cfg -o grubx64.efi -O x86_64-efi -m memdisk.tar diskfilter cryptodisk luks gcry_rijndael gcry_sha256 ext2 memdisk tar at_keyboard keylayouts configfile
生成的 EFI 核心镜像现在可以像 grub-install 自动生成的镜像一样使用:将其放置在你的 EFI 系统分区 中并使用 efibootmgr 启用它,或者根据你的系统固件进行配置。
UEFI 深入阅读
以下是有关通过 UEFI 安装 Arch 的其他相关信息。
替代安装方法
通常,无论 EFI 系统分区挂载在哪里,GRUB 都会将所有文件(包括配置文件)保存在 /boot 中。
如果你想将这些文件保留在 EFI 系统分区本身内,请在 grub-install 命令中添加 --boot-directory=esp
# grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=grub --boot-directory=esp --debug
这会将所有 GRUB 文件放在 esp/grub 中,而不是 /boot/grub 中。使用此方法时,请确保让 grub-mkconfig 将配置文件放在同一个地方
# grub-mkconfig -o esp/grub/grub.cfg
配置在其他方面是相同的。
UEFI 固件解决方法
参见 GRUB#Default/fallback boot path。
GRUB 独立模式
本节假设你正在为 x86_64 系统 (x86_64-efi) 创建独立 GRUB。对于 32 位 (IA32) EFI 系统,请在适当位置将 x86_64-efi 替换为 i386-efi。
可以创建一个 grubx64_standalone.efi 应用程序,该应用程序将所有模块嵌入到 UEFI 应用程序内的 tar 归档文件中,从而无需拥有填充有所有 GRUB UEFI 模块和其他相关文件的独立目录。这是使用 grub-mkstandalone 命令(包含在 grub 中)完成的,如下所示
# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --locales="en@quot" --themes="" -o "esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v
然后将 GRUB 配置文件复制到 esp/EFI/grub/grub.cfg,并使用 efibootmgr 为 esp/EFI/grub/grubx64_standalone.efi 创建 UEFI 引导管理器条目。
--modules="part_gpt part_msdos"(带引号)选项对于 ${cmdpath} 功能正常工作是必要的。- 你可能会发现
grub.cfg文件由于${cmdpath}缺少斜杠(即(hd1,msdos2)EFI/Boot而不是(hd1,msdos2)/EFI/Boot)而无法加载,因此你被引导至 GRUB shell。如果发生这种情况,请确定${cmdpath}设置为什么(echo ${cmdpath}),然后手动加载配置文件(例如configfile (hd1,msdos2)/EFI/Boot/grub.cfg)。 - 如果使用了带有 shim 的安全引导(Secure Boot),记得使用
--sbat /usr/share/grub/sbat.csv添加 SBAT 部分。
技术信息
GRUB EFI 文件始终期望其配置文件位于 ${prefix}/grub.cfg。然而在独立 GRUB EFI 文件中,${prefix} 位于嵌入在独立 GRUB EFI 文件本身的 tar 归档中(在 GRUB 环境中,它表示为 "(memdisk)",不带引号)。该 tar 归档包含所有通常在普通 GRUB EFI 安装时存储在 /boot/grub 中的文件。
由于 /boot/grub 内容嵌入在独立镜像本身中,它不依赖于实际的(外部)/boot/grub。因此,对于独立 GRUB EFI 文件,${prefix}==(memdisk)/boot/grub,独立 GRUB EFI 文件期望配置文件位于 ${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg。
因此,为了确保独立 GRUB EFI 文件读取与 EFI 文件位于同一目录下的外部 grub.cfg(在 GRUB 环境中,这表示为 ${cmdpath} ),我们创建一个简单的 /tmp/grub.cfg,指导 GRUB 使用 ${cmdpath}/grub.cfg 作为其配置((memdisk)/boot/grub/grub.cfg 中的 configfile ${cmdpath}/grub.cfg 命令)。然后我们使用 "boot/grub/grub.cfg=/tmp/grub.cfg" 选项,指示 grub-mkstandalone 将此 /tmp/grub.cfg 文件复制到 ${prefix}/grub.cfg(实际上是 (memdisk)/boot/grub/grub.cfg)。
这样,独立 GRUB EFI 文件和实际的 grub.cfg 可以存储在 EFI 系统分区内的任何目录中(只要它们在同一目录下),从而使其具有可移植性。
UEFI 和 BIOS 并存安装
如果你的 Arch 安装需要在 UEFI 和 BIOS 系统上均可引导,请同时使用两种方法安装 GRUB。将磁盘分区为 GPT,创建 EFI 系统分区 和 BIOS 引导分区,将 ESP 挂载在 /efi 并运行这两种方式的 GRUB 安装命令。
# grub-install --target=i386-pc --recheck /dev/sdx # grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB --recheck
在 BIOS 系统中,EFI 变量不存在,因此无法设置 UEFI NVRAM 引导条目,第二个命令会报告错误。通过使用 --no-nvram 和 --removable 选项,系统也将有很大机会在 UEFI 模式下可引导
# grub-install --target=i386-pc --recheck /dev/sdx # grub-install --target=x86_64-efi --efi-directory=/efi --recheck --removable --no-nvram
对于某些 BIOS 实现,可能需要设置 PMBR 的引导标志,例如使用 parted
(parted) disk_set pmbr_boot on
加速 GRUB 中的 LUKS 解密
在引导时,GRUB 在某些情况下可能需要很长时间来验证密码。这可能是由于 密钥派生函数 的高成本参数造成的,你可以通过以下方式检查
# cryptsetup luksDump /dev/sda3
问题在于,给定密钥槽的成本参数是在密钥添加时生成的,以确保在抵御暴力破解攻击的强度和允许计算机快速派生密钥之间取得平衡。但是,当 GRUB 启动时,它可能没有相同的计算资源,因此速度会慢得多。
如果你的密码本身提供了足够的熵来抵御常见的攻击,你可以降低参数。例如,要降低 PBKDF2 的迭代次数,请使用
# cryptsetup luksChangeKey --pbkdf-force-iterations 1000 /dev/sda3
根据 RFC 2898,建议至少 1000 次迭代,但如果可以,你应该追求更高的值(攻击者的成本以及密钥派生时间是线性缩放的)。
--key-slot 选项显式指定密钥槽。使用 TPM 解密 LUKS 保护的磁盘
在 GRUB 的最新版本中(自 2.14-rc1 起),可以使用 TPM 解锁加密磁盘。如果 /boot 分区已加密,这很有用,因为它避免了在引导时输入密码,并使无人值守引导成为可能。
第一步包括创建随机 LUKS 密钥并将其添加到存储中。这是通过以下方式实现的(调整 UUID 0228eb43-a7cc-4737-a0d3-cf784154feea 以匹配系统上的加密磁盘)
# dd if=/dev/urandom of=luks-key bs=1 count=32 # cryptsetup luksAddKey /dev/disk/by-uuid/0228eb43-a7cc-4737-a0d3-cf784154feea luks-key --pbkdf=pbkdf2 --hash=sha512
该密钥可以用 TPM 密封并存储在未加密的 esp 分区上,如下所示
# grub-protect --action=add --protector=tpm2 --tpm2-pcrs=7 --tpm2key --tpm2-keyfile=luks-key --tpm2-outfile=esp/EFI/GRUB/sealed.tpm
请注意,tpm2-pcrs 参数可以根据你的需要进行调整。更多信息请参见 Trusted_Platform_Module#Accessing_PCR_registers。
在 /boot/grub/early-grub.cfg 中创建一个早期 grub 引导脚本,内容如下
clear echo 'Starting grub...' tpm2_key_protector_init --tpm2key=(hd0,gpt1)/efi/grub/sealed.tpm cryptomount -u 0228eb43-a7cc-4737-a0d3-cf784154feea -P tpm2 set root='cryptouuid/0228eb43-a7cc-4737-a0d3-cf784154feea' set prefix=($root)/@/boot/grub configfile grub.cfg
在上述脚本中,你需要调整磁盘的 UUID 和 /boot/grub 目录的前缀。在此示例中,/boot/grub 目录位于 Btrfs 文件系统的 @ 子卷中。
重新生成 GRUB efi 二进制文件,并确保包含你所需的所有模块。
# grub-mkimage -p /boot/grub --disable-shim-lock -c /boot/grub/early-grub.cfg -o esp/EFI/GRUB/grubx64.efi -O x86_64-efi part_gpt cryptodisk luks2 gcry_rijndael gcry_sha256 gcry_sha512 btrfs tpm2_key_protector fat configfile tpm echo
如果启用了安全引导,请不要忘记签名 grub efi 二进制文件。例如使用 sbctl
# sbctl sign esp/EFI/GRUB/grubx64.efi
有关更多信息,请参阅 Unified_Extensible_Firmware_Interface/Secure_Boot。
参见
- GRUB 2 主题教程[失效链接 2025-11-17—HTTP 404]