opentitanlib/transport/
mod.rs1use anyhow::Result;
6use bitflags::bitflags;
7use serde::{Deserialize, Serialize};
8use std::any::Any;
9use std::collections::HashMap;
10use std::path::PathBuf;
11use std::rc::Rc;
12
13use crate::bootstrap::BootstrapOptions;
14use crate::io::emu::Emulator;
15use crate::io::gpio::{GpioBitbanging, GpioMonitoring, GpioPin};
16use crate::io::i2c::Bus;
17use crate::io::jtag::{JtagChain, JtagParams};
18use crate::io::spi::Target;
19use crate::io::uart::Uart;
20
21pub mod chip_whisperer;
22pub mod common;
23pub mod dediprog;
24pub mod ftdi;
25pub mod hyperdebug;
26pub mod ioexpander;
27pub mod proxy;
28pub mod ti50emulator;
29pub mod verilator;
30
31mod errors;
33pub use errors::{TransportError, TransportInterfaceType};
34
35bitflags! {
36 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
38 #[serde(transparent)]
39 pub struct Capability: u32 {
40 const NONE = 0x00;
41 const UART = 0x01 << 0;
42 const SPI = 0x01 << 1;
43 const GPIO = 0x01 << 2;
44 const I2C = 0x01 << 3;
45 const PROXY = 0x01 << 4;
46 const EMULATOR = 0x01 << 5;
47 const GPIO_MONITORING = 0x01 << 6; const JTAG = 0x01 << 7;
49 const UART_NONBLOCKING = 0x01 << 8;
50 const SPI_DUAL = 0x01 << 9;
51 const SPI_QUAD = 0x01 << 10;
52 const GPIO_BITBANGING = 0x01 << 11;
53 }
54}
55
56#[derive(Serialize, Deserialize)]
58pub struct Capabilities {
59 capabilities: Capability,
60}
61
62impl Capabilities {
63 fn new(cap: Capability) -> Self {
66 Self { capabilities: cap }
67 }
68
69 pub fn add(&self, extra: Capability) -> Self {
70 Self {
71 capabilities: self.capabilities | extra,
72 }
73 }
74
75 pub fn request(&self, needed: Capability) -> NeededCapabilities {
77 NeededCapabilities {
78 capabilities: self.capabilities,
79 needed,
80 }
81 }
82}
83
84pub struct NeededCapabilities {
86 capabilities: Capability,
87 needed: Capability,
88}
89
90impl NeededCapabilities {
91 pub fn ok(&self) -> Result<()> {
93 if self.capabilities & self.needed != self.needed {
94 Err(TransportError::MissingCapabilities(self.needed, self.capabilities).into())
95 } else {
96 Ok(())
97 }
98 }
99}
100
101pub trait Transport {
104 fn capabilities(&self) -> Result<Capabilities>;
107
108 fn apply_default_configuration(&self) -> Result<()> {
111 Ok(())
112 }
113
114 fn jtag(&self, _opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
116 Err(TransportError::InvalidInterface(TransportInterfaceType::Jtag).into())
117 }
118 fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> {
120 Err(TransportError::InvalidInterface(TransportInterfaceType::Spi).into())
121 }
122 fn i2c(&self, _instance: &str) -> Result<Rc<dyn Bus>> {
124 Err(TransportError::InvalidInterface(TransportInterfaceType::I2c).into())
125 }
126 fn uart(&self, _instance: &str) -> Result<Rc<dyn Uart>> {
128 Err(TransportError::InvalidInterface(TransportInterfaceType::Uart).into())
129 }
130 fn gpio_pin(&self, _instance: &str) -> Result<Rc<dyn GpioPin>> {
132 Err(TransportError::InvalidInterface(TransportInterfaceType::Gpio).into())
133 }
134 fn gpio_monitoring(&self) -> Result<Rc<dyn GpioMonitoring>> {
136 Err(TransportError::InvalidInterface(TransportInterfaceType::GpioMonitoring).into())
137 }
138 fn gpio_bitbanging(&self) -> Result<Rc<dyn GpioBitbanging>> {
141 Err(TransportError::InvalidInterface(TransportInterfaceType::GpioBitbanging).into())
142 }
143 fn emulator(&self) -> Result<Rc<dyn Emulator>> {
145 Err(TransportError::InvalidInterface(TransportInterfaceType::Emulator).into())
146 }
147
148 fn proxy_ops(&self) -> Result<Rc<dyn ProxyOps>> {
150 Err(TransportError::InvalidInterface(TransportInterfaceType::ProxyOps).into())
151 }
152
153 fn dispatch(&self, _action: &dyn Any) -> Result<Option<Box<dyn serde_annotate::Annotate>>> {
155 Err(TransportError::UnsupportedOperation.into())
156 }
157
158 fn maintain_connection(&self) -> Result<Rc<dyn MaintainConnection>> {
162 Ok(Rc::new(()))
164 }
165}
166
167pub trait MaintainConnection {}
171
172impl MaintainConnection for () {}
175
176pub trait ProxyOps {
178 fn provides_map(&self) -> Result<HashMap<String, String>>;
183
184 fn bootstrap(&self, options: &BootstrapOptions, payload: &[u8]) -> Result<()>;
185 fn apply_pin_strapping(&self, strapping_name: &str) -> Result<()>;
186 fn remove_pin_strapping(&self, strapping_name: &str) -> Result<()>;
187
188 fn apply_default_configuration_with_strap(&self, strapping_name: &str) -> Result<()>;
190}
191
192pub struct Bootstrap {
198 pub image_path: PathBuf,
199}
200
201pub struct SetJtagPins {
203 pub tclk: Option<Rc<dyn GpioPin>>,
204 pub tms: Option<Rc<dyn GpioPin>>,
205 pub tdi: Option<Rc<dyn GpioPin>>,
206 pub tdo: Option<Rc<dyn GpioPin>>,
207 pub trst: Option<Rc<dyn GpioPin>>,
208}
209
210pub trait ProgressIndicator {
211 fn new_stage(&self, name: &str, total: usize);
214 fn progress(&self, absolute: usize);
217}
218
219pub struct UpdateFirmware<'a> {
221 pub firmware: Option<Vec<u8>>,
225 pub progress: Box<dyn ProgressIndicator + 'a>,
227 pub force: bool,
230}
231
232pub struct EmptyTransport;
234
235impl Transport for EmptyTransport {
236 fn capabilities(&self) -> Result<Capabilities> {
237 Ok(Capabilities::new(Capability::NONE))
238 }
239}
240
241#[cfg(test)]
242pub mod tests {
243 use super::*;
244
245 #[test]
246 fn test_capabilities_met() -> anyhow::Result<()> {
247 let cap = Capabilities::new(Capability::UART | Capability::SPI);
248 assert!(cap.request(Capability::UART).ok().is_ok());
249 Ok(())
250 }
251
252 #[test]
253 fn test_capabilities_not_met() -> anyhow::Result<()> {
254 let cap = Capabilities::new(Capability::UART | Capability::SPI);
255 assert!(cap.request(Capability::GPIO).ok().is_err());
256 Ok(())
257 }
258}