Merge pull request #64815 from abbradar/ipxe-efi

IPXE EFI netboot fix
This commit is contained in:
Nikolay Amiantov 2019-07-15 21:21:29 +03:00 committed by GitHub
commit b392c5ab4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 65 deletions

View file

@ -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") {

View file

@ -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
'';

View file

@ -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 '<nixpkgs>' -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 '<nixpkgs>' -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"'';
};
}

View file

@ -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" ];
};
}