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.
This commit is contained in:
Samuel Dionne-Riel 2018-01-11 23:32:56 -05:00
parent 2f7d9c9f78
commit 41e7de42de
3 changed files with 229 additions and 46 deletions

View File

@ -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 <<EOF > $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;

View File

@ -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";
}

View File

@ -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 { };