about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJames Cook <jcook@cs.berkeley.edu>2015-02-16 13:13:26 -0800
committerJames Cook <jcook@cs.berkeley.edu>2015-02-16 13:13:26 -0800
commit6daf9aa922294e9fdb7509c157f3032aabe219f9 (patch)
tree731fe55f5cf1b7438e8e6b17307e46b5a1a31c51
parent6aa43976a7bead139ac522623b9dc1251246fe9c (diff)
parent80afabd5b5d034d41792b7cf99d3ca87ae34596a (diff)
downloadnixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.tar
nixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.tar.gz
nixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.tar.bz2
nixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.tar.lz
nixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.tar.xz
nixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.tar.zst
nixlib-6daf9aa922294e9fdb7509c157f3032aabe219f9.zip
Merge pull request #5995 from ts468/qemu-vm
Update QEMU Nixos Virtual Machine
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix89
-rw-r--r--pkgs/applications/virtualization/OVMF/default.nix30
-rw-r--r--pkgs/applications/virtualization/seabios/default.nix44
-rw-r--r--pkgs/top-level/all-packages.nix6
4 files changed, 145 insertions, 24 deletions
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";
diff --git a/pkgs/applications/virtualization/OVMF/default.nix b/pkgs/applications/virtualization/OVMF/default.nix
index 388248c5aa86..e29ab11947fd 100644
--- a/pkgs/applications/virtualization/OVMF/default.nix
+++ b/pkgs/applications/virtualization/OVMF/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, edk2, nasm, iasl }:
+{ stdenv, edk2, nasm, iasl, seabios, openssl, secureBoot ? false }:
 
 let
 
@@ -14,14 +14,36 @@ in
 stdenv.mkDerivation (edk2.setup "OvmfPkg/OvmfPkg${targetArch}.dsc" {
   name = "OVMF-2014-12-10";
 
-  buildInputs = [nasm iasl];
+  # TODO: properly include openssl for secureBoot
+  buildInputs = [nasm iasl] ++ stdenv.lib.optionals (secureBoot == true) [ openssl ];
+
   unpackPhase = ''
     for file in \
-      "${edk2.src}"/{OvmfPkg,UefiCpuPkg,MdeModulePkg,IntelFrameworkModulePkg,PcAtChipsetPkg,FatBinPkg,EdkShellBinPkg,MdePkg,ShellPkg,OptionRomPkg,IntelFrameworkPkg};
+      "${edk2.src}"/{UefiCpuPkg,MdeModulePkg,IntelFrameworkModulePkg,PcAtChipsetPkg,FatBinPkg,EdkShellBinPkg,MdePkg,ShellPkg,OptionRomPkg,IntelFrameworkPkg};
     do
       ln -sv "$file" .
     done
-  '';
+
+    ${if (seabios == false) then ''
+        ln -sv ${edk2.src}/OvmfPkg .
+      '' else ''
+        cp -r ${edk2.src}/OvmfPkg .
+        chmod +w OvmfPkg/Csm/Csm16
+        cp ${seabios}/Csm16.bin OvmfPkg/Csm/Csm16/Csm16.bin
+      ''}
+
+    ${if (secureBoot == true) then ''
+        ln -sv ${edk2.src}/SecurityPkg .
+        ln -sv ${edk2.src}/CryptoPkg .
+      '' else ''
+      ''}
+    '';
+
+  buildPhase = if (seabios == false) then ''
+      build ${if secureBoot then "-DSECURE_BOOT_ENABLE=TRUE" else ""}
+    '' else ''
+      build -D CSM_ENABLE -D FD_SIZE_2MB ${if secureBoot then "-DSECURE_BOOT_ENABLE=TRUE" else ""}
+    '';
 
   meta = {
     description = "Sample UEFI firmware for QEMU and KVM";
diff --git a/pkgs/applications/virtualization/seabios/default.nix b/pkgs/applications/virtualization/seabios/default.nix
new file mode 100644
index 000000000000..8e6a7fcb0d26
--- /dev/null
+++ b/pkgs/applications/virtualization/seabios/default.nix
@@ -0,0 +1,44 @@
+{ stdenv, fetchurl, iasl, python }:
+
+stdenv.mkDerivation rec {
+
+  name = "seabios-${version}";
+  version = "1.7.5.2";
+
+  src = fetchurl {
+    url = "http://code.coreboot.org/p/seabios/downloads/get/${name}.tar.gz";
+    sha256 = "1syd3gi5gq0gj2pjvmdis64xc3j1xf0jgy49ngymap0pdpm0cmh0";
+  };
+
+  buildInputs = [ iasl python ];
+
+  configurePhase = ''
+    # build SeaBIOS for CSM
+    cat > .config << EOF
+    CONFIG_CSM=y
+    CONFIG_QEMU_HARDWARE=y
+    CONFIG_PERMIT_UNALIGNED_PCIROM=y
+    EOF
+
+    make olddefconfig
+    '';
+
+  installPhase = ''
+    mkdir $out
+    cp out/Csm16.bin $out/Csm16.bin
+    '';
+
+  meta = with stdenv.lib; {
+    description = "Open source implementation of a 16bit X86 BIOS";
+    longDescription = ''
+      SeaBIOS is an open source implementation of a 16bit X86 BIOS.
+      It can run in an emulator or it can run natively on X86 hardware with the use of coreboot.
+      SeaBIOS is the default BIOS for QEMU and KVM.
+    '';
+    homepage = http://www.seabios.org;
+    license = licenses.lgpl3;
+    maintainers = [ maintainers.tstrobel ];
+    platforms = platforms.linux;
+  };
+}
+
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 19e3eb8b6b9e..629824b8205c 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -8133,7 +8133,11 @@ let
 
   oracleXE = callPackage ../servers/sql/oracle-xe { };
 
-  OVMF = callPackage ../applications/virtualization/OVMF { };
+  OVMF = callPackage ../applications/virtualization/OVMF { seabios=false; openssl=null; };
+  OVMF-CSM = callPackage ../applications/virtualization/OVMF { openssl=null; };
+  #WIP: OVMF-secureBoot = callPackage ../applications/virtualization/OVMF { seabios=false; secureBoot=true; };
+
+  seabios = callPackage ../applications/virtualization/seabios { };
 
   pgpool92 = callPackage ../servers/sql/pgpool/default.nix {
     postgresql = postgresql92;