index : archinstall32 | |
Archlinux32 installer | gitolite user |
summaryrefslogtreecommitdiff |
author | Anhad Singh <62820092+Andy-Python-Programmer@users.noreply.github.com> | 2023-06-30 17:53:53 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-30 09:53:53 +0200 |
commit | a0e4e6ee7604419d58d80f22b0348df6e745d8c8 (patch) | |
tree | 8e5188e1ff229bfeb45ac2ad90e067698a06bf47 /archinstall | |
parent | ffb9366280803578bd47f2d7102a5772fc44caab (diff) |
-rw-r--r-- | archinstall/lib/global_menu.py | 44 | ||||
-rw-r--r-- | archinstall/lib/installer.py | 112 | ||||
-rw-r--r-- | archinstall/lib/interactions/system_conf.py | 4 | ||||
-rw-r--r-- | archinstall/lib/models/bootloader.py | 1 |
diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index 54b30240..5a431010 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -169,8 +169,8 @@ class GlobalMenu(AbstractMenu): self._menu_options['install'] = \ Selector( self._install_text(), - exec_func=lambda n, v: True if len(self._missing_configs()) == 0 else False, - preview_func=self._prev_install_missing_config, + exec_func=lambda n, v: self._is_config_valid(), + preview_func=self._prev_install_invalid_config, no_store=True) self._menu_options['abort'] = Selector(_('Abort'), exec_func=lambda n,v:exit(1)) @@ -200,6 +200,14 @@ class GlobalMenu(AbstractMenu): return list(missing) + def _is_config_valid(self) -> bool: + """ + Checks the validity of the current configuration. + """ + if len(self._missing_configs()) != 0: + return False + return self._validate_bootloader() is None + def _update_install_text(self, name: str, value: str): text = self._install_text() self._menu_options['install'].update_description(text) @@ -321,12 +329,42 @@ class GlobalMenu(AbstractMenu): return disk.EncryptionType.type_to_text(current_value.encryption_type) return '' - def _prev_install_missing_config(self) -> Optional[str]: + def _validate_bootloader(self) -> Optional[str]: + """ + Checks the selected bootloader is valid for the selected filesystem + type of the boot partition. + + Returns [`None`] if the bootloader is valid, otherwise returns a + string with the error message. + """ + bootloader = self._menu_options['bootloader'].current_selection + boot_partition: Optional[disk.PartitionModification] = None + + if disk_config := self._menu_options['disk_config'].current_selection: + for layout in disk_config.device_modifications: + if boot_partition := layout.get_boot_partition(): + break + else: + return "No disk layout selected" + + if boot_partition is None: + return "Boot partition not found" + + if bootloader == Bootloader.Limine and boot_partition.fs_type == disk.FilesystemType.Btrfs: + return "Limine bootloader does not support booting from BTRFS filesystem" + + return None + + def _prev_install_invalid_config(self) -> Optional[str]: if missing := self._missing_configs(): text = str(_('Missing configurations:\n')) for m in missing: text += f'- {m}\n' return text[:-1] # remove last new line + + if error := self._validate_bootloader(): + return f"Invalid configuration: {error}" + return None def _prev_users(self) -> Optional[str]: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index ee546993..0d43b2fe 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -8,6 +8,8 @@ import time from pathlib import Path from typing import Any, List, Optional, TYPE_CHECKING, Union, Dict, Callable +from ..lib.disk.device_model import get_lsblk_info + from . import disk from .exceptions import DiskError, ServiceException, RequirementError, HardwareIncompatibilityError, SysCallError from .general import SysCommand @@ -850,6 +852,113 @@ class Installer: self.helper_flags['bootloader'] = "grub" + def _add_limine_bootloader( + self, + boot_partition: disk.PartitionModification, + root_partition: disk.PartitionModification + ): + self.pacman.strap('limine') + info(f"Limine boot partition: {boot_partition.dev_path}") + + # XXX: We cannot use `root_partition.uuid` since corresponds to the UUID of the root + # partition before the format. + root_uuid = get_lsblk_info(root_partition.safe_dev_path).uuid + + device = disk.device_handler.get_device_by_partition_path(boot_partition.safe_dev_path) + if not device: + raise ValueError(f'Can not find block device: {boot_partition.safe_dev_path}') + + def create_pacman_hook(contents: str): + HOOK_DIR = "/etc/pacman.d/hooks" + SysCommand(f"/usr/bin/arch-chroot {self.target} mkdir -p {HOOK_DIR}") + SysCommand(f"/usr/bin/arch-chroot {self.target} sh -c \"echo '{contents}' > {HOOK_DIR}/liminedeploy.hook\"") + + if SysInfo.has_uefi(): + try: + # The `limine.sys` file, contains stage 3 code. + cmd = f'/usr/bin/arch-chroot' \ + f' {self.target}' \ + f' cp' \ + f' /usr/share/limine/BOOTX64.EFI' \ + f' /boot/EFI/BOOT/' + except SysCallError as err: + raise DiskError(f"Failed to install Limine BOOTX64.EFI on {boot_partition.dev_path}: {err}") + + # Create the EFI limine pacman hook. + create_pacman_hook(""" +[Trigger] +Operation = Install +Operation = Upgrade +Type = Package +Target = limine + +[Action] +Description = Deploying Limine after upgrade... +When = PostTransaction +Exec = /usr/bin/cp /usr/share/limine/BOOTX64.EFI /boot/EFI/BOOT/ + """) + else: + try: + # The `limine.sys` file, contains stage 3 code. + cmd = f'/usr/bin/arch-chroot' \ + f' {self.target}' \ + f' cp' \ + f' /usr/share/limine/limine-bios.sys' \ + f' /boot/limine-bios.sys' + + SysCommand(cmd, peek_output=True) + + # `limine bios-install` deploys the stage 1 and 2 to the disk. + cmd = f'/usr/bin/arch-chroot' \ + f' {self.target}' \ + f' limine' \ + f' bios-install' \ + f' {device.device_info.path}' + + SysCommand(cmd, peek_output=True) + except SysCallError as err: + raise DiskError(f"Failed to install Limine on {boot_partition.dev_path}: {err}") + + create_pacman_hook(f""" +[Trigger] +Operation = Install +Operation = Upgrade +Type = Package +Target = limine + +[Action] +Description = Deploying Limine after upgrade... +When = PostTransaction +# XXX: Kernel name descriptors cannot be used since they are not persistent and +# can change after each boot. +Exec = /bin/sh -c \\"/usr/bin/limine bios-install /dev/disk/by-uuid/{root_uuid} && /usr/bin/cp /usr/share/limine/limine-bios.sys /boot/\\" + """) + + # Limine does not ship with a default configuation file. We are going to + # create a basic one that is similar to the one GRUB generates. + try: + config = f""" +TIMEOUT=5 + +:Arch Linux + PROTOCOL=linux + KERNEL_PATH=boot:///vmlinuz-linux + CMDLINE=root=UUID={root_uuid} rw rootfstype={root_partition.safe_fs_type.value} loglevel=3 + MODULE_PATH=boot:///initramfs-linux.img + +:Arch Linux (fallback) + PROTOCOL=linux + KERNEL_PATH=boot:///vmlinuz-linux + CMDLINE=root=UUID={root_uuid} rw rootfstype={root_partition.safe_fs_type.value} loglevel=3 + MODULE_PATH=boot:///initramfs-linux-fallback.img + """ + + SysCommand(f"/usr/bin/arch-chroot {self.target} sh -c \"echo '{config}' > /boot/limine.cfg\"") + except SysCallError as err: + raise DiskError(f"Could not configure Limine: {err}") + + self.helper_flags['bootloader'] = "limine" + def _add_efistub_bootloader( self, boot_partition: disk.PartitionModification, @@ -918,6 +1027,7 @@ class Installer: Archinstall supports one of three types: * systemd-bootctl * grub + * limine (beta) * efistub (beta) :param bootloader: Type of bootloader to be added @@ -948,6 +1058,8 @@ class Installer: self._add_grub_bootloader(boot_partition, root_partition) case Bootloader.Efistub: self._add_efistub_bootloader(boot_partition, root_partition) + case Bootloader.Limine: + self._add_limine_bootloader(boot_partition, root_partition) def add_additional_packages(self, packages: Union[str, List[str]]) -> bool: return self.pacman.strap(packages) diff --git a/archinstall/lib/interactions/system_conf.py b/archinstall/lib/interactions/system_conf.py index 5b1bc456..0e5e0f1e 100644 --- a/archinstall/lib/interactions/system_conf.py +++ b/archinstall/lib/interactions/system_conf.py @@ -40,9 +40,9 @@ def select_kernel(preset: List[str] = []) -> List[str]: def ask_for_bootloader(preset: Bootloader) -> Bootloader: - # when the system only supports grub + # Systemd is UEFI only if not SysInfo.has_uefi(): - options = [Bootloader.Grub.value] + options = [Bootloader.Grub.value, Bootloader.Limine.value] default = Bootloader.Grub.value else: options = Bootloader.values() diff --git a/archinstall/lib/models/bootloader.py b/archinstall/lib/models/bootloader.py index e21cda33..be9812a0 100644 --- a/archinstall/lib/models/bootloader.py +++ b/archinstall/lib/models/bootloader.py @@ -12,6 +12,7 @@ class Bootloader(Enum): Systemd = 'Systemd-boot' Grub = 'Grub' Efistub = 'Efistub' + Limine = 'Limine' def json(self): return self.value |