diff --git a/nixos/bootloaders/grub-windows.nix b/nixos/bootloaders/grub-windows.nix new file mode 100644 index 00000000..087ad849 --- /dev/null +++ b/nixos/bootloaders/grub-windows.nix @@ -0,0 +1,69 @@ +{ + config, + lib, + ... +}: let + cfg = config.myModules.bootloaders.grubWindows; + systemdBootCfg = config.myModules.bootloaders.systemdBoot; +in { + options.myModules.bootloaders.grubWindows = { + enable = lib.mkEnableOption "GRUB with Windows chainloading support"; + + configurationLimit = lib.mkOption { + default = 5; + type = lib.types.int; + description = "Maximum number of NixOS configurations shown in GRUB."; + }; + + windowsEfiUuid = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = '' + Filesystem UUID of the Windows EFI system partition. When set, GRUB + gets an explicit Windows Boot Manager chainload entry in addition to + entries discovered by os-prober. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = !systemdBootCfg.enable; + message = '' + myModules.bootloaders.grubWindows.enable conflicts with + myModules.bootloaders.systemdBoot.enable. Disable systemdBoot before + enabling the GRUB Windows boot strategy. + ''; + } + { + assertion = builtins.hasAttr "/boot" config.fileSystems; + message = "The GRUB Windows boot strategy expects an EFI filesystem mounted at /boot."; + } + ]; + + boot.loader = { + efi = { + canTouchEfiVariables = lib.mkDefault true; + efiSysMountPoint = lib.mkDefault "/boot"; + }; + + grub = { + enable = true; + efiSupport = true; + device = "nodev"; + useOSProber = true; + configurationLimit = cfg.configurationLimit; + timeoutStyle = "menu"; + extraEntries = lib.optionalString (cfg.windowsEfiUuid != null) '' + menuentry "Windows Boot Manager" { + insmod part_gpt + insmod fat + search --no-floppy --fs-uuid --set=windows_esp ${cfg.windowsEfiUuid} + chainloader ($windows_esp)/EFI/Microsoft/Boot/bootmgfw.efi + } + ''; + }; + }; + }; +} diff --git a/nixos/bootloaders/systemd-boot.nix b/nixos/bootloaders/systemd-boot.nix new file mode 100644 index 00000000..e8fe8d76 --- /dev/null +++ b/nixos/bootloaders/systemd-boot.nix @@ -0,0 +1,12 @@ +{ + config, + lib, + makeEnable, + ... +}: +makeEnable config "myModules.bootloaders.systemdBoot" true { + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = lib.mkDefault true; + }; +} diff --git a/nixos/configuration.nix b/nixos/configuration.nix index 27c98278..f19567c6 100644 --- a/nixos/configuration.nix +++ b/nixos/configuration.nix @@ -4,6 +4,8 @@ ./android.nix ./base.nix ./ben.nix + ./bootloaders/grub-windows.nix + ./bootloaders/systemd-boot.nix ./cache-server.nix ./cache.nix ./code.nix diff --git a/nixos/machines/ryzen-shine.nix b/nixos/machines/ryzen-shine.nix index 63f293a9..387da413 100644 --- a/nixos/machines/ryzen-shine.nix +++ b/nixos/machines/ryzen-shine.nix @@ -38,6 +38,11 @@ # boot.kernelPackages = pkgs.linuxPackages_latest; boot.loader.systemd-boot.configurationLimit = 5; + myModules.bootloaders.systemdBoot.enable = false; + myModules.bootloaders.grubWindows = { + enable = true; + windowsEfiUuid = "B270-C7E6"; + }; networking.hostName = "ryzen-shine"; @@ -59,9 +64,6 @@ networking.interfaces.enp5s0.useDHCP = true; networking.interfaces.wlp4s0.useDHCP = true; - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ]; hardware.nvidia.modesetting.enable = true; diff --git a/nixos/raspberry-pi.nix b/nixos/raspberry-pi.nix index efa11316..ede9f461 100644 --- a/nixos/raspberry-pi.nix +++ b/nixos/raspberry-pi.nix @@ -10,6 +10,8 @@ makeEnable config "myModules.raspberry-pi" false { hardware.deviceTree.filter = "bcm2711-rpi-4*.dtb"; hardware.raspberry-pi."4".fkms-3d.enable = true; # hardware.raspberry-pi."4".audio.enable = true; + myModules.bootloaders.systemdBoot.enable = false; + myModules.bootloaders.grubWindows.enable = false; boot = { initrd.systemd.tpm2.enable = false; diff --git a/nixos/wsl.nix b/nixos/wsl.nix index b67e7434..0f2b2b33 100644 --- a/nixos/wsl.nix +++ b/nixos/wsl.nix @@ -6,6 +6,8 @@ makeEnable config "myModules.wsl" false { myModules.base.enable = false; myModules.desktop.enable = false; + myModules.bootloaders.systemdBoot.enable = false; + myModules.bootloaders.grubWindows.enable = false; myModules.xmonad.enable = false; myModules.plasma.enable = false; # Tailscale-in-WSL is usually better handled by the Windows host Tailscale