Booting qemu/kvm directly from a file system

biosbootgrub2qemu

Having used Xen and its pygrub for a while, I'm now trying to do something similar with KVM/qemu.

Basically, I have a LVM logical volume (though that could as well be a file) that contains the root filesystem of a Linux distribution (no partitioning, just FS directly on disk) which also contains a /boot/grub/grub.cfg, and I'd like to be able to boot that.

I was under the impression that the grub-firmware-qemu package on Debian/Ubuntu was intended for that, but I have not managed to make it work. AFAICT, the grub.bin image contains a hardcoded memdisk with a grub.cfg file with a few menu options (like search for a multiboot.img or search for a grub.cfg), but all I get when running kvm -bios grub.bin is an "incompatible license" error message. And I'm not too sure how to generate a different grub.bin with a different grub.cfg (one that would only do configfile (hd0)/boot/grub/grub.cfg).

Of course, I could create a floppy or cdrom or disk image with a minimal grub configuration that does just that but I've got the feeling that there should be a cleaner/canonical way to do it and my research has brought back very little so far.

I suppose one could use qemu's -kernel option as well, but again, I don't know how to generate a grub.img for that. (using a grub.img generated with grub-mkimage -O i386-pc -o grub.img -c =(echo 'configfile (hd0)/boot/grub/grub.cfg') /usr/lib/grub/i386-pc/*.mod brings up the same "incompatible license" error message again).

That's on debian with version 1.99-23 of the grub packages and 1.1.2+dfsg-2 of kvm/qemu.

So, in short, how should I go about creating either a grub.bin (to be used with kvm -bios) or a grub.img (to be used with kvm -kernel) to have kvm boot a grub image that is able to parse the /boot/grub/grub.cfg on the virtual disk?

Best Answer

As it happens, it looks like a bug in debian's package of grub.

The -kernel grub.img approach works if I only include the grub modules I need upon grub-mkimage.

The -bios grub.bin works with the newer grub package from experimental (2.00-7). However, the grub.bin that comes with it is not very useful.

It comes with a memdisk that comes with the grub.cfg. It would have been better to use that memdisk to hold the modules and the grub.cfg be specified with the -c option of grub-mkimage. For instance, one of the menu entry looks for /boot/grub/grub.cfg and finds itself in the memdisk as a result. Also, the debian package doesn't include the qemu grub modules, so you can't build a different grub.bin (though you can binary edit the file to change the grub.cfg) unless you do it from the source package.

The -bios grub.bin approach sounds like the cleanest approach to me, but I'll use the -kernel or floppy approach until the debian package is fixed.

EDIT: well, the ata.mod grub module to read emulated IDE drives is a lot slower than using biosdisk.mod in combination with seabios (the default bios when not using -bios grub.bin). Also, it seems that grub firmware doesn't support virtio-blk nor virtio-scsi disks, so kvm -bios grub.bin is not going to be an option for me.

In case anyone wants to goes down that path, I'm now using (zsh syntax):

grub-mkimage -O i386-pc -c =(print -l serial 'terminal_input serial' \
  'terminal_output serial' 'set prefix=(hd0)/boot/grub' '. grub.cfg') -o grub.img \
  at_keyboard configfile biosdisk ext2 linux test serial halt minicmd terminal cat

And -kernel grub.img -nographic passed to kvm. That is to boot Linux VMs with no graphics (only a serial interface, so make sure that the VM's grub is configured to use serial (or at least not configured to use graphics), that the kernel console goes to ttyS0 and that you run a getty on there). It can easily be adapted to work for VGA consoles as well.

Related Question