fix: bootloader changes (#4073)

* Bootloader changes:

	-> GRUB: Support for UKI
		- Disable 10_linux or breaks at kernel updates
		- Create 09_custom entry
	-> rEFInd:
		- Remove fallback entry similar to other bootloaders
		- With UKI still one dead entry can be hidden with DEL key
	-> All bootloaders:
		- Default to UKI on if supported, if using no UKI and /efi
		Causes systemd boot to not load, because it needs a XTLDRBOOT part
		Safer default for modern setups and simpler sec boot compat

* Add new models

* Modify based on grub-2.14-rc1 -> No need to use chainload
Thanks to codefiles for the heads-up

* Simplify has_uki_support

* Tab

* checks
This commit is contained in:
HADEON 2026-01-06 10:04:01 +01:00 committed by GitHub
parent cc6e247dcf
commit 0188459917
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 55 additions and 27 deletions

View File

@ -1325,6 +1325,7 @@ class Installer:
boot_partition: PartitionModification,
root: PartitionModification | LvmVolume,
efi_partition: PartitionModification | None,
uki_enabled: bool = False,
bootloader_removable: bool = False,
) -> None:
debug('Installing grub bootloader')
@ -1396,6 +1397,37 @@ class Installer:
except SysCallError as err:
raise DiskError(f'Failed to install GRUB boot on {boot_partition.dev_path}: {err}')
# Add custom UKI entries if enabled
if uki_enabled and SysInfo.has_uefi() and efi_partition:
custom_entries = self.target / 'etc/grub.d/09_custom'
entries_content = (
'#!/bin/sh\n'
'exec tail -n +3 $0\n'
'# This file provides UKI (Unified Kernel Image) boot entries.\n'
'# Generated by archinstall. Do not modify the exec tail line above.\n'
'# Custom entries can be added below.\n\n'
)
uki_entries = []
for kernel in self.kernels:
entry = textwrap.dedent(
f"""
menuentry "Arch Linux ({kernel}) UKI" {{
uki /EFI/Linux/arch-{kernel}.efi
}}
"""
)
uki_entries.append(entry)
entries_content += '\n'.join(uki_entries)
custom_entries.write_text(entries_content)
custom_entries.chmod(0o755)
# Disable 10_linux to prevent broken entries on kernel updates
linux_script = self.target / 'etc/grub.d/10_linux'
if linux_script.exists():
linux_script.chmod(0o644)
try:
self.arch_chroot(
f'grub-mkconfig -o {boot_dir}/grub/grub.cfg',
@ -1669,29 +1701,28 @@ class Installer:
kernel_params = ' '.join(self._get_kernel_params(root))
for kernel in self.kernels:
for variant in ('', '-fallback'):
if uki_enabled:
entry = f'"Arch Linux ({kernel}{variant}) UKI" "{kernel_params}"'
else:
if boot_on_root:
# Kernels are in /boot subdirectory of root filesystem
if hasattr(root, 'btrfs_subvols') and root.btrfs_subvols:
# Root is btrfs with subvolume, find the root subvolume
root_subvol = next((sv for sv in root.btrfs_subvols if sv.is_root()), None)
if root_subvol:
subvol_name = root_subvol.name
initrd_path = f'initrd={subvol_name}\\boot\\initramfs-{kernel}{variant}.img'
else:
initrd_path = f'initrd=\\boot\\initramfs-{kernel}{variant}.img'
if uki_enabled:
entry = f'"Arch Linux ({kernel}) UKI" "{kernel_params}"'
else:
if boot_on_root:
# Kernels are in /boot subdirectory of root filesystem
if hasattr(root, 'btrfs_subvols') and root.btrfs_subvols:
# Root is btrfs with subvolume, find the root subvolume
root_subvol = next((sv for sv in root.btrfs_subvols if sv.is_root()), None)
if root_subvol:
subvol_name = root_subvol.name
initrd_path = f'initrd={subvol_name}\\boot\\initramfs-{kernel}.img'
else:
# Root without btrfs subvolume
initrd_path = f'initrd=\\boot\\initramfs-{kernel}{variant}.img'
initrd_path = f'initrd=\\boot\\initramfs-{kernel}.img'
else:
# Kernels are at root of their partition (ESP or separate boot partition)
initrd_path = f'initrd=\\initramfs-{kernel}{variant}.img'
entry = f'"Arch Linux ({kernel}{variant})" "{kernel_params} {initrd_path}"'
# Root without btrfs subvolume
initrd_path = f'initrd=\\boot\\initramfs-{kernel}.img'
else:
# Kernels are at root of their partition (ESP or separate boot partition)
initrd_path = f'initrd=\\initramfs-{kernel}.img'
entry = f'"Arch Linux ({kernel})" "{kernel_params} {initrd_path}"'
config_contents.append(entry)
config_contents.append(entry)
config_path.write_text('\n'.join(config_contents) + '\n')
@ -1823,7 +1854,7 @@ class Installer:
case Bootloader.Systemd:
self._add_systemd_bootloader(boot_partition, root, efi_partition, uki_enabled)
case Bootloader.Grub:
self._add_grub_bootloader(boot_partition, root, efi_partition, bootloader_removable)
self._add_grub_bootloader(boot_partition, root, efi_partition, uki_enabled, bootloader_removable)
case Bootloader.Efistub:
self._add_efistub_bootloader(boot_partition, root, uki_enabled)
case Bootloader.Limine:

View File

@ -20,11 +20,7 @@ class Bootloader(Enum):
Refind = 'Refind'
def has_uki_support(self) -> bool:
match self:
case Bootloader.Efistub | Bootloader.Limine | Bootloader.Systemd | Bootloader.Refind:
return True
case _:
return False
return self != Bootloader.NO_BOOTLOADER
def has_removable_support(self) -> bool:
match self:
@ -82,7 +78,8 @@ class BootloaderConfiguration:
def get_default(cls) -> BootloaderConfiguration:
bootloader = Bootloader.get_default()
removable = SysInfo.has_uefi() and bootloader.has_removable_support()
return cls(bootloader=bootloader, uki=False, removable=removable)
uki = SysInfo.has_uefi() and bootloader.has_uki_support()
return cls(bootloader=bootloader, uki=uki, removable=removable)
def preview(self) -> str:
text = f'{tr("Bootloader")}: {self.bootloader.value}'