feat(setup): add UEFI/Secure Boot preflight checks, force mkfs.btrfs, bake nomodeset into ISO

Both installers now fail fast if booted non-UEFI or warn on Secure Boot,
since GRUB install/NVRAM registration silently "succeeds" in both broken
cases and the failure only surfaces on next boot. mkfs.btrfs now forces
past leftover filesystem signatures on reinstalls. build.sh patches
nomodeset into every boot entry (BIOS/UEFI/PXE) to work around early-KMS
hangs on Optimus laptops (e.g. Lenovo Legion).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main
Amir Alexander Abdelbaki 2026-07-29 08:33:25 +02:00
parent 3f05f64281
commit 9cd8eb2065
3 changed files with 119 additions and 6 deletions

View File

@ -134,6 +134,50 @@ if $AF_MODE; then
command -v jq &>/dev/null || pacman -Sy --noconfirm jq
fi
############################################
# UEFI PREFLIGHT
############################################
# This installer is UEFI-only: it partitions GPT + a FAT32 ESP and installs
# GRUB with --target=x86_64-efi (no bios_grub partition, no MBR boot code).
# If the live USB itself was booted via legacy/CSM (easy to do by accident —
# many firmwares list the same USB stick twice in the boot menu, once as
# "UEFI: ..." and once plain/legacy), grub-install still exits 0 (it just
# skips the NVRAM update with a warning when /sys/firmware/efi is absent),
# so the install silently "succeeds" and produces a disk with no legacy-
# bootable code at all — the next boot has nothing to find and firmware
# drops straight back to its own boot menu. Fail fast here instead.
if [[ ! -d /sys/firmware/efi ]]; then
echo "ERROR: not booted in UEFI mode (/sys/firmware/efi missing)."
echo " This installer only produces UEFI-bootable systems. Reboot the"
echo " live USB and pick the UEFI boot entry for it (some firmware"
echo " boot menus list the same drive twice — once as legacy/CSM, once"
echo " as \"UEFI: <drive name>\") or disable CSM/Legacy boot in firmware setup."
exit 1
fi
# Secure Boot: pacstrap only installs plain (unsigned) `grub`. If Secure Boot
# is enabled, firmware will refuse to execute the unsigned grubx64.efi at boot
# time and silently fall back to its own boot menu — grub-install and NVRAM
# registration both succeed during install, so this failure only shows up
# after reboot. Read the standard EFI global variable directly rather than
# relying on `mokutil` (not in the live package set); byte 4 (0-indexed) is
# the actual boolean value, the first 4 bytes are the variable attributes.
_SB_VAR="/sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c"
if [[ -r "$_SB_VAR" ]]; then
_sb_val=$(od -An -tu1 -j4 -N1 "$_SB_VAR" 2>/dev/null | tr -d ' ')
if [[ "$_sb_val" == "1" ]]; then
echo "WARNING: Secure Boot is ENABLED in firmware."
echo " This installer's GRUB is unsigned — the system will not boot"
echo " with Secure Boot on. Disable Secure Boot in firmware setup"
echo " before or after installing (Secure Boot is a boot-time check,"
echo " not an install-time one, so this install will still \"succeed\")."
if ! $AF_MODE; then
read -rp "Continue anyway? [y/N]: " _sb_ans
[[ "${_sb_ans,,}" == "y" ]] || { echo "Aborted — disable Secure Boot and retry."; exit 1; }
fi
fi
fi
############################################
# NETWORK CHECK
############################################
@ -354,14 +398,17 @@ echo " Swap: ${SWAP_SIZE}"
# PARTITION DISK
############################################
# --script suppresses interactive prompts; mklabel gpt wipes any existing table.
# Partition 1: ESP at 1MiB10GiB, flagged boot/esp so firmware can find it.
# Partition 1: ESP at 1MiB10GiB, flagged esp so firmware can find it.
# Partition 2: ROOT immediately after the ESP.
# Partition 3: SWAP fills the rest (100%).
# Starting at 1MiB aligns the first partition to a 1 MiB boundary, which is
# optimal for both SSD erase blocks and spinner track alignment.
# `esp` (matches archbaseos-guided-install.sh): modern parted treats `boot` and
# `esp` as synonyms on a GPT table (both set the ESP type GUID), but `esp` is
# the unambiguous modern spelling.
parted "$DRIVE" --script mklabel gpt \
mkpart ESP fat32 1MiB 10GiB \
set 1 boot on \
set 1 esp on \
mkpart ROOT 10GiB "$((10 + ROOT_GIB))"GiB \
mkpart SWAP "$((10 + ROOT_GIB))"GiB 100%
@ -435,7 +482,10 @@ if [[ "$ENCRYPT_DISK" == "YES" ]]; then
# BTRFS ON ENCRYPTED ROOT
############################################
# Format the decrypted mapper device, not the raw partition.
mkfs.btrfs /dev/mapper/cryptroot
# -f: force — without it, mkfs.btrfs refuses when it finds a leftover
# filesystem signature at this offset (e.g. reinstalling on a drive that
# already had a filesystem before repartitioning).
mkfs.btrfs -f /dev/mapper/cryptroot
# Mount flat (no subvolume) first so we can create the subvolume layout.
mount /dev/mapper/cryptroot /mnt
# @ is the conventional name for the root subvolume in btrfs-on-Arch setups;
@ -457,7 +507,8 @@ else
# BTRFS ON UNENCRYPTED ROOT
############################################
# Same subvolume layout as the encrypted branch for consistency.
mkfs.btrfs "$ROOT_PART"
# -f: force — see comment on the encrypted-path mkfs.btrfs above.
mkfs.btrfs -f "$ROOT_PART"
mount "$ROOT_PART" /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home

View File

@ -141,6 +141,50 @@ else
echo "== Arch Linux FIDO2-Ready Installer =="
fi
############################################
# UEFI PREFLIGHT
############################################
# This installer is UEFI-only: it partitions GPT + a FAT32 ESP and installs
# GRUB with --target=x86_64-efi (no bios_grub partition, no MBR boot code).
# If the live USB itself was booted via legacy/CSM (easy to do by accident —
# many firmwares list the same USB stick twice in the boot menu, once as
# "UEFI: ..." and once plain/legacy), grub-install still exits 0 (it just
# skips the NVRAM update with a warning when /sys/firmware/efi is absent),
# so the install silently "succeeds" and produces a disk with no legacy-
# bootable code at all — the next boot has nothing to find and firmware
# drops straight back to its own boot menu. Fail fast here instead.
if [[ ! -d /sys/firmware/efi ]]; then
echo "ERROR: not booted in UEFI mode (/sys/firmware/efi missing)."
echo " This installer only produces UEFI-bootable systems. Reboot the"
echo " live USB and pick the UEFI boot entry for it (some firmware"
echo " boot menus list the same drive twice — once as legacy/CSM, once"
echo " as \"UEFI: <drive name>\") or disable CSM/Legacy boot in firmware setup."
exit 1
fi
# Secure Boot: pacstrap only installs plain (unsigned) `grub`. If Secure Boot
# is enabled, firmware will refuse to execute the unsigned grubx64.efi at boot
# time and silently fall back to its own boot menu — grub-install and NVRAM
# registration both succeed during install, so this failure only shows up
# after reboot. Read the standard EFI global variable directly rather than
# relying on `mokutil` (not in the live package set); byte 4 (0-indexed) is
# the actual boolean value, the first 4 bytes are the variable attributes.
_SB_VAR="/sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c"
if [[ -r "$_SB_VAR" ]]; then
_sb_val=$(od -An -tu1 -j4 -N1 "$_SB_VAR" 2>/dev/null | tr -d ' ')
if [[ "$_sb_val" == "1" ]]; then
echo "WARNING: Secure Boot is ENABLED in firmware."
echo " This installer's GRUB is unsigned — the system will not boot"
echo " with Secure Boot on. Disable Secure Boot in firmware setup"
echo " before or after installing (Secure Boot is a boot-time check,"
echo " not an install-time one, so this install will still \"succeed\")."
if ! $AF_MODE; then
read -rp "Continue anyway? [y/N]: " _sb_ans
[[ "${_sb_ans,,}" == "y" ]] || { echo "Aborted — disable Secure Boot and retry."; exit 1; }
fi
fi
fi
############################################
# NETWORK CHECK
############################################
@ -432,7 +476,10 @@ if [[ "$ENCRYPT_DISK" == "YES" ]]; then
fi
# Format btrfs on the decrypted mapper device, not the raw partition.
mkfs.btrfs /dev/mapper/cryptroot
# -f: force — without it, mkfs.btrfs refuses when it finds a leftover
# filesystem signature at this offset (e.g. reinstalling on a drive that
# already had a filesystem before repartitioning).
mkfs.btrfs -f /dev/mapper/cryptroot
# Mount flat (no subvolume) first so the subvolume tree can be created.
mount /dev/mapper/cryptroot /mnt
# @ is the conventional root subvolume; @home separates user data for independent snapshots.
@ -450,7 +497,8 @@ else
echo "Skipping encryption — formatting root directly."
# Same btrfs subvolume layout as the encrypted path for consistency.
mkfs.btrfs "$ROOT_PART"
# -f: force — see comment on the encrypted-path mkfs.btrfs above.
mkfs.btrfs -f "$ROOT_PART"
mount "$ROOT_PART" /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home

View File

@ -148,6 +148,20 @@ echo "Copying releng base profile..."
# entries, pacman.conf, syslinux/systemd-boot configs, etc.
cp -r "$RELENG" "$PROFILE"
echo "Patching boot entries with nomodeset..."
# Workaround for Lenovo Legion (Intel+Nvidia Optimus) and similar hardware where
# early KMS probing hangs the live boot. Applied to every entry that actually
# boots vmlinuz-linux (identified by the archisobasedir= param they all share) —
# BIOS/syslinux, UEFI/systemd-boot, and PXE — but not the tail/menu-switch
# APPEND lines in archiso_tail.cfg/syslinux.cfg, which aren't kernel cmdlines.
for f in \
"$PROFILE/syslinux/archiso_sys-linux.cfg" \
"$PROFILE/syslinux/archiso_pxe-linux.cfg" \
"$PROFILE/efiboot/loader/entries/01-archiso-linux.conf" \
"$PROFILE/efiboot/loader/entries/02-archiso-speech-linux.conf"; do
sed -i '/archisobasedir=/ s/$/ nomodeset/' "$f"
done
echo "Applying M-Archy overlay..."
# Merge our custom airootfs overlay ON TOP of the releng copy.
# Files in our overlay replace or extend the releng defaults.