unlock: introduce UnlockCtx + DiscKind; trait keys off context

Reshape the Unlocker seam so every unlocker is dispatched at ONE place from
ONE ordered registry — the firmware, cert, and CSS routes are all "remove the
bus-encryption barrier", differing only in what they key off. matches() and
unlock() now take an UnlockCtx { drive_id, kind: DiscKind } instead of a bare
DriveId: a firmware unlocker keys off drive_id (kind irrelevant), the cert
unlocker will match DiscKind::Aacs, the CSS unlocker DiscKind::Css. UnlockCtx
is #[non_exhaustive] so a host-cert source can be added without breaking
external unlockers. Drive-prep dispatch passes DiscKind::Unknown (no disc
probed yet); the cert/CSS registry impls + the single post-probe dispatch
point follow in subsequent commits.
This commit is contained in:
Matthew Jackson
2026-06-29 16:27:30 -07:00
parent 03820c68f8
commit cfcc524367
3 changed files with 120 additions and 29 deletions
+13 -4
View File
@@ -410,7 +410,12 @@ impl Drive {
// Walk the unlock registry: the first unlocker whose identity
// matches runs; none matching leaves the drive in stock mode so the
// host-cert AACS handshake (the OEM route) carries the disc.
let r = crate::unlock::route_unlock(self.scsi.as_mut(), &self.drive_id);
// Drive-prep dispatch: disc structure has not been probed yet, so the
// kind is Unknown — only a drive-keyed (firmware) unlocker can match.
let r = crate::unlock::route_unlock(
self.scsi.as_mut(),
&crate::unlock::UnlockCtx::new(&self.drive_id, crate::unlock::DiscKind::Unknown),
);
self.init_ran = true;
let r = match r {
Ok(Some((name, vid))) => {
@@ -421,9 +426,13 @@ impl Drive {
// The matched unlocker may also be able to raise the drive to
// its maximum read speed. Best-effort: a failure here must NOT
// fail the rip — a slow drive still rips. Log and continue.
if let Err(e) =
crate::unlock::unlocker_set_max_read_speed(self.scsi.as_mut(), &self.drive_id)
{
if let Err(e) = crate::unlock::unlocker_set_max_read_speed(
self.scsi.as_mut(),
&crate::unlock::UnlockCtx::new(
&self.drive_id,
crate::unlock::DiscKind::Unknown,
),
) {
tracing::warn!(
target: "freemkv::drive",
phase = "init",