From 5f754e3e641aab79a9d360cc6e3eac695334af81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20Sz=C3=B6ll=C5=91si?= Date: Thu, 24 Aug 2017 23:07:36 +0200 Subject: [PATCH] Recovery installer zip (#404) Supports flashing with TWRP and other Android recovery OS through adb sideload, as well as exporting a generated recovery zip file. See also: https://github.com/postmarketOS/pmbootstrap/wiki/deviceinfo_flash_methods#recovery-mode-adb --- .../APKBUILD | 33 +++++++ .../build_zip.sh | 52 ++++++++++ .../pmos_install | 86 ++++++++++++++++ .../pmos_install_functions | 98 +++++++++++++++++++ .../pmos_setpw | 29 ++++++ .../update-binary | 31 ++++++ main/postmarketos-mkinitfs/APKBUILD | 6 +- main/postmarketos-mkinitfs/init_functions.sh | 2 +- 8 files changed, 333 insertions(+), 4 deletions(-) create mode 100644 main/postmarketos-android-recovery-installer/APKBUILD create mode 100644 main/postmarketos-android-recovery-installer/build_zip.sh create mode 100755 main/postmarketos-android-recovery-installer/pmos_install create mode 100755 main/postmarketos-android-recovery-installer/pmos_install_functions create mode 100755 main/postmarketos-android-recovery-installer/pmos_setpw create mode 100644 main/postmarketos-android-recovery-installer/update-binary diff --git a/main/postmarketos-android-recovery-installer/APKBUILD b/main/postmarketos-android-recovery-installer/APKBUILD new file mode 100644 index 000000000..cd07925b0 --- /dev/null +++ b/main/postmarketos-android-recovery-installer/APKBUILD @@ -0,0 +1,33 @@ +pkgname=postmarketos-android-recovery-installer +pkgver=0.0.1 +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" +source="build_zip.sh + update-binary + pmos_install + pmos_install_functions + pmos_setpw" +arch="noarch" +license="GPL3" + +package() { + install -Dm755 "$srcdir/build_zip.sh" \ + "$pkgdir/sbin/build-recovery-zip" + mkdir -p "$pkgdir/var/lib/postmarketos-android-recovery-installer/META-INF/com/google/android/" + install -Dm644 "$srcdir"/update-binary \ + "$pkgdir/var/lib/postmarketos-android-recovery-installer/META-INF/com/google/android/update-binary" + mkdir "$pkgdir/var/lib/postmarketos-android-recovery-installer/bin/" + for file in pmos_install pmos_install_functions pmos_setpw; do + install -Dm755 "$srcdir/$file" \ + "$pkgdir/var/lib/postmarketos-android-recovery-installer/bin/$file" + done + mkdir "$pkgdir/var/lib/postmarketos-android-recovery-installer/lib/" +} +sha512sums="9c7a90965aeb7f19ac166282066063510eeba6691ae695b2821e1a9e050463378c56492a27b3bfd4c8155380e6f24adc558dd0c98fc308ee7335b00c7b12fc0b build_zip.sh +874d7505f9940d98a67fd8e5881ab0b93ae9fd0c46d7f4004468a2e9bbe4853f4bf6db64380c27684a66ebbd45ebe3399219b3910799de24003b8399ab2a4497 update-binary +5647a089c95d291d5662bbe6931a01f8591823d63b0226832897a046f351121c2c5d6ebfc83dcf9762ac50774920393fea37c05a92f2079e9688d6fe58711e49 pmos_install +dba3da4d2c18a480fda3bda233052f946bfd5a5f4fe05115341d4dc1466519584930e116719c5338ef4309a51dfea7d2e531ed133723f59c8d6d0c5a4f73a26b pmos_install_functions +1969a467bc1e0f04ed445dd78db4eb1ad77b769a6e04c35211ad2c45cb8293243f864e499cdecf6016292d1accb26e6f62073b2afab023a20a79e0ea3dc15bd9 pmos_setpw" diff --git a/main/postmarketos-android-recovery-installer/build_zip.sh b/main/postmarketos-android-recovery-installer/build_zip.sh new file mode 100644 index 000000000..59d342855 --- /dev/null +++ b/main/postmarketos-android-recovery-installer/build_zip.sh @@ -0,0 +1,52 @@ +#!/bin/ash + +# Copyright 2017 Attila Szöllősi +# +# This file is part of postmarketos-android-recovery-installer. +# +# postmarketos-android-recovery-installer 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. +# +# postmarketos-android-recovery-installer 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 postmarketos-android-recovery-installer. If not, see . + +set -e + +# Copy files to the destination specified +# $1: files +# $2: destination +copy_files() +{ + for file in $1; do + filename=$(basename "$file") + install -Dm755 "$file" "$2"/"$filename" + done +} + +check_whether_exists() +{ + if [ ! -e "$1" ] + then + echo "$1 not found" + return 1 + fi +} + +# shellcheck disable=SC1091 +. ./install_options + +BINARIES="/sbin/cryptsetup /sbin/kpartx /usr/sbin/parted /usr/sbin/partprobe" +# shellcheck disable=SC2086 +LIBRARIES=$(lddtree -l $BINARIES | awk '/lib/ {print}' | sort -u) +copy_files "$BINARIES" bin/ +copy_files "$LIBRARIES" lib/ +check_whether_exists rootfs.tar.gz +[ "$FLASH_BOOT" = "true" ] && check_whether_exists boot.img +zip -0 -r "pmos-$DEVICE.zip" . diff --git a/main/postmarketos-android-recovery-installer/pmos_install b/main/postmarketos-android-recovery-installer/pmos_install new file mode 100755 index 000000000..20c062141 --- /dev/null +++ b/main/postmarketos-android-recovery-installer/pmos_install @@ -0,0 +1,86 @@ +#!/sbin/ash + +# Copyright 2017 Attila Szöllősi +# +# This file is part of postmarketos-android-recovery-installer. +# +# postmarketos-android-recovery-installer 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. +# +# postmarketos-android-recovery-installer 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 postmarketos-android-recovery-installer. If not, see . + +# shellcheck source=pmos_install_functions +. /tmp/postmarketos/bin/pmos_install_functions "$1" "$2" +# shellcheck source=/dev/null +. "$WORKING_DIR"/install_options + +exec > "$WORKING_DIR"/pmos.log 2>&1 +set -ex + +ui_print "postmarketOS recovery installer" + +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" +mkdir /lib +ui_print "Symlinking .so files to /lib/..." +ln -s "$WORKING_DIR"/lib/* /lib/ +ui_print "Unmounting /$INSTALL_PARTITION..." +umount_install_partition +ui_print "Creating partition table on $INSTALL_DEVICE..." +# parted returns nonzero even when command executed successfully +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 + ui_print "Initializing LUKS device..." + cryptsetup luksFormat --use-urandom -c "$CIPHER" -q "$ROOT_PARTITION" "$WORKING_DIR"/lukskey + ui_print "Opening LUKS partition..." + cryptsetup luksOpen -d "$WORKING_DIR"/lukskey "$ROOT_PARTITION" pm_crypt + ui_print "Formatting LUKS partition..." + make_ext4fs -L 'pmOS_root' /dev/mapper/pm_crypt + ui_print "Mounting LUKS partition..." + mount -t ext4 -rw /dev/mapper/pm_crypt /"$INSTALL_PARTITION" +else + ui_print "Formatting root partition..." + make_ext4fs -L 'pmOS_root' "$ROOT_PARTITION" + ui_print "Mounting root partition..." + mount -t ext4 -rw "$ROOT_PARTITION" /"$INSTALL_PARTITION" +fi +ui_print "Formatting pmOS_boot..." +mkfs.ext2 -q -L 'pmOS_boot' "$PMOS_BOOT" +ui_print "Mounting pmOS_boot..." +mkdir /"$INSTALL_PARTITION"/boot +mount -t ext2 -rw "$PMOS_BOOT" /"$INSTALL_PARTITION"/boot || { + ui_print "Failed to format/mount ext2 partition." + ui_print "Trying ext4..." + make_ext4fs -L 'pmOS_boot' "$PMOS_BOOT" + mount -t ext4 -rw "$PMOS_BOOT" /"$INSTALL_PARTITION"/boot +} +ui_print "Installing rootfs..." +tar -xf rootfs.tar.gz -C /"$INSTALL_PARTITION" +if [ "$FLASH_BOOTIMG" = "true" ] +then + ui_print "Flashing boot.img..." + dd if=boot.img of="$BOOT" +fi +if [ "$FDE" = "true" ] +then + ui_print "Creating a symlink for password setting script in /sbin/..." + ln -s "$WORKING_DIR"/bin/pmos_setpw /sbin/ + ui_print "Do not forget to add a password to the LUKS partition!" + ui_print "Run the command: pmos_setpw from the terminal/adb shell!" +fi +ui_print "Installation done." diff --git a/main/postmarketos-android-recovery-installer/pmos_install_functions b/main/postmarketos-android-recovery-installer/pmos_install_functions new file mode 100755 index 000000000..688046baa --- /dev/null +++ b/main/postmarketos-android-recovery-installer/pmos_install_functions @@ -0,0 +1,98 @@ +#!/sbin/ash + +# Copyright 2017 Attila Szöllősi +# +# This file is part of postmarketos-android-recovery-installer. +# +# postmarketos-android-recovery-installer 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. +# +# postmarketos-android-recovery-installer 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 postmarketos-android-recovery-installer. If not, see . + +export OUTFD=$1 +export ZIP=$2 +export WORKING_DIR="/tmp/postmarketos" +export PATH=$PATH:"$WORKING_DIR"/bin + +# shellcheck source=/dev/null +. "$WORKING_DIR"/install_options + +# taken from https://github.com/Debuffer-XDA/Gov-Tuner/blob/master/META-INF/com/google/android/update-binary +# Copyright (c) 2016 - 2017 Debuffer +ui_print() { + echo -n -e "ui_print $1\n" > /proc/self/fd/"$OUTFD" + echo -n -e "ui_print\n" > /proc/self/fd/"$OUTFD" +} + +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)") + ;; + "external_sd") + _INSTALL_DEVICE=$(readlink -fn "$(awk '/^\/external_sd/ {print $4}' /etc/recovery.fstab)") + ;; + *) + echo "No support for flashing $INSTALL_PARTITION." + return 1 + ;; + esac + if [ ! -z "$_INSTALL_DEVICE" ] + then + echo "install device found at $_INSTALL_DEVICE" + export INSTALL_DEVICE=$_INSTALL_DEVICE + else + echo "Couldn't find /$INSTALL_PARTITION/ in fstab." + return 1 + fi + _BOOT=$(awk '/^\/boot/ {print $3}' /etc/recovery.fstab) + if [ ! -z "$_BOOT" ] + then + echo "boot partition found at $_BOOT" + export BOOT=$_BOOT + else + echo "Couldn't find /boot/ in fstab." + return 1 + fi +} + +partition_install_device() { + for command in "mktable msdos" \ + "mkpart primary ext2 2048s 100M" \ + "mkpart primary 100M 100%" \ + "set 1 boot on" + do + parted -s "$INSTALL_DEVICE" "$command" + done + partprobe + 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 +} + +umount_install_partition() { + if mountpoint -q "/$INSTALL_PARTITION/" + then + umount /"$INSTALL_PARTITION"/ + else + echo 'Continuing...' + return 0 + fi +} diff --git a/main/postmarketos-android-recovery-installer/pmos_setpw b/main/postmarketos-android-recovery-installer/pmos_setpw new file mode 100755 index 000000000..7da6ff21b --- /dev/null +++ b/main/postmarketos-android-recovery-installer/pmos_setpw @@ -0,0 +1,29 @@ +#!/sbin/ash -e + +# Copyright 2017 Attila Szöllősi +# +# This file is part of postmarketos-android-recovery-installer. +# +# postmarketos-android-recovery-installer 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. +# +# postmarketos-android-recovery-installer 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 postmarketos-android-recovery-installer. If not, see . + +# shellcheck source=pmos_install_functions +. /tmp/postmarketos/bin/pmos_install_functions + +extract_partition_table +set_subpartitions +echo "Set the password of the encrypted rootfs!" +cryptsetup luksAddKey -d "$WORKING_DIR"/lukskey "$ROOT_PARTITION" +# Remove temporary keyfile +cryptsetup luksRemoveKey "$ROOT_PARTITION" "$WORKING_DIR"/lukskey +echo "Successfully added key to the LUKS device." diff --git a/main/postmarketos-android-recovery-installer/update-binary b/main/postmarketos-android-recovery-installer/update-binary new file mode 100644 index 000000000..483ca7d3d --- /dev/null +++ b/main/postmarketos-android-recovery-installer/update-binary @@ -0,0 +1,31 @@ +#!/sbin/ash + +# Copyright 2017 Attila Szöllősi +# +# This file is part of postmarketos-android-recovery-installer. +# +# postmarketos-android-recovery-installer 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. +# +# postmarketos-android-recovery-installer 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 postmarketos-android-recovery-installer. If not, see . + +# Print fail information +OUTFD=$2 +fail_info() { + FAIL_MSG="Failed. Check /tmp/postmarketos/pmos.log for more info!" + echo -n -e "ui_print $FAIL_MSG\n" > /proc/self/fd/"$OUTFD" + echo -n -e "ui_print\n" > /proc/self/fd/"$OUTFD" +} +# 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/ +/tmp/postmarketos/bin/pmos_install "$2" "$3" || { fail_info ; exit 1 ; } diff --git a/main/postmarketos-mkinitfs/APKBUILD b/main/postmarketos-mkinitfs/APKBUILD index 7bf9a3f52..d442acb36 100644 --- a/main/postmarketos-mkinitfs/APKBUILD +++ b/main/postmarketos-mkinitfs/APKBUILD @@ -1,6 +1,6 @@ pkgname=postmarketos-mkinitfs -pkgver=0.3.3 -pkgrel=6 +pkgver=0.3.4 +pkgrel=0 pkgdesc="Tool to generate initramfs images for postmarketOS" url="https://github.com/postmarketOS" # multipath-tools: kpartx @@ -26,5 +26,5 @@ package() { mkdir -p "$pkgdir/etc/postmarketos-mkinitfs/hooks/" } sha512sums="3d0215d61a34e846c6c3e4ff1911742a620cd1c6ff1de3cf26eaa4cb7643467da72bf9abc6a53992cc750bb76340be820149b25b806152b70fc0d40e0f8aa310 init.sh.in -2331fe9a89ba58348b41fbfdeb6f4daeff3f6ef161d1b7582c3e900baba377fa9411efa0b052ea5c2ae22f75bc48f6b8f38dafad0bd836a0319906e70482898c init_functions.sh +a47398cdbb5e68a34086038cf6d72df91f6e58dcae7ff1ea8a375cd44f21e4573a944122ca5a32dda7b002bb14ec5826435edd2512c3db198dc9c0c3756e3cbe init_functions.sh ef1481ef45e786486fb8e9939f756afb1d873a92546468d3dda3065ef46404be7e9847ab1f630fa6cf3e4ab99bdb116401093bbb1bbc882ea85ea824cdf7e389 mkinitfs.sh" diff --git a/main/postmarketos-mkinitfs/init_functions.sh b/main/postmarketos-mkinitfs/init_functions.sh index b31980b07..cf5c2a83a 100644 --- a/main/postmarketos-mkinitfs/init_functions.sh +++ b/main/postmarketos-mkinitfs/init_functions.sh @@ -105,7 +105,7 @@ mount_boot_partition() { loop_forever fi echo "Mount boot partition ($partition)" - mount -r -t ext2 "$partition" /boot + mount -r "$partition" /boot } # $1: initramfs-extra path