我做了以下事情:
- 使用 dd 创建了一个空的 .img 文件
- 使用 losetup 将其与 /dev/loop0 关联
- 使用 fdisk 在其中创建一个分区
- 使用 mke2fs 格式化该分区
- 将自定义的 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)