forked from Mirror/pmbootstrap
dtbtool-exynos has two options --platform and --subtype that are embedded in dt.img header and need to match the values that the bootloader expects. For most devices these values are 0x50a6 and 0x217584da, respectively, but for some they have other values. Add functionality to parse the dt.img header and extract these values, and add them to the deviceinfo as bootimg_qcdt_exynos_{platform,subtype} if they are not equal to the default values. Part-of: https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/merge_requests/2638
296 lines
7.3 KiB
Python
296 lines
7.3 KiB
Python
# Copyright 2024 Caleb Connolly
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import enum
|
|
import subprocess
|
|
from argparse import Namespace
|
|
from pathlib import Path
|
|
from typing import Any, Literal, TypedDict
|
|
|
|
from pmb.core.arch import Arch
|
|
from pmb.core.chroot import Chroot
|
|
|
|
|
|
class CrossCompile(enum.Enum):
|
|
# Cross compilation isn't needed for this package:
|
|
# 1) Either because the arch we will build for is exactly the same as the
|
|
# native arch, or
|
|
# 2) because CPU emulation is not needed (e.g. x86 on x86_64)
|
|
UNNECESSARY = "unnecessary"
|
|
# Cross compilation disabled, only use QEMU
|
|
QEMU_ONLY = "qemu-only"
|
|
# Cross compilation will use crossdirect
|
|
CROSSDIRECT = "crossdirect"
|
|
# Cross compilation will use cross-native
|
|
CROSS_NATIVE = "cross-native"
|
|
# Cross compilation will use cross-native2
|
|
CROSS_NATIVE2 = "cross-native2"
|
|
|
|
def __str__(self) -> str:
|
|
return self.value
|
|
|
|
def enabled(self) -> bool:
|
|
"""Are we cross-compiling for this value of cross?"""
|
|
return self not in [CrossCompile.UNNECESSARY, CrossCompile.QEMU_ONLY]
|
|
|
|
def host_chroot(self, arch: Arch) -> Chroot:
|
|
"""Chroot for the package target architecture (the "host" machine).
|
|
Cross native (v1) is the exception, since we exclusively use the native
|
|
chroot for that."""
|
|
if arch == Arch.native():
|
|
return Chroot.native()
|
|
|
|
match self:
|
|
case CrossCompile.CROSS_NATIVE:
|
|
return Chroot.native()
|
|
case _:
|
|
return Chroot.buildroot(arch)
|
|
|
|
def build_chroot(self, arch: Arch) -> Chroot:
|
|
"""Chroot for the package build architecture (the "build" machine)."""
|
|
if arch == Arch.native():
|
|
return Chroot.native()
|
|
|
|
match self:
|
|
case CrossCompile.UNNECESSARY | CrossCompile.CROSSDIRECT | CrossCompile.QEMU_ONLY:
|
|
return Chroot.buildroot(arch)
|
|
case CrossCompile.CROSS_NATIVE | CrossCompile.CROSS_NATIVE2:
|
|
return Chroot.native()
|
|
|
|
|
|
class RunOutputTypeDefault(enum.Enum):
|
|
LOG = enum.auto()
|
|
STDOUT = enum.auto()
|
|
INTERACTIVE = enum.auto()
|
|
TUI = enum.auto()
|
|
NULL = enum.auto()
|
|
|
|
def is_to_stdout(self) -> bool:
|
|
match self:
|
|
case self.STDOUT | self.INTERACTIVE:
|
|
return True
|
|
case self.LOG | self.TUI | self.NULL:
|
|
return False
|
|
case _:
|
|
raise AssertionError
|
|
|
|
def has_timeout(self) -> bool:
|
|
match self:
|
|
case self.LOG | self.STDOUT:
|
|
return True
|
|
case self.INTERACTIVE | self.TUI | self.NULL:
|
|
return False
|
|
case _:
|
|
raise AssertionError
|
|
|
|
def has_pass_stdin(self) -> bool:
|
|
match self:
|
|
case self.INTERACTIVE | self.TUI:
|
|
return True
|
|
case self.LOG | self.STDOUT | self.NULL:
|
|
return False
|
|
case _:
|
|
raise AssertionError
|
|
|
|
|
|
class RunOutputTypePopen(enum.Enum):
|
|
BACKGROUND = enum.auto()
|
|
PIPE = enum.auto()
|
|
|
|
def is_to_stdout(self) -> bool:
|
|
return False
|
|
|
|
def has_timeout(self) -> bool:
|
|
return False
|
|
|
|
def has_pass_stdin(self) -> bool:
|
|
return False
|
|
|
|
|
|
RunOutputType = RunOutputTypeDefault | RunOutputTypePopen
|
|
RunReturnType = str | int | subprocess.Popen
|
|
PathString = Path | str
|
|
Env = dict[str, PathString]
|
|
Apkbuild = dict[str, Any]
|
|
WithExtraRepos = Literal["default", "enabled", "disabled"]
|
|
|
|
# These types are not definitive / API, they exist to describe the current
|
|
# state of things so that we can improve our type hinting coverage and make
|
|
# future refactoring efforts easier.
|
|
|
|
|
|
class PartitionLayout(TypedDict):
|
|
kernel: int | None
|
|
boot: int
|
|
reserve: int | None
|
|
root: int
|
|
|
|
|
|
class AportGenEntry(TypedDict):
|
|
prefixes: list[str]
|
|
confirm_overwrite: bool
|
|
|
|
|
|
class Bootimg(TypedDict):
|
|
cmdline: str
|
|
bootimg_qcdt: str
|
|
bootimg_qcdt_type: str | None
|
|
bootimg_qcdt_exynos_platform: str | None
|
|
bootimg_qcdt_exynos_subtype: str | None
|
|
dtb_offset: str | None
|
|
dtb_second: str
|
|
base: str
|
|
kernel_offset: str
|
|
ramdisk_offset: str
|
|
second_offset: str
|
|
tags_offset: str
|
|
pagesize: str
|
|
header_version: str | None
|
|
mtk_label_kernel: str
|
|
mtk_label_ramdisk: str
|
|
|
|
|
|
# Property list generated with:
|
|
# $ rg --vimgrep "((^|\s)args\.\w+)" --only-matching | cut -d"." -f3 | sort | uniq
|
|
class PmbArgs(Namespace):
|
|
action_flasher: str
|
|
action_initfs: str
|
|
action_kconfig: str
|
|
action_netboot: str
|
|
action_test: str
|
|
add: str
|
|
all: bool
|
|
all_git: bool
|
|
all_stable: bool
|
|
android_recovery_zip: bool
|
|
apkindex_path: Path
|
|
aports: list[Path] | None
|
|
arch: Arch | None
|
|
as_root: bool
|
|
assume_yes: bool
|
|
auto: bool
|
|
autoinstall: bool
|
|
boot_size: str
|
|
build_default_device_arch: str
|
|
buildroot: str
|
|
built: bool
|
|
ccache: bool
|
|
ccache_size: str
|
|
chroot_usb: bool
|
|
cipher: str
|
|
clear_log: bool
|
|
cmdline: str
|
|
command: str
|
|
config: Path
|
|
cross: bool
|
|
details: bool
|
|
details_to_stdout: bool
|
|
deviceinfo_parse_kernel: str
|
|
devices: str
|
|
disk: Path
|
|
dry: bool
|
|
efi: bool
|
|
envkernel: bool
|
|
export_folder: Path
|
|
extra_space: str
|
|
fast: bool
|
|
file: str
|
|
filesystem: str
|
|
flash_method: str
|
|
folder: str
|
|
force: bool
|
|
fork_alpine: bool
|
|
fork_alpine_retain_branch: bool
|
|
full_disk_encryption: bool
|
|
go_mod_cache: bool
|
|
hook: str
|
|
host: str
|
|
host_qemu: bool
|
|
http: bool
|
|
ignore_depends: bool
|
|
image_size: str
|
|
image: bool
|
|
install_base: bool
|
|
install_blockdev: bool
|
|
install_cgpt: bool
|
|
install_key: bool
|
|
install_local_pkgs: bool
|
|
install_recommends: bool
|
|
is_default_channel: str
|
|
iter_time: str
|
|
jobs: str
|
|
kconfig_check_details: bool
|
|
kernel: str
|
|
keymap: str
|
|
keep_going: bool
|
|
lines: int
|
|
log: Path
|
|
mirror_alpine: str
|
|
mirror_postmarketos: str
|
|
name: str
|
|
nconfig: bool
|
|
netboot: bool
|
|
no_depends: bool
|
|
no_fde: bool
|
|
no_firewall: bool
|
|
no_image: bool
|
|
no_reboot: bool
|
|
no_sshd: bool
|
|
non_existing: str
|
|
odin_flashable_tar: bool
|
|
offline: bool
|
|
on_device_installer: bool
|
|
ondev_cp: list[tuple[str, str]]
|
|
ondev_no_rootfs: bool
|
|
output: RunOutputType
|
|
overview: bool
|
|
# FIXME (#2324): figure out the args.package vs args.packages situation
|
|
package: str | list[str]
|
|
packages: list[str]
|
|
partition: str
|
|
password: str
|
|
path: Path
|
|
pkgname: str
|
|
pkgname_pkgver_srcurl: str
|
|
pkgs_local: bool
|
|
pkgs_local_mismatch: bool
|
|
pkgs_online_mismatch: bool
|
|
port: str
|
|
qemu_audio: str
|
|
qemu_cpu: str
|
|
qemu_display: str
|
|
qemu_gl: bool
|
|
qemu_kvm: bool
|
|
qemu_redir_stdio: str
|
|
qemu_tablet: bool
|
|
qemu_video: str
|
|
recovery_flash_kernel: bool
|
|
recovery_install_partition: str
|
|
ref: str
|
|
replace: bool
|
|
repository: str
|
|
reset: bool
|
|
resume: bool
|
|
rootfs: bool
|
|
rsync: bool
|
|
scripts: str
|
|
second_storage: str
|
|
sector_size: int | None
|
|
selected_providers: dict[str, str]
|
|
sparse: bool
|
|
split: bool
|
|
src: str
|
|
ssh_keys: str
|
|
strict: bool
|
|
sudo_timer: bool
|
|
suffix: str
|
|
systemd: str
|
|
timeout: float
|
|
user: str
|
|
value: str
|
|
verbose: bool
|
|
verify: bool
|
|
work: Path
|
|
xauth: bool
|
|
xconfig: bool
|
|
zap: bool
|