To https://github.com/graingert/efibootnext
Boot Windows from a GRUB menu entry without breaking BitLocker TPM measurements.
Chainloading \EFI\Microsoft\Boot\bootmgfw.efi from GRUB breaks TPM PCR
measurements, causing BitLocker to prompt for a recovery key every time.
Instead of chainloading, boot a minimal Linux kernel/initramfs that:
- Reads a
bootnext=parameter from the kernel command line - Mounts
efivarfsand callsefibootmgr --bootnextto set the UEFIBootNextvariable - Immediately reboots
The firmware then boots Windows natively with correct TPM state. BitLocker is happy.
The premount script runs before the LUKS prompt, so you never have to enter your Linux disk encryption password just to boot Windows.
The GRUB menu entry is auto-generated by 50_efibootnext during update-grub —
it detects Windows via os-prober, matches the EFI path to a boot entry via efibootmgr, and finds the
/boot partition via GRUB's prepare_grub_to_access_device, so no manual
configuration is needed.
| File | Install to |
|---|---|
efibootnext-hook |
/etc/initramfs-tools/hooks/efibootnext |
efibootnext-premount |
/etc/initramfs-tools/scripts/init-premount/efibootnext |
50_efibootnext |
/etc/grub.d/50_efibootnext |
sudo apt install efibootmgr os-prober
sudo make install
sudo update-initramfs -u
sudo update-grubTo uninstall:
sudo make uninstall
sudo update-initramfs -u
sudo update-grubCheck efibootmgr is in the initramfs:
lsinitramfs /boot/initrd.img | grep efibootmgrCheck the GRUB menu entry exists:
grep -E "^menuentry|^submenu" /boot/grub/grub.cfgupdate-grub
→ 50_efibootnext runs
→ detects Windows via os-prober
→ finds matching EFI boot entry (e.g. Boot0007) via efibootmgr
→ finds /boot device via GRUB's prepare_grub_to_access_device
→ generates menuentry with bootnext=0007
GRUB
→ boots linux kernel + initramfs with bootnext=XXXX
→ init-premount/efibootnext runs (before LUKS prompt)
→ mounts efivarfs
→ efibootmgr --bootnext XXXX
→ reboot -f
→ firmware reads BootNext, boots Windows natively
→ TPM PCRs are correct, BitLocker unlocks automatically
30_os-prober also detects Windows and creates a chainload menu entry. You will
see two Windows entries in GRUB: one from 30_os-prober (chainload, breaks
BitLocker) and one from 50_efibootnext (BootNext, BitLocker-safe). Use the
"(EFI BootNext)" entry. To remove the duplicate, either set
GRUB_DISABLE_OS_PROBER=true in /etc/default/grub (disables both scripts) or
add the Windows partition UUID to GRUB_OS_PROBER_SKIP_LIST (both scripts
respect this).
The premount script parses /proc/cmdline using the same for x in $(cat /proc/cmdline) +
case pattern used by initramfs-tools itself in /usr/share/initramfs-tools/init:
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case $x in
root=*)
ROOT=${x#root=}
;;
...
esac
doneThis word-splits on spaces, which is fine because bootnext=XXXX never contains spaces.
- Ubuntu with GRUB2 and EFI
efibootmgr,os-prober, andinitramfs-toolspackagesbusyboxin the initramfs (providesreboot,mount,mountpoint— included by default on Ubuntu)- UEFI firmware (not legacy BIOS)
Public domain / CC0