diff --git a/sw/host/opentitanlib/src/test_utils/lc_transition.rs b/sw/host/opentitanlib/src/test_utils/lc_transition.rs index ed4d557b92ce0b..585600b551b5ae 100644 --- a/sw/host/opentitanlib/src/test_utils/lc_transition.rs +++ b/sw/host/opentitanlib/src/test_utils/lc_transition.rs @@ -31,6 +31,8 @@ pub enum LcTransitionError { FailedToClaimMutex, #[error("Volatile raw unlock is not supported on this chip.")] VolatileRawUnlockNotSupported, + #[error("Volatile raw unlock is unexpectedly supported on this chip.")] + VolatileRawUnlockSupported, #[error("LC transition target programming failed (target state: 0x{0:x}).")] TargetProgrammingFailed(u32), #[error("LC transition failed (status: 0x{0:x}).")] @@ -216,6 +218,11 @@ pub fn trigger_lc_transition( /// provided (a pre-requisite of the volatile operation. The device will NOT be reset into the /// new lifecycle state as TAP straps are sampled again on a successfull transition. However, /// the TAP can be switched from LC to RISCV on a successfull transition. +/// +/// If the feature is not present in HW we expect the transition to fail with +/// a token error since the token is invalid for a real RAW unlock +/// transition. Use the expect_raw_unlock_supported argument to inficate +/// whether we expect this transition to succeed or not. pub fn trigger_volatile_raw_unlock<'t>( transport: &'t TransportWrapper, mut jtag: Box, @@ -224,6 +231,7 @@ pub fn trigger_volatile_raw_unlock<'t>( use_external_clk: bool, post_transition_tap: JtagTap, jtag_params: &JtagParams, + expect_raw_unlock_supported: bool, ) -> Result> { // Wait for the lc_ctrl to become initialized, claim the mutex, and program the target state // and token CSRs. @@ -237,8 +245,11 @@ pub fn trigger_volatile_raw_unlock<'t>( jtag.write_lc_ctrl_reg(&LcCtrlReg::TransitionCtrl, ctrl.bits())?; // Read back the volatile raw unlock bit to see if the feature is supported in the silicon. - if jtag.read_lc_ctrl_reg(&LcCtrlReg::TransitionCtrl)? < 2u32 { + let read = jtag.read_lc_ctrl_reg(&LcCtrlReg::TransitionCtrl)?; + if read < 2u32 && expect_raw_unlock_supported { return Err(LcTransitionError::VolatileRawUnlockNotSupported.into()); + } else if read >= 2u32 && !expect_raw_unlock_supported { + return Err(LcTransitionError::VolatileRawUnlockSupported.into()); } // Select the requested JTAG TAP to connect to post-transition. @@ -258,13 +269,21 @@ pub fn trigger_volatile_raw_unlock<'t>( jtag = transport.jtag(jtag_params)?.connect(JtagTap::RiscvTap)?; } - wait_for_status( - &mut *jtag, - Duration::from_secs(3), - LcCtrlStatus::TRANSITION_SUCCESSFUL, - ) - .context("failed waiting for TRANSITION_SUCCESSFUL status.")?; - + if expect_raw_unlock_supported { + wait_for_status( + &mut *jtag, + Duration::from_secs(3), + LcCtrlStatus::TRANSITION_SUCCESSFUL, + ) + .context("failed waiting for TRANSITION_SUCCESSFUL status.")?; + } else { + wait_for_status( + &mut *jtag, + Duration::from_secs(3), + LcCtrlStatus::TOKEN_ERROR, + ) + .context("failed waiting for TOKEN_ERROR status.")?; + } Ok(jtag) } diff --git a/sw/host/opentitantool/src/command/lc.rs b/sw/host/opentitantool/src/command/lc.rs index 14fa37509a1b46..ccdf50619d102b 100644 --- a/sw/host/opentitantool/src/command/lc.rs +++ b/sw/host/opentitantool/src/command/lc.rs @@ -478,6 +478,9 @@ impl CommandDispatch for VolatileRawUnlock { /*use_external_clk=*/ true, /*post_transition_tap=*/ JtagTap::LcTap, &self.jtag_params, + // whether we expect the RAW unlock feature to be present or not. + // on prod silicon this should be disabled. + false, )?; jtag = self