diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index ea5f6b0..fa00071 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -50,8 +50,8 @@ jobs: # the FP6 patches to the next upstream version bump. Requires the # PACKAGE_TOKEN repo secret (catbot account, package:write scope); # skips quietly until it exists. 409 = same version already published. - # imsd and fingerprintd are skipped: build.sh 3b took them FROM the - # registry (re-signed for the chroot), so they are not ours to publish. + # imsd is skipped: build.sh 3b took it FROM the registry (re-signed + # for the chroot), so it is not ours to publish. - name: Publish packages to the apk registry env: PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }} @@ -65,7 +65,7 @@ jobs: for f in /home/build/.local/var/pmbootstrap/packages/*/aarch64/*.apk; do [ -e "$f" ] || continue case "$(basename "$f")" in - imsd-*|fingerprintd-*) echo "registry-sourced, not republished: $(basename "$f")"; continue ;; + imsd-*) echo "registry-sourced, not republished: $(basename "$f")"; continue ;; esac found=1 code=$(curl -s -o /dev/null -w '%{http_code}' \ diff --git a/README.md b/README.md index e94b37f..fdd08a3 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,7 @@ Maintained by [Jorijn van der Graaf](https://catcrafts.net/about) Everything on the `combined-stable` branch: display, touch, wifi, cellular data, NFC (reader), speaker audio, microphone, IMU, magnetometer, barometer, -ambient light/proximity, fingerprint unlock through -[fingerprintd](https://forgejo.catcrafts.net/Catcrafts/fingerprintd), plus -VoLTE calls (both directions) through imsd. +ambient light/proximity plus VoLTE calls (both directions) through imsd. ## Flashing @@ -51,26 +49,4 @@ Find it in a stock-firmware capture or your carrier's IMS documentation, then `systemctl restart imsd` (the service is enabled at boot and waits for this file to exist). See the [imsd README](https://forgejo.catcrafts.net/Catcrafts/imsd) for the full -variable reference and carrier assumptions. - -## Fingerprint - -Enrol under **Settings → Users** (Plasma's own fingerprint page; the `fprintd` -command-line tools are not installed, fingerprintd replaces that package). -**Hold** the finger on the sensor for each of the ~20 presses rather than -tapping it; a held press is what the matcher was measured on. - -Two things to know: - -- The lock screen listens for a finger for **60 seconds after it appears**. - A press after that reaches nothing and looks like a dead sensor. Lock and - unlock again to re-arm it. -- The matcher is the phone's own proprietary trustlet, reassembled from the - stock modem partition on first boot and never shipped by us. Templates are - stored on the Android `persist` partition, sealed to the same hardware - anti-rollback counter stock Android uses. Whether fingerprints enrolled under - stock Android survive a return to it after using this has **not** been - tested. - -A finger can also run something in your session on a match -(`~/.config/fingerprintd/fingers.conf`, see the fingerprintd README). +variable reference and carrier assumptions. \ No newline at end of file diff --git a/aports/device/fp6-vendor-blobs/APKBUILD b/aports/device/fp6-vendor-blobs/APKBUILD index 8dc7a5b..6cd43ae 100644 --- a/aports/device/fp6-vendor-blobs/APKBUILD +++ b/aports/device/fp6-vendor-blobs/APKBUILD @@ -14,7 +14,7 @@ maintainer="Jorijn van der Graaf " pkgname=fp6-vendor-blobs pkgver=1 -pkgrel=2 +pkgrel=1 pkgdesc="On-device extraction of vendor blobs from the stock Android partitions" url="https://forgejo.catcrafts.net/Catcrafts/fp6-img" arch="noarch" diff --git a/aports/device/fp6-vendor-blobs/fp6-vendor-blobs-extract b/aports/device/fp6-vendor-blobs/fp6-vendor-blobs-extract index 1289b21..4239697 100644 --- a/aports/device/fp6-vendor-blobs/fp6-vendor-blobs-extract +++ b/aports/device/fp6-vendor-blobs/fp6-vendor-blobs-extract @@ -10,7 +10,6 @@ # processed in sorted order; '#' comments and blank lines ignored: # # file -# mbn # rebind # # file: mount the first available listed partition READ-ONLY (ext4 also @@ -21,16 +20,6 @@ # unverified blob is never installed and a missing one never silently # skipped. Dests that already exist are left alone (no hashing: a # deliberately replaced file stays). -# mbn: the same, for a Qualcomm trustlet, which is not shipped as one file. -# QTEE images live in the modem partition's image/ as an ELF header+hashes -# file (.mdt) plus one payload per program header (.b00, .b01, -# ...), and the loader wants them written back at each segment's p_offset. -# Reassembly is therefore not a concatenation: segments are page aligned -# but not contiguous, gaps stay zero, and two segments may share an offset -# (focal64 has two such pairs), so they are written in index order and the -# later one wins. Same guarantees as file: the sha256 is of the reassembled -# image, a mismatch tries the next partition, and an unverified image is -# never installed. # rebind: if this fragment's run extracted at least one file, unbind and # re-probe on so the consuming driver picks the file up # in the same boot. Unconditional on purpose: a still-bound consumer may @@ -114,90 +103,6 @@ mount_part() { MNT_PART=$1 } -# Little-endian scalars out of an ELF header. aarch64 is little endian and so -# is the image, so od's host order is the right one. -u64() { od -An -tu8 -j "$2" -N 8 "$1" | tr -d ' '; } -u16() { od -An -tu2 -j "$2" -N 2 "$1" | tr -d ' '; } - -# Reassemble /.mdt + .b0N into a flat image at . Mirrors -# utilities/ta-analysis/reassemble.py in the fp6 bring-up repo, which is where -# the format was worked out and where the known-good hash comes from. -# POSIX sh has no locals, so these names are deliberately distinct from -# extract_mbn's: reassemble() taking rdir= would rewrite its CALLER's copy to -# the mount path, and the next partition in the retry loop would then be -# searched at $MNT/$MNT/... -reassemble() { # - mdir=$1 mname=$2 mout=$3 - mdt="$mdir/$mname.mdt" - [ -f "$mdt" ] || return 1 - phoff=$(u64 "$mdt" 32) phentsize=$(u16 "$mdt" 54) phnum=$(u16 "$mdt" 56) - [ -n "$phoff" ] && [ -n "$phentsize" ] && [ -n "$phnum" ] || return 1 - [ "$phnum" -gt 0 ] 2>/dev/null || return 1 - - # The image is as long as the furthest segment reaches; everything no - # segment covers stays zero. - total=0 i=0 - while [ "$i" -lt "$phnum" ]; do - o=$((phoff + i * phentsize)) - pfsz=$(u64 "$mdt" $((o + 32))) - if [ "$pfsz" -gt 0 ]; then - poff=$(u64 "$mdt" $((o + 8))) - [ $((poff + pfsz)) -gt "$total" ] && total=$((poff + pfsz)) - fi - i=$((i + 1)) - done - [ "$total" -gt 0 ] || return 1 - : > "$mout" || return 1 - truncate -s "$total" "$mout" || return 1 - - i=0 - while [ "$i" -lt "$phnum" ]; do - o=$((phoff + i * phentsize)) - pfsz=$(u64 "$mdt" $((o + 32))) - if [ "$pfsz" -gt 0 ]; then - poff=$(u64 "$mdt" $((o + 8))) - seg=$(printf '%s/%s.b%02d' "$mdir" "$mname" "$i") - [ -f "$seg" ] || { log "$mname: segment $i missing"; return 1; } - # dd seeks in whole blocks, which is only correct because - # every p_offset in these images is page aligned. Refuse - # rather than silently misplace a segment if that changes. - [ $((poff % 4096)) -eq 0 ] || { - log "$mname: segment $i offset $poff is not page aligned" - return 1 - } - dd if="$seg" of="$mout" bs=4096 seek=$((poff / 4096)) \ - conv=notrunc 2>/dev/null || return 1 - fi - i=$((i + 1)) - done - return 0 -} - -extract_mbn() { # - parts=$1 rdir=$2 rname=$3 dest=$4 want=$5 - for part in $(echo "$parts" | tr ',' ' '); do - mount_part "$part" || { log "$part: not mountable, trying next"; continue; } - [ -f "$MNT/$rdir/$rname.mdt" ] || { log "$part: no $rdir/$rname.mdt, trying next"; continue; } - tmp="$dest.fp6-extract.$$" - mkdir -p "${dest%/*}" || fail "cannot create ${dest%/*}" - if ! reassemble "$MNT/$rdir" "$rname" "$tmp"; then - rm -f "$tmp" - log "$part: reassembling $rname failed, trying next" - continue - fi - got=$(sha256sum "$tmp" | awk '{print $1}') - if [ "$got" != "$want" ]; then - rm -f "$tmp" - log "$part:$rdir/$rname sha256 $got != expected, trying next" - continue - fi - chmod 644 "$tmp" && mv "$tmp" "$dest" || { rm -f "$tmp"; fail "installing $dest failed"; } - log "reassembled $part:$rdir/$rname.{mdt,b0N} -> $dest" - return 0 - done - fail "no listed partition ($parts) yields $rname with sha256 $want - $dest NOT installed" -} - extract() { # parts=$1 src=$2 dest=$3 want=$4 for part in $(echo "$parts" | tr ',' ' '); do @@ -250,11 +155,8 @@ fi missing= for f in "$MANIFEST_DIR"/*.manifest; do [ -e "$f" ] || continue - while read -r kind a b c d e; do - case "$kind" in - file) [ -e "$c" ] || missing=1 ;; - mbn) [ -e "$d" ] || missing=1 ;; - esac + while read -r kind _ _ dest _; do + [ "$kind" = file ] && [ ! -e "$dest" ] && missing=1 done < "$f" done [ -z "$missing" ] && exit 0 @@ -263,7 +165,7 @@ for f in "$MANIFEST_DIR"/*.manifest; do [ -e "$f" ] || continue extracted= rebinds= - while read -r kind a b c d e; do + while read -r kind a b c d; do case "$kind" in ''|'#'*) ;; file) @@ -272,12 +174,6 @@ for f in "$MANIFEST_DIR"/*.manifest; do extract "$a" "$b" "$c" "$d" = 1-r2, both -# built in this run. 0.2.3: 0.2.2 (enrol, unlock, agent, actions) + the -# versioned blobs dependency + a post-upgrade daemon restart. -FPD_VERSION=0.2.3-r0 -FPD_SHA256=" -3e28f0c1a9a844592ab6878b2dfc0d8f91674549e44bdc1652e7d7d029de1765 fingerprintd-0.2.3-r0.apk -0cc46eba5c6c77d5bb54cd9f0e2902f7644720f9c98153062ffa33e19ca36889 fingerprintd-systemd-0.2.3-r0.apk -6dfdbc6f971ba4b8f811f828e5868869c7d71fea6c7045e2bffd51bf2736c040 fingerprintd-agent-0.2.3-r0.apk -" PMAPORTS_REPO=https://gitlab.postmarketos.org/postmarketOS/pmaports.git cd "$(dirname "$0")" @@ -229,7 +215,7 @@ aports = $WORK/pmaports device = fairphone-fp6 ui = plasma-mobile systemd = always -extra_packages = soc-fairphone-fp6-audio,callaudioshim,imsd,fingerprintd,fingerprintd-systemd,fingerprintd-agent,fp6-device-tweaks,fp6-charging-mode,catcrafts-fp6-repo,postmarketos-base-ui-audio-backend-pipewire,pipewire-pulse,pipewire-echo-cancel +extra_packages = soc-fairphone-fp6-audio,callaudioshim,imsd,fp6-device-tweaks,fp6-charging-mode,catcrafts-fp6-repo,postmarketos-base-ui-audio-backend-pipewire,pipewire-pulse,pipewire-echo-cancel EOF # All four source tarballs are generated locally above, so every checksum @@ -258,9 +244,9 @@ retry "build modemmanager" pmbootstrap $NOCROSS build --arch aarch64 modemmanage # patched -r2 exists for the publish step even if the install set resolves # it before the overlay is considered. retry "build libcamera" pmbootstrap $NOCROSS build --arch aarch64 libcamera -# --- 3b. imsd + fingerprintd: the published apks, not local builds ----------- -# Each repo's package CI is the only producer of its apk; the image installs -# the exact registry package users later get via 'apk upgrade'. +# --- 3b. imsd: the published apk, not a local build -------------------------- +# The imsd repo's package CI is the only producer of the imsd apk; the image +# installs the exact registry package users later get via 'apk upgrade'. # pmbootstrap has no knob for a third-party repository, and after the main # 'apk add' it re-adds every package found in its local packages dir BY FILE # PATH — which makes apk verify the package's own signature, and registry @@ -270,21 +256,13 @@ retry "build libcamera" pmbootstrap $NOCROSS build --arch aarch64 libcamera # stay byte-identical, so the identity checksum equals the registry's), drop # into the local packages dir, re-index. The abuild key exists because the # builds above initialized the buildroot. -REG_DL="$WORK/registry-apks" -rm -rf "$REG_DL" -mkdir -p "$REG_DL" -for _f in "imsd-$IMSD_VERSION.apk" "imsd-systemd-$IMSD_VERSION.apk" \ - "fingerprintd-$FPD_VERSION.apk" "fingerprintd-systemd-$FPD_VERSION.apk" \ - "fingerprintd-agent-$FPD_VERSION.apk"; do - # every fetched file must have a pin: 'grep .' below drops empty lines, - # so an empty pin list would otherwise pass the check with nothing checked - printf '%s\n' "$IMSD_SHA256" "$FPD_SHA256" | grep -q " $_f\$" || { - echo "no sha256 pin for $_f - add it to IMSD_SHA256/FPD_SHA256" >&2 - exit 1 - } - retry "fetch $_f" curl -fsSL -o "$REG_DL/$_f" "$IMSD_REGISTRY/aarch64/$_f" +IMSD_DL="$WORK/imsd-apk" +rm -rf "$IMSD_DL" +mkdir -p "$IMSD_DL" +for _f in "imsd-$IMSD_VERSION.apk" "imsd-systemd-$IMSD_VERSION.apk"; do + retry "fetch $_f" curl -fsSL -o "$IMSD_DL/$_f" "$IMSD_REGISTRY/aarch64/$_f" done -(cd "$REG_DL" && printf '%s\n' "$IMSD_SHA256" "$FPD_SHA256" | grep . | sha256sum -c -) +(cd "$IMSD_DL" && printf '%s\n' "$IMSD_SHA256" | grep . | sha256sum -c -) ABUILD_KEY=$(echo "$WORKDIR"/config_abuild/*.rsa) if [ ! -f "$ABUILD_KEY" ]; then echo "expected exactly one abuild key in $WORKDIR/config_abuild" >&2 @@ -293,9 +271,9 @@ fi # abuild-keygen ran inside the chroot as pmbootstrap's user (uid 12345), so # the key is 0600 to that uid and unreadable here (run 49 died on exactly # this); sign from a private copy taken via sudo, then drop it. -KEYCOPY="$REG_DL/abuild-key.rsa" +KEYCOPY="$IMSD_DL/abuild-key.rsa" sudo install -m 0600 -o "$(id -un)" "$ABUILD_KEY" "$KEYCOPY" -for _f in "$REG_DL"/*.apk; do +for _f in "$IMSD_DL"/*.apk; do python3 ./apk-resign.py "$_f" "$KEYCOPY" "$(basename "$ABUILD_KEY").pub" done rm -f "$KEYCOPY" @@ -308,11 +286,11 @@ if [ ! -d "$PKGDIR" ]; then echo "$PKGDIR missing - the package builds above should have created it" >&2 exit 1 fi -for _f in "$REG_DL"/*.apk; do +for _f in "$IMSD_DL"/*.apk; do sudo install -m 0644 -o "$(stat -c %u "$PKGDIR")" -g "$(stat -c %g "$PKGDIR")" \ "$_f" "$PKGDIR/$(basename "$_f")" done -rm -f "$REG_DL"/*.apk +rm -f "$IMSD_DL"/*.apk pmbootstrap index # --- 4. build the image ------------------------------------------------------- @@ -345,7 +323,6 @@ cp README.md install.sh "$STAGE/fp6-img/" echo "built: $(date -u +%Y-%m-%dT%H:%M:%SZ)" echo "default login: user / 147147 (same as official postmarketOS images)" echo "imsd: $IMSD_REGISTRY imsd-$IMSD_VERSION (registry package, sha256-pinned)" - echo "fingerprintd: $IMSD_REGISTRY fingerprintd-$FPD_VERSION (registry package, sha256-pinned)" } > "$STAGE/fp6-img/build-info.txt" # sums of the extracted contents (cd "$STAGE/fp6-img" && sha256sum -- * > sha256sums.txt)