diff --git a/sw/device/silicon_creator/rom_ext/e2e/rescue/BUILD b/sw/device/silicon_creator/rom_ext/e2e/rescue/BUILD index a96b1320ba139..128ab78c27999 100644 --- a/sw/device/silicon_creator/rom_ext/e2e/rescue/BUILD +++ b/sw/device/silicon_creator/rom_ext/e2e/rescue/BUILD @@ -95,7 +95,7 @@ opentitan_test( --exec="fpga load-bitstream {bitstream}" --exec="bootstrap --clear-uart=true {firmware}" # Set next slot via the rescue protocol - --exec="rescue boot-svc set-next-bl0-slot --next=SlotB" + --exec="rescue boot-svc set-next-bl0-slot --next=SlotB --get-response=false" # Check for firmware execution in slot B --exec="console --non-interactive --exit-success='bl0_slot = __BB\r\n' --exit-failure='{exit_failure}'" # Reset and observe return to slot A. diff --git a/sw/host/opentitanlib/src/chip/boot_svc.rs b/sw/host/opentitanlib/src/chip/boot_svc.rs index e65e598792b9c..c70a678dfed99 100644 --- a/sw/host/opentitanlib/src/chip/boot_svc.rs +++ b/sw/host/opentitanlib/src/chip/boot_svc.rs @@ -86,6 +86,7 @@ pub struct MinBl0SecVerResponse { /// The current minimum BL0 version. pub ver: u32, /// The status response to the request. + #[annotate(format = hex)] pub status: u32, } @@ -102,6 +103,7 @@ pub struct NextBl0SlotRequest { #[derive(Debug, Default, Serialize, Annotate)] pub struct NextBl0SlotResponse { /// The status response to the request. + #[annotate(format = hex)] pub status: u32, /// The current primary slot. pub primary_bl0_slot: BootSlot, @@ -129,6 +131,7 @@ pub struct OwnershipUnlockRequest { #[derive(Debug, Default, Serialize, Annotate)] pub struct OwnershipUnlockResponse { /// The status response to the request. + #[annotate(format = hex)] pub status: u32, } @@ -154,6 +157,7 @@ pub struct OwnershipActivateRequest { #[derive(Debug, Default, Serialize, Annotate)] pub struct OwnershipActivateResponse { /// The status response to the request. + #[annotate(format = hex)] pub status: u32, } diff --git a/sw/host/opentitanlib/src/rescue/serial.rs b/sw/host/opentitanlib/src/rescue/serial.rs index 18f2141d92694..d04678545bde6 100644 --- a/sw/host/opentitanlib/src/rescue/serial.rs +++ b/sw/host/opentitanlib/src/rescue/serial.rs @@ -47,10 +47,12 @@ impl RescueSerial { } } - pub fn enter(&self, transport: &TransportWrapper) -> Result<()> { + pub fn enter(&self, transport: &TransportWrapper, reset_target: bool) -> Result<()> { log::info!("Setting serial break to trigger rescue mode."); self.uart.set_break(true)?; - transport.reset_target(self.reset_delay, /*clear_uart*=*/ true)?; + if reset_target { + transport.reset_target(self.reset_delay, /*clear_uart=*/ true)?; + } UartConsole::wait_for(&*self.uart, r"rescue:.*\r\n", self.enter_delay)?; log::info!("Rescue triggered. clearing serial break."); self.uart.set_break(false)?; diff --git a/sw/host/opentitantool/src/command/rescue.rs b/sw/host/opentitantool/src/command/rescue.rs index 0d3ab43c4ade2..4883029bb0b69 100644 --- a/sw/host/opentitantool/src/command/rescue.rs +++ b/sw/host/opentitantool/src/command/rescue.rs @@ -46,6 +46,13 @@ pub struct Firmware { help = "Wait after upload (no automatic reboot)" )] wait: bool, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, #[arg(value_name = "FILE")] filename: PathBuf, } @@ -77,7 +84,7 @@ impl CommandDispatch for Firmware { let uart = self.params.create(transport)?; let mut prev_baudrate = 0u32; let rescue = RescueSerial::new(Rc::clone(&uart)); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; if let Some(rate) = self.rate { prev_baudrate = uart.get_baudrate()?; rescue.set_baud(rate)?; @@ -101,6 +108,13 @@ impl CommandDispatch for Firmware { pub struct GetBootLog { #[command(flatten)] params: UartParams, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, #[arg(long, short, default_value = "false")] raw: bool, } @@ -113,7 +127,7 @@ impl CommandDispatch for GetBootLog { ) -> Result>> { let uart = self.params.create(transport)?; let rescue = RescueSerial::new(uart); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; if self.raw { let data = rescue.get_boot_log_raw()?; Ok(Some(Box::new(RawBytes(data)))) @@ -128,6 +142,13 @@ impl CommandDispatch for GetBootLog { pub struct GetBootSvc { #[command(flatten)] params: UartParams, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, #[arg(long, short, default_value = "false")] raw: bool, } @@ -140,7 +161,7 @@ impl CommandDispatch for GetBootSvc { ) -> Result>> { let uart = self.params.create(transport)?; let rescue = RescueSerial::new(uart); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; if self.raw { let data = rescue.get_boot_svc_raw()?; Ok(Some(Box::new(RawBytes(data)))) @@ -169,6 +190,20 @@ pub struct SetNextBl0Slot { help = "Set the one-time next boot slot" )] next: BootSlot, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Get the response from the target" + )] + get_response: bool, } impl CommandDispatch for SetNextBl0Slot { @@ -179,9 +214,16 @@ impl CommandDispatch for SetNextBl0Slot { ) -> Result>> { let uart = self.params.create(transport)?; let rescue = RescueSerial::new(uart); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; rescue.set_next_bl0_slot(self.primary, self.next)?; - Ok(None) + if self.get_response { + rescue.enter(transport, false)?; + let response = rescue.get_boot_svc()?; + rescue.reboot()?; + Ok(Some(Box::new(response))) + } else { + Ok(None) + } } } @@ -189,6 +231,20 @@ impl CommandDispatch for SetNextBl0Slot { pub struct OwnershipUnlock { #[command(flatten)] params: UartParams, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Get the response from the target" + )] + get_response: bool, #[command(flatten)] unlock: OwnershipUnlockParams, #[arg(short, long, help = "A file containing a binary unlock request")] @@ -207,9 +263,16 @@ impl CommandDispatch for OwnershipUnlock { let uart = self.params.create(transport)?; let rescue = RescueSerial::new(uart); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; rescue.ownership_unlock(unlock)?; - Ok(None) + if self.get_response { + rescue.enter(transport, false)?; + let response = rescue.get_boot_svc()?; + rescue.reboot()?; + Ok(Some(Box::new(response))) + } else { + Ok(None) + } } } @@ -217,6 +280,20 @@ impl CommandDispatch for OwnershipUnlock { pub struct OwnershipActivate { #[command(flatten)] params: UartParams, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Get the response from the target" + )] + get_response: bool, #[command(flatten)] activate: OwnershipActivateParams, #[arg(short, long, help = "A file containing a binary activate request")] @@ -235,9 +312,16 @@ impl CommandDispatch for OwnershipActivate { let uart = self.params.create(transport)?; let rescue = RescueSerial::new(uart); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; rescue.ownership_activate(activate)?; - Ok(None) + if self.get_response { + rescue.enter(transport, false)?; + let response = rescue.get_boot_svc()?; + rescue.reboot()?; + Ok(Some(Box::new(response))) + } else { + Ok(None) + } } } @@ -245,6 +329,13 @@ impl CommandDispatch for OwnershipActivate { pub struct SetOwnerConfig { #[command(flatten)] params: UartParams, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, #[arg(help = "A signed owner configuration block")] input: PathBuf, } @@ -258,14 +349,14 @@ impl CommandDispatch for SetOwnerConfig { let data = std::fs::read(&self.input)?; let uart = self.params.create(transport)?; let rescue = RescueSerial::new(uart); - rescue.enter(transport)?; + rescue.enter(transport, self.reset_target)?; rescue.set_owner_config(&data)?; Ok(None) } } #[derive(Debug, Subcommand, CommandDispatch)] -pub enum BootSvc { +pub enum BootSvcCommand { Get(GetBootSvc), SetNextBl0Slot(SetNextBl0Slot), OwnershipUnlock(OwnershipUnlock), @@ -275,7 +366,7 @@ pub enum BootSvc { #[derive(Debug, Subcommand, CommandDispatch)] pub enum RescueCommand { #[command(subcommand)] - BootSvc(BootSvc), + BootSvc(BootSvcCommand), GetBootLog(GetBootLog), Firmware(Firmware), SetOwnerConfig(SetOwnerConfig),