diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm index 006da889671..5e4c14e749f 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") { diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix index cdfba5ab9e3..f9b8d95c684 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 ''; diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix index c9bb1e77c6d..12a34d4401f 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"''; + }; } diff --git a/pkgs/tools/misc/ipxe/default.nix b/pkgs/tools/misc/ipxe/default.nix index a9cddcc5ff8..219c03f263c 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; @@ -37,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 @@ -49,11 +59,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 +80,6 @@ stdenv.mkDerivation { homepage = http://ipxe.org/; license = licenses.gpl2; maintainers = with maintainers; [ ehmry ]; - platforms = platforms.all; + platforms = [ "x86_64-linux" "i686-linux" ]; }; }