首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使grub1与GPT协同工作

如何使grub1与GPT协同工作
EN

Unix & Linux用户
提问于 2018-10-28 12:18:11
回答 1查看 636关注 0票数 2

我想让grub1和GPT一起工作。目前在虚拟机上,作为迁移真正的虚拟机之前的一个测试步骤。

我为/boot创建了一个分区,并创建了一个不同的分区,我希望在其中嵌入GRUBstage1.5。这是gdisk为GPT分区表显示的内容:

代码语言:javascript
复制
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的看法:

代码语言:javascript
复制
   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)上拥有真正的引导分区(包括D3、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有16 is的空间用于嵌入引导加载器),但是错误是相同的。但是,我创建的FS是一个非标准的FS,在一个单独的设备上有日志,因为512 to不足以创建一个正常的FS。

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

关于如何运行这个选项还有其他的选择吗?我正在考虑手动将stage1.5嵌入到选定的分区(cat /boot/grub/e2fs_stage1_5 > /dev/sda4)中,并正确地修改它(我猜这只是第一扇区的区块列表和第二扇区的stage2位置),然后从那里开始,但我想让它正常工作。

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

EN

回答 1

Unix & Linux用户

发布于 2018-11-19 23:04:16

结果却比预期的更容易也更难。

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

这更容易,因为标准setup (hd0,0)确实可以工作,比如“生成一个可引导的系统”。然而,按照我的标准,这个系统还不够健壮--因为setup无法在任何地方嵌入第1.5级,所以它需要修补stage2并将其位置包含在MBR中的磁盘上。因此,如果有什么东西移动stage2,改变以前的块,我就会得到一个无法引导的系统。更糟糕的是,我可能不会首先注意到这一点--一次升级将stage2移至不同的位置,但旧的则保持原样。系统还在启动,我什么也没注意到。但是,由于引导期间使用的代码现在是文件系统的POV中的空闲空间,所以后来有一些东西随机地覆盖了它并砰地一声。

因此,我采用了问题末尾概述的步骤,手动嵌入第1.5阶段。

首先,创建一个适当的stage1.5文件的副本,并在该副本上启动一个十六进制编辑器。如果您没有现成的工具,我已经成功地使用了vim和xxd -编辑文件,输入:!xxd编辑文件为十六进制,键入:!xxd -r并保存。文件在结束时会得到一个额外的行提要,但它是无害的。注意,在这种情况下,右侧的ASCII部分被完全忽略,只使用十六进制数字。您需要编辑该文件中的三项内容:

  • 将第二个块的块号放在偏移量0xf8处,第1.5级将嵌入其中。请注意,它是小端点,并且相对于磁盘的启动。由于BIOS引导分区从扇区1024开始,这是1025,或0x0401或(以小字节为单位)字节0104
  • 将第1.5级的512个字节扇区的数目减去一个偏移量0x1fc。因为我的第1.5阶段是9908字节(9909加上额外的换行符),它是20个扇区(19个扇区是19*512=9728,20个扇区是10240字节),所以我需要放19个,或者十六进制13
  • 将偏置219处的ff更改为00。不要碰附近的ff's。

下面是原始文件和修改文件的不同之处:

代码语言:javascript
复制
-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|

它的工作方式是,第一个阶段1.5的第一个扇区从它的末尾读取数字,并从磁盘开始时从指定的一个扇区开始读取许多扇区。这会将第1.5阶段的其余扇区加载到内存中,然后执行它们。第三部分实际上是stage2在磁盘上的位置,grub需要在其中找到正确的分区。如果您感兴趣的话,相关代码是grub源代码中的stage2/disk_io.c,请记住,您在#ifdef STAGE1_5中使用了该部分,加载其余部分的第一个扇区在stage2/start.S中。也许可以在几个不连续的部分中使用第1.5阶段,但我还没有尝试过。

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

最后,在grub中执行

代码语言:javascript
复制
install /boot/grub/stage1 (hd0) (hd0)1024+20

使用(hd0)作为正在使用的设备的grub名称,1024是嵌入式阶段1.5(顺便说一句,BIOS启动分区的启动)的开始,20是第1.5级块的大小。这就完成了这个过程。

票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/478247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档