This is for future‑me. It’s a field notebook you can follow step‑by‑step when a BIOS update wipes your Linux boot entry, plus just enough theory to remember why each step works. All IDs/UUIDs below are placeholders (e.g., ROOT_UUID, ESP_PARTUUID). Replace with your real values when you run commands.


The problem appears

It began on a quiet Tuesday. The hum of my machine was familiar, the rhythm of my digital life. I kicked off a routine reboot—and nothing. Silence. A single, baleful red eye on the motherboard: the DRAM Q‑LED. My AM5 desktop was frozen, a prisoner in its own chassis.. Tho the gremlin only appeared on warm reboots.

On reboot, the bootloader menu was gone. My EndeavourOS had vanished. The BIOS had scrubbed NVRAM and forgotten the path to Linux. Not bricked, just lost. Fear flickered and defiance followed and became a rescue mission.

So What likely happened (the 10‑second theory)

  • Warm‑reboot hangs (AM5): Commonly memory training / Memory Context Restore quirks. OS logs are clean because the hang is pre‑OS.
  • After BIOS update: Firmware often wipes NVRAM boot entries. Your ESP still has the files, but the firmware no longer knows to load systemd-boot.

Fix in two parts:

  1. Rebuild a boot path (install sd‑boot to the ESP, create a UKI in ESP/EFI/Linux/, add an NVRAM entry).
  2. Tame warm‑reboots (BIOS memory settings + reboot=efi).

Check we’re in the right boot mode

# Live ISO must be in UEFI mode
test -d /sys/firmware/efi && echo "UEFI OK" || echo "Not UEFI!"

Why: Only UEFI mode lets us manipulate EFI variables and use efibootmgr. Legacy/CSM mode won’t work here.


Phase 1 — Identify & mount the right partitions

Find your ESP (FAT32, “EFI System”) and your root.

lsblk -o NAME,SIZE,FSTYPE,PARTTYPENAME,UUID,PARTUUID,MOUNTPOINTS /dev/nvme0n1
# Example result you will map:
#  - ESP:  /dev/nvme0n1p2   FSTYPE=vfat     PARTTYPENAME="EFI System"   UUID=ESP_UUID  PARTUUID=ESP_PARTUUID
#  - ROOT: /dev/nvme0n1p4   FSTYPE=ext4     UUID=ROOT_UUID
#  - SWAP: /dev/nvme0n1p3   FSTYPE=swap     UUID=SWAP_UUID

Mount them precisely where your system expects:

sudo mount /dev/nvme0n1p4 /mnt                     # root
sudo mkdir -p /mnt/efi
sudo mount /dev/nvme0n1p2 /mnt/efi                 # ESP

# Sanity: fstab should confirm ESP mountpoint
sudo grep -E ' /(efi|boot) ' /mnt/etc/fstab

Confirm the kernel command line matches your actual UUIDs:

echo "cmdline: $(sudo cat /mnt/etc/kernel/cmdline)"
sudo blkid -s UUID -o value /dev/nvme0n1p4   # should match root=UUID=...
sudo blkid -s UUID -o value /dev/nvme0n1p3   # should match resume=UUID=...

What these pieces do

  • ESP is the firmware’s doormat; it loads .efi programs from here.
  • Kernel cmdline tells Linux how to find root (root=UUID=…) and resume (resume=UUID=…).

Story interlude — the descent

I booted the live ISO; its logo was a beacon. UEFI OK. The path was open. I mapped the partitions—the living root filesystem and the ESP where the firmware knocks. I mounted them and, before touching anything, made a sacred copy of the ESP: a digital ghost in case I strayed.


(Optional) Phase 1½ — Back up the ESP

sudo dd if=/dev/nvme0n1p2 of=/mnt/data/esp-backup.img bs=4M status=progress
md5sum /mnt/data/esp-backup.img

Why: ESP is tiny. A backup makes any misstep reversible (dd it back to the same partition).


Phase 2 — Put systemd‑boot back onto the ESP

# In the chroot, install/refresh sd-boot files on the ESP
sudo arch-chroot /mnt bootctl --esp-path=/efi install

# You should now have:
sudo ls -l /mnt/efi/EFI/systemd/systemd-bootx64.efi
sudo ls -l /mnt/efi/EFI/BOOT/BOOTX64.EFI

Note: In a chroot, bootctl may skip writing EFI variables—that’s fine. It still updates the loader files on the ESP. We’ll add the NVRAM entry with efibootmgr in a moment.


Phase 3 — Forge a UKI (Unified Kernel Image) with dracut

Find your kernel version from the installed system and build the UKI directly into ESP/EFI/Linux/:

sudo arch-chroot /mnt bash -eux <<'EOS'
ver=$(ls -1 /usr/lib/modules | sort -V | tail -n1)

# Ensure UKI target directory exists
mkdir -p /efi/EFI/Linux

# Build a UKI: kernel + initramfs + early microcode + cmdline
dracut --force --uefi --kver "$ver" \
  --early-microcode \
  --kernel-cmdline "$(cat /etc/kernel/cmdline)" \
  "/efi/EFI/Linux/endeavour-linux-$ver.efi"

ls -l /efi/EFI/Linux
EOS

What a UKI is One .efi file that bundles everything the firmware/bootloader needs. systemd‑boot auto‑discovers UKIs in EFI/Linux/, so you don’t need a .conf entry.

If you use mkinitcpio instead of dracut Enable UKI in your preset (e.g., default_uki="esp/EFI/Linux/my-linux.efi") and run mkinitcpio -p linux. Same outcome: a UKI under ESP/EFI/Linux/.


Story interlude — the forge

Inside the chroot, the terminal became a forge. dracut gathered the kernel—the system’s heart; the initramfs—its first breath; the microcode—its innate knowledge; and the command line—its very first thought. All fused into a single, gleaming .efi under EFI/Linux. A master key.


Phase 4 — Teach the firmware where to look (NVRAM entry)

Leave the chroot; add a “Linux Boot Manager” entry that points at systemd‑boot on the ESP:

sudo efibootmgr --create \
  --disk /dev/nvme0n1 --part 2 \
  --label "Linux Boot Manager" \
  --loader '\EFI\systemd\systemd-bootx64.efi'

sudo efibootmgr -v   # ensure it exists; put it first in BootOrder if needed

Why this works Firmware loads systemd-boot from that NVRAM entry; sd‑boot then discovers your UKI under EFI/Linux and boots it.


Phase 5 — Reboot and choose the right entry

sudo umount -R /mnt
sudo reboot

On the sd‑boot menu, pick the UKI (you’ll see it by its filename/version). It should boot straight to your login prompt.


Phase 6 — Make the right default and tidy

Sometimes a stale .conf points nowhere (e.g., linux /), causing a GRUB shell or a blank screen if it’s marked default. Remove any broken entry and set a robust default.

# Remove obviously broken loader entries (example):
sudo rm -v /efi/loader/entries/endeavour.conf

# Make the menu remember the last successful choice
sudo tee /efi/loader/loader.conf >/dev/null <<'EOF'
default @saved
timeout 3
console-mode auto
editor no
EOF

# Seed @saved to today's working UKI
sudo bootctl set-default @saved

# See what sd-boot knows about:
bootctl list

(Optional) clean firmware of stale boot entries:

sudo efibootmgr -v          # note Boot#### for old Fedora/Ubuntu/etc
sudo efibootmgr -b 0004 -B  # example: remove Fedora
sudo efibootmgr -b 0005 -B  # example: remove Ubuntu

Why @saved helps On updates, entry names/versions can change. @saved follows the last item you chose successfully.


(Optional) Phase 7 — Keep a Type‑#1 fallback entry

If you want a belt‑and‑suspenders entry (separate kernel + initramfs + microcode all on the ESP):

ver="$(ls -1 /usr/lib/modules | sort -V | tail -n1)"
sudo cp -av "/usr/lib/modules/$ver/vmlinuz" "/efi/vmlinuz-$ver"
sudo dracut --force "/efi/initramfs-$ver.img" "$ver"
[ -f /efi/amd-ucode.img ] || sudo cp -av /boot/amd-ucode.img /efi/ || true

sudo mkdir -p /efi/loader/entries
cat | sudo tee /efi/loader/entries/endeavour-fallback.conf >/dev/null <<EOL
title   EndeavourOS (fallback $ver)
linux   /vmlinuz-$ver
initrd  /amd-ucode.img
initrd  /initramfs-$ver.img
options $(cat /etc/kernel/cmdline)
EOL

Story interlude — the return

The screen went black; then the sd‑boot menu bloomed into view. Not a scatter of parts but a single, proud entry. I selected it. Text streamed; fans hummed the right notes—and a login prompt greeted me. Not just rescued—reborn. Now to chase the original gremlin.


Phase 8 — Fix warm‑reboots on AM5

In BIOS/UEFI (Advanced/OC areas, names vary):

  • Memory Context Restore (MCR)Disabled
  • DRAM Power DownDisabled
  • Fast Boot (both vendor “Fast Boot” and standard) → Disabled
  • If you use EXPO, test JEDEC (EXPO off) first. If reboots are clean, re‑enable EXPO. If hangs return, drop memory frequency one bin (e.g., 6000 → 5600) or loosen timings.

In Linux: prefer EFI reset path (often helps warm‑reboot):

# Append reboot=efi to your kernel cmdline
echo 'root=UUID=ROOT_UUID resume=UUID=SWAP_UUID nvme_load=YES nowatchdog rw reboot=efi' | sudo tee /etc/kernel/cmdline

# Rebuild the UKI so it embeds the updated cmdline
sudo dracut --force --uefi --kver "$(uname -r)" --early-microcode \
  --kernel-cmdline "$(cat /etc/kernel/cmdline)" \
  "/efi/EFI/Linux/endeavour-linux-$(uname -r).efi"

Quick sanity after boot:

dmesg | grep microcode | head -n1   # early microcode loaded

Phase 9 — Automate the boring bits

Let sd‑boot update itself and rebuild UKIs after kernel upgrades.

# Keep sd-boot fresh
sudo systemctl enable --now systemd-boot-update.service

# Rebuild UKI automatically after kernel updates (pacman hook)
sudo install -d /etc/pacman.d/hooks
sudo tee /etc/pacman.d/hooks/95-uki-rebuild.hook >/dev/null <<'EOF'
[Trigger]
Operation = Install
Operation = Upgrade
Type      = Package
Target    = linux

[Action]
Description = Rebuild UKI for EndeavourOS
When = PostTransaction
Exec = /usr/bin/bash -c 'ver=$(ls -1 /usr/lib/modules | sort -V | tail -n1); dracut --force --uefi --kver "$ver" --early-microcode --kernel-cmdline "$(cat /etc/kernel/cmdline)" "/efi/EFI/Linux/endeavour-linux-$ver.efi"'
NeedsTargets
EOF

Story interlude — the epilogue

In the BIOS I walked the labyrinth, turning off MCR and Fast Boot, muzzling the gremlin. I added reboot=efi to my UKI’s first thought. The next day, I pressed reboot and watched the lights play their normal sequence. No red eye. No fear. Just the quiet confidence of a castle that knows its gates and keys.

I learned that a BIOS update’s amnesia isn’t a death sentence. I learned the elegance of the UKI—a single key that unlocks everything. And I left a spell behind—an automated hook to reforge that key with every kernel update. If the forest grows dark again, I know the path home.


TL;DR — one screen of commands

# Live ISO (UEFI), mount root + ESP
sudo mount /dev/nvme0n1p4 /mnt
sudo mkdir -p /mnt/efi
sudo mount /dev/nvme0n1p2 /mnt/efi
sudo grep -E ' /(efi|boot) ' /mnt/etc/fstab
echo "cmdline: $(sudo cat /mnt/etc/kernel/cmdline)"

# Put sd-boot on ESP
sudo arch-chroot /mnt bootctl --esp-path=/efi install

# Build a UKI to ESP/EFI/Linux/
sudo arch-chroot /mnt bash -c '
ver=$(ls -1 /usr/lib/modules | sort -V | tail -n1);
mkdir -p /efi/EFI/Linux;
dracut --force --uefi --kver "$ver" --early-microcode \
  --kernel-cmdline "$(cat /etc/kernel/cmdline)" \
  "/efi/EFI/Linux/endeavour-linux-$ver.efi"'

# Create NVRAM entry for systemd-boot
sudo efibootmgr --create --disk /dev/nvme0n1 --part 2 \
  --label "Linux Boot Manager" --loader '\EFI\systemd\systemd-bootx64.efi'

# Reboot; choose the UKI; then on the installed system:
sudo tee /efi/loader/loader.conf <<< $'default @saved\ntimeout 3\nconsole-mode auto\neditor no'
sudo bootctl set-default @saved

Appendix — quick glossary

  • ESP: EFI System Partition; FAT32; where firmware looks for bootloaders.
  • systemd‑boot: Tiny UEFI boot manager that lists entries and boots Linux.
  • UKI: Unified Kernel Image—single .efi containing kernel, initramfs, cmdline, microcode.
  • NVRAM entry: Firmware record pointing to an .efi loader on the ESP.
  • dracut/mkinitcpio: Tools that build initramfs/UKIs.
  • reboot=efi: Kernel parameter that uses the EFI reset vector (often helps AM5 warm‑reboot).


Buy Me a Coffee