如何将 grub 安装到 .img 文件中?

Fra*_*rco 28 linux grub

我做了以下事情:

  1. 使用 dd 创建了一个空的 .img 文件
  2. 将它关联到 /dev/loop0 与 Lostup
  3. 使用 fdisk 在其中创建了一个分区
  4. 用 mke2fs 格式化这样的分区
  5. 将自定义 GNU/Linux 系统复制到该分区

现在我想通过将 grub 安装到其 MBR 和 /boot 目录中来使 .img 文件可启动。我的目标是使用 qemu 加载 .img 文件。如果使用 grub2 而不是 grub legacy 会更好。

谢谢。

小智 25

这是 grub-pc 版本 1.98+20100804-5ubuntu3 (Maverick Meerkat)。

grub2 安装程序可以安装到环回设备,但是如果您使用设备映射器进行安装,它会感到困惑并相信您有一个 LVM 方案,神秘地失败并抱怨缺少抽象。

相反,您应该自己为分区设置环回设备,名称必须与模式“/dev/loop[0-9]”匹配,即末尾没有任何分区指示符:

kpartx -v -a /dev/loop0
losetup /dev/loop1 /dev/mapper/loop0p1
mount /dev/loop1 /mnt
Run Code Online (Sandbox Code Playgroud)

(注意,如果想让grub-mkconfig/update-grub对这个卷进行操作,那么分区环回必须连接到/dev下的磁盘环回,而不是直接连接到镜像文件)。

由于您使用 fdisk 对映像进行分区,因此您有一个msdos样式的分区表(又名标签),并使用 BIOS 启动。除了将stage1/boot.img放入MBR之外,stage1.5/core.img会被放入紧随其后的未分区空间(!)的embedding区域,并且必须有空间。

现在的技巧是通过设备映射告诉 grub2 安装程序您的环回设置将如何映射到虚拟机中的 BIOS 驱动器。(在 grub1 legacy 中,这是直接在 shell 中完成的)。您可能打算将此映像作为第一个磁盘启动,因此我想适当的映射是:

mkdir -p /mnt/boot/grub
cat > /mnt/boot/grub/device.map <<EOF
(hd0)   /dev/loop0
(hd0,1) /dev/loop1
EOF
Run Code Online (Sandbox Code Playgroud)

这里我把设备映射放在了guest磁盘镜像中,这样就可以生成启动配置文件grub.cfg:

mount --bind /dev /mnt/dev
chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg
Run Code Online (Sandbox Code Playgroud)

(请注意,grub-pc 软件包的后安装程序将运行覆盖设备映射(!)的探针,因此您必须安装编写它并自己运行 grub-mkconfig/update-grub)。

现在从主机运行安装程序,指向来宾安装:

grub-install --no-floppy --grub-mkdevicemap=/mnt/boot/grub/device.map --root-directory=/mnt /dev/loop0
Run Code Online (Sandbox Code Playgroud)

最后,在您的镜像上启动 qemu 之前卸载这里设置的所有内容:

umount /mnt/dev
umount /mnt
losetup -d /dev/loop1
kpartx -v -d /dev/loop0
Run Code Online (Sandbox Code Playgroud)


小智 11

非常感谢这些解释。我通过以下修改将您的解决方案集成到我自己的脚本中(转换为您的符号/变量):

modprobe dm_mod
kpartx -va /root/rootfs.img # *.img is setup elsewhere
# normally you now would mount /dev/loop0p1 directly. BUT
# grub specialists didn't manage to work with loop partitions other than /dev/loop[0-9]
losetup -v -f --show /dev/mapper/loop0p1
mount /dev/loop1 /mnt
mkdir -p /mnt/boot/grub

# change into chrooted environment. all remaining work will be done from here. this differs from the howto above.
LANG=C chroot /mnt /bin/bash
set -o vi
mount -t sysfs sysfs /sys
mount -t proc  proc  /proc
# avoid grub asking questions
cat << ! | debconf-set-selections -v
grub2   grub2/linux_cmdline                select   
grub2   grub2/linux_cmdline_default        select   
grub-pc grub-pc/install_devices_empty      select yes
grub-pc grub-pc/install_devices            select   
!
apt-get -y install grub-pc
# don't setup device.map prior to this point. It will be overwritten by grub-pc install
#corrected the /mnt/boot/grub/device.map to /boot/grub/device.map
cat > /boot/grub/device.map << !
(hd0)   /dev/loop0
(hd0,1) /dev/loop1
!
# install here to fill /boot/grub for grub-mkconfig (update-grub)
grub-install /dev/loop0
# generate /boot/grub/grub.cfg
update-grub
Run Code Online (Sandbox Code Playgroud)

这至少适用于 debian 挤压。检查“/boot/grub/grub.cfg”是否正确。