10.4. 使用 GRUB 设定引导过程

[注意]

注意

本节假设您的系统支持 UEFI 且您希望使用它引导 LFS 系统。如果您的系统不支持 UEFI,或者您不想使用它,您需要自行寻找配置引导过程的方法。

10.4.1. 概述

[警告]

警告

如果您不小心错误地配置了 GRUB,可能导致您的系统完全无法使用,除非使用 CD-ROM 或可引导的 USB 存储器等备用引导设备。本节不是引导您的 LFS 系统的唯一方案,您可能只要修改现有的启动加载器 (如 Grub-Legacy、GRUB2 或 LILO) 配置即可引导 LFS。

您务必保证自己拥有一个紧急引导磁盘,它在计算机不可用 (无法引导) 时能够 抢修 计算机。如果您现在还没有引导设备,您可以执行以下命令创建一个。如果要创建用于 UEFI 的紧急引导设备,参阅 BLFS 页面中的Create an Emergency Boot Disk一节。

10.4.2. 关闭 Secure Boot

LFS 没有支持 Secure Boot 所需的关键软件包。为了按照本节给出的方法设定引导过程,必须在固件的设置界面关闭安全引导。如果您不知道如何操作,阅读您的系统生产商给出的文档。

10.4.3. GRUB 命名惯例

GRUB 使用一种独特的命名结构,为驱动器和分区命名。分区名的形式为 (hdn,m),这里 n 是硬盘驱动器编号,m 是分区编号。硬盘驱动器编号从 0 开始,但分区号对于主分区来说从 1 开始 (对于扩展分区来说从 5 开始)。例如,分区 sda1 在 GRUB 中的名字是 (hd0,1),而 sdb3 的名字是 (hd1,3)。和 Linux 不同,GRUB 不认为 CD-ROM 驱动器属于硬盘驱动器。例如,如果在 hdb 上有一个 CD-ROM 驱动器,而 hdc 上有第二个硬盘驱动器,则第二个硬盘驱动器仍然名为 hd1

10.4.4. 设定 GRUB 配置

GRUB 需要在 EFI 系统分区 (ESP) 中创建一个 EFI 可执行文件才能正常工作。您可以用以下命令找到 ESP:

fdisk -l | grep 'EFI System'

如果您的硬盘上没有 ESP (例如,您在一个全新的硬件系统上使用 Live CD 作为宿主发行版构建 LFS),阅读 BLFS 页面以了解如何在硬盘上创建 ESP。

如果 ESP 没有挂载到 (chroot 中的) /boot/efi,现在挂载它:

mkdir -pv /boot/efi
mount /boot/efi
[注意]

注意

这里有意略去了命令中的设备节点路径。我们假设将 ESP 挂载到 /boot/efi 的条目已经写入 /etc/fstab。如果您忘记在第 10.2 节 “创建 /etc/fstab 文件”中创建 ESP 的条目,需要在运行上述命令前,补充这一条目。

引导分区的位置由负责进行配置的用户自己决定,作者推荐创建一个小的 (建议大小为 200 MB) 分区,专门存放引导信息。这样,不同的 Linux 系统 (无论是 LFS 还是商业发行版) 在启动时和启动后都能访问相同的引导文件。如果您选择这样做,您需要挂载这个单独的分区,将 /boot 中已有的文件 (例如上一节中构建的 Linux 内核) 移动到新的分区中。之后,解除该分区的挂载,并将它挂载为 /boot。另外,还要注意更新 /etc/fstab

直接将 /boot 目录保留在 LFS 分区也是可以的,但这样在配置多系统启动时比较麻烦。

根据以上信息,确定 LFS 根分区 (或 boot 分区,如果使用了独立的 boot 分区) 的名称。下面假设 LFS 根分区 (或 boot 分区) 是 sda2

将 GRUB 文件安装到 /boot/grub,并将 GRUB EFI 可执行文件安装到 /boot/efi/EFI/BOOT/BOOTLOONGARCH64.EFI

[警告]

警告

以下命令会覆盖 BOOTLOONGARCH64.EFI,如果这不是您希望的,不要运行该命令。例如,如果该文件已经包含了另一启动管理器。您可以用 cp 命令备份它,因为它只是一个普通文件。

grub-install --removable
[注意]

注意

这里的 --removable 可能看上去很奇怪。UEFI 固件在 ESP 中以硬编码的路径,即 EFI/BOOT/BOOTLOONGARCH64.EFI,以及 EFI 变量中列出的其他引导加载器路径搜索包含引导加载器的 EFI 可执行文件。我们尚未安装能够操作 EFI 变量的工具,因此只能将 EFI 可执行文件安装到硬编码的路径上。硬编码的路径通常用于可移动设备 (如 USB 闪存盘),因此 使得 grub-install 使用硬编码路径的选项名为 --removable

UEFI 实现通常倾向于使用 EFI 变量中记录的路径,而不是硬编码的搜索路径。在下次引导系统时,您可能需要使用 EFI 固件提供的引导设备选择目录或者设置界面,以手动选择引导加载器。

某些 UEFI 实现在同一硬盘中存在记录于 EFI 变量的引导加载器时,会完全忽略硬编码的路径。此时您需要为新安装的引导加载器创建一个 EFI 变量。安装 efibootmgr,并按照 BLFS 中的说明在不用 --removable 选项的情况下执行 grub-install 命令。

10.4.5. 创建 GRUB 配置文件

生成 /boot/grub/grub.cfg

cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5

insmod part_gpt
insmod ext2
set root=(hd0,2)

insmod efi_gop
insmod efi_uga

menuentry "GNU/Linux, Linux 6.10.5-lfs-loongarch-12.2-systemd" {
        linux   /boot/vmlinuz-6.10.5-lfs-loongarch-12.2-systemd root=/dev/sda2 ro
}
EOF

insmod 命令加载 GRUB 模块 part_gpt and ext2ext2 模块尽管如此命名,实际上却支持 ext2ext3,以及 ext4 文件系统。grub-install 命令已经将一些模块嵌入 GRUB 主映像 (它安装在 MBR 或 GRUB BIOS 分区中),以便在访问其他模块 (这些模块在 /boot/grub/i386-pc 中) 时避免“先有鸡还是先有蛋”的问题。因此,在典型的系统配置中,这两个模块已经被嵌入主映像,此时这两条 insmod 命令不会产生任何效果。但是无论如何它们不会造成损害,而且在一些少见的系统配置中它们可能是必要的。

[注意]

注意

GRUB的视角来看,内核文件的位置相对于它使用的分区。如果您使用了单独的 /boot 分区,需要从上面的 linux 行删除 /boot,然后修改 set root 行,指向 /boot 分区。

[注意]

注意

如果新增或移除了一些存储设备 (包括 USB 闪存盘等可移动存储设备),则 GRUB 赋予分区的编号可能发生改变。这可能导致引导失败,因为 grub.cfg 仍然在使用旧的编号。如果希望避免这种问题,可以使用分区和文件系统的 UUID 指定分区,以代替 GRUB 编号。运行 lsblk -o UUID,PARTUUID,PATH,MOUNTPOINT 以显示文件系统 (在 UUID 列) 和分区 (在 PARTUUID 列) 的 UUID。之后将 set root=(hdx,y) 替换为 search --set=root --fs-uuid <内核所在文件系统的 UUID>,并将 root=/dev/sda2 替换为 root=PARTUUID=<构建 LFS 使用的分区的 UUID>

注意分区的 UUID 和该分区中文件系统的 UUID 是完全不同的。一些在线资料可能建议使用 root=UUID=<文件系统 UUID> 代替root=PARTUUID=<分区 UUID>,但是这种方法依赖于 initramfs,而 initramfs 超出了 LFS 的范畴。

/dev 中分区对应的设备节点名也可能发生改变 (和 GRUB 分区编号的变化相比较为少见)。在 /etc/fstab 中,也可以将 /dev/sda1 这样的设备节点路径改为 PARTUUID=<分区 UUID>,从而避免设备节点命名发生改变时可能导致的引导失败。

GRUB 是一个很强大的程序,它提供了非常多的选项,可以支持多种设备、操作系统和分区类型,还有很多用于定制启动屏幕、声音、鼠标输入等的选项。这些选项的细节超过了本书的范围,不予讨论。

[小心]

小心

有一个命令 grub-mkconfig 被用于自动创建配置文件。它使用 /etc/grub.d 中的脚本创建新配置文件,这会覆盖您手动编写的 grub.cfg。这些脚本主要是为非源代码发行版设计的,在 LFS 中不推荐使用。但是,如果您安装了商业发行版,它很可能在发行版中被运行,记得备份 grub.cfg 以防它被覆盖。