Fix 1934 - audio server regression (#1946)
* Audio configuration * Update * Update schema --------- Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com>
This commit is contained in:
parent
d76f4a0296
commit
439bb5428b
|
|
@ -237,6 +237,9 @@ def load_config():
|
||||||
if arguments.get('bootloader', None) is not None:
|
if arguments.get('bootloader', None) is not None:
|
||||||
arguments['bootloader'] = models.Bootloader.from_arg(arguments['bootloader'])
|
arguments['bootloader'] = models.Bootloader.from_arg(arguments['bootloader'])
|
||||||
|
|
||||||
|
if arguments.get('audio_config', None) is not None:
|
||||||
|
arguments['audio_config'] = models.AudioConfiguration.parse_arg(arguments['audio_config'])
|
||||||
|
|
||||||
if arguments.get('disk_encryption', None) is not None and disk_config is not None:
|
if arguments.get('disk_encryption', None) is not None and disk_config is not None:
|
||||||
password = arguments.get('encryption_password', '')
|
password = arguments.get('encryption_password', '')
|
||||||
arguments['disk_encryption'] = disk.DiskEncryption.parse_arg(
|
arguments['disk_encryption'] = disk.DiskEncryption.parse_arg(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, List, Optional, Union, Dict, TYPE_CHECKING
|
from typing import Any, List, Optional, Dict, TYPE_CHECKING
|
||||||
|
|
||||||
from . import disk
|
from . import disk
|
||||||
from .general import secret
|
from .general import secret
|
||||||
|
|
@ -9,6 +9,7 @@ from .menu import Selector, AbstractMenu
|
||||||
from .mirrors import MirrorConfiguration, MirrorMenu
|
from .mirrors import MirrorConfiguration, MirrorMenu
|
||||||
from .models import NetworkConfiguration, NicType
|
from .models import NetworkConfiguration, NicType
|
||||||
from .models.bootloader import Bootloader
|
from .models.bootloader import Bootloader
|
||||||
|
from .models.audio_configuration import Audio, AudioConfiguration
|
||||||
from .models.users import User
|
from .models.users import User
|
||||||
from .output import FormattedOutput
|
from .output import FormattedOutput
|
||||||
from .profile.profile_menu import ProfileConfiguration
|
from .profile.profile_menu import ProfileConfiguration
|
||||||
|
|
@ -109,12 +110,11 @@ class GlobalMenu(AbstractMenu):
|
||||||
display_func=lambda x: x.profile.name if x else '',
|
display_func=lambda x: x.profile.name if x else '',
|
||||||
preview_func=self._prev_profile
|
preview_func=self._prev_profile
|
||||||
)
|
)
|
||||||
self._menu_options['audio'] = \
|
self._menu_options['audio_config'] = \
|
||||||
Selector(
|
Selector(
|
||||||
_('Audio'),
|
_('Audio'),
|
||||||
lambda preset: self._select_audio(preset),
|
lambda preset: self._select_audio(preset),
|
||||||
display_func=lambda x: x if x else '',
|
display_func=lambda x: self._display_audio(x)
|
||||||
default=None
|
|
||||||
)
|
)
|
||||||
self._menu_options['parallel downloads'] = \
|
self._menu_options['parallel downloads'] = \
|
||||||
Selector(
|
Selector(
|
||||||
|
|
@ -421,13 +421,18 @@ class GlobalMenu(AbstractMenu):
|
||||||
profile_config = ProfileMenu(store, preset=current_profile).run()
|
profile_config = ProfileMenu(store, preset=current_profile).run()
|
||||||
return profile_config
|
return profile_config
|
||||||
|
|
||||||
def _select_audio(self, current: Union[str, None]) -> Optional[str]:
|
def _select_audio(
|
||||||
profile_config: Optional[ProfileConfiguration] = self._menu_options['profile_config'].current_selection
|
self,
|
||||||
if profile_config and profile_config.profile:
|
current: Optional[AudioConfiguration] = None
|
||||||
is_desktop = profile_config.profile.is_desktop_profile() if profile_config else False
|
) -> Optional[AudioConfiguration]:
|
||||||
selection = ask_for_audio_selection(is_desktop, current)
|
selection = ask_for_audio_selection(current)
|
||||||
return selection
|
return selection
|
||||||
return None
|
|
||||||
|
def _display_audio(self, current: Optional[AudioConfiguration]) -> str:
|
||||||
|
if not current:
|
||||||
|
return Audio.no_audio_text()
|
||||||
|
else:
|
||||||
|
return current.audio.name
|
||||||
|
|
||||||
def _create_user_account(self, defined_users: List[User]) -> List[User]:
|
def _create_user_account(self, defined_users: List[User]) -> List[User]:
|
||||||
users = ask_for_additional_users(defined_users=defined_users)
|
users = ask_for_additional_users(defined_users=defined_users)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from typing import List, Any, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
from ..locale import list_timezones, list_keyboard_languages
|
from ..locale import list_timezones, list_keyboard_languages
|
||||||
from ..menu import MenuSelectionType, Menu, TextInput
|
from ..menu import MenuSelectionType, Menu, TextInput
|
||||||
|
from ..models.audio_configuration import Audio, AudioConfiguration
|
||||||
from ..output import warn
|
from ..output import warn
|
||||||
from ..packages.packages import validate_package_list
|
from ..packages.packages import validate_package_list
|
||||||
from ..storage import storage
|
from ..storage import storage
|
||||||
|
|
@ -55,16 +56,31 @@ def ask_for_a_timezone(preset: Optional[str] = None) -> Optional[str]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def ask_for_audio_selection(desktop: bool = True, preset: Optional[str] = None) -> Optional[str]:
|
def ask_for_audio_selection(
|
||||||
no_audio = str(_('No audio server'))
|
current: Optional[AudioConfiguration] = None
|
||||||
choices = ['pipewire', 'pulseaudio'] if desktop else ['pipewire', 'pulseaudio', no_audio]
|
) -> Optional[AudioConfiguration]:
|
||||||
default = 'pipewire' if desktop else no_audio
|
choices = [
|
||||||
|
Audio.Pipewire.name,
|
||||||
|
Audio.Pulseaudio.name,
|
||||||
|
Audio.no_audio_text()
|
||||||
|
]
|
||||||
|
|
||||||
choice = Menu(_('Choose an audio server'), choices, preset_values=preset, default_option=default).run()
|
preset = current.audio.name if current else None
|
||||||
|
|
||||||
|
choice = Menu(
|
||||||
|
_('Choose an audio server'),
|
||||||
|
choices,
|
||||||
|
preset_values=preset
|
||||||
|
).run()
|
||||||
|
|
||||||
match choice.type_:
|
match choice.type_:
|
||||||
case MenuSelectionType.Skip: return preset
|
case MenuSelectionType.Skip: return current
|
||||||
case MenuSelectionType.Selection: return choice.single_value
|
case MenuSelectionType.Selection:
|
||||||
|
value = choice.single_value
|
||||||
|
if value == Audio.no_audio_text():
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return AudioConfiguration(Audio[value])
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,4 @@ from .network_configuration import (
|
||||||
from .bootloader import Bootloader
|
from .bootloader import Bootloader
|
||||||
from .gen import VersionDef, PackageSearchResult, PackageSearch, LocalPackage
|
from .gen import VersionDef, PackageSearchResult, PackageSearch, LocalPackage
|
||||||
from .users import PasswordStrength, User
|
from .users import PasswordStrength, User
|
||||||
|
from .audio_configuration import Audio, AudioConfiguration
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any, TYPE_CHECKING, Dict
|
||||||
|
|
||||||
|
from ..hardware import SysInfo
|
||||||
|
from ..output import info
|
||||||
|
from ...default_profiles.applications.pipewire import PipewireProfile
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
_: Any
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Audio(Enum):
|
||||||
|
Pipewire = 'pipewire'
|
||||||
|
Pulseaudio = 'pulseaudio'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def no_audio_text() -> str:
|
||||||
|
return str(_('No audio server'))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AudioConfiguration:
|
||||||
|
audio: Audio
|
||||||
|
|
||||||
|
def __dump__(self) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
'audio': self.audio.value
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_arg(arg: Dict[str, Any]) -> 'AudioConfiguration':
|
||||||
|
return AudioConfiguration(
|
||||||
|
Audio(arg['audio'])
|
||||||
|
)
|
||||||
|
|
||||||
|
def install_audio_config(
|
||||||
|
self,
|
||||||
|
installation: Any
|
||||||
|
):
|
||||||
|
info(f'Installing audio server: {self.audio.name}')
|
||||||
|
|
||||||
|
match self.audio:
|
||||||
|
case Audio.Pipewire:
|
||||||
|
PipewireProfile().install(installation)
|
||||||
|
case Audio.Pulseaudio:
|
||||||
|
installation.add_additional_packages("pulseaudio")
|
||||||
|
|
||||||
|
if SysInfo.requires_sof_fw():
|
||||||
|
installation.add_additional_packages('sof-firmware')
|
||||||
|
|
||||||
|
if SysInfo.requires_alsa_fw():
|
||||||
|
installation.add_additional_packages('alsa-firmware')
|
||||||
|
|
@ -8,11 +8,11 @@ from archinstall import SysInfo
|
||||||
from archinstall.lib import locale
|
from archinstall.lib import locale
|
||||||
from archinstall.lib import disk
|
from archinstall.lib import disk
|
||||||
from archinstall.lib.global_menu import GlobalMenu
|
from archinstall.lib.global_menu import GlobalMenu
|
||||||
from archinstall.default_profiles.applications.pipewire import PipewireProfile
|
|
||||||
from archinstall.lib.configuration import ConfigurationOutput
|
from archinstall.lib.configuration import ConfigurationOutput
|
||||||
from archinstall.lib.installer import Installer
|
from archinstall.lib.installer import Installer
|
||||||
from archinstall.lib.menu import Menu
|
from archinstall.lib.menu import Menu
|
||||||
from archinstall.lib.mirrors import use_mirrors, add_custom_mirrors
|
from archinstall.lib.mirrors import use_mirrors, add_custom_mirrors
|
||||||
|
from archinstall.lib.models import AudioConfiguration
|
||||||
from archinstall.lib.models.bootloader import Bootloader
|
from archinstall.lib.models.bootloader import Bootloader
|
||||||
from archinstall.lib.models.network_configuration import NetworkConfiguration
|
from archinstall.lib.models.network_configuration import NetworkConfiguration
|
||||||
from archinstall.lib.networking import check_mirror_reachable
|
from archinstall.lib.networking import check_mirror_reachable
|
||||||
|
|
@ -70,7 +70,7 @@ def ask_user_questions():
|
||||||
global_menu.enable('profile_config')
|
global_menu.enable('profile_config')
|
||||||
|
|
||||||
# Ask about audio server selection if one is not already set
|
# Ask about audio server selection if one is not already set
|
||||||
global_menu.enable('audio')
|
global_menu.enable('audio_config')
|
||||||
|
|
||||||
# Ask for preferred kernel:
|
# Ask for preferred kernel:
|
||||||
global_menu.enable('kernels', mandatory=True)
|
global_menu.enable('kernels', mandatory=True)
|
||||||
|
|
@ -172,18 +172,9 @@ def perform_installation(mountpoint: Path):
|
||||||
if users := archinstall.arguments.get('!users', None):
|
if users := archinstall.arguments.get('!users', None):
|
||||||
installation.create_users(users)
|
installation.create_users(users)
|
||||||
|
|
||||||
if audio := archinstall.arguments.get('audio', None):
|
audio_config: Optional[AudioConfiguration] = archinstall.arguments.get('audio_config', None)
|
||||||
info(f'Installing audio server: {audio}')
|
if audio_config:
|
||||||
if audio == 'pipewire':
|
audio_config.install_audio_config(installation)
|
||||||
PipewireProfile().install(installation)
|
|
||||||
elif audio == 'pulseaudio':
|
|
||||||
installation.add_additional_packages("pulseaudio")
|
|
||||||
|
|
||||||
if SysInfo.requires_sof_fw():
|
|
||||||
installation.add_additional_packages('sof-firmware')
|
|
||||||
|
|
||||||
if SysInfo.requires_alsa_fw():
|
|
||||||
installation.add_additional_packages('alsa-firmware')
|
|
||||||
else:
|
else:
|
||||||
info("No audio server will be installed")
|
info("No audio server will be installed")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import os
|
import os
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any, Dict
|
from typing import TYPE_CHECKING, Any, Dict, Optional
|
||||||
|
|
||||||
import archinstall
|
import archinstall
|
||||||
from archinstall import SysInfo, info, debug
|
from archinstall import SysInfo, info, debug
|
||||||
|
|
@ -9,13 +9,13 @@ from archinstall.lib import mirrors
|
||||||
from archinstall.lib import models
|
from archinstall.lib import models
|
||||||
from archinstall.lib import disk
|
from archinstall.lib import disk
|
||||||
from archinstall.lib import locale
|
from archinstall.lib import locale
|
||||||
|
from archinstall.lib.models import AudioConfiguration
|
||||||
from archinstall.lib.networking import check_mirror_reachable
|
from archinstall.lib.networking import check_mirror_reachable
|
||||||
from archinstall.lib.profile.profiles_handler import profile_handler
|
from archinstall.lib.profile.profiles_handler import profile_handler
|
||||||
from archinstall.lib import menu
|
from archinstall.lib import menu
|
||||||
from archinstall.lib.global_menu import GlobalMenu
|
from archinstall.lib.global_menu import GlobalMenu
|
||||||
from archinstall.lib.installer import Installer
|
from archinstall.lib.installer import Installer
|
||||||
from archinstall.lib.configuration import ConfigurationOutput
|
from archinstall.lib.configuration import ConfigurationOutput
|
||||||
from archinstall.default_profiles.applications.pipewire import PipewireProfile
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
_: Any
|
_: Any
|
||||||
|
|
@ -95,7 +95,7 @@ class SwissMainMenu(GlobalMenu):
|
||||||
options_list = [
|
options_list = [
|
||||||
'mirror_config', 'disk_config',
|
'mirror_config', 'disk_config',
|
||||||
'disk_encryption', 'swap', 'bootloader', 'hostname', '!root-password',
|
'disk_encryption', 'swap', 'bootloader', 'hostname', '!root-password',
|
||||||
'!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'network_config',
|
'!users', 'profile_config', 'audio_config', 'kernels', 'packages', 'additional-repositories', 'network_config',
|
||||||
'timezone', 'ntp'
|
'timezone', 'ntp'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ class SwissMainMenu(GlobalMenu):
|
||||||
case ExecutionMode.Only_OS:
|
case ExecutionMode.Only_OS:
|
||||||
options_list = [
|
options_list = [
|
||||||
'mirror_config','bootloader', 'hostname',
|
'mirror_config','bootloader', 'hostname',
|
||||||
'!root-password', '!users', 'profile_config', 'audio', 'kernels',
|
'!root-password', '!users', 'profile_config', 'audio_config', 'kernels',
|
||||||
'packages', 'additional-repositories', 'network_config', 'timezone', 'ntp'
|
'packages', 'additional-repositories', 'network_config', 'timezone', 'ntp'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -236,14 +236,11 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode):
|
||||||
if users := archinstall.arguments.get('!users', None):
|
if users := archinstall.arguments.get('!users', None):
|
||||||
installation.create_users(users)
|
installation.create_users(users)
|
||||||
|
|
||||||
if audio := archinstall.arguments.get('audio', None):
|
audio_config: Optional[AudioConfiguration] = archinstall.arguments.get('audio_config', None)
|
||||||
info(f'Installing audio server: {audio}')
|
if audio_config:
|
||||||
if audio == 'pipewire':
|
audio_config.install_audio_config(installation)
|
||||||
PipewireProfile().install(installation)
|
|
||||||
elif audio == 'pulseaudio':
|
|
||||||
installation.add_additional_packages("pulseaudio")
|
|
||||||
else:
|
else:
|
||||||
info("No audio server will be installed.")
|
info("No audio server will be installed")
|
||||||
|
|
||||||
if profile_config := archinstall.arguments.get('profile_config', None):
|
if profile_config := archinstall.arguments.get('profile_config', None):
|
||||||
profile_handler.install_profile_config(installation, profile_config)
|
profile_handler.install_profile_config(installation, profile_config)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ There are three different configuration files, all of which are optional.
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
{
|
{
|
||||||
"audio": "pipewire",
|
"audio_config": {"audio": "pipewire"},
|
||||||
"bootloader": "systemd-bootctl",
|
"bootloader": "systemd-bootctl",
|
||||||
"custom-commands": [
|
"custom-commands": [
|
||||||
"cd /home/devel; git clone https://aur.archlinux.org/paru.git",
|
"cd /home/devel; git clone https://aur.archlinux.org/paru.git",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"config_version": "2.5.2",
|
"config_version": "2.5.2",
|
||||||
"additional-repositories": [],
|
"additional-repositories": [],
|
||||||
"archinstall-language": "English",
|
"archinstall-language": "English",
|
||||||
"audio": "pipewire",
|
"audio_config": {"audio": "pipewire"},
|
||||||
"bootloader": "Systemd-boot",
|
"bootloader": "Systemd-boot",
|
||||||
"debug": false,
|
"debug": false,
|
||||||
"disk_config": {
|
"disk_config": {
|
||||||
|
|
@ -99,19 +99,13 @@
|
||||||
"http://archlinux.mirror.digitalpacific.com.au/$repo/os/$arch": true,
|
"http://archlinux.mirror.digitalpacific.com.au/$repo/os/$arch": true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"network_config": {
|
"nic": {
|
||||||
"nics": [
|
"dhcp": true,
|
||||||
{
|
"dns": null,
|
||||||
"dhcp": false,
|
"gateway": null,
|
||||||
"dns": [
|
"iface": null,
|
||||||
"3.3.3.3"
|
"ip": null,
|
||||||
],
|
"type": "nm"
|
||||||
"gateway": "2.2.2.2",
|
|
||||||
"iface": "enp0s31f6",
|
|
||||||
"ip": "1.1.1.1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"type": "manual"
|
|
||||||
},
|
},
|
||||||
"no_pkg_lookups": false,
|
"no_pkg_lookups": false,
|
||||||
"ntp": true,
|
"ntp": true,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"dry_run": true,
|
"dry_run": true,
|
||||||
"audio": "none",
|
|
||||||
"bootloader": "systemd-bootctl",
|
"bootloader": "systemd-bootctl",
|
||||||
"debug": false,
|
"debug": false,
|
||||||
"harddrives": [
|
"harddrives": [
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, Optional
|
||||||
|
|
||||||
import archinstall
|
import archinstall
|
||||||
from archinstall import Installer
|
from archinstall import Installer
|
||||||
from archinstall import profile
|
from archinstall import profile
|
||||||
from archinstall import SysInfo
|
from archinstall import SysInfo
|
||||||
from archinstall import mirrors
|
from archinstall import mirrors
|
||||||
from archinstall.default_profiles.applications.pipewire import PipewireProfile
|
|
||||||
from archinstall import disk
|
from archinstall import disk
|
||||||
from archinstall import menu
|
from archinstall import menu
|
||||||
from archinstall import models
|
from archinstall import models
|
||||||
|
|
@ -49,7 +48,7 @@ def ask_user_questions():
|
||||||
global_menu.enable('profile_config')
|
global_menu.enable('profile_config')
|
||||||
|
|
||||||
# Ask about audio server selection if one is not already set
|
# Ask about audio server selection if one is not already set
|
||||||
global_menu.enable('audio')
|
global_menu.enable('audio_config')
|
||||||
|
|
||||||
# Ask for preferred kernel:
|
# Ask for preferred kernel:
|
||||||
global_menu.enable('kernels', mandatory=True)
|
global_menu.enable('kernels', mandatory=True)
|
||||||
|
|
@ -151,20 +150,11 @@ def perform_installation(mountpoint: Path):
|
||||||
if users := archinstall.arguments.get('!users', None):
|
if users := archinstall.arguments.get('!users', None):
|
||||||
installation.create_users(users)
|
installation.create_users(users)
|
||||||
|
|
||||||
if audio := archinstall.arguments.get('audio', None):
|
audio_config: Optional[models.AudioConfiguration] = archinstall.arguments.get('audio_config', None)
|
||||||
info(f'Installing audio server: {audio}')
|
if audio_config:
|
||||||
if audio == 'pipewire':
|
audio_config.install_audio_config(installation)
|
||||||
PipewireProfile().install(installation)
|
|
||||||
elif audio == 'pulseaudio':
|
|
||||||
installation.add_additional_packages("pulseaudio")
|
|
||||||
|
|
||||||
if SysInfo.requires_sof_fw():
|
|
||||||
installation.add_additional_packages('sof-firmware')
|
|
||||||
|
|
||||||
if SysInfo.requires_alsa_fw():
|
|
||||||
installation.add_additional_packages('alsa-firmware')
|
|
||||||
else:
|
else:
|
||||||
info("No audio server will be installed.")
|
info("No audio server will be installed")
|
||||||
|
|
||||||
if profile_config := archinstall.arguments.get('profile_config', None):
|
if profile_config := archinstall.arguments.get('profile_config', None):
|
||||||
profile.profile_handler.install_profile_config(installation, profile_config)
|
profile.profile_handler.install_profile_config(installation, profile_config)
|
||||||
|
|
|
||||||
19
schema.json
19
schema.json
|
|
@ -12,14 +12,19 @@
|
||||||
"testing"
|
"testing"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"audio": {
|
"audio_config": {
|
||||||
"description": "Audio server to be installed",
|
"description": "Audio server to be installed",
|
||||||
"type": "string",
|
"type": "object",
|
||||||
"enum": [
|
"properties": {
|
||||||
"pipewire",
|
"audio": {
|
||||||
"pulseaudio",
|
"description": "Audio server to be installed",
|
||||||
"none"
|
"type": "string",
|
||||||
]
|
"enum": [
|
||||||
|
"pipewire",
|
||||||
|
"pulseaudio"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"bootloader": {
|
"bootloader": {
|
||||||
"description": "Bootloader to be installed",
|
"description": "Bootloader to be installed",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue