Add support for rEFInd boot manager (#3707)
* Add support for rEFInd boot manager * Fix ruff formatting complaints * Added support for different mountpoints for /efi and /boot Also fixed issue where if /boot is located in a BTRFS root partition, the initrd path wasn't including the subvol name. * Fix ruff formatting complaints * Replace SysCommand with self.arch_chroot call * Fix ruff formatting complaints --------- Co-authored-by: Diogo Bispo <gpg.jta36@slmail.me>
This commit is contained in:
parent
446d23c59d
commit
cb6fe6b34b
|
|
@ -466,6 +466,10 @@ class GlobalMenu(AbstractMenu[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:
|
||||
|
|
|
|||
|
|
@ -1604,6 +1604,106 @@ class Installer:
|
|||
|
||||
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('refind-install')
|
||||
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,
|
||||
|
|
@ -1657,11 +1757,12 @@ class Installer:
|
|||
def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = False, bootloader_removable: 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
|
||||
* efistub (beta)
|
||||
* refnd (beta)
|
||||
|
||||
:param bootloader: Type of bootloader to be added
|
||||
:param uki_enabled: Whether to use unified kernel images
|
||||
|
|
@ -1713,6 +1814,8 @@ class Installer:
|
|||
self._add_efistub_bootloader(boot_partition, root, uki_enabled)
|
||||
case Bootloader.Limine:
|
||||
self._add_limine_bootloader(boot_partition, efi_partition, root, uki_enabled, bootloader_removable)
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,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
|
||||
|
|
|
|||
Loading…
Reference in New Issue