Every unlocker now implements one method — unlock(&self, scsi, ctx) ->
Result<Option<Unlocked>> — with identical workflow and error handling,
differing only in CDBs/checks. Drops the unlock_features/unlock_bus split,
per-unlocker result state, and the drive_unlocked flag ("unlocked" is just
Some). Only a dead bus is Err; everything else falls through as Ok(None).
- VID read is best-effort everywhere via the shared crate::vid reader: a
VID miss no longer discards an unlock that already removed the bus — the
bug that dropped a freemkv-unlocked drive to the cert path and sent the
keyserver vid=none.
- AACS: host certs injected at construction (AacsUnlocker::new(certs)), not
passed per-call; a successful cert AKE is a real unlock.
- Renesas/Pioneer: the vendor open enables raw reads (LibreDrive parity),
then reads the VID via the same 0xAD reader — no host cert, matching the
firmware routes.
- Rename the MT1959 unlocker to LD (matches the ld/ module); the MediaTek
MT1959 platform driver keeps its name.
- Consumer assembles its own dispatch list from the exported types; no
central factory. Adds a uniform dead-bus contract test over all unlockers.
freemkv-unlock
The unlock layer for the freemkv toolchain.
An unlocker removes a drive-level bus-encryption barrier so the drive serves readable (de-bus'd / de-scrambled) sectors. Content-key decryption is a separate concern — the consumer's job.
This crate defines the Unlocker contract and a generic SCSI transport
contract, and holds the self-contained unlocker modules. The consumer
(libfreemkv) depends on this crate and
dispatches through all_unlockers(); it never names an individual unlocker, and
clients of libfreemkv are oblivious to unlockers entirely (as they are to the
SCSI layer).
use freemkv_unlock::UnlockError;
// Drive-prep: try each unlocker's feature unlock until one claims the drive.
// `NotApplicable` means "not this unlocker's drive" — move on; a transport
// error means a dead bus — abort. `unlock_bus` follows the same contract for
// removing per-disc bus encryption.
for u in freemkv_unlock::all_unlockers() {
match u.unlock_features(&mut scsi, &ctx) {
Ok(unlocked) => return Ok(unlocked),
Err(UnlockError::NotApplicable) => continue,
Err(e) => return Err(e),
}
}
To remove an unlocker, delete its module directory and its one line in
all_unlockers() — nothing else changes.
License
freemkv-unlock's own source is MIT — see LICENSE.
src/ld/profiles.json bundles volatile, RAM-only LibreDrive microcode
authored and owned by the MakeMKV team (GuinpinSoft inc.) — Copyright (c)
MakeMKV team, all rights reserved. That microcode is third-party proprietary
material, not covered by the MIT license; no ownership is claimed. See
NOTICE. With thanks to the MakeMKV team for
LibreDrive.