forked from Mirror/pmbootstrap
parse: deviceinfo: make Deviceinfo a class (MR 2252)
Introduce a Deviceinfo class and use it rather than the dictionary. This gives us sweet sweet autocomplete, and lays the foundation for having a proper deviceinfo validator in the future. Additionally, continue refactoring out args... Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
parent
b51d31acab
commit
97bd8b96ec
27 changed files with 372 additions and 288 deletions
|
@ -1,16 +1,16 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.types import PmbArgs
|
from pmb.parse.deviceinfo import Deviceinfo
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.aportgen.core
|
import pmb.aportgen.core
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
|
|
||||||
|
|
||||||
def generate_apkbuild(pkgname, deviceinfo, patches):
|
def generate_apkbuild(pkgname, deviceinfo: Deviceinfo, patches):
|
||||||
device = "-".join(pkgname.split("-")[1:])
|
device = "-".join(pkgname.split("-")[1:])
|
||||||
carch = pmb.parse.arch.alpine_to_kernel(deviceinfo["arch"])
|
carch = pmb.parse.arch.alpine_to_kernel(deviceinfo.arch)
|
||||||
|
|
||||||
makedepends = ["bash", "bc", "bison", "devicepkg-dev", "findutils", "flex",
|
makedepends = ["bash", "bc", "bison", "devicepkg-dev", "findutils", "flex",
|
||||||
"openssl-dev", "perl"]
|
"openssl-dev", "perl"]
|
||||||
|
@ -24,13 +24,13 @@ def generate_apkbuild(pkgname, deviceinfo, patches):
|
||||||
downstreamkernel_package "$builddir" "$pkgdir" "$_carch\" \\
|
downstreamkernel_package "$builddir" "$pkgdir" "$_carch\" \\
|
||||||
"$_flavor" "$_outdir\""""
|
"$_flavor" "$_outdir\""""
|
||||||
|
|
||||||
if deviceinfo.get("header_version") == "2":
|
if deviceinfo.header_version == "2":
|
||||||
package += """
|
package += """
|
||||||
|
|
||||||
make dtbs_install O="$_outdir" ARCH="$_carch" \\
|
make dtbs_install O="$_outdir" ARCH="$_carch" \\
|
||||||
INSTALL_DTBS_PATH="$pkgdir\"/boot/dtbs"""
|
INSTALL_DTBS_PATH="$pkgdir\"/boot/dtbs"""
|
||||||
|
|
||||||
if deviceinfo["bootimg_qcdt"] == "true":
|
if deviceinfo.bootimg_qcdt == "true":
|
||||||
build += """\n
|
build += """\n
|
||||||
# Master DTB (deviceinfo_bootimg_qcdt)"""
|
# Master DTB (deviceinfo_bootimg_qcdt)"""
|
||||||
vendors = ["spreadtrum", "exynos", "other"]
|
vendors = ["spreadtrum", "exynos", "other"]
|
||||||
|
@ -68,8 +68,8 @@ def generate_apkbuild(pkgname, deviceinfo, patches):
|
||||||
pkgname={pkgname}
|
pkgname={pkgname}
|
||||||
pkgver=3.x.x
|
pkgver=3.x.x
|
||||||
pkgrel=0
|
pkgrel=0
|
||||||
pkgdesc="{deviceinfo["name"]} kernel fork"
|
pkgdesc="{deviceinfo.name} kernel fork"
|
||||||
arch="{deviceinfo["arch"]}"
|
arch="{deviceinfo.arch}"
|
||||||
_carch="{carch}"
|
_carch="{carch}"
|
||||||
_flavor="{device}"
|
_flavor="{device}"
|
||||||
url="https://kernel.org"
|
url="https://kernel.org"
|
||||||
|
|
|
@ -13,7 +13,7 @@ from pmb.core import Chroot, ChrootType, get_context
|
||||||
|
|
||||||
|
|
||||||
# FIXME (#2324): type hint Arch
|
# FIXME (#2324): type hint Arch
|
||||||
def arch_from_deviceinfo(args: PmbArgs, pkgname, aport: Path) -> Optional[str]:
|
def arch_from_deviceinfo(pkgname, aport: Path) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
The device- packages are noarch packages. But it only makes sense to build
|
The device- packages are noarch packages. But it only makes sense to build
|
||||||
them for the device's architecture, which is specified in the deviceinfo
|
them for the device's architecture, which is specified in the deviceinfo
|
||||||
|
@ -31,12 +31,12 @@ def arch_from_deviceinfo(args: PmbArgs, pkgname, aport: Path) -> Optional[str]:
|
||||||
|
|
||||||
# Return its arch
|
# Return its arch
|
||||||
device = pkgname.split("-", 1)[1]
|
device = pkgname.split("-", 1)[1]
|
||||||
arch = pmb.parse.deviceinfo(device)["arch"]
|
arch = pmb.parse.deviceinfo(device).arch
|
||||||
logging.verbose(pkgname + ": arch from deviceinfo: " + arch)
|
logging.verbose(pkgname + ": arch from deviceinfo: " + arch)
|
||||||
return arch
|
return arch
|
||||||
|
|
||||||
|
|
||||||
def arch(args: PmbArgs, pkgname: str):
|
def arch(pkgname: str):
|
||||||
"""
|
"""
|
||||||
Find a good default in case the user did not specify for which architecture
|
Find a good default in case the user did not specify for which architecture
|
||||||
a package should be built.
|
a package should be built.
|
||||||
|
@ -50,7 +50,7 @@ def arch(args: PmbArgs, pkgname: str):
|
||||||
aport = pmb.helpers.pmaports.find(pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
if not aport:
|
if not aport:
|
||||||
raise FileNotFoundError(f"APKBUILD not found for {pkgname}")
|
raise FileNotFoundError(f"APKBUILD not found for {pkgname}")
|
||||||
ret = arch_from_deviceinfo(args, pkgname, aport)
|
ret = arch_from_deviceinfo(pkgname, aport)
|
||||||
if ret:
|
if ret:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -59,11 +59,11 @@ def arch(args: PmbArgs, pkgname: str):
|
||||||
deviceinfo = pmb.parse.deviceinfo()
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
|
|
||||||
if get_context().config.build_default_device_arch:
|
if get_context().config.build_default_device_arch:
|
||||||
preferred_arch = deviceinfo["arch"]
|
preferred_arch = deviceinfo.arch
|
||||||
preferred_arch_2nd = pmb.config.arch_native
|
preferred_arch_2nd = pmb.config.arch_native
|
||||||
else:
|
else:
|
||||||
preferred_arch = pmb.config.arch_native
|
preferred_arch = pmb.config.arch_native
|
||||||
preferred_arch_2nd = deviceinfo["arch"]
|
preferred_arch_2nd = deviceinfo.arch
|
||||||
|
|
||||||
if "noarch" in arches or "all" in arches or preferred_arch in arches:
|
if "noarch" in arches or "all" in arches or preferred_arch in arches:
|
||||||
return preferred_arch
|
return preferred_arch
|
||||||
|
|
|
@ -190,7 +190,7 @@ def package_kernel(args: PmbArgs):
|
||||||
modify_apkbuild(pkgname, aport)
|
modify_apkbuild(pkgname, aport)
|
||||||
apkbuild_path = context.config.work / "aportgen/APKBUILD"
|
apkbuild_path = context.config.work / "aportgen/APKBUILD"
|
||||||
|
|
||||||
arch = pmb.parse.deviceinfo()["arch"]
|
arch = pmb.parse.deviceinfo().arch
|
||||||
apkbuild = pmb.parse.apkbuild(apkbuild_path, check_pkgname=False)
|
apkbuild = pmb.parse.apkbuild(apkbuild_path, check_pkgname=False)
|
||||||
if apkbuild["_outdir"]:
|
if apkbuild["_outdir"]:
|
||||||
kbuild_out = apkbuild["_outdir"]
|
kbuild_out = apkbuild["_outdir"]
|
||||||
|
|
|
@ -58,7 +58,7 @@ def shutdown_cryptsetup_device(name: str):
|
||||||
raise RuntimeError("Failed to parse 'cryptsetup status' output!")
|
raise RuntimeError("Failed to parse 'cryptsetup status' output!")
|
||||||
|
|
||||||
|
|
||||||
def shutdown(args: PmbArgs, only_install_related=False):
|
def shutdown(only_install_related=False):
|
||||||
# Stop daemons
|
# Stop daemons
|
||||||
kill_adb()
|
kill_adb()
|
||||||
kill_sccache()
|
kill_sccache()
|
||||||
|
|
|
@ -4,17 +4,18 @@ import glob
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import pmb.build.other
|
||||||
|
import pmb.config.workdir
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
import pmb.config.workdir
|
import pmb.config.workdir
|
||||||
from pmb.types import PmbArgs
|
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot, get_context
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
def zap(confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
pkgs_local_mismatch=False, pkgs_online_mismatch=False, distfiles=False,
|
pkgs_local_mismatch=False, pkgs_online_mismatch=False, distfiles=False,
|
||||||
rust=False, netboot=False):
|
rust=False, netboot=False):
|
||||||
"""
|
"""
|
||||||
|
@ -38,13 +39,13 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
# Delete packages with a different version compared to aports,
|
# Delete packages with a different version compared to aports,
|
||||||
# then re-index
|
# then re-index
|
||||||
if pkgs_local_mismatch:
|
if pkgs_local_mismatch:
|
||||||
zap_pkgs_local_mismatch(args, confirm, dry)
|
zap_pkgs_local_mismatch(confirm, dry)
|
||||||
|
|
||||||
# Delete outdated binary packages
|
# Delete outdated binary packages
|
||||||
if pkgs_online_mismatch:
|
if pkgs_online_mismatch:
|
||||||
zap_pkgs_online_mismatch(args, confirm, dry)
|
zap_pkgs_online_mismatch(confirm, dry)
|
||||||
|
|
||||||
pmb.chroot.shutdown(args)
|
pmb.chroot.shutdown()
|
||||||
|
|
||||||
# Deletion patterns for folders inside get_context().config.work
|
# Deletion patterns for folders inside get_context().config.work
|
||||||
patterns = list(Chroot.iter_patterns())
|
patterns = list(Chroot.iter_patterns())
|
||||||
|
@ -72,7 +73,7 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
pmb.helpers.run.root(["rm", "-rf", match])
|
pmb.helpers.run.root(["rm", "-rf", match])
|
||||||
|
|
||||||
# Remove config init dates for deleted chroots
|
# Remove config init dates for deleted chroots
|
||||||
pmb.config.workdir.clean(args)
|
pmb.config.workdir.clean()
|
||||||
|
|
||||||
# Chroots were zapped, so no repo lists exist anymore
|
# Chroots were zapped, so no repo lists exist anymore
|
||||||
pmb.helpers.other.cache["apk_repository_list_updated"].clear()
|
pmb.helpers.other.cache["apk_repository_list_updated"].clear()
|
||||||
|
@ -82,7 +83,7 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
logging.info("Dry run: nothing has been deleted")
|
logging.info("Dry run: nothing has been deleted")
|
||||||
|
|
||||||
|
|
||||||
def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
def zap_pkgs_local_mismatch(confirm=True, dry=False):
|
||||||
channel = pmb.config.pmaports.read_config()["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
if not os.path.exists(f"{get_context().config.work}/packages/{channel}"):
|
if not os.path.exists(f"{get_context().config.work}/packages/{channel}"):
|
||||||
return
|
return
|
||||||
|
@ -131,10 +132,10 @@ def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
reindex = True
|
reindex = True
|
||||||
|
|
||||||
if reindex:
|
if reindex:
|
||||||
pmb.build.other.index_repo(args)
|
pmb.build.other.index_repo()
|
||||||
|
|
||||||
|
|
||||||
def zap_pkgs_online_mismatch(args: PmbArgs, confirm=True, dry=False):
|
def zap_pkgs_online_mismatch(confirm=True, dry=False):
|
||||||
# Check whether we need to do anything
|
# Check whether we need to do anything
|
||||||
paths = glob.glob(f"{get_context().config.work}/cache_apk_*")
|
paths = glob.glob(f"{get_context().config.work}/cache_apk_*")
|
||||||
if not len(paths):
|
if not len(paths):
|
||||||
|
|
|
@ -745,6 +745,6 @@ def frontend(args: PmbArgs):
|
||||||
setattr(args, "deviceinfo", info)
|
setattr(args, "deviceinfo", info)
|
||||||
|
|
||||||
# Do not zap any existing packages or cache_http directories
|
# Do not zap any existing packages or cache_http directories
|
||||||
pmb.chroot.zap(args, confirm=False)
|
pmb.chroot.zap(confirm=False)
|
||||||
|
|
||||||
logging.info("DONE!")
|
logging.info("DONE!")
|
||||||
|
|
|
@ -90,7 +90,7 @@ def chroot_check_channel(chroot: Chroot):
|
||||||
f" '{channel}' channel now. {msg_again}")
|
f" '{channel}' channel now. {msg_again}")
|
||||||
|
|
||||||
|
|
||||||
def clean(args: PmbArgs):
|
def clean():
|
||||||
"""Remove obsolete data data from workdir.cfg.
|
"""Remove obsolete data data from workdir.cfg.
|
||||||
|
|
||||||
:returns: None if workdir does not exist,
|
:returns: None if workdir does not exist,
|
||||||
|
|
|
@ -33,4 +33,4 @@ def frontend(args: PmbArgs): # FIXME: ARGS_REFACTOR
|
||||||
logging.info(f"Export symlinks to: {target}")
|
logging.info(f"Export symlinks to: {target}")
|
||||||
if args.odin_flashable_tar:
|
if args.odin_flashable_tar:
|
||||||
pmb.export.odin(context, flavor, target)
|
pmb.export.odin(context, flavor, target)
|
||||||
pmb.export.symlinks(args, flavor, target)
|
pmb.export.symlinks(flavor, target)
|
||||||
|
|
|
@ -18,7 +18,7 @@ def odin(context: Context, flavor, folder: Path):
|
||||||
for devices configured with the flasher method 'heimdall-isorec'
|
for devices configured with the flasher method 'heimdall-isorec'
|
||||||
and with boot.img for devices with 'heimdall-bootimg'
|
and with boot.img for devices with 'heimdall-bootimg'
|
||||||
"""
|
"""
|
||||||
pmb.flasher.init(context.device)
|
pmb.flasher.init(context.device, "heimdall-isorec")
|
||||||
suffix = Chroot(ChrootType.ROOTFS, context.device)
|
suffix = Chroot(ChrootType.ROOTFS, context.device)
|
||||||
deviceinfo = pmb.parse.deviceinfo(context.device)
|
deviceinfo = pmb.parse.deviceinfo(context.device)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ def odin(context: Context, flavor, folder: Path):
|
||||||
suffix_flavor = ""
|
suffix_flavor = ""
|
||||||
|
|
||||||
# Validate method
|
# Validate method
|
||||||
method = deviceinfo["flash_method"]
|
method = deviceinfo.flash_method or ""
|
||||||
if not method.startswith("heimdall-"):
|
if not method.startswith("heimdall-"):
|
||||||
raise RuntimeError("An odin flashable tar is not supported"
|
raise RuntimeError("An odin flashable tar is not supported"
|
||||||
f" for the flash method '{method}' specified"
|
f" for the flash method '{method}' specified"
|
||||||
|
@ -37,8 +37,8 @@ def odin(context: Context, flavor, folder: Path):
|
||||||
" Only 'heimdall' methods are supported.")
|
" Only 'heimdall' methods are supported.")
|
||||||
|
|
||||||
# Partitions
|
# Partitions
|
||||||
partition_kernel = deviceinfo["flash_heimdall_partition_kernel"] or "KERNEL"
|
partition_kernel = deviceinfo.flash_heimdall_partition_kernel or "KERNEL"
|
||||||
partition_initfs = deviceinfo["flash_heimdall_partition_initfs"] or "RECOVERY"
|
partition_initfs = deviceinfo.flash_heimdall_partition_initfs or "RECOVERY"
|
||||||
|
|
||||||
# Temporary folder
|
# Temporary folder
|
||||||
temp_folder = "/tmp/odin-flashable-tar"
|
temp_folder = "/tmp/odin-flashable-tar"
|
||||||
|
|
|
@ -9,19 +9,18 @@ import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.types import PmbArgs
|
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def symlinks(args: PmbArgs, flavor, folder: Path):
|
def symlinks(flavor, folder: Path):
|
||||||
"""
|
"""
|
||||||
Create convenience symlinks to the rootfs and boot files.
|
Create convenience symlinks to the rootfs and boot files.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
context = get_context()
|
context = get_context()
|
||||||
arch = pmb.parse.deviceinfo(context.device)["arch"]
|
arch = pmb.parse.deviceinfo(context.device).arch
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
suffix = f"-{flavor}"
|
suffix = f"-{flavor}"
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from typing import Dict
|
|
||||||
from pmb.core.context import get_context
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
|
from pmb.parse.deviceinfo import Deviceinfo
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.install
|
import pmb.install
|
||||||
|
@ -17,11 +17,11 @@ import pmb.parse.kconfig
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def kernel(device: str, deviceinfo: Dict[str, str], boot: bool = False, autoinstall: bool = False):
|
def kernel(deviceinfo: Deviceinfo, method: str, boot: bool = False, autoinstall: bool = False):
|
||||||
# Rebuild the initramfs, just to make sure (see #69)
|
# Rebuild the initramfs, just to make sure (see #69)
|
||||||
flavor = pmb.helpers.frontend._parse_flavor(device, autoinstall)
|
flavor = pmb.helpers.frontend._parse_flavor(deviceinfo.codename, autoinstall)
|
||||||
if autoinstall:
|
if autoinstall:
|
||||||
pmb.chroot.initfs.build(flavor, Chroot(ChrootType.ROOTFS, device))
|
pmb.chroot.initfs.build(flavor, Chroot(ChrootType.ROOTFS, deviceinfo.codename))
|
||||||
|
|
||||||
# Check kernel config
|
# Check kernel config
|
||||||
pmb.parse.kconfig.check(flavor, must_exist=False)
|
pmb.parse.kconfig.check(flavor, must_exist=False)
|
||||||
|
@ -29,10 +29,10 @@ def kernel(device: str, deviceinfo: Dict[str, str], boot: bool = False, autoinst
|
||||||
# Generate the paths and run the flasher
|
# Generate the paths and run the flasher
|
||||||
if boot:
|
if boot:
|
||||||
logging.info("(native) boot " + flavor + " kernel")
|
logging.info("(native) boot " + flavor + " kernel")
|
||||||
pmb.flasher.run(device, deviceinfo, "boot", flavor)
|
pmb.flasher.run(deviceinfo, method, "boot", flavor)
|
||||||
else:
|
else:
|
||||||
logging.info("(native) flash kernel " + flavor)
|
logging.info("(native) flash kernel " + flavor)
|
||||||
pmb.flasher.run(device, deviceinfo, "flash_kernel", flavor)
|
pmb.flasher.run(deviceinfo, method, "flash_kernel", flavor)
|
||||||
logging.info("You will get an IP automatically assigned to your "
|
logging.info("You will get an IP automatically assigned to your "
|
||||||
"USB interface shortly.")
|
"USB interface shortly.")
|
||||||
logging.info("Then you can connect to your device using ssh after pmOS has"
|
logging.info("Then you can connect to your device using ssh after pmOS has"
|
||||||
|
@ -49,61 +49,61 @@ def list_flavors(device: str):
|
||||||
logging.info("* " + pmb.chroot.other.kernel_flavor_installed(chroot))
|
logging.info("* " + pmb.chroot.other.kernel_flavor_installed(chroot))
|
||||||
|
|
||||||
|
|
||||||
def rootfs(device: str, deviceinfo: Dict[str, str], method: str):
|
def rootfs(deviceinfo: Deviceinfo, method: str):
|
||||||
# Generate rootfs, install flasher
|
# Generate rootfs, install flasher
|
||||||
suffix = ".img"
|
suffix = ".img"
|
||||||
if pmb.config.flashers.get(method, {}).get("split", False):
|
if pmb.config.flashers.get(method, {}).get("split", False):
|
||||||
suffix = "-root.img"
|
suffix = "-root.img"
|
||||||
|
|
||||||
img_path = Chroot.native() / "home/pmos/rootfs" / f"{device}{suffix}"
|
img_path = Chroot.native() / "home/pmos/rootfs" / f"{deviceinfo.codename}{suffix}"
|
||||||
if not img_path.exists():
|
if not img_path.exists():
|
||||||
raise RuntimeError("The rootfs has not been generated yet, please run"
|
raise RuntimeError("The rootfs has not been generated yet, please run"
|
||||||
" 'pmbootstrap install' first.")
|
" 'pmbootstrap install' first.")
|
||||||
|
|
||||||
# Do not flash if using fastboot & image is too large
|
# Do not flash if using fastboot & image is too large
|
||||||
if method.startswith("fastboot") \
|
if method.startswith("fastboot") \
|
||||||
and deviceinfo["flash_fastboot_max_size"]:
|
and deviceinfo.flash_fastboot_max_size:
|
||||||
img_size = img_path.stat().st_size / 1024**2
|
img_size = img_path.stat().st_size / 1024**2
|
||||||
max_size = int(deviceinfo["flash_fastboot_max_size"])
|
max_size = int(deviceinfo.flash_fastboot_max_size)
|
||||||
if img_size > max_size:
|
if img_size > max_size:
|
||||||
raise RuntimeError("The rootfs is too large for fastboot to"
|
raise RuntimeError("The rootfs is too large for fastboot to"
|
||||||
" flash.")
|
" flash.")
|
||||||
|
|
||||||
# Run the flasher
|
# Run the flasher
|
||||||
logging.info("(native) flash rootfs image")
|
logging.info("(native) flash rootfs image")
|
||||||
pmb.flasher.run(device, deviceinfo, "flash_rootfs")
|
pmb.flasher.run(deviceinfo, method, "flash_rootfs")
|
||||||
|
|
||||||
|
|
||||||
def list_devices(device, deviceinfo):
|
def list_devices(deviceinfo: Deviceinfo, method: str):
|
||||||
pmb.flasher.run(device, deviceinfo, "list_devices")
|
pmb.flasher.run(deviceinfo, method, "list_devices")
|
||||||
|
|
||||||
|
|
||||||
def sideload(device: str, deviceinfo: Dict[str, str]):
|
def sideload(deviceinfo: Deviceinfo, method: str):
|
||||||
# Install depends
|
# Install depends
|
||||||
pmb.flasher.install_depends()
|
pmb.flasher.install_depends(method)
|
||||||
|
|
||||||
# Mount the buildroot
|
# Mount the buildroot
|
||||||
chroot = Chroot.buildroot(deviceinfo["arch"])
|
chroot = Chroot.buildroot(deviceinfo.arch)
|
||||||
mountpoint = "/mnt/" / chroot
|
mountpoint = "/mnt/" / chroot
|
||||||
pmb.helpers.mount.bind(chroot.path,
|
pmb.helpers.mount.bind(chroot.path,
|
||||||
Chroot.native().path / mountpoint)
|
Chroot.native().path / mountpoint)
|
||||||
|
|
||||||
# Missing recovery zip error
|
# Missing recovery zip error
|
||||||
if not (Chroot.native() / mountpoint / "/var/lib/postmarketos-android-recovery-installer"
|
if not (Chroot.native() / mountpoint / "/var/lib/postmarketos-android-recovery-installer"
|
||||||
/ f"pmos-{device}.zip").exists():
|
/ f"pmos-{deviceinfo.codename}.zip").exists():
|
||||||
raise RuntimeError("The recovery zip has not been generated yet,"
|
raise RuntimeError("The recovery zip has not been generated yet,"
|
||||||
" please run 'pmbootstrap install' with the"
|
" please run 'pmbootstrap install' with the"
|
||||||
" '--android-recovery-zip' parameter first!")
|
" '--android-recovery-zip' parameter first!")
|
||||||
|
|
||||||
pmb.flasher.run(device, deviceinfo, "sideload")
|
pmb.flasher.run(deviceinfo, method, "sideload")
|
||||||
|
|
||||||
|
|
||||||
def flash_lk2nd(device: str, deviceinfo: Dict[str, str], method: str):
|
def flash_lk2nd(deviceinfo: Deviceinfo, method: str):
|
||||||
if method == "fastboot":
|
if method == "fastboot":
|
||||||
# In the future this could be expanded to use "fastboot flash lk2nd $img"
|
# In the future this could be expanded to use "fastboot flash lk2nd $img"
|
||||||
# which reflashes/updates lk2nd from itself. For now let the user handle this
|
# which reflashes/updates lk2nd from itself. For now let the user handle this
|
||||||
# manually since supporting the codepath with heimdall requires more effort.
|
# manually since supporting the codepath with heimdall requires more effort.
|
||||||
pmb.flasher.init(device)
|
pmb.flasher.init(deviceinfo.codename, method)
|
||||||
logging.info("(native) checking current fastboot product")
|
logging.info("(native) checking current fastboot product")
|
||||||
output = pmb.chroot.root(["fastboot", "getvar", "product"],
|
output = pmb.chroot.root(["fastboot", "getvar", "product"],
|
||||||
output="interactive", output_return=True)
|
output="interactive", output_return=True)
|
||||||
|
@ -114,7 +114,7 @@ def flash_lk2nd(device: str, deviceinfo: Dict[str, str], method: str):
|
||||||
" bootloader mode to re-flash lk2nd.")
|
" bootloader mode to re-flash lk2nd.")
|
||||||
|
|
||||||
# Get the lk2nd package (which is a dependency of the device package)
|
# Get the lk2nd package (which is a dependency of the device package)
|
||||||
device_pkg = f"device-{device}"
|
device_pkg = f"device-{deviceinfo.codename}"
|
||||||
apkbuild = pmb.helpers.pmaports.get(device_pkg)
|
apkbuild = pmb.helpers.pmaports.get(device_pkg)
|
||||||
lk2nd_pkg = None
|
lk2nd_pkg = None
|
||||||
for dep in apkbuild["depends"]:
|
for dep in apkbuild["depends"]:
|
||||||
|
@ -125,11 +125,11 @@ def flash_lk2nd(device: str, deviceinfo: Dict[str, str], method: str):
|
||||||
if not lk2nd_pkg:
|
if not lk2nd_pkg:
|
||||||
raise RuntimeError(f"{device_pkg} does not depend on any lk2nd package")
|
raise RuntimeError(f"{device_pkg} does not depend on any lk2nd package")
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, device)
|
suffix = Chroot(ChrootType.ROOTFS, deviceinfo.codename)
|
||||||
pmb.chroot.apk.install([lk2nd_pkg], suffix)
|
pmb.chroot.apk.install([lk2nd_pkg], suffix)
|
||||||
|
|
||||||
logging.info("(native) flash lk2nd image")
|
logging.info("(native) flash lk2nd image")
|
||||||
pmb.flasher.run(device, deviceinfo, "flash_lk2nd")
|
pmb.flasher.run(deviceinfo, method, "flash_lk2nd")
|
||||||
|
|
||||||
|
|
||||||
def frontend(args: PmbArgs):
|
def frontend(args: PmbArgs):
|
||||||
|
@ -137,7 +137,7 @@ def frontend(args: PmbArgs):
|
||||||
action = args.action_flasher
|
action = args.action_flasher
|
||||||
device = context.device
|
device = context.device
|
||||||
deviceinfo = pmb.parse.deviceinfo()
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
method = args.flash_method or deviceinfo["flash_method"]
|
method = args.flash_method or deviceinfo.flash_method or "none"
|
||||||
|
|
||||||
if method == "none" and action in ["boot", "flash_kernel", "flash_rootfs",
|
if method == "none" and action in ["boot", "flash_kernel", "flash_rootfs",
|
||||||
"flash_lk2nd"]:
|
"flash_lk2nd"]:
|
||||||
|
@ -145,20 +145,20 @@ def frontend(args: PmbArgs):
|
||||||
return
|
return
|
||||||
|
|
||||||
if action in ["boot", "flash_kernel"]:
|
if action in ["boot", "flash_kernel"]:
|
||||||
kernel(device, deviceinfo)
|
kernel(deviceinfo, method)
|
||||||
elif action == "flash_rootfs":
|
elif action == "flash_rootfs":
|
||||||
rootfs(device, deviceinfo, method)
|
rootfs(deviceinfo, method)
|
||||||
elif action == "flash_vbmeta":
|
elif action == "flash_vbmeta":
|
||||||
logging.info("(native) flash vbmeta.img with verity disabled flag")
|
logging.info("(native) flash vbmeta.img with verity disabled flag")
|
||||||
pmb.flasher.run(device, deviceinfo, "flash_vbmeta")
|
pmb.flasher.run(deviceinfo, method, "flash_vbmeta")
|
||||||
elif action == "flash_dtbo":
|
elif action == "flash_dtbo":
|
||||||
logging.info("(native) flash dtbo image")
|
logging.info("(native) flash dtbo image")
|
||||||
pmb.flasher.run(device, deviceinfo, "flash_dtbo")
|
pmb.flasher.run(deviceinfo, method, "flash_dtbo")
|
||||||
elif action == "flash_lk2nd":
|
elif action == "flash_lk2nd":
|
||||||
flash_lk2nd(device, deviceinfo, method)
|
flash_lk2nd(deviceinfo, method)
|
||||||
elif action == "list_flavors":
|
elif action == "list_flavors":
|
||||||
list_flavors(device)
|
list_flavors(device)
|
||||||
elif action == "list_devices":
|
elif action == "list_devices":
|
||||||
list_devices(device, deviceinfo)
|
pmb.flasher.run(deviceinfo, method, "list_devices")
|
||||||
elif action == "sideload":
|
elif action == "sideload":
|
||||||
sideload(device, deviceinfo)
|
sideload(deviceinfo, method)
|
||||||
|
|
|
@ -10,14 +10,7 @@ from pmb.helpers.mount import mount_device_rootfs
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def install_depends() -> None:
|
def install_depends(method: str) -> None:
|
||||||
args: PmbArgs = pmb.helpers.args.please_i_really_need_args()
|
|
||||||
if hasattr(args, 'flash_method'):
|
|
||||||
method = args.flash_method
|
|
||||||
|
|
||||||
if not method:
|
|
||||||
method = pmb.parse.deviceinfo()["flash_method"]
|
|
||||||
|
|
||||||
if method not in pmb.config.flashers:
|
if method not in pmb.config.flashers:
|
||||||
raise RuntimeError(f"Flash method {method} is not supported by the"
|
raise RuntimeError(f"Flash method {method} is not supported by the"
|
||||||
" current configuration. However, adding a new"
|
" current configuration. However, adding a new"
|
||||||
|
@ -46,8 +39,8 @@ def install_depends() -> None:
|
||||||
pmb.chroot.apk.install(depends, Chroot.native())
|
pmb.chroot.apk.install(depends, Chroot.native())
|
||||||
|
|
||||||
|
|
||||||
def init(device: str):
|
def init(device: str, method: str):
|
||||||
install_depends()
|
install_depends(method)
|
||||||
|
|
||||||
# Mount folders from host system
|
# Mount folders from host system
|
||||||
for folder in pmb.config.flash_mount_bind:
|
for folder in pmb.config.flash_mount_bind:
|
||||||
|
|
|
@ -1,31 +1,28 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from pmb.parse.deviceinfo import Deviceinfo
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
import pmb.helpers.args
|
import pmb.helpers.args
|
||||||
|
|
||||||
|
|
||||||
def check_partition_blacklist(args: PmbArgs, deviceinfo: Dict[str, str], key, value):
|
def check_partition_blacklist(deviceinfo: Deviceinfo, key, value):
|
||||||
if not key.startswith("$PARTITION_"):
|
if not key.startswith("$PARTITION_"):
|
||||||
return
|
return
|
||||||
|
|
||||||
name = deviceinfo["name"]
|
name = deviceinfo.name
|
||||||
if value in deviceinfo["partition_blacklist"].split(","):
|
if value in (deviceinfo.partition_blacklist or "").split(","):
|
||||||
raise RuntimeError("'" + value + "'" + " partition is blacklisted " +
|
raise RuntimeError("'" + value + "'" + " partition is blacklisted " +
|
||||||
"from being flashed! See the " + name + " device " +
|
"from being flashed! See the " + name + " device " +
|
||||||
"wiki page for more information.")
|
"wiki page for more information.")
|
||||||
|
|
||||||
|
|
||||||
def run(device: str, deviceinfo: Dict[str, str], action, flavor=None):
|
def run(deviceinfo: Deviceinfo, method: str, action: str, flavor=None):
|
||||||
pmb.flasher.init(device)
|
pmb.flasher.init(deviceinfo.codename, method)
|
||||||
|
|
||||||
# FIXME: handle argparsing and pass in only the args we need.
|
|
||||||
args = pmb.helpers.args.please_i_really_need_args()
|
|
||||||
|
|
||||||
# Verify action
|
# Verify action
|
||||||
method = args.flash_method or deviceinfo["flash_method"]
|
|
||||||
cfg = pmb.config.flashers[method]
|
cfg = pmb.config.flashers[method]
|
||||||
if not isinstance(cfg["actions"], dict):
|
if not isinstance(cfg["actions"], dict):
|
||||||
raise TypeError(f"Flashers misconfigured! {method} key 'actions' should be a dictionary")
|
raise TypeError(f"Flashers misconfigured! {method} key 'actions' should be a dictionary")
|
||||||
|
@ -38,6 +35,8 @@ def run(device: str, deviceinfo: Dict[str, str], action, flavor=None):
|
||||||
"Deviceinfo_flash_methods>")
|
"Deviceinfo_flash_methods>")
|
||||||
|
|
||||||
# Variable setup
|
# Variable setup
|
||||||
|
# FIXME: handle argparsing and pass in only the args we need.
|
||||||
|
args = pmb.helpers.args.please_i_really_need_args()
|
||||||
fvars = pmb.flasher.variables(args, flavor, method)
|
fvars = pmb.flasher.variables(args, flavor, method)
|
||||||
|
|
||||||
# vbmeta flasher requires vbmeta partition to be explicitly specified
|
# vbmeta flasher requires vbmeta partition to be explicitly specified
|
||||||
|
@ -79,7 +78,7 @@ def run(device: str, deviceinfo: Dict[str, str], action, flavor=None):
|
||||||
" but the value for this variable"
|
" but the value for this variable"
|
||||||
" is None! Is that missing in your"
|
" is None! Is that missing in your"
|
||||||
" deviceinfo?")
|
" deviceinfo?")
|
||||||
check_partition_blacklist(args, deviceinfo, key, value)
|
check_partition_blacklist(deviceinfo, key, value)
|
||||||
command[i] = command[i].replace(key, value)
|
command[i] = command[i].replace(key, value)
|
||||||
|
|
||||||
# Remove empty strings
|
# Remove empty strings
|
||||||
|
|
|
@ -9,11 +9,11 @@ from pmb.types import PmbArgs
|
||||||
def variables(args: PmbArgs, flavor, method):
|
def variables(args: PmbArgs, flavor, method):
|
||||||
device = get_context().config.device
|
device = get_context().config.device
|
||||||
deviceinfo = pmb.parse.deviceinfo()
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
_cmdline = deviceinfo["kernel_cmdline"] or ""
|
_cmdline = deviceinfo.kernel_cmdline or ""
|
||||||
if "cmdline" in args and args.cmdline:
|
if "cmdline" in args and args.cmdline:
|
||||||
_cmdline = args.cmdline
|
_cmdline = args.cmdline
|
||||||
|
|
||||||
flash_pagesize = deviceinfo['flash_pagesize']
|
flash_pagesize = deviceinfo.flash_pagesize
|
||||||
|
|
||||||
# TODO Remove _partition_system deviceinfo support once pmaports has been
|
# TODO Remove _partition_system deviceinfo support once pmaports has been
|
||||||
# updated and minimum pmbootstrap version bumped.
|
# updated and minimum pmbootstrap version bumped.
|
||||||
|
@ -23,39 +23,39 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
_partition_rootfs: Optional[str]
|
_partition_rootfs: Optional[str]
|
||||||
|
|
||||||
if method.startswith("fastboot"):
|
if method.startswith("fastboot"):
|
||||||
_partition_kernel = deviceinfo["flash_fastboot_partition_kernel"]\
|
_partition_kernel = deviceinfo.flash_fastboot_partition_kernel\
|
||||||
or "boot"
|
or "boot"
|
||||||
_partition_rootfs = deviceinfo["flash_fastboot_partition_rootfs"]\
|
_partition_rootfs = deviceinfo.flash_fastboot_partition_rootfs\
|
||||||
or deviceinfo["flash_fastboot_partition_system"] or "userdata"
|
or deviceinfo.flash_fastboot_partition_system or "userdata"
|
||||||
_partition_vbmeta = deviceinfo["flash_fastboot_partition_vbmeta"]\
|
_partition_vbmeta = deviceinfo.flash_fastboot_partition_vbmeta\
|
||||||
or None
|
or None
|
||||||
_partition_dtbo = deviceinfo["flash_fastboot_partition_dtbo"]\
|
_partition_dtbo = deviceinfo.flash_fastboot_partition_dtbo\
|
||||||
or None
|
or None
|
||||||
# Require that the partitions are specified in deviceinfo for now
|
# Require that the partitions are specified in deviceinfo for now
|
||||||
elif method.startswith("rkdeveloptool"):
|
elif method.startswith("rkdeveloptool"):
|
||||||
_partition_kernel = deviceinfo["flash_rk_partition_kernel"]\
|
_partition_kernel = deviceinfo.flash_rk_partition_kernel\
|
||||||
or None
|
or None
|
||||||
_partition_rootfs = deviceinfo["flash_rk_partition_rootfs"]\
|
_partition_rootfs = deviceinfo.flash_rk_partition_rootfs\
|
||||||
or deviceinfo["flash_rk_partition_system"] or None
|
or deviceinfo.flash_rk_partition_system or None
|
||||||
_partition_vbmeta = None
|
_partition_vbmeta = None
|
||||||
_partition_dtbo = None
|
_partition_dtbo = None
|
||||||
elif method.startswith("mtkclient"):
|
elif method.startswith("mtkclient"):
|
||||||
_partition_kernel = deviceinfo["flash_mtkclient_partition_kernel"]\
|
_partition_kernel = deviceinfo.flash_mtkclient_partition_kernel\
|
||||||
or "boot"
|
or "boot"
|
||||||
_partition_rootfs = deviceinfo["flash_mtkclient_partition_rootfs"]\
|
_partition_rootfs = deviceinfo.flash_mtkclient_partition_rootfs\
|
||||||
or "userdata"
|
or "userdata"
|
||||||
_partition_vbmeta = deviceinfo["flash_mtkclient_partition_vbmeta"]\
|
_partition_vbmeta = deviceinfo.flash_mtkclient_partition_vbmeta\
|
||||||
or None
|
or None
|
||||||
_partition_dtbo = deviceinfo["flash_mtkclient_partition_dtbo"]\
|
_partition_dtbo = deviceinfo.flash_mtkclient_partition_dtbo\
|
||||||
or None
|
or None
|
||||||
else:
|
else:
|
||||||
_partition_kernel = deviceinfo["flash_heimdall_partition_kernel"]\
|
_partition_kernel = deviceinfo.flash_heimdall_partition_kernel\
|
||||||
or "KERNEL"
|
or "KERNEL"
|
||||||
_partition_rootfs = deviceinfo["flash_heimdall_partition_rootfs"]\
|
_partition_rootfs = deviceinfo.flash_heimdall_partition_rootfs\
|
||||||
or deviceinfo["flash_heimdall_partition_system"] or "SYSTEM"
|
or deviceinfo.flash_heimdall_partition_system or "SYSTEM"
|
||||||
_partition_vbmeta = deviceinfo["flash_heimdall_partition_vbmeta"]\
|
_partition_vbmeta = deviceinfo.flash_heimdall_partition_vbmeta\
|
||||||
or None
|
or None
|
||||||
_partition_dtbo = deviceinfo["flash_heimdall_partition_dtbo"]\
|
_partition_dtbo = deviceinfo.flash_heimdall_partition_dtbo\
|
||||||
or None
|
or None
|
||||||
|
|
||||||
if "partition" in args and args.partition:
|
if "partition" in args and args.partition:
|
||||||
|
@ -67,7 +67,7 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
_partition_dtbo = args.partition
|
_partition_dtbo = args.partition
|
||||||
|
|
||||||
_dtb = ""
|
_dtb = ""
|
||||||
if deviceinfo["append_dtb"] == "true":
|
if deviceinfo.append_dtb == "true":
|
||||||
_dtb = "-dtb"
|
_dtb = "-dtb"
|
||||||
|
|
||||||
_no_reboot = ""
|
_no_reboot = ""
|
||||||
|
@ -86,16 +86,15 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
"$IMAGE": "/home/pmos/rootfs/" + device + ".img",
|
"$IMAGE": "/home/pmos/rootfs/" + device + ".img",
|
||||||
"$KERNEL_CMDLINE": _cmdline,
|
"$KERNEL_CMDLINE": _cmdline,
|
||||||
"$PARTITION_KERNEL": _partition_kernel,
|
"$PARTITION_KERNEL": _partition_kernel,
|
||||||
"$PARTITION_INITFS": deviceinfo[
|
"$PARTITION_INITFS": deviceinfo.flash_heimdall_partition_initfs or "RECOVERY",
|
||||||
"flash_heimdall_partition_initfs"] or "RECOVERY",
|
|
||||||
"$PARTITION_ROOTFS": _partition_rootfs,
|
"$PARTITION_ROOTFS": _partition_rootfs,
|
||||||
"$PARTITION_VBMETA": _partition_vbmeta,
|
"$PARTITION_VBMETA": _partition_vbmeta,
|
||||||
"$PARTITION_DTBO": _partition_dtbo,
|
"$PARTITION_DTBO": _partition_dtbo,
|
||||||
"$FLASH_PAGESIZE": flash_pagesize,
|
"$FLASH_PAGESIZE": flash_pagesize,
|
||||||
"$RECOVERY_ZIP": "/mnt/buildroot_" + deviceinfo["arch"] +
|
"$RECOVERY_ZIP": "/mnt/buildroot_" + deviceinfo.arch +
|
||||||
"/var/lib/postmarketos-android-recovery-installer"
|
"/var/lib/postmarketos-android-recovery-installer"
|
||||||
"/pmos-" + device + ".zip",
|
"/pmos-" + device + ".zip",
|
||||||
"$UUU_SCRIPT": "/mnt/rootfs_" + deviceinfo["codename"] +
|
"$UUU_SCRIPT": "/mnt/rootfs_" + deviceinfo.codename +
|
||||||
"/usr/share/uuu/flash_script.lst",
|
"/usr/share/uuu/flash_script.lst",
|
||||||
"$NO_REBOOT": _no_reboot,
|
"$NO_REBOOT": _no_reboot,
|
||||||
"$RESUME": _resume
|
"$RESUME": _resume
|
||||||
|
|
|
@ -99,7 +99,7 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
pmb.config.pmaports.read_config()
|
pmb.config.pmaports.read_config()
|
||||||
pmb.helpers.git.parse_channels_cfg(config.aports)
|
pmb.helpers.git.parse_channels_cfg(config.aports)
|
||||||
deviceinfo = pmb.parse.deviceinfo()
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
context.device_arch = deviceinfo["arch"]
|
context.device_arch = deviceinfo.arch
|
||||||
|
|
||||||
# Remove attributes from args so they don't get used by mistake
|
# Remove attributes from args so they don't get used by mistake
|
||||||
delattr(args, "timeout")
|
delattr(args, "timeout")
|
||||||
|
|
|
@ -65,7 +65,7 @@ def _parse_suffix(args: PmbArgs) -> Chroot:
|
||||||
return Chroot(ChrootType.ROOTFS, get_context().config.device)
|
return Chroot(ChrootType.ROOTFS, get_context().config.device)
|
||||||
elif args.buildroot:
|
elif args.buildroot:
|
||||||
if args.buildroot == "device":
|
if args.buildroot == "device":
|
||||||
return Chroot.buildroot(pmb.parse.deviceinfo()["arch"])
|
return Chroot.buildroot(pmb.parse.deviceinfo().arch)
|
||||||
else:
|
else:
|
||||||
return Chroot.buildroot(args.buildroot)
|
return Chroot.buildroot(args.buildroot)
|
||||||
elif args.suffix:
|
elif args.suffix:
|
||||||
|
@ -118,14 +118,14 @@ def build(args: PmbArgs):
|
||||||
|
|
||||||
# Ensure repo_bootstrap is done for all arches we intend to build for
|
# Ensure repo_bootstrap is done for all arches we intend to build for
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
arch_package = args.arch or pmb.build.autodetect.arch(args, package)
|
arch_package = args.arch or pmb.build.autodetect.arch(package)
|
||||||
pmb.helpers.repo_bootstrap.require_bootstrap(arch_package,
|
pmb.helpers.repo_bootstrap.require_bootstrap(arch_package,
|
||||||
f"build {package} for {arch_package}")
|
f"build {package} for {arch_package}")
|
||||||
|
|
||||||
context = get_context()
|
context = get_context()
|
||||||
# Build all packages
|
# Build all packages
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
arch_package = args.arch or pmb.build.autodetect.arch(args, package)
|
arch_package = args.arch or pmb.build.autodetect.arch(package)
|
||||||
if not pmb.build.package(context, package, arch_package, force,
|
if not pmb.build.package(context, package, arch_package, force,
|
||||||
args.strict, src=src):
|
args.strict, src=src):
|
||||||
logging.info("NOTE: Package '" + package + "' is up to date. Use"
|
logging.info("NOTE: Package '" + package + "' is up to date. Use"
|
||||||
|
@ -215,7 +215,9 @@ def config(args: PmbArgs):
|
||||||
logging.info("NOTE: Valid config keys: " + ", ".join(keys))
|
logging.info("NOTE: Valid config keys: " + ", ".join(keys))
|
||||||
raise RuntimeError("Invalid config key: " + args.name)
|
raise RuntimeError("Invalid config key: " + args.name)
|
||||||
|
|
||||||
config = pmb.config.load(args)
|
# Reload the config because get_context().config has been overwritten
|
||||||
|
# by any rogue cmdline arguments.
|
||||||
|
config = pmb.config.load(args.config)
|
||||||
if args.reset:
|
if args.reset:
|
||||||
if args.name is None:
|
if args.name is None:
|
||||||
raise RuntimeError("config --reset requires a name to be given.")
|
raise RuntimeError("config --reset requires a name to be given.")
|
||||||
|
@ -242,7 +244,7 @@ def config(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def repo_bootstrap(args: PmbArgs):
|
def repo_bootstrap(args: PmbArgs):
|
||||||
pmb.helpers.repo_bootstrap.main(args)
|
pmb.helpers.repo_bootstrap.main(args.arch, args.repository)
|
||||||
|
|
||||||
|
|
||||||
def repo_missing(args: PmbArgs):
|
def repo_missing(args: PmbArgs):
|
||||||
|
@ -272,8 +274,8 @@ def install(args: PmbArgs):
|
||||||
raise ValueError("Installation using rsync"
|
raise ValueError("Installation using rsync"
|
||||||
" is not currently supported on btrfs filesystem.")
|
" is not currently supported on btrfs filesystem.")
|
||||||
|
|
||||||
pmb.helpers.repo_bootstrap.require_bootstrap(deviceinfo["arch"],
|
pmb.helpers.repo_bootstrap.require_bootstrap(deviceinfo.arch,
|
||||||
f"do 'pmbootstrap install' for {deviceinfo['arch']}"
|
f"do 'pmbootstrap install' for {deviceinfo.arch}"
|
||||||
" (deviceinfo_arch)")
|
" (deviceinfo_arch)")
|
||||||
|
|
||||||
# On-device installer checks
|
# On-device installer checks
|
||||||
|
@ -297,7 +299,7 @@ def install(args: PmbArgs):
|
||||||
raise ValueError("--on-device-installer cannot be combined with"
|
raise ValueError("--on-device-installer cannot be combined with"
|
||||||
" --filesystem")
|
" --filesystem")
|
||||||
|
|
||||||
if deviceinfo["cgpt_kpart"]:
|
if deviceinfo.cgpt_kpart:
|
||||||
raise ValueError("--on-device-installer cannot be used with"
|
raise ValueError("--on-device-installer cannot be used with"
|
||||||
" ChromeOS devices")
|
" ChromeOS devices")
|
||||||
else:
|
else:
|
||||||
|
@ -324,7 +326,7 @@ def install(args: PmbArgs):
|
||||||
|
|
||||||
if not args.disk and args.split is None:
|
if not args.disk and args.split is None:
|
||||||
# Default to split if the flash method requires it
|
# Default to split if the flash method requires it
|
||||||
flasher = pmb.config.flashers.get(deviceinfo["flash_method"], {})
|
flasher = pmb.config.flashers.get(deviceinfo.flash_method, {})
|
||||||
if flasher.get("split", False):
|
if flasher.get("split", False):
|
||||||
args.split = True
|
args.split = True
|
||||||
|
|
||||||
|
@ -567,7 +569,7 @@ def work_migrate(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def zap(args: PmbArgs):
|
def zap(args: PmbArgs):
|
||||||
pmb.chroot.zap(args, dry=args.dry, http=args.http,
|
pmb.chroot.zap(dry=args.dry, http=args.http,
|
||||||
distfiles=args.distfiles, pkgs_local=args.pkgs_local,
|
distfiles=args.distfiles, pkgs_local=args.pkgs_local,
|
||||||
pkgs_local_mismatch=args.pkgs_local_mismatch,
|
pkgs_local_mismatch=args.pkgs_local_mismatch,
|
||||||
pkgs_online_mismatch=args.pkgs_online_mismatch,
|
pkgs_online_mismatch=args.pkgs_online_mismatch,
|
||||||
|
|
|
@ -107,7 +107,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
# Zap and update abuild.conf
|
# Zap and update abuild.conf
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(False)
|
||||||
conf = context.config.work / "config_abuild/abuild.conf"
|
conf = context.config.work / "config_abuild/abuild.conf"
|
||||||
if os.path.exists(conf):
|
if os.path.exists(conf):
|
||||||
pmb.helpers.run.root(["sed", "-i",
|
pmb.helpers.run.root(["sed", "-i",
|
||||||
|
@ -145,7 +145,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
# Zap chroots
|
# Zap chroots
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(False)
|
||||||
|
|
||||||
# Update version file
|
# Update version file
|
||||||
migrate_success(context.config.work, 3)
|
migrate_success(context.config.work, 3)
|
||||||
|
@ -186,7 +186,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
# Zap chroots
|
# Zap chroots
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(False)
|
||||||
|
|
||||||
# Move packages to edge subdir
|
# Move packages to edge subdir
|
||||||
edge_path = context.config.work / "packages/edge"
|
edge_path = context.config.work / "packages/edge"
|
||||||
|
@ -224,7 +224,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
|
|
||||||
# Zap chroots to avoid potential "ERROR: Chroot 'native' was created
|
# Zap chroots to avoid potential "ERROR: Chroot 'native' was created
|
||||||
# for the 'stable' channel, but you are on the 'v20.05' channel now."
|
# for the 'stable' channel, but you are on the 'v20.05' channel now."
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(False)
|
||||||
|
|
||||||
# Migrate
|
# Migrate
|
||||||
packages_dir = f"{context.config.work}/packages"
|
packages_dir = f"{context.config.work}/packages"
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
# Copyright 2024 Oliver Smith
|
# Copyright 2024 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from typing import Optional
|
||||||
from pmb.core.chroot import Chroot
|
from pmb.core.chroot import Chroot
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import Config
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,19 +16,15 @@ progress_total = 0
|
||||||
progress_step: str
|
progress_step: str
|
||||||
|
|
||||||
|
|
||||||
def get_arch(args: PmbArgs):
|
def get_arch(config: Config):
|
||||||
if args.arch:
|
if config.build_default_device_arch:
|
||||||
return args.arch
|
return pmb.parse.deviceinfo().arch
|
||||||
|
|
||||||
if args.build_default_device_arch:
|
|
||||||
return pmb.parse.deviceinfo()["arch"]
|
|
||||||
|
|
||||||
return pmb.config.arch_native
|
return pmb.config.arch_native
|
||||||
|
|
||||||
|
|
||||||
def check_repo_arg(args: PmbArgs):
|
def check_repo_arg(repo: str):
|
||||||
cfg = pmb.config.pmaports.read_config_repos()
|
cfg = pmb.config.pmaports.read_config_repos()
|
||||||
repo = args.repository
|
|
||||||
|
|
||||||
if repo in cfg:
|
if repo in cfg:
|
||||||
return
|
return
|
||||||
|
@ -41,9 +38,9 @@ def check_repo_arg(args: PmbArgs):
|
||||||
" current branch")
|
" current branch")
|
||||||
|
|
||||||
|
|
||||||
def check_existing_pkgs(args: PmbArgs, arch):
|
def check_existing_pkgs(config: Config, arch):
|
||||||
channel = pmb.config.pmaports.read_config()["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
path = get_context().config.work / "packages" / channel / arch
|
path = config.work / "packages" / channel / arch
|
||||||
|
|
||||||
if glob.glob(f"{path}/*"):
|
if glob.glob(f"{path}/*"):
|
||||||
logging.info(f"Packages path: {path}")
|
logging.info(f"Packages path: {path}")
|
||||||
|
@ -57,12 +54,12 @@ def check_existing_pkgs(args: PmbArgs, arch):
|
||||||
raise RuntimeError(f"{msg}!")
|
raise RuntimeError(f"{msg}!")
|
||||||
|
|
||||||
|
|
||||||
def get_steps(args: PmbArgs):
|
def get_steps(repo: str):
|
||||||
cfg = pmb.config.pmaports.read_config_repos()
|
cfg = pmb.config.pmaports.read_config_repos()
|
||||||
prev_step = 0
|
prev_step = 0
|
||||||
ret = {}
|
ret = {}
|
||||||
|
|
||||||
for key, packages in cfg[args.repository].items():
|
for key, packages in cfg[repo].items():
|
||||||
if not key.startswith("bootstrap_"):
|
if not key.startswith("bootstrap_"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -76,7 +73,7 @@ def get_steps(args: PmbArgs):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_suffix(args: PmbArgs, arch):
|
def get_suffix(arch):
|
||||||
if pmb.parse.arch.cpu_emulation_required(arch):
|
if pmb.parse.arch.cpu_emulation_required(arch):
|
||||||
return f"buildroot_{arch}"
|
return f"buildroot_{arch}"
|
||||||
return "native"
|
return "native"
|
||||||
|
@ -91,7 +88,7 @@ def get_packages(bootstrap_line):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def set_progress_total(args: PmbArgs, steps, arch):
|
def set_progress_total(steps, arch):
|
||||||
global progress_total
|
global progress_total
|
||||||
|
|
||||||
progress_total = 0
|
progress_total = 0
|
||||||
|
@ -117,14 +114,14 @@ def log_progress(msg):
|
||||||
progress_done += 1
|
progress_done += 1
|
||||||
|
|
||||||
|
|
||||||
def run_steps(args: PmbArgs, steps, arch, chroot: Chroot):
|
def run_steps(steps, arch, chroot: Chroot):
|
||||||
global progress_step
|
global progress_step
|
||||||
|
|
||||||
for step, bootstrap_line in steps.items():
|
for step, bootstrap_line in steps.items():
|
||||||
progress_step = step.replace("bootstrap_", "BOOTSTRAP=")
|
progress_step = step.replace("bootstrap_", "BOOTSTRAP=")
|
||||||
|
|
||||||
log_progress("zapping")
|
log_progress("zapping")
|
||||||
pmb.chroot.zap(args, confirm=False)
|
pmb.chroot.zap(confirm=False)
|
||||||
|
|
||||||
usr_merge = pmb.chroot.UsrMerge.OFF
|
usr_merge = pmb.chroot.UsrMerge.OFF
|
||||||
if "[usr_merge]" in bootstrap_line:
|
if "[usr_merge]" in bootstrap_line:
|
||||||
|
@ -148,17 +145,18 @@ def run_steps(args: PmbArgs, steps, arch, chroot: Chroot):
|
||||||
log_progress("bootstrap complete!")
|
log_progress("bootstrap complete!")
|
||||||
|
|
||||||
|
|
||||||
def main(args: PmbArgs):
|
def main(arch: Optional[str], repository: str): # noqa: F821
|
||||||
check_repo_arg(args)
|
config = get_context().config
|
||||||
|
check_repo_arg(repository)
|
||||||
|
|
||||||
arch = get_arch(args)
|
arch = arch or get_arch(config)
|
||||||
check_existing_pkgs(args, arch)
|
check_existing_pkgs(config, arch)
|
||||||
|
|
||||||
steps = get_steps(args)
|
steps = get_steps(repository)
|
||||||
suffix = get_suffix(args, arch)
|
suffix = get_suffix(arch)
|
||||||
|
|
||||||
set_progress_total(args, steps, arch)
|
set_progress_total(steps, arch)
|
||||||
run_steps(args, steps, arch, suffix)
|
run_steps(steps, arch, suffix)
|
||||||
|
|
||||||
|
|
||||||
def require_bootstrap_error(repo, arch, trigger_str):
|
def require_bootstrap_error(repo, arch, trigger_str):
|
||||||
|
|
|
@ -38,7 +38,7 @@ def print_device(config: Config) -> None:
|
||||||
if pmb.parse._apkbuild.kernels(config.device):
|
if pmb.parse._apkbuild.kernels(config.device):
|
||||||
kernel = f", kernel: {config.kernel}"
|
kernel = f", kernel: {config.kernel}"
|
||||||
|
|
||||||
value = f"{config.device} ({pmb.parse.deviceinfo()['arch']}{kernel})"
|
value = f"{config.device} ({pmb.parse.deviceinfo().arch}{kernel})"
|
||||||
print_status_line("Device", value)
|
print_status_line("Device", value)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import pmb.chroot.other
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
|
from pmb.parse.deviceinfo import Deviceinfo
|
||||||
from pmb.types import Config, PartitionLayout, PmbArgs
|
from pmb.types import Config, PartitionLayout, PmbArgs
|
||||||
import pmb.helpers.devices
|
import pmb.helpers.devices
|
||||||
from pmb.helpers.mount import mount_device_rootfs
|
from pmb.helpers.mount import mount_device_rootfs
|
||||||
|
@ -118,7 +119,7 @@ def copy_files_from_chroot(args: PmbArgs, chroot: Chroot):
|
||||||
mountpoint_outside = Chroot.native() / mountpoint
|
mountpoint_outside = Chroot.native() / mountpoint
|
||||||
|
|
||||||
# Remove empty qemu-user binary stub (where the binary was bind-mounted)
|
# Remove empty qemu-user binary stub (where the binary was bind-mounted)
|
||||||
arch_qemu = pmb.parse.arch.alpine_to_qemu(pmb.parse.deviceinfo()["arch"])
|
arch_qemu = pmb.parse.arch.alpine_to_qemu(pmb.parse.deviceinfo().arch)
|
||||||
qemu_binary = mountpoint_outside / ("/usr/bin/qemu-" + arch_qemu + "-static")
|
qemu_binary = mountpoint_outside / ("/usr/bin/qemu-" + arch_qemu + "-static")
|
||||||
if os.path.exists(qemu_binary):
|
if os.path.exists(qemu_binary):
|
||||||
pmb.helpers.run.root(["rm", qemu_binary])
|
pmb.helpers.run.root(["rm", qemu_binary])
|
||||||
|
@ -185,7 +186,7 @@ def configure_apk(args: PmbArgs):
|
||||||
pmb.helpers.run.root(["cp", key, rootfs / "etc/apk/keys/"])
|
pmb.helpers.run.root(["cp", key, rootfs / "etc/apk/keys/"])
|
||||||
|
|
||||||
# Copy over the corresponding APKINDEX files from cache
|
# Copy over the corresponding APKINDEX files from cache
|
||||||
index_files = pmb.helpers.repo.apkindex_files(arch=pmb.parse.deviceinfo()["arch"],
|
index_files = pmb.helpers.repo.apkindex_files(arch=pmb.parse.deviceinfo().arch,
|
||||||
user_repository=False)
|
user_repository=False)
|
||||||
for f in index_files:
|
for f in index_files:
|
||||||
pmb.helpers.run.root(["cp", f, rootfs / "var/cache/apk/"])
|
pmb.helpers.run.root(["cp", f, rootfs / "var/cache/apk/"])
|
||||||
|
@ -325,11 +326,11 @@ def setup_keymap(config: Config):
|
||||||
Set the keymap with the setup-keymap utility if the device requires it
|
Set the keymap with the setup-keymap utility if the device requires it
|
||||||
"""
|
"""
|
||||||
chroot = Chroot(ChrootType.ROOTFS, config.device)
|
chroot = Chroot(ChrootType.ROOTFS, config.device)
|
||||||
info = pmb.parse.deviceinfo(device=config.device)
|
deviceinfo = pmb.parse.deviceinfo(device=config.device)
|
||||||
if "keymaps" not in info or info["keymaps"].strip() == "":
|
if not deviceinfo.keymaps or deviceinfo.keymaps.strip() == "":
|
||||||
logging.info("NOTE: No valid keymap specified for device")
|
logging.info("NOTE: No valid keymap specified for device")
|
||||||
return
|
return
|
||||||
options = info["keymaps"].split(' ')
|
options = deviceinfo.keymaps.split(' ')
|
||||||
if (config.keymap != "" and
|
if (config.keymap != "" and
|
||||||
config.keymap is not None and
|
config.keymap is not None and
|
||||||
config.keymap in options):
|
config.keymap in options):
|
||||||
|
@ -525,7 +526,7 @@ def generate_binary_list(args: PmbArgs, chroot: Chroot, step):
|
||||||
"""
|
"""
|
||||||
binary_ranges: Dict[int, int] = {}
|
binary_ranges: Dict[int, int] = {}
|
||||||
binary_list = []
|
binary_list = []
|
||||||
binaries = pmb.parse.deviceinfo()["sd_embed_firmware"].split(",")
|
binaries = pmb.parse.deviceinfo().sd_embed_firmware.split(",")
|
||||||
|
|
||||||
for binary_offset in binaries:
|
for binary_offset in binaries:
|
||||||
binary, _offset = binary_offset.split(':')
|
binary, _offset = binary_offset.split(':')
|
||||||
|
@ -541,7 +542,7 @@ def generate_binary_list(args: PmbArgs, chroot: Chroot, step):
|
||||||
f"/usr/share/{binary}")
|
f"/usr/share/{binary}")
|
||||||
# Insure that embedding the firmware will not overrun the
|
# Insure that embedding the firmware will not overrun the
|
||||||
# first partition
|
# first partition
|
||||||
boot_part_start = pmb.parse.deviceinfo()["boot_part_start"] or "2048"
|
boot_part_start = pmb.parse.deviceinfo().boot_part_start or "2048"
|
||||||
max_size = (int(boot_part_start) * 512) - (offset * step)
|
max_size = (int(boot_part_start) * 512) - (offset * step)
|
||||||
binary_size = os.path.getsize(binary_path)
|
binary_size = os.path.getsize(binary_path)
|
||||||
if binary_size > max_size:
|
if binary_size > max_size:
|
||||||
|
@ -574,13 +575,13 @@ def embed_firmware(args: PmbArgs, suffix: Chroot):
|
||||||
:param suffix: of the chroot, which holds the firmware files (either the
|
:param suffix: of the chroot, which holds the firmware files (either the
|
||||||
rootfs_{args.device} or installer_{args.device}
|
rootfs_{args.device} or installer_{args.device}
|
||||||
"""
|
"""
|
||||||
if not pmb.parse.deviceinfo()["sd_embed_firmware"]:
|
if not pmb.parse.deviceinfo().sd_embed_firmware:
|
||||||
return
|
return
|
||||||
|
|
||||||
step = 1024
|
step = 1024
|
||||||
if pmb.parse.deviceinfo()["sd_embed_firmware_step_size"]:
|
if pmb.parse.deviceinfo().sd_embed_firmware_step_size:
|
||||||
try:
|
try:
|
||||||
step = int(pmb.parse.deviceinfo()["sd_embed_firmware_step_size"])
|
step = int(pmb.parse.deviceinfo().sd_embed_firmware_step_size)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise RuntimeError("Value for "
|
raise RuntimeError("Value for "
|
||||||
"deviceinfo_sd_embed_firmware_step_size "
|
"deviceinfo_sd_embed_firmware_step_size "
|
||||||
|
@ -606,7 +607,7 @@ def write_cgpt_kpart(args: PmbArgs, layout, suffix: Chroot):
|
||||||
:param layout: partition layout from get_partition_layout()
|
:param layout: partition layout from get_partition_layout()
|
||||||
:param suffix: of the chroot, which holds the image file to be flashed
|
:param suffix: of the chroot, which holds the image file to be flashed
|
||||||
"""
|
"""
|
||||||
if not pmb.parse.deviceinfo()["cgpt_kpart"] or not args.install_cgpt:
|
if not pmb.parse.deviceinfo().cgpt_kpart or not args.install_cgpt:
|
||||||
return
|
return
|
||||||
|
|
||||||
device_rootfs = mount_device_rootfs(suffix)
|
device_rootfs = mount_device_rootfs(suffix)
|
||||||
|
@ -667,7 +668,7 @@ def sanity_check_disk_size(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def get_ondev_pkgver(args: PmbArgs):
|
def get_ondev_pkgver(args: PmbArgs):
|
||||||
arch = pmb.parse.deviceinfo()["arch"]
|
arch = pmb.parse.deviceinfo().arch
|
||||||
package = pmb.helpers.package.get(args, "postmarketos-ondev", arch)
|
package = pmb.helpers.package.get(args, "postmarketos-ondev", arch)
|
||||||
return package["version"].split("-r")[0]
|
return package["version"].split("-r")[0]
|
||||||
|
|
||||||
|
@ -762,7 +763,7 @@ def create_fstab(args: PmbArgs, layout, chroot: Chroot):
|
||||||
else f"UUID={get_uuid(args, root_dev)}"
|
else f"UUID={get_uuid(args, root_dev)}"
|
||||||
|
|
||||||
boot_options = "nodev,nosuid,noexec"
|
boot_options = "nodev,nosuid,noexec"
|
||||||
boot_filesystem = pmb.parse.deviceinfo()["boot_filesystem"] or "ext2"
|
boot_filesystem = pmb.parse.deviceinfo().boot_filesystem or "ext2"
|
||||||
if boot_filesystem in ("fat16", "fat32"):
|
if boot_filesystem in ("fat16", "fat32"):
|
||||||
boot_filesystem = "vfat"
|
boot_filesystem = "vfat"
|
||||||
boot_options += ",umask=0077,nosymfollow,codepage=437,iocharset=ascii"
|
boot_options += ",umask=0077,nosymfollow,codepage=437,iocharset=ascii"
|
||||||
|
@ -812,15 +813,15 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
device = chroot.name()
|
device = chroot.name()
|
||||||
# Partition and fill image file/disk block device
|
# Partition and fill image file/disk block device
|
||||||
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(True)
|
||||||
(size_boot, size_root) = get_subpartitions_size(chroot)
|
(size_boot, size_root) = get_subpartitions_size(chroot)
|
||||||
layout = get_partition_layout(size_reserve, pmb.parse.deviceinfo()["cgpt_kpart"] \
|
layout = get_partition_layout(size_reserve, pmb.parse.deviceinfo().cgpt_kpart \
|
||||||
and args.install_cgpt)
|
and args.install_cgpt)
|
||||||
if not args.rsync:
|
if not args.rsync:
|
||||||
pmb.install.blockdevice.create(args, size_boot, size_root,
|
pmb.install.blockdevice.create(args, size_boot, size_root,
|
||||||
size_reserve, split, disk)
|
size_reserve, split, disk)
|
||||||
if not split:
|
if not split:
|
||||||
if pmb.parse.deviceinfo()["cgpt_kpart"] and args.install_cgpt:
|
if pmb.parse.deviceinfo().cgpt_kpart and args.install_cgpt:
|
||||||
pmb.install.partition_cgpt(
|
pmb.install.partition_cgpt(
|
||||||
args, layout, size_boot, size_reserve)
|
args, layout, size_boot, size_reserve)
|
||||||
else:
|
else:
|
||||||
|
@ -862,12 +863,12 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
if disk:
|
if disk:
|
||||||
logging.info(f"Unmounting disk {disk} (this may take a while "
|
logging.info(f"Unmounting disk {disk} (this may take a while "
|
||||||
"to sync, please wait)")
|
"to sync, please wait)")
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(True)
|
||||||
|
|
||||||
# Convert rootfs to sparse using img2simg
|
# Convert rootfs to sparse using img2simg
|
||||||
sparse = args.sparse
|
sparse = args.sparse
|
||||||
if sparse is None:
|
if sparse is None:
|
||||||
sparse = pmb.parse.deviceinfo()["flash_sparse"] == "true"
|
sparse = pmb.parse.deviceinfo().flash_sparse == "true"
|
||||||
|
|
||||||
if sparse and not split and not disk:
|
if sparse and not split and not disk:
|
||||||
workdir = Path("/home/pmos/rootfs")
|
workdir = Path("/home/pmos/rootfs")
|
||||||
|
@ -881,7 +882,7 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
|
||||||
# patch sparse image for Samsung devices if specified
|
# patch sparse image for Samsung devices if specified
|
||||||
samsungify_strategy = pmb.parse.deviceinfo()["flash_sparse_samsung_format"]
|
samsungify_strategy = pmb.parse.deviceinfo().flash_sparse_samsung_format
|
||||||
if samsungify_strategy:
|
if samsungify_strategy:
|
||||||
logging.info("(native) convert sparse image into Samsung's sparse image format")
|
logging.info("(native) convert sparse image into Samsung's sparse image format")
|
||||||
pmb.chroot.apk.install(["sm-sparse-image-tool"], Chroot.native())
|
pmb.chroot.apk.install(["sm-sparse-image-tool"], Chroot.native())
|
||||||
|
@ -894,14 +895,14 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
|
||||||
|
|
||||||
def print_flash_info(device: str, deviceinfo: Dict[str, str], split: bool, have_disk: bool):
|
def print_flash_info(device: str, deviceinfo: Deviceinfo, split: bool, have_disk: bool):
|
||||||
""" Print flashing information, based on the deviceinfo data and the
|
""" Print flashing information, based on the deviceinfo data and the
|
||||||
pmbootstrap arguments. """
|
pmbootstrap arguments. """
|
||||||
logging.info("") # make the note stand out
|
logging.info("") # make the note stand out
|
||||||
logging.info("*** FLASHING INFORMATION ***")
|
logging.info("*** FLASHING INFORMATION ***")
|
||||||
|
|
||||||
# System flash information
|
# System flash information
|
||||||
method = deviceinfo["flash_method"]
|
method = deviceinfo.flash_method
|
||||||
flasher = pmb.config.flashers.get(method, {})
|
flasher = pmb.config.flashers.get(method, {})
|
||||||
flasher_actions = flasher.get("actions", {})
|
flasher_actions = flasher.get("actions", {})
|
||||||
if not isinstance(flasher_actions, dict):
|
if not isinstance(flasher_actions, dict):
|
||||||
|
@ -934,16 +935,16 @@ def print_flash_info(device: str, deviceinfo: Dict[str, str], split: bool, have_
|
||||||
# if current flasher supports vbmeta and partition is explicitly specified
|
# if current flasher supports vbmeta and partition is explicitly specified
|
||||||
# in deviceinfo
|
# in deviceinfo
|
||||||
if "flash_vbmeta" in flasher_actions and \
|
if "flash_vbmeta" in flasher_actions and \
|
||||||
(deviceinfo["flash_fastboot_partition_vbmeta"] or
|
(deviceinfo.flash_fastboot_partition_vbmeta or
|
||||||
deviceinfo["flash_heimdall_partition_vbmeta"]):
|
deviceinfo.flash_heimdall_partition_vbmeta):
|
||||||
logging.info("* pmbootstrap flasher flash_vbmeta")
|
logging.info("* pmbootstrap flasher flash_vbmeta")
|
||||||
logging.info(" Flashes vbmeta image with verification disabled flag.")
|
logging.info(" Flashes vbmeta image with verification disabled flag.")
|
||||||
|
|
||||||
# if current flasher supports dtbo and partition is explicitly specified
|
# if current flasher supports dtbo and partition is explicitly specified
|
||||||
# in deviceinfo
|
# in deviceinfo
|
||||||
if "flash_dtbo" in flasher_actions and \
|
if "flash_dtbo" in flasher_actions and \
|
||||||
(deviceinfo["flash_fastboot_partition_dtbo"] or
|
(deviceinfo.flash_fastboot_partition_dtbo or
|
||||||
deviceinfo["flash_heimdall_partition_dtbo"]):
|
deviceinfo.flash_heimdall_partition_dtbo):
|
||||||
logging.info("* pmbootstrap flasher flash_dtbo")
|
logging.info("* pmbootstrap flasher flash_dtbo")
|
||||||
logging.info(" Flashes dtbo image.")
|
logging.info(" Flashes dtbo image.")
|
||||||
|
|
||||||
|
@ -1226,7 +1227,7 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
else:
|
else:
|
||||||
install_packages += ["postmarketos-base-nofde"]
|
install_packages += ["postmarketos-base-nofde"]
|
||||||
|
|
||||||
pmb.helpers.repo.update(pmb.parse.deviceinfo()["arch"])
|
pmb.helpers.repo.update(pmb.parse.deviceinfo().arch)
|
||||||
|
|
||||||
# Install uninstallable "dependencies" by default
|
# Install uninstallable "dependencies" by default
|
||||||
install_packages += get_recommends(args, install_packages)
|
install_packages += get_recommends(args, install_packages)
|
||||||
|
@ -1235,7 +1236,7 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
# dependency, in case the version increased
|
# dependency, in case the version increased
|
||||||
if config.build_pkgs_on_install:
|
if config.build_pkgs_on_install:
|
||||||
for pkgname in install_packages:
|
for pkgname in install_packages:
|
||||||
pmb.build.package(context, pkgname, pmb.parse.deviceinfo()["arch"])
|
pmb.build.package(context, pkgname, pmb.parse.deviceinfo().arch)
|
||||||
|
|
||||||
# Install all packages to device rootfs chroot (and rebuild the initramfs,
|
# Install all packages to device rootfs chroot (and rebuild the initramfs,
|
||||||
# because that doesn't always happen automatically yet, e.g. when the user
|
# because that doesn't always happen automatically yet, e.g. when the user
|
||||||
|
@ -1296,7 +1297,7 @@ def install(args: PmbArgs):
|
||||||
steps = 4
|
steps = 4
|
||||||
|
|
||||||
if args.zap:
|
if args.zap:
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(False)
|
||||||
|
|
||||||
# Install required programs in native chroot
|
# Install required programs in native chroot
|
||||||
step = 1
|
step = 1
|
||||||
|
@ -1313,7 +1314,7 @@ def install(args: PmbArgs):
|
||||||
if args.no_image:
|
if args.no_image:
|
||||||
return
|
return
|
||||||
elif args.android_recovery_zip:
|
elif args.android_recovery_zip:
|
||||||
return install_recovery_zip(args, device, deviceinfo["arch"], steps)
|
return install_recovery_zip(args, device, deviceinfo.arch, steps)
|
||||||
|
|
||||||
if args.on_device_installer:
|
if args.on_device_installer:
|
||||||
# Runs install_system_image twice
|
# Runs install_system_image twice
|
||||||
|
@ -1324,7 +1325,7 @@ def install(args: PmbArgs):
|
||||||
|
|
||||||
print_flash_info(device, deviceinfo, args.split, True if args.disk and args.disk.is_absolute() else False)
|
print_flash_info(device, deviceinfo, args.split, True if args.disk and args.disk.is_absolute() else False)
|
||||||
print_sshd_info(args)
|
print_sshd_info(args)
|
||||||
print_firewall_info(args.no_firewall, deviceinfo["arch"])
|
print_firewall_info(args.no_firewall, deviceinfo.arch)
|
||||||
|
|
||||||
# Leave space before 'chroot still active' note
|
# Leave space before 'chroot still active' note
|
||||||
logging.info("")
|
logging.info("")
|
||||||
|
|
|
@ -23,7 +23,7 @@ def format_and_mount_boot(args: PmbArgs, device, boot_label):
|
||||||
ondev-prepare-internal-storage.sh in postmarketos-ondev.git!
|
ondev-prepare-internal-storage.sh in postmarketos-ondev.git!
|
||||||
"""
|
"""
|
||||||
mountpoint = "/mnt/install/boot"
|
mountpoint = "/mnt/install/boot"
|
||||||
filesystem = pmb.parse.deviceinfo()["boot_filesystem"] or "ext2"
|
filesystem = pmb.parse.deviceinfo().boot_filesystem or "ext2"
|
||||||
install_fsprogs(filesystem)
|
install_fsprogs(filesystem)
|
||||||
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
||||||
f" {mountpoint}")
|
f" {mountpoint}")
|
||||||
|
@ -72,7 +72,7 @@ def format_luks_root(args: PmbArgs, device):
|
||||||
|
|
||||||
|
|
||||||
def get_root_filesystem(args: PmbArgs):
|
def get_root_filesystem(args: PmbArgs):
|
||||||
ret = args.filesystem or pmb.parse.deviceinfo()["root_filesystem"] or "ext4"
|
ret = args.filesystem or pmb.parse.deviceinfo().root_filesystem or "ext4"
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config()
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
|
|
||||||
supported = pmaports_cfg.get("supported_root_filesystems", "ext4")
|
supported = pmaports_cfg.get("supported_root_filesystems", "ext4")
|
||||||
|
|
|
@ -42,7 +42,7 @@ def mount(args: PmbArgs, img_path: Path):
|
||||||
init()
|
init()
|
||||||
|
|
||||||
losetup_cmd: List[PathString] = ["losetup", "-f", img_path]
|
losetup_cmd: List[PathString] = ["losetup", "-f", img_path]
|
||||||
sector_size = pmb.parse.deviceinfo()["rootfs_image_sector_size"]
|
sector_size = pmb.parse.deviceinfo().rootfs_image_sector_size
|
||||||
if sector_size:
|
if sector_size:
|
||||||
losetup_cmd += ["-b", str(int(sector_size))]
|
losetup_cmd += ["-b", str(int(sector_size))]
|
||||||
|
|
||||||
|
|
|
@ -80,15 +80,15 @@ def partition(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
logging.info(f"(native) partition /dev/install (boot: {mb_boot},"
|
logging.info(f"(native) partition /dev/install (boot: {mb_boot},"
|
||||||
f" reserved: {mb_reserved}, root: the rest)")
|
f" reserved: {mb_reserved}, root: the rest)")
|
||||||
|
|
||||||
filesystem = pmb.parse.deviceinfo()["boot_filesystem"] or "ext2"
|
filesystem = pmb.parse.deviceinfo().boot_filesystem or "ext2"
|
||||||
|
|
||||||
# Actual partitioning with 'parted'. Using check=False, because parted
|
# Actual partitioning with 'parted'. Using check=False, because parted
|
||||||
# sometimes "fails to inform the kernel". In case it really failed with
|
# sometimes "fails to inform the kernel". In case it really failed with
|
||||||
# partitioning, the follow-up mounting/formatting will not work, so it
|
# partitioning, the follow-up mounting/formatting will not work, so it
|
||||||
# will stop there (see #463).
|
# will stop there (see #463).
|
||||||
boot_part_start = pmb.parse.deviceinfo()["boot_part_start"] or "2048"
|
boot_part_start = pmb.parse.deviceinfo().boot_part_start or "2048"
|
||||||
|
|
||||||
partition_type = pmb.parse.deviceinfo()["partition_type"] or "msdos"
|
partition_type = pmb.parse.deviceinfo().partition_type or "msdos"
|
||||||
|
|
||||||
commands = [
|
commands = [
|
||||||
["mktable", partition_type],
|
["mktable", partition_type],
|
||||||
|
@ -131,8 +131,8 @@ def partition_cgpt(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
pmb.chroot.apk.install(["cgpt"], Chroot.native(), build=False)
|
pmb.chroot.apk.install(["cgpt"], Chroot.native(), build=False)
|
||||||
|
|
||||||
cgpt = {
|
cgpt = {
|
||||||
'kpart_start': pmb.parse.deviceinfo()["cgpt_kpart_start"],
|
'kpart_start': pmb.parse.deviceinfo().cgpt_kpart_start,
|
||||||
'kpart_size': pmb.parse.deviceinfo()["cgpt_kpart_size"],
|
'kpart_size': pmb.parse.deviceinfo().cgpt_kpart_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert to MB and print info
|
# Convert to MB and print info
|
||||||
|
|
|
@ -20,7 +20,7 @@ def create_zip(args: PmbArgs, chroot: Chroot, device: str):
|
||||||
rootfs = "/mnt/rootfs_" + device
|
rootfs = "/mnt/rootfs_" + device
|
||||||
flavor = pmb.helpers.frontend._parse_flavor(device)
|
flavor = pmb.helpers.frontend._parse_flavor(device)
|
||||||
deviceinfo = pmb.parse.deviceinfo()
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
method = deviceinfo["flash_method"]
|
method = deviceinfo.flash_method
|
||||||
fvars = pmb.flasher.variables(args, flavor, method)
|
fvars = pmb.flasher.variables(args, flavor, method)
|
||||||
|
|
||||||
# Install recovery installer package in buildroot
|
# Install recovery installer package in buildroot
|
||||||
|
@ -30,7 +30,7 @@ def create_zip(args: PmbArgs, chroot: Chroot, device: str):
|
||||||
logging.info(f"({chroot}) create recovery zip")
|
logging.info(f"({chroot}) create recovery zip")
|
||||||
|
|
||||||
for key in fvars:
|
for key in fvars:
|
||||||
pmb.flasher.check_partition_blacklist(args, deviceinfo, key, fvars[key])
|
pmb.flasher.check_partition_blacklist(deviceinfo, key, fvars[key])
|
||||||
|
|
||||||
# Create config file for the recovery installer
|
# Create config file for the recovery installer
|
||||||
options = {
|
options = {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import copy
|
import copy
|
||||||
from typing import Dict
|
from pathlib import Path
|
||||||
|
from typing import Dict, Optional
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
@ -9,47 +10,210 @@ import pmb.config
|
||||||
import pmb.helpers.other
|
import pmb.helpers.other
|
||||||
import pmb.helpers.devices
|
import pmb.helpers.devices
|
||||||
|
|
||||||
|
# FIXME: It feels weird to handle this at parse time.
|
||||||
|
# we should instead have the Deviceinfo object store
|
||||||
|
# the attributes for all kernels and require the user
|
||||||
|
# to specify which one they're using.
|
||||||
|
# Basically: treat Deviceinfo as a standalone type that
|
||||||
|
# doesn't need to traverse pmaports.
|
||||||
|
def _parse_kernel_suffix(info, device, kernel):
|
||||||
|
"""
|
||||||
|
Remove the kernel suffix (as selected in 'pmbootstrap init') from
|
||||||
|
deviceinfo variables. Related:
|
||||||
|
https://wiki.postmarketos.org/wiki/Device_specific_package#Multiple_kernels
|
||||||
|
|
||||||
def sanity_check(info, path):
|
:param info: deviceinfo dict, e.g.:
|
||||||
|
{"a": "first",
|
||||||
|
"b_mainline": "second",
|
||||||
|
"b_downstream": "third"}
|
||||||
|
:param device: which device info belongs to
|
||||||
|
:param kernel: which kernel suffix to remove (e.g. "mainline")
|
||||||
|
:returns: info, but with the configured kernel suffix removed, e.g:
|
||||||
|
{"a": "first",
|
||||||
|
"b": "second",
|
||||||
|
"b_downstream": "third"}
|
||||||
|
"""
|
||||||
|
# Do nothing if the configured kernel isn't available in the kernel (e.g.
|
||||||
|
# after switching from device with multiple kernels to device with only one
|
||||||
|
# kernel)
|
||||||
|
kernels = pmb.parse._apkbuild.kernels(device)
|
||||||
|
if not kernels or kernel not in kernels:
|
||||||
|
logging.verbose(f"parse_kernel_suffix: {kernel} not in {kernels}")
|
||||||
|
return info
|
||||||
|
|
||||||
|
ret = copy.copy(info)
|
||||||
|
|
||||||
|
suffix_kernel = kernel.replace("-", "_")
|
||||||
|
for key in Deviceinfo.__annotations__.keys():
|
||||||
|
key_kernel = f"{key}_{suffix_kernel}"
|
||||||
|
if key_kernel not in ret:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Move ret[key_kernel] to ret[key]
|
||||||
|
logging.verbose(f"parse_kernel_suffix: {key_kernel} => {key}")
|
||||||
|
ret[key] = ret[key_kernel]
|
||||||
|
del ret[key_kernel]
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def deviceinfo(device=None, kernel=None) -> "Deviceinfo":
|
||||||
|
"""
|
||||||
|
:param device: defaults to args.device
|
||||||
|
:param kernel: defaults to args.kernel
|
||||||
|
"""
|
||||||
|
context = get_context()
|
||||||
|
if not device:
|
||||||
|
device = context.config.device
|
||||||
|
if not kernel:
|
||||||
|
kernel = context.config.kernel
|
||||||
|
|
||||||
|
if device in pmb.helpers.other.cache["deviceinfo"]:
|
||||||
|
return pmb.helpers.other.cache["deviceinfo"][device]
|
||||||
|
|
||||||
|
aports = context.config.aports
|
||||||
|
if not aports.exists():
|
||||||
|
logging.fatal(f"Aports directory is missing, expected: {aports}")
|
||||||
|
logging.fatal("Please provide a path to the aports directory using the"
|
||||||
|
" -p flag")
|
||||||
|
raise RuntimeError("Aports directory missing")
|
||||||
|
|
||||||
|
path = pmb.helpers.devices.find_path(device, 'deviceinfo')
|
||||||
|
if not path:
|
||||||
|
raise RuntimeError(
|
||||||
|
"Device '" + device + "' not found. Run 'pmbootstrap init' to"
|
||||||
|
" start a new device port or to choose another device. It may have"
|
||||||
|
" been renamed, see <https://postmarketos.org/renamed>")
|
||||||
|
|
||||||
|
di = Deviceinfo(path, kernel)
|
||||||
|
|
||||||
|
pmb.helpers.other.cache["deviceinfo"][device] = di
|
||||||
|
return di
|
||||||
|
|
||||||
|
class Deviceinfo:
|
||||||
|
"""Variables from deviceinfo. Reference: <https://postmarketos.org/deviceinfo>
|
||||||
|
Many of these are unused in pmbootstrap, and still more that are described
|
||||||
|
on the wiki are missing. Eventually this class and associated code should
|
||||||
|
be moved to a separate library and become the authoritative source of truth
|
||||||
|
for the deviceinfo format."""
|
||||||
|
path: Path
|
||||||
|
# general
|
||||||
|
format_version: str
|
||||||
|
name: str
|
||||||
|
manufacturer: str
|
||||||
|
codename: str
|
||||||
|
year: str
|
||||||
|
dtb: str
|
||||||
|
arch: str
|
||||||
|
|
||||||
|
# device
|
||||||
|
chassis: str
|
||||||
|
keyboard: Optional[str] = ""
|
||||||
|
external_storage: Optional[str] = ""
|
||||||
|
dev_touchscreen: Optional[str] = ""
|
||||||
|
dev_touchscreen_calibration: Optional[str] = ""
|
||||||
|
append_dtb: Optional[str] = ""
|
||||||
|
|
||||||
|
# bootloader
|
||||||
|
flash_method: Optional[str] = ""
|
||||||
|
boot_filesystem: Optional[str] = ""
|
||||||
|
|
||||||
|
# flash
|
||||||
|
flash_heimdall_partition_kernel: Optional[str] = ""
|
||||||
|
flash_heimdall_partition_initfs: Optional[str] = ""
|
||||||
|
flash_heimdall_partition_rootfs: Optional[str] = ""
|
||||||
|
flash_heimdall_partition_system: Optional[str] = "" # deprecated
|
||||||
|
flash_heimdall_partition_vbmeta: Optional[str] = ""
|
||||||
|
flash_heimdall_partition_dtbo: Optional[str] = ""
|
||||||
|
flash_fastboot_partition_kernel: Optional[str] = ""
|
||||||
|
flash_fastboot_partition_rootfs: Optional[str] = ""
|
||||||
|
flash_fastboot_partition_system: Optional[str] = "" # deprecated
|
||||||
|
flash_fastboot_partition_vbmeta: Optional[str] = ""
|
||||||
|
flash_fastboot_partition_dtbo: Optional[str] = ""
|
||||||
|
flash_rk_partition_kernel: Optional[str] = ""
|
||||||
|
flash_rk_partition_rootfs: Optional[str] = ""
|
||||||
|
flash_rk_partition_system: Optional[str] = "" # deprecated
|
||||||
|
flash_mtkclient_partition_kernel: Optional[str] = ""
|
||||||
|
flash_mtkclient_partition_rootfs: Optional[str] = ""
|
||||||
|
flash_mtkclient_partition_vbmeta: Optional[str] = ""
|
||||||
|
flash_mtkclient_partition_dtbo: Optional[str] = ""
|
||||||
|
generate_legacy_uboot_initfs: Optional[str] = ""
|
||||||
|
kernel_cmdline: Optional[str] = ""
|
||||||
|
generate_bootimg: Optional[str] = ""
|
||||||
|
header_version: Optional[str] = ""
|
||||||
|
bootimg_qcdt: Optional[str] = ""
|
||||||
|
bootimg_mtk_mkimage: Optional[str] = "" # deprecated
|
||||||
|
bootimg_mtk_label_kernel: Optional[str] = ""
|
||||||
|
bootimg_mtk_label_ramdisk: Optional[str] = ""
|
||||||
|
bootimg_dtb_second: Optional[str] = ""
|
||||||
|
bootimg_custom_args: Optional[str] = ""
|
||||||
|
flash_offset_base: Optional[str] = ""
|
||||||
|
flash_offset_dtb: Optional[str] = ""
|
||||||
|
flash_offset_kernel: Optional[str] = ""
|
||||||
|
flash_offset_ramdisk: Optional[str] = ""
|
||||||
|
flash_offset_second: Optional[str] = ""
|
||||||
|
flash_offset_tags: Optional[str] = ""
|
||||||
|
flash_pagesize: Optional[str] = ""
|
||||||
|
flash_fastboot_max_size: Optional[str] = ""
|
||||||
|
flash_sparse: Optional[str] = ""
|
||||||
|
flash_sparse_samsung_format: Optional[str] = ""
|
||||||
|
rootfs_image_sector_size: Optional[str] = ""
|
||||||
|
sd_embed_firmware: Optional[str] = ""
|
||||||
|
sd_embed_firmware_step_size: Optional[str] = ""
|
||||||
|
partition_blacklist: Optional[str] = ""
|
||||||
|
boot_part_start: Optional[str] = ""
|
||||||
|
partition_type: Optional[str] = ""
|
||||||
|
root_filesystem: Optional[str] = ""
|
||||||
|
flash_kernel_on_update: Optional[str] = ""
|
||||||
|
cgpt_kpart: Optional[str] = ""
|
||||||
|
cgpt_kpart_start: Optional[str] = ""
|
||||||
|
cgpt_kpart_size: Optional[str] = ""
|
||||||
|
|
||||||
|
# weston
|
||||||
|
weston_pixman_type: Optional[str] = ""
|
||||||
|
|
||||||
|
# keymaps
|
||||||
|
keymaps: Optional[str] = ""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __validate(info: Dict[str, str], path: Path):
|
||||||
# Resolve path for more readable error messages
|
# Resolve path for more readable error messages
|
||||||
path = os.path.realpath(path)
|
path = path.resolve()
|
||||||
|
|
||||||
# Legacy errors
|
# Legacy errors
|
||||||
if "flash_methods" in info:
|
if "flash_methods" in info:
|
||||||
raise RuntimeError("deviceinfo_flash_methods has been renamed to"
|
raise RuntimeError("deviceinfo_flash_methods has been renamed to"
|
||||||
" deviceinfo_flash_method. Please adjust your"
|
" deviceinfo_flash_method. Please adjust your"
|
||||||
" deviceinfo file: " + path)
|
f" deviceinfo file: {path}")
|
||||||
if "external_disk" in info or "external_disk_install" in info:
|
if "external_disk" in info or "external_disk_install" in info:
|
||||||
raise RuntimeError("Instead of deviceinfo_external_disk and"
|
raise RuntimeError("Instead of deviceinfo_external_disk and"
|
||||||
" deviceinfo_external_disk_install, please use the"
|
" deviceinfo_external_disk_install, please use the"
|
||||||
" new variable deviceinfo_external_storage in your"
|
" new variable deviceinfo_external_storage in your"
|
||||||
" deviceinfo file: " + path)
|
f" deviceinfo file: {path}")
|
||||||
if "msm_refresher" in info:
|
if "msm_refresher" in info:
|
||||||
raise RuntimeError("It is enough to specify 'msm-fb-refresher' in the"
|
raise RuntimeError("It is enough to specify 'msm-fb-refresher' in the"
|
||||||
" depends of your device's package now. Please"
|
" depends of your device's package now. Please"
|
||||||
" delete the deviceinfo_msm_refresher line in: " +
|
" delete the deviceinfo_msm_refresher line in: "
|
||||||
path)
|
f"{path}")
|
||||||
if "flash_fastboot_vendor_id" in info:
|
if "flash_fastboot_vendor_id" in info:
|
||||||
raise RuntimeError("Fastboot doesn't allow specifying the vendor ID"
|
raise RuntimeError("Fastboot doesn't allow specifying the vendor ID"
|
||||||
" anymore (#1830). Try removing the"
|
" anymore (#1830). Try removing the"
|
||||||
" 'deviceinfo_flash_fastboot_vendor_id' line in: " +
|
" 'deviceinfo_flash_fastboot_vendor_id' line in: "
|
||||||
path + " (if you are sure that you need this, then"
|
f"{path} (if you are sure that you need this, then"
|
||||||
" we can probably bring it back to fastboot, just"
|
" we can probably bring it back to fastboot, just"
|
||||||
" let us know in the postmarketOS issues!)")
|
" let us know in the postmarketOS issues!)")
|
||||||
if "nonfree" in info:
|
if "nonfree" in info:
|
||||||
raise RuntimeError("deviceinfo_nonfree is unused. "
|
raise RuntimeError("deviceinfo_nonfree is unused. "
|
||||||
"Please delete it in: " + path)
|
f"Please delete it in: {path}")
|
||||||
if "dev_keyboard" in info:
|
if "dev_keyboard" in info:
|
||||||
raise RuntimeError("deviceinfo_dev_keyboard is unused. "
|
raise RuntimeError("deviceinfo_dev_keyboard is unused. "
|
||||||
"Please delete it in: " + path)
|
f"Please delete it in: {path}")
|
||||||
if "date" in info:
|
if "date" in info:
|
||||||
raise RuntimeError("deviceinfo_date was replaced by deviceinfo_year. "
|
raise RuntimeError("deviceinfo_date was replaced by deviceinfo_year. "
|
||||||
"Set it to the release year in: " + path)
|
f"Set it to the release year in: {path}")
|
||||||
|
|
||||||
# "codename" is required
|
# "codename" is required
|
||||||
codename = os.path.basename(os.path.dirname(path))
|
codename = os.path.basename(os.path.dirname(path))[7:]
|
||||||
if codename.startswith("device-"):
|
|
||||||
codename = codename[7:]
|
|
||||||
if "codename" not in info or info["codename"] != codename:
|
if "codename" not in info or info["codename"] != codename:
|
||||||
raise RuntimeError(f"Please add 'deviceinfo_codename=\"{codename}\"' "
|
raise RuntimeError(f"Please add 'deviceinfo_codename=\"{codename}\"' "
|
||||||
f"to: {path}")
|
f"to: {path}")
|
||||||
|
@ -80,76 +244,7 @@ def sanity_check(info, path):
|
||||||
f" and try again: {path}")
|
f" and try again: {path}")
|
||||||
|
|
||||||
|
|
||||||
def _parse_kernel_suffix(info, device, kernel):
|
def __init__(self, path: Path, kernel: Optional[str] = None):
|
||||||
"""
|
|
||||||
Remove the kernel suffix (as selected in 'pmbootstrap init') from
|
|
||||||
deviceinfo variables. Related:
|
|
||||||
https://wiki.postmarketos.org/wiki/Device_specific_package#Multiple_kernels
|
|
||||||
|
|
||||||
:param info: deviceinfo dict, e.g.:
|
|
||||||
{"a": "first",
|
|
||||||
"b_mainline": "second",
|
|
||||||
"b_downstream": "third"}
|
|
||||||
:param device: which device info belongs to
|
|
||||||
:param kernel: which kernel suffix to remove (e.g. "mainline")
|
|
||||||
:returns: info, but with the configured kernel suffix removed, e.g:
|
|
||||||
{"a": "first",
|
|
||||||
"b": "second",
|
|
||||||
"b_downstream": "third"}
|
|
||||||
"""
|
|
||||||
# Do nothing if the configured kernel isn't available in the kernel (e.g.
|
|
||||||
# after switching from device with multiple kernels to device with only one
|
|
||||||
# kernel)
|
|
||||||
kernels = pmb.parse._apkbuild.kernels(device)
|
|
||||||
if not kernels or kernel not in kernels:
|
|
||||||
logging.verbose(f"parse_kernel_suffix: {kernel} not in {kernels}")
|
|
||||||
return info
|
|
||||||
|
|
||||||
ret = copy.copy(info)
|
|
||||||
|
|
||||||
suffix_kernel = kernel.replace("-", "_")
|
|
||||||
for key in pmb.config.deviceinfo_attributes:
|
|
||||||
key_kernel = f"{key}_{suffix_kernel}"
|
|
||||||
if key_kernel not in ret:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Move ret[key_kernel] to ret[key]
|
|
||||||
logging.verbose(f"parse_kernel_suffix: {key_kernel} => {key}")
|
|
||||||
ret[key] = ret[key_kernel]
|
|
||||||
del ret[key_kernel]
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME (#2324): Make deviceinfo a type! (class!!!)
|
|
||||||
def deviceinfo(device=None, kernel=None) -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
:param device: defaults to args.device
|
|
||||||
:param kernel: defaults to args.kernel
|
|
||||||
"""
|
|
||||||
context = get_context()
|
|
||||||
if not device:
|
|
||||||
device = context.config.device
|
|
||||||
if not kernel:
|
|
||||||
kernel = context.config.kernel
|
|
||||||
|
|
||||||
if device in pmb.helpers.other.cache["deviceinfo"]:
|
|
||||||
return pmb.helpers.other.cache["deviceinfo"][device]
|
|
||||||
|
|
||||||
aports = context.config.aports
|
|
||||||
if not aports.exists():
|
|
||||||
logging.fatal(f"Aports directory is missing, expected: {aports}")
|
|
||||||
logging.fatal("Please provide a path to the aports directory using the"
|
|
||||||
" -p flag")
|
|
||||||
raise RuntimeError("Aports directory missing")
|
|
||||||
|
|
||||||
path = pmb.helpers.devices.find_path(device, 'deviceinfo')
|
|
||||||
if not path:
|
|
||||||
raise RuntimeError(
|
|
||||||
"Device '" + device + "' not found. Run 'pmbootstrap init' to"
|
|
||||||
" start a new device port or to choose another device. It may have"
|
|
||||||
" been renamed, see <https://postmarketos.org/renamed>")
|
|
||||||
|
|
||||||
ret = {}
|
ret = {}
|
||||||
with open(path) as handle:
|
with open(path) as handle:
|
||||||
for line in handle:
|
for line in handle:
|
||||||
|
@ -162,13 +257,11 @@ def deviceinfo(device=None, kernel=None) -> Dict[str, str]:
|
||||||
value = split[1].replace("\"", "").replace("\n", "")
|
value = split[1].replace("\"", "").replace("\n", "")
|
||||||
ret[key] = value
|
ret[key] = value
|
||||||
|
|
||||||
# Assign empty string as default
|
ret = _parse_kernel_suffix(ret, ret["codename"], kernel)
|
||||||
for key in pmb.config.deviceinfo_attributes:
|
Deviceinfo.__validate(ret, path)
|
||||||
if key not in ret:
|
|
||||||
ret[key] = ""
|
|
||||||
|
|
||||||
ret = _parse_kernel_suffix(ret, device, kernel)
|
for key, value in ret.items():
|
||||||
sanity_check(ret, path)
|
# FIXME: something to turn on and fix in the future
|
||||||
|
# if key not in Deviceinfo.__annotations__.keys():
|
||||||
pmb.helpers.other.cache["deviceinfo"][device] = ret
|
# logging.warning(f"deviceinfo: {key} is not a known attribute")
|
||||||
return ret
|
setattr(self, key, value)
|
||||||
|
|
|
@ -92,7 +92,7 @@ def command_qemu(args: PmbArgs, device: str, arch, img_path, img_path_2nd=None):
|
||||||
"""
|
"""
|
||||||
Generate the full qemu command with arguments to run postmarketOS
|
Generate the full qemu command with arguments to run postmarketOS
|
||||||
"""
|
"""
|
||||||
cmdline = pmb.parse.deviceinfo()["kernel_cmdline"]
|
cmdline = pmb.parse.deviceinfo().kernel_cmdline
|
||||||
if args.cmdline:
|
if args.cmdline:
|
||||||
cmdline = args.cmdline
|
cmdline = args.cmdline
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ def command_qemu(args: PmbArgs, device: str, arch, img_path, img_path_2nd=None):
|
||||||
"if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF.fd"]
|
"if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF.fd"]
|
||||||
|
|
||||||
# Kernel Virtual Machine (KVM) support
|
# Kernel Virtual Machine (KVM) support
|
||||||
native = pmb.config.arch_native == pmb.parse.deviceinfo()["arch"]
|
native = pmb.config.arch_native == pmb.parse.deviceinfo().arch
|
||||||
if args.qemu_kvm and native and os.path.exists("/dev/kvm"):
|
if args.qemu_kvm and native and os.path.exists("/dev/kvm"):
|
||||||
command += ["-enable-kvm"]
|
command += ["-enable-kvm"]
|
||||||
command += ["-cpu", "host"]
|
command += ["-cpu", "host"]
|
||||||
|
@ -338,7 +338,7 @@ def run(args: PmbArgs):
|
||||||
raise RuntimeError("'pmbootstrap qemu' can be only used with one of "
|
raise RuntimeError("'pmbootstrap qemu' can be only used with one of "
|
||||||
"the QEMU device packages. Run 'pmbootstrap init' "
|
"the QEMU device packages. Run 'pmbootstrap init' "
|
||||||
"and select the 'qemu' vendor.")
|
"and select the 'qemu' vendor.")
|
||||||
arch = pmb.parse.arch.alpine_to_qemu(pmb.parse.deviceinfo()["arch"])
|
arch = pmb.parse.arch.alpine_to_qemu(pmb.parse.deviceinfo().arch)
|
||||||
|
|
||||||
img_path = system_image(device)
|
img_path = system_image(device)
|
||||||
img_path_2nd = None
|
img_path_2nd = None
|
||||||
|
|
|
@ -57,7 +57,6 @@ class PmbArgs(Namespace):
|
||||||
cross: bool
|
cross: bool
|
||||||
details: bool
|
details: bool
|
||||||
details_to_stdout: bool
|
details_to_stdout: bool
|
||||||
deviceinfo: Dict[str, str]
|
|
||||||
deviceinfo_parse_kernel: str
|
deviceinfo_parse_kernel: str
|
||||||
devices: str
|
devices: str
|
||||||
disk: Path
|
disk: Path
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue