From 80afabd5b5d034d41792b7cf99d3ca87ae34596a Mon Sep 17 00:00:00 2001 From: Thomas Strobel Date: Mon, 26 Jan 2015 21:13:31 +0100 Subject: Update QEMU Nixos Virtual Machine The Nixos Qemu VM that are used for VM tests can now start without boot menu even when using a bootloader. The Nixos Qemu VM with bootloader can emulate a EFI boot now. --- nixos/modules/virtualisation/qemu-vm.nix | 89 +++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 19 deletions(-) (limited to 'nixos/modules') diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 33c64cc890e0..a5a133dfa5dc 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -36,13 +36,28 @@ let ${toString config.virtualisation.diskSize}M || exit 1 fi - # Create a directory for exchanging data with the VM. + # Create a directory for storing temporary data of the running VM. if [ -z "$TMPDIR" -o -z "$USE_TMPDIR" ]; then TMPDIR=$(mktemp -d nix-vm.XXXXXXXXXX --tmpdir) fi - cd $TMPDIR + # Create a directory for exchanging data with the VM. mkdir -p $TMPDIR/xchg + ${if cfg.useBootLoader then '' + # Create a writable copy/snapshot of the boot disk + # A writable boot disk can be booted from automatically + ${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 -b ${bootDisk}/disk.img $TMPDIR/disk.img || exit 1 + + ${if cfg.useEFIBoot then '' + # VM needs a writable flash BIOS + cp ${bootDisk}/bios.bin $TMPDIR || exit 1 + chmod 0644 $TMPDIR/bios.bin || exit 1 + '' else '' + ''} + '' else '' + ''} + + cd $TMPDIR idx=2 extraDisks="" ${flip concatMapStrings cfg.emptyDiskImages (size: '' @@ -52,7 +67,6 @@ let '')} # Start QEMU. - # "-boot menu=on" is there, because I don't know how to make qemu boot from 2nd hd. exec ${pkgs.qemu_kvm}/bin/qemu-kvm \ -name ${vmName} \ -m ${toString config.virtualisation.memorySize} \ @@ -63,8 +77,11 @@ let -virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \ ${if cfg.useBootLoader then '' -drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \ - -drive index=1,id=drive2,file=${bootDisk}/disk.img,if=virtio,readonly \ - -boot menu=on \ + -drive index=1,id=drive2,file=$TMPDIR/disk.img,media=disk \ + ${if cfg.useEFIBoot then '' + -pflash $TMPDIR/bios.bin \ + '' else '' + ''} '' else '' -drive file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \ -kernel ${config.system.build.toplevel}/kernel \ @@ -74,7 +91,8 @@ let $extraDisks \ ${qemuGraphics} \ ${toString config.virtualisation.qemu.options} \ - $QEMU_OPTS + $QEMU_OPTS \ + $@ ''; @@ -98,23 +116,44 @@ let '' mkdir $out diskImage=$out/disk.img - ${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 $diskImage "32M" + bootFlash=$out/bios.bin + ${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 $diskImage "40M" + ${if cfg.useEFIBoot then '' + cp ${pkgs.OVMF-CSM}/FV/OVMF.fd $bootFlash + chmod 0644 $bootFlash + '' else '' + ''} ''; buildInputs = [ pkgs.utillinux ]; + QEMU_OPTS = if cfg.useEFIBoot + then "-pflash $out/bios.bin -nographic -serial pty" + else "-nographic -serial pty"; } '' - # Create a single /boot partition. - ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos - ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s - . /sys/class/block/vda1/uevent - mknod /dev/vda1 b $MAJOR $MINOR + # Create a /boot EFI partition with 40M + ${pkgs.gptfdisk}/sbin/sgdisk -G /dev/vda + ${pkgs.gptfdisk}/sbin/sgdisk -a 1 -n 1:34:2047 -c 1:"BIOS Boot Partition" -t 1:ef02 /dev/vda + ${pkgs.gptfdisk}/sbin/sgdisk -a 512 -N 2 -c 2:"EFI System" -t 2:ef00 /dev/vda + ${pkgs.gptfdisk}/sbin/sgdisk -A 1:set:1 /dev/vda + ${pkgs.gptfdisk}/sbin/sgdisk -A 2:set:2 /dev/vda + ${pkgs.gptfdisk}/sbin/sgdisk -h 2 /dev/vda + ${pkgs.gptfdisk}/sbin/sgdisk -C /dev/vda + ${pkgs.utillinux}/bin/sfdisk /dev/vda -A 2 + . /sys/class/block/vda2/uevent + mknod /dev/vda2 b $MAJOR $MINOR . /sys/class/block/vda/uevent - ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L boot /dev/vda1 - ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 - - # Mount /boot. + ${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2 + export MTOOLS_SKIP_CHECK=1 + ${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot + + # Mount /boot; load necessary modules first. + ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_cp437.ko || true + ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_iso8859-1.ko || true + ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/fat.ko || true + ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/vfat.ko || true + ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/efivarfs/efivarfs.ko || true mkdir /boot - mount /dev/vda1 /boot + mount /dev/vda2 /boot # This is needed for GRUB 0.97, which doesn't know about virtio devices. mkdir /boot/grub @@ -287,6 +326,17 @@ in ''; }; + virtualisation.useEFIBoot = + mkOption { + default = false; + description = + '' + If enabled, the virtual machine will provide a EFI boot + manager. + useEFIBoot is ignored if useBootLoader == false. + ''; + }; + }; config = { @@ -379,8 +429,8 @@ in }; } // optionalAttrs cfg.useBootLoader { "/boot" = - { device = "/dev/disk/by-label/boot"; - fsType = "ext4"; + { device = "/dev/vdb2"; + fsType = "vfat"; options = "ro"; noCheck = true; # fsck fails on a r/o filesystem }; @@ -413,6 +463,7 @@ in # Wireless won't work in the VM. networking.wireless.enable = mkVMOverride false; + networking.connman.enable = mkVMOverride false; # Speed up booting by not waiting for ARP. networking.dhcpcd.extraConfig = "noarp"; -- cgit 1.4.1