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

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

我做了以下事情:

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

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

谢谢。

答案1

这是 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

(请注意,如果希望 grub-mkconfig/update-grub 在该卷上运行,则分区环回必须连接到 /dev 下的磁盘环回,并且不是直接复制到图像文件)。

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

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

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

这里我把设备映射放在了客户磁盘映像中,以便您可以生成启动配置文件 grub.cfg:

mount --bind /dev /mnt/dev
chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg

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

现在从运行安装程序主持人,指向客户机安装:

grub-install --no-floppy --grub-mkdevicemap=/mnt/boot/grub/device.map --root-directory=/mnt /dev/loop0

最后,在您的映像上启动 qemu 之前,卸载此处设置的所有内容:

umount /mnt/dev
umount /mnt
losetup -d /dev/loop1
kpartx -v -d /dev/loop0

答案2

非常感谢这些解释。我将您的解决方案集成到我自己的脚本中,并进行了以下修改(翻译成您的符号/变量):

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

这至少在 debian squeeze 上有效。检查“/boot/grub/grub.cfg”是否正确。

答案3

以下是关于如何在 QEMU 磁盘映像中手动安装和启动 GRUB 的快速指南。我还没有使用 grub.cfg 进行下一步,但我认为一旦完成此主要设置,这将非常简单。

假设:

  • 'grub-install --version' 是“grub-install (GRUB) 2.02~beta2-36ubuntu3.2”
  • 'qemu-system-x86_64 --version' 是“QEMU 模拟器版本 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.6),版权所有 (c) 2003-2008 Fabrice Bellard”
  • 当前目录中名为“disk1”的磁盘映像
  • /dev/loop0 有“磁盘标签类型:dos”(即使用 fdisk)
  • /dev/loop0p1 是可启动分区,已使用 ext4 格式化

以下是我如何将 qemu 启动到 GRUB 菜单:

    # losetup -fP disk1
    # ls /dev/loop0*
    /dev/loop0  /dev/loop0p1  /dev/loop0p2  /dev/loop0p3
    # mount /dev/loop0p1 /mnt
    # cat > loop0device.map <<EOF
    (hd0) /dev/loop0
    EOF
    # grub-install --no-floppy --grub-mkdevicemap=loop0device.map \
    --modules="part_msdos" --boot-directory=/mnt /dev/loop0 -v
    # umount /mnt
    # losetup -d /dev/loop0
    # qemu-system-x86_64 -m 512 -curses -hda disk1 -enable-kvm

然后出现 GRUB shell:

                        GNU GRUB  version 2.02~beta2-36ubuntu3.2

       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> ls
    (hd0) (hd0,msdos3) (hd0,msdos2) (hd0,msdos1) (fd0)
    grub>

如果你已经将内核和 RAM 磁盘复制到 /dev/loop0p1,那么你可以启动它:

    grub> linux (hd0,msdos1)/vmlinuz
    grub> initrd (hd0,msdos1)/initrd
    grub> boot

这是默认的 Linux shell(因为在这种情况下没有可用的 /sbin/init)

    BusyBox v1.22.1 (Ubuntu 1:1.22.0-15ubuntu1) built-in shell (ash)
    Enter 'help' for a list of built-in commands.

    (initramfs)

相关内容