fingerprintd/packaging/APKBUILD
Jorijn van der Graaf b228287c5b A verify nobody answered is not a failure, and the trustlet is not ours to ship
Two things the packaging left behind.

A verify that ran its 600-frame budget without the sensor being touched was
reported to the client as verify-unknown-error. Nothing had gone wrong: nobody
had pressed. It cost three verifications during packaging, each reading as a
broken daemon. fprintd's contract is that a verify runs until the client stops
it, so the frame cap bounds one trustlet scan session rather than the user's
patience, and a window with no press simply runs again. Verified across the
rollover: 600 frames untouched, "still waiting", then a press matching on its
first contact frame in 44 ms.

Presses that happen and never reach a verdict now report verify-retry-scan --
a bad scan, which fprintd has a word for, and not the matcher saying no.

The cost is that an unanswered verify polls every ~200 ms for as long as the
client holds it. The cure is measured and available -- gpio75 is silent at
idle and bursts on contact -- but it would make the IRQ the only way a press
is ever noticed, deleting the poll under every rate this daemon has been
measured at. Noted where the loop waits, not done.

And the trustlet: focal64.mbn is a proprietary OEM-signed blob, so the package
ships a fp6-vendor-blobs manifest fragment instead, the same mechanism
soc-fairphone-fp6-audio uses for the amp config. It needed a new directive
there -- a QTEE image is an ELF header file plus one payload per program
header, not one file -- and reassembly on the phone reproduces the image QTEE
has accepted since August, byte for byte.
2026-09-05 04:01:06 +02:00

111 lines
5.6 KiB
Text

# SPDX-License-Identifier: GPL-3.0-only
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
# Maintainer: Jorijn van der Graaf <jorijnvdgraaf@catcrafts.net>
# Binary packaging: wraps a crafter-build binary cross-compiled per the
# README's "Cross-compiling" section into a proper apk — used by this repo's
# package CI (packaging/build-package.sh, which seds pkgver from
# implementations/main.cpp) and runnable by hand. The source tarball is
# produced by packaging/make-bin-tarball.sh. There is deliberately no
# source-building aport: the build driver is crafter-build, which is not in
# Alpine, so an APKBUILD that compiled from source could not be built by
# anyone but us either.
pkgname=fingerprintd
pkgver=0.1.2
pkgrel=0
pkgdesc="Fingerprint daemon for the Fairphone 6 (FocalTech FT9391 behind QTEE)"
url="https://forgejo.catcrafts.net/Catcrafts/fingerprintd"
arch="aarch64"
license="GPL-3.0-only"
# GLib for the D-Bus interface; libc++ because the binary is a clang/libc++
# C++26 modules build linked dynamically against the phone's own runtime.
#
# fprintd-pam is pam_fprintd, which is the point of the whole daemon: it is
# what turns a matched finger into a login. It is an install_if subpackage
# conditioned on the EXACT version fprintd-pam was built against
# (i:fprintd=1.94.5-r1), so the provides below breaks that condition and apk
# would purge it as no-longer-needed. Depending on it explicitly is what keeps
# it. It has no dependency on fprintd itself, so nothing is being forced.
#
# fp6-vendor-blobs runs the manifest fragment below, which reassembles the
# trustlet out of the stock modem partition on first boot. Without it there is
# no matcher and the unit stays inert on its ConditionPathExists -- so this is
# a real dependency, not a nicety. It is an FP6 device package; so is this.
depends="dbus glib libc++ fprintd-pam fp6-vendor-blobs"
# The versioned provides both satisfies plasma-workspace's fprintd dependency
# — its Users KCM is the fingerprint enrolment UI and speaks exactly this bus
# name — and EXCLUDES the real package, which is required rather than tidy:
# fprintd is D-Bus-activatable, so a client call would otherwise start the
# real daemon and fight for net.reactivated.Fprint. fprintd-pam is a separate
# package that does not depend on fprintd, so PAM keeps working.
#
# The cost, which is real: the fprintd-enroll/-list/-verify/-delete CLIs go
# away with the package. Enrolment then goes through Plasma's Users KCM.
provides="fprintd=$pkgver-r$pkgrel"
# The unit is the deliverable — a daemon holding QTEE's listener table open for
# the life of the boot is not something to start by hand — but abuild wants
# systemd files in their own package, and install_if puts them back on any
# system that has systemd. No OpenRC service: nothing here has ever been run
# under one, and the unit's conditions (the vendor blob, /dev/tee0) are what
# keep the package inert on a phone that cannot use it.
subpackages="$pkgname-systemd"
# nothing is compiled here, and the aarch64 ELF's NEEDED entries must not be
# traced against an x86_64 build host
options="!check !tracedeps"
source="fingerprintd-$pkgver.tar.gz"
package() {
cd "$srcdir/fingerprintd-$pkgver"
install -Dm755 fingerprintd "$pkgdir"/usr/bin/fingerprintd
install -Dm644 fingerprintd.service \
"$pkgdir"/usr/lib/systemd/system/fingerprintd.service
install -Dm644 mnt-persist.mount \
"$pkgdir"/usr/lib/systemd/system/mnt-persist.mount
# enabled by preset, and by an explicit .wants link so a fingerprint
# surviving a reboot never depends on a manual systemctl enable. The
# mount needs neither: fingerprintd.service pulls it in with
# RequiresMountsFor.
install -Dm644 80-fingerprintd.preset \
"$pkgdir"/usr/lib/systemd/system-preset/80-fingerprintd.preset
mkdir -p "$pkgdir"/etc/systemd/system/multi-user.target.wants
ln -s /usr/lib/systemd/system/fingerprintd.service \
"$pkgdir"/etc/systemd/system/multi-user.target.wants/fingerprintd.service
# who may own and call the bus name
install -Dm644 net.reactivated.Fprint.conf \
"$pkgdir"/usr/share/dbus-1/system.d/net.reactivated.Fprint.conf
# replaces fprintd's activation file, which points at /usr/libexec/fprintd
install -Dm644 net.reactivated.Fprint.service \
"$pkgdir"/usr/share/dbus-1/system-services/net.reactivated.Fprint.service
# the action ids fprintd defined; see the file for what enforces them
install -Dm644 net.reactivated.fprint.device.policy \
"$pkgdir"/usr/share/polkit-1/actions/net.reactivated.fprint.device.policy
# the SFS root's directories and its two symlinks into the persist mount
install -Dm644 fingerprintd.tmpfiles.conf \
"$pkgdir"/usr/lib/tmpfiles.d/fingerprintd.conf
# qcomtee -> /dev/tee0
install -Dm644 fingerprintd.modules-load.conf \
"$pkgdir"/usr/lib/modules-load.d/fingerprintd.conf
# the trustlet's configuration, generated by fp6fpcfg.py from the captured
# stock dump — see packaging/README.config.md. Not a user config file:
# the TA discards a file whose configuration_uuid does not match, and the
# two policy keys in it were each forced by a measurement.
install -Dm644 fingerprintd.json \
"$pkgdir"/usr/lib/firmware/fingerprintd.json
# the trustlet is NOT in this package and never will be: it is a
# proprietary OEM-signed blob. This tells fp6-vendor-blobs how to
# reassemble it from the phone's own stock partitions, which is the
# same mechanism soc-fairphone-fp6-audio uses for the amp config.
install -Dm644 20-focal64.manifest \
"$pkgdir"/usr/share/fp6-vendor-blobs/manifest.d/20-focal64.manifest
}
systemd() {
install_if="$pkgname=$pkgver-r$pkgrel systemd"
amove usr/lib/systemd
amove etc/systemd
}