我可以解释 Grub2 后 MBR 的差距吗?

我可以解释 Grub2 后 MBR 的差距吗?

在设置用于基于 QEMU 的虚拟机的 RAW 磁盘映像时,我感到很沮丧,因为 QEMU 会加载 GRUB,但 GRUB 不会加载要启动的操作系统菜单。我得出的结论是 GRUB 一定无法找到 crug.cfg 文件,这使我相信它在后 MBR 间隙中编码了错误的内容。是否存在任何工具可以检查此间隙的内容?


以下是我将 GRUB 安装到 VM 映像中的方法:

# Disk Image
fallocate -l $((4*1024*1024*1024)) "$file"
DEV=$(sudo losetup --show --nooverlap --find "$file")

# Partition Table
sudo parted "$DEV" mklabel msdos
sudo parted "$DEV" mkpart primary fat16 1MiB 101MiB 
sudo parted "$DEV" mkpart primary ext4 102MiB 100%
sudo parted "$DEV" set 1 boot on
sudo mkfs.vfat "${DEV}p1"
sudo mkfs.ext4 -E lazy_journal_init=1 -E lazy_itable_init=1 -E discard "${DEV}p2"

# Mounting, installing base packages, configuration, etc..
# ...

# Bootloader
sudo mkdir "$mountpoint/boot/grub"
sudo install "$grub_default_file" "$mountpoint/etc/default/grub"
sudo arch-chroot "$mountpoint" grub-install --boot-directory="/boot/grub" --target=i386-pc "$DEV"
sudo arch-chroot "$mountpoint" grub-mkconfig -o "/boot/grub/grub.cfg"

修改后的版本$grub_default_file只是进行了一些小的修改来打开串行输出,以便我可以从 QEMU 的串行控制台进行查看。

GRUB_CMDLINE_LINUX="quiet console=tty0 console=ttyS0,38400n8"
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --speed=38400 --unit=0 --word=8 --parity=no --stop=1"

这是我到目前为止已经验证的内容:

  1. MBR 包含字符串“GRUB”,表明 grub 已将自身安装到磁盘映像上
  2. 分区表有足够大的 post-MBR 间隙
  3. 第一个分区设置了启动标志
  4. 第一个分区是vfat文件系统
  5. 第一个分区包含/grub/grub.cfg相关文件
  6. grub.cfg文件包含第一个和第二个分区的正确 UUID

我无法真正验证的唯一链接是 grub 定位包含配置文件的分区。也许我设置了错误的启动标志。也许我选择了错误的文件系统类型。也许 grub 在 MBR/post-MBR 间隙中错误地编码了该分区的位置。调试起来相当困难。

$ sudo dd if=zonemanager bs=$((2048*512)) count=1 | strings | grep -i grub
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.00742499 s, 141 MB/s
GRUB 
$ sudo parted /dev/loop1
GNU Parted 3.2
Using /dev/loop1
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit s                                                           
(parted) p                                                                
Model: Loopback device (loopback)
Disk /dev/loop1: 8388608s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start    End       Size      Type     File system  Flags
 1      2048s    206847s   204800s   primary  fat16        boot, lba
 2      208896s  8388607s  8179712s  primary  ext4
$ sudo file -s /dev/loop1
/dev/loop1: DOS/MBR boot sector
$ sudo file -s /dev/loop1p1
/dev/loop1p1: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, reserved sectors 4, root entries )
$ sudo lsblk -f
NAME               FSTYPE      LABEL UUID                                   FSAVAIL FSUSE% MOUNTPOINT
loop1                                                                                      
├─loop1p1          vfat              58D5-B48F                                45.1M    55% /mnt/boot
└─loop1p2          ext4              0014f737-33b7-4dba-be4a-2b186e2e46a0      2.1G    39% /mnt

$ grep 58D5-B48F /mnt/boot/grub/grub.cfg 
      search --no-floppy --fs-uuid --set=root  58D5-B48F
      search --no-floppy --fs-uuid --set=root 58D5-B48F
          search --no-floppy --fs-uuid --set=root  58D5-B48F
          search --no-floppy --fs-uuid --set=root 58D5-B48F
          search --no-floppy --fs-uuid --set=root  58D5-B48F
          search --no-floppy --fs-uuid --set=root 58D5-B48F
$ grep 0014f737-33b7-4dba-be4a-2b186e2e46a0 /mnt/boot/grub/grub.cfg 
menuentry 'Arch Linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-0014f737-33b7-4dba-be4a-2b186e2e46a0' {
    linux   /vmlinuz-linux root=UUID=0014f737-33b7-4dba-be4a-2b186e2e46a0 rw quiet console=tty0 console=ttyS0,38400n8 quiet
submenu 'Advanced options for Arch Linux' $menuentry_id_option 'gnulinux-advanced-0014f737-33b7-4dba-be4a-2b186e2e46a0' {
    menuentry 'Arch Linux, with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-0014f737-33b7-4{
        linux   /vmlinuz-linux root=UUID=0014f737-33b7-4dba-be4a-2b186e2e46a0 rw quiet console=tty0 console=ttyS0,38400n8 quiet
    menuentry 'Arch Linux, with Linux linux (fallback initramfs)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-fal{
        linux   /vmlinuz-linux root=UUID=0014f737-33b7-4dba-be4a-2b186e2e46a0 rw quiet console=tty0 console=ttyS0,38400n8 quiet

错误#1:grub-install --boot-directory应该是/boot而不是/boot/grub


当前调查#1:我将其grub.cfg与已知的工作 QEMU 虚拟机进行了比较。除了设备的 UUID 之外,只有两点不同:

  1. set root=(hd0,1)
  2. 额外的参数search

在职的

set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
    search --no-floppy --fs-uuid --set=root --hint-ieee1275='ieee1275//disk@0,msdos1' --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  0959-F5DD

不工作

if [ x$feature_platform_search_hint = xy ]; then
    search --no-floppy --fs-uuid --set=root  ECB4-BE7A

当前调查#2:在 grub shell 中时,我可以找到并引导到早期用户空间。


                             GNU GRUB  version 2.02

   Minimal BASH-like line editing is supported. For the first word, TAB   
   lists possible command completions. Anywhere else TAB lists possible   
   device or file completions.                                            


grub> set pager=1
grub> echo $feature_platform_search_hint
y
grub> ls
(hd0) (hd0,msdos2) (hd0,msdos1) (fd0) 
grub> ls (hd0,msdos1)/
vmlinuz-linux initramfs-linux.img initramfs-linux-fallback.img grub/ 
grub> set root=(hd0,msdos1)
grub> linux /vmlinuz-linux root=UUID=0014f737-33b7-4dba-be4a-2b186e2e46a0  rw quiet console=tty0 console=ttyS0,38400n8 quiet
grub> initrd /initramfs-linux.img
grub> boot
Starting version 242.32-2-arch

此外,使用该configfile命令实际上会加载菜单!

grub> configfile /grub/grub.cfg

所以这让我相信 grub 由于某种原因找不到配置文件。


错误#2:启动正确的该死的映像文件。

为了消除工作虚拟机和非工作虚拟机之间的变量,我将非工作虚拟机从原始磁盘映像转换为 qcow2 映像。在过去的几个小时里我一直在启动该映像,因为我从未恢复过 systemd 单元。 “错误#1”之后的一切都是转移注意力的。不过,我将把它保留下来,因为它是一个很好的学习辅助工具。

相关内容