summary refs log tree commit diff
path: root/nixos/modules/system/boot
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/system/boot')
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix17
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl15
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh26
-rw-r--r--nixos/modules/system/boot/stage-1.nix32
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh36
-rw-r--r--nixos/modules/system/boot/stage-2.nix3
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix2
7 files changed, 61 insertions, 70 deletions
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index 0640ec306e18..61c34cc2f034 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -341,7 +341,7 @@ in
         default = false;
         type = types.bool;
         description = ''
-          Whether GRUB should be build against libzfs.
+          Whether GRUB should be built against libzfs.
           ZFS support is only available for GRUB v2.
           This option is ignored for GRUB v1.
         '';
@@ -351,7 +351,7 @@ in
         default = false;
         type = types.bool;
         description = ''
-          Whether GRUB should be build with EFI support.
+          Whether GRUB should be built with EFI support.
           EFI support is only available for GRUB v2.
           This option is ignored for GRUB v1.
         '';
@@ -425,13 +425,20 @@ in
         { path = "/boot"; inherit (cfg) devices; inherit (efi) efiSysMountPoint; }
       ];
 
-      system.build.installBootLoader = pkgs.writeScript "install-grub.sh" (''
+      system.build.installBootLoader =
+        let
+          install-grub-pl = pkgs.substituteAll {
+            src = ./install-grub.pl;
+            inherit (pkgs) utillinux;
+            btrfsprogs = pkgs.btrfs-progs;
+          };
+        in pkgs.writeScript "install-grub.sh" (''
         #!${pkgs.stdenv.shell}
         set -e
         export PERL5LIB=${makePerlPath (with pkgs.perlPackages; [ FileSlurp XMLLibXML XMLSAX ListCompare ])}
         ${optionalString cfg.enableCryptodisk "export GRUB_ENABLE_CRYPTODISK=y"}
       '' + flip concatMapStrings cfg.mirroredBoots (args: ''
-        ${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig args} $@
+        ${pkgs.perl}/bin/perl ${install-grub-pl} ${grubConfig args} $@
       ''));
 
       system.build.grub = grub;
@@ -500,7 +507,7 @@ in
 
 
   imports =
-    [ (mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ])
+    [ (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" ])
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index 4fa157641a4a..06eece5025f8 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -12,8 +12,10 @@ 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"); }
@@ -97,6 +99,8 @@ sub PathInMount {
     }
     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 => "");
@@ -136,7 +140,10 @@ my $driveid = 1;
 sub GrubFs {
     my ($dir) = @_;
     my $fs = GetFs($dir);
-    my $path = "/" . substr($dir, length($fs->mount));
+    my $path = substr($dir, length($fs->mount));
+    if (substr($path, 0, 1) ne "/") {
+      $path = "/$path";
+    }
     my $search = "";
 
     if ($grubVersion > 1) {
@@ -169,7 +176,7 @@ sub GrubFs {
                 $search = $types{$fsIdentifier} . ' ';
 
                 # Based on the type pull in the identifier from the system
-                my ($status, @devInfo) = runCommand("blkid -o export @{[$fs->device]}");
+                my ($status, @devInfo) = runCommand("@utillinux@/bin/blkid -o export @{[$fs->device]}");
                 if ($status != 0) {
                     die "Failed to get blkid info for @{[$fs->mount]} on @{[$fs->device]}";
                 }
@@ -182,7 +189,7 @@ sub GrubFs {
 
             # 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("btrfs subvol show @{[$fs->mount]}");
+                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";
                 }
@@ -190,7 +197,7 @@ sub GrubFs {
                 if ($#ids > 0) {
                     die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n"
                 } elsif ($#ids == 0) {
-                    my ($status, @path_info) = runCommand("btrfs subvol list @{[$fs->mount]}");
+                    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";
                     }
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 65d1dcb61681..abab5f20baac 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -59,22 +59,24 @@ echo
 echo "<<< NixOS Stage 1 >>>"
 echo
 
-
-# Mount special file systems.
+# Make several required directories.
 mkdir -p /etc/udev
 touch /etc/fstab # to shut up mount
-touch /etc/mtab # to shut up mke2fs
+ln -s /proc/mounts /etc/mtab # to shut up mke2fs
 touch /etc/udev/hwdb.bin # to shut up udev
 touch /etc/initrd-release
-mkdir -p /proc
-mount -t proc proc /proc
-mkdir -p /sys
-mount -t sysfs sysfs /sys
-mount -t devtmpfs -o "size=@devSize@" devtmpfs /dev
-mkdir -p /run
-mount -t tmpfs -o "mode=0755,size=@runSize@" tmpfs /run
-mkdir /dev/pts
-mount -t devpts devpts /dev/pts
+
+# Mount special file systems.
+specialMount() {
+  local device="$1"
+  local mountPoint="$2"
+  local options="$3"
+  local fsType="$4"
+
+  mkdir -m 0755 -p "$mountPoint"
+  mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
+}
+source @earlyMountScript@
 
 # Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
 mkdir -p /tmp
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 9be7ad4ae077..513c121347b1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -3,7 +3,7 @@
 # the modules necessary to mount the root file system, then calls the
 # init in the root file system to start the second boot stage.
 
-{ config, lib, pkgs, ... }:
+{ config, lib, utils, pkgs, ... }:
 
 with lib;
 
@@ -23,6 +23,12 @@ let
   };
 
 
+  # The initrd only has to mount `/` or any FS marked as necessary for
+  # booting (such as the FS containing `/nix/store`, or an FS needed for
+  # mounting `/`, like `/` on a loopback).
+  fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems;
+
+
   # Some additional utilities needed in stage 1, like mount, lvm, fsck
   # etc.  We don't want to bring in all of those packages, so we just
   # copy what we need.  Instead of using statically linked binaries,
@@ -71,7 +77,7 @@ let
       ln -sf kmod $out/bin/modprobe
 
       # Copy resize2fs if needed.
-      ${optionalString (any (fs: fs.autoResize) (attrValues config.fileSystems)) ''
+      ${optionalString (any (fs: fs.autoResize) fileSystems) ''
         # We need mke2fs in the initrd.
         copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
       ''}
@@ -128,21 +134,6 @@ let
     ''; # */
 
 
-  # The initrd only has to mount / or any FS marked as necessary for
-  # booting (such as the FS containing /nix/store, or an FS needed for
-  # mounting /, like / on a loopback).
-  #
-  # We need to guarantee that / is the first filesystem in the list so
-  # that if and when lustrateRoot is invoked, nothing else is mounted
-  fileSystems = let
-    filterNeeded = filter
-      (fs: fs.mountPoint != "/" && (fs.neededForBoot || elem fs.mountPoint [ "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ]));
-    filterRoot = filter
-      (fs: fs.mountPoint == "/");
-    allFileSystems = attrValues config.fileSystems;
-  in (filterRoot allFileSystems) ++ (filterNeeded allFileSystems);
-
-
   udevRules = pkgs.stdenv.mkDerivation {
     name = "udev-rules";
     allowedReferences = [ extraUtils ];
@@ -199,7 +190,9 @@ let
 
     inherit udevRules extraUtils modulesClosure;
 
-    inherit (config.boot) resumeDevice devSize runSize;
+    inherit (config.boot) resumeDevice;
+
+    inherit (config.system.build) earlyMountScript;
 
     inherit (config.boot.initrd) checkJournalingFS
       preLVMCommands preDeviceCommands postDeviceCommands postMountCommands preFailCommands kernelModules;
@@ -405,9 +398,8 @@ in
   };
 
   config = mkIf (!config.boot.isContainer) {
-
     assertions = [
-      { assertion = any (fs: fs.mountPoint == "/") (attrValues config.fileSystems);
+      { assertion = any (fs: fs.mountPoint == "/") fileSystems;
         message = "The ‘fileSystems’ option does not specify your root file system.";
       }
       { assertion = let inherit (config.boot) resumeDevice; in
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index c5a14f0766d5..704150e77d72 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -37,12 +37,16 @@ fi
 # Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a
 # stage 1, we need to do that here.
 if [ ! -e /proc/1 ]; then
-    mkdir -m 0755 -p /proc
-    mount -n -t proc proc /proc
-    mkdir -m 0755 -p /dev
-    mount -t devtmpfs devtmpfs /dev
-    mkdir -m 0755 -p /sys
-    mount -t sysfs sysfs /sys
+    specialMount() {
+        local device="$1"
+        local mountPoint="$2"
+        local options="$3"
+        local fsType="$4"
+
+        mkdir -m 0755 -p "$mountPoint"
+        mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
+    }
+    source @earlyMountScript@
 fi
 
 
@@ -87,11 +91,6 @@ done
 
 
 # More special file systems, initialise required directories.
-if ! mountpoint -q /dev/shm; then
-    mkdir -m 0755 /dev/shm
-    mount -t tmpfs -o "rw,nosuid,nodev,size=@devShmSize@" tmpfs /dev/shm
-fi
-mkdir -m 0755 -p /dev/pts
 [ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
 mkdir -m 01777 -p /tmp
 mkdir -m 0755 -p /var /var/log /var/lib /var/db
@@ -112,14 +111,6 @@ rm -f /etc/{group,passwd,shadow}.lock
 rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots
 
 
-# Create a tmpfs on /run to hold runtime state for programs such as
-# udev (if stage 1 hasn't already done so).
-if ! mountpoint -q /run; then
-    rm -rf /run
-    mkdir -m 0755 -p /run
-    mount -t tmpfs -o "mode=0755,size=@runSize@" tmpfs /run
-fi
-
 # Create a ramfs on /run/keys to hold secrets that shouldn't be
 # written to disk (generally used for NixOps, harmless elsewhere).
 if ! mountpoint -q /run/keys; then
@@ -150,13 +141,6 @@ if [ -n "@useHostResolvConf@" -a -e /etc/resolv.conf ]; then
     cat /etc/resolv.conf | resolvconf -m 1000 -a host
 fi
 
-
-# Create /var/setuid-wrappers as a tmpfs.
-rm -rf /var/setuid-wrappers
-mkdir -m 0755 -p /var/setuid-wrappers
-mount -t tmpfs -o "mode=0755" tmpfs /var/setuid-wrappers
-
-
 # Log the script output to /dev/kmsg or /run/log/stage-2-init.log.
 # Only at this point are all the necessary prerequisites ready for these commands.
 exec {logOutFd}>&1 {logErrFd}>&2
diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix
index b67f42a017e6..7e4ec2a4a670 100644
--- a/nixos/modules/system/boot/stage-2.nix
+++ b/nixos/modules/system/boot/stage-2.nix
@@ -20,10 +20,9 @@ let
     src = ./stage-2-init.sh;
     shellDebug = "${pkgs.bashInteractive}/bin/bash";
     isExecutable = true;
-    inherit (config.boot) devShmSize runSize;
     inherit (config.nix) readOnlyStore;
     inherit (config.networking) useHostResolvConf;
-    ttyGid = config.ids.gids.tty;
+    inherit (config.system.build) earlyMountScript;
     path =
       [ pkgs.coreutils
         pkgs.utillinux
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index f2a22e4ada8a..f4892244de47 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -309,7 +309,7 @@ in rec {
     };
 
     startAt = mkOption {
-      type = types.str;
+      type = with types; either str (listOf str);
       default = "";
       example = "Sun 14:00:00";
       description = ''