Extend validate_bootloader_layout with UEFI-dependent checks
Add is_uefi parameter and three new validations: Systemd-boot, Efistub and rEFInd require UEFI; Efistub additionally requires a FAT boot partition. Move the rEFInd UEFI-only check out of GlobalMenu so guided.py and Installer silent-install paths get the same coverage.
This commit is contained in:
parent
de43019094
commit
da19fcdff7
|
|
@ -9,6 +9,8 @@ from archinstall.lib.models.device import DiskLayoutConfiguration
|
||||||
class BootloaderValidationFailureKind(Enum):
|
class BootloaderValidationFailureKind(Enum):
|
||||||
LimineNonFatBoot = auto()
|
LimineNonFatBoot = auto()
|
||||||
LimineLayout = auto()
|
LimineLayout = auto()
|
||||||
|
BootloaderRequiresUefi = auto()
|
||||||
|
EfistubNonFatBoot = auto()
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
|
|
@ -17,9 +19,13 @@ class BootloaderValidationFailure:
|
||||||
description: str
|
description: str
|
||||||
|
|
||||||
|
|
||||||
|
_UEFI_ONLY_BOOTLOADERS = (Bootloader.Systemd, Bootloader.Efistub, Bootloader.Refind)
|
||||||
|
|
||||||
|
|
||||||
def validate_bootloader_layout(
|
def validate_bootloader_layout(
|
||||||
bootloader_config: BootloaderConfiguration | None,
|
bootloader_config: BootloaderConfiguration | None,
|
||||||
disk_config: DiskLayoutConfiguration | None,
|
disk_config: DiskLayoutConfiguration | None,
|
||||||
|
is_uefi: bool,
|
||||||
) -> BootloaderValidationFailure | None:
|
) -> BootloaderValidationFailure | None:
|
||||||
"""Validate bootloader configuration against disk layout.
|
"""Validate bootloader configuration against disk layout.
|
||||||
|
|
||||||
|
|
@ -29,12 +35,32 @@ def validate_bootloader_layout(
|
||||||
if not (bootloader_config and disk_config):
|
if not (bootloader_config and disk_config):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if bootloader_config.bootloader == Bootloader.Limine:
|
bootloader = bootloader_config.bootloader
|
||||||
boot_part = next(
|
|
||||||
(p for m in disk_config.device_modifications if (p := m.get_boot_partition())),
|
if bootloader == Bootloader.NO_BOOTLOADER:
|
||||||
None,
|
return None
|
||||||
|
|
||||||
|
if bootloader in _UEFI_ONLY_BOOTLOADERS and not is_uefi:
|
||||||
|
return BootloaderValidationFailure(
|
||||||
|
kind=BootloaderValidationFailureKind.BootloaderRequiresUefi,
|
||||||
|
description=f'{bootloader.value} requires a UEFI system.',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
boot_part = next(
|
||||||
|
(p for m in disk_config.device_modifications if (p := m.get_boot_partition())),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
if bootloader == Bootloader.Efistub:
|
||||||
|
# The UEFI firmware reads the kernel directly from the boot partition,
|
||||||
|
# which must be FAT.
|
||||||
|
if boot_part and (boot_part.fs_type is None or not boot_part.fs_type.is_fat()):
|
||||||
|
return BootloaderValidationFailure(
|
||||||
|
kind=BootloaderValidationFailureKind.EfistubNonFatBoot,
|
||||||
|
description='Efistub does not support booting with a non-FAT boot partition.',
|
||||||
|
)
|
||||||
|
|
||||||
|
if bootloader == Bootloader.Limine:
|
||||||
# Limine reads its config and kernels from the boot partition, which
|
# Limine reads its config and kernels from the boot partition, which
|
||||||
# must be FAT.
|
# must be FAT.
|
||||||
if boot_part and (boot_part.fs_type is None or not boot_part.fs_type.is_fat()):
|
if boot_part and (boot_part.fs_type is None or not boot_part.fs_type.is_fat()):
|
||||||
|
|
|
||||||
|
|
@ -461,8 +461,6 @@ class GlobalMenu(AbstractMenu[None]):
|
||||||
if not bootloader_config or bootloader_config.bootloader == Bootloader.NO_BOOTLOADER:
|
if not bootloader_config or bootloader_config.bootloader == Bootloader.NO_BOOTLOADER:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
bootloader = bootloader_config.bootloader
|
|
||||||
|
|
||||||
if disk_config := self._item_group.find_by_key('disk_config').value:
|
if disk_config := self._item_group.find_by_key('disk_config').value:
|
||||||
for layout in disk_config.device_modifications:
|
for layout in disk_config.device_modifications:
|
||||||
if root_partition := layout.get_root_partition():
|
if root_partition := layout.get_root_partition():
|
||||||
|
|
@ -490,10 +488,7 @@ class GlobalMenu(AbstractMenu[None]):
|
||||||
if efi_partition.fs_type is None or not efi_partition.fs_type.is_fat():
|
if efi_partition.fs_type is None or not efi_partition.fs_type.is_fat():
|
||||||
return 'ESP must be formatted as a FAT filesystem'
|
return 'ESP must be formatted as a FAT filesystem'
|
||||||
|
|
||||||
if bootloader == Bootloader.Refind and not self._uefi:
|
if failure := validate_bootloader_layout(bootloader_config, disk_config, self._uefi):
|
||||||
return 'rEFInd can only be used on UEFI systems'
|
|
||||||
|
|
||||||
if failure := validate_bootloader_layout(bootloader_config, disk_config):
|
|
||||||
return failure.description
|
return failure.description
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
|
|
@ -1472,6 +1472,7 @@ class Installer:
|
||||||
if failure := validate_bootloader_layout(
|
if failure := validate_bootloader_layout(
|
||||||
BootloaderConfiguration(bootloader=Bootloader.Limine, uki=uki_enabled),
|
BootloaderConfiguration(bootloader=Bootloader.Limine, uki=uki_enabled),
|
||||||
self._disk_config,
|
self._disk_config,
|
||||||
|
SysInfo.has_uefi(),
|
||||||
):
|
):
|
||||||
raise DiskError(failure.description)
|
raise DiskError(failure.description)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from archinstall.lib.disk.filesystem import FilesystemHandler
|
||||||
from archinstall.lib.disk.utils import disk_layouts
|
from archinstall.lib.disk.utils import disk_layouts
|
||||||
from archinstall.lib.general.general_menu import PostInstallationAction, select_post_installation
|
from archinstall.lib.general.general_menu import PostInstallationAction, select_post_installation
|
||||||
from archinstall.lib.global_menu import GlobalMenu
|
from archinstall.lib.global_menu import GlobalMenu
|
||||||
|
from archinstall.lib.hardware import SysInfo
|
||||||
from archinstall.lib.installer import Installer, accessibility_tools_in_use, run_custom_user_commands
|
from archinstall.lib.installer import Installer, accessibility_tools_in_use, run_custom_user_commands
|
||||||
from archinstall.lib.menu.util import delayed_warning
|
from archinstall.lib.menu.util import delayed_warning
|
||||||
from archinstall.lib.mirror.mirror_handler import MirrorListHandler
|
from archinstall.lib.mirror.mirror_handler import MirrorListHandler
|
||||||
|
|
@ -217,6 +218,7 @@ def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
|
||||||
if failure := validate_bootloader_layout(
|
if failure := validate_bootloader_layout(
|
||||||
arch_config_handler.config.bootloader_config,
|
arch_config_handler.config.bootloader_config,
|
||||||
arch_config_handler.config.disk_config,
|
arch_config_handler.config.disk_config,
|
||||||
|
SysInfo.has_uefi(),
|
||||||
):
|
):
|
||||||
error(failure.description)
|
error(failure.description)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue