From db42eeba6b191e01356d4537546a9ca33699ad61 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 13 Feb 2024 16:35:33 -0500 Subject: [PATCH] nixos/iso-image: Support systemd initrd --- nixos/modules/installer/cd-dvd/iso-image.nix | 80 +++++++++++++++----- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 47397b99d922..040d9bb02ea5 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -4,6 +4,7 @@ { config, lib, + utils, pkgs, ... }: @@ -785,7 +786,11 @@ in # specified on the kernel command line, created in the stage 1 # init script. "/iso" = lib.mkImageMediaOverride { - device = "/dev/root"; + device = + if config.boot.initrd.systemd.enable then + "/dev/disk/by-label/${config.isoImage.volumeID}" + else + "/dev/root"; neededForBoot = true; noCheck = true; }; @@ -794,7 +799,7 @@ in # image) to make this a live CD. "/nix/.ro-store" = lib.mkImageMediaOverride { fsType = "squashfs"; - device = "/iso/nix-store.squashfs"; + device = "${lib.optionalString config.boot.initrd.systemd.enable "/sysroot"}/iso/nix-store.squashfs"; options = [ "loop" ] @@ -809,18 +814,11 @@ in }; "/nix/store" = lib.mkImageMediaOverride { - fsType = "overlay"; - device = "overlay"; - options = [ - "lowerdir=/nix/.ro-store" - "upperdir=/nix/.rw-store/store" - "workdir=/nix/.rw-store/work" - ]; - depends = [ - "/nix/.ro-store" - "/nix/.rw-store/store" - "/nix/.rw-store/work" - ]; + overlay = { + lowerdir = [ "/nix/.ro-store" ]; + upperdir = "/nix/.rw-store/store"; + workdir = "/nix/.rw-store/work"; + }; }; }; @@ -882,9 +880,9 @@ in # UUID of the USB stick. It would be nicer to write # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't # recognise that. - boot.kernelParams = [ - "root=LABEL=${config.isoImage.volumeID}" + boot.kernelParams = lib.optionals (!config.boot.initrd.systemd.enable) [ "boot.shell_on_fail" + "root=LABEL=${config.isoImage.volumeID}" ]; fileSystems = config.lib.isoFileSystems; @@ -901,6 +899,44 @@ in "overlay" ]; + boot.initrd.systemd = lib.mkIf config.boot.initrd.systemd.enable { + emergencyAccess = true; + + # Most of util-linux is not included by default. + initrdBin = [ config.boot.initrd.systemd.package.util-linux ]; + services.copytoram = { + description = "Copy ISO contents to RAM"; + requiredBy = [ "initrd.target" ]; + before = [ + "${utils.escapeSystemdPath "/sysroot/nix/.ro-store"}.mount" + "initrd-switch-root.target" + ]; + unitConfig = { + RequiresMountsFor = "/sysroot/iso"; + ConditionKernelCommandLine = "copytoram"; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + path = [ + pkgs.coreutils + config.boot.initrd.systemd.package.util-linux + ]; + script = '' + device=$(findmnt -n -o SOURCE --target /sysroot/iso) + fsSize=$(blockdev --getsize64 "$device" || stat -Lc '%s' "$device") + mkdir -p /tmp-iso + mount --bind --make-private /sysroot/iso /tmp-iso + umount /sysroot/iso + mount -t tmpfs -o size="$fsSize" tmpfs /sysroot/iso + cp -r /tmp-iso/* /sysroot/iso/ + umount /tmp-iso + rm -r /tmp-iso + ''; + }; + }; + # Closures to be copied to the Nix store on the CD, namely the init # script and the top-level system configuration directory. isoImage.storeContents = [ @@ -958,15 +994,19 @@ in source = "${efiDir}/EFI"; target = "/EFI"; } - { - source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/BOOT/grub.cfg") + "/grub"; - target = "/boot/grub"; - } { source = config.isoImage.efiSplashImage; target = "/EFI/BOOT/efi-background.png"; } ] + ++ lib.optionals (config.isoImage.makeEfiBootable && !config.boot.initrd.systemd.enable) [ + # http://www.supergrubdisk.org/wiki/Loopback.cfg + # This feature will be removed, and thus is not supported by systemd initrd + { + source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/BOOT/grub.cfg") + "/grub"; + target = "/boot/grub"; + } + ] ++ lib.optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [ { source = "${pkgs.memtest86plus}/memtest.bin";