From 9e12db91de503094f41b69e9a21838c3569fbc3a Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Mon, 15 Jul 2019 17:36:09 +0300 Subject: [PATCH 1/5] ipxe: support renaming targets and add several This allows to build several targets with conflicting names. UEFI version of USB image is now built, and so is option ROM. --- pkgs/tools/misc/ipxe/default.nix | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/pkgs/tools/misc/ipxe/default.nix b/pkgs/tools/misc/ipxe/default.nix index a9cddcc5ff81..c8668a5ad721 100644 --- a/pkgs/tools/misc/ipxe/default.nix +++ b/pkgs/tools/misc/ipxe/default.nix @@ -1,23 +1,28 @@ -{ stdenv, lib, fetchgit, perl, cdrkit, syslinux, xz, openssl, gnu-efi +{ stdenv, lib, fetchgit, perl, cdrkit, syslinux, xz, openssl, gnu-efi, mtools , embedScript ? null +, additionalTargets ? {} }: let date = "20190318"; rev = "ebf2eaf515e46abd43bc798e7e4ba77bfe529218"; - targets = (lib.optional stdenv.isx86_64 "bin-x86_64-efi/ipxe.efi") ++ [ - "bin/ipxe.dsk" - "bin/ipxe.usb" - "bin/ipxe.iso" - "bin/ipxe.lkrn" - "bin/undionly.kpxe" - ]; + targets = additionalTargets // lib.optionalAttrs stdenv.isx86_64 { + "bin-x86_64-efi/ipxe.efi" = null; + "bin-x86_64-efi/ipxe.efirom" = null; + "bin-x86_64-efi/ipxe.usb" = "ipxe-efi.usb"; + } // { + "bin/ipxe.dsk" = null; + "bin/ipxe.usb" = null; + "bin/ipxe.iso" = null; + "bin/ipxe.lkrn" = null; + "bin/undionly.kpxe" = null; + }; in stdenv.mkDerivation { name = "ipxe-${date}-${builtins.substring 0 7 rev}"; - buildInputs = [ perl cdrkit syslinux xz openssl gnu-efi ]; + nativeBuildInputs = [ perl cdrkit syslinux xz openssl gnu-efi mtools ]; src = fetchgit { url = https://git.ipxe.org/ipxe.git; @@ -49,11 +54,14 @@ stdenv.mkDerivation { preBuild = "cd src"; - buildFlags = targets; + buildFlags = lib.attrNames targets; installPhase = '' mkdir -p $out - cp ${lib.concatStringsSep " " targets} $out + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (from: to: + if to == null + then "cp -v ${from} $out" + else "cp -v ${from} $out/${to}") targets)} # Some PXE constellations especially with dnsmasq are looking for the file with .0 ending # let's provide it as a symlink to be compatible in this case. @@ -67,6 +75,6 @@ stdenv.mkDerivation { homepage = http://ipxe.org/; license = licenses.gpl2; maintainers = with maintainers; [ ehmry ]; - platforms = platforms.all; + platforms = [ "x86_64-linux" "i686-linux" ]; }; } From 6152007747ea5441c0f3e73c2d4ad0977a6079c1 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Mon, 15 Jul 2019 17:37:30 +0300 Subject: [PATCH 2/5] ipxe: add imgtrust and ping imgtrust is needed to run netboot.xyz scripts. ping is useful for testing network settings. Also add HTTP option for clarity (it's already being built). --- pkgs/tools/misc/ipxe/default.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/tools/misc/ipxe/default.nix b/pkgs/tools/misc/ipxe/default.nix index c8668a5ad721..219c03f263c7 100644 --- a/pkgs/tools/misc/ipxe/default.nix +++ b/pkgs/tools/misc/ipxe/default.nix @@ -42,7 +42,12 @@ stdenv.mkDerivation { ] ++ lib.optional (embedScript != null) "EMBED=${embedScript}"; - enabledOptions = [ "DOWNLOAD_PROTO_HTTPS" ]; + enabledOptions = [ + "PING_CMD" + "IMAGE_TRUST_CMD" + "DOWNLOAD_PROTO_HTTP" + "DOWNLOAD_PROTO_HTTPS" + ]; configurePhase = '' runHook preConfigure From e4837acf21f891f7f28196adcb94345dd8fec677 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Mon, 15 Jul 2019 17:44:22 +0300 Subject: [PATCH 3/5] nixos netboot: explicitly specify initrd Needed for iPXE on UEFI, see http://forum.ipxe.org/archive/index.php/thread-7589.html --- nixos/modules/installer/netboot/netboot.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix index cdfba5ab9e31..f9b8d95c684d 100644 --- a/nixos/modules/installer/netboot/netboot.nix +++ b/nixos/modules/installer/netboot/netboot.nix @@ -84,7 +84,7 @@ with lib; system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" '' #!ipxe - kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} + kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} initrd initrd boot ''; From 81d35a9d7ea9dab5949af5e8e2d2fcb6315b1b12 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Mon, 15 Jul 2019 18:42:36 +0300 Subject: [PATCH 4/5] nixos-test-driver: support netRomFile Needed for UEFI PXE netboot testing. --- nixos/lib/test-driver/Machine.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm index 006da889671e..5e4c14e749fd 100644 --- a/nixos/lib/test-driver/Machine.pm +++ b/nixos/lib/test-driver/Machine.pm @@ -31,9 +31,12 @@ sub new { if (!$startCommand) { # !!! merge with qemu-vm.nix. + my $netArgs = ""; + $netArgs .= ",romfile=$args->{netRomFile}" + if defined $args->{netRomFile}; $startCommand = "qemu-kvm -m 384 " . - "-net nic,model=virtio \$QEMU_OPTS "; + "-device virtio-net-pci,netdev=net0${netArgs} \$QEMU_OPTS "; if (defined $args->{hda}) { if ($args->{hdaInterface} eq "scsi") { From a2e8be9fc32368a476408d4cb1b073f755b6492c Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Mon, 15 Jul 2019 18:56:53 +0300 Subject: [PATCH 5/5] boot tests: add UEFI PXE netboot testing Generalize netboot testing and add tests for UEFI PXE netboot. --- nixos/tests/boot.nix | 106 +++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix index c9bb1e77c6d0..12a34d4401f6 100644 --- a/nixos/tests/boot.nix +++ b/nixos/tests/boot.nix @@ -17,46 +17,33 @@ let ]; }).config.system.build.isoImage; - makeBootTest = name: machineConfig: - makeTest { - inherit iso; - name = "boot-" + name; - nodes = { }; - testScript = - '' - my $machine = createMachine({ ${machineConfig}, qemuFlags => '-m 768' }); - $machine->start; - $machine->waitForUnit("multi-user.target"); - $machine->succeed("nix verify -r --no-trust /run/current-system"); + perlAttrs = params: "{ ${concatStringsSep "," (mapAttrsToList (name: param: "${name} => '${toString param}'") params)} }"; - # Test whether the channel got installed correctly. - $machine->succeed("nix-instantiate --dry-run '' -A hello"); - $machine->succeed("nix-env --dry-run -iA nixos.procps"); + makeBootTest = name: extraConfig: + let + machineConfig = perlAttrs ({ qemuFlags = "-m 768"; } // extraConfig); + in + makeTest { + inherit iso; + name = "boot-" + name; + nodes = { }; + testScript = + '' + my $machine = createMachine(${machineConfig}); + $machine->start; + $machine->waitForUnit("multi-user.target"); + $machine->succeed("nix verify -r --no-trust /run/current-system"); - $machine->shutdown; - ''; - }; -in { + # Test whether the channel got installed correctly. + $machine->succeed("nix-instantiate --dry-run '' -A hello"); + $machine->succeed("nix-env --dry-run -iA nixos.procps"); - biosCdrom = makeBootTest "bios-cdrom" '' - cdrom => glob("${iso}/iso/*.iso") - ''; + $machine->shutdown; + ''; + }; - biosUsb = makeBootTest "bios-usb" '' - usb => glob("${iso}/iso/*.iso") - ''; - - uefiCdrom = makeBootTest "uefi-cdrom" '' - cdrom => glob("${iso}/iso/*.iso"), - bios => '${pkgs.OVMF.fd}/FV/OVMF.fd' - ''; - - uefiUsb = makeBootTest "uefi-usb" '' - usb => glob("${iso}/iso/*.iso"), - bios => '${pkgs.OVMF.fd}/FV/OVMF.fd' - ''; - - netboot = let + makeNetbootTest = name: extraConfig: + let config = (import ../lib/eval-config.nix { inherit system; modules = @@ -65,35 +52,54 @@ in { { key = "serial"; } ]; }).config; - ipxeScriptDir = pkgs.writeTextFile { - name = "ipxeScriptDir"; - text = '' - #!ipxe - dhcp - kernel bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0 - initrd initrd - boot - ''; - destination = "/boot.ipxe"; - }; ipxeBootDir = pkgs.symlinkJoin { name = "ipxeBootDir"; paths = [ config.system.build.netbootRamdisk config.system.build.kernel - ipxeScriptDir + config.system.build.netbootIpxeScript ]; }; + machineConfig = perlAttrs ({ + qemuFlags = "-boot order=n -netdev user,id=net0,tftp=${ipxeBootDir}/,bootfile=netboot.ipxe -m 2000"; + } // extraConfig); in makeTest { - name = "boot-netboot"; + name = "boot-netboot-" + name; nodes = { }; testScript = '' - my $machine = createMachine({ qemuFlags => '-boot order=n -net nic,model=e1000 -net user,tftp=${ipxeBootDir}/,bootfile=boot.ipxe -m 2000M' }); + my $machine = createMachine(${machineConfig}); $machine->start; $machine->waitForUnit("multi-user.target"); $machine->shutdown; ''; }; +in { + + biosCdrom = makeBootTest "bios-cdrom" { + cdrom = ''glob("${iso}/iso/*.iso")''; + }; + + biosUsb = makeBootTest "bios-usb" { + usb = ''glob("${iso}/iso/*.iso")''; + }; + + uefiCdrom = makeBootTest "uefi-cdrom" { + cdrom = ''glob("${iso}/iso/*.iso"''; + bios = ''"${pkgs.OVMF.fd}/FV/OVMF.fd"''; + }; + + uefiUsb = makeBootTest "uefi-usb" { + usb = ''glob("${iso}/iso/*.iso")''; + bios = ''"${pkgs.OVMF.fd}/FV/OVMF.fd"''; + }; + + biosNetboot = makeNetbootTest "bios" {}; + + uefiNetboot = makeNetbootTest "uefi" { + bios = ''"${pkgs.OVMF.fd}/FV/OVMF.fd"''; + # Custom ROM is needed for EFI PXE boot. I failed to understand exactly why, because QEMU should still use iPXE for EFI. + netRomFile = ''"${pkgs.ipxe}/ipxe.efirom"''; + }; }