From 3cbd0d19c2e0b62f3b003d6adc7a3e9611cf1386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20Sz=C3=B6ll=C5=91si?= Date: Fri, 29 Sep 2017 00:05:00 +0200 Subject: [PATCH] Add support for isorec flashing in recovery installer (#609) --- .../APKBUILD | 12 ++--- .../build_zip.sh | 2 +- .../pmos_install | 25 +++++++--- .../pmos_install_functions | 43 +++++++++++------ .../update-binary | 2 +- pmb/flasher/__init__.py | 1 + pmb/flasher/frontend.py | 6 +++ pmb/flasher/run.py | 24 +--------- pmb/flasher/variables.py | 46 +++++++++++++++++++ pmb/install/recovery.py | 36 +++++++++------ pmb/parse/arguments.py | 6 +-- 11 files changed, 135 insertions(+), 68 deletions(-) create mode 100644 pmb/flasher/variables.py diff --git a/aports/main/postmarketos-android-recovery-installer/APKBUILD b/aports/main/postmarketos-android-recovery-installer/APKBUILD index 0682b618..7a62d015 100644 --- a/aports/main/postmarketos-android-recovery-installer/APKBUILD +++ b/aports/main/postmarketos-android-recovery-installer/APKBUILD @@ -1,10 +1,10 @@ pkgname=postmarketos-android-recovery-installer -pkgver=0.0.2 +pkgver=0.0.3 pkgrel=1 pkgdesc="TWRP compatible postmarketOS installer script" url="https://github.com/postmarketOS" # multipath-tools: kpartx -depends="busybox-extras lddtree cryptsetup multipath-tools device-mapper parted zip" +depends="busybox-extras lddtree cryptsetup multipath-tools device-mapper parted util-linux zip" source="build_zip.sh update-binary pmos_install @@ -26,8 +26,8 @@ package() { done mkdir "$pkgdir/var/lib/postmarketos-android-recovery-installer/lib/" } -sha512sums="4e4f56c84b404c53c3835304e8f7b651d6dbf19a653358daa6be1cc47e23360cb1dabb1331c13dd288fabb8eabaf8a01d094f054c334a156ca79f03948c9a17f build_zip.sh -22083b3c776ae2e3e098dc8d9c4e085e7aae543aef20b42732c6750608e22c69211e199b946d55581403b71eb78e6508f618128122058a59466ad8a632e46ed8 update-binary -446d0d00322c92a5af7e5be340e9f185ef41eaa9cf6df4f5b29f3437dfcf45e0bc5e845c1c5a864694f8e89efd1a30e5e615b7ccfff1b7a0571dfb6f1f5cf3e5 pmos_install -152bcf1375cff515205af2427e537ae8536537f3ce7cbcbe7b848496be5af45baa149fe676c2d4979dcef017b843280752d35587b1e81905fa6daa2444e037c8 pmos_install_functions +sha512sums="d065577f587ee604cfa635c3eaba5c856800e9dafbbab65d4311dc89b72feab131fc23605bc0a344979f0760162bc509ac2056ee3c4d3e78e56be15032e314c1 build_zip.sh +156f889593d82d4b1c88f3873299fc054e70e78bf26af37af4dd7770ed31a0a581f2cf03cad9e11a60159f424d2d3869fd6cd28600ad305469ddf01eaff49f6c update-binary +bc60b75dcd499084d66453c9f9beb989ad386a4bb394d0018982dc16e4f23f05c2b3308119fc513a3a391d7878047e65f46557b214a543a6a4cdfd92f6f7cf5a pmos_install +b4c669ab6dfe330a30c575f864cea916ac357ae96547c2296d1b5399669c6f49570c60554985d2939a1d3e3cb464e3229e2b4724eba1dd5d920dcec1b0f7f0e3 pmos_install_functions 27dd89aa8471349995a1cbbc1034ead662a0d1dd70ca5490f3191ceaaeb853331003c20ffddbbd95fe822135a85c1beb1e2a32bb33b10c2a4177b30347a40555 pmos_setpw" diff --git a/aports/main/postmarketos-android-recovery-installer/build_zip.sh b/aports/main/postmarketos-android-recovery-installer/build_zip.sh index fe438271..54678859 100644 --- a/aports/main/postmarketos-android-recovery-installer/build_zip.sh +++ b/aports/main/postmarketos-android-recovery-installer/build_zip.sh @@ -43,7 +43,7 @@ check_whether_exists() # shellcheck disable=SC1091 . ./install_options -BINARIES="/sbin/cryptsetup /sbin/kpartx /usr/sbin/parted /usr/sbin/partprobe" +BINARIES="/sbin/cryptsetup /sbin/kpartx /usr/sbin/parted /usr/sbin/partprobe /sbin/findfs" # shellcheck disable=SC2086 LIBRARIES=$(lddtree -l $BINARIES | awk '/lib/ {print}' | sort -u) copy_files "$BINARIES" bin/ diff --git a/aports/main/postmarketos-android-recovery-installer/pmos_install b/aports/main/postmarketos-android-recovery-installer/pmos_install index 02a26f38..008fa501 100755 --- a/aports/main/postmarketos-android-recovery-installer/pmos_install +++ b/aports/main/postmarketos-android-recovery-installer/pmos_install @@ -52,15 +52,17 @@ ui_print " " ui_print "postmarketOS recovery installer " ui_print " " -ui_print "Extracting partition info from fstab..." -extract_partition_table ui_print "Entering working directory..." cd "$WORKING_DIR" ui_print "Extracting files..." -unzip -o "$ZIP" +busybox unzip -o "$ZIP" mkdir /lib ui_print "Symlinking .so files to /lib/..." ln -s "$WORKING_DIR"/lib/* /lib/ +ui_print "Symlinking block devices..." +ln -s /dev/block/* /dev/ +ui_print "Extracting partition table..." +extract_partition_table ui_print "Unmounting /$INSTALL_PARTITION..." umount_install_partition ui_print "Creating partition table on $INSTALL_DEVICE..." @@ -69,7 +71,7 @@ partition_install_device || : if [ "$FDE" = "true" ] then ui_print "Generating temporary keyfile with random data..." - dd bs=512 count=4 if=/dev/urandom of="$WORKING_DIR"/lukskey + busybox dd bs=512 count=4 if=/dev/urandom of="$WORKING_DIR"/lukskey ui_print "Initializing LUKS device..." cryptsetup luksFormat --use-urandom -c "$CIPHER" -q "$ROOT_PARTITION" "$WORKING_DIR"/lukskey ui_print "Opening LUKS partition..." @@ -96,10 +98,19 @@ mount -t ext2 -rw "$PMOS_BOOT" /"$INSTALL_PARTITION"/boot || { } ui_print "Installing rootfs..." tar -xf rootfs.tar.gz -C /"$INSTALL_PARTITION" -if [ "$FLASH_BOOTIMG" = "true" ] +if [ "$FLASH_KERNEL" = "true" ] then - ui_print "Flashing boot.img..." - dd if=boot.img of="$BOOT" + if [ "$ISOREC" = "true" ] + then + ui_print "Flashing kernel..." + busybox dd if=/"$INSTALL_PARTITION"/boot/vmlinuz-"$FLAVOR" of="$KERNEL_PARTITION" + ui_print "Flashing initfs..." + busybox gunzip -c /"$INSTALL_PARTITION"/boot/initramfs-"$FLAVOR" | busybox lzop \ + > "$INITFS_PARTITION" + else + ui_print "Flashing boot.img..." + busybox dd if=/"$INSTALL_PARTITION"/boot/boot.img-"$FLAVOR" of="$BOOT_PARTITION" + fi fi if [ "$FDE" = "true" ] then diff --git a/aports/main/postmarketos-android-recovery-installer/pmos_install_functions b/aports/main/postmarketos-android-recovery-installer/pmos_install_functions index e467e5bc..1ea68469 100755 --- a/aports/main/postmarketos-android-recovery-installer/pmos_install_functions +++ b/aports/main/postmarketos-android-recovery-installer/pmos_install_functions @@ -23,6 +23,10 @@ export ZIP=$2 export WORKING_DIR="/tmp/postmarketos" export PATH=$PATH:"$WORKING_DIR"/bin +# Use findfs from util-linux +# shellcheck disable=SC2139 +alias findfs="$WORKING_DIR/bin/findfs" + # shellcheck source=/dev/null . "$WORKING_DIR"/install_options @@ -36,11 +40,12 @@ ui_print() { extract_partition_table() { case "$INSTALL_PARTITION" in "system") - # We need to resolve symlinks, to make set_subpartitions() work. - _INSTALL_DEVICE=$(readlink -fn "$(awk '/^\/system/ {print $3}' /etc/recovery.fstab)") + _INSTALL_DEVICE=$(findfs PARTLABEL="$SYSTEM_PARTLABEL") || \ + # We need to resolve symlinks, to make set_subpartitions() work. + _INSTALL_DEVICE=$(busybox readlink -fn "$(awk '/^\/system/ {print $3}' /etc/recovery.fstab)") ;; "external_sd") - _INSTALL_DEVICE=$(readlink -fn "$(awk '/^\/external_sd/ {print $4}' /etc/recovery.fstab)") + _INSTALL_DEVICE=$(busybox readlink -fn "$(awk '/^\/external_sd/ {print $4}' /etc/recovery.fstab)") ;; *) echo "No support for flashing $INSTALL_PARTITION." @@ -52,17 +57,26 @@ extract_partition_table() { echo "install device found at $_INSTALL_DEVICE" export INSTALL_DEVICE=$_INSTALL_DEVICE else - echo "Couldn't find /$INSTALL_PARTITION/ in fstab." + echo "Couldn't find $INSTALL_PARTITION partition." return 1 fi - _BOOT=$(awk '/^\/boot/ {print $3}' /etc/recovery.fstab) - if [ ! -z "$_BOOT" ] + if [ "$ISOREC" = "true" ] then - echo "boot partition found at $_BOOT" - export BOOT=$_BOOT + export KERNEL_PARTITION + KERNEL_PARTITION=$(findfs PARTLABEL="$KERNEL_PARTLABEL") + export INITFS_PARTITION + INITFS_PARTITION=$(findfs PARTLABEL="$INITFS_PARTLABEL") else - echo "Couldn't find /boot/ in fstab." - return 1 + _BOOT_PARTITION=$(findfs PARTLABEL="boot") || \ + _BOOT_PARTITION=$(awk '/^\/boot/ {print $3}' /etc/recovery.fstab) + if [ ! -z "$_BOOT_PARTITION" ] + then + echo "boot partition found at $_BOOT_PARTITION" + export BOOT_PARTITION=$_BOOT_PARTITION + else + echo "Couldn't find boot partition." + return 1 + fi fi } @@ -78,18 +92,19 @@ partition_install_device() { if [ "$INSTALL_PARTITION" = "system" ] then kpartx -afs "$INSTALL_DEVICE" - ln -s /dev/mapper/* /dev/block/ fi set_subpartitions } set_subpartitions() { - export PMOS_BOOT="$INSTALL_DEVICE"p1 - export ROOT_PARTITION="$INSTALL_DEVICE"p2 + export PMOS_BOOT + PMOS_BOOT=/dev/mapper/"$(busybox basename "$INSTALL_DEVICE")"p1 + export ROOT_PARTITION + ROOT_PARTITION=/dev/mapper/"$(busybox basename "$INSTALL_DEVICE")"p2 } umount_install_partition() { - if mountpoint -q "/$INSTALL_PARTITION/" + if busybox mountpoint -q "/$INSTALL_PARTITION/" then umount /"$INSTALL_PARTITION"/ else diff --git a/aports/main/postmarketos-android-recovery-installer/update-binary b/aports/main/postmarketos-android-recovery-installer/update-binary index 5dde5821..67b9d1de 100644 --- a/aports/main/postmarketos-android-recovery-installer/update-binary +++ b/aports/main/postmarketos-android-recovery-installer/update-binary @@ -28,5 +28,5 @@ fail_info() { # Create working directory mkdir /tmp/postmarketos/ # Extract and start the installer script -unzip "$3" "bin/pmos_install" "bin/pmos_install_functions" "install_options" -d /tmp/postmarketos/ +busybox unzip "$3" "bin/pmos_install" "bin/pmos_install_functions" "install_options" -d /tmp/postmarketos/ /tmp/postmarketos/bin/pmos_install "$2" "$3" || { fail_info ; exit 1 ; } diff --git a/pmb/flasher/__init__.py b/pmb/flasher/__init__.py index fed79cef..54a5c782 100644 --- a/pmb/flasher/__init__.py +++ b/pmb/flasher/__init__.py @@ -18,4 +18,5 @@ along with pmbootstrap. If not, see . """ from pmb.flasher.init import init from pmb.flasher.run import run +from pmb.flasher.variables import variables from pmb.flasher.frontend import frontend diff --git a/pmb/flasher/frontend.py b/pmb/flasher/frontend.py index d8fe4151..88518267 100644 --- a/pmb/flasher/frontend.py +++ b/pmb/flasher/frontend.py @@ -79,6 +79,12 @@ def list_devices(args): def sideload(args): + method = args.flash_method or args.deviceinfo["flash_methods"] + cfg = pmb.config.flashers[method] + + # Install depends + pmb.chroot.apk.install(args, cfg["depends"]) + # Mount the buildroot suffix = "buildroot_" + args.deviceinfo["arch"] mountpoint = "/mnt/" + suffix diff --git a/pmb/flasher/run.py b/pmb/flasher/run.py index feaf228e..201abc20 100644 --- a/pmb/flasher/run.py +++ b/pmb/flasher/run.py @@ -30,30 +30,8 @@ def run(args, action, flavor=None): raise RuntimeError("action " + action + " is not" " configured for method " + method + "!") - _cmdline = args.deviceinfo["kernel_cmdline"] - if "cmdline" in args and args.cmdline: - _cmdline = args.cmdline - - if method == "fastboot": - _partition_system = "system" - else: - _partition_system = args.deviceinfo["flash_heimdall_partition_system"] or "SYSTEM" - if "partition" in args and args.partition: - _partition_system = args.partition - # Variable setup - vars = { - "$BOOT": "/mnt/rootfs_" + args.device + "/boot", - "$FLAVOR": flavor if flavor is not None else "", - "$IMAGE": "/home/user/rootfs/" + args.device + ".img", - "$KERNEL_CMDLINE": _cmdline, - "$PARTITION_KERNEL": args.deviceinfo["flash_heimdall_partition_kernel"] or "KERNEL", - "$PARTITION_INITFS": args.deviceinfo["flash_heimdall_partition_initfs"] or "RECOVERY", - "$PARTITION_SYSTEM": _partition_system, - "$RECOVERY_ZIP": "/mnt/buildroot_" + args.deviceinfo["arch"] + - "/var/lib/postmarketos-android-recovery-installer" - "/pmos-" + args.device + ".zip", - } + vars = pmb.flasher.variables(args, flavor, method) # Run the commands of each action for command in cfg["actions"][action]: diff --git a/pmb/flasher/variables.py b/pmb/flasher/variables.py new file mode 100644 index 00000000..0312cb12 --- /dev/null +++ b/pmb/flasher/variables.py @@ -0,0 +1,46 @@ +""" +Copyright 2017 Oliver Smith + +This file is part of pmbootstrap. + +pmbootstrap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pmbootstrap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pmbootstrap. If not, see . +""" + + +def variables(args, flavor, method): + _cmdline = args.deviceinfo["kernel_cmdline"] + if "cmdline" in args and args.cmdline: + _cmdline = args.cmdline + + if method == "fastboot": + _partition_system = "system" + else: + _partition_system = args.deviceinfo["flash_heimdall_partition_system"] or "SYSTEM" + if "partition" in args and args.partition: + _partition_system = args.partition + + vars = { + "$BOOT": "/mnt/rootfs_" + args.device + "/boot", + "$FLAVOR": flavor if flavor is not None else "", + "$IMAGE": "/home/user/rootfs/" + args.device + ".img", + "$KERNEL_CMDLINE": _cmdline, + "$PARTITION_KERNEL": args.deviceinfo["flash_heimdall_partition_kernel"] or "KERNEL", + "$PARTITION_INITFS": args.deviceinfo["flash_heimdall_partition_initfs"] or "RECOVERY", + "$PARTITION_SYSTEM": _partition_system, + "$RECOVERY_ZIP": "/mnt/buildroot_" + args.deviceinfo["arch"] + + "/var/lib/postmarketos-android-recovery-installer" + "/pmos-" + args.device + ".zip", + } + + return vars diff --git a/pmb/install/recovery.py b/pmb/install/recovery.py index 07929bd0..75ad5b78 100644 --- a/pmb/install/recovery.py +++ b/pmb/install/recovery.py @@ -19,6 +19,7 @@ along with pmbootstrap. If not, see . import logging import pmb.chroot +import pmb.flasher import pmb.helpers.frontend @@ -29,6 +30,8 @@ def create_zip(args, suffix): zip_root = "/var/lib/postmarketos-android-recovery-installer/" rootfs = "/mnt/rootfs_" + args.device flavor = pmb.helpers.frontend._parse_flavor(args) + method = args.deviceinfo["flash_methods"] + vars = pmb.flasher.variables(args, flavor, method) # Install recovery installer package in buildroot pmb.chroot.apk.install(args, @@ -38,23 +41,30 @@ def create_zip(args, suffix): logging.info("(" + suffix + ") create recovery zip") # Create config file for the recovery installer - with open(args.work + "/chroot_" + suffix + "/tmp/install_options", - "w") as install_options: - install_options.write( - "\n".join(['DEVICE="{}"'.format(args.device), - 'FLASH_BOOTIMG="{}"'.format( - str(args.recovery_flash_bootimg).lower()), - 'INSTALL_PARTITION="{}"'.format( - args.recovery_install_partition), - 'CIPHER="{}"'.format(args.cipher), - 'FDE="{}"'.format( - str(args.full_disk_encryption).lower())])) + options = { + "DEVICE": args.device, + "FLAVOR": flavor, + "FLASH_KERNEL": args.recovery_flash_kernel, + "ISOREC": method == "heimdall-isorec", + "KERNEL_PARTLABEL": vars["$PARTITION_KERNEL"], + "INITFS_PARTLABEL": vars["$PARTITION_INITFS"], + "SYSTEM_PARTLABEL": vars["$PARTITION_SYSTEM"], + "INSTALL_PARTITION": args.recovery_install_partition, + "CIPHER": args.cipher, + "FDE": args.full_disk_encryption, + } + + # Write to a temporary file + config_temp = args.work + "/chroot_" + suffix + "/tmp/install_options" + with open(config_temp, "w") as handle: + for key, value in options.items(): + if isinstance(value, bool): + value = str(value).lower() + handle.write(key + "='" + value + "'\n") commands = [ # Move config file from /tmp/ to zip root ["mv", "/tmp/install_options", "install_options"], - # Copy boot.img to zip root - ["cp", rootfs + "/boot/boot.img-" + flavor, "boot.img"], # Create tar archive of the rootfs ["tar", "-pczf", "rootfs.tar.gz", "--exclude", "./home/user/*", "-C", rootfs, "."], diff --git a/pmb/parse/arguments.py b/pmb/parse/arguments.py index f17e62e1..1101ccdc 100644 --- a/pmb/parse/arguments.py +++ b/pmb/parse/arguments.py @@ -216,13 +216,13 @@ def arguments(): install.add_argument("--android-recovery-zip", help="generate TWRP flashable zip", action="store_true", dest="android_recovery_zip") - install.add_argument("--recovery-flash-bootimg", - help="include kernel in recovery flashable zip", - action="store_true", dest="recovery_flash_bootimg") install.add_argument("--recovery-install-partition", default="system", help="partition to flash from recovery," " eg. external_sd", dest="recovery_install_partition") + install.add_argument("--recovery-no-kernel", + help="do not overwrite the existing kernel", + action="store_false", dest="recovery_flash_kernel") # Action: menuconfig / parse_apkbuild menuconfig = sub.add_parser("menuconfig", help="run menuconfig on"