Grub2 系统硬编码 stage2 文件的位置。此信息存储在引导加载程序分区中。我知道 grub-install 会写这个以及更多。
我的问题是 grub2-install 如何确定 /boot 目录(它自己的分区)所在的位置。grub-mkconfig 可以解决这个问题,但是,grub-install 似乎没有调用 grub-mkconfig。
我真的很想深入解释这是如何解决的。
底线问题是:“当 /boot 的位置发生更改时,更新 mbr/bios-boot 分区中的引导加载程序代码的正确方法是什么”?
官方文档或维基百科的指针将不胜感激。
您混淆了 GRUB Legacy 和 GRUB2 术语。术语“stage2”仅适用于 GRUB Legacy(即版本 0.9x)。但我想我明白你的意思。
当
i386-pc
GRUB 版本安装到 MBR 以及 MBR 和第一个分区之间的间隙或安装到 BIOS 引导分区时,这些/boot/grub2/i386-pc/{core,boot}.img
文件仅由 所使用grub2-install
,而不是由实际引导过程使用。由于
i386-pc
GRUB 架构上的操作系统没有可靠的方法来获取有关 BIOS 在引导时最后如何看到磁盘排序的信息,因此grub-install
如果配置为依赖 BIOS 磁盘支持(通常的方式),则在安装时基本上有两个可用选项:/boot/grub[2]/device.map
已提供文件,请使用其中的信息将操作系统设备映射到 GRUB 设备名称(这将直接对应于 BIOS 磁盘编号)device.map
文件不可用,请大胆猜测当前操作系统磁盘顺序与 BIOS 磁盘检测顺序相同。这个猜测可能正确,也可能不正确。(具体来说,当从 USB 运行安装程序或实时媒体时,通常会将 USB 存储设备检测为第一个“磁盘”;这可以消除 的猜测
grub-install
,因为一旦安装的操作系统自行启动, USB 存储的 BIOS 级磁盘模拟将不再存在,因为此时 BIOS 不会从 USB 介质启动。)嵌入实际 MBR 块中的 GRUB 引导代码包含两条同时写入其中的信息
grub-install
:引导驱动器号和 GRUB 接下来应读取的 LBA 块号。在现代版本的 GRUB 中,驱动器号通常编码为0xff
,意思是“使用用于读取 MBR 的相同磁盘 BIOS”。当在 MBR 分区磁盘上时,LBA 块号通常为
0x0000000000000001
,指向 MBR 和第一个分区之间的间隙。在 MBR 分区磁盘上,GRUB 核心映像的其余部分、基本模块和前缀字符串(将指向目录位置/boot/grub
)将嵌入其中。在 GPT 分区磁盘上,所有这些都将被写入分区bios-boot
,并且实际 MBR 引导代码中嵌入的 LBA 块号将更高,因为它将指向分区的开头bios-boot
。嵌入代码的第一个块包括一个块列表,用于标识接下来要读取哪些块:当嵌入到 MBR 分区磁盘时,这将是从 LBA 块 #2 开始的一系列连续块。本系列的长度主要取决于与 GRUB 核心映像一起嵌入的基本模块的数量和类型。大多数嵌入代码将被 LZMA 压缩,然后用 Reed-Solomon 纠错码进行保护,因此修改它通常会迫使您从本质上重写整个代码。不幸的是,标识目录位置的前缀字符串
/boot/grub[2]
肯定会在压缩部分内。在现代系统上,MBR 和第一个分区的开头之间的间隙通常正好是 2047 个块,以将第一个分区对齐到磁盘中的 1 MiB 处。
fdisk
但是较旧的系统可能已使用不关心数据对齐的版本进行分区,而是尝试保持 DOS 兼容性,将分区的开头定位在磁盘磁道的开头(尽管经典的 C/H/S 磁盘几何结构具有长期以来只是由磁盘固件维护的虚构)。在这些情况下,MBR 和第一个分区的开头之间的间隙可能要小得多。因此,为了最大限度地提高兼容性,grub-install
需要将绝对最少数量的基本 GRUB 模块与核心映像一起嵌入,以最大限度地减少嵌入代码的大小。对于由 PC 硬件和 BIOS 实现导致的其他相关限制,请参阅 GRUB 文档:i386-pc
在这方面被认为是“严重受限的平台”。在基于 MBR 的磁盘上进行简单的 RedHat/Debian 安装时,作为
/boot
磁盘上第一个分区的单独分区,典型的嵌入式模块集如下:biosdisk.mod
使用 BIOS 功能进行磁盘访问part_msdos.mod
了解MBR分区表/boot
支持分区的文件系统所需的任何模块至少(如果
/boot
分区初始化为 ext2 文件系统),ext2 文件系统支持所需的 GRUB 模块将为ext2.mod
和fshelp.mod
。这是一种实用的配置,可能会产生现代 GRUB 架构可实现的最小嵌入式代码大小之一i386-pc
。/grub
如果 GRUB 目录在单独的文件系统上命名/boot
,并且/boot
是磁盘上的第一个分区,则嵌入的前缀字符串通常为(,msdos1)/grub
. 请注意,GRUB 磁盘标识符丢失:这意味着“使用 BIOS 从中读取 MBR 的同一磁盘”。表示msdos1
磁盘上的第一个 MBR 样式分区,只是从文件系统根目录开始的目录/grub
路径。/boot/grub
/boot
因此,仅使用嵌入在 MBR 间隙或 BIOS 引导分区中的代码,GRUB 将能够使用 BIOS 读取
normal.mod
磁盘(,msdos1)/grub/i386-pc/normal.mod
支持和文件系统元数据,以找到正确的块。之后,将分别读取配置文件(,msdos1)/grub/grub.cfg
。还可以将 例如
ahci.mod
和search_fs_uuid.mod
与 GRUB 核心映像一起嵌入,以使 GRUB 能够直接访问 AHCI SATA 控制器并通过 UUID 识别正确的分区/文件系统,但其ahci.mod
大小超过 3 倍biosdisk.mod
,这使得命中图像大小更有可能受到限制。唯一实际的答案是“通过再次运行来重写嵌入式引导加载程序代码
grub[2]-install
”。执行此操作时,请确保已将新/boot
安装为/boot
,并且如有必要,请为该文件提供适合下次启动时系统/boot/grub/device.map
配置的内容。在 Debian 以及 Ubuntu 和 Mint 等衍生产品上,包管理系统会记住 GRUB 版本的安装目标设备
i386-pc
。您可以使用 查看此信息sudo debconf-show grub-pc
,并使用 进行更新sudo dpkg-reconfigure grub-pc
。RedHat 的包装中似乎没有类似的功能。
RedHat 及其衍生产品不会升级嵌入式引导代码。
相比之下,在
x86_64-efi
GRUB 架构上,通常没有大小限制来阻止您将所有可用的 GRUB 模块嵌入到grubx64.efi
文件中,从而生成一个可以进行安全启动签名的 UEFI 二进制文件,并且永远不需要加载任何额外的可执行代码功能。实际上,这保证了只要系统可以读取,即使目录被完全破坏,grubx64.efi
所有 GRUB 正常模式命令行功能都将可用。/boot/grub[2]