fingerprintd's own code now talks to QTEE. On the phone:
root object on /dev/tee0
client env obtained (uid 0, 13-byte credentials)
QSEECOM-compat app loader (UID 122) opened
The credentials object is ours rather than libqcomtee's. Upstream's exists only
to build a thirteen-byte CBOR map and drags in QCBOR to do it, so
packaging/make-libqcomtee.sh compiles the two sources that matter and drops
credentials_obj.c entirely -- nothing else references it, and the library then
has no dependency beyond libc. The map is built in Fingerprintd:Tee where it is
pinned byte-for-byte against the string verified on-device, and the object's
two-op read protocol is served here.
Three interop details, all of which cost a build cycle:
* libqcomtee's headers carry no extern "C" guard, having only ever been
consumed from C, so everything came out C++-mangled. They also pull in
<stdatomic.h> and <stdio.h>, which under libc++ drag in templates that may
not appear inside extern "C" -- so those are included first.
* tee_call_t's second parameter is unsigned long on glibc and int on musl.
The native build is glibc and the phone is musl; both forms are compiled.
* On the callback path a UBUF_OUTPUT param arrives with addr = NULL. The
dispatcher supplies the buffer, so a handler POINTS the param at its own
storage rather than writing through the incoming address. Doing the latter
is a null dereference that takes the supplicant thread with it, which is
how the first run against real QTEE ended -- with the correct behaviour
already spelled out in the module comment above the code that ignored it.
That comment now says so in as many words.
packaging/make-sysroot.sh populates a minimal Alpine aarch64 rootfs with
apk-tools-static, so a cross build needs no root, no qemu and no phone. Adapted
from imsd's, plus glib-dev for the bus layer that is coming.
Building against a real Alpine sysroot means the binary links dynamically
against the phone's own musl and libc++ -- libc++, libc++abi, libunwind and
libgcc_s are all already on pmOS. The harness this daemon replaces had to be
built -static, but only because it was built with the host's glibc toolchain;
that constraint was never about the target.
The pipeline is proven end to end rather than assumed: the cross-built binary
runs on the phone, and all five core suites pass there too -- on the real
hardware, not just under qemu-aarch64. That matters for modules that are almost
entirely little-endian field packing and offset arithmetic.