about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix')
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix94
1 files changed, 78 insertions, 16 deletions
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
index 1418420afcd9..c2836b5a9a1b 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -162,12 +162,14 @@ let
   isolinuxCfg = concatStringsSep "\n"
     ([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
 
+  refindBinary = if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null;
+
   # Setup instructions for rEFInd.
   refind =
-    if targetArch == "x64" then
+    if refindBinary != null then
       ''
       # Adds rEFInd to the ISO.
-      cp -v ${pkgs.refind}/share/refind/refind_x64.efi $out/EFI/boot/
+      cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/boot/
       ''
     else
       "# No refind for ${targetArch}"
@@ -180,13 +182,32 @@ let
     # Menu configuration
     #
 
+    # Search using a "marker file"
+    search --set=root --file /EFI/nixos-installer-image
+
     insmod gfxterm
     insmod png
     set gfxpayload=keep
+    set gfxmode=${concatStringsSep "," [
+      # GRUB will use the first valid mode listed here.
+      # `auto` will sometimes choose the smallest valid mode it detects.
+      # So instead we'll list a lot of possibly valid modes :/
+      #"3840x2160"
+      #"2560x1440"
+      "1920x1080"
+      "1366x768"
+      "1280x720"
+      "1024x768"
+      "800x600"
+      "auto"
+    ]}
 
     # Fonts can be loaded?
     # (This font is assumed to always be provided as a fallback by NixOS)
-    if loadfont (hd0)/EFI/boot/unicode.pf2; then
+    if loadfont (\$root)/EFI/boot/unicode.pf2; then
+      set with_fonts=true
+    fi
+    if [ "\$textmode" != "true" -a "\$with_fonts" == "true" ]; then
       # Use graphical term, it can be either with background image or a theme.
       # input is "console", while output is "gfxterm".
       # This enables "serial" input and output only when possible.
@@ -207,11 +228,11 @@ let
     ${ # When there is a theme configured, use it, otherwise use the background image.
     if config.isoImage.grubTheme != null then ''
       # Sets theme.
-      set theme=(hd0)/EFI/boot/grub-theme/theme.txt
+      set theme=(\$root)/EFI/boot/grub-theme/theme.txt
       # Load theme fonts
-      $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (hd0)/EFI/boot/grub-theme/%P\n")
+      $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
     '' else ''
-      if background_image (hd0)/EFI/boot/efi-background.png; then
+      if background_image (\$root)/EFI/boot/efi-background.png; then
         # Black background means transparent background when there
         # is a background image set... This seems undocumented :(
         set color_normal=black/black
@@ -228,9 +249,15 @@ let
   # Notes about grub:
   #  * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you
   #    will get white-on-black console-like text on sub-menus. *sigh*
-  efiDir = pkgs.runCommand "efi-directory" {} ''
+  efiDir = pkgs.runCommand "efi-directory" {
+    nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ];
+    strictDeps = true;
+  } ''
     mkdir -p $out/EFI/boot/
 
+    # Add a marker so GRUB can find the filesystem.
+    touch $out/EFI/nixos-installer-image
+
     # ALWAYS required modules.
     MODULES="fat iso9660 part_gpt part_msdos \
              normal boot linux configfile loopback chain halt \
@@ -258,12 +285,14 @@ let
 
     # Make our own efi program, we can't rely on "grub-install" since it seems to
     # probe for devices, even with --skip-fs-probe.
-    ${grubPkgs.grub2_efi}/bin/grub-mkimage -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${grubPkgs.grub2_efi.grubTarget} \
+    grub-mkimage --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${grubPkgs.grub2_efi.grubTarget} \
       $MODULES
     cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/
 
     cat <<EOF > $out/EFI/boot/grub.cfg
 
+    set with_fonts=false
+    set textmode=false
     # If you want to use serial for "terminal_*" commands, you need to set one up:
     #   Example manual configuration:
     #    → serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
@@ -273,8 +302,28 @@ let
     export with_serial
     clear
     set timeout=10
+
+    # This message will only be viewable when "gfxterm" is not used.
+    echo ""
+    echo "Loading graphical boot menu..."
+    echo ""
+    echo "Press 't' to use the text boot menu on this console..."
+    echo ""
+
     ${grubMenuCfg}
 
+    hiddenentry 'Text mode' --hotkey 't' {
+      loadfont (\$root)/EFI/boot/unicode.pf2
+      set textmode=true
+      terminal_output gfxterm console
+    }
+    hiddenentry 'GUI mode' --hotkey 'g' {
+      $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
+      set textmode=false
+      terminal_output gfxterm
+    }
+
+
     # If the parameter iso_path is set, append the findiso parameter to the kernel
     # line. We need this to allow the nixos iso to be booted from grub directly.
     if [ \''${iso_path} ] ; then
@@ -337,11 +386,17 @@ let
       }
     }
 
-    menuentry 'rEFInd' --class refind {
-      # UUID is hard-coded in the derivation.
+    ${lib.optionalString (refindBinary != null) ''
+    # GRUB apparently cannot do "chainloader" operations on "CD".
+    if [ "\$root" != "cd0" ]; then
+      # Force root to be the FAT partition
+      # Otherwise it breaks rEFInd's boot
       search --set=root --no-floppy --fs-uuid 1234-5678
-      chainloader (\$root)/EFI/boot/refind_x64.efi
-    }
+      menuentry 'rEFInd' --class refind {
+        chainloader (\$root)/EFI/boot/${refindBinary}
+      }
+    fi
+    ''}
     menuentry 'Firmware Setup' --class settings {
       fwsetup
       clear
@@ -357,7 +412,10 @@ let
     ${refind}
   '';
 
-  efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools pkgs.libfaketime ]; }
+  efiImg = pkgs.runCommand "efi-image_eltorito" {
+    nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ];
+    strictDeps = true;
+  }
     # Be careful about determinism: du --apparent-size,
     #   dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
     ''
@@ -366,7 +424,9 @@ let
       mkdir ./boot
       cp -p "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}" \
         "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}" ./boot/
-      touch --date=@0 ./EFI ./boot
+
+      # Rewrite dates for everything in the FS
+      find . -exec touch --date=2000-01-01 {} +
 
       usage_size=$(du -sb --apparent-size . | tr -cd '[:digit:]')
       # Make the image 110% as big as the files need to make up for FAT overhead
@@ -377,10 +437,10 @@ let
       echo "Usage size: $usage_size"
       echo "Image size: $image_size"
       truncate --size=$image_size "$out"
-      ${pkgs.libfaketime}/bin/faketime "2000-01-01 00:00:00" ${pkgs.dosfstools}/sbin/mkfs.vfat -i 12345678 -n EFIBOOT "$out"
+      faketime "2000-01-01 00:00:00" mkfs.vfat -i 12345678 -n EFIBOOT "$out"
       mcopy -psvm -i "$out" ./EFI ./boot ::
       # Verify the FAT partition.
-      ${pkgs.dosfstools}/sbin/fsck.vfat -vn "$out"
+      fsck.vfat -vn "$out"
     ''; # */
 
   # Name used by UEFI for architectures.
@@ -389,6 +449,8 @@ let
       "ia32"
     else if pkgs.stdenv.isx86_64 then
       "x64"
+    else if pkgs.stdenv.isAarch32 then
+      "arm"
     else if pkgs.stdenv.isAarch64 then
       "aa64"
     else