Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 52 additions & 21 deletions archinstall/lib/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,7 @@ def _add_grub_bootloader(
boot_partition: PartitionModification,
root: PartitionModification | LvmVolume,
efi_partition: PartitionModification | None,
uki_enabled: bool = False,
bootloader_removable: bool = False,
) -> None:
debug('Installing grub bootloader')
Expand Down Expand Up @@ -1396,6 +1397,37 @@ def _add_grub_bootloader(
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',
Expand Down Expand Up @@ -1669,29 +1701,28 @@ def _add_refind_bootloader(
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')

Expand Down Expand Up @@ -1823,7 +1854,7 @@ def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = False, boot
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:
Expand Down
9 changes: 3 additions & 6 deletions archinstall/lib/models/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -82,7 +78,8 @@ def parse_arg(cls, config: dict[str, Any], skip_boot: bool) -> BootloaderConfigu
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}'
Expand Down