summary refs log tree commit diff
path: root/nixos/modules/system/boot/loader
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/system/boot/loader')
-rw-r--r--nixos/modules/system/boot/loader/efi.nix20
-rw-r--r--nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh106
-rw-r--r--nixos/modules/system/boot/loader/generations-dir/generations-dir.nix62
-rw-r--r--nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix82
-rw-r--r--nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix8
-rw-r--r--nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh157
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix848
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl780
-rw-r--r--nixos/modules/system/boot/loader/grub/ipxe.nix64
-rw-r--r--nixos/modules/system/boot/loader/grub/memtest.nix116
-rw-r--r--nixos/modules/system/boot/loader/init-script/init-script-builder.sh92
-rw-r--r--nixos/modules/system/boot/loader/init-script/init-script.nix51
-rw-r--r--nixos/modules/system/boot/loader/loader.nix20
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix9
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh143
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix105
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/uboot-builder.nix37
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh38
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py305
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix303
20 files changed, 0 insertions, 3346 deletions
diff --git a/nixos/modules/system/boot/loader/efi.nix b/nixos/modules/system/boot/loader/efi.nix
deleted file mode 100644
index 6043c904c45..00000000000
--- a/nixos/modules/system/boot/loader/efi.nix
+++ /dev/null
@@ -1,20 +0,0 @@
-{ lib, ... }:
-
-with lib;
-
-{
-  options.boot.loader.efi = {
-
-    canTouchEfiVariables = mkOption {
-      default = false;
-      type = types.bool;
-      description = "Whether the installation process is allowed to modify EFI boot variables.";
-    };
-
-    efiSysMountPoint = mkOption {
-      default = "/boot";
-      type = types.str;
-      description = "Where the EFI System Partition is mounted.";
-    };
-  };
-}
diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh b/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh
deleted file mode 100644
index 8ae23dc988c..00000000000
--- a/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh
+++ /dev/null
@@ -1,106 +0,0 @@
-#! @bash@/bin/sh -e
-
-shopt -s nullglob
-
-export PATH=/empty
-for i in @path@; do PATH=$PATH:$i/bin; done
-
-default=$1
-if test -z "$1"; then
-    echo "Syntax: generations-dir-builder.sh <DEFAULT-CONFIG>"
-    exit 1
-fi
-
-echo "updating the boot generations directory..."
-
-mkdir -p /boot
-
-rm -Rf /boot/system* || true
-
-target=/boot/grub/menu.lst
-tmp=$target.tmp
-
-# Convert a path to a file in the Nix store such as
-# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
-cleanName() {
-    local path="$1"
-    echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g'
-}
-
-# Copy a file from the Nix store to /boot/kernels.
-declare -A filesCopied
-
-copyToKernelsDir() {
-    local src="$1"
-    local dst="/boot/kernels/$(cleanName $src)"
-    # Don't copy the file if $dst already exists.  This means that we
-    # have to create $dst atomically to prevent partially copied
-    # kernels or initrd if this script is ever interrupted.
-    if ! test -e $dst; then
-        local dstTmp=$dst.tmp.$$
-        cp $src $dstTmp
-        mv $dstTmp $dst
-    fi
-    filesCopied[$dst]=1
-    result=$dst
-}
-
-
-# Copy its kernel and initrd to /boot/kernels.
-addEntry() {
-    local path="$1"
-    local generation="$2"
-    local outdir=/boot/system-$generation
-
-    if ! test -e $path/kernel -a -e $path/initrd; then
-        return
-    fi
-
-    local kernel=$(readlink -f $path/kernel)
-    local initrd=$(readlink -f $path/initrd)
-
-    if test -n "@copyKernels@"; then
-        copyToKernelsDir $kernel; kernel=$result
-        copyToKernelsDir $initrd; initrd=$result
-    fi
-
-    mkdir -p $outdir
-    ln -sf $(readlink -f $path) $outdir/system
-    ln -sf $(readlink -f $path/init) $outdir/init
-    ln -sf $initrd $outdir/initrd
-    ln -sf $kernel $outdir/kernel
-
-    if test $(readlink -f "$path") = "$default"; then
-      cp "$kernel" /boot/nixos-kernel
-      cp "$initrd" /boot/nixos-initrd
-      cp "$(readlink -f "$path/init")" /boot/nixos-init
-
-      mkdir -p /boot/default
-      # ln -sfT: overrides target even if it exists.
-      ln -sfT $(readlink -f $path) /boot/default/system
-      ln -sfT $(readlink -f $path/init) /boot/default/init
-      ln -sfT $initrd /boot/default/initrd
-      ln -sfT $kernel /boot/default/kernel
-    fi
-}
-
-if test -n "@copyKernels@"; then
-    mkdir -p /boot/kernels
-fi
-
-# Add all generations of the system profile to the menu, in reverse
-# (most recent to least recent) order.
-for generation in $(
-    (cd /nix/var/nix/profiles && ls -d system-*-link) \
-    | sed 's/system-\([0-9]\+\)-link/\1/' \
-    | sort -n -r); do
-    link=/nix/var/nix/profiles/system-$generation-link
-    addEntry $link $generation
-done
-
-# Remove obsolete files from /boot/kernels.
-for fn in /boot/kernels/*; do
-    if ! test "${filesCopied[$fn]}" = 1; then
-        rm -vf -- "$fn"
-    fi
-done
diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
deleted file mode 100644
index 1437ab38770..00000000000
--- a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
+++ /dev/null
@@ -1,62 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  generationsDirBuilder = pkgs.substituteAll {
-    src = ./generations-dir-builder.sh;
-    isExecutable = true;
-    inherit (pkgs) bash;
-    path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
-    inherit (config.boot.loader.generationsDir) copyKernels;
-  };
-
-in
-
-{
-  options = {
-
-    boot.loader.generationsDir = {
-
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to create symlinks to the system generations under
-          <literal>/boot</literal>.  When enabled,
-          <literal>/boot/default/kernel</literal>,
-          <literal>/boot/default/initrd</literal>, etc., are updated to
-          point to the current generation's kernel image, initial RAM
-          disk, and other bootstrap files.
-
-          This optional is not necessary with boot loaders such as GNU GRUB
-          for which the menu is updated to point to the latest bootstrap
-          files.  However, it is needed for U-Boot on platforms where the
-          boot command line is stored in flash memory rather than in a
-          menu file.
-        '';
-      };
-
-      copyKernels = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether copy the necessary boot files into /boot, so
-          /nix/store is not needed by the boot loader.
-        '';
-      };
-
-    };
-
-  };
-
-
-  config = mkIf config.boot.loader.generationsDir.enable {
-
-    system.build.installBootLoader = generationsDirBuilder;
-    system.boot.loader.id = "generationsDir";
-    system.boot.loader.kernelFile = pkgs.stdenv.hostPlatform.linux-kernel.target;
-
-  };
-}
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix b/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
deleted file mode 100644
index 545b594674f..00000000000
--- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
+++ /dev/null
@@ -1,82 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  blCfg = config.boot.loader;
-  dtCfg = config.hardware.deviceTree;
-  cfg = blCfg.generic-extlinux-compatible;
-
-  timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
-
-  # The builder used to write during system activation
-  builder = import ./extlinux-conf-builder.nix { inherit pkgs; };
-  # The builder exposed in populateCmd, which runs on the build architecture
-  populateBuilder = import ./extlinux-conf-builder.nix { pkgs = pkgs.buildPackages; };
-in
-{
-  options = {
-    boot.loader.generic-extlinux-compatible = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to generate an extlinux-compatible configuration file
-          under <literal>/boot/extlinux.conf</literal>.  For instance,
-          U-Boot's generic distro boot support uses this file format.
-
-          See <link xlink:href="http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.distro;hb=refs/heads/master">U-boot's documentation</link>
-          for more information.
-        '';
-      };
-
-      useGenerationDeviceTree = mkOption {
-        default = true;
-        type = types.bool;
-        description = ''
-          Whether to generate Device Tree-related directives in the
-          extlinux configuration.
-
-          When enabled, the bootloader will attempt to load the device
-          tree binaries from the generation's kernel.
-
-          Note that this affects all generations, regardless of the
-          setting value used in their configurations.
-        '';
-      };
-
-      configurationLimit = mkOption {
-        default = 20;
-        example = 10;
-        type = types.int;
-        description = ''
-          Maximum number of configurations in the boot menu.
-        '';
-      };
-
-      populateCmd = mkOption {
-        type = types.str;
-        readOnly = true;
-        description = ''
-          Contains the builder command used to populate an image,
-          honoring all options except the <literal>-c &lt;path-to-default-configuration&gt;</literal>
-          argument.
-          Useful to have for sdImage.populateRootCommands
-        '';
-      };
-
-    };
-  };
-
-  config = let
-    builderArgs = "-g ${toString cfg.configurationLimit} -t ${timeoutStr}"
-      + lib.optionalString (dtCfg.name != null) " -n ${dtCfg.name}"
-      + lib.optionalString (!cfg.useGenerationDeviceTree) " -r";
-  in
-    mkIf cfg.enable {
-      system.build.installBootLoader = "${builder} ${builderArgs} -c";
-      system.boot.loader.id = "generic-extlinux-compatible";
-
-      boot.loader.generic-extlinux-compatible.populateCmd = "${populateBuilder} ${builderArgs}";
-    };
-}
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix
deleted file mode 100644
index 576a07c1d27..00000000000
--- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{ pkgs }:
-
-pkgs.substituteAll {
-  src = ./extlinux-conf-builder.sh;
-  isExecutable = true;
-  path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
-  inherit (pkgs) bash;
-}
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
deleted file mode 100644
index 1a0da005029..00000000000
--- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
+++ /dev/null
@@ -1,157 +0,0 @@
-#! @bash@/bin/sh -e
-
-shopt -s nullglob
-
-export PATH=/empty
-for i in @path@; do PATH=$PATH:$i/bin; done
-
-usage() {
-    echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>] [-n <dtbName>] [-r]" >&2
-    exit 1
-}
-
-timeout=                # Timeout in centiseconds
-default=                # Default configuration
-target=/boot            # Target directory
-numGenerations=0        # Number of other generations to include in the menu
-
-while getopts "t:c:d:g:n:r" opt; do
-    case "$opt" in
-        t) # U-Boot interprets '0' as infinite and negative as instant boot
-            if [ "$OPTARG" -lt 0 ]; then
-                timeout=0
-            elif [ "$OPTARG" = 0 ]; then
-                timeout=-10
-            else
-                timeout=$((OPTARG * 10))
-            fi
-            ;;
-        c) default="$OPTARG" ;;
-        d) target="$OPTARG" ;;
-        g) numGenerations="$OPTARG" ;;
-        n) dtbName="$OPTARG" ;;
-        r) noDeviceTree=1 ;;
-        \?) usage ;;
-    esac
-done
-
-[ "$timeout" = "" -o "$default" = "" ] && usage
-
-mkdir -p $target/nixos
-mkdir -p $target/extlinux
-
-# Convert a path to a file in the Nix store such as
-# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
-cleanName() {
-    local path="$1"
-    echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g'
-}
-
-# Copy a file from the Nix store to $target/nixos.
-declare -A filesCopied
-
-copyToKernelsDir() {
-    local src=$(readlink -f "$1")
-    local dst="$target/nixos/$(cleanName $src)"
-    # Don't copy the file if $dst already exists.  This means that we
-    # have to create $dst atomically to prevent partially copied
-    # kernels or initrd if this script is ever interrupted.
-    if ! test -e $dst; then
-        local dstTmp=$dst.tmp.$$
-        cp -r $src $dstTmp
-        mv $dstTmp $dst
-    fi
-    filesCopied[$dst]=1
-    result=$dst
-}
-
-# Copy its kernel, initrd and dtbs to $target/nixos, and echo out an
-# extlinux menu entry
-addEntry() {
-    local path=$(readlink -f "$1")
-    local tag="$2" # Generation number or 'default'
-
-    if ! test -e $path/kernel -a -e $path/initrd; then
-        return
-    fi
-
-    copyToKernelsDir "$path/kernel"; kernel=$result
-    copyToKernelsDir "$path/initrd"; initrd=$result
-    dtbDir=$(readlink -m "$path/dtbs")
-    if [ -e "$dtbDir" ]; then
-        copyToKernelsDir "$dtbDir"; dtbs=$result
-    fi
-
-    timestampEpoch=$(stat -L -c '%Z' $path)
-
-    timestamp=$(date "+%Y-%m-%d %H:%M" -d @$timestampEpoch)
-    nixosLabel="$(cat $path/nixos-version)"
-    extraParams="$(cat $path/kernel-params)"
-
-    echo
-    echo "LABEL nixos-$tag"
-    if [ "$tag" = "default" ]; then
-        echo "  MENU LABEL NixOS - Default"
-    else
-        echo "  MENU LABEL NixOS - Configuration $tag ($timestamp - $nixosLabel)"
-    fi
-    echo "  LINUX ../nixos/$(basename $kernel)"
-    echo "  INITRD ../nixos/$(basename $initrd)"
-    echo "  APPEND init=$path/init $extraParams"
-
-    if [ -n "$noDeviceTree" ]; then
-        return
-    fi
-
-    if [ -d "$dtbDir" ]; then
-        # if a dtbName was specified explicitly, use that, else use FDTDIR
-        if [ -n "$dtbName" ]; then
-            echo "  FDT ../nixos/$(basename $dtbs)/${dtbName}"
-        else
-            echo "  FDTDIR ../nixos/$(basename $dtbs)"
-        fi
-    else
-        if [ -n "$dtbName" ]; then
-            echo "Explicitly requested dtbName $dtbName, but there's no FDTDIR - bailing out." >&2
-            exit 1
-        fi
-    fi
-}
-
-tmpFile="$target/extlinux/extlinux.conf.tmp.$$"
-
-cat > $tmpFile <<EOF
-# Generated file, all changes will be lost on nixos-rebuild!
-
-# Change this to e.g. nixos-42 to temporarily boot to an older configuration.
-DEFAULT nixos-default
-
-MENU TITLE ------------------------------------------------------------
-TIMEOUT $timeout
-EOF
-
-addEntry $default default >> $tmpFile
-
-if [ "$numGenerations" -gt 0 ]; then
-    # Add up to $numGenerations generations of the system profile to the menu,
-    # in reverse (most recent to least recent) order.
-    for generation in $(
-            (cd /nix/var/nix/profiles && ls -d system-*-link) \
-            | sed 's/system-\([0-9]\+\)-link/\1/' \
-            | sort -n -r \
-            | head -n $numGenerations); do
-        link=/nix/var/nix/profiles/system-$generation-link
-        addEntry $link $generation
-    done >> $tmpFile
-fi
-
-mv -f $tmpFile $target/extlinux/extlinux.conf
-
-# Remove obsolete files from $target/nixos.
-for fn in $target/nixos/*; do
-    if ! test "${filesCopied[$fn]}" = 1; then
-        echo "Removing no longer needed boot file: $fn"
-        chmod +w -- "$fn"
-        rm -rf -- "$fn"
-    fi
-done
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
deleted file mode 100644
index 8db271f8713..00000000000
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ /dev/null
@@ -1,848 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  cfg = config.boot.loader.grub;
-
-  efi = config.boot.loader.efi;
-
-  grubPkgs =
-    # Package set of targeted architecture
-    if cfg.forcei686 then pkgs.pkgsi686Linux else pkgs;
-
-  realGrub = if cfg.version == 1 then grubPkgs.grub
-    else if cfg.zfsSupport then grubPkgs.grub2.override { zfsSupport = true; }
-    else if cfg.trustedBoot.enable
-         then if cfg.trustedBoot.isHPLaptop
-              then grubPkgs.trustedGrub-for-HP
-              else grubPkgs.trustedGrub
-         else grubPkgs.grub2;
-
-  grub =
-    # Don't include GRUB if we're only generating a GRUB menu (e.g.,
-    # in EC2 instances).
-    if cfg.devices == ["nodev"]
-    then null
-    else realGrub;
-
-  grubEfi =
-    # EFI version of Grub v2
-    if cfg.efiSupport && (cfg.version == 2)
-    then realGrub.override { efiSupport = cfg.efiSupport; }
-    else null;
-
-  f = x: if x == null then "" else "" + x;
-
-  grubConfig = args:
-    let
-      efiSysMountPoint = if args.efiSysMountPoint == null then args.path else args.efiSysMountPoint;
-      efiSysMountPoint' = replaceChars [ "/" ] [ "-" ] efiSysMountPoint;
-    in
-    pkgs.writeText "grub-config.xml" (builtins.toXML
-    { splashImage = f cfg.splashImage;
-      splashMode = f cfg.splashMode;
-      backgroundColor = f cfg.backgroundColor;
-      grub = f grub;
-      grubTarget = f (grub.grubTarget or "");
-      shell = "${pkgs.runtimeShell}";
-      fullName = lib.getName realGrub;
-      fullVersion = lib.getVersion realGrub;
-      grubEfi = f grubEfi;
-      grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f (grubEfi.grubTarget or "") else "";
-      bootPath = args.path;
-      storePath = config.boot.loader.grub.storePath;
-      bootloaderId = if args.efiBootloaderId == null then "NixOS${efiSysMountPoint'}" else args.efiBootloaderId;
-      timeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout;
-      users = if cfg.users == {} || cfg.version != 1 then cfg.users else throw "GRUB version 1 does not support user accounts.";
-      theme = f cfg.theme;
-      inherit efiSysMountPoint;
-      inherit (args) devices;
-      inherit (efi) canTouchEfiVariables;
-      inherit (cfg)
-        version extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber
-        extraGrubInstallArgs
-        extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels
-        default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios;
-      path = with pkgs; makeBinPath (
-        [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ]
-        ++ optional (cfg.efiSupport && (cfg.version == 2)) efibootmgr
-        ++ optionals cfg.useOSProber [ busybox os-prober ]);
-      font = if cfg.font == null then ""
-        else (if lib.last (lib.splitString "." cfg.font) == "pf2"
-             then cfg.font
-             else "${convertedFont}");
-    });
-
-  bootDeviceCounters = foldr (device: attr: attr // { ${device} = (attr.${device} or 0) + 1; }) {}
-    (concatMap (args: args.devices) cfg.mirroredBoots);
-
-  convertedFont = (pkgs.runCommand "grub-font-converted.pf2" {}
-           (builtins.concatStringsSep " "
-             ([ "${realGrub}/bin/grub-mkfont"
-               cfg.font
-               "--output" "$out"
-             ] ++ (optional (cfg.fontSize!=null) "--size ${toString cfg.fontSize}")))
-         );
-
-  defaultSplash = pkgs.nixos-artwork.wallpapers.simple-dark-gray-bootloader.gnomeFilePath;
-in
-
-{
-
-  ###### interface
-
-  options = {
-
-    boot.loader.grub = {
-
-      enable = mkOption {
-        default = !config.boot.isContainer;
-        defaultText = literalExpression "!config.boot.isContainer";
-        type = types.bool;
-        description = ''
-          Whether to enable the GNU GRUB boot loader.
-        '';
-      };
-
-      version = mkOption {
-        default = 2;
-        example = 1;
-        type = types.int;
-        description = ''
-          The version of GRUB to use: <literal>1</literal> for GRUB
-          Legacy (versions 0.9x), or <literal>2</literal> (the
-          default) for GRUB 2.
-        '';
-      };
-
-      device = mkOption {
-        default = "";
-        example = "/dev/disk/by-id/wwn-0x500001234567890a";
-        type = types.str;
-        description = ''
-          The device on which the GRUB boot loader will be installed.
-          The special value <literal>nodev</literal> means that a GRUB
-          boot menu will be generated, but GRUB itself will not
-          actually be installed.  To install GRUB on multiple devices,
-          use <literal>boot.loader.grub.devices</literal>.
-        '';
-      };
-
-      devices = mkOption {
-        default = [];
-        example = [ "/dev/disk/by-id/wwn-0x500001234567890a" ];
-        type = types.listOf types.str;
-        description = ''
-          The devices on which the boot loader, GRUB, will be
-          installed. Can be used instead of <literal>device</literal> to
-          install GRUB onto multiple devices.
-        '';
-      };
-
-      users = mkOption {
-        default = {};
-        example = {
-          root = { hashedPasswordFile = "/path/to/file"; };
-        };
-        description = ''
-          User accounts for GRUB. When specified, the GRUB command line and
-          all boot options except the default are password-protected.
-          All passwords and hashes provided will be stored in /boot/grub/grub.cfg,
-          and will be visible to any local user who can read this file. Additionally,
-          any passwords and hashes provided directly in a Nix configuration
-          (as opposed to external files) will be copied into the Nix store, and
-          will be visible to all local users.
-        '';
-        type = with types; attrsOf (submodule {
-          options = {
-            hashedPasswordFile = mkOption {
-              example = "/path/to/file";
-              default = null;
-              type = with types; uniq (nullOr str);
-              description = ''
-                Specifies the path to a file containing the password hash
-                for the account, generated with grub-mkpasswd-pbkdf2.
-                This hash will be stored in /boot/grub/grub.cfg, and will
-                be visible to any local user who can read this file.
-              '';
-            };
-            hashedPassword = mkOption {
-              example = "grub.pbkdf2.sha512.10000.674DFFDEF76E13EA...2CC972B102CF4355";
-              default = null;
-              type = with types; uniq (nullOr str);
-              description = ''
-                Specifies the password hash for the account,
-                generated with grub-mkpasswd-pbkdf2.
-                This hash will be copied to the Nix store, and will be visible to all local users.
-              '';
-            };
-            passwordFile = mkOption {
-              example = "/path/to/file";
-              default = null;
-              type = with types; uniq (nullOr str);
-              description = ''
-                Specifies the path to a file containing the
-                clear text password for the account.
-                This password will be stored in /boot/grub/grub.cfg, and will
-                be visible to any local user who can read this file.
-              '';
-            };
-            password = mkOption {
-              example = "Pa$$w0rd!";
-              default = null;
-              type = with types; uniq (nullOr str);
-              description = ''
-                Specifies the clear text password for the account.
-                This password will be copied to the Nix store, and will be visible to all local users.
-              '';
-            };
-          };
-        });
-      };
-
-      mirroredBoots = mkOption {
-        default = [ ];
-        example = [
-          { path = "/boot1"; devices = [ "/dev/disk/by-id/wwn-0x500001234567890a" ]; }
-          { path = "/boot2"; devices = [ "/dev/disk/by-id/wwn-0x500009876543210a" ]; }
-        ];
-        description = ''
-          Mirror the boot configuration to multiple partitions and install grub
-          to the respective devices corresponding to those partitions.
-        '';
-
-        type = with types; listOf (submodule {
-          options = {
-
-            path = mkOption {
-              example = "/boot1";
-              type = types.str;
-              description = ''
-                The path to the boot directory where GRUB will be written. Generally
-                this boot path should double as an EFI path.
-              '';
-            };
-
-            efiSysMountPoint = mkOption {
-              default = null;
-              example = "/boot1/efi";
-              type = types.nullOr types.str;
-              description = ''
-                The path to the efi system mount point. Usually this is the same
-                partition as the above path and can be left as null.
-              '';
-            };
-
-            efiBootloaderId = mkOption {
-              default = null;
-              example = "NixOS-fsid";
-              type = types.nullOr types.str;
-              description = ''
-                The id of the bootloader to store in efi nvram.
-                The default is to name it NixOS and append the path or efiSysMountPoint.
-                This is only used if <literal>boot.loader.efi.canTouchEfiVariables</literal> is true.
-              '';
-            };
-
-            devices = mkOption {
-              default = [ ];
-              example = [ "/dev/disk/by-id/wwn-0x500001234567890a" "/dev/disk/by-id/wwn-0x500009876543210a" ];
-              type = types.listOf types.str;
-              description = ''
-                The path to the devices which will have the GRUB MBR written.
-                Note these are typically device paths and not paths to partitions.
-              '';
-            };
-
-          };
-        });
-      };
-
-      configurationName = mkOption {
-        default = "";
-        example = "Stable 2.6.21";
-        type = types.str;
-        description = ''
-          GRUB entry name instead of default.
-        '';
-      };
-
-      storePath = mkOption {
-        default = "/nix/store";
-        type = types.str;
-        description = ''
-          Path to the Nix store when looking for kernels at boot.
-          Only makes sense when copyKernels is false.
-        '';
-      };
-
-      extraPrepareConfig = mkOption {
-        default = "";
-        type = types.lines;
-        description = ''
-          Additional bash commands to be run at the script that
-          prepares the GRUB menu entries.
-        '';
-      };
-
-      extraConfig = mkOption {
-        default = "";
-        example = ''
-          serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
-          terminal_input --append serial
-          terminal_output --append serial
-        '';
-        type = types.lines;
-        description = ''
-          Additional GRUB commands inserted in the configuration file
-          just before the menu entries.
-        '';
-      };
-
-      extraGrubInstallArgs = mkOption {
-        default = [ ];
-        example = [ "--modules=nativedisk ahci pata part_gpt part_msdos diskfilter mdraid1x lvm ext2" ];
-        type = types.listOf types.str;
-        description = ''
-          Additional arguments passed to <literal>grub-install</literal>.
-
-          A use case for this is to build specific GRUB2 modules
-          directly into the GRUB2 kernel image, so that they are available
-          and activated even in the <literal>grub rescue</literal> shell.
-
-          They are also necessary when the BIOS/UEFI is bugged and cannot
-          correctly read large disks (e.g. above 2 TB), so GRUB2's own
-          <literal>nativedisk</literal> and related modules can be used
-          to use its own disk drivers. The example shows one such case.
-          This is also useful for booting from USB.
-          See the
-          <link xlink:href="http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/commands/nativedisk.c?h=grub-2.04#n326">
-          GRUB source code
-          </link>
-          for which disk modules are available.
-
-          The list elements are passed directly as <literal>argv</literal>
-          arguments to the <literal>grub-install</literal> program, in order.
-        '';
-      };
-
-      extraInstallCommands = mkOption {
-        default = "";
-        example = ''
-          # the example below generates detached signatures that GRUB can verify
-          # https://www.gnu.org/software/grub/manual/grub/grub.html#Using-digital-signatures
-          ''${pkgs.findutils}/bin/find /boot -not -path "/boot/efi/*" -type f -name '*.sig' -delete
-          old_gpg_home=$GNUPGHOME
-          export GNUPGHOME="$(mktemp -d)"
-          ''${pkgs.gnupg}/bin/gpg --import ''${priv_key} > /dev/null 2>&1
-          ''${pkgs.findutils}/bin/find /boot -not -path "/boot/efi/*" -type f -exec ''${pkgs.gnupg}/bin/gpg --detach-sign "{}" \; > /dev/null 2>&1
-          rm -rf $GNUPGHOME
-          export GNUPGHOME=$old_gpg_home
-        '';
-        type = types.lines;
-        description = ''
-          Additional shell commands inserted in the bootloader installer
-          script after generating menu entries.
-        '';
-      };
-
-      extraPerEntryConfig = mkOption {
-        default = "";
-        example = "root (hd0)";
-        type = types.lines;
-        description = ''
-          Additional GRUB commands inserted in the configuration file
-          at the start of each NixOS menu entry.
-        '';
-      };
-
-      extraEntries = mkOption {
-        default = "";
-        type = types.lines;
-        example = ''
-          # GRUB 1 example (not GRUB 2 compatible)
-          title Windows
-            chainloader (hd0,1)+1
-
-          # GRUB 2 example
-          menuentry "Windows 7" {
-            chainloader (hd0,4)+1
-          }
-
-          # GRUB 2 with UEFI example, chainloading another distro
-          menuentry "Fedora" {
-            set root=(hd1,1)
-            chainloader /efi/fedora/grubx64.efi
-          }
-        '';
-        description = ''
-          Any additional entries you want added to the GRUB boot menu.
-        '';
-      };
-
-      extraEntriesBeforeNixOS = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether extraEntries are included before the default option.
-        '';
-      };
-
-      extraFiles = mkOption {
-        type = types.attrsOf types.path;
-        default = {};
-        example = literalExpression ''
-          { "memtest.bin" = "''${pkgs.memtest86plus}/memtest.bin"; }
-        '';
-        description = ''
-          A set of files to be copied to <filename>/boot</filename>.
-          Each attribute name denotes the destination file name in
-          <filename>/boot</filename>, while the corresponding
-          attribute value specifies the source file.
-        '';
-      };
-
-      useOSProber = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          If set to true, append entries for other OSs detected by os-prober.
-        '';
-      };
-
-      splashImage = mkOption {
-        type = types.nullOr types.path;
-        example = literalExpression "./my-background.png";
-        description = ''
-          Background image used for GRUB.
-          Set to <literal>null</literal> to run GRUB in text mode.
-
-          <note><para>
-          For grub 1:
-          It must be a 640x480,
-          14-colour image in XPM format, optionally compressed with
-          <command>gzip</command> or <command>bzip2</command>.
-          </para></note>
-
-          <note><para>
-          For grub 2:
-          File must be one of .png, .tga, .jpg, or .jpeg. JPEG images must
-          not be progressive.
-          The image will be scaled if necessary to fit the screen.
-          </para></note>
-        '';
-      };
-
-      backgroundColor = mkOption {
-        type = types.nullOr types.str;
-        example = "#7EBAE4";
-        default = null;
-        description = ''
-          Background color to be used for GRUB to fill the areas the image isn't filling.
-
-          <note><para>
-          This options has no effect for GRUB 1.
-          </para></note>
-        '';
-      };
-
-      theme = mkOption {
-        type = types.nullOr types.path;
-        example = literalExpression "pkgs.nixos-grub2-theme";
-        default = null;
-        description = ''
-          Grub theme to be used.
-
-          <note><para>
-          This options has no effect for GRUB 1.
-          </para></note>
-        '';
-      };
-
-      splashMode = mkOption {
-        type = types.enum [ "normal" "stretch" ];
-        default = "stretch";
-        description = ''
-          Whether to stretch the image or show the image in the top-left corner unstretched.
-
-          <note><para>
-          This options has no effect for GRUB 1.
-          </para></note>
-        '';
-      };
-
-      font = mkOption {
-        type = types.nullOr types.path;
-        default = "${realGrub}/share/grub/unicode.pf2";
-        defaultText = literalExpression ''"''${pkgs.grub2}/share/grub/unicode.pf2"'';
-        description = ''
-          Path to a TrueType, OpenType, or pf2 font to be used by Grub.
-        '';
-      };
-
-      fontSize = mkOption {
-        type = types.nullOr types.int;
-        example = 16;
-        default = null;
-        description = ''
-          Font size for the grub menu. Ignored unless <literal>font</literal>
-          is set to a ttf or otf font.
-        '';
-      };
-
-      gfxmodeEfi = mkOption {
-        default = "auto";
-        example = "1024x768";
-        type = types.str;
-        description = ''
-          The gfxmode to pass to GRUB when loading a graphical boot interface under EFI.
-        '';
-      };
-
-      gfxmodeBios = mkOption {
-        default = "1024x768";
-        example = "auto";
-        type = types.str;
-        description = ''
-          The gfxmode to pass to GRUB when loading a graphical boot interface under BIOS.
-        '';
-      };
-
-      gfxpayloadEfi = mkOption {
-        default = "keep";
-        example = "text";
-        type = types.str;
-        description = ''
-          The gfxpayload to pass to GRUB when loading a graphical boot interface under EFI.
-        '';
-      };
-
-      gfxpayloadBios = mkOption {
-        default = "text";
-        example = "keep";
-        type = types.str;
-        description = ''
-          The gfxpayload to pass to GRUB when loading a graphical boot interface under BIOS.
-        '';
-      };
-
-      configurationLimit = mkOption {
-        default = 100;
-        example = 120;
-        type = types.int;
-        description = ''
-          Maximum of configurations in boot menu. GRUB has problems when
-          there are too many entries.
-        '';
-      };
-
-      copyKernels = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether the GRUB menu builder should copy kernels and initial
-          ramdisks to /boot.  This is done automatically if /boot is
-          on a different partition than /.
-        '';
-      };
-
-      default = mkOption {
-        default = "0";
-        type = types.either types.int types.str;
-        apply = toString;
-        description = ''
-          Index of the default menu item to be booted.
-          Can also be set to "saved", which will make GRUB select
-          the menu item that was used at the last boot.
-        '';
-      };
-
-      fsIdentifier = mkOption {
-        default = "uuid";
-        type = types.enum [ "uuid" "label" "provided" ];
-        description = ''
-          Determines how GRUB will identify devices when generating the
-          configuration file. A value of uuid / label signifies that grub
-          will always resolve the uuid or label of the device before using
-          it in the configuration. A value of provided means that GRUB will
-          use the device name as show in <command>df</command> or
-          <command>mount</command>. Note, zfs zpools / datasets are ignored
-          and will always be mounted using their labels.
-        '';
-      };
-
-      zfsSupport = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether GRUB should be built against libzfs.
-          ZFS support is only available for GRUB v2.
-          This option is ignored for GRUB v1.
-        '';
-      };
-
-      efiSupport = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether GRUB should be built with EFI support.
-          EFI support is only available for GRUB v2.
-          This option is ignored for GRUB v1.
-        '';
-      };
-
-      efiInstallAsRemovable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to invoke <literal>grub-install</literal> with
-          <literal>--removable</literal>.</para>
-
-          <para>Unless you turn this on, GRUB will install itself somewhere in
-          <literal>boot.loader.efi.efiSysMountPoint</literal> (exactly where
-          depends on other config variables). If you've set
-          <literal>boot.loader.efi.canTouchEfiVariables</literal> *AND* you
-          are currently booted in UEFI mode, then GRUB will use
-          <literal>efibootmgr</literal> to modify the boot order in the
-          EFI variables of your firmware to include this location. If you are
-          *not* booted in UEFI mode at the time GRUB is being installed, the
-          NVRAM will not be modified, and your system will not find GRUB at
-          boot time. However, GRUB will still return success so you may miss
-          the warning that gets printed ("<literal>efibootmgr: EFI variables
-          are not supported on this system.</literal>").</para>
-
-          <para>If you turn this feature on, GRUB will install itself in a
-          special location within <literal>efiSysMountPoint</literal> (namely
-          <literal>EFI/boot/boot$arch.efi</literal>) which the firmwares
-          are hardcoded to try first, regardless of NVRAM EFI variables.</para>
-
-          <para>To summarize, turn this on if:
-          <itemizedlist>
-            <listitem><para>You are installing NixOS and want it to boot in UEFI mode,
-            but you are currently booted in legacy mode</para></listitem>
-            <listitem><para>You want to make a drive that will boot regardless of
-            the NVRAM state of the computer (like a USB "removable" drive)</para></listitem>
-            <listitem><para>You simply dislike the idea of depending on NVRAM
-            state to make your drive bootable</para></listitem>
-          </itemizedlist>
-        '';
-      };
-
-      enableCryptodisk = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Enable support for encrypted partitions. GRUB should automatically
-          unlock the correct encrypted partition and look for filesystems.
-        '';
-      };
-
-      forceInstall = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to try and forcibly install GRUB even if problems are
-          detected. It is not recommended to enable this unless you know what
-          you are doing.
-        '';
-      };
-
-      forcei686 = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to force the use of a ia32 boot loader on x64 systems. Required
-          to install and run NixOS on 64bit x86 systems with 32bit (U)EFI.
-        '';
-      };
-
-      trustedBoot = {
-
-        enable = mkOption {
-          default = false;
-          type = types.bool;
-          description = ''
-            Enable trusted boot. GRUB will measure all critical components during
-            the boot process to offer TCG (TPM) support.
-          '';
-        };
-
-        systemHasTPM = mkOption {
-          default = "";
-          example = "YES_TPM_is_activated";
-          type = types.str;
-          description = ''
-            Assertion that the target system has an activated TPM. It is a safety
-            check before allowing the activation of 'trustedBoot.enable'. TrustedBoot
-            WILL FAIL TO BOOT YOUR SYSTEM if no TPM is available.
-          '';
-        };
-
-        isHPLaptop = mkOption {
-          default = false;
-          type = types.bool;
-          description = ''
-            Use a special version of TrustedGRUB that is needed by some HP laptops
-            and works only for the HP laptops.
-          '';
-        };
-
-      };
-
-    };
-
-  };
-
-
-  ###### implementation
-
-  config = mkMerge [
-
-    { boot.loader.grub.splashImage = mkDefault (
-        if cfg.version == 1 then pkgs.fetchurl {
-          url = "http://www.gnome-look.org/CONTENT/content-files/36909-soft-tux.xpm.gz";
-          sha256 = "14kqdx2lfqvh40h6fjjzqgff1mwk74dmbjvmqphi6azzra7z8d59";
-        }
-        # GRUB 1.97 doesn't support gzipped XPMs.
-        else defaultSplash);
-    }
-
-    (mkIf (cfg.splashImage == defaultSplash) {
-      boot.loader.grub.backgroundColor = mkDefault "#2F302F";
-      boot.loader.grub.splashMode = mkDefault "normal";
-    })
-
-    (mkIf cfg.enable {
-
-      boot.loader.grub.devices = optional (cfg.device != "") cfg.device;
-
-      boot.loader.grub.mirroredBoots = optionals (cfg.devices != [ ]) [
-        { path = "/boot"; inherit (cfg) devices; inherit (efi) efiSysMountPoint; }
-      ];
-
-      boot.loader.supportsInitrdSecrets = true;
-
-      system.build.installBootLoader =
-        let
-          install-grub-pl = pkgs.substituteAll {
-            src = ./install-grub.pl;
-            utillinux = pkgs.util-linux;
-            btrfsprogs = pkgs.btrfs-progs;
-          };
-          perl = pkgs.perl.withPackages (p: with p; [
-            FileSlurp FileCopyRecursive
-            XMLLibXML XMLSAX XMLSAXBase
-            ListCompare JSON
-          ]);
-        in pkgs.writeScript "install-grub.sh" (''
-        #!${pkgs.runtimeShell}
-        set -e
-        ${optionalString cfg.enableCryptodisk "export GRUB_ENABLE_CRYPTODISK=y"}
-      '' + flip concatMapStrings cfg.mirroredBoots (args: ''
-        ${perl}/bin/perl ${install-grub-pl} ${grubConfig args} $@
-      '') + cfg.extraInstallCommands);
-
-      system.build.grub = grub;
-
-      # Common attribute for boot loaders so only one of them can be
-      # set at once.
-      system.boot.loader.id = "grub";
-
-      environment.systemPackages = optional (grub != null) grub;
-
-      boot.loader.grub.extraPrepareConfig =
-        concatStrings (mapAttrsToList (n: v: ''
-          ${pkgs.coreutils}/bin/cp -pf "${v}" "@bootPath@/${n}"
-        '') config.boot.loader.grub.extraFiles);
-
-      assertions = [
-        {
-          assertion = !cfg.zfsSupport || cfg.version == 2;
-          message = "Only GRUB version 2 provides ZFS support";
-        }
-        {
-          assertion = cfg.mirroredBoots != [ ];
-          message = "You must set the option ‘boot.loader.grub.devices’ or "
-            + "'boot.loader.grub.mirroredBoots' to make the system bootable.";
-        }
-        {
-          assertion = cfg.efiSupport || all (c: c < 2) (mapAttrsToList (n: c: if n == "nodev" then 0 else c) bootDeviceCounters);
-          message = "You cannot have duplicated devices in mirroredBoots";
-        }
-        {
-          assertion = !cfg.trustedBoot.enable || cfg.version == 2;
-          message = "Trusted GRUB is only available for GRUB 2";
-        }
-        {
-          assertion = !cfg.efiSupport || !cfg.trustedBoot.enable;
-          message = "Trusted GRUB does not have EFI support";
-        }
-        {
-          assertion = !cfg.zfsSupport || !cfg.trustedBoot.enable;
-          message = "Trusted GRUB does not have ZFS support";
-        }
-        {
-          assertion = !cfg.trustedBoot.enable || cfg.trustedBoot.systemHasTPM == "YES_TPM_is_activated";
-          message = "Trusted GRUB can break the system! Confirm that the system has an activated TPM by setting 'systemHasTPM'.";
-        }
-        {
-          assertion = cfg.efiInstallAsRemovable -> cfg.efiSupport;
-          message = "If you wish to to use boot.loader.grub.efiInstallAsRemovable, then turn on boot.loader.grub.efiSupport";
-        }
-        {
-          assertion = cfg.efiInstallAsRemovable -> !config.boot.loader.efi.canTouchEfiVariables;
-          message = "If you wish to to use boot.loader.grub.efiInstallAsRemovable, then turn off boot.loader.efi.canTouchEfiVariables";
-        }
-      ] ++ flip concatMap cfg.mirroredBoots (args: [
-        {
-          assertion = args.devices != [ ];
-          message = "A boot path cannot have an empty devices string in ${args.path}";
-        }
-        {
-          assertion = hasPrefix "/" args.path;
-          message = "Boot paths must be absolute, not ${args.path}";
-        }
-        {
-          assertion = if args.efiSysMountPoint == null then true else hasPrefix "/" args.efiSysMountPoint;
-          message = "EFI paths must be absolute, not ${args.efiSysMountPoint}";
-        }
-      ] ++ forEach args.devices (device: {
-        assertion = device == "nodev" || hasPrefix "/" device;
-        message = "GRUB devices must be absolute paths, not ${device} in ${args.path}";
-      }));
-    })
-
-  ];
-
-
-  imports =
-    [ (mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ] "")
-      (mkRenamedOptionModule [ "boot" "copyKernels" ] [ "boot" "loader" "grub" "copyKernels" ])
-      (mkRenamedOptionModule [ "boot" "extraGrubEntries" ] [ "boot" "loader" "grub" "extraEntries" ])
-      (mkRenamedOptionModule [ "boot" "extraGrubEntriesBeforeNixos" ] [ "boot" "loader" "grub" "extraEntriesBeforeNixOS" ])
-      (mkRenamedOptionModule [ "boot" "grubDevice" ] [ "boot" "loader" "grub" "device" ])
-      (mkRenamedOptionModule [ "boot" "bootMount" ] [ "boot" "loader" "grub" "bootDevice" ])
-      (mkRenamedOptionModule [ "boot" "grubSplashImage" ] [ "boot" "loader" "grub" "splashImage" ])
-      (mkRemovedOptionModule [ "boot" "loader" "grub" "extraInitrd" ] ''
-        This option has been replaced with the bootloader agnostic
-        boot.initrd.secrets option. To migrate to the initrd secrets system,
-        extract the extraInitrd archive into your main filesystem:
-
-          # zcat /boot/extra_initramfs.gz | cpio -idvmD /etc/secrets/initrd
-          /path/to/secret1
-          /path/to/secret2
-
-        then replace boot.loader.grub.extraInitrd with boot.initrd.secrets:
-
-          boot.initrd.secrets = {
-            "/path/to/secret1" = "/etc/secrets/initrd/path/to/secret1";
-            "/path/to/secret2" = "/etc/secrets/initrd/path/to/secret2";
-          };
-
-        See the boot.initrd.secrets option documentation for more information.
-      '')
-    ];
-
-}
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
deleted file mode 100644
index 0c93b288fc6..00000000000
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ /dev/null
@@ -1,780 +0,0 @@
-use strict;
-use warnings;
-use Class::Struct;
-use XML::LibXML;
-use File::Basename;
-use File::Path;
-use File::stat;
-use File::Copy;
-use File::Copy::Recursive qw(rcopy pathrm);
-use File::Slurp;
-use File::Temp;
-use JSON;
-use File::Find;
-require List::Compare;
-use POSIX;
-use Cwd;
-
-# system.build.toplevel path
-my $defaultConfig = $ARGV[1] or die;
-
-# Grub config XML generated by grubConfig function in grub.nix
-my $dom = XML::LibXML->load_xml(location => $ARGV[0]);
-
-sub get { my ($name) = @_; return $dom->findvalue("/expr/attrs/attr[\@name = '$name']/*/\@value"); }
-
-sub getList {
-    my ($name) = @_;
-    my @list = ();
-    foreach my $entry ($dom->findnodes("/expr/attrs/attr[\@name = '$name']/list/string/\@value")) {
-        $entry = $entry->findvalue(".") or die;
-        push(@list, $entry);
-    }
-    return @list;
-}
-
-sub readFile {
-    my ($fn) = @_; local $/ = undef;
-    open FILE, "<$fn" or return undef; my $s = <FILE>; close FILE;
-    local $/ = "\n"; chomp $s; return $s;
-}
-
-sub writeFile {
-    my ($fn, $s) = @_;
-    open FILE, ">$fn" or die "cannot create $fn: $!\n";
-    print FILE $s or die;
-    close FILE or die;
-}
-
-sub runCommand {
-    my ($cmd) = @_;
-    open FILE, "$cmd 2>/dev/null |" or die "Failed to execute: $cmd\n";
-    my @ret = <FILE>;
-    close FILE;
-    return ($?, @ret);
-}
-
-my $grub = get("grub");
-my $grubVersion = int(get("version"));
-my $grubTarget = get("grubTarget");
-my $extraConfig = get("extraConfig");
-my $extraPrepareConfig = get("extraPrepareConfig");
-my $extraPerEntryConfig = get("extraPerEntryConfig");
-my $extraEntries = get("extraEntries");
-my $extraEntriesBeforeNixOS = get("extraEntriesBeforeNixOS") eq "true";
-my $splashImage = get("splashImage");
-my $splashMode = get("splashMode");
-my $backgroundColor = get("backgroundColor");
-my $configurationLimit = int(get("configurationLimit"));
-my $copyKernels = get("copyKernels") eq "true";
-my $timeout = int(get("timeout"));
-my $defaultEntry = get("default");
-my $fsIdentifier = get("fsIdentifier");
-my $grubEfi = get("grubEfi");
-my $grubTargetEfi = get("grubTargetEfi");
-my $bootPath = get("bootPath");
-my $storePath = get("storePath");
-my $canTouchEfiVariables = get("canTouchEfiVariables");
-my $efiInstallAsRemovable = get("efiInstallAsRemovable");
-my $efiSysMountPoint = get("efiSysMountPoint");
-my $gfxmodeEfi = get("gfxmodeEfi");
-my $gfxmodeBios = get("gfxmodeBios");
-my $gfxpayloadEfi = get("gfxpayloadEfi");
-my $gfxpayloadBios = get("gfxpayloadBios");
-my $bootloaderId = get("bootloaderId");
-my $forceInstall = get("forceInstall");
-my $font = get("font");
-my $theme = get("theme");
-my $saveDefault = $defaultEntry eq "saved";
-$ENV{'PATH'} = get("path");
-
-die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
-
-print STDERR "updating GRUB $grubVersion menu...\n";
-
-mkpath("$bootPath/grub", 0, 0700);
-
-# Discover whether the bootPath is on the same filesystem as / and
-# /nix/store.  If not, then all kernels and initrds must be copied to
-# the bootPath.
-if (stat($bootPath)->dev != stat("/nix/store")->dev) {
-    $copyKernels = 1;
-}
-
-# Discover information about the location of the bootPath
-struct(Fs => {
-    device => '$',
-    type => '$',
-    mount => '$',
-});
-sub PathInMount {
-    my ($path, $mount) = @_;
-    my @splitMount = split /\//, $mount;
-    my @splitPath = split /\//, $path;
-    if ($#splitPath < $#splitMount) {
-        return 0;
-    }
-    for (my $i = 0; $i <= $#splitMount; $i++) {
-        if ($splitMount[$i] ne $splitPath[$i]) {
-            return 0;
-        }
-    }
-    return 1;
-}
-
-# Figure out what filesystem is used for the directory with init/initrd/kernel files
-sub GetFs {
-    my ($dir) = @_;
-    my $bestFs = Fs->new(device => "", type => "", mount => "");
-    foreach my $fs (read_file("/proc/self/mountinfo")) {
-        chomp $fs;
-        my @fields = split / /, $fs;
-        my $mountPoint = $fields[4];
-        next unless -d $mountPoint;
-        my @mountOptions = split /,/, $fields[5];
-
-        # Skip the optional fields.
-        my $n = 6; $n++ while $fields[$n] ne "-"; $n++;
-        my $fsType = $fields[$n];
-        my $device = $fields[$n + 1];
-        my @superOptions = split /,/, $fields[$n + 2];
-
-        # Skip the bind-mount on /nix/store.
-        next if $mountPoint eq "/nix/store" && (grep { $_ eq "rw" } @superOptions);
-        # Skip mount point generated by systemd-efi-boot-generator?
-        next if $fsType eq "autofs";
-
-        # Ensure this matches the intended directory
-        next unless PathInMount($dir, $mountPoint);
-
-        # Is it better than our current match?
-        if (length($mountPoint) > length($bestFs->mount)) {
-            $bestFs = Fs->new(device => $device, type => $fsType, mount => $mountPoint);
-        }
-    }
-    return $bestFs;
-}
-struct (Grub => {
-    path => '$',
-    search => '$',
-});
-my $driveid = 1;
-sub GrubFs {
-    my ($dir) = @_;
-    my $fs = GetFs($dir);
-    my $path = substr($dir, length($fs->mount));
-    if (substr($path, 0, 1) ne "/") {
-        $path = "/$path";
-    }
-    my $search = "";
-
-    if ($grubVersion > 1) {
-        # ZFS is completely separate logic as zpools are always identified by a label
-        # or custom UUID
-        if ($fs->type eq 'zfs') {
-            my $sid = index($fs->device, '/');
-
-            if ($sid < 0) {
-                $search = '--label ' . $fs->device;
-                $path = '/@' . $path;
-            } else {
-                $search = '--label ' . substr($fs->device, 0, $sid);
-                $path = '/' . substr($fs->device, $sid) . '/@' . $path;
-            }
-        } else {
-            my %types = ('uuid' => '--fs-uuid', 'label' => '--label');
-
-            if ($fsIdentifier eq 'provided') {
-                # If the provided dev is identifying the partition using a label or uuid,
-                # we should get the label / uuid and do a proper search
-                my @matches = $fs->device =~ m/\/dev\/disk\/by-(label|uuid)\/(.*)/;
-                if ($#matches > 1) {
-                    die "Too many matched devices"
-                } elsif ($#matches == 1) {
-                    $search = "$types{$matches[0]} $matches[1]"
-                }
-            } else {
-                # Determine the identifying type
-                $search = $types{$fsIdentifier} . ' ';
-
-                # Based on the type pull in the identifier from the system
-                my ($status, @devInfo) = runCommand("@utillinux@/bin/blkid -o export @{[$fs->device]}");
-                if ($status != 0) {
-                    die "Failed to get blkid info (returned $status) for @{[$fs->mount]} on @{[$fs->device]}";
-                }
-                my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/;
-                if ($#matches != 0) {
-                    die "Couldn't find a $types{$fsIdentifier} for @{[$fs->device]}\n"
-                }
-                $search .= $matches[0];
-            }
-
-            # BTRFS is a special case in that we need to fix the referrenced path based on subvolumes
-            if ($fs->type eq 'btrfs') {
-                my ($status, @id_info) = runCommand("@btrfsprogs@/bin/btrfs subvol show @{[$fs->mount]}");
-                if ($status != 0) {
-                    die "Failed to retrieve subvolume info for @{[$fs->mount]}\n";
-                }
-                my @ids = join("\n", @id_info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s;
-                if ($#ids > 0) {
-                    die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n"
-                } elsif ($#ids == 0) {
-                    my ($status, @path_info) = runCommand("@btrfsprogs@/bin/btrfs subvol list @{[$fs->mount]}");
-                    if ($status != 0) {
-                        die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n";
-                    }
-                    my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/;
-                    if ($#paths > 0) {
-                        die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n";
-                    } elsif ($#paths != 0) {
-                        die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n";
-                    }
-                    $path = "/$paths[0]$path";
-                }
-            }
-        }
-        if (not $search eq "") {
-            $search = "search --set=drive$driveid " . $search;
-            $path = "(\$drive$driveid)$path";
-            $driveid += 1;
-        }
-    }
-    return Grub->new(path => $path, search => $search);
-}
-my $grubBoot = GrubFs($bootPath);
-my $grubStore;
-if ($copyKernels == 0) {
-    $grubStore = GrubFs($storePath);
-}
-
-# Generate the header.
-my $conf .= "# Automatically generated.  DO NOT EDIT THIS FILE!\n";
-
-if ($grubVersion == 1) {
-    # $defaultEntry might be "saved", indicating that we want to use the last selected configuration as default.
-    # Incidentally this is already the correct value for the grub 1 config to achieve this behaviour.
-    $conf .= "
-        default $defaultEntry
-        timeout $timeout
-    ";
-    if ($splashImage) {
-        copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath: $!\n";
-        $conf .= "splashimage " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background.xpm.gz\n";
-    }
-}
-
-else {
-    my @users = ();
-    foreach my $user ($dom->findnodes('/expr/attrs/attr[@name = "users"]/attrs/attr')) {
-        my $name = $user->findvalue('@name') or die;
-        my $hashedPassword = $user->findvalue('./attrs/attr[@name = "hashedPassword"]/string/@value');
-        my $hashedPasswordFile = $user->findvalue('./attrs/attr[@name = "hashedPasswordFile"]/string/@value');
-        my $password = $user->findvalue('./attrs/attr[@name = "password"]/string/@value');
-        my $passwordFile = $user->findvalue('./attrs/attr[@name = "passwordFile"]/string/@value');
-
-        if ($hashedPasswordFile) {
-            open(my $f, '<', $hashedPasswordFile) or die "Can't read file '$hashedPasswordFile'!";
-            $hashedPassword = <$f>;
-            chomp $hashedPassword;
-        }
-        if ($passwordFile) {
-            open(my $f, '<', $passwordFile) or die "Can't read file '$passwordFile'!";
-            $password = <$f>;
-            chomp $password;
-        }
-
-        if ($hashedPassword) {
-            if (index($hashedPassword, "grub.pbkdf2.") == 0) {
-                $conf .= "\npassword_pbkdf2 $name $hashedPassword";
-            }
-            else {
-                die "Password hash for GRUB user '$name' is not valid!";
-            }
-        }
-        elsif ($password) {
-            $conf .= "\npassword $name $password";
-        }
-        else {
-            die "GRUB user '$name' has no password!";
-        }
-        push(@users, $name);
-    }
-    if (@users) {
-        $conf .= "\nset superusers=\"" . join(' ',@users) . "\"\n";
-    }
-
-    if ($copyKernels == 0) {
-        $conf .= "
-            " . $grubStore->search;
-    }
-    # FIXME: should use grub-mkconfig.
-    my $defaultEntryText = $defaultEntry;
-    if ($saveDefault) {
-        $defaultEntryText = "\"\${saved_entry}\"";
-    }
-    $conf .= "
-        " . $grubBoot->search . "
-        if [ -s \$prefix/grubenv ]; then
-          load_env
-        fi
-
-        # ‘grub-reboot’ sets a one-time saved entry, which we process here and
-        # then delete.
-        if [ \"\${next_entry}\" ]; then
-          set default=\"\${next_entry}\"
-          set next_entry=
-          save_env next_entry
-          set timeout=1
-          set boot_once=true
-        else
-          set default=$defaultEntryText
-          set timeout=$timeout
-        fi
-
-        function savedefault {
-            if [ -z \"\${boot_once}\"]; then
-            saved_entry=\"\${chosen}\"
-            save_env saved_entry
-            fi
-        }
-
-        # Setup the graphics stack for bios and efi systems
-        if [ \"\${grub_platform}\" = \"efi\" ]; then
-          insmod efi_gop
-          insmod efi_uga
-        else
-          insmod vbe
-        fi
-    ";
-
-    if ($font) {
-        copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n";
-        $conf .= "
-            insmod font
-            if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then
-              insmod gfxterm
-              if [ \"\${grub_platform}\" = \"efi\" ]; then
-                set gfxmode=$gfxmodeEfi
-                set gfxpayload=$gfxpayloadEfi
-              else
-                set gfxmode=$gfxmodeBios
-                set gfxpayload=$gfxpayloadBios
-              fi
-              terminal_output gfxterm
-            fi
-        ";
-    }
-    if ($splashImage) {
-        # Keeps the image's extension.
-        my ($filename, $dirs, $suffix) = fileparse($splashImage, qr"\..[^.]*$");
-        # The module for jpg is jpeg.
-        if ($suffix eq ".jpg") {
-            $suffix = ".jpeg";
-        }
-        if ($backgroundColor) {
-            $conf .= "
-            background_color '$backgroundColor'
-            ";
-        }
-        copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n";
-        $conf .= "
-            insmod " . substr($suffix, 1) . "
-            if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then
-              set color_normal=white/black
-              set color_highlight=black/white
-            else
-              set menu_color_normal=cyan/blue
-              set menu_color_highlight=white/blue
-            fi
-        ";
-    }
-
-    rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" if -e "$bootPath/theme";
-
-    if ($theme) {
-        # Copy theme
-        rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n";
-        $conf .= "
-            # Sets theme.
-            set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt
-            export theme
-            # Load theme fonts, if any
-        ";
-
-        find( { wanted => sub {
-            if ($_ =~ /\.pf2$/i) {
-                $font = File::Spec->abs2rel($File::Find::name, $theme);
-                $conf .= "
-                    loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font
-                ";
-            }
-        }, no_chdir => 1 }, $theme );
-    }
-}
-
-$conf .= "$extraConfig\n";
-
-
-# Generate the menu entries.
-$conf .= "\n";
-
-my %copied;
-mkpath("$bootPath/kernels", 0, 0755) if $copyKernels;
-
-sub copyToKernelsDir {
-    my ($path) = @_;
-    return $grubStore->path . substr($path, length("/nix/store")) unless $copyKernels;
-    $path =~ /\/nix\/store\/(.*)/ or die;
-    my $name = $1; $name =~ s/\//-/g;
-    my $dst = "$bootPath/kernels/$name";
-    # Don't copy the file if $dst already exists.  This means that we
-    # have to create $dst atomically to prevent partially copied
-    # kernels or initrd if this script is ever interrupted.
-    if (! -e $dst) {
-        my $tmp = "$dst.tmp";
-        copy $path, $tmp or die "cannot copy $path to $tmp: $!\n";
-        rename $tmp, $dst or die "cannot rename $tmp to $dst: $!\n";
-    }
-    $copied{$dst} = 1;
-    return ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$name";
-}
-
-sub addEntry {
-    my ($name, $path, $options) = @_;
-    return unless -e "$path/kernel" && -e "$path/initrd";
-
-    my $kernel = copyToKernelsDir(Cwd::abs_path("$path/kernel"));
-    my $initrd = copyToKernelsDir(Cwd::abs_path("$path/initrd"));
-
-    # Include second initrd with secrets
-    if (-e -x "$path/append-initrd-secrets") {
-        my $initrdName = basename($initrd);
-        my $initrdSecretsPath = "$bootPath/kernels/$initrdName-secrets";
-
-        mkpath(dirname($initrdSecretsPath), 0, 0755);
-        my $oldUmask = umask;
-        # Make sure initrd is not world readable (won't work if /boot is FAT)
-        umask 0137;
-        my $initrdSecretsPathTemp = File::Temp::mktemp("$initrdSecretsPath.XXXXXXXX");
-        system("$path/append-initrd-secrets", $initrdSecretsPathTemp) == 0 or die "failed to create initrd secrets: $!\n";
-        # Check whether any secrets were actually added
-        if (-e $initrdSecretsPathTemp && ! -z _) {
-            rename $initrdSecretsPathTemp, $initrdSecretsPath or die "failed to move initrd secrets into place: $!\n";
-            $copied{$initrdSecretsPath} = 1;
-            $initrd .= " " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$initrdName-secrets";
-        } else {
-            unlink $initrdSecretsPathTemp;
-            rmdir dirname($initrdSecretsPathTemp);
-        }
-        umask $oldUmask;
-    }
-
-    my $xen = -e "$path/xen.gz" ? copyToKernelsDir(Cwd::abs_path("$path/xen.gz")) : undef;
-
-    # FIXME: $confName
-
-    my $kernelParams =
-        "init=" . Cwd::abs_path("$path/init") . " " .
-        readFile("$path/kernel-params");
-    my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : "";
-
-    if ($grubVersion == 1) {
-        $conf .= "title $name\n";
-        $conf .= "  $extraPerEntryConfig\n" if $extraPerEntryConfig;
-        $conf .= "  kernel $xen $xenParams\n" if $xen;
-        $conf .= "  " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n";
-        $conf .= "  " . ($xen ? "module" : "initrd") . " $initrd\n";
-        if ($saveDefault) {
-            $conf .= "  savedefault\n";
-        }
-        $conf .= "\n";
-    } else {
-        $conf .= "menuentry \"$name\" " . ($options||"") . " {\n";
-        if ($saveDefault) {
-            $conf .= "  savedefault\n";
-        }
-        $conf .= $grubBoot->search . "\n";
-        if ($copyKernels == 0) {
-            $conf .= $grubStore->search . "\n";
-        }
-        $conf .= "  $extraPerEntryConfig\n" if $extraPerEntryConfig;
-        $conf .= "  multiboot $xen $xenParams\n" if $xen;
-        $conf .= "  " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";
-        $conf .= "  " . ($xen ? "module" : "initrd") . " $initrd\n";
-        $conf .= "}\n\n";
-    }
-}
-
-
-# Add default entries.
-$conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS;
-
-addEntry("NixOS - Default", $defaultConfig, "--unrestricted");
-
-$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
-
-# Find all the children of the current default configuration
-# Do not search for grand children
-my @links = sort (glob "$defaultConfig/specialisation/*");
-foreach my $link (@links) {
-
-    my $entryName = "";
-
-    my $cfgName = readFile("$link/configuration-name");
-
-    my $date = strftime("%F", localtime(lstat($link)->mtime));
-    my $version =
-        -e "$link/nixos-version"
-        ? readFile("$link/nixos-version")
-        : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]);
-
-    if ($cfgName) {
-        $entryName = $cfgName;
-    } else {
-        my $linkname = basename($link);
-        $entryName = "($linkname - $date - $version)";
-    }
-    addEntry("NixOS - $entryName", $link);
-}
-
-my $grubBootPath = $grubBoot->path;
-# extraEntries could refer to @bootRoot@, which we have to substitute
-$conf =~ s/\@bootRoot\@/$grubBootPath/g;
-
-# Emit submenus for all system profiles.
-sub addProfile {
-    my ($profile, $description) = @_;
-
-    # Add entries for all generations of this profile.
-    $conf .= "submenu \"$description\" {\n" if $grubVersion == 2;
-
-    sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; }
-
-    my @links = sort
-        { nrFromGen($b) <=> nrFromGen($a) }
-        (glob "$profile-*-link");
-
-    my $curEntry = 0;
-    foreach my $link (@links) {
-        last if $curEntry++ >= $configurationLimit;
-        if (! -e "$link/nixos-version") {
-            warn "skipping corrupt system profile entry ‘$link’\n";
-            next;
-        }
-        my $date = strftime("%F", localtime(lstat($link)->mtime));
-        my $version =
-            -e "$link/nixos-version"
-            ? readFile("$link/nixos-version")
-            : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]);
-        addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link);
-    }
-
-    $conf .= "}\n" if $grubVersion == 2;
-}
-
-addProfile "/nix/var/nix/profiles/system", "NixOS - All configurations";
-
-if ($grubVersion == 2) {
-    for my $profile (glob "/nix/var/nix/profiles/system-profiles/*") {
-        my $name = basename($profile);
-        next unless $name =~ /^\w+$/;
-        addProfile $profile, "NixOS - Profile '$name'";
-    }
-}
-
-# extraPrepareConfig could refer to @bootPath@, which we have to substitute
-$extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g;
-
-# Run extraPrepareConfig in sh
-if ($extraPrepareConfig ne "") {
-    system((get("shell"), "-c", $extraPrepareConfig));
-}
-
-# write the GRUB config.
-my $confFile = $grubVersion == 1 ? "$bootPath/grub/menu.lst" : "$bootPath/grub/grub.cfg";
-my $tmpFile = $confFile . ".tmp";
-writeFile($tmpFile, $conf);
-
-
-# check whether to install GRUB EFI or not
-sub getEfiTarget {
-    if ($grubVersion == 1) {
-        return "no"
-    } elsif (($grub ne "") && ($grubEfi ne "")) {
-        # EFI can only be installed when target is set;
-        # A target is also required then for non-EFI grub
-        if (($grubTarget eq "") || ($grubTargetEfi eq "")) { die }
-        else { return "both" }
-    } elsif (($grub ne "") && ($grubEfi eq "")) {
-        # TODO: It would be safer to disallow non-EFI grub installation if no taget is given.
-        #       If no target is given, then grub auto-detects the target which can lead to errors.
-        #       E.g. it seems as if grub would auto-detect a EFI target based on the availability
-        #       of a EFI partition.
-        #       However, it seems as auto-detection is currently relied on for non-x86_64 and non-i386
-        #       architectures in NixOS. That would have to be fixed in the nixos modules first.
-        return "no"
-    } elsif (($grub eq "") && ($grubEfi ne "")) {
-        # EFI can only be installed when target is set;
-        if ($grubTargetEfi eq "") { die }
-        else {return "only" }
-    } else {
-        # prevent an installation if neither grub nor grubEfi is given
-        return "neither"
-    }
-}
-
-my $efiTarget = getEfiTarget();
-
-# Append entries detected by os-prober
-if (get("useOSProber") eq "true") {
-    if ($saveDefault) {
-        # os-prober will read this to determine if "savedefault" should be added to generated entries
-        $ENV{'GRUB_SAVEDEFAULT'} = "true";
-    }
-
-    my $targetpackage = ($efiTarget eq "no") ? $grub : $grubEfi;
-    system(get("shell"), "-c", "pkgdatadir=$targetpackage/share/grub $targetpackage/etc/grub.d/30_os-prober >> $tmpFile");
-}
-
-# Atomically switch to the new config
-rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile: $!\n";
-
-
-# Remove obsolete files from $bootPath/kernels.
-foreach my $fn (glob "$bootPath/kernels/*") {
-    next if defined $copied{$fn};
-    print STDERR "removing obsolete file $fn\n";
-    unlink $fn;
-}
-
-
-#
-# Install GRUB if the parameters changed from the last time we installed it.
-#
-
-struct(GrubState => {
-    name => '$',
-    version => '$',
-    efi => '$',
-    devices => '$',
-    efiMountPoint => '$',
-    extraGrubInstallArgs => '@',
-});
-# If you add something to the state file, only add it to the end
-# because it is read line-by-line.
-sub readGrubState {
-    my $defaultGrubState = GrubState->new(name => "", version => "", efi => "", devices => "", efiMountPoint => "", extraGrubInstallArgs => () );
-    open FILE, "<$bootPath/grub/state" or return $defaultGrubState;
-    local $/ = "\n";
-    my $name = <FILE>;
-    chomp($name);
-    my $version = <FILE>;
-    chomp($version);
-    my $efi = <FILE>;
-    chomp($efi);
-    my $devices = <FILE>;
-    chomp($devices);
-    my $efiMountPoint = <FILE>;
-    chomp($efiMountPoint);
-    # Historically, arguments in the state file were one per each line, but that
-    # gets really messy when newlines are involved, structured arguments
-    # like lists are needed (they have to have a separator encoding), or even worse,
-    # when we need to remove a setting in the future. Thus, the 6th line is a JSON
-    # object that can store structured data, with named keys, and all new state
-    # should go in there.
-    my $jsonStateLine = <FILE>;
-    # For historical reasons we do not check the values above for un-definedness
-    # (that is, when the state file has too few lines and EOF is reached),
-    # because the above come from the first version of this logic and are thus
-    # guaranteed to be present.
-    $jsonStateLine = defined $jsonStateLine ? $jsonStateLine : '{}'; # empty JSON object
-    chomp($jsonStateLine);
-    if ($jsonStateLine eq "") {
-        $jsonStateLine = '{}'; # empty JSON object
-    }
-    my %jsonState = %{decode_json($jsonStateLine)};
-    my @extraGrubInstallArgs = exists($jsonState{'extraGrubInstallArgs'}) ? @{$jsonState{'extraGrubInstallArgs'}} : ();
-    close FILE;
-    my $grubState = GrubState->new(name => $name, version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint, extraGrubInstallArgs => \@extraGrubInstallArgs );
-    return $grubState
-}
-
-my @deviceTargets = getList('devices');
-my $prevGrubState = readGrubState();
-my @prevDeviceTargets = split/,/, $prevGrubState->devices;
-my @extraGrubInstallArgs = getList('extraGrubInstallArgs');
-my @prevExtraGrubInstallArgs = @{$prevGrubState->extraGrubInstallArgs};
-
-my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference());
-my $extraGrubInstallArgsDiffer = scalar (List::Compare->new( '-u', '-a', \@extraGrubInstallArgs, \@prevExtraGrubInstallArgs)->get_symmetric_difference());
-my $nameDiffer = get("fullName") ne $prevGrubState->name;
-my $versionDiffer = get("fullVersion") ne $prevGrubState->version;
-my $efiDiffer = $efiTarget ne $prevGrubState->efi;
-my $efiMountPointDiffer = $efiSysMountPoint ne $prevGrubState->efiMountPoint;
-if (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1") {
-    warn "NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER";
-    $ENV{'NIXOS_INSTALL_BOOTLOADER'} = "1";
-}
-my $requireNewInstall = $devicesDiffer || $extraGrubInstallArgsDiffer || $nameDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_BOOTLOADER'} // "") eq "1");
-
-# install a symlink so that grub can detect the boot drive
-my $tmpDir = File::Temp::tempdir(CLEANUP => 1) or die "Failed to create temporary space: $!";
-symlink "$bootPath", "$tmpDir/boot" or die "Failed to symlink $tmpDir/boot: $!";
-
-# install non-EFI GRUB
-if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
-    foreach my $dev (@deviceTargets) {
-        next if $dev eq "nodev";
-        print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n";
-        my @command = ("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev), @extraGrubInstallArgs);
-        if ($forceInstall eq "true") {
-            push @command, "--force";
-        }
-        if ($grubTarget ne "") {
-            push @command, "--target=$grubTarget";
-        }
-        (system @command) == 0 or die "$0: installation of GRUB on $dev failed: $!\n";
-    }
-}
-
-
-# install EFI GRUB
-if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) {
-    print STDERR "installing the GRUB $grubVersion EFI boot loader into $efiSysMountPoint...\n";
-    my @command = ("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", @extraGrubInstallArgs);
-    if ($forceInstall eq "true") {
-        push @command, "--force";
-    }
-    if ($canTouchEfiVariables eq "true") {
-        push @command, "--bootloader-id=$bootloaderId";
-    } else {
-        push @command, "--no-nvram";
-        push @command, "--removable" if $efiInstallAsRemovable eq "true";
-    }
-
-    (system @command) == 0 or die "$0: installation of GRUB EFI into $efiSysMountPoint failed: $!\n";
-}
-
-
-# update GRUB state file
-if ($requireNewInstall != 0) {
-    # Temp file for atomic rename.
-    my $stateFile = "$bootPath/grub/state";
-    my $stateFileTmp = $stateFile . ".tmp";
-
-    open FILE, ">$stateFileTmp" or die "cannot create $stateFileTmp: $!\n";
-    print FILE get("fullName"), "\n" or die;
-    print FILE get("fullVersion"), "\n" or die;
-    print FILE $efiTarget, "\n" or die;
-    print FILE join( ",", @deviceTargets ), "\n" or die;
-    print FILE $efiSysMountPoint, "\n" or die;
-    my %jsonState = (
-        extraGrubInstallArgs => \@extraGrubInstallArgs
-    );
-    my $jsonStateLine = encode_json(\%jsonState);
-    print FILE $jsonStateLine, "\n" or die;
-    close FILE or die;
-
-    # Atomically switch to the new state file
-    rename $stateFileTmp, $stateFile or die "cannot rename $stateFileTmp to $stateFile: $!\n";
-}
diff --git a/nixos/modules/system/boot/loader/grub/ipxe.nix b/nixos/modules/system/boot/loader/grub/ipxe.nix
deleted file mode 100644
index ef8595592f4..00000000000
--- a/nixos/modules/system/boot/loader/grub/ipxe.nix
+++ /dev/null
@@ -1,64 +0,0 @@
-# This module adds a scripted iPXE entry to the GRUB boot menu.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  scripts = builtins.attrNames config.boot.loader.grub.ipxe;
-
-  grubEntry = name:
-    ''
-      menuentry "iPXE - ${name}" {
-        linux16 @bootRoot@/ipxe.lkrn
-        initrd16 @bootRoot@/${name}.ipxe
-      }
-
-    '';
-
-  scriptFile = name:
-    let
-      value = builtins.getAttr name config.boot.loader.grub.ipxe;
-    in
-    if builtins.typeOf value == "path" then value
-    else builtins.toFile "${name}.ipxe" value;
-in
-{
-  options =
-    { boot.loader.grub.ipxe = mkOption {
-        type = types.attrsOf (types.either types.path types.str);
-        description =
-          ''
-            Set of iPXE scripts available for
-            booting from the GRUB boot menu.
-          '';
-        default = { };
-        example = literalExpression ''
-          { demo = '''
-              #!ipxe
-              dhcp
-              chain http://boot.ipxe.org/demo/boot.php
-            ''';
-          }
-        '';
-      };
-    };
-
-  config = mkIf (builtins.length scripts != 0) {
-
-    boot.loader.grub.extraEntries =
-      if config.boot.loader.grub.version == 2 then
-        toString (map grubEntry scripts)
-      else
-        throw "iPXE is not supported with GRUB 1.";
-
-    boot.loader.grub.extraFiles =
-      { "ipxe.lkrn" = "${pkgs.ipxe}/ipxe.lkrn"; }
-      //
-      builtins.listToAttrs ( map
-        (name: { name = name+".ipxe"; value = scriptFile name; })
-        scripts
-      );
-  };
-
-}
diff --git a/nixos/modules/system/boot/loader/grub/memtest.nix b/nixos/modules/system/boot/loader/grub/memtest.nix
deleted file mode 100644
index 71e50dd0577..00000000000
--- a/nixos/modules/system/boot/loader/grub/memtest.nix
+++ /dev/null
@@ -1,116 +0,0 @@
-# This module adds Memtest86+/Memtest86 to the GRUB boot menu.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  memtest86 = pkgs.memtest86plus;
-  efiSupport = config.boot.loader.grub.efiSupport;
-  cfg = config.boot.loader.grub.memtest86;
-in
-
-{
-  options = {
-
-    boot.loader.grub.memtest86 = {
-
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Make Memtest86+ (or MemTest86 if EFI support is enabled),
-          a memory testing program, available from the
-          GRUB boot menu. MemTest86 is an unfree program, so
-          this requires <literal>allowUnfree</literal> to be set to
-          <literal>true</literal>.
-        '';
-      };
-
-      params = mkOption {
-        default = [];
-        example = [ "console=ttyS0,115200" ];
-        type = types.listOf types.str;
-        description = ''
-          Parameters added to the Memtest86+ command line. As of memtest86+ 5.01
-          the following list of (apparently undocumented) parameters are
-          accepted:
-
-          <itemizedlist>
-
-          <listitem>
-            <para><literal>console=...</literal>, set up a serial console.
-            Examples:
-            <literal>console=ttyS0</literal>,
-            <literal>console=ttyS0,9600</literal> or
-            <literal>console=ttyS0,115200n8</literal>.</para>
-          </listitem>
-
-          <listitem>
-            <para><literal>btrace</literal>, enable boot trace.</para>
-          </listitem>
-
-          <listitem>
-            <para><literal>maxcpus=N</literal>, limit number of CPUs.</para>
-          </listitem>
-
-          <listitem>
-            <para><literal>onepass</literal>, run one pass and exit if there
-            are no errors.</para>
-          </listitem>
-
-          <listitem>
-            <para><literal>tstlist=...</literal>, list of tests to run.
-            Example: <literal>0,1,2</literal>.</para>
-          </listitem>
-
-          <listitem>
-            <para><literal>cpumask=...</literal>, set a CPU mask, to select CPUs
-            to use for testing.</para>
-          </listitem>
-
-          </itemizedlist>
-
-          This list of command line options was obtained by reading the
-          Memtest86+ source code.
-        '';
-      };
-
-    };
-  };
-
-  config = mkMerge [
-    (mkIf (cfg.enable && efiSupport) {
-      assertions = [
-        {
-          assertion = cfg.params == [];
-          message = "Parameters are not available for MemTest86";
-        }
-      ];
-
-      boot.loader.grub.extraFiles = {
-        "memtest86.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi";
-      };
-
-      boot.loader.grub.extraEntries = ''
-        menuentry "Memtest86" {
-          chainloader /memtest86.efi
-        }
-      '';
-    })
-
-    (mkIf (cfg.enable && !efiSupport) {
-      boot.loader.grub.extraEntries =
-        if config.boot.loader.grub.version == 2 then
-          ''
-            menuentry "Memtest86+" {
-              linux16 @bootRoot@/memtest.bin ${toString cfg.params}
-            }
-          ''
-        else
-          throw "Memtest86+ is not supported with GRUB 1.";
-
-      boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
-    })
-  ];
-}
diff --git a/nixos/modules/system/boot/loader/init-script/init-script-builder.sh b/nixos/modules/system/boot/loader/init-script/init-script-builder.sh
deleted file mode 100644
index bd3fc64999d..00000000000
--- a/nixos/modules/system/boot/loader/init-script/init-script-builder.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#! @bash@/bin/sh -e
-
-shopt -s nullglob
-
-export PATH=/empty
-for i in @path@; do PATH=$PATH:$i/bin; done
-
-if test $# -ne 1; then
-    echo "Usage: init-script-builder.sh DEFAULT-CONFIG"
-    exit 1
-fi
-
-defaultConfig="$1"
-
-
-[ "$(stat -f -c '%i' /)" = "$(stat -f -c '%i' /boot)" ] || {
-  # see grub-menu-builder.sh
-  echo "WARNING: /boot being on a different filesystem not supported by init-script-builder.sh"
-}
-
-
-
-target="/sbin/init"
-targetOther="/boot/init-other-configurations-contents.txt"
-
-tmp="$target.tmp"
-tmpOther="$targetOther.tmp"
-
-
-configurationCounter=0
-numAlienEntries=`cat <<EOF | egrep '^[[:space:]]*title' | wc -l
-@extraEntries@
-EOF`
-
-
-
-
-# Add an entry to $targetOther
-addEntry() {
-    local name="$1"
-    local path="$2"
-    local shortSuffix="$3"
-
-    configurationCounter=$((configurationCounter + 1))
-
-    local stage2=$path/init
-
-    content="$(
-      echo "#!/bin/sh"
-      echo "# $name"
-      echo "# created by init-script-builder.sh"
-      echo "exec $stage2"
-    )"
-
-    [ "$path" != "$defaultConfig" ] || {
-      echo "$content" > $tmp
-      echo "# older configurations: $targetOther" >> $tmp
-      chmod +x $tmp
-    }
-
-    echo -e "$content\n\n" >> $tmpOther
-}
-
-
-mkdir -p /boot /sbin
-
-addEntry "NixOS - Default" $defaultConfig ""
-
-# Add all generations of the system profile to the menu, in reverse
-# (most recent to least recent) order.
-for link in $((ls -d $defaultConfig/specialisation/* ) | sort -n); do
-    date=$(stat --printf="%y\n" $link | sed 's/\..*//')
-    addEntry "NixOS - variation" $link ""
-done
-
-for generation in $(
-    (cd /nix/var/nix/profiles && ls -d system-*-link) \
-    | sed 's/system-\([0-9]\+\)-link/\1/' \
-    | sort -n -r); do
-    link=/nix/var/nix/profiles/system-$generation-link
-    date=$(stat --printf="%y\n" $link | sed 's/\..*//')
-    if [ -d $link/kernel ]; then
-      kernelVersion=$(cd $(dirname $(readlink -f $link/kernel))/lib/modules && echo *)
-      suffix="($date - $kernelVersion)"
-    else
-      suffix="($date)"
-    fi
-    addEntry "NixOS - Configuration $generation $suffix" $link "$generation ($date)"
-done
-
-mv $tmpOther $targetOther
-mv $tmp $target
diff --git a/nixos/modules/system/boot/loader/init-script/init-script.nix b/nixos/modules/system/boot/loader/init-script/init-script.nix
deleted file mode 100644
index 374d9524ff1..00000000000
--- a/nixos/modules/system/boot/loader/init-script/init-script.nix
+++ /dev/null
@@ -1,51 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  initScriptBuilder = pkgs.substituteAll {
-    src = ./init-script-builder.sh;
-    isExecutable = true;
-    inherit (pkgs) bash;
-    path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
-  };
-
-in
-
-{
-
-  ###### interface
-
-  options = {
-
-    boot.loader.initScript = {
-
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Some systems require a /sbin/init script which is started.
-          Or having it makes starting NixOS easier.
-          This applies to some kind of hosting services and user mode linux.
-
-          Additionally this script will create
-          /boot/init-other-configurations-contents.txt containing
-          contents of remaining configurations. You can copy paste them into
-          /sbin/init manually running a rescue system or such.
-        '';
-      };
-    };
-
-  };
-
-
-  ###### implementation
-
-  config = mkIf config.boot.loader.initScript.enable {
-
-    system.build.installBootLoader = initScriptBuilder;
-
-  };
-
-}
diff --git a/nixos/modules/system/boot/loader/loader.nix b/nixos/modules/system/boot/loader/loader.nix
deleted file mode 100644
index 01475f79b9c..00000000000
--- a/nixos/modules/system/boot/loader/loader.nix
+++ /dev/null
@@ -1,20 +0,0 @@
-{ lib, ... }:
-
-with lib;
-
-{
-  imports = [
-    (mkRenamedOptionModule [ "boot" "loader" "grub" "timeout" ] [ "boot" "loader" "timeout" ])
-    (mkRenamedOptionModule [ "boot" "loader" "gummiboot" "timeout" ] [ "boot" "loader" "timeout" ])
-  ];
-
-    options = {
-        boot.loader.timeout =  mkOption {
-            default = 5;
-            type = types.nullOr types.int;
-            description = ''
-              Timeout (in seconds) until loader boots the default menu item. Use null if the loader menu should be displayed indefinitely.
-            '';
-        };
-    };
-}
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix
deleted file mode 100644
index 64e106036ab..00000000000
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix
+++ /dev/null
@@ -1,9 +0,0 @@
-{ pkgs, configTxt, firmware ? pkgs.raspberrypifw }:
-
-pkgs.substituteAll {
-  src = ./raspberrypi-builder.sh;
-  isExecutable = true;
-  inherit (pkgs) bash;
-  path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
-  inherit firmware configTxt;
-}
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
deleted file mode 100644
index 0541ca1ba62..00000000000
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
+++ /dev/null
@@ -1,143 +0,0 @@
-#! @bash@/bin/sh
-
-# This can end up being called disregarding the shebang.
-set -e
-
-shopt -s nullglob
-
-export PATH=/empty
-for i in @path@; do PATH=$PATH:$i/bin; done
-
-usage() {
-    echo "usage: $0 -c <path-to-default-configuration> [-d <boot-dir>]" >&2
-    exit 1
-}
-
-default=                # Default configuration
-target=/boot            # Target directory
-
-while getopts "c:d:" opt; do
-    case "$opt" in
-        c) default="$OPTARG" ;;
-        d) target="$OPTARG" ;;
-        \?) usage ;;
-    esac
-done
-
-echo "updating the boot generations directory..."
-
-mkdir -p $target/old
-
-# Convert a path to a file in the Nix store such as
-# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
-cleanName() {
-    local path="$1"
-    echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g'
-}
-
-# Copy a file from the Nix store to $target/kernels.
-declare -A filesCopied
-
-copyToKernelsDir() {
-    local src="$1"
-    local dst="$target/old/$(cleanName $src)"
-    # Don't copy the file if $dst already exists.  This means that we
-    # have to create $dst atomically to prevent partially copied
-    # kernels or initrd if this script is ever interrupted.
-    if ! test -e $dst; then
-        local dstTmp=$dst.tmp.$$
-        cp $src $dstTmp
-        mv $dstTmp $dst
-    fi
-    filesCopied[$dst]=1
-    result=$dst
-}
-
-copyForced() {
-    local src="$1"
-    local dst="$2"
-    cp $src $dst.tmp
-    mv $dst.tmp $dst
-}
-
-outdir=$target/old
-mkdir -p $outdir || true
-
-# Copy its kernel and initrd to $target/old.
-addEntry() {
-    local path="$1"
-    local generation="$2"
-
-    if ! test -e $path/kernel -a -e $path/initrd; then
-        return
-    fi
-
-    local kernel=$(readlink -f $path/kernel)
-    local initrd=$(readlink -f $path/initrd)
-    local dtb_path=$(readlink -f $path/dtbs)
-
-    if test -n "@copyKernels@"; then
-        copyToKernelsDir $kernel; kernel=$result
-        copyToKernelsDir $initrd; initrd=$result
-    fi
-
-    echo $(readlink -f $path) > $outdir/$generation-system
-    echo $(readlink -f $path/init) > $outdir/$generation-init
-    cp $path/kernel-params $outdir/$generation-cmdline.txt
-    echo $initrd > $outdir/$generation-initrd
-    echo $kernel > $outdir/$generation-kernel
-
-    if test "$generation" = "default"; then
-      copyForced $kernel $target/kernel.img
-      copyForced $initrd $target/initrd
-      for dtb in $dtb_path/{broadcom,}/bcm*.dtb; do
-        dst="$target/$(basename $dtb)"
-        copyForced $dtb "$dst"
-        filesCopied[$dst]=1
-      done
-      cp "$(readlink -f "$path/init")" $target/nixos-init
-      echo "`cat $path/kernel-params` init=$path/init" >$target/cmdline.txt
-    fi
-}
-
-addEntry $default default
-
-# Add all generations of the system profile to the menu, in reverse
-# (most recent to least recent) order.
-for generation in $(
-    (cd /nix/var/nix/profiles && ls -d system-*-link) \
-    | sed 's/system-\([0-9]\+\)-link/\1/' \
-    | sort -n -r); do
-    link=/nix/var/nix/profiles/system-$generation-link
-    addEntry $link $generation
-done
-
-# Add the firmware files
-fwdir=@firmware@/share/raspberrypi/boot/
-copyForced $fwdir/bootcode.bin  $target/bootcode.bin
-copyForced $fwdir/fixup.dat     $target/fixup.dat
-copyForced $fwdir/fixup4.dat    $target/fixup4.dat
-copyForced $fwdir/fixup4cd.dat  $target/fixup4cd.dat
-copyForced $fwdir/fixup4db.dat  $target/fixup4db.dat
-copyForced $fwdir/fixup4x.dat   $target/fixup4x.dat
-copyForced $fwdir/fixup_cd.dat  $target/fixup_cd.dat
-copyForced $fwdir/fixup_db.dat  $target/fixup_db.dat
-copyForced $fwdir/fixup_x.dat   $target/fixup_x.dat
-copyForced $fwdir/start.elf     $target/start.elf
-copyForced $fwdir/start4.elf    $target/start4.elf
-copyForced $fwdir/start4cd.elf  $target/start4cd.elf
-copyForced $fwdir/start4db.elf  $target/start4db.elf
-copyForced $fwdir/start4x.elf   $target/start4x.elf
-copyForced $fwdir/start_cd.elf  $target/start_cd.elf
-copyForced $fwdir/start_db.elf  $target/start_db.elf
-copyForced $fwdir/start_x.elf   $target/start_x.elf
-
-# Add the config.txt
-copyForced @configTxt@ $target/config.txt
-
-# Remove obsolete files from $target and $target/old.
-for fn in $target/old/*linux* $target/old/*initrd-initrd* $target/bcm*.dtb; do
-    if ! test "${filesCopied[$fn]}" = 1; then
-        rm -vf -- "$fn"
-    fi
-done
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
deleted file mode 100644
index 1023361f0b1..00000000000
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
+++ /dev/null
@@ -1,105 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.boot.loader.raspberryPi;
-
-  builderUboot = import ./uboot-builder.nix { inherit pkgs configTxt; inherit (cfg) version; };
-  builderGeneric = import ./raspberrypi-builder.nix { inherit pkgs configTxt; };
-
-  builder =
-    if cfg.uboot.enable then
-      "${builderUboot} -g ${toString cfg.uboot.configurationLimit} -t ${timeoutStr} -c"
-    else
-      "${builderGeneric} -c";
-
-  blCfg = config.boot.loader;
-  timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
-
-  isAarch64 = pkgs.stdenv.hostPlatform.isAarch64;
-  optional = pkgs.lib.optionalString;
-
-  configTxt =
-    pkgs.writeText "config.txt" (''
-      # U-Boot used to need this to work, regardless of whether UART is actually used or not.
-      # TODO: check when/if this can be removed.
-      enable_uart=1
-
-      # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
-      # when attempting to show low-voltage or overtemperature warnings.
-      avoid_warnings=1
-    '' + optional isAarch64 ''
-      # Boot in 64-bit mode.
-      arm_64bit=1
-    '' + (if cfg.uboot.enable then ''
-      kernel=u-boot-rpi.bin
-    '' else ''
-      kernel=kernel.img
-      initramfs initrd followkernel
-    '') + optional (cfg.firmwareConfig != null) cfg.firmwareConfig);
-
-in
-
-{
-  options = {
-
-    boot.loader.raspberryPi = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to create files with the system generations in
-          <literal>/boot</literal>.
-          <literal>/boot/old</literal> will hold files from old generations.
-        '';
-      };
-
-      version = mkOption {
-        default = 2;
-        type = types.enum [ 0 1 2 3 4 ];
-        description = "";
-      };
-
-      uboot = {
-        enable = mkOption {
-          default = false;
-          type = types.bool;
-          description = ''
-            Enable using uboot as bootmanager for the raspberry pi.
-          '';
-        };
-
-        configurationLimit = mkOption {
-          default = 20;
-          example = 10;
-          type = types.int;
-          description = ''
-            Maximum number of configurations in the boot menu.
-          '';
-        };
-
-      };
-
-      firmwareConfig = mkOption {
-        default = null;
-        type = types.nullOr types.lines;
-        description = ''
-          Extra options that will be appended to <literal>/boot/config.txt</literal> file.
-          For possible values, see: https://www.raspberrypi.org/documentation/configuration/config-txt/
-        '';
-      };
-    };
-  };
-
-  config = mkIf cfg.enable {
-    assertions = singleton {
-      assertion = !pkgs.stdenv.hostPlatform.isAarch64 || cfg.version >= 3;
-      message = "Only Raspberry Pi >= 3 supports aarch64.";
-    };
-
-    system.build.installBootLoader = builder;
-    system.boot.loader.id = "raspberrypi";
-    system.boot.loader.kernelFile = pkgs.stdenv.hostPlatform.linux-kernel.target;
-  };
-}
diff --git a/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.nix b/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.nix
deleted file mode 100644
index a4352ab9a24..00000000000
--- a/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.nix
+++ /dev/null
@@ -1,37 +0,0 @@
-{ pkgs, version, configTxt }:
-
-let
-  isAarch64 = pkgs.stdenv.hostPlatform.isAarch64;
-
-  uboot =
-    if version == 0 then
-      pkgs.ubootRaspberryPiZero
-    else if version == 1 then
-      pkgs.ubootRaspberryPi
-    else if version == 2 then
-      pkgs.ubootRaspberryPi2
-    else if version == 3 then
-      if isAarch64 then
-        pkgs.ubootRaspberryPi3_64bit
-      else
-        pkgs.ubootRaspberryPi3_32bit
-    else
-      throw "U-Boot is not yet supported on the raspberry pi 4.";
-
-  extlinuxConfBuilder =
-    import ../generic-extlinux-compatible/extlinux-conf-builder.nix {
-      pkgs = pkgs.buildPackages;
-    };
-in
-pkgs.substituteAll {
-  src = ./uboot-builder.sh;
-  isExecutable = true;
-  inherit (pkgs) bash;
-  path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
-  firmware = pkgs.raspberrypifw;
-  inherit uboot;
-  inherit configTxt;
-  inherit extlinuxConfBuilder;
-  inherit version;
-}
-
diff --git a/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh b/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh
deleted file mode 100644
index ea591427179..00000000000
--- a/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#! @bash@/bin/sh -e
-
-target=/boot # Target directory
-
-while getopts "t:c:d:g:" opt; do
-    case "$opt" in
-        d) target="$OPTARG" ;;
-        *) ;;
-    esac
-done
-
-copyForced() {
-    local src="$1"
-    local dst="$2"
-    cp $src $dst.tmp
-    mv $dst.tmp $dst
-}
-
-# Call the extlinux builder
-"@extlinuxConfBuilder@" "$@"
-
-# Add the firmware files
-fwdir=@firmware@/share/raspberrypi/boot/
-copyForced $fwdir/bootcode.bin  $target/bootcode.bin
-copyForced $fwdir/fixup.dat     $target/fixup.dat
-copyForced $fwdir/fixup_cd.dat  $target/fixup_cd.dat
-copyForced $fwdir/fixup_db.dat  $target/fixup_db.dat
-copyForced $fwdir/fixup_x.dat   $target/fixup_x.dat
-copyForced $fwdir/start.elf     $target/start.elf
-copyForced $fwdir/start_cd.elf  $target/start_cd.elf
-copyForced $fwdir/start_db.elf  $target/start_db.elf
-copyForced $fwdir/start_x.elf   $target/start_x.elf
-
-# Add the uboot file
-copyForced @uboot@/u-boot.bin $target/u-boot-rpi.bin
-
-# Add the config.txt
-copyForced @configTxt@ $target/config.txt
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
deleted file mode 100644
index adc89306309..00000000000
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ /dev/null
@@ -1,305 +0,0 @@
-#! @python3@/bin/python3 -B
-import argparse
-import shutil
-import os
-import sys
-import errno
-import subprocess
-import glob
-import tempfile
-import errno
-import warnings
-import ctypes
-libc = ctypes.CDLL("libc.so.6")
-import re
-import datetime
-import glob
-import os.path
-from typing import Tuple, List, Optional
-
-SystemIdentifier = Tuple[Optional[str], int, Optional[str]]
-
-
-def copy_if_not_exists(source: str, dest: str) -> None:
-    if not os.path.exists(dest):
-        shutil.copyfile(source, dest)
-
-
-def generation_dir(profile: Optional[str], generation: int) -> str:
-    if profile:
-        return "/nix/var/nix/profiles/system-profiles/%s-%d-link" % (profile, generation)
-    else:
-        return "/nix/var/nix/profiles/system-%d-link" % (generation)
-
-def system_dir(profile: Optional[str], generation: int, specialisation: Optional[str]) -> str:
-    d = generation_dir(profile, generation)
-    if specialisation:
-        return os.path.join(d, "specialisation", specialisation)
-    else:
-        return d
-
-BOOT_ENTRY = """title NixOS{profile}{specialisation}
-version Generation {generation} {description}
-linux {kernel}
-initrd {initrd}
-options {kernel_params}
-"""
-
-def generation_conf_filename(profile: Optional[str], generation: int, specialisation: Optional[str]) -> str:
-    pieces = [
-        "nixos",
-        profile or None,
-        "generation",
-        str(generation),
-        f"specialisation-{specialisation}" if specialisation else None,
-    ]
-    return "-".join(p for p in pieces if p) + ".conf"
-
-
-def write_loader_conf(profile: Optional[str], generation: int, specialisation: Optional[str]) -> None:
-    with open("@efiSysMountPoint@/loader/loader.conf.tmp", 'w') as f:
-        if "@timeout@" != "":
-            f.write("timeout @timeout@\n")
-        f.write("default %s\n" % generation_conf_filename(profile, generation, specialisation))
-        if not @editor@:
-            f.write("editor 0\n");
-        f.write("console-mode @consoleMode@\n");
-    os.rename("@efiSysMountPoint@/loader/loader.conf.tmp", "@efiSysMountPoint@/loader/loader.conf")
-
-
-def profile_path(profile: Optional[str], generation: int, specialisation: Optional[str], name: str) -> str:
-    return os.path.realpath("%s/%s" % (system_dir(profile, generation, specialisation), name))
-
-
-def copy_from_profile(profile: Optional[str], generation: int, specialisation: Optional[str], name: str, dry_run: bool = False) -> str:
-    store_file_path = profile_path(profile, generation, specialisation, name)
-    suffix = os.path.basename(store_file_path)
-    store_dir = os.path.basename(os.path.dirname(store_file_path))
-    efi_file_path = "/efi/nixos/%s-%s.efi" % (store_dir, suffix)
-    if not dry_run:
-        copy_if_not_exists(store_file_path, "@efiSysMountPoint@%s" % (efi_file_path))
-    return efi_file_path
-
-
-def describe_generation(generation_dir: str) -> str:
-    try:
-        with open("%s/nixos-version" % generation_dir) as f:
-            nixos_version = f.read()
-    except IOError:
-        nixos_version = "Unknown"
-
-    kernel_dir = os.path.dirname(os.path.realpath("%s/kernel" % generation_dir))
-    module_dir = glob.glob("%s/lib/modules/*" % kernel_dir)[0]
-    kernel_version = os.path.basename(module_dir)
-
-    build_time = int(os.path.getctime(generation_dir))
-    build_date = datetime.datetime.fromtimestamp(build_time).strftime('%F')
-
-    description = "NixOS {}, Linux Kernel {}, Built on {}".format(
-        nixos_version, kernel_version, build_date
-    )
-
-    return description
-
-
-def write_entry(profile: Optional[str], generation: int, specialisation: Optional[str], machine_id: str) -> None:
-    kernel = copy_from_profile(profile, generation, specialisation, "kernel")
-    initrd = copy_from_profile(profile, generation, specialisation, "initrd")
-    try:
-        append_initrd_secrets = profile_path(profile, generation, specialisation, "append-initrd-secrets")
-        subprocess.check_call([append_initrd_secrets, "@efiSysMountPoint@%s" % (initrd)])
-    except FileNotFoundError:
-        pass
-    entry_file = "@efiSysMountPoint@/loader/entries/%s" % (
-        generation_conf_filename(profile, generation, specialisation))
-    generation_dir = os.readlink(system_dir(profile, generation, specialisation))
-    tmp_path = "%s.tmp" % (entry_file)
-    kernel_params = "init=%s/init " % generation_dir
-
-    with open("%s/kernel-params" % (generation_dir)) as params_file:
-        kernel_params = kernel_params + params_file.read()
-    with open(tmp_path, 'w') as f:
-        f.write(BOOT_ENTRY.format(profile=" [" + profile + "]" if profile else "",
-                    specialisation=" (%s)" % specialisation if specialisation else "",
-                    generation=generation,
-                    kernel=kernel,
-                    initrd=initrd,
-                    kernel_params=kernel_params,
-                    description=describe_generation(generation_dir)))
-        if machine_id is not None:
-            f.write("machine-id %s\n" % machine_id)
-    os.rename(tmp_path, entry_file)
-
-
-def mkdir_p(path: str) -> None:
-    try:
-        os.makedirs(path)
-    except OSError as e:
-        if e.errno != errno.EEXIST or not os.path.isdir(path):
-            raise
-
-
-def get_generations(profile: Optional[str] = None) -> List[SystemIdentifier]:
-    gen_list = subprocess.check_output([
-        "@nix@/bin/nix-env",
-        "--list-generations",
-        "-p",
-        "/nix/var/nix/profiles/%s" % ("system-profiles/" + profile if profile else "system"),
-        "--option", "build-users-group", ""],
-        universal_newlines=True)
-    gen_lines = gen_list.split('\n')
-    gen_lines.pop()
-
-    configurationLimit = @configurationLimit@
-    configurations: List[SystemIdentifier] = [ (profile, int(line.split()[0]), None) for line in gen_lines ]
-    return configurations[-configurationLimit:]
-
-
-def get_specialisations(profile: Optional[str], generation: int, _: Optional[str]) -> List[SystemIdentifier]:
-    specialisations_dir = os.path.join(
-            system_dir(profile, generation, None), "specialisation")
-    if not os.path.exists(specialisations_dir):
-        return []
-    return [(profile, generation, spec) for spec in os.listdir(specialisations_dir)]
-
-
-def remove_old_entries(gens: List[SystemIdentifier]) -> None:
-    rex_profile = re.compile("^@efiSysMountPoint@/loader/entries/nixos-(.*)-generation-.*\.conf$")
-    rex_generation = re.compile("^@efiSysMountPoint@/loader/entries/nixos.*-generation-(.*)\.conf$")
-    known_paths = []
-    for gen in gens:
-        known_paths.append(copy_from_profile(*gen, "kernel", True))
-        known_paths.append(copy_from_profile(*gen, "initrd", True))
-    for path in glob.iglob("@efiSysMountPoint@/loader/entries/nixos*-generation-[1-9]*.conf"):
-        try:
-            if rex_profile.match(path):
-                prof = rex_profile.sub(r"\1", path)
-            else:
-                prof = "system"
-            gen_number = int(rex_generation.sub(r"\1", path))
-            if not (prof, gen_number) in gens:
-                os.unlink(path)
-        except ValueError:
-            pass
-    for path in glob.iglob("@efiSysMountPoint@/efi/nixos/*"):
-        if not path in known_paths and not os.path.isdir(path):
-            os.unlink(path)
-
-
-def get_profiles() -> List[str]:
-    if os.path.isdir("/nix/var/nix/profiles/system-profiles/"):
-        return [x
-            for x in os.listdir("/nix/var/nix/profiles/system-profiles/")
-            if not x.endswith("-link")]
-    else:
-        return []
-
-
-def main() -> None:
-    parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files')
-    parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default NixOS config to boot')
-    args = parser.parse_args()
-
-    try:
-        with open("/etc/machine-id") as machine_file:
-            machine_id = machine_file.readlines()[0]
-    except IOError as e:
-        if e.errno != errno.ENOENT:
-            raise
-        # Since systemd version 232 a machine ID is required and it might not
-        # be there on newly installed systems, so let's generate one so that
-        # bootctl can find it and we can also pass it to write_entry() later.
-        cmd = ["@systemd@/bin/systemd-machine-id-setup", "--print"]
-        machine_id = subprocess.run(
-          cmd, text=True, check=True, stdout=subprocess.PIPE
-        ).stdout.rstrip()
-
-    if os.getenv("NIXOS_INSTALL_GRUB") == "1":
-        warnings.warn("NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER", DeprecationWarning)
-        os.environ["NIXOS_INSTALL_BOOTLOADER"] = "1"
-
-    if os.getenv("NIXOS_INSTALL_BOOTLOADER") == "1":
-        # bootctl uses fopen() with modes "wxe" and fails if the file exists.
-        if os.path.exists("@efiSysMountPoint@/loader/loader.conf"):
-            os.unlink("@efiSysMountPoint@/loader/loader.conf")
-
-        flags = []
-
-        if "@canTouchEfiVariables@" != "1":
-            flags.append("--no-variables")
-
-        if "@graceful@" == "1":
-            flags.append("--graceful")
-
-        subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@"] + flags + ["install"])
-    else:
-        # Update bootloader to latest if needed
-        systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2]
-        sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True)
-
-        # See status_binaries() in systemd bootctl.c for code which generates this
-        m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$",
-                      sdboot_status, re.IGNORECASE | re.MULTILINE)
-
-        needs_install = False
-
-        if m is None:
-            print("could not find any previously installed systemd-boot, installing.")
-            # Let systemd-boot attempt an installation if a previous one wasn't found
-            needs_install = True
-        else:
-            sdboot_version = f'({m.group(2)})'
-            if systemd_version != sdboot_version:
-                print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version))
-                needs_install = True
-
-        if needs_install:
-            subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"])
-
-    mkdir_p("@efiSysMountPoint@/efi/nixos")
-    mkdir_p("@efiSysMountPoint@/loader/entries")
-
-    gens = get_generations()
-    for profile in get_profiles():
-        gens += get_generations(profile)
-    remove_old_entries(gens)
-    for gen in gens:
-        try:
-            write_entry(*gen, machine_id)
-            for specialisation in get_specialisations(*gen):
-                write_entry(*specialisation, machine_id)
-            if os.readlink(system_dir(*gen)) == args.default_config:
-                write_loader_conf(*gen)
-        except OSError as e:
-            print("ignoring generation '{}' in the list of boot entries because of the following error:\n{}".format(*gen, e), file=sys.stderr)
-
-    for root, _, files in os.walk('@efiSysMountPoint@/efi/nixos/.extra-files', topdown=False):
-        relative_root = root.removeprefix("@efiSysMountPoint@/efi/nixos/.extra-files").removeprefix("/")
-        actual_root = os.path.join("@efiSysMountPoint@", relative_root)
-
-        for file in files:
-            actual_file = os.path.join(actual_root, file)
-
-            if os.path.exists(actual_file):
-                os.unlink(actual_file)
-            os.unlink(os.path.join(root, file))
-
-        if not len(os.listdir(actual_root)):
-            os.rmdir(actual_root)
-        os.rmdir(root)
-
-    mkdir_p("@efiSysMountPoint@/efi/nixos/.extra-files")
-
-    subprocess.check_call("@copyExtraFiles@")
-
-    # Since fat32 provides little recovery facilities after a crash,
-    # it can leave the system in an unbootable state, when a crash/outage
-    # happens shortly after an update. To decrease the likelihood of this
-    # event sync the efi filesystem after each update.
-    rc = libc.syncfs(os.open("@efiSysMountPoint@", os.O_RDONLY))
-    if rc != 0:
-        print("could not sync @efiSysMountPoint@: {}".format(os.strerror(rc)), file=sys.stderr)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
deleted file mode 100644
index c07567ec82e..00000000000
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ /dev/null
@@ -1,303 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.boot.loader.systemd-boot;
-
-  efi = config.boot.loader.efi;
-
-  systemdBootBuilder = pkgs.substituteAll {
-    src = ./systemd-boot-builder.py;
-
-    isExecutable = true;
-
-    inherit (pkgs) python3;
-
-    systemd = config.systemd.package;
-
-    nix = config.nix.package.out;
-
-    timeout = if config.boot.loader.timeout != null then config.boot.loader.timeout else "";
-
-    editor = if cfg.editor then "True" else "False";
-
-    configurationLimit = if cfg.configurationLimit == null then 0 else cfg.configurationLimit;
-
-    inherit (cfg) consoleMode graceful;
-
-    inherit (efi) efiSysMountPoint canTouchEfiVariables;
-
-    memtest86 = if cfg.memtest86.enable then pkgs.memtest86-efi else "";
-
-    netbootxyz = if cfg.netbootxyz.enable then pkgs.netbootxyz-efi else "";
-
-    copyExtraFiles = pkgs.writeShellScript "copy-extra-files" ''
-      empty_file=$(mktemp)
-
-      ${concatStrings (mapAttrsToList (n: v: ''
-        ${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n}
-        ${pkgs.coreutils}/bin/install -D $empty_file "${efi.efiSysMountPoint}/efi/nixos/.extra-files/"${escapeShellArg n}
-      '') cfg.extraFiles)}
-
-      ${concatStrings (mapAttrsToList (n: v: ''
-        ${pkgs.coreutils}/bin/install -Dp "${pkgs.writeText n v}" "${efi.efiSysMountPoint}/loader/entries/"${escapeShellArg n}
-        ${pkgs.coreutils}/bin/install -D $empty_file "${efi.efiSysMountPoint}/efi/nixos/.extra-files/loader/entries/"${escapeShellArg n}
-      '') cfg.extraEntries)}
-    '';
-  };
-
-  checkedSystemdBootBuilder = pkgs.runCommand "systemd-boot" {
-    nativeBuildInputs = [ pkgs.mypy ];
-  } ''
-    install -m755 ${systemdBootBuilder} $out
-    mypy \
-      --no-implicit-optional \
-      --disallow-untyped-calls \
-      --disallow-untyped-defs \
-      $out
-  '';
-in {
-
-  imports =
-    [ (mkRenamedOptionModule [ "boot" "loader" "gummiboot" "enable" ] [ "boot" "loader" "systemd-boot" "enable" ])
-    ];
-
-  options.boot.loader.systemd-boot = {
-    enable = mkOption {
-      default = false;
-
-      type = types.bool;
-
-      description = "Whether to enable the systemd-boot (formerly gummiboot) EFI boot manager";
-    };
-
-    editor = mkOption {
-      default = true;
-
-      type = types.bool;
-
-      description = ''
-        Whether to allow editing the kernel command-line before
-        boot. It is recommended to set this to false, as it allows
-        gaining root access by passing init=/bin/sh as a kernel
-        parameter. However, it is enabled by default for backwards
-        compatibility.
-      '';
-    };
-
-    configurationLimit = mkOption {
-      default = null;
-      example = 120;
-      type = types.nullOr types.int;
-      description = ''
-        Maximum number of latest generations in the boot menu.
-        Useful to prevent boot partition running out of disk space.
-
-        <literal>null</literal> means no limit i.e. all generations
-        that were not garbage collected yet.
-      '';
-    };
-
-    consoleMode = mkOption {
-      default = "keep";
-
-      type = types.enum [ "0" "1" "2" "auto" "max" "keep" ];
-
-      description = ''
-        The resolution of the console. The following values are valid:
-
-        <itemizedlist>
-          <listitem><para>
-            <literal>"0"</literal>: Standard UEFI 80x25 mode
-          </para></listitem>
-          <listitem><para>
-            <literal>"1"</literal>: 80x50 mode, not supported by all devices
-          </para></listitem>
-          <listitem><para>
-            <literal>"2"</literal>: The first non-standard mode provided by the device firmware, if any
-          </para></listitem>
-          <listitem><para>
-            <literal>"auto"</literal>: Pick a suitable mode automatically using heuristics
-          </para></listitem>
-          <listitem><para>
-            <literal>"max"</literal>: Pick the highest-numbered available mode
-          </para></listitem>
-          <listitem><para>
-            <literal>"keep"</literal>: Keep the mode selected by firmware (the default)
-          </para></listitem>
-        </itemizedlist>
-      '';
-    };
-
-    memtest86 = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Make MemTest86 available from the systemd-boot menu. MemTest86 is a
-          program for testing memory.  MemTest86 is an unfree program, so
-          this requires <literal>allowUnfree</literal> to be set to
-          <literal>true</literal>.
-        '';
-      };
-
-      entryFilename = mkOption {
-        default = "memtest86.conf";
-        type = types.str;
-        description = ''
-          <literal>systemd-boot</literal> orders the menu entries by the config file names,
-          so if you want something to appear after all the NixOS entries,
-          it should start with <filename>o</filename> or onwards.
-        '';
-      };
-    };
-
-    netbootxyz = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Make <literal>netboot.xyz</literal> available from the
-          <literal>systemd-boot</literal> menu. <literal>netboot.xyz</literal>
-          is a menu system that allows you to boot OS installers and
-          utilities over the network.
-        '';
-      };
-
-      entryFilename = mkOption {
-        default = "o_netbootxyz.conf";
-        type = types.str;
-        description = ''
-          <literal>systemd-boot</literal> orders the menu entries by the config file names,
-          so if you want something to appear after all the NixOS entries,
-          it should start with <filename>o</filename> or onwards.
-        '';
-      };
-    };
-
-    extraEntries = mkOption {
-      type = types.attrsOf types.lines;
-      default = {};
-      example = literalExpression ''
-        { "memtest86.conf" = '''
-          title MemTest86
-          efi /efi/memtest86/memtest86.efi
-        '''; }
-      '';
-      description = ''
-        Any additional entries you want added to the <literal>systemd-boot</literal> menu.
-        These entries will be copied to <filename>/boot/loader/entries</filename>.
-        Each attribute name denotes the destination file name,
-        and the corresponding attribute value is the contents of the entry.
-
-        <literal>systemd-boot</literal> orders the menu entries by the config file names,
-        so if you want something to appear after all the NixOS entries,
-        it should start with <filename>o</filename> or onwards.
-      '';
-    };
-
-    extraFiles = mkOption {
-      type = types.attrsOf types.path;
-      default = {};
-      example = literalExpression ''
-        { "efi/memtest86/memtest86.efi" = "''${pkgs.memtest86-efi}/BOOTX64.efi"; }
-      '';
-      description = ''
-        A set of files to be copied to <filename>/boot</filename>.
-        Each attribute name denotes the destination file name in
-        <filename>/boot</filename>, while the corresponding
-        attribute value specifies the source file.
-      '';
-    };
-
-    graceful = mkOption {
-      default = false;
-
-      type = types.bool;
-
-      description = ''
-        Invoke <literal>bootctl install</literal> with the <literal>--graceful</literal> option,
-        which ignores errors when EFI variables cannot be written or when the EFI System Partition
-        cannot be found. Currently only applies to random seed operations.
-
-        Only enable this option if <literal>systemd-boot</literal> otherwise fails to install, as the
-        scope or implication of the <literal>--graceful</literal> option may change in the future.
-      '';
-    };
-
-  };
-
-  config = mkIf cfg.enable {
-    assertions = [
-      {
-        assertion = (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) ? efiBootStub;
-        message = "This kernel does not support the EFI boot stub";
-      }
-    ] ++ concatMap (filename: [
-      {
-        assertion = !(hasInfix "/" filename);
-        message = "boot.loader.systemd-boot.extraEntries.${lib.strings.escapeNixIdentifier filename} is invalid: entries within folders are not supported";
-      }
-      {
-        assertion = hasSuffix ".conf" filename;
-        message = "boot.loader.systemd-boot.extraEntries.${lib.strings.escapeNixIdentifier filename} is invalid: entries must have a .conf file extension";
-      }
-    ]) (builtins.attrNames cfg.extraEntries)
-      ++ concatMap (filename: [
-        {
-          assertion = !(hasPrefix "/" filename);
-          message = "boot.loader.systemd-boot.extraFiles.${lib.strings.escapeNixIdentifier filename} is invalid: paths must not begin with a slash";
-        }
-        {
-          assertion = !(hasInfix ".." filename);
-          message = "boot.loader.systemd-boot.extraFiles.${lib.strings.escapeNixIdentifier filename} is invalid: paths must not reference the parent directory";
-        }
-        {
-          assertion = !(hasInfix "nixos/.extra-files" (toLower filename));
-          message = "boot.loader.systemd-boot.extraFiles.${lib.strings.escapeNixIdentifier filename} is invalid: files cannot be placed in the nixos/.extra-files directory";
-        }
-      ]) (builtins.attrNames cfg.extraFiles);
-
-    boot.loader.grub.enable = mkDefault false;
-
-    boot.loader.supportsInitrdSecrets = true;
-
-    boot.loader.systemd-boot.extraFiles = mkMerge [
-      # TODO: This is hard-coded to use the 64-bit EFI app, but it could probably
-      # be updated to use the 32-bit EFI app on 32-bit systems.  The 32-bit EFI
-      # app filename is BOOTIA32.efi.
-      (mkIf cfg.memtest86.enable {
-        "efi/memtest86/BOOTX64.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi";
-      })
-      (mkIf cfg.netbootxyz.enable {
-        "efi/netbootxyz/netboot.xyz.efi" = "${pkgs.netbootxyz-efi}";
-      })
-    ];
-
-    boot.loader.systemd-boot.extraEntries = mkMerge [
-      (mkIf cfg.memtest86.enable {
-        "${cfg.memtest86.entryFilename}" = ''
-          title  MemTest86
-          efi    /efi/memtest86/BOOTX64.efi
-        '';
-      })
-      (mkIf cfg.netbootxyz.enable {
-        "${cfg.netbootxyz.entryFilename}" = ''
-          title  netboot.xyz
-          efi    /efi/netbootxyz/netboot.xyz.efi
-        '';
-      })
-    ];
-
-    system = {
-      build.installBootLoader = checkedSystemdBootBuilder;
-
-      boot.loader.id = "systemd-boot";
-
-      requiredKernelConfig = with config.lib.kernelConfig; [
-        (isYes "EFI_STUB")
-      ];
-    };
-  };
-}