v0.25.14: rename Drive raw-read API to remove third-party project breadcrumbs
Pure rename pass — no behavioral change: - Drive::is_libredrive_active() → Drive::is_raw_read_active() - PlatformDriver::is_libredrive_active() trait method (same rename) - Mt1959 struct field libredrive_active → raw_read_active - Error::AacsLibredriveUnsupported → Error::AacsRawReadUnsupported (numeric code E7016 unchanged) - All callers, tests, and doc comments updated to the new name. Old identifiers removed entirely; downstream consumers must update. Mirrored in bdemu, freemkv, autorip, freemkv-tools.
This commit is contained in:
@@ -1,5 +1,20 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.25.14 (2026-05-21)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `Drive::is_libredrive_active()` renamed to `Drive::is_raw_read_active()`.
|
||||||
|
Same semantics; old name removed. Mirrored on the internal
|
||||||
|
`PlatformDriver::is_libredrive_active()` trait method (now
|
||||||
|
`is_raw_read_active()`).
|
||||||
|
- `Error::AacsLibredriveUnsupported` renamed to
|
||||||
|
`Error::AacsRawReadUnsupported`; the underlying numeric code (E7016)
|
||||||
|
is unchanged. The `E_AACS_LIBREDRIVE_UNSUPPORTED` constant is
|
||||||
|
renamed to `E_AACS_RAW_READ_UNSUPPORTED`.
|
||||||
|
|
||||||
|
No behavioural change — purely a rename pass.
|
||||||
|
|
||||||
## 0.25.13 (2026-05-21)
|
## 0.25.13 (2026-05-21)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfreemkv"
|
name = "libfreemkv"
|
||||||
version = "0.25.13"
|
version = "0.25.14"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version = "1.86"
|
rust-version = "1.86"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|||||||
+1
-1
@@ -858,7 +858,7 @@ fn resolve_keys_classical(ctx: &ResolveContext<'_>, version: AacsVersion) -> Opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Paths 2-4 all consume the Volume ID. Without it (handshake
|
// Paths 2-4 all consume the Volume ID. Without it (handshake
|
||||||
// skipped, libredrive bypass failed, etc.) every downstream
|
// skipped, raw-read bypass failed, etc.) every downstream
|
||||||
// derivation produces garbage. Caller stamps `[0u8; 16]` as the
|
// derivation produces garbage. Caller stamps `[0u8; 16]` as the
|
||||||
// sentinel "no VID" — short-circuit here so we don't surface a
|
// sentinel "no VID" — short-circuit here so we don't surface a
|
||||||
// misleading "all paths failed" log when really the math is
|
// misleading "all paths failed" log when really the math is
|
||||||
|
|||||||
+7
-8
@@ -17,10 +17,10 @@ impl Disc {
|
|||||||
/// SCSI handshake — AACS mutual auth via host certs from the keydb,
|
/// SCSI handshake — AACS mutual auth via host certs from the keydb,
|
||||||
/// returning VID (and bus keys when applicable) on success.
|
/// returning VID (and bus keys when applicable) on success.
|
||||||
///
|
///
|
||||||
/// `Drive::is_libredrive_active()` is logged for diagnostics but no
|
/// `Drive::is_raw_read_active()` is logged for diagnostics but no
|
||||||
/// longer alters the auth path. v0.25.11 introduced a "raw-read VID"
|
/// longer alters the auth path. v0.25.11 introduced a "raw-read VID"
|
||||||
/// shortcut that issued `READ_DISC_STRUCTURE` format 0x80 with
|
/// shortcut that issued `READ_DISC_STRUCTURE` format 0x80 with
|
||||||
/// AGID=0 on libredrive-active drives, on the hypothesis that the
|
/// AGID=0 on raw-read-active drives, on the hypothesis that the
|
||||||
/// firmware-uploaded drive would serve VID without cert auth. The
|
/// firmware-uploaded drive would serve VID without cert auth. The
|
||||||
/// BU40N returned 0x05/0x6F/0x02 (`KEY NOT ESTABLISHED`) to that
|
/// BU40N returned 0x05/0x6F/0x02 (`KEY NOT ESTABLISHED`) to that
|
||||||
/// CDB — the AACS spec requires an AGID established via successful
|
/// CDB — the AACS spec requires an AGID established via successful
|
||||||
@@ -33,7 +33,7 @@ impl Disc {
|
|||||||
/// Returns `(handshake, error)`:
|
/// Returns `(handshake, error)`:
|
||||||
/// * `(Some(_), None)` — VID acquired
|
/// * `(Some(_), None)` — VID acquired
|
||||||
/// * `(None, Some(_))` — specific failure mode (see
|
/// * `(None, Some(_))` — specific failure mode (see
|
||||||
/// `AacsHostCertRejected` / `AacsLibredriveUnsupported` /
|
/// `AacsHostCertRejected` / `AacsRawReadUnsupported` /
|
||||||
/// `AacsVidUnavailable` variants in `error.rs`)
|
/// `AacsVidUnavailable` variants in `error.rs`)
|
||||||
/// * `(None, None)` — handshake not attempted (no keydb;
|
/// * `(None, None)` — handshake not attempted (no keydb;
|
||||||
/// resolution will proceed with VID=zero and rely on path 1
|
/// resolution will proceed with VID=zero and rely on path 1
|
||||||
@@ -45,7 +45,7 @@ impl Disc {
|
|||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
target: "freemkv::disc",
|
target: "freemkv::disc",
|
||||||
phase = "handshake_entry",
|
phase = "handshake_entry",
|
||||||
libredrive_active = session.is_libredrive_active(),
|
raw_read_active = session.is_raw_read_active(),
|
||||||
"do_handshake entered"
|
"do_handshake entered"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -101,10 +101,9 @@ impl Disc {
|
|||||||
|
|
||||||
if host_cert_count == 0 {
|
if host_cert_count == 0 {
|
||||||
// No host certs in keydb -> cert auth cannot proceed.
|
// No host certs in keydb -> cert auth cannot proceed.
|
||||||
// Surface as
|
// Surface as RawReadUnsupported so the caller knows
|
||||||
// LibredriveUnsupported so the caller knows neither path
|
// neither path is available on this configuration.
|
||||||
// is available on this configuration.
|
return (None, Some(Error::AacsRawReadUnsupported));
|
||||||
return (None, Some(Error::AacsLibredriveUnsupported));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// v0.25.7 wedge fix. Pre-0.25.7 this loop fired up to 16 AACS
|
// v0.25.7 wedge fix. Pre-0.25.7 this loop fired up to 16 AACS
|
||||||
|
|||||||
+2
-2
@@ -1044,7 +1044,7 @@ impl Disc {
|
|||||||
/// All disc reads use standard READ(10) via UDF -- no vendor SCSI commands.
|
/// All disc reads use standard READ(10) via UDF -- no vendor SCSI commands.
|
||||||
pub fn scan(session: &mut Drive, opts: &ScanOptions) -> Result<Self> {
|
pub fn scan(session: &mut Drive, opts: &ScanOptions) -> Result<Self> {
|
||||||
// AACS handshake (Blu-ray/UHD). Cert-based mutual auth; logs
|
// AACS handshake (Blu-ray/UHD). Cert-based mutual auth; logs
|
||||||
// is_libredrive_active() as a diagnostic but the auth path no
|
// is_raw_read_active() as a diagnostic but the auth path no
|
||||||
// longer branches on it.
|
// longer branches on it.
|
||||||
let (handshake, handshake_error) = Self::do_handshake(session, opts);
|
let (handshake, handshake_error) = Self::do_handshake(session, opts);
|
||||||
|
|
||||||
@@ -1133,7 +1133,7 @@ impl Disc {
|
|||||||
/// Core scan pipeline — works with any SectorSource.
|
/// Core scan pipeline — works with any SectorSource.
|
||||||
///
|
///
|
||||||
/// `handshake_error` is plumbed from `do_handshake` so failures
|
/// `handshake_error` is plumbed from `do_handshake` so failures
|
||||||
/// (cert rejected, libredrive unsupported, VID read failed) are
|
/// (cert rejected, raw-read unsupported, VID read failed) are
|
||||||
/// preserved as `disc.aacs_error` for callers to render. When key
|
/// preserved as `disc.aacs_error` for callers to render. When key
|
||||||
/// resolution succeeds despite the handshake failure (built-in
|
/// resolution succeeds despite the handshake failure (built-in
|
||||||
/// keys + disc-hash lookup hit) the error is dropped.
|
/// keys + disc-hash lookup hit) the error is dropped.
|
||||||
|
|||||||
+5
-5
@@ -432,7 +432,7 @@ impl Drive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if the drive is currently in libredrive raw-read mode.
|
/// True if the drive is currently in raw-read mode.
|
||||||
///
|
///
|
||||||
/// Detected by the platform driver during `init()` from the unlock
|
/// Detected by the platform driver during `init()` from the unlock
|
||||||
/// response's mode markers. When true:
|
/// response's mode markers. When true:
|
||||||
@@ -444,11 +444,11 @@ impl Drive {
|
|||||||
///
|
///
|
||||||
/// AACS layer code should branch on this: if true, skip
|
/// AACS layer code should branch on this: if true, skip
|
||||||
/// `aacs::handshake::aacs_authenticate` (the cert dance) and read
|
/// `aacs::handshake::aacs_authenticate` (the cert dance) and read
|
||||||
/// VID via the libredrive alternate path. If false, fall back to
|
/// VID via the alternate VID read path. If false, fall back to the
|
||||||
/// the standard cert-based handshake.
|
/// standard cert-based handshake.
|
||||||
pub fn is_libredrive_active(&self) -> bool {
|
pub fn is_raw_read_active(&self) -> bool {
|
||||||
match self.driver {
|
match self.driver {
|
||||||
Some(ref d) => d.is_libredrive_active(),
|
Some(ref d) => d.is_raw_read_active(),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -72,7 +72,7 @@ pub const E_AACS_DATA_KEY: u16 = 7011;
|
|||||||
pub const E_DECRYPT_FAILED: u16 = 7013;
|
pub const E_DECRYPT_FAILED: u16 = 7013;
|
||||||
pub const E_CSS_AUTH_FAILED: u16 = 7014;
|
pub const E_CSS_AUTH_FAILED: u16 = 7014;
|
||||||
pub const E_AACS_HOST_CERT_REJECTED: u16 = 7015;
|
pub const E_AACS_HOST_CERT_REJECTED: u16 = 7015;
|
||||||
pub const E_AACS_LIBREDRIVE_UNSUPPORTED: u16 = 7016;
|
pub const E_AACS_RAW_READ_UNSUPPORTED: u16 = 7016;
|
||||||
pub const E_AACS_VID_UNAVAILABLE: u16 = 7017;
|
pub const E_AACS_VID_UNAVAILABLE: u16 = 7017;
|
||||||
pub const E_AACS_MK_UNAVAILABLE: u16 = 7018;
|
pub const E_AACS_MK_UNAVAILABLE: u16 = 7018;
|
||||||
pub const E_AACS_VUK_NOT_IN_KEYDB: u16 = 7019;
|
pub const E_AACS_VUK_NOT_IN_KEYDB: u16 = 7019;
|
||||||
@@ -230,11 +230,11 @@ pub enum Error {
|
|||||||
/// Host certificate rejected by the drive's revocation list (HRL hit).
|
/// Host certificate rejected by the drive's revocation list (HRL hit).
|
||||||
/// All available host certs failed mutual auth on this drive.
|
/// All available host certs failed mutual auth on this drive.
|
||||||
AacsHostCertRejected,
|
AacsHostCertRejected,
|
||||||
/// Drive cannot be put into libredrive raw-read mode and standard
|
/// Drive cannot be put into raw-read mode and standard AACS cert
|
||||||
/// AACS cert auth failed. No path to decryption remains.
|
/// auth failed. No path to decryption remains.
|
||||||
AacsLibredriveUnsupported,
|
AacsRawReadUnsupported,
|
||||||
/// Volume ID could not be retrieved from the drive (neither via cert
|
/// Volume ID could not be retrieved from the drive (neither via cert
|
||||||
/// auth nor via the libredrive alternate path). Downstream of step 1
|
/// auth nor via the alternate VID read path). Downstream of step 1
|
||||||
/// of the AACS chain.
|
/// of the AACS chain.
|
||||||
AacsVidUnavailable,
|
AacsVidUnavailable,
|
||||||
/// No available path produced a Media Key (no MK+VID in keydb, no
|
/// No available path produced a Media Key (no MK+VID in keydb, no
|
||||||
@@ -329,7 +329,7 @@ impl Error {
|
|||||||
Error::DecryptFailed => E_DECRYPT_FAILED,
|
Error::DecryptFailed => E_DECRYPT_FAILED,
|
||||||
Error::CssAuthFailed => E_CSS_AUTH_FAILED,
|
Error::CssAuthFailed => E_CSS_AUTH_FAILED,
|
||||||
Error::AacsHostCertRejected => E_AACS_HOST_CERT_REJECTED,
|
Error::AacsHostCertRejected => E_AACS_HOST_CERT_REJECTED,
|
||||||
Error::AacsLibredriveUnsupported => E_AACS_LIBREDRIVE_UNSUPPORTED,
|
Error::AacsRawReadUnsupported => E_AACS_RAW_READ_UNSUPPORTED,
|
||||||
Error::AacsVidUnavailable => E_AACS_VID_UNAVAILABLE,
|
Error::AacsVidUnavailable => E_AACS_VID_UNAVAILABLE,
|
||||||
Error::AacsMkUnavailable => E_AACS_MK_UNAVAILABLE,
|
Error::AacsMkUnavailable => E_AACS_MK_UNAVAILABLE,
|
||||||
Error::AacsVukNotInKeydb => E_AACS_VUK_NOT_IN_KEYDB,
|
Error::AacsVukNotInKeydb => E_AACS_VUK_NOT_IN_KEYDB,
|
||||||
|
|||||||
+8
-8
@@ -19,17 +19,17 @@ pub(crate) trait PlatformDriver: Send {
|
|||||||
/// True after successful init().
|
/// True after successful init().
|
||||||
fn is_ready(&self) -> bool;
|
fn is_ready(&self) -> bool;
|
||||||
|
|
||||||
/// True if the drive is currently in libredrive raw-read mode (the
|
/// True if the drive is currently in raw-read mode (the per-drive
|
||||||
/// per-drive runtime firmware has been uploaded AND the drive
|
/// runtime firmware has been uploaded AND the drive confirms
|
||||||
/// confirms active mode via the `MMkv` / `LbDr` markers in the
|
/// active mode via the marker bytes in the unlock response). When
|
||||||
/// unlock response). When true the host can read sectors without
|
/// true the host can read sectors without AACS bus encryption and
|
||||||
/// AACS bus encryption and retrieve VID without cert-based mutual
|
/// retrieve VID without cert-based mutual auth — the cert/HRL gate
|
||||||
/// auth — the cert/HRL gate on the drive's standard AACS path is
|
/// on the drive's standard AACS path is effectively bypassed by
|
||||||
/// effectively bypassed by the alternate data path.
|
/// the alternate data path.
|
||||||
///
|
///
|
||||||
/// Default `false` — platforms that don't implement this mode are
|
/// Default `false` — platforms that don't implement this mode are
|
||||||
/// always reported as inactive.
|
/// always reported as inactive.
|
||||||
fn is_libredrive_active(&self) -> bool {
|
fn is_raw_read_active(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-29
@@ -52,10 +52,10 @@ pub struct Mt1959 {
|
|||||||
pub(crate) buffer_id: u8,
|
pub(crate) buffer_id: u8,
|
||||||
pub(crate) unlocked: bool,
|
pub(crate) unlocked: bool,
|
||||||
/// True when the unlock response carried both the per-drive
|
/// True when the unlock response carried both the per-drive
|
||||||
/// signature AND the active-mode markers (`MMkv` at [12..16],
|
/// signature AND a 4-byte marker at offset 12 plus a secondary
|
||||||
/// `LbDr` at [16..20]). When true the drive will accept raw-read
|
/// 4-byte marker at offset 16. When true the drive will accept
|
||||||
/// SCSI traffic without AACS bus encryption / cert auth.
|
/// raw-read SCSI traffic without AACS bus encryption / cert auth.
|
||||||
libredrive_active: bool,
|
raw_read_active: bool,
|
||||||
probed: bool,
|
probed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ impl Mt1959 {
|
|||||||
mode,
|
mode,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
unlocked: false,
|
unlocked: false,
|
||||||
libredrive_active: false,
|
raw_read_active: false,
|
||||||
probed: false,
|
probed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,14 +152,15 @@ impl Mt1959 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Raw-read mode is active when BOTH the per-drive signature
|
// Raw-read mode is active when BOTH the per-drive signature
|
||||||
// matched AND the response carries the secondary `LbDr` marker
|
// matched AND the response carries the secondary 4-byte marker
|
||||||
// repeated through bytes 16..64. The active-mode signature at
|
// at offset 16, repeated through bytes 16..64. The active-mode
|
||||||
// [12..16] checked above is the primary gate; the [16..20]
|
// signature at [12..16] checked above is the primary gate; the
|
||||||
// marker is the redundant confirmation Mt1959 firmware writes
|
// [16..20] marker is the redundant confirmation the firmware
|
||||||
// through the rest of the response. Requiring both before we
|
// writes through the rest of the response. Requiring both
|
||||||
// tell the AACS layer "skip the cert dance" keeps any partial
|
// before we tell the AACS layer "skip the cert dance" keeps
|
||||||
// / corrupted response from steering us into the bypass.
|
// any partial / corrupted response from steering us into the
|
||||||
self.libredrive_active = response.len() >= FIRMWARE_MODE_OFFSET + 4
|
// bypass.
|
||||||
|
self.raw_read_active = response.len() >= FIRMWARE_MODE_OFFSET + 4
|
||||||
&& response[FIRMWARE_ACTIVE_OFFSET..FIRMWARE_ACTIVE_OFFSET + 4] == FIRMWARE_ACTIVE_SIG
|
&& response[FIRMWARE_ACTIVE_OFFSET..FIRMWARE_ACTIVE_OFFSET + 4] == FIRMWARE_ACTIVE_SIG
|
||||||
&& response[FIRMWARE_MODE_OFFSET..FIRMWARE_MODE_OFFSET + 4] == FIRMWARE_MODE_SIG;
|
&& response[FIRMWARE_MODE_OFFSET..FIRMWARE_MODE_OFFSET + 4] == FIRMWARE_MODE_SIG;
|
||||||
|
|
||||||
@@ -357,8 +358,8 @@ impl PlatformDriver for Mt1959 {
|
|||||||
self.unlocked
|
self.unlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_libredrive_active(&self) -> bool {
|
fn is_raw_read_active(&self) -> bool {
|
||||||
self.libredrive_active
|
self.raw_read_active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,14 +418,15 @@ mod tests {
|
|||||||
r[0..4].copy_from_slice(&signature);
|
r[0..4].copy_from_slice(&signature);
|
||||||
// bytes [4..12] left as zeros (version + reserved per format)
|
// bytes [4..12] left as zeros (version + reserved per format)
|
||||||
r[12..16].copy_from_slice(&mode_marker);
|
r[12..16].copy_from_slice(&mode_marker);
|
||||||
// Real firmware repeats LbDr through [16..64]; the parser only
|
// Real firmware repeats the secondary marker through [16..64];
|
||||||
// checks [16..20], so we just write the marker once.
|
// the parser only checks [16..20], so we just write the marker
|
||||||
|
// once.
|
||||||
r[16..20].copy_from_slice(&id_marker);
|
r[16..20].copy_from_slice(&id_marker);
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn do_unlock_sets_libredrive_active_when_both_markers_present() {
|
fn do_unlock_sets_raw_read_active_when_both_markers_present() {
|
||||||
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
||||||
let response = build_response(sig, FIRMWARE_ACTIVE_SIG, FIRMWARE_MODE_SIG);
|
let response = build_response(sig, FIRMWARE_ACTIVE_SIG, FIRMWARE_MODE_SIG);
|
||||||
let mut transport = ScriptedTransport { response };
|
let mut transport = ScriptedTransport { response };
|
||||||
@@ -434,16 +436,16 @@ mod tests {
|
|||||||
assert_eq!(raw.len(), 64);
|
assert_eq!(raw.len(), 64);
|
||||||
assert!(mt.unlocked, "unlocked flag set after success");
|
assert!(mt.unlocked, "unlocked flag set after success");
|
||||||
assert!(
|
assert!(
|
||||||
mt.is_libredrive_active(),
|
mt.is_raw_read_active(),
|
||||||
"both MMkv and LbDr present -> libredrive_active"
|
"both markers present -> raw_read_active"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn do_unlock_unlocked_but_not_libredrive_when_id_marker_missing() {
|
fn do_unlock_unlocked_but_not_raw_read_when_id_marker_missing() {
|
||||||
// Active-mode primary marker present (so unlock passes) but the
|
// Active-mode primary marker present (so unlock passes) but the
|
||||||
// secondary LbDr marker is replaced with zeros — drive isn't
|
// secondary marker is replaced with zeros — drive isn't serving
|
||||||
// serving raw-read traffic on this path.
|
// raw-read traffic on this path.
|
||||||
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
||||||
let response = build_response(sig, FIRMWARE_ACTIVE_SIG, [0u8; 4]);
|
let response = build_response(sig, FIRMWARE_ACTIVE_SIG, [0u8; 4]);
|
||||||
let mut transport = ScriptedTransport { response };
|
let mut transport = ScriptedTransport { response };
|
||||||
@@ -452,8 +454,8 @@ mod tests {
|
|||||||
mt.do_unlock(&mut transport).expect("unlock should succeed");
|
mt.do_unlock(&mut transport).expect("unlock should succeed");
|
||||||
assert!(mt.unlocked);
|
assert!(mt.unlocked);
|
||||||
assert!(
|
assert!(
|
||||||
!mt.is_libredrive_active(),
|
!mt.is_raw_read_active(),
|
||||||
"missing LbDr marker -> raw-read not active"
|
"missing secondary marker -> raw-read not active"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,13 +472,14 @@ mod tests {
|
|||||||
let err = mt.do_unlock(&mut transport).unwrap_err();
|
let err = mt.do_unlock(&mut transport).unwrap_err();
|
||||||
assert!(matches!(err, Error::SignatureMismatch { .. }));
|
assert!(matches!(err, Error::SignatureMismatch { .. }));
|
||||||
assert!(!mt.unlocked);
|
assert!(!mt.unlocked);
|
||||||
assert!(!mt.is_libredrive_active());
|
assert!(!mt.is_raw_read_active());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn do_unlock_rejects_inactive_mode_marker() {
|
fn do_unlock_rejects_inactive_mode_marker() {
|
||||||
// Signature matches but [12..16] is NOT MMkv -> drive is not in
|
// Signature matches but the primary marker at [12..16] is
|
||||||
// active mode; both unlock and libredrive flag must stay false.
|
// missing -> drive is not in active mode; both unlock and the
|
||||||
|
// raw-read flag must stay false.
|
||||||
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
||||||
let response = build_response(sig, [0u8; 4], FIRMWARE_MODE_SIG);
|
let response = build_response(sig, [0u8; 4], FIRMWARE_MODE_SIG);
|
||||||
let mut transport = ScriptedTransport { response };
|
let mut transport = ScriptedTransport { response };
|
||||||
@@ -485,6 +488,6 @@ mod tests {
|
|||||||
let err = mt.do_unlock(&mut transport).unwrap_err();
|
let err = mt.do_unlock(&mut transport).unwrap_err();
|
||||||
assert!(matches!(err, Error::UnlockFailed));
|
assert!(matches!(err, Error::UnlockFailed));
|
||||||
assert!(!mt.unlocked);
|
assert!(!mt.unlocked);
|
||||||
assert!(!mt.is_libredrive_active());
|
assert!(!mt.is_raw_read_active());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user