据我了解,BIOS 系统上的 GRUB 引导加载程序(以及大多数其他引导加载程序)由 3 个部分组成。第一部分(阶段 1)存储在第一个448
字节中,负责将控制传递给所谓的阶段 1.5,该阶段位于内存中稍后的位置。该阶段最终从 /boot 文件夹加载阶段 2,并将控制权转移给它。
stage 1 如何知道 stage 1.5 驻留在哪个磁盘上?一旦阶段 1 中的代码开始执行,它就无法知道它是从哪个磁盘加载的(除非此信息以某种方式传递到阶段 1 或者 BIOS 本身也将阶段 1.5 加载到内存中?)
对于阶段 1.5 到阶段 2,阶段 1.5 如何知道 /boot 目录驻留在哪个磁盘(以及哪个分区)?
答案1
如果你查看 GRUB 的源代码,可以找到这里,你会发现 stage1 实际上是在 处定义的grub/grub-core/boot/i386/pc/boot.S
。
如果配置的话它可以执行软盘引导。它确实从配置的硬盘启动,并且需要知道必须从哪个 C/H/S 加载 stage1.5。它唯一具有的自动功能是确定引导扇区是从哪个驱动器加载的(如果没有进行其他配置)。正常运行的 BIOS 会在将控制权传递给 stage1 之前将该值加载到 DL 中。有些则不然,grub 会退回到第一个硬盘。
stage1.5已经能够理解分区和文件系统,因此它不再依赖于C/H/S值。不过,它加载的驱动器仍然与上面相同。
答案2
第一部分(阶段 1)存储在前 448 个字节中,负责将控制传递给所谓的阶段 1.5,该阶段位于内存中稍后的位置。该阶段最终从 /boot 文件夹加载阶段 2,并将控制权转移给它。
名称“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 模块动态构建的。
我可以看到这些信息被硬编码到阶段 1.5,但这如何处理以不同顺序安装的驱动器(保证 (hd0) 和 (hd1) 始终是相同的驱动器,因此硬编码类似的内容似乎是一个脆弱的策略。
事实上的标准 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 固件读取启动信息,并在需要时修改启动设置。