diff --git a/archinstall/lib/disk/partitioning_menu.py b/archinstall/lib/disk/partitioning_menu.py index 780d83fa..2df42779 100644 --- a/archinstall/lib/disk/partitioning_menu.py +++ b/archinstall/lib/disk/partitioning_menu.py @@ -95,13 +95,19 @@ class PartitioningList(ListManager): 'assign_mountpoint': str(_('Assign mountpoint')), 'mark_formatting': str(_('Mark/Unmark to be formatted (wipes data)')), 'mark_bootable': str(_('Mark/Unmark as bootable')), - 'mark_xbootldr': str(_('Mark/Unmark as XBOOTLDR')), + } + if self._using_gpt: + self._actions.update({ + 'mark_esp': str(_('Mark/Unmark as ESP')), + 'mark_xbootldr': str(_('Mark/Unmark as XBOOTLDR')) + }) + self._actions.update({ 'set_filesystem': str(_('Change filesystem')), 'btrfs_mark_compressed': str(_('Mark/Unmark as compressed')), # btrfs only 'btrfs_mark_nodatacow': str(_('Mark/Unmark as nodatacow')), # btrfs only 'btrfs_set_subvolumes': str(_('Set subvolumes')), # btrfs only 'delete_partition': str(_('Delete partition')) - } + }) device_partitions = [] @@ -239,8 +245,14 @@ class PartitioningList(ListManager): # how do we know it was the original one? not_filter += [ self._actions['set_filesystem'], - self._actions['mark_bootable'], - self._actions['mark_xbootldr'], + self._actions['mark_bootable'] + ] + if self._using_gpt: + not_filter += [ + self._actions['mark_esp'], + self._actions['mark_xbootldr'] + ] + not_filter += [ self._actions['btrfs_mark_compressed'], self._actions['btrfs_mark_nodatacow'], self._actions['btrfs_set_subvolumes'] @@ -287,23 +299,46 @@ class PartitioningList(ListManager): action_key = [k for k, v in self._actions.items() if v == action][0] match action_key: case 'assign_mountpoint': - partition.mountpoint = self._prompt_mountpoint() - if partition.mountpoint == Path('/boot'): - partition.set_flag(PartitionFlag.BOOT) - if self._using_gpt: - partition.set_flag(PartitionFlag.ESP) + new_mountpoint = self._prompt_mountpoint() + if not partition.is_swap(): + if partition.is_home(): + partition.invert_flag(PartitionFlag.LINUX_HOME) + partition.mountpoint = new_mountpoint + if partition.is_root(): + partition.flags = [] + if partition.is_boot(): + partition.flags = [] + partition.set_flag(PartitionFlag.BOOT) + if self._using_gpt: + partition.set_flag(PartitionFlag.ESP) + if partition.is_home(): + partition.flags = [] + partition.set_flag(PartitionFlag.LINUX_HOME) case 'mark_formatting': self._prompt_formatting(partition) case 'mark_bootable': - partition.invert_flag(PartitionFlag.BOOT) - if self._using_gpt: + if not partition.is_swap(): + partition.invert_flag(PartitionFlag.BOOT) + case 'mark_esp': + if not partition.is_root() and not partition.is_home() and not partition.is_swap(): + if PartitionFlag.XBOOTLDR in partition.flags: + partition.invert_flag(PartitionFlag.XBOOTLDR) partition.invert_flag(PartitionFlag.ESP) case 'mark_xbootldr': - partition.invert_flag(PartitionFlag.XBOOTLDR) + if not partition.is_root() and not partition.is_home() and not partition.is_swap(): + if PartitionFlag.ESP in partition.flags: + partition.invert_flag(PartitionFlag.ESP) + partition.invert_flag(PartitionFlag.XBOOTLDR) case 'set_filesystem': fs_type = self._prompt_partition_fs_type() if fs_type: + if partition.is_swap(): + partition.invert_flag(PartitionFlag.SWAP) partition.fs_type = fs_type + if partition.is_swap(): + partition.mountpoint = None + partition.flags = [] + partition.set_flag(PartitionFlag.SWAP) # btrfs subvolumes will define mountpoints if fs_type == FilesystemType.Btrfs: partition.mountpoint = None @@ -390,7 +425,6 @@ class PartitioningList(ListManager): def _prompt_mountpoint(self) -> Path: header = str(_('Partition mount-points are relative to inside the installation, the boot would be /boot as an example.')) + '\n' - header += str(_('If mountpoint /boot is set, then the partition will also be marked as bootable.')) + '\n' prompt = str(_('Mountpoint')) mountpoint = prompt_dir(prompt, header, validate=False, allow_skip=False) @@ -520,6 +554,8 @@ class PartitioningList(ListManager): if self._using_gpt: partition.set_flag(PartitionFlag.ESP) elif partition.is_swap(): + partition.mountpoint = None + partition.flags = [] partition.set_flag(PartitionFlag.SWAP) return partition diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index c3c45ecd..d633047d 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -425,21 +425,40 @@ class GlobalMenu(AbstractMenu): shim if necessary. """ bootloader = self._item_group.find_by_key('bootloader').value + root_partition: PartitionModification | None = None boot_partition: PartitionModification | None = None + efi_partition: PartitionModification | None = None if disk_config := self._item_group.find_by_key('disk_config').value: + for layout in disk_config.device_modifications: + if root_partition := layout.get_root_partition(): + break for layout in disk_config.device_modifications: if boot_partition := layout.get_boot_partition(): break + if SysInfo.has_uefi(): + for layout in disk_config.device_modifications: + if efi_partition := layout.get_efi_partition(): + break else: return "No disk layout selected" + if root_partition is None: + return "Root partition not found" + if boot_partition is None: return "Boot partition not found" + if SysInfo.has_uefi(): + if efi_partition is None: + return "EFI system partition (ESP) not found" + + if efi_partition.fs_type not in [FilesystemType.Fat12, FilesystemType.Fat16, FilesystemType.Fat32]: + return "ESP must be formatted as a FAT filesystem" + if bootloader == Bootloader.Limine: - if boot_partition.fs_type != FilesystemType.Fat32: - return "Limine does not support booting without a FAT boot partition" + 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 None diff --git a/archinstall/lib/models/device_model.py b/archinstall/lib/models/device_model.py index e5742e7a..47f79b9c 100644 --- a/archinstall/lib/models/device_model.py +++ b/archinstall/lib/models/device_model.py @@ -871,9 +871,6 @@ class PartitionModification: partuuid: str | None = None uuid: str | None = None - _efi_indicator_flags = (PartitionFlag.BOOT, PartitionFlag.ESP) - _boot_indicator_flags = (PartitionFlag.BOOT, PartitionFlag.XBOOTLDR) - def __post_init__(self) -> None: # needed to use the object as a dictionary key due to hash func if not hasattr(self, '_obj_id'): @@ -951,26 +948,16 @@ class PartitionModification: raise ValueError('Mountpoint is not specified') def is_efi(self) -> bool: - return ( - any(set(self.flags) & set(self._efi_indicator_flags)) - and ( - self.fs_type == FilesystemType.Fat12 - or self.fs_type == FilesystemType.Fat16 - or self.fs_type == FilesystemType.Fat32 - ) - and PartitionFlag.XBOOTLDR not in self.flags - ) + return PartitionFlag.ESP in self.flags def is_boot(self) -> bool: - """ - Returns True if any of the boot indicator flags are found in self.flags - or if the partition is mounted on /boot - """ - return any(set(self.flags) & set(self._boot_indicator_flags)) or Path('/boot') == self.mountpoint + if self.mountpoint is not None: + return self.mountpoint == Path('/boot') + return False def is_root(self) -> bool: if self.mountpoint is not None: - return Path('/') == self.mountpoint + return self.mountpoint == Path('/') else: for subvol in self.btrfs_subvols: if subvol.is_root(): @@ -979,10 +966,9 @@ class PartitionModification: return False def is_home(self) -> bool: - return ( - self.mountpoint == Path('/home') - or PartitionFlag.LINUX_HOME in self.flags - ) + if self.mountpoint is not None: + return self.mountpoint == Path('/home') + return False def is_swap(self) -> bool: return self.fs_type == FilesystemType.LinuxSwap @@ -1377,26 +1363,12 @@ class DeviceModification: self.partitions.append(partition) def get_efi_partition(self) -> PartitionModification | None: - """ - Similar to get_boot_partition() but excludes XBOOTLDR partitions from it's candidates. - """ filtered = filter(lambda x: x.is_efi() and x.mountpoint, self.partitions) return next(filtered, None) def get_boot_partition(self) -> PartitionModification | None: - """ - Returns the first partition marked as XBOOTLDR (PARTTYPE id of bc13c2ff-...) or Boot and has a mountpoint. - Only returns XBOOTLDR if separate EFI is detected using self.get_efi_partition() - Will return None if no suitable partition is found. - """ - if efi_partition := self.get_efi_partition(): - filtered = filter(lambda x: x.is_boot() and x != efi_partition and x.mountpoint, self.partitions) - if boot_partition := next(filtered, None): - return boot_partition - return efi_partition - else: - filtered = filter(lambda x: x.is_boot() and x.mountpoint, self.partitions) - return next(filtered, None) + filtered = filter(lambda x: x.is_boot() and x.mountpoint, self.partitions) + return next(filtered, None) def get_root_partition(self) -> PartitionModification | None: filtered = filter(lambda x: x.is_root(), self.partitions)