Skip to content
Open
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
4 changes: 4 additions & 0 deletions archinstall/lib/global_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ def _validate_bootloader(self) -> str | None:
if boot_partition.fs_type not in [FilesystemType.Fat12, FilesystemType.Fat16, FilesystemType.Fat32]:
return 'Limine does not support booting with a non-FAT boot partition'

elif bootloader == Bootloader.Refind:
if not SysInfo.has_uefi():
return 'rEFInd can only be used on UEFI systems'

return None

def _prev_install_invalid_config(self, item: MenuItem) -> str | None:
Expand Down
105 changes: 104 additions & 1 deletion archinstall/lib/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,106 @@

self._helper_flags['bootloader'] = 'efistub'

def _add_refind_bootloader(
self,
boot_partition: PartitionModification,
efi_partition: PartitionModification | None,
root: PartitionModification | LvmVolume,
uki_enabled: bool = False,
) -> None:
debug('Installing rEFInd bootloader')

self.pacman.strap('refind')

if not SysInfo.has_uefi():
raise HardwareIncompatibilityError

info(f'rEFInd boot partition: {boot_partition.dev_path}')

if not efi_partition:
raise ValueError('Could not detect EFI system partition')
elif not efi_partition.mountpoint:
raise ValueError('EFI system partition is not mounted')

info(f'rEFInd EFI partition: {efi_partition.dev_path}')

try:
self.arch_chroot(f'refind-install')

Check failure on line 1580 in archinstall/lib/installer.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F541)

archinstall/lib/installer.py:1580:21: F541 f-string without any placeholders

Check failure on line 1580 in archinstall/lib/installer.py

View workflow job for this annotation

GitHub Actions / ruff_format_check

Ruff (F541)

archinstall/lib/installer.py:1580:21: F541 f-string without any placeholders
except SysCallError as err:
raise DiskError(f'Could not install rEFInd to {self.target}{efi_partition.mountpoint}: {err}')

if not boot_partition.mountpoint:
raise ValueError('Boot partition is not mounted, cannot write rEFInd config')

boot_is_separate = boot_partition != efi_partition and boot_partition.dev_path != efi_partition.dev_path

if boot_is_separate:
# Separate boot partition (not ESP, not root)
config_path = self.target / boot_partition.mountpoint.relative_to('/') / 'refind_linux.conf'
boot_on_root = False
elif efi_partition.mountpoint == Path('/boot'):
# ESP is mounted at /boot, kernels are on ESP
config_path = self.target / 'boot' / 'refind_linux.conf'
boot_on_root = False
else:
# ESP is elsewhere (/efi, /boot/efi, etc.), kernels are on root filesystem at /boot
config_path = self.target / 'boot' / 'refind_linux.conf'
boot_on_root = True

config_contents = []

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'
else:
# Root without btrfs subvolume
initrd_path = f'initrd=\\boot\\initramfs-{kernel}{variant}.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}"'

config_contents.append(entry)

config_path.write_text('\n'.join(config_contents) + '\n')

hook_contents = textwrap.dedent(
"""\
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = refind

[Action]
Description = Updating rEFInd on ESP
When = PostTransaction
Exec = /usr/bin/refind-install
"""
)

hooks_dir = self.target / 'etc' / 'pacman.d' / 'hooks'
hooks_dir.mkdir(parents=True, exist_ok=True)

hook_path = hooks_dir / '99-refind.hook'
hook_path.write_text(hook_contents)

self._helper_flags['bootloader'] = 'refind'

def _config_uki(
self,
root: PartitionModification | LvmVolume,
Expand Down Expand Up @@ -1606,11 +1706,12 @@
def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = False) -> None:
"""
Adds a bootloader to the installation instance.
Archinstall supports one of three types:
Archinstall supports one of five types:
* systemd-bootctl
* grub
* limine (beta)
* efistub (beta)
* refnd (beta)

:param bootloader: Type of bootloader to be added
"""
Expand Down Expand Up @@ -1646,6 +1747,8 @@
self._add_efistub_bootloader(boot_partition, root, uki_enabled)
case Bootloader.Limine:
self._add_limine_bootloader(boot_partition, efi_partition, root, uki_enabled)
case Bootloader.Refind:
self._add_refind_bootloader(boot_partition, efi_partition, root, uki_enabled)

def add_additional_packages(self, packages: str | list[str]) -> None:
return self.pacman.strap(packages)
Expand Down
3 changes: 2 additions & 1 deletion archinstall/lib/models/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ class Bootloader(Enum):
Grub = 'Grub'
Efistub = 'Efistub'
Limine = 'Limine'
Refind = 'Refind'

def has_uki_support(self) -> bool:
match self:
case Bootloader.Efistub | Bootloader.Limine | Bootloader.Systemd:
case Bootloader.Efistub | Bootloader.Limine | Bootloader.Systemd | Bootloader.Refind:
return True
case _:
return False
Expand Down
Loading