aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
# First-boot, on-device extraction of proprietary blobs from the stock
|
|
|
|
|
# Android partitions, so the image never has to ship or distribute them.
|
|
|
|
|
# pmOS installs flash only boot+userdata: the stock vendor/dsp partitions
|
|
|
|
|
# stay on every installed unit, and the device duplicates files it already
|
|
|
|
|
# lawfully contains, for its own operation. Design, legal frame and the
|
|
|
|
|
# on-phone verification: fp6 repo journal/blobs/.
|
|
|
|
|
#
|
|
|
|
|
# Consumers depend on this package and install a manifest fragment into
|
|
|
|
|
# /usr/share/fp6-vendor-blobs/manifest.d/ (syntax in the extract script);
|
|
|
|
|
# their post-install/post-upgrade should also run
|
|
|
|
|
# /usr/lib/fp6-vendor-blobs/extract --if-device so a package upgrade that
|
|
|
|
|
# drops a previously-shipped blob restores the file immediately instead of
|
|
|
|
|
# at the next boot. First consumer: soc-fairphone-fp6-audio (aw88261 acf).
|
|
|
|
|
maintainer="Jorijn van der Graaf <jorijnvdgraaf@catcrafts.net>"
|
|
|
|
|
pkgname=fp6-vendor-blobs
|
|
|
|
|
pkgver=1
|
fp6-vendor-blobs: reassemble a Qualcomm trustlet, not just copy a file
The fingerprint matcher is a proprietary OEM-signed trustlet, and it is not
shipped as one file: QTEE images live in the modem partition's image/ as an
ELF header+hashes file plus one payload per program header, and the loader
wants each payload written back at its segment's p_offset. So the existing
file directive cannot reach it.
An mbn directive does, with the same guarantees file has: the sha256 is of
the reassembled image, a mismatch tries the next partition, and an unverified
image is never installed. Reassembly is not a concatenation -- segments are
page aligned but not contiguous, gaps stay zero, and two pairs of focal64's
nine segments share an offset, so they are written in index order and the
later one wins, exactly as the bring-up repo's reassemble.py does.
Verified on the dev phone against the hash QTEE has actually accepted since
August: 3600472 bytes, sha256 1930c490..., reassembled from the phone's own
modem_a. The retry path was verified too, with a deliberately wrong first
partition -- which is how the variable clobber got caught: POSIX sh has no
locals, and reassemble() taking rdir= rewrote its caller's copy to the mount
path, so the second partition would have been searched at $MNT/$MNT/...
The fast path needed teaching as well: mbn's dest is the fifth field, and a
first boot would otherwise have exited early and extracted nothing.
Not pushed. The consumer fragment lives in the fingerprintd package.
2026-09-05 03:56:13 +02:00
|
|
|
pkgrel=2
|
aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
pkgdesc="On-device extraction of vendor blobs from the stock Android partitions"
|
|
|
|
|
url="https://forgejo.catcrafts.net/Catcrafts/fp6-img"
|
|
|
|
|
arch="noarch"
|
|
|
|
|
license="MIT"
|
|
|
|
|
# fallback mapper for when the initramfs didn't map the dynamic partitions
|
|
|
|
|
depends="make-dynpart-mappings"
|
aports: extract vendor blobs before udev coldplug so first-boot audio fully works
The preset fix (6ecc1dc) makes the unit run, but multi-user is too late: the
sound card probes at ~21 s, hard-fails (-2, no retry) on the missing ACF, and
the extractor's amp rebind at ~60 s cannot re-form a card whose machine
driver already failed. Re-probing the machine driver does re-form it, but a
late-formed card has a dead capture path - the wcd9378 TX sequencer refuses
PS0 (act_ps 0x3) until the next boot. So rebinding after the fact can never
fully win; extraction has to happen before the drivers probe.
- fp6-vendor-blobs.service: DefaultDependencies=no, run after remount-fs and
before systemd-udev-trigger, so blobs exist before module coldplug.
multi-user stays a second Wants as a post-udev retry if the early run
failed (by-partlabel/make-dynpart-mappings fallbacks need udev).
- aw88261-acf.manifest: add 'rebind platform sound' so the fallback path at
least recovers playback the same boot (capture then heals on reboot).
- fp6-vendor-blobs.post-upgrade (pkgrel 1): systemctl preset + immediate
extract, so installs of the 2026-08-24 image (unit shipped disabled, no
version bump to deliver the preset) finally heal via plain apk upgrade.
- soc-fairphone-fp6-audio pkgrel 1: carries the manifest change.
Verified on the dev phone with the exact staged bytes (sha256-compared):
simulated fresh install (ACF removed, reboot) extracts at 13.3 s, coldplug
probes the amps at 15.1 s, card init at 20.9 s loads the ACF cleanly, and a
1 kHz speaker-to-mic loopback passes on that same first boot with zero TX
sequencer warnings; next boot takes the all-dests-present fast path in 25 ms.
Evidence: fp6 repo journal/blobs/, 2026-08-29.
Assisted-by: Claude:claude-fable-5
2026-08-29 21:53:02 +02:00
|
|
|
install="$pkgname.post-upgrade"
|
aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
options="!check"
|
|
|
|
|
source="
|
|
|
|
|
fp6-vendor-blobs-extract
|
|
|
|
|
fp6-vendor-blobs.service
|
2026-08-28 00:57:56 +02:00
|
|
|
fp6-vendor-blobs.preset
|
aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
"
|
|
|
|
|
|
|
|
|
|
package() {
|
|
|
|
|
install -Dm755 "$srcdir"/fp6-vendor-blobs-extract \
|
|
|
|
|
"$pkgdir"/usr/lib/fp6-vendor-blobs/extract
|
|
|
|
|
install -Dm644 "$srcdir"/fp6-vendor-blobs.service \
|
|
|
|
|
"$pkgdir"/usr/lib/systemd/system/fp6-vendor-blobs.service
|
|
|
|
|
# enabled unconditionally: the unit is a fast no-op once every manifest
|
|
|
|
|
# dest exists, and blobs appearing on first boot must not depend on a
|
aports: extract vendor blobs before udev coldplug so first-boot audio fully works
The preset fix (6ecc1dc) makes the unit run, but multi-user is too late: the
sound card probes at ~21 s, hard-fails (-2, no retry) on the missing ACF, and
the extractor's amp rebind at ~60 s cannot re-form a card whose machine
driver already failed. Re-probing the machine driver does re-form it, but a
late-formed card has a dead capture path - the wcd9378 TX sequencer refuses
PS0 (act_ps 0x3) until the next boot. So rebinding after the fact can never
fully win; extraction has to happen before the drivers probe.
- fp6-vendor-blobs.service: DefaultDependencies=no, run after remount-fs and
before systemd-udev-trigger, so blobs exist before module coldplug.
multi-user stays a second Wants as a post-udev retry if the early run
failed (by-partlabel/make-dynpart-mappings fallbacks need udev).
- aw88261-acf.manifest: add 'rebind platform sound' so the fallback path at
least recovers playback the same boot (capture then heals on reboot).
- fp6-vendor-blobs.post-upgrade (pkgrel 1): systemctl preset + immediate
extract, so installs of the 2026-08-24 image (unit shipped disabled, no
version bump to deliver the preset) finally heal via plain apk upgrade.
- soc-fairphone-fp6-audio pkgrel 1: carries the manifest change.
Verified on the dev phone with the exact staged bytes (sha256-compared):
simulated fresh install (ACF removed, reboot) extracts at 13.3 s, coldplug
probes the amps at 15.1 s, card init at 20.9 s loads the ACF cleanly, and a
1 kHz speaker-to-mic loopback passes on that same first boot with zero TX
sequencer warnings; next boot takes the all-dests-present fast path in 25 ms.
Evidence: fp6 repo journal/blobs/, 2026-08-29.
Assisted-by: Claude:claude-fable-5
2026-08-29 21:53:02 +02:00
|
|
|
# manual systemctl enable. sysinit = the real (pre-coldplug) run;
|
|
|
|
|
# multi-user = the post-udev retry if the early run failed (see unit)
|
|
|
|
|
mkdir -p "$pkgdir"/etc/systemd/system/sysinit.target.wants \
|
|
|
|
|
"$pkgdir"/etc/systemd/system/multi-user.target.wants
|
|
|
|
|
ln -s /usr/lib/systemd/system/fp6-vendor-blobs.service \
|
|
|
|
|
"$pkgdir"/etc/systemd/system/sysinit.target.wants/fp6-vendor-blobs.service
|
aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
ln -s /usr/lib/systemd/system/fp6-vendor-blobs.service \
|
|
|
|
|
"$pkgdir"/etc/systemd/system/multi-user.target.wants/fp6-vendor-blobs.service
|
2026-08-28 00:57:56 +02:00
|
|
|
# ...and a preset, because the symlink alone does NOT survive: image
|
|
|
|
|
# build runs `systemctl preset-all`, which removes .wants links for any
|
|
|
|
|
# unit not enabled by a preset. That is what shipped the 2026-08-24
|
|
|
|
|
# image with the service `disabled; preset: disabled` -- no blob
|
|
|
|
|
# extracted, no sound card. See journal/blobs/ 2026-08-28.
|
|
|
|
|
install -Dm644 "$srcdir"/fp6-vendor-blobs.preset \
|
|
|
|
|
"$pkgdir"/usr/lib/systemd/system-preset/50-fp6-vendor-blobs.preset
|
aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
mkdir -p "$pkgdir"/usr/share/fp6-vendor-blobs/manifest.d
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sha512sums="
|
2026-09-05 22:26:06 +02:00
|
|
|
2caafdedf93e103516834a1f815dd828ecee66c82d569e4a925ccc6bd6ac75d6778290adb02db69538af3bb6ad36cee5c13c8afba2c722a4c4550efe761ba8a0 fp6-vendor-blobs-extract
|
aports: extract vendor blobs before udev coldplug so first-boot audio fully works
The preset fix (6ecc1dc) makes the unit run, but multi-user is too late: the
sound card probes at ~21 s, hard-fails (-2, no retry) on the missing ACF, and
the extractor's amp rebind at ~60 s cannot re-form a card whose machine
driver already failed. Re-probing the machine driver does re-form it, but a
late-formed card has a dead capture path - the wcd9378 TX sequencer refuses
PS0 (act_ps 0x3) until the next boot. So rebinding after the fact can never
fully win; extraction has to happen before the drivers probe.
- fp6-vendor-blobs.service: DefaultDependencies=no, run after remount-fs and
before systemd-udev-trigger, so blobs exist before module coldplug.
multi-user stays a second Wants as a post-udev retry if the early run
failed (by-partlabel/make-dynpart-mappings fallbacks need udev).
- aw88261-acf.manifest: add 'rebind platform sound' so the fallback path at
least recovers playback the same boot (capture then heals on reboot).
- fp6-vendor-blobs.post-upgrade (pkgrel 1): systemctl preset + immediate
extract, so installs of the 2026-08-24 image (unit shipped disabled, no
version bump to deliver the preset) finally heal via plain apk upgrade.
- soc-fairphone-fp6-audio pkgrel 1: carries the manifest change.
Verified on the dev phone with the exact staged bytes (sha256-compared):
simulated fresh install (ACF removed, reboot) extracts at 13.3 s, coldplug
probes the amps at 15.1 s, card init at 20.9 s loads the ACF cleanly, and a
1 kHz speaker-to-mic loopback passes on that same first boot with zero TX
sequencer warnings; next boot takes the all-dests-present fast path in 25 ms.
Evidence: fp6 repo journal/blobs/, 2026-08-29.
Assisted-by: Claude:claude-fable-5
2026-08-29 21:53:02 +02:00
|
|
|
b4c290095d9f39515378dfef08de720ce49324210342aa13c131dfce1103785e796e6f821f0c659671a4c44b46f466ce0e03f11f216fdcdee2a99db5e7970800 fp6-vendor-blobs.service
|
2026-08-28 00:57:56 +02:00
|
|
|
9e79dd0aed13f11a71282aa24b2a26331e85c105e25ab0c0fed6189b8c300769a5f4308b18b91d9855868d658ad3a57c03e26c9b11bd27fd5e03f9a5decbbd6a fp6-vendor-blobs.preset
|
aports: extract aw88261_acf.bin on-device instead of shipping it
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.
The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.
soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.
Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.
Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
|
|
|
"
|