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
parent
3f05f64281
commit
9cd8eb2065
|
|
@ -134,6 +134,50 @@ if $AF_MODE; then
|
||||||
command -v jq &>/dev/null || pacman -Sy --noconfirm jq
|
command -v jq &>/dev/null || pacman -Sy --noconfirm jq
|
||||||
fi
|
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
|
# NETWORK CHECK
|
||||||
############################################
|
############################################
|
||||||
|
|
@ -354,14 +398,17 @@ echo " Swap: ${SWAP_SIZE}"
|
||||||
# PARTITION DISK
|
# PARTITION DISK
|
||||||
############################################
|
############################################
|
||||||
# --script suppresses interactive prompts; mklabel gpt wipes any existing table.
|
# --script suppresses interactive prompts; mklabel gpt wipes any existing table.
|
||||||
# Partition 1: ESP at 1MiB–10GiB, flagged boot/esp so firmware can find it.
|
# Partition 1: ESP at 1MiB–10GiB, flagged esp so firmware can find it.
|
||||||
# Partition 2: ROOT immediately after the ESP.
|
# Partition 2: ROOT immediately after the ESP.
|
||||||
# Partition 3: SWAP fills the rest (100%).
|
# Partition 3: SWAP fills the rest (100%).
|
||||||
# Starting at 1MiB aligns the first partition to a 1 MiB boundary, which is
|
# Starting at 1MiB aligns the first partition to a 1 MiB boundary, which is
|
||||||
# optimal for both SSD erase blocks and spinner track alignment.
|
# 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 \
|
parted "$DRIVE" --script mklabel gpt \
|
||||||
mkpart ESP fat32 1MiB 10GiB \
|
mkpart ESP fat32 1MiB 10GiB \
|
||||||
set 1 boot on \
|
set 1 esp on \
|
||||||
mkpart ROOT 10GiB "$((10 + ROOT_GIB))"GiB \
|
mkpart ROOT 10GiB "$((10 + ROOT_GIB))"GiB \
|
||||||
mkpart SWAP "$((10 + ROOT_GIB))"GiB 100%
|
mkpart SWAP "$((10 + ROOT_GIB))"GiB 100%
|
||||||
|
|
||||||
|
|
@ -435,7 +482,10 @@ if [[ "$ENCRYPT_DISK" == "YES" ]]; then
|
||||||
# BTRFS ON ENCRYPTED ROOT
|
# BTRFS ON ENCRYPTED ROOT
|
||||||
############################################
|
############################################
|
||||||
# Format the decrypted mapper device, not the raw partition.
|
# 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 flat (no subvolume) first so we can create the subvolume layout.
|
||||||
mount /dev/mapper/cryptroot /mnt
|
mount /dev/mapper/cryptroot /mnt
|
||||||
# @ is the conventional name for the root subvolume in btrfs-on-Arch setups;
|
# @ is the conventional name for the root subvolume in btrfs-on-Arch setups;
|
||||||
|
|
@ -457,7 +507,8 @@ else
|
||||||
# BTRFS ON UNENCRYPTED ROOT
|
# BTRFS ON UNENCRYPTED ROOT
|
||||||
############################################
|
############################################
|
||||||
# Same subvolume layout as the encrypted branch for consistency.
|
# 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
|
mount "$ROOT_PART" /mnt
|
||||||
btrfs subvolume create /mnt/@
|
btrfs subvolume create /mnt/@
|
||||||
btrfs subvolume create /mnt/@home
|
btrfs subvolume create /mnt/@home
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,50 @@ else
|
||||||
echo "== Arch Linux FIDO2-Ready Installer =="
|
echo "== Arch Linux FIDO2-Ready Installer =="
|
||||||
fi
|
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
|
# NETWORK CHECK
|
||||||
############################################
|
############################################
|
||||||
|
|
@ -432,7 +476,10 @@ if [[ "$ENCRYPT_DISK" == "YES" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Format btrfs on the decrypted mapper device, not the raw partition.
|
# 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 flat (no subvolume) first so the subvolume tree can be created.
|
||||||
mount /dev/mapper/cryptroot /mnt
|
mount /dev/mapper/cryptroot /mnt
|
||||||
# @ is the conventional root subvolume; @home separates user data for independent snapshots.
|
# @ is the conventional root subvolume; @home separates user data for independent snapshots.
|
||||||
|
|
@ -450,7 +497,8 @@ else
|
||||||
echo "Skipping encryption — formatting root directly."
|
echo "Skipping encryption — formatting root directly."
|
||||||
|
|
||||||
# Same btrfs subvolume layout as the encrypted path for consistency.
|
# 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
|
mount "$ROOT_PART" /mnt
|
||||||
btrfs subvolume create /mnt/@
|
btrfs subvolume create /mnt/@
|
||||||
btrfs subvolume create /mnt/@home
|
btrfs subvolume create /mnt/@home
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,20 @@ echo "Copying releng base profile..."
|
||||||
# entries, pacman.conf, syslinux/systemd-boot configs, etc.
|
# entries, pacman.conf, syslinux/systemd-boot configs, etc.
|
||||||
cp -r "$RELENG" "$PROFILE"
|
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..."
|
echo "Applying M-Archy overlay..."
|
||||||
# Merge our custom airootfs overlay ON TOP of the releng copy.
|
# Merge our custom airootfs overlay ON TOP of the releng copy.
|
||||||
# Files in our overlay replace or extend the releng defaults.
|
# Files in our overlay replace or extend the releng defaults.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue