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:
Caleb Connolly 2024-06-06 15:05:59 +02:00 committed by Oliver Smith
parent b51d31acab
commit 97bd8b96ec
No known key found for this signature in database
GPG key ID: 5AE7F5513E0885CB
27 changed files with 372 additions and 288 deletions

View file

@ -1,10 +1,10 @@
# Copyright 2023 Oliver Smith
# SPDX-License-Identifier: GPL-3.0-or-later
from typing import Dict
from pmb.core.context import get_context
from pmb.helpers import logging
import pmb.config
from pmb.parse.deviceinfo import Deviceinfo
from pmb.types import PmbArgs
import pmb.flasher
import pmb.install
@ -17,11 +17,11 @@ import pmb.parse.kconfig
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)
flavor = pmb.helpers.frontend._parse_flavor(device, autoinstall)
flavor = pmb.helpers.frontend._parse_flavor(deviceinfo.codename, 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
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
if boot:
logging.info("(native) boot " + flavor + " kernel")
pmb.flasher.run(device, deviceinfo, "boot", flavor)
pmb.flasher.run(deviceinfo, method, "boot", flavor)
else:
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 "
"USB interface shortly.")
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))
def rootfs(device: str, deviceinfo: Dict[str, str], method: str):
def rootfs(deviceinfo: Deviceinfo, method: str):
# Generate rootfs, install flasher
suffix = ".img"
if pmb.config.flashers.get(method, {}).get("split", False):
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():
raise RuntimeError("The rootfs has not been generated yet, please run"
" 'pmbootstrap install' first.")
# Do not flash if using fastboot & image is too large
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
max_size = int(deviceinfo["flash_fastboot_max_size"])
max_size = int(deviceinfo.flash_fastboot_max_size)
if img_size > max_size:
raise RuntimeError("The rootfs is too large for fastboot to"
" flash.")
# Run the flasher
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):
pmb.flasher.run(device, deviceinfo, "list_devices")
def list_devices(deviceinfo: Deviceinfo, method: str):
pmb.flasher.run(deviceinfo, method, "list_devices")
def sideload(device: str, deviceinfo: Dict[str, str]):
def sideload(deviceinfo: Deviceinfo, method: str):
# Install depends
pmb.flasher.install_depends()
pmb.flasher.install_depends(method)
# Mount the buildroot
chroot = Chroot.buildroot(deviceinfo["arch"])
chroot = Chroot.buildroot(deviceinfo.arch)
mountpoint = "/mnt/" / chroot
pmb.helpers.mount.bind(chroot.path,
Chroot.native().path / mountpoint)
# Missing recovery zip error
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,"
" please run 'pmbootstrap install' with the"
" '--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":
# 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
# 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")
output = pmb.chroot.root(["fastboot", "getvar", "product"],
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.")
# 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)
lk2nd_pkg = None
for dep in apkbuild["depends"]:
@ -125,11 +125,11 @@ def flash_lk2nd(device: str, deviceinfo: Dict[str, str], method: str):
if not lk2nd_pkg:
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)
logging.info("(native) flash lk2nd image")
pmb.flasher.run(device, deviceinfo, "flash_lk2nd")
pmb.flasher.run(deviceinfo, method, "flash_lk2nd")
def frontend(args: PmbArgs):
@ -137,7 +137,7 @@ def frontend(args: PmbArgs):
action = args.action_flasher
device = context.device
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",
"flash_lk2nd"]:
@ -145,20 +145,20 @@ def frontend(args: PmbArgs):
return
if action in ["boot", "flash_kernel"]:
kernel(device, deviceinfo)
kernel(deviceinfo, method)
elif action == "flash_rootfs":
rootfs(device, deviceinfo, method)
rootfs(deviceinfo, method)
elif action == "flash_vbmeta":
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":
logging.info("(native) flash dtbo image")
pmb.flasher.run(device, deviceinfo, "flash_dtbo")
pmb.flasher.run(deviceinfo, method, "flash_dtbo")
elif action == "flash_lk2nd":
flash_lk2nd(device, deviceinfo, method)
flash_lk2nd(deviceinfo, method)
elif action == "list_flavors":
list_flavors(device)
elif action == "list_devices":
list_devices(device, deviceinfo)
pmb.flasher.run(deviceinfo, method, "list_devices")
elif action == "sideload":
sideload(device, deviceinfo)
sideload(deviceinfo, method)