load_firmware returns Ok only after its own do_unlock succeeded. run_init
then slept 10 s and re-ran do_unlock, and on attempt 2 fell out of the loop
returning Err(last_err), discarding a real unlock. Return Ok at once; the
firmware upload itself is unchanged (stop-design-v5 §1 D10, ST-D10).
stop-design-v5 §5.2 UT10 / G3 (D10). Red on dev: after a confirmed
load_firmware, run_init settles 10 s and loops back into do_unlock, and a
confirmation on the last attempt is discarded as Err(last_err).
Share one IDENTITY reply fixture; assert UnsupportedFirmware/InvalidArgument;
cover the v2 length gate under P-256 and dead-bus/rejected VID after an arm.
Adds the org doc-links caller, cargo test --doc, and a consumers job building
libfreemkv and bdemu against this commit. ci/qa default to contents: read.
0.8.x de-bus via 0x06 is hardware-dependent, not validated; 0.7.1 replies "freemkv 0.7.1".
Note arm_stealth_oem's version gate vs raw reset(); FwMock Bd slot at its default.
Parse only the IDENTITY version token; refuse fw < 0.9 in FreemkvUnlocker and every arm recipe.
AACS arm runs before the cert check; an Encryption=off arm returns the bare VID. Unlocked zeroizes on drop.
Mark the 1.0 drive dead only for a type-0x01 cert failing LA verify or a type-0x11
cert; zeroed/unknown types and step-6/9 failures stay per-cert. Log the skip.
Drop the unreachable ILLEGAL_REQUEST wedge arm; stop retrying host certs after a
drive-side 1.0 verify failure; skip truncated/known-dead v1 creds up front; read
fmt 0x84 only from a Bus Encryption Capable drive; accept unreduced keydb scalars.
find_by_drive_id ran the four-field fallback per section, so an earlier
section's fallback beat a later section's exact match. Exact pass now spans
all sections first; fallback uniqueness is checked across all sections.
The 1.7.6 unified release ships no rip-path change (Linux desktop shell,
notifications, menu_layout refactor, XDG paths). Real-media QA on EC2
adds ~2h + real money to the release cycle to prove code that never
enters the rip pipeline. This empty commit puts `[skip-media]` in qa's
HEAD so the media matrix in qa.yml auto-skips per the documented bypass;
the full-platform builds/tests still run.
Release-orchestrate committed to qa (v1.7.5 version bump, etc.) but did
not push those commits back to dev, so promote's fast-forward gate
refused (qa was diverged from dev). This is an ours-merge: the commit
records qa as an ancestor of dev without applying its content, since
dev has already moved past 1.7.5 to 1.7.6 with the equivalent
information in place.
Bumps Cargo.toml + Cargo.lock to 1.7.6. Also fixes a CI-shape defect the
previous release left behind: dev's CHANGELOG still said
`## [1.7.5] — UNRELEASED` after 1.7.5 shipped (release-orchestrate dated
main but did not push a fresh UNRELEASED heading back to dev). Corrects
that here so the changelog job accepts 1.7.6 on the way to qa:
## [1.7.6] — UNRELEASED
- Version aligned; unified release driven by freemkv 1.7.6.
## [1.7.5] — 2026-09-23
- Version aligned (or actual content, per the shipped main entry).
The driver for 1.7.6 is the freemkv Linux desktop shell (GTK4 +
libadwaita) + rip-finished desktop notification (issue #56).
Firmware 0.9.0 consolidates the Ake (0x06) and Bus (0x07) features into a
single Encryption (0x06) lever; wire id 0x07 no longer exists. The separate
Bus lever was proven inert on BU40N/MT1959 — the one Encryption lever
de-busses on its own — so the unlock recipe now sets one flag where it used
to set two, and the trailing best-effort Set(Bus, off) is gone.
Set(Encryption, STATE_OFF) is the load-bearing step: the drive acts
pre-authenticated, so a bare 0xAD returns the VID with no cert and no AKE,
and content comes back de-bussed. Failure still maps to VidUnavailable.
Hardware-validated against fw 0.9.0 on BU40N 1.00 with a UHD disc: every
sampled unit returns de-bussed and opens with the AACS unit key resolved
from the live keyserver.
Replace comment/leak/identity guard workflows with thin callers into
freemkv/.github reusable guards (guard-comment/leak/identity @v1); fork
PRs still run, same-repo pushes aren't double-run. Delete now-unused
local ci/comment-guard.py and ci/leak-guard.sh. Add top-level
concurrency (cancel-in-progress) to ci.yml and qa.yml and standardize
actions/checkout to @v5.
arm_bypass_bd/arm_bypass_uhd now also Set(Hrl, off) (revocation skip) so a
revoked/absent cert never trips the HRL check on a keyless bypass rip; tests
updated for the new SET/verify order.
FreemkvUnlocker::set sent the vendor SET with DataDirection::None + an
empty buffer, but the SET CDB advertises a MIN_ALLOC_LEN (64B) data-in
allocation and the drive ABORTS a no-data transfer (CHECK CONDITION /
Aborted Command — HW-confirmed on BU40N fw 0.8.1). Every Set(feature)
failed, so the load-bearing Set(Ake,off) failed and the whole freemkv
unlock aborted, silently falling back to the AACS/online key route
(autorip showed 'Unlockers — freemkv: no'). Mirror the working
FirmwareControl::set (exec_in): read the state table back over a
FromDevice phase and ignore it. Adds a regression test modelling the
drive's abort-without-data-phase contract.