据我了解,BIOS 系统上的 GRUB 引导加载程序(以及大多数其他引导加载程序)由 3 个部分组成。第一部分(阶段 1)存储在第一个448
字节中,负责将控制传递给所谓的阶段 1.5,它位于内存中稍晚一点的位置。这个阶段最终从 /boot 文件夹加载阶段 2,并将控制权转移给它。
阶段 1 如何知道阶段 1.5 驻留在哪个磁盘上?一旦阶段 1 中的代码开始执行,它就无法知道它是从哪个磁盘加载的(除非此信息以某种方式传递到阶段 1 或者 BIOS 本身也将阶段 1.5 加载到内存中?)
同样,对于阶段 1.5 到阶段 2,阶段 1.5 如何知道 /boot 目录驻留在哪个磁盘(和哪个分区)上?
名称“stage1”、“stage1.5”和“stage2”属于 GRUB Legacy,即 GRUB 版本 0.xx。当阶段 1 写入 MBR(或 PBR)时,安装程序还将在其中写入下一阶段开始所在的实际磁盘块号。下一阶段的第一个块将包含更多程序代码,以及描述该阶段其余部分所在位置的块列表。阻止列表条目的形式为“从磁盘块 #Y 开始加载 X 块”。如果下一阶段作为连续(非分段)文件写入磁盘,则通常只需要一个阻止列表条目。
stage1.5 实际上是可选的:完全有可能根本不安装 stage1.5,而只是让 stage1 直接加载 stage2。阶段 1.5 将包含足够的代码来理解单个文件系统类型;stage2 将包含所有受支持的文件系统驱动程序,这将使其更大。这样,stage1.5 可以嵌入到 MBR 和第一个分区开头之间的通常未使用的空间中。
(现代 MBR 分区磁盘现在从第一个磁盘的开头正好 1 MiB 开始第一个分区,即在块 #2048,以允许大型存储系统的最佳数据对齐。这在 MBR 之间留下了更多未使用的空间并且第一个分区的开头比旧约定在 C/H/S 0/1/1 开始第一个分区。)
stage1.5 和 stage2 都有一个预先分配的空间,供安装程序写入 GRUB 磁盘标识符和路径名。对于 stage1.5,这将标识实际 stage2 所在的分区和文件名;在 stage2 的情况下,它将识别 GRUB 配置文件的位置。
与 BIOS 兼容的 GNU GRUB(即 GRUB 版本 1.xx 及更高版本)完全跳过 stage1.5,并使用不同的名称:
stage1
是现在boot.img
stage2
是现在core.img
它
boot.img
仍然是嵌入到 MBR 中的 448 字节,但是core.img
在 GRUB 安装时从kernel.img
一组 GRUB 模块动态构建。事实上的标准 BIOS 约定是,从 BIOS 中选择的任何磁盘作为要从其引导的磁盘都将被分配 ID 0x80 用于 BIOS 磁盘访问功能,并且该 ID 将直接映射到 GRUB
(hd0)
。(古老的 MS-DOS 同样总是将 BIOS 磁盘 ID 0x80 映射到驱动器C:
。)幸运的是,BIOS 在枚举不同磁盘控制器的方式上通常非常确定。因此,只要硬件配置和 BIOS 设置保持不变,磁盘检测顺序就会从一次引导到下一次保持不变。
但是,是的,这绝对是一个脆弱的策略。不幸的是,没有普遍的标准方法可以将 BIOS 的磁盘检测信息从 16 位 BIOS 例程传递到使用 32 位保护模式编程(甚至 64 位)的操作系统。因此,在从基于 BIOS 的引导加载程序切换到完整的 32 位或 64 位模式后,所有 32 位或更好的操作系统都将从头重新检测其磁盘。
是的,BIOS 增强型磁盘驱动器服务(简称 EDD)包括一个 BIOS 扩展,可用于向受保护模式的操作系统报告 BIOS 磁盘检测的基本细节……但该扩展引入得相当晚,并且报告部分是可选的,因此它的可用性远不能保证。
在具有多个磁盘控制器的基于 BIOS 的系统上,这基本上是一个令人头疼的问题。
获胜的策略通常是在第一次遇到特定的硬件型号时彻底测试 BIOS 引导设置(可能会尝试多次安装操作系统),一旦找到好的配置,就将其写下来,不要碰 BIOS之后的启动设置。
现代 GNU GRUB 包括
search
可用于通过标签、UUID 和/或特定文件的存在来选择磁盘分区的命令。在现代生成的grub-mkconfig
GRUB 2.xx 配置文件中,固定标识符通常应该是最后的选择,仅在早期search
命令失败时使用。GPT 分区表包括每个磁盘和分区的唯一 UUID 作为标准,UEFI NVRAM 变量实际上使用 ESP 的分区 UUID + ESP 分区内的引导加载程序的路径名指定引导加载程序的位置。这允许更健壮的配置。运行中的操作系统还有一个标准接口,可以从 UEFI 固件读取引导信息,并在需要时修改引导设置。
如果您查看 GRUB 的来源,可在此处找到,您会发现 stage1 实际上定义在
grub/grub-core/boot/i386/pc/boot.S
.如果已配置,它可以执行软盘引导。它确实从配置的硬盘启动,并且它需要知道它必须从哪个 C/H/S 加载 stage1.5。它唯一的自动功能是确定从哪个驱动器加载引导扇区,如果没有另外配置的话。在将控制权传递给 stage1 之前,功能性 BIOS 会将该值加载到 DL 中。有些不这样做,grub 会退回到第一个硬盘。
stage1.5 已经能够理解分区和文件系统,因此它不再依赖 C/H/S 值。它加载的驱动器仍然与上面相同。