firmware: mirror BD-disable wire change to STATE_BD_DISABLE (0x02)

Lockstep with freemkv-fw BD-refuse stealth fix: the BD force-disable wire
value moves from STATE_OFF (0x00, the SRAM boot value) to a distinct
sentinel STATE_BD_DISABLE (0x02), so an unarmed firmware image stays
OEM-identical. disable_bd() now sends 0x02; add the const and align the
Feature::Bd / Feature::Uhd ABI-mirror docs (enable dir / STATE_OFF are
OEM no-ops).
This commit is contained in:
Matthew Jackson
2026-09-15 14:15:39 -07:00
parent bce5f36ef2
commit b4e5d90c81
2 changed files with 16 additions and 5 deletions
+14 -4
View File
@@ -83,6 +83,11 @@ pub const SPEED_MAX: u8 = 0x01;
/// valid-empty. Destructive; NOT undone by [`Verb::Reset`]. `0x02`. /// valid-empty. Destructive; NOT undone by [`Verb::Reset`]. `0x02`.
pub const HRL_WIPE_ONCE: u8 = 0x02; pub const HRL_WIPE_ONCE: u8 = 0x02;
/// [`Feature::Bd`] state: force-refuse BD (AACS 1.0) discs (`0x02`). A distinct
/// sentinel — NOT [`STATE_OFF`] (`0x00`, the SRAM boot value) — so an unarmed image
/// leaves BD engaged (OEM). Mirrors the firmware ABI `STATE_BD_DISABLE`.
pub const STATE_BD_DISABLE: u8 = 0x02;
/// [`Feature::Region`] state: force BD region A (`0x2A`). See [`BdRegion`]. /// [`Feature::Region`] state: force BD region A (`0x2A`). See [`BdRegion`].
pub const REGION_BD_A: u8 = 0x2A; pub const REGION_BD_A: u8 = 0x2A;
/// [`Feature::Region`] state: force BD region B (`0x2B`). /// [`Feature::Region`] state: force BD region B (`0x2B`).
@@ -121,9 +126,12 @@ pub enum Feature {
/// Region (RPC) control. [`STATE_ON`] = region-free; `0x11..=0x18` = force /// Region (RPC) control. [`STATE_ON`] = region-free; `0x11..=0x18` = force
/// DVD region 1..8; [`REGION_BD_A`]/`_B`/`_C` = force BD region A/B/C. /// DVD region 1..8; [`REGION_BD_A`]/`_B`/`_C` = force BD region A/B/C.
Region = 0x02, Region = 0x02,
/// UHD (AACS 2.0) capability gate. /// UHD (AACS 2.0) capability gate. [`STATE_ON`] = force enabled; [`STATE_OFF`]
/// is a reserved/OEM no-op (only the enable direction is emitted).
Uhd = 0x03, Uhd = 0x03,
/// Blu-ray (AACS 1.0) capability gate. /// Blu-ray (AACS 1.0) capability gate. [`STATE_BD_DISABLE`] (`0x02`) =
/// force-refuse BD discs; passthrough/`0x00` boot/[`STATE_ON`] = OEM (engaged —
/// the enable direction is a no-op, OEM already engages BD).
Bd = 0x04, Bd = 0x04,
/// Host Revocation List handling. [`STATE_ON`] = skip lookup; /// Host Revocation List handling. [`STATE_ON`] = skip lookup;
/// [`HRL_WIPE_ONCE`] = one-time permanent wipe. /// [`HRL_WIPE_ONCE`] = one-time permanent wipe.
@@ -534,9 +542,11 @@ impl<'a> FirmwareControl<'a> {
pub fn enable_bd(&mut self) -> Result<()> { pub fn enable_bd(&mut self) -> Result<()> {
self.set(Feature::Bd, STATE_ON) self.set(Feature::Bd, STATE_ON)
} }
/// Force the Blu-ray capability gate off. /// Force the Blu-ray capability gate off (drive refuses BD discs). Sends
/// [`STATE_BD_DISABLE`] (`0x02`) — a distinct sentinel, NOT `0x00` (the SRAM boot
/// value) — so an unarmed image stays OEM-behaviour-identical (BD engaged).
pub fn disable_bd(&mut self) -> Result<()> { pub fn disable_bd(&mut self) -> Result<()> {
self.set(Feature::Bd, STATE_OFF) self.set(Feature::Bd, STATE_BD_DISABLE)
} }
/// Skip the HRL lookup (revoked certs accepted; non-destructive). /// Skip the HRL lookup (revoked certs accepted; non-destructive).
pub fn skip_hrl(&mut self) -> Result<()> { pub fn skip_hrl(&mut self) -> Result<()> {
+2 -1
View File
@@ -39,6 +39,7 @@ fn state_and_frame_constants_match_abi() {
assert_eq!(STATE_ON, 0x01); assert_eq!(STATE_ON, 0x01);
assert_eq!(SPEED_MAX, 0x01); assert_eq!(SPEED_MAX, 0x01);
assert_eq!(HRL_WIPE_ONCE, 0x02); assert_eq!(HRL_WIPE_ONCE, 0x02);
assert_eq!(STATE_BD_DISABLE, 0x02);
assert_eq!([REGION_BD_A, REGION_BD_B, REGION_BD_C], [0x2A, 0x2B, 0x2C]); assert_eq!([REGION_BD_A, REGION_BD_B, REGION_BD_C], [0x2A, 0x2B, 0x2C]);
assert_eq!(REGION_DVD_BASE, 0x10); assert_eq!(REGION_DVD_BASE, 0x10);
} }
@@ -348,7 +349,7 @@ fn typed_setters_issue_expected_set_cdbs() {
fw.unlock_speed().unwrap(); fw.unlock_speed().unwrap();
} }
assert_eq!(m.cdbs[0], build_set_cdb(Feature::Uhd, STATE_ON)); assert_eq!(m.cdbs[0], build_set_cdb(Feature::Uhd, STATE_ON));
assert_eq!(m.cdbs[1], build_set_cdb(Feature::Bd, STATE_OFF)); assert_eq!(m.cdbs[1], build_set_cdb(Feature::Bd, STATE_BD_DISABLE));
assert_eq!(m.cdbs[2], build_set_cdb(Feature::Hrl, STATE_ON)); assert_eq!(m.cdbs[2], build_set_cdb(Feature::Hrl, STATE_ON));
assert_eq!(m.cdbs[3], build_set_cdb(Feature::Hrl, HRL_WIPE_ONCE)); assert_eq!(m.cdbs[3], build_set_cdb(Feature::Hrl, HRL_WIPE_ONCE));
assert_eq!(m.cdbs[4], build_set_cdb(Feature::Ake, STATE_ON)); assert_eq!(m.cdbs[4], build_set_cdb(Feature::Ake, STATE_ON));