Fix Limine install with ESP mounted outside /boot
Place limine.conf next to the EFI binary on the ESP so it is found regardless of ESP mountpoint, and block unbootable layouts (non-UKI Limine with ESP not at /boot and no separate /boot partition) in GlobalMenu validation, guided.main() and _add_limine_bootloader(). Fixes #4333
This commit is contained in:
parent
cd62eff4a7
commit
71cd6d46f8
|
|
@ -1,3 +1,4 @@
|
|||
from pathlib import Path
|
||||
from typing import override
|
||||
|
||||
from archinstall.default_profiles.profile import GreeterType
|
||||
|
|
@ -492,6 +493,11 @@ class GlobalMenu(AbstractMenu[None]):
|
|||
if bootloader == Bootloader.Limine:
|
||||
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'
|
||||
if self._uefi and efi_partition and boot_partition == efi_partition and efi_partition.mountpoint != Path('/boot') and not bootloader_config.uki:
|
||||
return (
|
||||
f'Limine requires kernels on a FAT partition. The ESP is mounted at {efi_partition.mountpoint}, '
|
||||
'enable UKI or add a separate /boot partition'
|
||||
)
|
||||
|
||||
elif bootloader == Bootloader.Refind:
|
||||
if not self._uefi:
|
||||
|
|
|
|||
|
|
@ -1466,6 +1466,16 @@ class Installer:
|
|||
elif not efi_partition.mountpoint:
|
||||
raise ValueError('EFI partition is not mounted')
|
||||
|
||||
# Limine can only read FAT filesystems. When the ESP doubles as
|
||||
# the boot partition but is mounted outside /boot (e.g. /efi,
|
||||
# /boot/efi) and UKI is disabled, kernels end up on the root
|
||||
# filesystem under /boot/ which Limine cannot access.
|
||||
if boot_partition == efi_partition and efi_partition.mountpoint != Path('/boot') and not uki_enabled:
|
||||
raise DiskError(
|
||||
f'Limine requires kernels on a FAT partition. The ESP is mounted at {efi_partition.mountpoint}, '
|
||||
'so enable UKI or add a separate /boot partition to install Limine.',
|
||||
)
|
||||
|
||||
info(f'Limine EFI partition: {efi_partition.dev_path}')
|
||||
|
||||
parent_dev_path = get_parent_device_path(efi_partition.safe_dev_path)
|
||||
|
|
@ -1476,15 +1486,11 @@ class Installer:
|
|||
if bootloader_removable:
|
||||
efi_dir_path = efi_dir_path / 'BOOT'
|
||||
efi_dir_path_target = efi_dir_path_target / 'BOOT'
|
||||
|
||||
boot_limine_path = self.target / 'boot' / 'limine'
|
||||
boot_limine_path.mkdir(parents=True, exist_ok=True)
|
||||
config_path = boot_limine_path / 'limine.conf'
|
||||
else:
|
||||
efi_dir_path = efi_dir_path / 'arch-limine'
|
||||
efi_dir_path_target = efi_dir_path_target / 'arch-limine'
|
||||
|
||||
config_path = efi_dir_path / 'limine.conf'
|
||||
config_path = efi_dir_path / 'limine.conf'
|
||||
|
||||
efi_dir_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from archinstall.lib.applications.application_handler import ApplicationHandler
|
||||
from archinstall.lib.args import ArchConfig, ArchConfigHandler
|
||||
|
|
@ -195,6 +196,35 @@ def perform_installation(
|
|||
pass
|
||||
|
||||
|
||||
def _check_bootloader_layout(config: ArchConfig) -> str | None:
|
||||
"""Validate bootloader configuration against disk layout.
|
||||
|
||||
Returns an error message if the configuration would produce an
|
||||
unbootable system, or None if it is valid.
|
||||
"""
|
||||
# Limine can only read FAT. When the ESP is the boot partition but
|
||||
# mounted outside /boot and UKI is disabled, the kernel ends up on the
|
||||
# root filesystem which Limine cannot access.
|
||||
if not (config.bootloader_config and config.bootloader_config.bootloader == Bootloader.Limine and not config.bootloader_config.uki and config.disk_config):
|
||||
return None
|
||||
|
||||
efi_part = next(
|
||||
(p for m in config.disk_config.device_modifications if (p := m.get_efi_partition())),
|
||||
None,
|
||||
)
|
||||
boot_part = next(
|
||||
(p for m in config.disk_config.device_modifications if (p := m.get_boot_partition())),
|
||||
None,
|
||||
)
|
||||
|
||||
if efi_part and boot_part == efi_part and efi_part.mountpoint != Path('/boot'):
|
||||
return (
|
||||
f'Limine requires kernels on a FAT partition. The ESP is mounted at {efi_part.mountpoint}, '
|
||||
'enable UKI or add a separate /boot partition to install Limine.'
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
|
||||
if arch_config_handler is None:
|
||||
arch_config_handler = ArchConfigHandler()
|
||||
|
|
@ -211,6 +241,12 @@ def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
|
|||
config.write_debug()
|
||||
config.save()
|
||||
|
||||
# Safety net for silent/config-file flow. The TUI menu blocks Install via
|
||||
# GlobalMenu._validate_bootloader() before reaching this point.
|
||||
if err_msg := _check_bootloader_layout(arch_config_handler.config):
|
||||
error(err_msg)
|
||||
return
|
||||
|
||||
if arch_config_handler.args.dry_run:
|
||||
return
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue