diff --git a/sw/host/opentitanlib/src/io/uart.rs b/sw/host/opentitanlib/src/io/uart.rs index b9b830d5a26e2..0b413e30d4c62 100644 --- a/sw/host/opentitanlib/src/io/uart.rs +++ b/sw/host/opentitanlib/src/io/uart.rs @@ -18,7 +18,7 @@ use crate::impl_serializable_error; use crate::io::console::ConsoleDevice; use crate::transport::TransportError; -#[derive(Clone, Debug, Args, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Args, Serialize, Deserialize)] pub struct UartParams { /// UART instance. #[arg(long, default_value = "CONSOLE")] diff --git a/sw/host/opentitanlib/src/rescue/mod.rs b/sw/host/opentitanlib/src/rescue/mod.rs index 319a252a961c2..a3109aeb15137 100644 --- a/sw/host/opentitanlib/src/rescue/mod.rs +++ b/sw/host/opentitanlib/src/rescue/mod.rs @@ -2,13 +2,173 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +use anyhow::{ensure, Result}; +use clap::{Args, ValueEnum}; use thiserror::Error; +use crate::app::TransportWrapper; +use crate::chip::boot_log::BootLog; +use crate::chip::boot_svc::{BootSlot, BootSvc, OwnershipActivateRequest, OwnershipUnlockRequest}; +use crate::chip::device_id::DeviceId; +use crate::io::uart::UartParams; +use crate::with_unknown; + pub mod serial; pub mod xmodem; +pub use serial::RescueSerial; + #[derive(Debug, Error)] pub enum RescueError { #[error("bad mode: {0}")] BadMode(String), + #[error("configuration error: {0}")] + Configuration(String), +} + +#[derive(ValueEnum, Default, Debug, Clone, Copy, PartialEq)] +pub enum RescueProtocol { + #[default] + Xmodem, + UsbDfu, + SpiDfu, +} + +#[derive(ValueEnum, Default, Debug, Clone, Copy, PartialEq)] +pub enum RescueTrigger { + #[default] + SerialBreak, + Gpio, + Strap, +} + +#[derive(Clone, Default, Debug, Args)] +pub struct RescueParams { + /// Rescue Protocol + #[arg(short, long, value_enum, default_value_t = RescueProtocol::Xmodem)] + pub protocol: RescueProtocol, + #[arg(short, long, value_enum, default_value_t = RescueTrigger::SerialBreak)] + pub trigger: RescueTrigger, + #[arg(short, long, default_value = "")] + pub value: String, + #[command(flatten)] + uart: UartParams, +} + +impl RescueParams { + pub fn create(&self, transport: &TransportWrapper) -> Result> { + match self.protocol { + RescueProtocol::Xmodem => self.create_serial(transport), + RescueProtocol::UsbDfu => self.create_usbdfu(transport), + RescueProtocol::SpiDfu => self.create_spidfu(transport), + } + } + fn create_serial(&self, transport: &TransportWrapper) -> Result> { + ensure!( + self.trigger == RescueTrigger::SerialBreak, + RescueError::Configuration(format!( + "Xmodem does not support trigger {:?}", + self.trigger + )) + ); + ensure!( + self.value.is_empty(), + RescueError::Configuration(format!( + "Xmodem does not support trigger value {:?}", + self.value + )) + ); + + Ok(Box::new(RescueSerial::new(self.uart.create(transport)?))) + } + fn create_usbdfu(&self, _transport: &TransportWrapper) -> Result> { + unimplemented!() + } + fn create_spidfu(&self, _transport: &TransportWrapper) -> Result> { + unimplemented!() + } +} + +with_unknown! { +pub enum RescueMode: u32 { + Rescue = u32::from_be_bytes(*b"RESQ"), + RescueB = u32::from_be_bytes(*b"RESB"), + BootLog = u32::from_be_bytes(*b"BLOG"), + BootSvcReq = u32::from_be_bytes(*b"BREQ"), + BootSvcRsp = u32::from_be_bytes(*b"BRSP"), + OwnerBlock = u32::from_be_bytes(*b"OWNR"), + GetOwnerPage0 = u32::from_be_bytes(*b"OPG0"), + GetOwnerPage1 = u32::from_be_bytes(*b"OPG1"), + DeviceId = u32::from_be_bytes(*b"OTID"), + EraseOwner = u32::from_be_bytes(*b"KLBR"), +} +} + +pub trait Rescue { + fn enter(&self, transport: &TransportWrapper, reset_target: bool) -> Result<()>; + fn set_mode(&self, mode: RescueMode) -> Result<()>; + fn send(&self, data: &[u8]) -> Result<()>; + fn recv(&self) -> Result>; + + // Not supported by all backends + fn set_speed(&self, speed: u32) -> Result; + fn wait(&self) -> Result<()>; + fn reboot(&self) -> Result<()>; + + fn get_raw(&self, mode: RescueMode) -> Result> { + self.set_mode(mode)?; + self.recv() + } + + fn set_raw(&self, mode: RescueMode, data: &[u8]) -> Result<()> { + self.set_mode(mode)?; + self.send(data) + } + + fn update_firmware(&self, slot: BootSlot, image: &[u8]) -> Result<()> { + let mode = if slot == BootSlot::SlotB { + RescueMode::RescueB + } else { + RescueMode::Rescue + }; + self.set_raw(mode, image) + } + + fn get_boot_log(&self) -> Result { + let blog = self.get_raw(RescueMode::BootLog)?; + Ok(BootLog::try_from(blog.as_slice())?) + } + + fn get_boot_svc(&self) -> Result { + let bsvc = self.get_raw(RescueMode::BootSvcRsp)?; + Ok(BootSvc::try_from(bsvc.as_slice())?) + } + + fn get_device_id(&self) -> Result { + let id = self.get_raw(RescueMode::DeviceId)?; + DeviceId::read(&mut std::io::Cursor::new(&id)) + } + + fn set_next_bl0_slot(&self, primary: BootSlot, next: BootSlot) -> Result<()> { + let message = BootSvc::next_boot_bl0_slot(primary, next); + self.set_raw(RescueMode::BootSvcReq, &message.to_bytes()?) + } + + fn ownership_unlock(&self, unlock: OwnershipUnlockRequest) -> Result<()> { + let message = BootSvc::ownership_unlock(unlock); + self.set_raw(RescueMode::BootSvcReq, &message.to_bytes()?) + } + + fn ownership_activate(&self, activate: OwnershipActivateRequest) -> Result<()> { + let message = BootSvc::ownership_activate(activate); + self.set_raw(RescueMode::BootSvcReq, &message.to_bytes()?) + } + + fn set_owner_config(&self, data: &[u8]) -> Result<()> { + self.set_raw(RescueMode::OwnerBlock, data) + } + + fn erase_owner(&self) -> Result<()> { + self.set_raw(RescueMode::EraseOwner, &[]) + } } diff --git a/sw/host/opentitanlib/src/rescue/serial.rs b/sw/host/opentitanlib/src/rescue/serial.rs index 82388645fef28..32d295b63c48b 100644 --- a/sw/host/opentitanlib/src/rescue/serial.rs +++ b/sw/host/opentitanlib/src/rescue/serial.rs @@ -7,12 +7,9 @@ use std::rc::Rc; use std::time::Duration; use crate::app::TransportWrapper; -use crate::chip::boot_log::BootLog; -use crate::chip::boot_svc::{BootSlot, BootSvc, OwnershipActivateRequest, OwnershipUnlockRequest}; -use crate::chip::device_id::DeviceId; use crate::io::uart::Uart; use crate::rescue::xmodem::Xmodem; -use crate::rescue::RescueError; +use crate::rescue::{Rescue, RescueError, RescueMode}; use crate::uart::console::UartConsole; pub struct RescueSerial { @@ -23,19 +20,9 @@ pub struct RescueSerial { impl RescueSerial { const ONE_SECOND: Duration = Duration::from_secs(1); - pub const RESCUE: [u8; 4] = *b"RESQ"; - pub const RESCUE_B: [u8; 4] = *b"RESB"; - pub const REBOOT: [u8; 4] = *b"REBO"; - pub const BAUD: [u8; 4] = *b"BAUD"; - pub const BOOT_LOG: [u8; 4] = *b"BLOG"; - pub const BOOT_SVC_REQ: [u8; 4] = *b"BREQ"; - pub const BOOT_SVC_RSP: [u8; 4] = *b"BRSP"; - pub const OWNER_BLOCK: [u8; 4] = *b"OWNR"; - pub const GET_OWNER_PAGE0: [u8; 4] = *b"OPG0"; - pub const GET_OWNER_PAGE1: [u8; 4] = *b"OPG1"; - pub const OT_ID: [u8; 4] = *b"OTID"; - pub const ERASE_OWNER: [u8; 4] = *b"KLBR"; - pub const WAIT: [u8; 4] = *b"WAIT"; + pub const REBOOT: RescueMode = RescueMode(u32::from_be_bytes(*b"REBO")); + pub const BAUD: RescueMode = RescueMode(u32::from_be_bytes(*b"BAUD")); + pub const WAIT: RescueMode = RescueMode(u32::from_be_bytes(*b"WAIT")); const BAUD_115K: [u8; 4] = *b"115K"; const BAUD_230K: [u8; 4] = *b"230K"; @@ -51,8 +38,10 @@ impl RescueSerial { enter_delay: Duration::from_secs(5), } } +} - pub fn enter(&self, transport: &TransportWrapper, reset_target: bool) -> Result<()> { +impl Rescue for RescueSerial { + fn enter(&self, transport: &TransportWrapper, reset_target: bool) -> Result<()> { log::info!("Setting serial break to trigger rescue mode."); self.uart.set_break(true)?; if reset_target { @@ -67,7 +56,7 @@ impl RescueSerial { Ok(()) } - pub fn set_baud(&self, baud: u32) -> Result<()> { + fn set_speed(&self, baud: u32) -> Result { // Make sure the requested rate is a known rate. let symbol = match baud { 115200 => Self::BAUD_115K, @@ -89,11 +78,13 @@ impl RescueSerial { return Err(RescueError::BadMode(result[0].clone()).into()); } // Change our side of the connection to the new rate. + let old = self.uart.get_baudrate()?; self.uart.set_baudrate(baud)?; - Ok(()) + Ok(old) } - pub fn set_mode(&self, mode: [u8; 4]) -> Result<()> { + fn set_mode(&self, mode: RescueMode) -> Result<()> { + let mode = mode.0.to_be_bytes(); self.uart.write(&mode)?; let enter = b'\r'; self.uart.write(std::slice::from_ref(&enter))?; @@ -110,84 +101,26 @@ impl RescueSerial { Ok(()) } - pub fn wait(&self) -> Result<()> { + fn wait(&self) -> Result<()> { self.set_mode(Self::WAIT)?; Ok(()) } - pub fn reboot(&self) -> Result<()> { + fn reboot(&self) -> Result<()> { self.set_mode(Self::REBOOT)?; Ok(()) } - pub fn update_firmware(&self, slot: BootSlot, image: &[u8]) -> Result<()> { - self.set_mode(if slot == BootSlot::SlotB { - Self::RESCUE_B - } else { - Self::RESCUE - })?; + fn send(&self, data: &[u8]) -> Result<()> { let xm = Xmodem::new(); - xm.send(&*self.uart, image)?; + xm.send(&*self.uart, data)?; Ok(()) } - pub fn get_raw(&self, mode: [u8; 4]) -> Result> { - self.set_mode(mode)?; + fn recv(&self) -> Result> { let mut data = Vec::new(); let xm = Xmodem::new(); xm.receive(&*self.uart, &mut data)?; Ok(data) } - - pub fn get_boot_log(&self) -> Result { - let blog = self.get_raw(Self::BOOT_LOG)?; - Ok(BootLog::try_from(blog.as_slice())?) - } - - pub fn get_boot_svc(&self) -> Result { - let bsvc = self.get_raw(Self::BOOT_SVC_RSP)?; - Ok(BootSvc::try_from(bsvc.as_slice())?) - } - - pub fn get_device_id(&self) -> Result { - let id = self.get_raw(Self::OT_ID)?; - DeviceId::read(&mut std::io::Cursor::new(&id)) - } - - pub fn set_boot_svc_raw(&self, data: &[u8]) -> Result<()> { - self.set_mode(Self::BOOT_SVC_REQ)?; - let xm = Xmodem::new(); - xm.send(&*self.uart, data)?; - Ok(()) - } - - pub fn set_next_bl0_slot(&self, primary: BootSlot, next: BootSlot) -> Result<()> { - let message = BootSvc::next_boot_bl0_slot(primary, next); - let data = message.to_bytes()?; - self.set_boot_svc_raw(&data) - } - - pub fn ownership_unlock(&self, unlock: OwnershipUnlockRequest) -> Result<()> { - let message = BootSvc::ownership_unlock(unlock); - let data = message.to_bytes()?; - self.set_boot_svc_raw(&data) - } - - pub fn ownership_activate(&self, activate: OwnershipActivateRequest) -> Result<()> { - let message = BootSvc::ownership_activate(activate); - let data = message.to_bytes()?; - self.set_boot_svc_raw(&data) - } - - pub fn set_owner_config(&self, data: &[u8]) -> Result<()> { - self.set_mode(Self::OWNER_BLOCK)?; - let xm = Xmodem::new(); - xm.send(&*self.uart, data)?; - Ok(()) - } - - pub fn erase_owner(&self) -> Result<()> { - self.set_mode(Self::ERASE_OWNER)?; - Ok(()) - } } diff --git a/sw/host/opentitanlib/src/rescue/xmodem.rs b/sw/host/opentitanlib/src/rescue/xmodem.rs index ba415a3a50d86..da0f367881b9c 100644 --- a/sw/host/opentitanlib/src/rescue/xmodem.rs +++ b/sw/host/opentitanlib/src/rescue/xmodem.rs @@ -188,7 +188,8 @@ impl Xmodem { } _ => { return Err(XmodemError::UnsupportedMode(format!( - "bad start of packet: {byte:?}" + "bad start of packet: {byte:02x} ({})", + byte as char )) .into()); } diff --git a/sw/host/opentitantool/src/command/rescue.rs b/sw/host/opentitantool/src/command/rescue.rs index fced6260bd252..306a5e8a9c861 100644 --- a/sw/host/opentitantool/src/command/rescue.rs +++ b/sw/host/opentitantool/src/command/rescue.rs @@ -4,12 +4,10 @@ use anyhow::{anyhow, Result}; use clap::{Args, Subcommand}; -use opentitanlib::io::uart::UartParams; use serde_annotate::Annotate; use std::any::Any; use std::fs::File; use std::path::PathBuf; -use std::rc::Rc; use opentitanlib::app::command::CommandDispatch; use opentitanlib::app::TransportWrapper; @@ -18,7 +16,7 @@ use opentitanlib::chip::helper::{OwnershipActivateParams, OwnershipUnlockParams} use opentitanlib::image::image::Image; use opentitanlib::image::manifest::ManifestKind; use opentitanlib::ownership::{OwnerBlock, TlvHeader}; -use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::{RescueMode, RescueParams}; use opentitanlib::util::file::FromReader; use opentitanlib::util::parse_int::ParseInt; @@ -31,8 +29,6 @@ pub struct RawBytes( #[derive(Debug, Args)] pub struct Firmware { - #[command(flatten)] - params: UartParams, #[arg(long, help = "After connecting to rescue, negotiate faster baudrate")] rate: Option, #[arg(long, default_value = "SlotA", help = "Which flash slot to rescue")] @@ -61,7 +57,7 @@ pub struct Firmware { impl CommandDispatch for Firmware { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { let image = Image::read_from_file(&self.filename)?; @@ -82,13 +78,12 @@ impl CommandDispatch for Firmware { } subimage.data }; - let uart = self.params.create(transport)?; + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; let mut prev_baudrate = 0u32; - let rescue = RescueSerial::new(Rc::clone(&uart)); rescue.enter(transport, self.reset_target)?; if let Some(rate) = self.rate { - prev_baudrate = uart.get_baudrate()?; - rescue.set_baud(rate)?; + prev_baudrate = rescue.set_speed(rate)?; } if self.wait { rescue.wait()?; @@ -96,9 +91,10 @@ impl CommandDispatch for Firmware { rescue.update_firmware(self.slot, payload)?; if self.rate.is_some() { if self.wait { - rescue.set_baud(prev_baudrate)?; + rescue.set_speed(prev_baudrate)?; } else { - uart.set_baudrate(prev_baudrate)?; + // FIXME: restore speed + //uart.set_baudrate(prev_baudrate)?; } } Ok(None) @@ -107,8 +103,6 @@ impl CommandDispatch for Firmware { #[derive(Debug, Args)] pub struct GetBootLog { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -123,14 +117,14 @@ pub struct GetBootLog { impl CommandDispatch for GetBootLog { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; if self.raw { - let data = rescue.get_raw(RescueSerial::BOOT_LOG)?; + let data = rescue.get_raw(RescueMode::BootLog)?; Ok(Some(Box::new(RawBytes(data)))) } else { let data = rescue.get_boot_log()?; @@ -141,8 +135,6 @@ impl CommandDispatch for GetBootLog { #[derive(Debug, Args)] pub struct GetBootSvc { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -157,14 +149,14 @@ pub struct GetBootSvc { impl CommandDispatch for GetBootSvc { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; if self.raw { - let data = rescue.get_raw(RescueSerial::BOOT_SVC_RSP)?; + let data = rescue.get_raw(RescueMode::BootSvcRsp)?; Ok(Some(Box::new(RawBytes(data)))) } else { let data = rescue.get_boot_svc()?; @@ -175,8 +167,6 @@ impl CommandDispatch for GetBootSvc { #[derive(Debug, Args)] pub struct GetDeviceId { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -191,14 +181,14 @@ pub struct GetDeviceId { impl CommandDispatch for GetDeviceId { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; if self.raw { - let data = rescue.get_raw(RescueSerial::OT_ID)?; + let data = rescue.get_raw(RescueMode::DeviceId)?; Ok(Some(Box::new(RawBytes(data)))) } else { let data = rescue.get_device_id()?; @@ -209,8 +199,6 @@ impl CommandDispatch for GetDeviceId { #[derive(Debug, Args)] pub struct SetNextBl0Slot { - #[command(flatten)] - params: UartParams, #[arg( long, short, @@ -244,11 +232,11 @@ pub struct SetNextBl0Slot { impl CommandDispatch for SetNextBl0Slot { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; rescue.set_next_bl0_slot(self.primary, self.next)?; if self.get_response { @@ -264,8 +252,6 @@ impl CommandDispatch for SetNextBl0Slot { #[derive(Debug, Args)] pub struct OwnershipUnlock { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -289,15 +275,15 @@ pub struct OwnershipUnlock { impl CommandDispatch for OwnershipUnlock { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { let unlock = self .unlock .apply_to(self.input.as_ref().map(File::open).transpose()?.as_mut())?; - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; rescue.ownership_unlock(unlock)?; if self.get_response { @@ -313,8 +299,6 @@ impl CommandDispatch for OwnershipUnlock { #[derive(Debug, Args)] pub struct OwnershipActivate { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -338,15 +322,15 @@ pub struct OwnershipActivate { impl CommandDispatch for OwnershipActivate { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { let activate = self .activate .apply_to(self.input.as_ref().map(File::open).transpose()?.as_mut())?; - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; rescue.ownership_activate(activate)?; if self.get_response { @@ -362,8 +346,6 @@ impl CommandDispatch for OwnershipActivate { #[derive(Debug, Args)] pub struct SetOwnerConfig { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -378,12 +360,12 @@ pub struct SetOwnerConfig { impl CommandDispatch for SetOwnerConfig { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { let data = std::fs::read(&self.input)?; - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; rescue.set_owner_config(&data)?; Ok(None) @@ -392,8 +374,6 @@ impl CommandDispatch for SetOwnerConfig { #[derive(Debug, Args)] pub struct GetOwnerConfig { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -417,16 +397,16 @@ pub struct GetOwnerConfig { impl CommandDispatch for GetOwnerConfig { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { let page = match self.page { - 0 => RescueSerial::GET_OWNER_PAGE0, - 1 => RescueSerial::GET_OWNER_PAGE1, + 0 => RescueMode::GetOwnerPage0, + 1 => RescueMode::GetOwnerPage1, _ => return Err(anyhow!("Unsupported page {}", self.page)), }; - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; let data = rescue.get_raw(page)?; if let Some(output) = &self.output { @@ -444,8 +424,6 @@ impl CommandDispatch for GetOwnerConfig { #[derive(Debug, Args)] pub struct EraseOwner { - #[command(flatten)] - params: UartParams, #[arg( long, default_value_t = true, @@ -460,12 +438,12 @@ pub struct EraseOwner { impl CommandDispatch for EraseOwner { fn run( &self, - _context: &dyn Any, + context: &dyn Any, transport: &TransportWrapper, ) -> Result>> { if self.really { - let uart = self.params.create(transport)?; - let rescue = RescueSerial::new(uart); + let context = context.downcast_ref::().unwrap(); + let rescue = context.params.create(transport)?; rescue.enter(transport, self.reset_target)?; rescue.erase_owner()?; Ok(None) @@ -484,7 +462,7 @@ pub enum BootSvcCommand { } #[derive(Debug, Subcommand, CommandDispatch)] -pub enum RescueCommand { +pub enum InternalRescueCommand { #[command(subcommand)] BootSvc(BootSvcCommand), EraseOwner(EraseOwner), @@ -494,3 +472,24 @@ pub enum RescueCommand { SetOwnerConfig(SetOwnerConfig), GetOwnerConfig(GetOwnerConfig), } + +#[derive(Debug, Args)] +pub struct RescueCommand { + #[command(flatten)] + params: RescueParams, + + #[command(subcommand)] + command: InternalRescueCommand, +} + +impl CommandDispatch for RescueCommand { + fn run( + &self, + _context: &dyn Any, + transport: &TransportWrapper, + ) -> Result>> { + // None of the SPI commands care about the prior context, but they do + // care about the `bus` parameter in the current node. + self.command.run(self, transport) + } +} diff --git a/sw/host/opentitantool/src/main.rs b/sw/host/opentitantool/src/main.rs index 10edafc29064e..786fd4434519c 100644 --- a/sw/host/opentitantool/src/main.rs +++ b/sw/host/opentitantool/src/main.rs @@ -48,7 +48,6 @@ enum RootCommandHierarchy { Otp(command::otp::Otp), #[command(subcommand)] Ownership(command::ownership::OwnershipCommand), - #[command(subcommand)] Rescue(command::rescue::RescueCommand), #[command(subcommand)] Rsa(command::rsa::Rsa), diff --git a/sw/host/tests/ownership/flash_permission_test.rs b/sw/host/tests/ownership/flash_permission_test.rs index a7ab90403ad8b..a817a785fd21d 100644 --- a/sw/host/tests/ownership/flash_permission_test.rs +++ b/sw/host/tests/ownership/flash_permission_test.rs @@ -14,6 +14,7 @@ use opentitanlib::app::TransportWrapper; use opentitanlib::chip::boot_svc::{BootSlot, UnlockMode}; use opentitanlib::chip::rom_error::RomError; use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::Rescue; use opentitanlib::test_utils::init::InitializeTest; use opentitanlib::uart::console::UartConsole; diff --git a/sw/host/tests/ownership/newversion_test.rs b/sw/host/tests/ownership/newversion_test.rs index 789139a1897af..2c9ef01f30e73 100644 --- a/sw/host/tests/ownership/newversion_test.rs +++ b/sw/host/tests/ownership/newversion_test.rs @@ -13,6 +13,7 @@ use std::time::Duration; use opentitanlib::app::TransportWrapper; use opentitanlib::chip::rom_error::RomError; use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::Rescue; use opentitanlib::test_utils::init::InitializeTest; use opentitanlib::uart::console::UartConsole; diff --git a/sw/host/tests/ownership/rescue_limit_test.rs b/sw/host/tests/ownership/rescue_limit_test.rs index adccaad4b93c5..756631df610b4 100644 --- a/sw/host/tests/ownership/rescue_limit_test.rs +++ b/sw/host/tests/ownership/rescue_limit_test.rs @@ -14,6 +14,7 @@ use opentitanlib::app::TransportWrapper; use opentitanlib::chip::boot_svc::{BootSlot, UnlockMode}; use opentitanlib::chip::rom_error::RomError; use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::Rescue; use opentitanlib::test_utils::init::InitializeTest; use opentitanlib::uart::console::UartConsole; diff --git a/sw/host/tests/ownership/rescue_permission_test.rs b/sw/host/tests/ownership/rescue_permission_test.rs index 30c02111bec6f..1f293078b3806 100644 --- a/sw/host/tests/ownership/rescue_permission_test.rs +++ b/sw/host/tests/ownership/rescue_permission_test.rs @@ -13,6 +13,7 @@ use std::time::Duration; use opentitanlib::app::TransportWrapper; use opentitanlib::chip::boot_svc::{BootSlot, UnlockMode}; use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::Rescue; use opentitanlib::test_utils::init::InitializeTest; #[derive(Debug, Parser)] diff --git a/sw/host/tests/ownership/transfer_lib.rs b/sw/host/tests/ownership/transfer_lib.rs index 917f699340633..3bd06dace3f5b 100644 --- a/sw/host/tests/ownership/transfer_lib.rs +++ b/sw/host/tests/ownership/transfer_lib.rs @@ -17,6 +17,7 @@ use opentitanlib::ownership::{ OwnerRescueConfig, OwnershipKeyAlg, }; use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::Rescue; use std::path::Path; diff --git a/sw/host/tests/ownership/transfer_test.rs b/sw/host/tests/ownership/transfer_test.rs index 2925724b01e0a..7b62af55c1449 100644 --- a/sw/host/tests/ownership/transfer_test.rs +++ b/sw/host/tests/ownership/transfer_test.rs @@ -14,6 +14,7 @@ use opentitanlib::app::TransportWrapper; use opentitanlib::chip::boot_svc::{BootSlot, UnlockMode}; use opentitanlib::chip::rom_error::RomError; use opentitanlib::rescue::serial::RescueSerial; +use opentitanlib::rescue::Rescue; use opentitanlib::test_utils::init::InitializeTest; use opentitanlib::uart::console::UartConsole; diff --git a/third_party/rust/Cargo.lock b/third_party/rust/Cargo.lock index 664a2b4a96e9e..753a6d5801031 100644 --- a/third_party/rust/Cargo.lock +++ b/third_party/rust/Cargo.lock @@ -1519,9 +1519,9 @@ dependencies = [ [[package]] name = "libusb1-sys" -version = "0.6.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" +checksum = "da050ade7ac4ff1ba5379af847a10a10a8e284181e060105bf8d86960ce9ce0f" dependencies = [ "cc", "libc", @@ -2425,9 +2425,9 @@ dependencies = [ [[package]] name = "rusb" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fff149b6033f25e825cbb7b2c625a11ee8e6dac09264d49beb125e39aa97bf" +checksum = "ab9f9ff05b63a786553a4c02943b74b34a988448671001e9a27e2f0565cc05a4" dependencies = [ "libc", "libusb1-sys", diff --git a/third_party/rust/Cargo.toml b/third_party/rust/Cargo.toml index d223cd2781d01..32f2aa019cf45 100644 --- a/third_party/rust/Cargo.toml +++ b/third_party/rust/Cargo.toml @@ -75,7 +75,7 @@ rand_chacha = "0.3" regex = "1.7" reqwest = { version = "0.12.9", features = ["http2", "default-tls", "blocking", "json"] } rsa = "0.9.2" -rusb = "0.9.3" +rusb = "0.9.4" rust-crypto = "0.2.36" rustix = { version = "0.38", features = ["event", "fs", "net", "process", "stdio", "termios"] } scopeguard = "1.2" diff --git a/third_party/rust/crates/BUILD.bazel b/third_party/rust/crates/BUILD.bazel index feb0a6b91872e..52fbd385816a5 100644 --- a/third_party/rust/crates/BUILD.bazel +++ b/third_party/rust/crates/BUILD.bazel @@ -429,7 +429,7 @@ alias( alias( name = "rusb", - actual = "@crate_index__rusb-0.9.3//:rusb", + actual = "@crate_index__rusb-0.9.4//:rusb", tags = ["manual"], ) diff --git a/third_party/rust/crates/BUILD.libusb1-sys-0.6.4.bazel b/third_party/rust/crates/BUILD.libusb1-sys-0.7.0.bazel similarity index 96% rename from third_party/rust/crates/BUILD.libusb1-sys-0.6.4.bazel rename to third_party/rust/crates/BUILD.libusb1-sys-0.7.0.bazel index f28bfa828c8e4..72e5d17f10e3d 100644 --- a/third_party/rust/crates/BUILD.libusb1-sys-0.6.4.bazel +++ b/third_party/rust/crates/BUILD.libusb1-sys-0.7.0.bazel @@ -73,10 +73,10 @@ rust_library( "@rules_rust//rust/platform:x86_64-unknown-none": [], "//conditions:default": ["@platforms//:incompatible"], }), - version = "0.6.4", + version = "0.7.0", deps = [ "@crate_index__libc-0.2.169//:libc", - "@crate_index__libusb1-sys-0.6.4//:build_script_build", + "@crate_index__libusb1-sys-0.7.0//:build_script_build", ], ) @@ -108,20 +108,20 @@ cargo_build_script( "noclippy", "norustfmt", ], - version = "0.6.4", + version = "0.7.0", visibility = ["//visibility:private"], deps = [ "@crate_index__cc-1.0.83//:cc", "@crate_index__pkg-config-0.3.27//:pkg_config", ] + select({ "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [ - "@crate_index__vcpkg-0.2.15//:vcpkg", # cfg(target_env = "msvc") + "@crate_index__vcpkg-0.2.15//:vcpkg", # cfg(target_os = "windows") ], "@rules_rust//rust/platform:i686-pc-windows-msvc": [ - "@crate_index__vcpkg-0.2.15//:vcpkg", # cfg(target_env = "msvc") + "@crate_index__vcpkg-0.2.15//:vcpkg", # cfg(target_os = "windows") ], "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [ - "@crate_index__vcpkg-0.2.15//:vcpkg", # cfg(target_env = "msvc") + "@crate_index__vcpkg-0.2.15//:vcpkg", # cfg(target_os = "windows") ], "//conditions:default": [], }), diff --git a/third_party/rust/crates/BUILD.rusb-0.9.3.bazel b/third_party/rust/crates/BUILD.rusb-0.9.4.bazel similarity index 94% rename from third_party/rust/crates/BUILD.rusb-0.9.3.bazel rename to third_party/rust/crates/BUILD.rusb-0.9.4.bazel index 377adba858868..7e440a663ed83 100644 --- a/third_party/rust/crates/BUILD.rusb-0.9.3.bazel +++ b/third_party/rust/crates/BUILD.rusb-0.9.4.bazel @@ -73,11 +73,11 @@ rust_library( "@rules_rust//rust/platform:x86_64-unknown-none": [], "//conditions:default": ["@platforms//:incompatible"], }), - version = "0.9.3", + version = "0.9.4", deps = [ "@crate_index__libc-0.2.169//:libc", - "@crate_index__libusb1-sys-0.6.4//:libusb1_sys", - "@crate_index__rusb-0.9.3//:build_script_build", + "@crate_index__libusb1-sys-0.7.0//:libusb1_sys", + "@crate_index__rusb-0.9.4//:build_script_build", ], ) @@ -99,7 +99,7 @@ cargo_build_script( ), edition = "2018", link_deps = [ - "@crate_index__libusb1-sys-0.6.4//:libusb1_sys", + "@crate_index__libusb1-sys-0.7.0//:libusb1_sys", ], rustc_flags = [ "--cap-lints=allow", @@ -111,7 +111,7 @@ cargo_build_script( "noclippy", "norustfmt", ], - version = "0.9.3", + version = "0.9.4", visibility = ["//visibility:private"], ) diff --git a/third_party/rust/crates/defs.bzl b/third_party/rust/crates/defs.bzl index 971256628d7bc..4b9e4a4fc2a63 100644 --- a/third_party/rust/crates/defs.bzl +++ b/third_party/rust/crates/defs.bzl @@ -359,7 +359,7 @@ _NORMAL_DEPENDENCIES = { "ring": "@crate_index__ring-0.16.20//:ring", "rsa": "@crate_index__rsa-0.9.2//:rsa", "rsa-der": "@crate_index__rsa-der-0.3.0//:rsa_der", - "rusb": "@crate_index__rusb-0.9.3//:rusb", + "rusb": "@crate_index__rusb-0.9.4//:rusb", "rust-crypto": "@crate_index__rust-crypto-0.2.36//:crypto", "rustix": "@crate_index__rustix-0.38.10//:rustix", "scopeguard": "@crate_index__scopeguard-1.2.0//:scopeguard", @@ -500,7 +500,6 @@ _CONDITIONS = { "cfg(not(windows_raw_dylib))": ["@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:aarch64-apple-ios", "@rules_rust//rust/platform:aarch64-apple-ios-sim", "@rules_rust//rust/platform:aarch64-fuchsia", "@rules_rust//rust/platform:aarch64-linux-android", "@rules_rust//rust/platform:aarch64-pc-windows-msvc", "@rules_rust//rust/platform:aarch64-unknown-linux-gnu", "@rules_rust//rust/platform:arm-unknown-linux-gnueabi", "@rules_rust//rust/platform:armv7-linux-androideabi", "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi", "@rules_rust//rust/platform:i686-apple-darwin", "@rules_rust//rust/platform:i686-linux-android", "@rules_rust//rust/platform:i686-pc-windows-msvc", "@rules_rust//rust/platform:i686-unknown-freebsd", "@rules_rust//rust/platform:i686-unknown-linux-gnu", "@rules_rust//rust/platform:powerpc-unknown-linux-gnu", "@rules_rust//rust/platform:riscv32imc-unknown-none-elf", "@rules_rust//rust/platform:riscv64gc-unknown-none-elf", "@rules_rust//rust/platform:s390x-unknown-linux-gnu", "@rules_rust//rust/platform:thumbv7em-none-eabi", "@rules_rust//rust/platform:thumbv8m.main-none-eabi", "@rules_rust//rust/platform:wasm32-unknown-unknown", "@rules_rust//rust/platform:wasm32-wasi", "@rules_rust//rust/platform:x86_64-apple-darwin", "@rules_rust//rust/platform:x86_64-apple-ios", "@rules_rust//rust/platform:x86_64-fuchsia", "@rules_rust//rust/platform:x86_64-linux-android", "@rules_rust//rust/platform:x86_64-pc-windows-msvc", "@rules_rust//rust/platform:x86_64-unknown-freebsd", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", "@rules_rust//rust/platform:x86_64-unknown-none"], "cfg(target_arch = \"aarch64\")": ["@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:aarch64-apple-ios", "@rules_rust//rust/platform:aarch64-apple-ios-sim", "@rules_rust//rust/platform:aarch64-fuchsia", "@rules_rust//rust/platform:aarch64-linux-android", "@rules_rust//rust/platform:aarch64-pc-windows-msvc", "@rules_rust//rust/platform:aarch64-unknown-linux-gnu"], "cfg(target_arch = \"wasm32\")": ["@rules_rust//rust/platform:wasm32-unknown-unknown", "@rules_rust//rust/platform:wasm32-wasi"], - "cfg(target_env = \"msvc\")": ["@rules_rust//rust/platform:aarch64-pc-windows-msvc", "@rules_rust//rust/platform:i686-pc-windows-msvc", "@rules_rust//rust/platform:x86_64-pc-windows-msvc"], "cfg(target_env = \"sgx\")": [], "cfg(target_family = \"wasm\")": ["@rules_rust//rust/platform:wasm32-unknown-unknown", "@rules_rust//rust/platform:wasm32-wasi"], "cfg(target_feature = \"atomics\")": [], @@ -2067,12 +2066,12 @@ def crate_repositories(): maybe( http_archive, - name = "crate_index__libusb1-sys-0.6.4", - sha256 = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27", + name = "crate_index__libusb1-sys-0.7.0", + sha256 = "da050ade7ac4ff1ba5379af847a10a10a8e284181e060105bf8d86960ce9ce0f", type = "tar.gz", - urls = ["https://static.crates.io/crates/libusb1-sys/0.6.4/download"], - strip_prefix = "libusb1-sys-0.6.4", - build_file = Label("@lowrisc_opentitan//third_party/rust/crates:BUILD.libusb1-sys-0.6.4.bazel"), + urls = ["https://static.crates.io/crates/libusb1-sys/0.7.0/download"], + strip_prefix = "libusb1-sys-0.7.0", + build_file = Label("@lowrisc_opentitan//third_party/rust/crates:BUILD.libusb1-sys-0.7.0.bazel"), ) maybe( @@ -2953,12 +2952,12 @@ def crate_repositories(): maybe( http_archive, - name = "crate_index__rusb-0.9.3", - sha256 = "45fff149b6033f25e825cbb7b2c625a11ee8e6dac09264d49beb125e39aa97bf", + name = "crate_index__rusb-0.9.4", + sha256 = "ab9f9ff05b63a786553a4c02943b74b34a988448671001e9a27e2f0565cc05a4", type = "tar.gz", - urls = ["https://static.crates.io/crates/rusb/0.9.3/download"], - strip_prefix = "rusb-0.9.3", - build_file = Label("@lowrisc_opentitan//third_party/rust/crates:BUILD.rusb-0.9.3.bazel"), + urls = ["https://static.crates.io/crates/rusb/0.9.4/download"], + strip_prefix = "rusb-0.9.4", + build_file = Label("@lowrisc_opentitan//third_party/rust/crates:BUILD.rusb-0.9.4.bazel"), ) maybe(