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]:
|
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'
|
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
|
return None
|
||||||
|
|
||||||
def _prev_install_invalid_config(self, item: MenuItem) -> str | None:
|
def _prev_install_invalid_config(self, item: MenuItem) -> str | None:
|
||||||
|
|
|
||||||
|
|
@ -1604,6 +1604,106 @@ class Installer:
|
||||||
|
|
||||||
self._helper_flags['bootloader'] = 'efistub'
|
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(
|
def _config_uki(
|
||||||
self,
|
self,
|
||||||
root: PartitionModification | LvmVolume,
|
root: PartitionModification | LvmVolume,
|
||||||
|
|
@ -1657,11 +1757,12 @@ class Installer:
|
||||||
def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = False, bootloader_removable: bool = False) -> None:
|
def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = False, bootloader_removable: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
Adds a bootloader to the installation instance.
|
Adds a bootloader to the installation instance.
|
||||||
Archinstall supports one of three types:
|
Archinstall supports one of five types:
|
||||||
* systemd-bootctl
|
* systemd-bootctl
|
||||||
* grub
|
* grub
|
||||||
* limine
|
* limine
|
||||||
* efistub (beta)
|
* efistub (beta)
|
||||||
|
* refnd (beta)
|
||||||
|
|
||||||
:param bootloader: Type of bootloader to be added
|
:param bootloader: Type of bootloader to be added
|
||||||
:param uki_enabled: Whether to use unified kernel images
|
:param uki_enabled: Whether to use unified kernel images
|
||||||
|
|
@ -1713,6 +1814,8 @@ class Installer:
|
||||||
self._add_efistub_bootloader(boot_partition, root, uki_enabled)
|
self._add_efistub_bootloader(boot_partition, root, uki_enabled)
|
||||||
case Bootloader.Limine:
|
case Bootloader.Limine:
|
||||||
self._add_limine_bootloader(boot_partition, efi_partition, root, uki_enabled, bootloader_removable)
|
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:
|
def add_additional_packages(self, packages: str | list[str]) -> None:
|
||||||
return self.pacman.strap(packages)
|
return self.pacman.strap(packages)
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,11 @@ class Bootloader(Enum):
|
||||||
Grub = 'Grub'
|
Grub = 'Grub'
|
||||||
Efistub = 'Efistub'
|
Efistub = 'Efistub'
|
||||||
Limine = 'Limine'
|
Limine = 'Limine'
|
||||||
|
Refind = 'Refind'
|
||||||
|
|
||||||
def has_uki_support(self) -> bool:
|
def has_uki_support(self) -> bool:
|
||||||
match self:
|
match self:
|
||||||
case Bootloader.Efistub | Bootloader.Limine | Bootloader.Systemd:
|
case Bootloader.Efistub | Bootloader.Limine | Bootloader.Systemd | Bootloader.Refind:
|
||||||
return True
|
return True
|
||||||
case _:
|
case _:
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue