# Copyright 2020 Oliver Smith # SPDX-License-Identifier: GPL-3.0-or-later import logging import os import pmb.helpers.cli import pmb.helpers.run import pmb.aportgen.core import pmb.parse.apkindex import pmb.parse.bootimg def ask_for_architecture(args): architectures = pmb.config.build_device_architectures while True: ret = pmb.helpers.cli.ask(args, "Device architecture", architectures, architectures[0]) if ret in architectures: return ret logging.fatal("ERROR: Invalid architecture specified. If you want to" " add a new architecture, edit build_device_architectures" " in pmb/config/__init__.py.") def ask_for_manufacturer(args): logging.info("Who produced the device (e.g. LG)?") return pmb.helpers.cli.ask(args, "Manufacturer", None, None, False) def ask_for_name(args, manufacturer): logging.info("What is the official name (e.g. Google Nexus 5)?") ret = pmb.helpers.cli.ask(args, "Name", None, None, False) # Always add the manufacturer if not ret.startswith(manufacturer) and \ not ret.startswith("Google"): ret = manufacturer + " " + ret return ret def ask_for_year(args): # Regex from https://stackoverflow.com/a/12240826 logging.info("In what year was the device released (e.g. 2012)?") return pmb.helpers.cli.ask(args, "Year", None, None, False, validation_regex=r'^[1-9]\d{3,}$') def ask_for_keyboard(args): return pmb.helpers.cli.confirm(args, "Does the device have a hardware keyboard?") def ask_for_external_storage(args): return pmb.helpers.cli.confirm(args, "Does the device have a sdcard or other" " external storage medium?") def ask_for_flash_method(args): while True: logging.info("Which flash method does the device support?") method = pmb.helpers.cli.ask(args, "Flash method", pmb.config.flash_methods, pmb.config.flash_methods[0]) if method in pmb.config.flash_methods: if method == "heimdall": heimdall_types = ["isorec", "bootimg"] while True: logging.info("Does the device use the \"isolated recovery\" or boot.img?") logging.info("") heimdall_type = pmb.helpers.cli.ask(args, "Type", heimdall_types, heimdall_types[0]) if heimdall_type in heimdall_types: method += "-" + heimdall_type break logging.fatal("ERROR: Invalid type specified.") return method logging.fatal("ERROR: Invalid flash method specified. If you want to" " add a new flash method, edit flash_methods in" " pmb/config/__init__.py.") def ask_for_bootimg(args): logging.info("You can analyze a known working boot.img file to automatically fill" " out the flasher information for your deviceinfo file. Either specify" " the path to an image or press return to skip this step (you can do" " it later with 'pmbootstrap bootimg_analyze').") while True: path = os.path.expanduser(pmb.helpers.cli.ask(args, "Path", None, "", False)) if not path: return None try: return pmb.parse.bootimg(args, path) except Exception as e: logging.fatal("ERROR: " + str(e) + ". Please try again.") def generate_deviceinfo_fastboot_content(args, bootimg=None): if bootimg is None: bootimg = {"cmdline": "", "qcdt": "false", "dtb_second": "false", "base": "", "kernel_offset": "", "ramdisk_offset": "", "second_offset": "", "tags_offset": "", "pagesize": "2048"} return """\ deviceinfo_kernel_cmdline=\"""" + bootimg["cmdline"] + """\" deviceinfo_generate_bootimg="true" deviceinfo_bootimg_qcdt=\"""" + bootimg["qcdt"] + """\" deviceinfo_bootimg_dtb_second=\"""" + bootimg["dtb_second"] + """\" deviceinfo_flash_offset_base=\"""" + bootimg["base"] + """\" deviceinfo_flash_offset_kernel=\"""" + bootimg["kernel_offset"] + """\" deviceinfo_flash_offset_ramdisk=\"""" + bootimg["ramdisk_offset"] + """\" deviceinfo_flash_offset_second=\"""" + bootimg["second_offset"] + """\" deviceinfo_flash_offset_tags=\"""" + bootimg["tags_offset"] + """\" deviceinfo_flash_pagesize=\"""" + bootimg["pagesize"] + """\" """ def generate_deviceinfo(args, pkgname, name, manufacturer, year, arch, has_keyboard, has_external_storage, flash_method, bootimg=None): codename = "-".join(pkgname.split("-")[1:]) # Note: New variables must be added to pmb/config/__init__.py as well content = """\ # Reference: # Please use double quotes only. You can source this file in shell scripts. deviceinfo_format_version="0" deviceinfo_name=\"""" + name + """\" deviceinfo_manufacturer=\"""" + manufacturer + """\" deviceinfo_codename=\"""" + codename + """\" deviceinfo_year=\"""" + year + """\" deviceinfo_dtb="" deviceinfo_modules_initfs="" deviceinfo_arch=\"""" + arch + """\" # Device related deviceinfo_keyboard=\"""" + ("true" if has_keyboard else "false") + """\" deviceinfo_external_storage=\"""" + ("true" if has_external_storage else "false") + """\" deviceinfo_screen_width="800" deviceinfo_screen_height="600" # Bootloader related deviceinfo_flash_method=\"""" + flash_method + """\" """ content_heimdall_bootimg = """\ deviceinfo_flash_heimdall_partition_kernel="" deviceinfo_flash_heimdall_partition_system="" """ content_heimdall_isorec = """\ deviceinfo_flash_heimdall_partition_kernel="" deviceinfo_flash_heimdall_partition_initfs="" deviceinfo_flash_heimdall_partition_system="" """ content_0xffff = """\ deviceinfo_generate_legacy_uboot_initfs="true" """ content_uuu = """\ deviceinfo_generate_legacy_uboot_initfs="true" """ if flash_method == "fastboot": content += generate_deviceinfo_fastboot_content(args, bootimg) elif flash_method == "heimdall-bootimg": content += generate_deviceinfo_fastboot_content(args, bootimg) content += content_heimdall_bootimg elif flash_method == "heimdall-isorec": content += content_heimdall_isorec elif flash_method == "0xffff": content += content_0xffff elif flash_method == "uuu": content += content_uuu # Write to file pmb.helpers.run.user(args, ["mkdir", "-p", args.work + "/aportgen"]) with open(args.work + "/aportgen/deviceinfo", "w", encoding="utf-8") as handle: for line in content.split("\n"): handle.write(line.lstrip() + "\n") def generate_apkbuild(args, pkgname, name, arch, flash_method): # Dependencies depends = "postmarketos-base linux-" + "-".join(pkgname.split("-")[1:]) if flash_method in ["fastboot", "heimdall-bootimg"]: depends += " mkbootimg" if flash_method == "0xffff": depends += " uboot-tools" depends += " mesa-dri-swrast" # Whole APKBUILD content = """\ # Contributor: Firstname Lastname (CHANGEME!) # Maintainer: Firstname Lastname (CHANGEME!) # Reference: pkgname=\"""" + pkgname + """\" pkgdesc=\"""" + name + """\" pkgver=0.1 pkgrel=0 url="https://postmarketos.org" license="MIT" arch=\"""" + arch + """\" options="!check !archcheck" depends=\"""" + depends + """\" makedepends="devicepkg-dev" source="deviceinfo" build() { devicepkg_build $startdir $pkgname } package() { devicepkg_package $startdir $pkgname } sha512sums="(run 'pmbootstrap checksum """ + pkgname + """' to fill)" """ # Write the file pmb.helpers.run.user(args, ["mkdir", "-p", args.work + "/aportgen"]) with open(args.work + "/aportgen/APKBUILD", "w", encoding="utf-8") as handle: for line in content.split("\n"): handle.write(line[8:].replace(" " * 4, "\t") + "\n") def generate(args, pkgname): arch = ask_for_architecture(args) manufacturer = ask_for_manufacturer(args) name = ask_for_name(args, manufacturer) year = ask_for_year(args) has_keyboard = ask_for_keyboard(args) has_external_storage = ask_for_external_storage(args) flash_method = ask_for_flash_method(args) bootimg = None if flash_method in ["fastboot", "heimdall-bootimg"]: bootimg = ask_for_bootimg(args) generate_deviceinfo(args, pkgname, name, manufacturer, year, arch, has_keyboard, has_external_storage, flash_method, bootimg) generate_apkbuild(args, pkgname, name, arch, flash_method)