STATE moved to 2026-08-09. One instrument is waiting on a finger; everything else about the enrol lifecycle is reachable in RAM today.
5.9 KiB
DUMP — fingerprint, 2026-08-09
Handoff. TASK-44 is the owner and carries the design; this is what moved today and what to do first when you sit down.
What moved
The TA's command protocol is recovered. fpctzappfingerprint is not
stripped — every handler logs __func__ — so its dispatch tables resolve to
real names. Eight targets; the two that matter are 10 (sensor) and
11 (bio), and bio carries the whole lifecycle: begin_enrol, enrol,
end_enrol, identify, get_template_ids, delete_template,
set_active_fingerprint_set, load_empty_db, get_template_db_id.
Full tables, wire format, method: Pixel3Arch/docs/fpc-ta-protocol.md.
Done statically, from ~/pixel3-work/los-vendor/vendor.img with debugfs. No
device, no Android, no Frida. The Frida-tracing plan from earlier in the
session was unnecessary.
It cross-checks against your own work. The router's -201 / -210 /
-211 are INPUT / CONFIG / NOT_INITIALIZED in the table fp-go.py
already carried from the HAL disassembly on 2026-08-01. Two binaries, two
methods, weeks apart, same numbers.
Two labels in TASK-44 were wrong. Sensor command 3 is wakeup_setup
("arm" is right in effect). Command 5 is deep_sleep, not "idle" — the
part is asleep between events, not idling.
Do this first
ssh pixel
sudo ~/fp-finger.py load 120 # or pass a resident app_id
Arms once, then polls target 10 command 1 check_finger_lost at 10 Hz for
two minutes. Touch whenever — no window to hit.
This answers the question TASK-44 has been stuck on since 2026-08-01. Every
prior instrument counted edges and needed a human to vouch that a touch
happened; this one asks the application. A ret that moves only while your
finger is on the reader is the answer.
It brackets each query with the interrupt count, so the call's own edge is in a
separate column from spontaneous ones — the 1444-event trap. If the own
column accounts for everything, the sensor is not talking to you and you will
see it immediately.
If ret never moves, try qualify_capture (10/4) next: the part may only
report finger state during a capture rather than as a standing query.
Then, in order
- RAM-only enrol and identify. 11/6
load_empty_db→ 11/9set_active_fingerprint_set(set id at+12) → 11/0begin_enrol→ 11/1enrolper capture → 11/2end_enrol→ 11/3identify. Nothing persists yet, and nothing here can block. - Persistence. Target 2 only, through a listener. See the safety note.
souveraine-fpd. The daemon. TASK-44 §"Where it plugs in".
Safety, and it is narrow
The application's only persistence is qsee_fts_*, and the call graph says
only targets 2 and 12 can reach it. Targets 10 and 11 cannot, so neither
can block on a listener.
- Safe on the daily driver: all of target 10, all of target 11.
- Not on the daily driver: target 2 (fs) and target 12's
remove_file— these can leave TZ parked, and a parked TZ blocks every QSEECOM caller until a reboot, not just yours. Target 5 is 19 production-test commands with a 529-byte payload and the build manifest listsprodtestlibandsensor_settings; treat it as the destructive group. Both want the spare.
delete_template and load_empty_db are harmless while nothing persists.
They become destructive the moment target 2 works — wire the guard before
the listener, not after.
Also landed
- Five fingerprint tools were phone-only and are now in
Pixel3Arch/tools/:fp-arm.py,fp-bringup.py,fp-go.py,fp-load.py,fp-sweep.py. They had lived only in~on the device since 2026-08-01 and a reprovision would have taken them. The three already tracked still hash-match the phone. - References cloned to
Pixel3Arch/references/biometrics/(gitignored):fprintd,libfprintwithwrobelda/goodix-qseefetched as a branch,sailfish-fpd-community,biometryd,qsee-supplicant,goodix-fp-spi-linux, both wrobelda kernel series, Google's ownfpc1020_platform_tee.candsdm845-b1c1-fingerprint.dtsi, and the extracted TA and HAL. - There is no API to design — fprintd, gazed, sailfish-fpd and biometryd are the same interface four times. TASK-44 maps every call onto a TA command.
- The boot-chain trio (katana / sdm845-payloads / QHEEStub) is a separate
strand:
Pixel3Arch/docs/secure-world-references.md. blueline'shypis Google-signed not QTI-signed, so QHEEStub's precondition holds, but qtestsign only works where firmware secure boot is off — so EL2 is per-boot over USB, never persistent.bootxblis the piece worth having now; it turns a broken boot chain from a brick into a recovery.
Traps recorded today
- Do not blind-dump
/sys/bus/nvmem/devices/qfprom0/nvmemon a live phone. Did it, andcdc_ncmtransmit-queue watchdogs and a dead tether followed. Possibly coincident with the known stale-usb0 hijack — not separable after the fact, and not worth separating. The fuse question belongs in EDL, on a device that is not the daily driver. - A call graph that loses jump-table case blocks reports no SPI anywhere.
That is how the bug announces itself; the corrected graph resolves
qsee_spi_*for exactly the sensor commands. Recorded in the protocol doc because the next session will rebuild this graph. llvm-objdump22 has no-b binary. Useaarch64-linux-gnu-objdump -D -b binary -m aarch64.
Open, and honest about it
- Attribution — the one measurement above. Needs a finger.
- Whether enrolment demands a Gatekeeper-signed
hw_auth_token(target 3). It would return an error rather than block, so it costs a result, not a reboot. linux-firmwarecarries no fingerprint TA on sdm845, sm8250 or sm8150. TAs are per-device extracts, so this can be enabled on a phone whose vendor image you hold and cannot be packaged for anyone else. Say so out loud rather than discovering it at release.