From 853475fed771dcde688cc6cc63e66bddfc37489c Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Sun, 7 Jan 2018 22:09:42 -0500 Subject: [PATCH 1/3] Fixes isolinux configuration for new artwork. --- nixos/modules/installer/cd-dvd/iso-image.nix | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 1ac9e5c5c74b..b6fa57242af7 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -36,6 +36,28 @@ let UI vesamenu.c32 MENU TITLE NixOS MENU BACKGROUND /isolinux/background.png + MENU RESOLUTION 800 600 + MENU CLEAR + MENU ROWS 6 + MENU CMDLINEROW -4 + MENU TIMEOUTROW -3 + MENU TABMSGROW -2 + MENU HELPMSGROW -1 + MENU HELPMSGENDROW -1 + MENU MARGIN 0 + + # FG:AARRGGBB BG:AARRGGBB shadow + MENU COLOR BORDER 30;44 #00000000 #00000000 none + MENU COLOR SCREEN 37;40 #FF000000 #00E2E8FF none + MENU COLOR TABMSG 31;40 #80000000 #00000000 none + MENU COLOR TIMEOUT 1;37;40 #FF000000 #00000000 none + MENU COLOR TIMEOUT_MSG 37;40 #FF000000 #00000000 none + MENU COLOR CMDMARK 1;36;40 #FF000000 #00000000 none + MENU COLOR CMDLINE 37;40 #FF000000 #00000000 none + MENU COLOR TITLE 1;36;44 #00000000 #00000000 none + MENU COLOR UNSEL 37;44 #FF000000 #00000000 none + MENU COLOR SEL 7;37;40 #FFFFFFFF #FF5277C3 std + DEFAULT boot LABEL boot @@ -236,8 +258,8 @@ in isoImage.splashImage = mkOption { default = pkgs.fetchurl { - url = https://raw.githubusercontent.com/NixOS/nixos-artwork/5729ab16c6a5793c10a2913b5a1b3f59b91c36ee/ideas/grub-splash/grub-nixos-1.png; - sha256 = "43fd8ad5decf6c23c87e9026170a13588c2eba249d9013cb9f888da5e2002217"; + url = https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png; + sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd"; }; description = '' The splash image to use in the bootloader. From 2f7d9c9f78ae36bc8eedd3969b131a393aded413 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Wed, 10 Jan 2018 21:14:52 -0500 Subject: [PATCH 2/3] Adds refind to the installer image. This is a 277K (as of right now) addition that can greatly help in some last recourse scenarios. The specific rEFInd setup will not be able to boot the installer image, but this is not why it has been added. It has been added to make use of its volumes scanning capabilities to boot existing EFI images on the target computer, which is sometimes necessary with buggy EFI. While is isn't NixOS's job to fix buggy EFI, shipping this small bit with the installer will help the unlucky few. Example scenario: two wildly different EFI implementation I have encountered have fatal flaws in which they sometimes will lose all the settings, this includes boot configuration. This is compounded by the fact that the two specific and distinct implementation do not allow manually adding ESP paths from their interface. The only recourse is to let the EFI boot the default paths, EFI/boot/boot{platform}.efi, which is not a default location used by the NixOS bootloaders. rEFInd is able to scan the volumes and detect the existing efi bootloaders, and boot them successfully. --- nixos/modules/installer/cd-dvd/iso-image.nix | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index b6fa57242af7..0dbdd39d639a 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -98,6 +98,24 @@ let isolinuxCfg = concatStringsSep "\n" ([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry); + # Setup instructions for rEFInd. + refind = + if targetArch == "x64" then + '' + # Adds rEFInd to the ISO. + cp -v ${pkgs.refind}/share/refind/refind_x64.efi $out/EFI/boot/ + + # Makes it bootable through systemd-boot. + # It purposefully does not have a refind configuration file nor theme. + cat << EOF > $out/loader/entries/zz-rEFInd.conf + title rEFInd rescue bootloader + efi /EFI/boot/refind_x64.efi + EOF + '' + else + "# No refind for ia32" + ; + # The EFI boot image. efiDir = pkgs.runCommand "efi-directory" {} '' mkdir -p $out/EFI/boot @@ -141,6 +159,8 @@ let default nixos-iso timeout ${builtins.toString config.boot.loader.timeout} EOF + + ${refind} ''; efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools pkgs.libfaketime ]; } From 41e7de42de030e47d273ab143732cdcb3547ab9a Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Thu, 11 Jan 2018 23:32:56 -0500 Subject: [PATCH 3/3] Use a themed grub for the installer image This replaces systemd-boot with grub, it is at feature parity, as in it can do everything systemd-boot did in the previous commit. --- nixos/modules/installer/cd-dvd/iso-image.nix | 269 +++++++++++++++---- pkgs/data/misc/nixos-artwork/grub2-theme.nix | 5 + pkgs/top-level/all-packages.nix | 1 + 3 files changed, 229 insertions(+), 46 deletions(-) create mode 100644 pkgs/data/misc/nixos-artwork/grub2-theme.nix diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 0dbdd39d639a..74fce0d1721d 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -7,6 +7,63 @@ with lib; let + /** + * Given a list of `options`, concats the result of mapping each options + * to a menuentry for use in grub. + * + * * defaults: {name, image, params, initrd} + * * options: [ option... ] + * * option: {name, params, class} + */ + menuBuilderGrub2 = + defaults: options: lib.concatStrings + ( + map + (option: '' + menuentry '${defaults.name} ${ + # Name appended to menuentry defaults to params if no specific name given. + option.name or (if option ? params then "(${option.params})" else "") + }' ${if option ? class then " --class ${option.class}" else ""} { + linux ${defaults.image} ${defaults.params} ${ + option.params or "" + } + initrd ${defaults.initrd} + } + '') + options + ) + ; + + /** + * Given a `config`, builds the default options. + */ + buildMenuGrub2 = config: + buildMenuAdditionalParamsGrub2 config "" + ; + + /** + * Given a `config` and params to add to `params`, build a set of default options. + * Use this one when creating a variant (e.g. hidpi) + */ + buildMenuAdditionalParamsGrub2 = config: additional: + let + finalCfg = { + name = "NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}"; + params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}"; + image = "/boot/bzImage"; + initrd = "/boot/initrd"; + }; + in + menuBuilderGrub2 + finalCfg + [ + { class = "installer"; } + { class = "nomodeset"; params = "nomodeset"; } + { class = "copytoram"; params = "copytoram"; } + { class = "debug"; params = "debug"; } + ] + ; + # Timeout in syslinux is in units of 1/10 of a second. # 0 is used to disable timeouts. syslinuxTimeout = if config.boot.loader.timeout == null then @@ -104,60 +161,158 @@ let '' # Adds rEFInd to the ISO. cp -v ${pkgs.refind}/share/refind/refind_x64.efi $out/EFI/boot/ - - # Makes it bootable through systemd-boot. - # It purposefully does not have a refind configuration file nor theme. - cat << EOF > $out/loader/entries/zz-rEFInd.conf - title rEFInd rescue bootloader - efi /EFI/boot/refind_x64.efi - EOF '' else "# No refind for ia32" ; + grubMenuCfg = '' + # + # Menu configuration + # + + insmod gfxterm + insmod png + set gfxpayload=keep + + # 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 + # 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. + # Otherwise the failure mode is to not even enable gfxterm. + if test "\$with_serial" == "yes"; then + terminal_output gfxterm serial + terminal_input console serial + else + terminal_output gfxterm + terminal_input console + fi + else + # Sets colors for the non-graphical term. + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi + + ${ # When there is a theme configured, use it, otherwise use the background image. + if (!isNull config.isoImage.grubTheme) then '' + # Sets theme. + set theme=(hd0)/EFI/boot/grub-theme/theme.txt + # Load theme fonts + $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (hd0)/EFI/boot/grub-theme/%P\n") + '' else '' + if background_image (hd0)/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 + set color_highlight=white/blue + else + # Falls back again to proper colors. + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi + ''} + ''; + # The EFI boot image. + # 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" {} '' - mkdir -p $out/EFI/boot - cp -v ${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${targetArch}.efi $out/EFI/boot/boot${targetArch}.efi - mkdir -p $out/loader/entries + mkdir -p $out/EFI/boot/ - cat << EOF > $out/loader/entries/nixos-iso.conf - title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} - linux /boot/${config.system.boot.loader.kernelFile} - initrd /boot/${config.system.boot.loader.initrdFile} - options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} - EOF + MODULES="fat iso9660 part_gpt part_msdos \ + normal boot linux configfile loopback chain halt \ + efifwsetup efi_gop efi_uga \ + ls search search_label search_fs_uuid search_fs_file \ + gfxmenu gfxterm gfxterm_background gfxterm_menu test all_video loadenv \ + exfat ext2 ntfs btrfs hfsplus udf \ + videoinfo png \ + echo serial \ + " + # Make our own efi program, we can't rely on "grub-install" since it seems to + # probe for devices, even with --skip-fs-probe. + ${pkgs.grub2_efi}/bin/grub-mkimage -o $out/EFI/boot/bootx64.efi -p /EFI/boot -O x86_64-efi \ + $MODULES + cp ${pkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/ - # A variant to boot with 'nomodeset' - cat << EOF > $out/loader/entries/nixos-iso-nomodeset.conf - title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} - version nomodeset - linux /boot/${config.system.boot.loader.kernelFile} - initrd /boot/${config.system.boot.loader.initrdFile} - options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset - EOF + cat < $out/EFI/boot/grub.cfg - # A variant to boot with 'copytoram' - cat << EOF > $out/loader/entries/nixos-iso-copytoram.conf - title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} - version copytoram - linux /boot/${config.system.boot.loader.kernelFile} - initrd /boot/${config.system.boot.loader.initrdFile} - options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram - EOF + # 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 + # This uses the defaults, and makes the serial terminal available. + set with_serial=no + if serial; then set with_serial=yes ;fi + export with_serial + clear + set timeout=10 + ${grubMenuCfg} - # A variant to boot with verbose logging to the console - cat << EOF > $out/loader/entries/nixos-iso-debug.conf - title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug) - linux /boot/${config.system.boot.loader.kernelFile} - initrd /boot/${config.system.boot.loader.initrdFile} - options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7 - EOF + # + # Menu entries + # - cat << EOF > $out/loader/loader.conf - default nixos-iso - timeout ${builtins.toString config.boot.loader.timeout} + ${buildMenuGrub2 config} + submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu { + ${grubMenuCfg} + submenu "Suggests resolution @720p" --class hidpi-720p { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "video=1280x720@60"} + } + submenu "Suggests resolution @1080p" --class hidpi-1080p { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "video=1920x1080@60"} + } + + # Some laptop and convertibles have the panel installed in an + # inconvenient way, rotated away from the keyboard. + # Those entries makes it easier to use the installer. + submenu "" {return} + submenu "Rotate framebuffer Clockwise" --class rotate-90cw { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:1"} + } + submenu "Rotate framebuffer Upside-Down" --class rotate-180 { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:2"} + } + submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:3"} + } + + # As a proof of concept, mainly. (Not sure it has accessibility merits.) + submenu "" {return} + submenu "Use black on white" --class accessibility-blakconwhite { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "vt.default_red=0xFF,0xBC,0x4F,0xB4,0x56,0xBC,0x4F,0x00,0xA1,0xCF,0x84,0xCA,0x8D,0xB4,0x84,0x68 vt.default_grn=0xFF,0x55,0xBA,0xBA,0x4D,0x4D,0xB3,0x00,0xA0,0x8F,0xB3,0xCA,0x88,0x93,0xA4,0x68 vt.default_blu=0xFF,0x58,0x5F,0x58,0xC5,0xBD,0xC5,0x00,0xA8,0xBB,0xAB,0x97,0xBD,0xC7,0xC5,0x68"} + } + + # Serial access is a must! + submenu "" {return} + submenu "Serial console=ttyS0,115200n8" --class serial { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "console=ttyS0,115200n8"} + } + } + + menuentry 'rEFInd' --class refind { + # UUID is hard-coded in the derivation. + search --set=root --no-floppy --fs-uuid 1234-5678 + chainloader (\$root)/EFI/boot/refind_x64.efi + } + menuentry 'Firmware Setup' --class settings { + fwsetup + clear + echo "" + echo "If you see this message, your EFI system doesn't support this feature." + echo "" + } + menuentry 'Shutdown' --class shutdown { + halt + } EOF ${refind} @@ -276,13 +431,31 @@ in ''; }; + isoImage.efiSplashImage = mkOption { + default = pkgs.fetchurl { + url = https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png; + sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x"; + }; + description = '' + The splash image to use in the EFI bootloader. + ''; + }; + isoImage.splashImage = mkOption { default = pkgs.fetchurl { url = https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png; sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd"; }; description = '' - The splash image to use in the bootloader. + The splash image to use in the legacy-boot bootloader. + ''; + }; + + isoImage.grubTheme = mkOption { + default = pkgs.nixos-grub2-theme; + type = types.nullOr (types.either types.path types.package); + description = '' + The grub2 theme used for UEFI boot. ''; }; @@ -400,6 +573,9 @@ in { source = "${pkgs.syslinux}/share/syslinux"; target = "/isolinux"; } + { source = config.isoImage.efiSplashImage; + target = "/EFI/boot/efi-background.png"; + } { source = config.isoImage.splashImage; target = "/isolinux/background.png"; } @@ -413,13 +589,14 @@ in { source = "${efiDir}/EFI"; target = "/EFI"; } - { source = "${efiDir}/loader"; - target = "/loader"; - } ] ++ optionals config.boot.loader.grub.memtest86.enable [ { source = "${pkgs.memtest86plus}/memtest.bin"; target = "/boot/memtest.bin"; } + ] ++ optionals (!isNull config.isoImage.grubTheme) [ + { source = config.isoImage.grubTheme; + target = "/EFI/boot/grub-theme"; + } ]; boot.loader.timeout = 10; diff --git a/pkgs/data/misc/nixos-artwork/grub2-theme.nix b/pkgs/data/misc/nixos-artwork/grub2-theme.nix new file mode 100644 index 000000000000..8bc6c8adc13e --- /dev/null +++ b/pkgs/data/misc/nixos-artwork/grub2-theme.nix @@ -0,0 +1,5 @@ +{fetchzip}: +fetchzip { + url = https://github.com/NixOS/nixos-artwork/releases/download/bootloader-18.09-pre/grub2-installer.tar.bz2; + sha256 = "0rhh061m1hpgadm7587inw3fxfacnd53xjc53w3vzghlck56djq5"; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index cce255e3728a..82ca928fe4d9 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -21625,6 +21625,7 @@ with pkgs; nixos-artwork = callPackage ../data/misc/nixos-artwork { }; nixos-icons = callPackage ../data/misc/nixos-artwork/icons.nix { }; + nixos-grub2-theme = callPackage ../data/misc/nixos-artwork/grub2-theme.nix { }; nixos-container = callPackage ../tools/virtualization/nixos-container { };