{
  mountScript ? "/bin/sh -i;",
  pkgs ? (import <nixpkgs> {}),
  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" "$@"
  '';
}