Skip to content

Commit

Permalink
WIP: SPI flashrom
Browse files Browse the repository at this point in the history
Change-Id: I9511b449f303a5f0cd901dac19ce9654209b3fd1
  • Loading branch information
jesultra committed Nov 21, 2024
1 parent 16375ed commit b8466e9
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 0 deletions.
7 changes: 7 additions & 0 deletions sw/host/opentitanlib/src/app/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ impl Target for LogicalSpiWrapper {
self.physical_wrapper.underlying_target.set_voltage(voltage)
}

fn get_flashrom_programmer(&self) -> Result<String> {
self.apply_settings_to_underlying()?;
self.physical_wrapper
.underlying_target
.get_flashrom_programmer()
}

fn run_transaction(&self, transaction: &mut [spi::Transfer]) -> Result<()> {
self.apply_settings_to_underlying()?;
self.physical_wrapper
Expand Down
7 changes: 7 additions & 0 deletions sw/host/opentitanlib/src/io/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use thiserror::Error;
use super::{eeprom, gpio};
use crate::app::TransportWrapper;
use crate::impl_serializable_error;
use crate::transport::TransportError;
use crate::util::voltage::Voltage;

#[derive(Clone, Debug, Args, Serialize, Deserialize)]
Expand Down Expand Up @@ -202,6 +203,12 @@ pub trait Target {
Err(SpiError::InvalidOption("This target does not support set_voltage".to_string()).into())
}

/// Returns `"raiden_debug_spi:serial=XXX"` or similar string usable for passing via `-p`
/// argument to `flashrom`, in order for it to connect to this SPI port instance.
fn get_flashrom_programmer(&self) -> Result<String> {
Err(TransportError::UnsupportedOperation.into())
}

/// Runs a SPI transaction composed from the slice of [`Transfer`] objects. Will assert the
/// CS for the duration of the entire transactions.
fn run_transaction(&self, transaction: &mut [Transfer]) -> Result<()>;
Expand Down
4 changes: 4 additions & 0 deletions sw/host/opentitanlib/src/proxy/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,10 @@ impl<'a> TransportCommandHandler<'a> {
instance.set_voltage(*voltage)?;
Ok(Response::Spi(SpiResponse::SetVoltage))
}
SpiRequest::GetFlashromArgs => {
let programmer = instance.get_flashrom_programmer()?;
Ok(Response::Spi(SpiResponse::GetFlashromArgs { programmer }))
}
SpiRequest::RunTransaction { transaction: reqs } => {
// Construct proper response to each transfer in request.
let mut resps: Vec<SpiTransferResponse> = reqs
Expand Down
4 changes: 4 additions & 0 deletions sw/host/opentitanlib/src/proxy/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ pub enum SpiRequest {
SetVoltage {
voltage: Voltage,
},
GetFlashromArgs,
RunTransaction {
transaction: Vec<SpiTransferRequest>,
},
Expand Down Expand Up @@ -281,6 +282,9 @@ pub enum SpiResponse {
sizes: MaxSizes,
},
SetVoltage,
GetFlashromArgs {
programmer: String,
},
RunTransaction {
transaction: Vec<SpiTransferResponse>,
},
Expand Down
21 changes: 21 additions & 0 deletions sw/host/opentitanlib/src/transport/dediprog/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,27 @@ impl Target for DediprogSpi {
inner.set_voltage()
}

fn get_flashrom_programmer(&self) -> Result<String> {
let inner = self.inner.borrow();
let voltage = match inner.voltage {
super::Voltage::V0 => "0V",
super::Voltage::V1p8 => "1.8V",
super::Voltage::V2p5 => "2.5V",
super::Voltage::V3p5 => "3.5V",
};
let spispeed = match inner.spi_clock {
ClockSpeed::Clk24Mhz => "24M",
ClockSpeed::Clk12Mhz => "12M",
ClockSpeed::Clk8Mhz => "8M",
ClockSpeed::Clk3Mhz => "3M",
ClockSpeed::Clk2p18Mhz => "2.18M",
ClockSpeed::Clk1p5Mhz => "1.5M",
ClockSpeed::Clk750Khz => "750k",
ClockSpeed::Clk375Khz => "375k",
};
Ok(format!("dediprog:voltage={voltage},spispeed={spispeed}"))
}

/// Dediprog has limited support for "plain" SPI transactions. It can only hold the CS
/// asserted across a write then optional read, both of at most 16 bytes.
fn run_transaction(&self, transaction: &mut [Transfer]) -> Result<()> {
Expand Down
6 changes: 6 additions & 0 deletions sw/host/opentitanlib/src/transport/hyperdebug/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,12 @@ impl Target for HyperdebugSpiTarget {
Ok(self.max_sizes)
}

fn get_flashrom_programmer(&self) -> Result<String> {
Ok(format!("raiden_debug_spi:serial={},target={}",
self.inner.usb_device.borrow().get_serial_number(),
self.target_idx))
}

fn run_transaction(&self, transaction: &mut [Transfer]) -> Result<()> {
let mut idx: usize = 0;
self.select_my_spi_bus()?;
Expand Down
7 changes: 7 additions & 0 deletions sw/host/opentitanlib/src/transport/proxy/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ impl Target for ProxySpi {
}
}

fn get_flashrom_programmer(&self) -> Result<String> {
match self.execute_command(SpiRequest::GetFlashromArgs)? {
SpiResponse::GetFlashromArgs { programmer } => Ok(programmer),
_ => bail!(ProxyError::UnexpectedReply()),
}
}

fn run_transaction(&self, transaction: &mut [Transfer]) -> Result<()> {
let mut req: Vec<SpiTransferRequest> = Vec::new();
for transfer in transaction.iter() {
Expand Down
27 changes: 27 additions & 0 deletions sw/host/opentitantool/src/command/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,32 @@ impl CommandDispatch for SpiRawTransceive {
}
}

/// Produces output useful for separate invocation of `flashrom` connecting to a particular SPI
/// bus alias.
#[derive(Debug, Args)]
pub struct SpiFlashromArgs {
}

#[derive(Debug, serde::Serialize)]
pub struct SpiFlashromArgsResponse {
programmer: String,
}

impl CommandDispatch for SpiFlashromArgs {
fn run(
&self,
context: &dyn Any,
transport: &TransportWrapper,
) -> Result<Option<Box<dyn Annotate>>> {
transport.capabilities()?.request(Capability::SPI).ok()?;
let context = context.downcast_ref::<SpiCommand>().unwrap();
let spi_bus = context.params.create(transport, "BOOTSTRAP")?;
Ok(Some(Box::new(SpiFlashromArgsResponse {
programmer: spi_bus.get_flashrom_programmer()?,
})))
}
}

/// Commands for interacting with a SPI EEPROM.
#[derive(Debug, Subcommand, CommandDispatch)]
pub enum InternalSpiCommand {
Expand All @@ -429,6 +455,7 @@ pub enum InternalSpiCommand {
RawWriteRead(SpiRawWriteRead),
RawTransceive(SpiRawTransceive),
Tpm(SpiTpm),
FlashromArgs(SpiFlashromArgs),
}

#[derive(Debug, Args)]
Expand Down

0 comments on commit b8466e9

Please sign in to comment.