{ mountScript ? "/bin/sh -i;", pkgs ? (import {}), kernelPackages ? pkgs: pkgs.linuxPackagesFor pkgs.linux_latest, udevPackages ? pkgs: [], kernelModulePackages ? kp: [], firmwarePackages ? pkgs: [pkgs.firmwareLinuxNonfree], tools ? pkgs: [], modprobeConfig ? "", qemu ? pkgs: pkgs.kvm, qemuArgs ? "--enable-kvm -m 2G -bios ${pkgs.OVMF.fd}/FV/OVMF.fd" }: rec { maybeCall = f: arg: if builtins.isFunction f then f arg else f; kernel = (maybeCall kernelPackages pkgs).kernel; bzImage = kernel + "/bzImage"; firmwareSet = pkgs.buildEnv { name = "firmware-set"; paths = maybeCall firmwarePackages pkgs; pathsToLink = ["/lib/firmware"]; }; _kernelPackages = maybeCall kernelPackages pkgs; _kernelModulePackages = [_kernelPackages.kernel] ++ maybeCall kernelModulePackages _kernelPackages; kernelModules = pkgs.aggregateModules _kernelModulePackages; _udevPackages = maybeCall udevPackages pkgs ++ [ pkgs.eudev pkgs.lvm2 pkgs.libinput ]; udevRules = pkgs.runCommand "udev-rules" {} '' mkdir -p "$out"/etc/udev/{rules.d,hwdb.d} for i in ${toString _udevPackages}; do test -d "$i"/etc/udev/rules.d/ && ln -sf "$i"/etc/udev/rules.d/* "$out"/etc/udev/rules.d test -d "$i"/var/lib/udev/rules.d/ && ln -sf "$i"/var/lib/udev/rules.d/* "$out"/etc/udev/rules.d test -d "$i"/etc/udev/hwdb.d/ && ln -sf "$i"/etc/udev/hwdb.d/* "$out"/etc/udev/hwdb.d test -d "$i"/var/lib/udev/hwdb.d/ && ln -sf "$i"/var/lib/udev/hwdb.d/* "$out"/etc/udev/hwdb.d done ${pkgs.eudev}/bin/udevadm hwdb -u -r "$out" ''; modprobeConf = pkgs.writeText "modprobe.conf" '' blacklist evbug '' + modprobeConfig; initTools = pkgs.buildEnv { name = "init-tools"; paths = (with pkgs; [ busybox utillinux kmod bashInteractive lvm2 cryptsetup coreutils gnugrep gnused eudev ]) ++ (maybeCall tools pkgs); ignoreCollisions = true; pathsToLink = ["/"]; extraOutputsToInstall = ["bin" "out"]; }; initScript = '' export PATH="/init-tools/bin" mkdir -p /new-root /proc /sys /dev /run /tmp /etc mount proc -t proc /proc mount sysfs -t sysfs /sys mount run-tmpfs -t tmpfs /run mount dev-tmpfs -t devtmpfs /dev mkdir -p /dev/shm /dev/pts /run/user /run/lock /run/nix mount shm -t tmpfs /dev/shm mount /devpts -t devpts /dev/pts chmod a+rwt /dev/shm echo -n /init-tools/bin/modprobe > /proc/sys/kernel/modprobe echo -n /firmware > /sys/module/firmware_class/parameters/path ln -sfT /proc/mounts /etc/mtab touch /etc/fstab echo "Ready to start udev" udevd & udevadm trigger --action=add udevadm settle vgchange -ay udevadm trigger --action=add udevadm settle ${mountScript} cd /new-root/ udevadm control -e lsmod mkdir -p ./{proc,sys,dev,run} mount --move /proc ./proc mount --move /sys ./sys mount --move /dev ./dev mount --move /run ./run echo "Ready for switch_root" exec switch_root . ./"$targetInit" ''; init = pkgs.writeScript "init" ("#!/bin/sh\n" + initScript); initrd = pkgs.makeInitrd { contents = [ { object = init; symlink = "/init";} { object = kernelModules + "/lib/modules"; symlink = "/lib/modules"; } { object = initTools; symlink = "/init-tools"; } { object = pkgs.busybox; symlink = "/busybox"; } { object = initTools + "/bin/bash"; symlink = "/bin/sh"; } { object = initTools + "/bin/env"; symlink = "/usr/bin/env"; } { object = firmwareSet + "/lib/firmware"; symlink = "/firmware"; } { object = modprobeConf; symlink = "/etc/modprobe.d/modprobe.conf"; } { object = udevRules + "/etc/udev"; symlink = "/etc/udev"; } ]; }; qemuScript = pkgs.writeScript "qemu-script" ''#! /bin/sh ${maybeCall qemu pkgs}/bin/qemu-system-$(echo "${builtins.currentSystem}" | sed -e "s/-.*//") \ ${qemuArgs} -kernel ${bzImage} -initrd ${initrd}/initrd "$@" ''; qemuScriptTextMode = pkgs.writeScript "qemu-script" ''#! /bin/sh ${maybeCall qemu pkgs}/bin/qemu-system-$(echo "${builtins.currentSystem}" | sed -e "s/-.*//") \ ${qemuArgs} -kernel ${bzImage} -initrd ${initrd}/initrd \ -nographic -append "console=ttyS0" "$@" ''; }