diff --git a/setup/arch-autoinstall.sh b/setup/arch-autoinstall.sh index 86ce8f1..e78f295 100755 --- a/setup/arch-autoinstall.sh +++ b/setup/arch-autoinstall.sh @@ -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: \") 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 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 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 diff --git a/setup/archbaseos-guided-install.sh b/setup/archbaseos-guided-install.sh index e9328b4..460de23 100755 --- a/setup/archbaseos-guided-install.sh +++ b/setup/archbaseos-guided-install.sh @@ -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: \") 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 diff --git a/setup/tools/build.sh b/setup/tools/build.sh index 5bec73f..cd294a1 100755 --- a/setup/tools/build.sh +++ b/setup/tools/build.sh @@ -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.