archinstall/archinstall/lib/models/bootloader.py

116 lines
3.0 KiB
Python

import sys
from dataclasses import dataclass
from enum import Enum
from typing import Any, Self, override
from archinstall.lib.log import warn
from archinstall.lib.models.config import SubConfig
from archinstall.lib.translationhandler import tr
class Bootloader(Enum):
NO_BOOTLOADER = 'No bootloader'
Systemd = 'Systemd-boot'
Grub = 'Grub'
Efistub = 'Efistub'
Limine = 'Limine'
Refind = 'Refind'
def has_uki_support(self) -> bool:
return self != Bootloader.NO_BOOTLOADER
def has_removable_support(self) -> bool:
match self:
case Bootloader.Grub | Bootloader.Limine:
return True
case _:
return False
def is_uefi_only(self) -> bool:
match self:
case Bootloader.Systemd | Bootloader.Efistub | Bootloader.Refind:
return True
case _:
return False
def json(self) -> str:
return self.value
@classmethod
def get_default(cls, uefi: bool, skip_boot: bool = False) -> Self:
if skip_boot:
return cls.NO_BOOTLOADER
elif uefi:
return cls.Systemd
else:
return cls.Grub
@classmethod
def from_arg(cls, bootloader: str, skip_boot: bool) -> Self:
# to support old configuration files
bootloader = bootloader.capitalize()
bootloader_options = [e.value for e in cls if e != cls.NO_BOOTLOADER or skip_boot is True]
if bootloader not in bootloader_options:
values = ', '.join(bootloader_options)
warn(f'Invalid bootloader value "{bootloader}". Allowed values: {values}')
sys.exit(1)
return cls(bootloader)
@dataclass
class BootloaderConfiguration(SubConfig):
bootloader: Bootloader
uki: bool = False
removable: bool = True
@override
def json(self) -> dict[str, Any]:
return {'bootloader': self.bootloader.json(), 'uki': self.uki, 'removable': self.removable}
@override
def summary(self) -> list[str]:
out = [tr('Bootloader "{}"').format(self.bootloader.value)]
if self.uki:
out.append(tr('UKI enabled'))
if self.removable:
out.append(tr('Removable'))
return out
@classmethod
def parse_arg(cls, config: dict[str, Any], skip_boot: bool) -> Self:
bootloader = Bootloader.from_arg(config.get('bootloader', ''), skip_boot)
uki = config.get('uki', False)
removable = config.get('removable', True)
return cls(bootloader=bootloader, uki=uki, removable=removable)
@classmethod
def get_default(cls, uefi: bool, skip_boot: bool = False) -> Self:
bootloader = Bootloader.get_default(uefi, skip_boot)
removable = uefi and bootloader.has_removable_support()
uki = uefi and bootloader.has_uki_support()
return cls(bootloader=bootloader, uki=uki, removable=removable)
def preview(self, uefi: bool) -> str:
text = f'{tr("Bootloader")}: {self.bootloader.value}'
text += '\n'
if uefi and self.bootloader.has_uki_support():
if self.uki:
uki_string = tr('Enabled')
else:
uki_string = tr('Disabled')
text += f'UKI: {uki_string}'
text += '\n'
if uefi and self.bootloader.has_removable_support():
if self.removable:
removable_string = tr('Enabled')
else:
removable_string = tr('Disabled')
text += f'{tr("Removable")}: {removable_string}'
text += '\n'
return text