{ self, inputs, ... }: { flake.nixosModules.shadowConfiguration = {...}: { networking = { hostName = "shadow"; }; # Windows lives on the 476G NVMe -- the one with three partitions: 16M # "Microsoft reserved" MSR, 476G NTFS (fs-uuid 70E4E841E4E80AE4, the C: # volume), 832M WinRE. Identified by layout rather than by nvmeXnY on # purpose; see the enumeration note below. # # That disk has NO EFI System Partition of its own -- its 16M partition is a # "Microsoft reserved" MSR with no filesystem. Windows was installed against # the ESP that NixOS now owns: the 1G vfat partition fs-uuid 5873-AD05 on the # 1.9T NVMe (that disk holds only two partitions, the ESP and the ext4 root # deff63fc-1738-4cfc-a79c-06e58c78471a). So both OSes boot from one shared # ESP; there is no separate Windows boot drive. # # The NixOS install reformatted that ESP, which wiped # EFI/Microsoft/Boot/{bootmgfw.efi,BCD} and left Windows unbootable. That has # since been repaired from WinRE and both files are back in place, so the # menuentry below is live. Keep the recovery command to hand in case the ESP # is ever reformatted again -- it has to be run from Windows install media or # WinRE, because the BCD store cannot be generated from Linux: # # bcdboot C:\Windows /s S: /f UEFI (S: = the ESP, fs-uuid 5873-AD05) # # Copying bootmgfw.efi alone is not enough; without BCD it fails 0xc000000f. # Note bcdboot also drops a copy of the Windows boot manager at # EFI/BOOT/bootx64.efi -- see the fallback-path note in core/boot.nix. # # Chainloaded explicitly rather than via grub.useOSProber: deterministic, # pulls in no extra tooling, and avoids probing every disk on each bootloader # install. The `-f` guard makes the entry self-disabling: it renders only # while bootmgfw.efi is actually present, so a future ESP reformat degrades # to a missing menu item rather than one that boots into an error. # # fs-uuid is shadow's ESP, matching the "/boot" entry in disks.nix. Searching # by UUID rather than (hdX,gptN) matters here: NVMe enumeration is not stable # on this board -- /boot has been seen as both nvme0n1p1 and nvme1n1p1. For # the same reason, re-derive device names before running anything # destructive: # # lsblk -o NAME,SIZE,FSTYPE,PARTTYPENAME,UUID,MOUNTPOINT # # Windows' boot files now occupy ~30-60MiB of that shared 1G ESP and Windows # Update rewrites them periodically, which is part of why # grub.configurationLimit is held at 10 in core/boot.nix. # # Before dual-booting, turn off Windows Fast Startup. hiberfil.sys is present # on the 476G NTFS volume, and Fast Startup plus this host's hibernation # setup will corrupt any NTFS volume mounted read-write from both sides. # # On the GRUB script itself: # # The outer `search` + `-f` test run at *boot*, while GRUB parses grub.cfg — # not at Nix eval time. That is why repairing Windows needed no rebuild: the # entry started rendering as soon as bcdboot put bootmgfw.efi back, and it # will stop again by itself if the file disappears. # # The `-n "$esp"` test is a *separate, # nested* if rather than `[ -n "$esp" -a -f ... ]`: a failed search leaves # $esp unset, and GRUB's `test` builtin evaluates both operands of `-a` # rather than short-circuiting, so the combined form would still expand the # `-f` to `()/...` and could complain about a bad device on every boot. # Nesting guarantees the path test is not reached at all. # # No `insmod` is needed for the outer search: GRUB's EFI core image already # embeds part_gpt/fat/search_fs_uuid, since it must find its own $prefix on # the FAT ESP before reading this file. NixOS' own install-grub.pl relies on # exactly that for the search it emits. The insmods inside the menuentry are # kept only because `chain` genuinely is a separate module. # # The inner `search` deliberately repeats the outer one rather than reusing # `set root=$esp`. It costs one extra disk scan, and only when the entry is # actually selected, in exchange for a menuentry that is self-contained and # cannot be broken by anything that clobbers $esp in between. This also # matches the per-entry search install-grub.pl generates. boot.loader.grub.extraEntries = '' search --no-floppy --set=esp --fs-uuid 5873-AD05 if [ -n "$esp" ]; then if [ -f ($esp)/EFI/Microsoft/Boot/bootmgfw.efi ]; then menuentry "Windows Boot Manager" --class windows --class os { insmod part_gpt insmod fat insmod chain search --no-floppy --set=root --fs-uuid 5873-AD05 chainloader /EFI/Microsoft/Boot/bootmgfw.efi } fi fi ''; }; }