如何让 grub1 使用 GPT

如何让 grub1 使用 GPT

我正在尝试让 grub1 与 GPT 一起工作。目前在虚拟机上,作为迁移真实计算机之前的测试步骤。

我已经为/boot和 另一个分区创建了一个分区,我想在其中嵌入 grub stage1.5。这是 gdisk 显示的 GPT 分区表:

Number  Start (sector)    End (sector) Size        Code  Name
   1             2048           104447 50.0 MiB    8300  boot
   2           104448           206847 50.0 MiB    EF00  EFI
   3           206848         16984063 8.0 GiB     8E00  
   4             1024             2047 512.0 KiB   EF02  GRUB1

不要理会 EFI 分区,在这种情况下不会使用它。只是我打算稍后将系统升级到UEFI(我知道,告别grub1),想早点创建分区。

现在,由于 grub1 不理解 GPT,我创建了一个混合 MBR,由第 1 和第 4 分区组成。 gdisk 对于​​混合 MBR 是这么说的:

   Number  Boot  Start Sector   End Sector   Status      Code
   1                        1         1023   primary     0xEE
   2         *           2048       104447   primary     0x83
   3                     1024         2047   primary     0xEF
   4                   104448     20971519   primary     0xEE

我的目的是将stage1.5放在1MB以下的小分区上,并在分区boot(GPT 1/MBR 2)处有真正的引导分区(带有stage2、grub配置和内核映像)。但是我无法让 grub 安装阶段。

grub运行命令时find /grub/menu.lst显示(hd0,0),所以看起来它正在使用正在运行的内核分区布局,即嵌入分区所在的位置(hd0,3)。然而给予root (hd0,3)给了我

文件系统类型未知,分区类型 0x83

文件系统类型并不奇怪,因为分区是空的,但我已经设置了分区类型并且它是不可见的。

当我尝试将 stage1.5 嵌入分区时(使用embed (hd0,0)/grub/e2fs_stage1_5 (hd0,3)我收到错误:

错误17:无法挂载所选分区

我尝试在该分区上创建 reiserfs3 (因为 reiserfs3 有 16KB 的空间用于嵌入引导加载程序),但错误是相同的。然而,我创建的 FS 是非标准的,日志位于单独的设备上,因为 512KB 不足以创建普通的 FS。

我已经检查过 (hd0,3) 是正确的驱动器,因为向分区的第一个扇区写入一些内容并cat (hd0,3)+1在 grub shell 中运行会给出预期的输出。

关于如何运行它的任何其他选项?我正在考虑手动将 stage1.5 嵌入到所选分区(cat /boot/grub/e2fs_stage1_5 > /dev/sda4)中,并对其进行适当修改(我猜测它只是第一个扇区中的阻止列表和第二个扇区中的 stage2 位置),并从那里开始,但我想让它正常工作。

我使用的版本是 Gentoo 的 sys-boot/grub-0.97-r18。

答案1

事实证明,比预想的更容易,也更难。

首先,Gentoo(以及据我所知的许多其他发行版)已经对 Grub 进行了修补,使其能够读取 GPT,因此不需要混合 MBR 的整个麻烦,它可以与纯 GPT 一起使用。

这更容易,因为标准setup (hd0,0)确实有效,就像“制作可启动系统”一样。然而,按照我的标准,系统不够健壮 - 因为setup无法将 stage1.5 嵌入到任何地方,所以它求助于修补 stage2 并将其在 MBR 中的磁盘位置包含在内。因此,如果有任何东西移动了 stage2,改变了之前所在的块,我就会得到一个无法启动的系统。更糟糕的是,我可能不会首先注意到它 - 升级将 stage2 移动到不同的位置,但旧的位置保持不变。系统仍在启动,我什么也没注意到。但由于启动期间使用的代码现在是文件系统 POV 中的可用空间,因此稍后会随机覆盖它并繁荣。

因此,我采取了问题末尾概述的步骤,手动嵌入 stage1.5。

首先,复制相应的 stage1.5 文件,然后在该副本上启动十六进制编辑器。如果您手头没有,我已经成功使用 vim 和 xxd - 编辑文件,键入:!xxd<enter>将文件编辑为十六进制,键入:!xxd -r<enter>并保存。文件末尾有一个额外的换行符,但它是无害的。请注意,在这种情况下,右侧的 ASCII 部分将被完全忽略,仅使用十六进制数字。您需要在此文件中编辑 3 项内容:

  • 放入块号第二将在 offset 处嵌入 stage1.5 的块0xf8。请注意,它是小端字节序,并且相对于磁盘的开头。由于 BIOS 引导分区从扇区 1024 开始,因此为 1025 或0x0401或(以小端字节序表示)字节0104
  • 将 stage1.5 的 512 字节扇区数减一置于 offset 处0x1fc。由于我的 stage1.5 是 9908 字节(9909 加上额外的换行符),它有 20 个扇区(19 个扇区是19*512=972810240 字节,20 个扇区是 10240 字节,所以我需要13在其中放入 19 或十六进制)。
  • ff将偏移量 219 处更改为00.不要触摸ff附近的 。

以下是原始文件和修改后的文件的十六进制转储的差异:

-000001f0  00 00 00 00 00 00 00 00  02 00 00 00 00 00 20 02  |.............. .|
+000001f0  00 00 00 00 00 00 00 00  01 04 00 00 13 00 20 02  |.............. .|
 00000200  ea 70 22 00 00 00 03 02  ff ff ff 00 00 00 00 00  |.p".............|
-00000210  02 00 30 2e 39 37 00 ff  ff ff ff 2f 62 6f 6f 74  |..0.97...../boot|
+00000210  02 00 30 2e 39 37 00 ff  ff 00 ff 2f 62 6f 6f 74  |..0.97...../boot|

其工作方式是,stage1.5 的第一个扇区从接近末尾处读取数字,并从磁盘开头的指定扇区开始读取那么多扇区。这会将 stage1.5 的剩余扇区加载到内存中,然后执行它们。第三部分实际上是stage2在磁盘上的一个位置,grub需要在这里找到正确的分区。如果有人感兴趣的话,相关代码位于stage2/disk_io.cgrub 的源代码中,只需记住您使用的部分位于 中#ifdef STAGE1_5,而加载其余部分的第一个扇区位于 中stage2/start.S。可能有可能在几个不连续的部分中有stage1.5,但我还没有尝试过。

编写修改后的 stage1.5 后,只需将其复制到目标分区(我的示例中的第四个分区),根据您的喜好使用catdd

最后,在grub shell中执行

install /boot/grub/stage1 (hd0) (hd0)1024+20

(hd0) 是您正在使用的设备的 grub 名称,1024是嵌入式 stage1.5 的开始(顺便说一下,BIOS 引导分区的开始),并且20是 stage1.5 的大小(以块为单位)。这样就完成了整个过程。

相关内容