diff --git a/packaging/deploy-dev.sh b/packaging/deploy-dev.sh new file mode 100755 index 0000000..2cab772 --- /dev/null +++ b/packaging/deploy-dev.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# deploy-dev.sh -- bring the dev phone back to a running daemon, from nothing. +# +# packaging/deploy-dev.sh [host] default: fp6usb4 +# +# Run from the repo root on the workstation, after a cross build. Everything the +# daemon needs on the phone that does NOT survive a reboot is put back by this: +# +# /tmp/fingerprintd the cross-built binary +# /tmp/fpenrol.sh fptrial.sh the enrolment and labelled-trial scripts +# /tmp/fplearn.sh the template-learning protocol +# qcomtee.ko loaded /dev/tee0 does not exist until it is +# /dev/sda6 on /mnt/persist the real persist partition, read-write -- +# the daemon's SFS root symlinks into it +# fingerprintd-test the transient unit, learning on +# +# What survives a reboot and is therefore NOT touched: /usr/lib/firmware/ +# qcomtee.ko, /lib/firmware/fingerprintd.json (regenerate with +# fp6fpcfg.py --daemon --verbose and pass --config to refresh it), the SFS +# symlinks under /var/lib/fingerprintd/sfs, and the finger name map. +# +# WHY /tmp. Nothing here is packaged yet; /tmp is deliberate so a reboot leaves +# a stock phone rather than a half-installed daemon. The cost is exactly this +# script, run once after each reboot. +set -eu + +HOST=${1:-fp6usb4} +CONFIG=${CONFIG:-} # optional: a fingerprintd.json to install +SSH="ssh -o ConnectTimeout=8 -o BatchMode=yes $HOST" + +cd "$(dirname "$0")/.." +BIN=$(ls -dt bin/fingerprintd-aarch64-alpine-linux-musl-*/ | head -1)fingerprintd +[ -x "$BIN" ] || { echo "no cross-built binary under bin/; build first" >&2; exit 1; } +echo ">> binary $BIN" +echo " $(sha256sum "$BIN" | cut -c1-16)" + +# The binary goes in under a NEW name and is swapped into place on the phone +# after the unit stops: a running executable cannot be overwritten (ETXTBSY, +# which scp reports only as "dest open: Failure"), and a retry loop turns that +# into six identical failures instead of one clear one. mv replaces the inode, +# which is allowed while the old one is still executing. +# +# The phone also drops off the network transiently, which IS worth retrying. +cp "$BIN" /tmp/fingerprintd.new +i=0 +until scp -o ConnectTimeout=8 -o BatchMode=yes -q \ + /tmp/fingerprintd.new packaging/fpenrol.sh packaging/fptrial.sh packaging/fplearn.sh \ + ${CONFIG:+"$CONFIG"} "$HOST:/tmp/"; do + i=$((i+1)); [ $i -lt 6 ] || { echo "scp failed 6 times" >&2; rm -f /tmp/fingerprintd.new; exit 1; } + echo " scp retry $i"; sleep 5 +done +rm -f /tmp/fingerprintd.new +echo ">> copied" + +$SSH 'set -e +# Stop before the swap so the new binary is what starts, not the old inode. +sudo systemctl stop fingerprintd-test 2>/dev/null || true +sudo mv /tmp/fingerprintd.new /tmp/fingerprintd +sudo chmod +x /tmp/fingerprintd /tmp/fpenrol.sh /tmp/fptrial.sh /tmp/fplearn.sh +if [ -f /tmp/fingerprintd.json ]; then + sudo cp /tmp/fingerprintd.json /lib/firmware/fingerprintd.json + echo ">> config installed" +fi +if ! lsmod | grep -q "^qcomtee"; then + sudo insmod /usr/lib/firmware/qcomtee.ko qseeflow=0 +fi +[ -c /dev/tee0 ] || { echo "no /dev/tee0 after insmod" >&2; exit 1; } +echo ">> qcomtee loaded, /dev/tee0 present" +sudo mkdir -p /mnt/persist +if ! mount | grep -q " /mnt/persist "; then + sudo mount -o rw /dev/sda6 /mnt/persist +fi +mount | grep " /mnt/persist " | grep -q "rw," || { echo "persist not rw" >&2; exit 1; } +echo ">> persist mounted rw" +sudo systemctl stop fingerprintd-test 2>/dev/null || true +sleep 1 +sudo systemd-run --unit=fingerprintd-test --collect \ + /tmp/fingerprintd --daemon --verbose --edge-wake \ + --sfs-root=/var/lib/fingerprintd/sfs --sfs-writable --rpmb-write >/dev/null +printf ">> daemon starting" +# Scope the readiness check to THIS invocation. The journal persists across +# restarts and reboots, so grepping the whole unit history matches the ready +# line of the PREVIOUS run and reports the daemon up while the session is +# still coming up on the worker thread -- which is how a first version of this +# script ran fprintd-list into "device is still starting". +# (No apostrophes in this block: the whole remote script is single-quoted.) +INV=$(systemctl show -p InvocationID --value fingerprintd-test) +log() { sudo journalctl "_SYSTEMD_INVOCATION_ID=$INV" --no-pager -o cat 2>/dev/null; } +i=0 +while [ $i -lt 40 ]; do + if log | grep -q "fingerprintd: ready"; then echo " ready"; break; fi + if log | grep -q "StartFailed\|must run as root\|sensor power-up failed\|cannot open config"; then + echo " FAILED"; log | tail -15; exit 1 + fi + printf "."; sleep 1; i=$((i+1)) +done +[ $i -lt 40 ] || { echo " TIMED OUT"; log | tail -15; exit 1; } +echo ">> $(systemctl is-active fingerprintd-test), owning: $(busctl --system list 2>/dev/null | grep -c net.reactivated.Fprint)" +fprintd-list user 2>&1 | tail -n +2 +echo ">> binary $(sha256sum /tmp/fingerprintd | cut -c1-16) config $(sha256sum /lib/firmware/fingerprintd.json | cut -c1-16)" +' +echo +echo "measurement:" +echo " ssh $HOST 'sudo /tmp/fplearn.sh enrol right-middle-finger'" +echo " ssh $HOST 'sudo /tmp/fplearn.sh base'" +echo " ssh $HOST 'sudo /tmp/fplearn.sh trend'"