diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index 5e576367eb2f..f1874f239778 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -527,8 +527,11 @@ EOF # Use the GRUB 2 boot loader. boot.loader.grub.enable = true; boot.loader.grub.version = 2; + # boot.loader.grub.efiSupport = true; + # boot.loader.grub.efiInstallAsRemovable = true; + # boot.loader.efi.efiSysMountPoint = "/boot/efi"; # Define on which hard drive you want to install Grub. - # boot.loader.grub.device = "/dev/sda"; + # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only EOF } diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 61c34cc2f034..e47afd061e2b 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -55,7 +55,7 @@ let inherit (cfg) version extraConfig extraPerEntryConfig extraEntries extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels - default fsIdentifier efiSupport gfxmodeEfi gfxmodeBios; + default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios; path = (makeBinPath ([ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfs-progs pkgs.utillinux ] ++ (if cfg.efiSupport && (cfg.version == 2) then [pkgs.efibootmgr ] else []) @@ -357,6 +357,44 @@ in ''; }; + efiInstallAsRemovable = mkOption { + default = false; + example = true; + type = types.bool; + description = '' + Whether to invoke grub-install with + --removable. + + Unless turn this on, GRUB will install itself somewhere (exactly + where depends on other config variables) in + boot.loader.efi.efiSysMountPoint. If you've set + boot.loader.efi.canTouchEfiVariables *AND* you + are currently booted in UEFI mode, then GRUB will use + efibootmgr to modify the boot order in the NVRAM's + EFI variables of your computer 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. GRUB will still succeed (althgouh you'll see a warning + printed "efibootmgr: EFI variables are not supported on + this system."). + + If you do turn this feature on, then GRUB will install itself + in a specific special location within efiSysMountPoint + (namely EFI/boot/boot$arch.efi) which is the firmwares + are hardcoded to try first, regardless of NVRAM EFI variables. + + To summarize, turn this on if: + + You are installing NixOS and want it to boot in UEFI mode, + but you are currently booted in legacy mode + You want to make a drive that will boot regardless of + the NVRAM state of the computer (like a USB "removable" drive) + You simply dislike the idea of depending on some NVRAM + state to make your drive bootable + + ''; + }; + enableCryptodisk = mkOption { default = false; type = types.bool; @@ -484,6 +522,14 @@ in 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 != [ ]; diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 06eece5025f8..b93395300b72 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -60,6 +60,7 @@ 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"); @@ -544,13 +545,15 @@ if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) { # 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"); if ($canTouchEfiVariables eq "true") { - system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", "--bootloader-id=$bootloaderId") == 0 - or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n"; + push @command, "--bootloader-id=$bootloaderId"; } else { - system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", "--no-nvram") == 0 - or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n"; + 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"; }