This commit is contained in:
Victor Zacarias 2026-08-12 22:04:36 -03:00 committed by GitHub
commit 7757daf366
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 128 additions and 18 deletions

View File

@ -41,6 +41,11 @@ class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
if not removable_enabled:
self._bootloader_conf.removable = False
# os-prober availability
os_prober_enabled = bootloader.has_os_prober_support()
if not os_prober_enabled:
self._bootloader_conf.os_prober = False
return [
MenuItem(
text=tr('Bootloader'),
@ -66,6 +71,14 @@ class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
key='removable',
enabled=removable_enabled,
),
MenuItem(
text=tr('Detect other operating systems'),
action=self._select_os_prober,
value=self._bootloader_conf.os_prober,
preview_action=self._prev_os_prober,
key='os_prober',
enabled=os_prober_enabled,
),
MenuItem(
text=tr('Plymouth'),
action=self._select_plymouth,
@ -92,6 +105,13 @@ class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
return tr('Will install to /EFI/BOOT/ (removable location, safe default)')
return tr('Will install to custom location with NVRAM entry')
def _prev_os_prober(self, item: MenuItem) -> str | None:
os_prober_text = f'{tr("Detect other operating systems")}'
if item.value:
return f'{os_prober_text}: {tr("Enabled")}'
else:
return f'{os_prober_text}: {tr("Disabled")}'
def _prev_plymouth(self, item: MenuItem) -> str | None:
if item.value:
return f'{tr("Plymouth")}: {item.value.value}'
@ -127,6 +147,15 @@ class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
self._bootloader_conf.removable = True
removable_item.enabled = True
# Update os-prober option based on bootloader
os_prober_item = self._menu_item_group.find_by_key('os_prober')
if not bootloader.has_os_prober_support():
os_prober_item.enabled = False
os_prober_item.value = False
self._bootloader_conf.os_prober = False
else:
os_prober_item.enabled = True
return bootloader
async def _select_plymouth(self, preset: PlymouthTheme | None) -> PlymouthTheme | None:
@ -219,6 +248,19 @@ class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
case ResultType.Reset:
raise ValueError('Unhandled result type')
async def _select_os_prober(self, preset: bool) -> bool:
prompt = tr('Would you like to enable os-prober to detect other operating systems (e.g. Windows)?') + '\n'
result = await Confirmation(header=prompt, allow_skip=True, preset=preset).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.item() == MenuItem.yes()
case ResultType.Reset:
raise ValueError('Unhandled result type')
async def select_bootloader(
preset: Bootloader | None,

View File

@ -1331,6 +1331,7 @@ class Installer:
efi_partition: PartitionModification | None,
uki_enabled: bool = False,
bootloader_removable: bool = False,
os_prober: bool = False,
) -> None:
debug('Installing grub bootloader')
@ -1430,6 +1431,31 @@ class Installer:
grub_default.write_text(config)
if os_prober:
debug('Enabling os-prober in GRUB configuration')
# fuse3 enables grub-mount, which os-prober requires to inspect
# partitions that are not mounted (e.g. Windows on another disk)
self.pacman.strap(['os-prober', 'fuse3'])
# grub-mkconfig only runs os-prober when GRUB_DISABLE_OS_PROBER is
# explicitly set to false; the stock config ships the option commented out
grub_default = self.target / 'etc/default/grub'
config = grub_default.read_text()
config, count = re.subn(
r'^#?GRUB_DISABLE_OS_PROBER=.*$',
'GRUB_DISABLE_OS_PROBER=false',
config,
count=1,
flags=re.MULTILINE,
)
if count == 0:
config += '\nGRUB_DISABLE_OS_PROBER=false\n'
grub_default.write_text(config)
try:
self.arch_chroot(
f'grub-mkconfig -o {boot_dir}/grub/grub.cfg',
@ -1833,7 +1859,12 @@ class Installer:
error('Error generating initramfs (continuing anyway)')
def add_bootloader(
self, bootloader: Bootloader, uki_enabled: bool = False, bootloader_removable: bool = False, plymouth: PlymouthTheme | None = None
self,
bootloader: Bootloader,
uki_enabled: bool = False,
bootloader_removable: bool = False,
plymouth: PlymouthTheme | None = None,
os_prober: bool = False,
) -> None:
"""
Adds a bootloader to the installation instance.
@ -1848,6 +1879,7 @@ class Installer:
:param uki_enabled: Whether to use unified kernel images
:param bootloader_removable: Whether to install to removable media location (UEFI only, for GRUB and Limine)
:param plymouth: Optional Plymouth theme to install and configure
:param os_prober: Whether to enable os-prober so grub-mkconfig detects other operating systems (GRUB only)
"""
for plugin in plugins.values():
@ -1883,6 +1915,11 @@ class Installer:
warn(f'Bootloader {bootloader.value} lacks removable support; disabling.')
bootloader_removable = False
# validate os-prober option
if os_prober and not bootloader.has_os_prober_support():
warn(f'Bootloader {bootloader.value} does not support os-prober; disabling.')
os_prober = False
if plymouth is not None:
self._install_plymouth(plymouth)
@ -1899,7 +1936,7 @@ class Installer:
case Bootloader.Systemd:
self._add_systemd_bootloader(boot_partition, root, efi_partition, uki_enabled)
case Bootloader.Grub:
self._add_grub_bootloader(boot_partition, root, efi_partition, uki_enabled, bootloader_removable)
self._add_grub_bootloader(boot_partition, root, efi_partition, uki_enabled, bootloader_removable, os_prober)
case Bootloader.Efistub:
self._add_efistub_bootloader(boot_partition, root, uki_enabled)
case Bootloader.Limine:

View File

@ -26,6 +26,9 @@ class Bootloader(Enum):
case _:
return False
def has_os_prober_support(self) -> bool:
return self == Bootloader.Grub
def is_uefi_only(self) -> bool:
match self:
case Bootloader.Systemd | Bootloader.Efistub | Bootloader.Refind:
@ -94,10 +97,11 @@ class BootloaderConfiguration(SubConfig):
uki: bool = False
removable: bool = True
plymouth: PlymouthTheme | None = None
os_prober: bool = False
@override
def json(self) -> dict[str, Any]:
data = {'bootloader': self.bootloader.json(), 'uki': self.uki, 'removable': self.removable}
data = {'bootloader': self.bootloader.json(), 'uki': self.uki, 'removable': self.removable, 'os_prober': self.os_prober}
if self.plymouth is not None:
data['plymouth'] = self.plymouth.value
@ -111,6 +115,8 @@ class BootloaderConfiguration(SubConfig):
out.append(tr('UKI enabled'))
if self.removable:
out.append(tr('Removable'))
if self.os_prober:
out.append(tr('os-prober enabled'))
if self.plymouth is not None:
out.append(tr('Plymouth "{}"').format(self.plymouth.value))
@ -122,7 +128,8 @@ class BootloaderConfiguration(SubConfig):
uki = config.get('uki', False)
removable = config.get('removable', True)
plymouth = PlymouthTheme.from_arg(config.get('plymouth', None))
return cls(bootloader=bootloader, uki=uki, removable=removable, plymouth=plymouth)
os_prober = config.get('os_prober', False)
return cls(bootloader=bootloader, uki=uki, removable=removable, plymouth=plymouth, os_prober=os_prober)
@classmethod
def get_default(cls, uefi: bool, skip_boot: bool = False) -> Self:
@ -130,7 +137,8 @@ class BootloaderConfiguration(SubConfig):
removable = uefi and bootloader.has_removable_support()
uki = uefi and bootloader.has_uki_support()
plymouth = None
return cls(bootloader=bootloader, uki=uki, removable=removable, plymouth=plymouth)
os_prober = False
return cls(bootloader=bootloader, uki=uki, removable=removable, plymouth=plymouth, os_prober=os_prober)
def preview(self, uefi: bool) -> str:
text = f'{tr("Bootloader")}: {self.bootloader.value}'
@ -149,6 +157,13 @@ class BootloaderConfiguration(SubConfig):
removable_string = tr('Disabled')
text += f'{tr("Removable")}: {removable_string}'
text += '\n'
if self.bootloader.has_os_prober_support():
if self.os_prober:
os_prober_string = tr('Enabled')
else:
os_prober_string = tr('Disabled')
text += f'{tr("Detect other operating systems")}: {os_prober_string}'
text += '\n'
if self.plymouth is not None:
text += f'{tr("Plymouth")}: {self.plymouth.value}'
text += '\n'

View File

@ -209,6 +209,9 @@ msgstr ""
msgid "Install to removable location"
msgstr ""
msgid "Detect other operating systems"
msgstr ""
msgid "Plymouth"
msgstr ""
@ -259,6 +262,11 @@ msgstr ""
msgid "Systems where you want the disk to be bootable on any computer."
msgstr ""
msgid ""
"Would you like to enable os-prober to detect other operating systems (e.g. "
"Windows)?"
msgstr ""
msgid "Select bootloader to install"
msgstr ""
@ -906,6 +914,9 @@ msgstr ""
msgid "Removable"
msgstr ""
msgid "os-prober enabled"
msgstr ""
#, python-brace-format
msgid "Plymouth \"{}\""
msgstr ""
@ -1122,6 +1133,15 @@ msgid ""
"Select any packages from the below list that should be installed additionally"
msgstr ""
msgid ""
"Pacman is already running, waiting maximum 10 minutes for it to terminate."
msgstr ""
msgid ""
"Pre-existing pacman lock never exited. Please clean up any existing pacman "
"sessions before using archinstall."
msgstr ""
#, python-brace-format
msgid "Enter the number of parallel downloads (1-{})"
msgstr ""
@ -1133,15 +1153,6 @@ msgstr ""
msgid "Enable colored output for pacman"
msgstr ""
msgid ""
"Pacman is already running, waiting maximum 10 minutes for it to terminate."
msgstr ""
msgid ""
"Pre-existing pacman lock never exited. Please clean up any existing pacman "
"sessions before using archinstall."
msgstr ""
msgid "The proprietary Nvidia driver is not supported by Sway."
msgstr ""

View File

@ -120,6 +120,7 @@ def perform_installation(
config.bootloader_config.uki,
config.bootloader_config.removable,
config.bootloader_config.plymouth,
config.bootloader_config.os_prober,
)
if config.network_config:

View File

@ -2,7 +2,7 @@ Key,Value(s),Description,Required
additional-repositories,[ `multilib <https://wiki.archlinux.org/title/Official_repositories#multilib>`_!, `testing <https://wiki.archlinux.org/title/Official_repositories#Testing_repositories>`_ ],Enables one or more of the testing and multilib repositories before proceeding with installation,No
archinstall-language,`lang <https://github.com/archlinux/archinstall/blob/master/archinstall/locales/languages.json>`__,Sets the TUI language used *(make sure to use the ``lang`` value not the ``abbr``)*,No
audio_config,`pipewire <https://wiki.archlinux.org/title/PipeWire>`_!, `pulseaudio <https://wiki.archlinux.org/title/PulseAudio>`_,Audioserver to be installed,No
bootloader_config,"{ bootloader: `Systemd-boot <https://wiki.archlinux.org/title/Systemd-boot>`_!, `grub <https://wiki.archlinux.org/title/GRUB>`_!, `limine <https://wiki.archlinux.org/title/Limine>`_!, uki: ``true``/``false``!, removable: ``true``/``false`` }","Bootloader configuration. ``bootloader`` selects which bootloader to install *(grub/limine mandatory on BIOS)*. ``uki`` enables unified kernel images *(UEFI only!, systemd-boot/limine only)*. ``removable`` installs to default removable media path /EFI/BOOT/ instead of NVRAM *(UEFI only!, grub/limine only)*",Yes
bootloader_config,"{ bootloader: `Systemd-boot <https://wiki.archlinux.org/title/Systemd-boot>`_!, `grub <https://wiki.archlinux.org/title/GRUB>`_!, `limine <https://wiki.archlinux.org/title/Limine>`_!, uki: ``true``/``false``!, removable: ``true``/``false``!, os_prober: ``true``/``false`` }","Bootloader configuration. ``bootloader`` selects which bootloader to install *(grub/limine mandatory on BIOS)*. ``uki`` enables unified kernel images *(UEFI only!, systemd-boot/limine only)*. ``removable`` installs to default removable media path /EFI/BOOT/ instead of NVRAM *(UEFI only!, grub/limine only)*. ``os_prober`` installs os-prober so GRUB can detect other operating systems such as Windows *(grub only)*",Yes
debug,``true``!, ``false``,Enables debug output,No
disk_config,*Read more under* :ref:`disk config`,Contains the desired disk setup to be used during installation,No
disk_encryption,*Read more about under* :ref:`disk encryption`,Parameters for disk encryption applied on top of ``disk_config``,No

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -69,7 +69,8 @@ The contents of :code:`https://domain.lan/config.json`:
"bootloader_config": {
"bootloader": "Systemd-boot",
"uki": false,
"removable": false
"removable": false,
"os_prober": false
},
"bootloader": "Systemd-boot",
"debug": false,

View File

@ -6,7 +6,8 @@
"bootloader_config": {
"bootloader": "Systemd-boot",
"uki": false,
"removable": false
"removable": false,
"os_prober": false
},
"debug": false,
"disk_config": {

View File

@ -24,7 +24,8 @@
"bootloader_config": {
"bootloader": "Systemd-boot",
"uki": false,
"removable": false
"removable": false,
"os_prober": true
},
"services": [
"service_1",

View File

@ -233,6 +233,7 @@ def test_config_file_parsing(
bootloader=Bootloader.Systemd,
uki=False,
removable=False,
os_prober=True,
),
hostname='archy',
kernels=['linux-zen'],