1use anyhow::{Result, bail, ensure};
6use clap::ValueEnum;
7use serde::{Deserialize, Serialize};
8use std::rc::Rc;
9use std::thread;
10use std::time::{Duration, Instant};
11use thiserror::Error;
12
13use crate::io::i2c;
14use crate::io::spi;
15use crate::tpm::access::TpmAccess;
16use crate::tpm::status::TpmStatus;
17
18#[allow(non_camel_case_types)]
20#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ValueEnum)]
21#[value(rename_all = "verbatim")]
22pub enum Register {
23 ACCESS,
24 INT_ENABLE,
25 INT_VECTOR,
26 INT_STATUS,
27 INTF_CAPABILITY,
28 STS,
29 DATA_FIFO,
30 INTERFACE_ID,
31 XDATA_FIFO,
32 DID_VID,
33 RID,
34}
35
36impl Register {
37 pub fn size(&self) -> Option<usize> {
39 Some(match *self {
40 Self::ACCESS => 1,
41 Self::INT_ENABLE => 4,
42 Self::INT_VECTOR => 4,
43 Self::INT_STATUS => 4,
44 Self::INTF_CAPABILITY => 4,
45 Self::STS => 4,
46 Self::DATA_FIFO => return None,
47 Self::INTERFACE_ID => 4,
48 Self::XDATA_FIFO => return None,
49 Self::DID_VID => 4,
50 Self::RID => 4,
51 })
52 }
53}
54
55#[derive(Error, Debug)]
57pub enum TpmError {
58 #[error("TPM timeout")]
59 Timeout,
60 #[error("Unexpected response size {0}")]
61 UnexpectedResponseSize(usize),
62 #[error("Response incomplete. Missing {0} bytes.")]
63 ResponseIncomplete(usize),
64 #[error("Failed to get status")]
65 ReadStatusFail,
66 #[error("Timeout polling for response")]
67 ResponseTimeout,
68}
69
70pub trait Driver {
72 fn init(&self) -> Result<()> {
74 self.write_register(
75 Register::ACCESS,
76 &TpmAccess::ACTIVE_LOCALITY.bits().to_be_bytes(),
77 )?;
78 self.write_register(
79 Register::ACCESS,
80 &TpmAccess::REQUEST_USE.bits().to_be_bytes(),
81 )?;
82 Ok(())
83 }
84
85 fn read_register(&self, register: Register, data: &mut [u8]) -> Result<()>;
87
88 fn write_register(&self, register: Register, data: &[u8]) -> Result<()>;
90
91 fn execute_command(&self, cmd: &[u8]) -> Result<Vec<u8>> {
93 self.write_register(Register::STS, &TpmStatus::CMD_READY.to_le_bytes())?;
94
95 log::debug!("RUN({}) {:02X?}", cmd.len(), cmd);
96 let burst_count = self.poll_for_ready()?.burst_count();
97 for slice in cmd.chunks(burst_count) {
98 self.write_register(Register::DATA_FIFO, slice)?;
99 }
100 self.write_register(Register::STS, &TpmStatus::TPM_GO.to_le_bytes())?;
101
102 let burst_count = self.poll_for_data_available()?.burst_count();
103 let mut result: Vec<u8> = vec![0; burst_count];
104 self.read_register(Register::DATA_FIFO, result.as_mut_slice())?;
105 let resp_size: usize = u32::from_be_bytes(result[2..6].try_into().unwrap()) as usize;
106 ensure!(
107 resp_size < MAX_RESPONSE_SIZE,
108 TpmError::UnexpectedResponseSize(resp_size)
109 );
110 let mut remaining = resp_size - result.len();
111
112 let mut sts = self.read_status()?;
113 while sts.is_valid() && sts.data_available() && remaining > 0 {
114 let to_read: usize = remaining.min(burst_count);
115 let mut result2: Vec<u8> = vec![0; to_read];
116 self.read_register(Register::DATA_FIFO, result2.as_mut_slice())?;
117 result.append(&mut result2);
118 remaining -= to_read;
119 sts = self.read_status()?;
120 }
121 ensure!(remaining == 0, TpmError::ResponseIncomplete(remaining));
122 log::debug!("RES({}) {:02X?}", result.len(), result.as_slice());
123
124 self.write_register(Register::STS, &TpmStatus::CMD_READY.to_le_bytes())?;
126
127 Ok(result)
128 }
129
130 fn read_status(&self) -> Result<TpmStatus> {
132 let mut out = [0u8; 4];
133 let res = self.read_register(Register::STS, &mut out);
134 if res.is_ok() {
135 Ok(TpmStatus::from_bytes(out))
136 } else {
137 log::error!("Failed to read status");
138 Err(TpmError::ReadStatusFail.into())
139 }
140 }
141
142 fn poll_for_data_available(&self) -> Result<TpmStatus> {
144 const STATUS_POLL_TIMEOUT: Duration = Duration::from_secs(5 * 60);
146 let deadline = Instant::now() + STATUS_POLL_TIMEOUT;
147 let mut sts = self.read_status()?;
148 while !sts.is_valid()
151 || !sts.data_available()
152 || sts.raw_value() == !0
153 || (sts.raw_value() & 0xFF) == 0xFF
155 {
156 if Instant::now() > deadline {
157 log::error!("Status poll timeout.");
158 return Err(TpmError::ResponseTimeout.into());
159 }
160 sts = self.read_status()?;
161 thread::sleep(Duration::from_millis(10));
162 }
163 Ok(sts)
164 }
165
166 fn poll_for_ready(&self) -> Result<TpmStatus> {
168 const STATUS_POLL_TIMEOUT: Duration = Duration::from_millis(30000);
169 let deadline = Instant::now() + STATUS_POLL_TIMEOUT;
170 let mut sts = self.read_status()?;
171 while !sts.is_valid()
174 || !sts.is_ready()
175 || sts.raw_value() == !0
176 || (sts.raw_value() & 0xFF) == 0xFF
178 {
179 ensure!(Instant::now() <= deadline, TpmError::Timeout);
180 sts = self.read_status()?;
181 thread::sleep(Duration::from_millis(10));
182 }
183 Ok(sts)
184 }
185}
186
187pub struct SpiDriver {
189 spi: Rc<dyn spi::Target>,
190 use_gsc_ready: bool,
191}
192
193impl SpiDriver {
194 pub fn new(spi: Rc<dyn spi::Target>, use_gsc_ready: bool) -> Result<Self> {
195 Ok(Self { spi, use_gsc_ready })
196 }
197
198 pub fn addr(register: Register) -> u16 {
200 match register {
201 Register::ACCESS => 0x0000,
202 Register::INT_ENABLE => 0x0008,
203 Register::INT_VECTOR => 0x000C,
204 Register::INT_STATUS => 0x0010,
205 Register::INTF_CAPABILITY => 0x0014,
206 Register::STS => 0x0018,
207 Register::DATA_FIFO => 0x0024,
208 Register::INTERFACE_ID => 0x0030,
209 Register::XDATA_FIFO => 0x0080,
210 Register::DID_VID => 0x0F00,
211 Register::RID => 0x0F04,
212 }
213 }
214
215 fn compose_header(&self, register: Register, len: usize, is_read: bool) -> [u8; 4] {
216 let mut req: u32 = ((len as u32 - 1) << SPI_TPM_DATA_LEN_POS)
217 | SPI_TPM_ADDRESS_OFFSET
218 | (Self::addr(register) as u32);
219 if is_read {
220 req |= SPI_TPM_READ;
221 } else {
222 req |= SPI_TPM_WRITE;
223 }
224 req.to_be_bytes()
225 }
226
227 fn write_header(&self, register: Register, len: usize, is_read: bool) -> Result<()> {
229 let mut buffer = [0u8; 4];
230 let req = self.compose_header(register, len, is_read);
231 self.spi
232 .run_transaction(&mut [spi::Transfer::Both(&req, &mut buffer)])?;
233 if buffer[3] & 1 == 0 {
237 let start_time = Instant::now();
239 while {
240 self.spi
241 .run_transaction(&mut [spi::Transfer::Read(&mut buffer[0..1])])?;
242 buffer[0] & 1 == 0
243 } {
244 if Instant::now().duration_since(start_time) > TIMEOUT {
245 bail!(TpmError::Timeout)
246 }
247 }
248 }
249 Ok(())
250 }
251
252 fn do_read_register(&self, register: Register, data: &mut [u8]) -> Result<()> {
253 let _cs_asserted = Rc::clone(&self.spi).assert_cs()?; self.write_header(register, data.len(), true)?;
255 self.spi.run_transaction(&mut [spi::Transfer::Read(data)])?;
256 Ok(())
257 }
258
259 fn do_write_register(&self, register: Register, data: &[u8]) -> Result<()> {
260 let _cs_asserted = Rc::clone(&self.spi).assert_cs()?; self.write_header(register, data.len(), false)?;
262 self.spi
263 .run_transaction(&mut [spi::Transfer::Write(data)])?;
264 Ok(())
265 }
266}
267
268const SPI_TPM_READ: u32 = 0xC0000000;
269const SPI_TPM_WRITE: u32 = 0x40000000;
270const SPI_TPM_DATA_LEN_POS: u8 = 24;
271const SPI_TPM_ADDRESS_OFFSET: u32 = 0x00D40000;
272
273const MAX_RESPONSE_SIZE: usize = 4096;
274const TIMEOUT: Duration = Duration::from_millis(500);
275
276impl Driver for SpiDriver {
277 fn read_register(&self, register: Register, data: &mut [u8]) -> Result<()> {
278 if !self.spi.supports_tpm_poll()? {
279 return self.do_read_register(register, data);
281 }
282 let req = self.compose_header(register, data.len(), true );
283 if self.use_gsc_ready {
284 self.spi.run_transaction(&mut [
285 spi::Transfer::Write(&req),
286 spi::Transfer::TpmPoll,
287 spi::Transfer::Read(data),
288 spi::Transfer::GscReady,
289 ])
290 } else {
291 self.spi.run_transaction(&mut [
292 spi::Transfer::Write(&req),
293 spi::Transfer::TpmPoll,
294 spi::Transfer::Read(data),
295 ])
296 }
297 }
298
299 fn write_register(&self, register: Register, data: &[u8]) -> Result<()> {
300 if !self.spi.supports_tpm_poll()? {
301 return self.do_write_register(register, data);
303 }
304 let req = self.compose_header(register, data.len(), false );
305 if self.use_gsc_ready {
306 self.spi.run_transaction(&mut [
307 spi::Transfer::Write(&req),
308 spi::Transfer::TpmPoll,
309 spi::Transfer::Write(data),
310 spi::Transfer::GscReady,
311 ])
312 } else {
313 self.spi.run_transaction(&mut [
314 spi::Transfer::Write(&req),
315 spi::Transfer::TpmPoll,
316 spi::Transfer::Write(data),
317 ])
318 }
319 }
320}
321
322pub struct I2cDriver {
324 i2c: Rc<dyn i2c::Bus>,
325 use_gsc_ready: bool,
326}
327
328impl I2cDriver {
329 pub fn new(i2c: Rc<dyn i2c::Bus>, use_gsc_ready: bool) -> Result<Self> {
330 Ok(Self { i2c, use_gsc_ready })
331 }
332
333 pub fn addr(reg: Register) -> Option<u8> {
335 match reg {
336 Register::ACCESS => Some(0x00),
337 Register::STS => Some(0x01),
338 Register::DATA_FIFO => Some(0x05),
339 Register::DID_VID => Some(0x06),
340 _ => None,
341 }
342 }
343
344 fn try_read_register(&self, register: Register, data: &mut [u8]) -> Result<()> {
345 if !self.use_gsc_ready {
346 self.i2c.run_transaction(
348 None, &mut [
350 i2c::Transfer::Write(&[Self::addr(register).unwrap()]),
351 i2c::Transfer::Read(data),
352 ],
353 )
354 } else {
355 self.i2c.run_transaction(
356 None, &mut [
358 i2c::Transfer::Write(&[Self::addr(register).unwrap()]),
359 i2c::Transfer::GscReady,
360 i2c::Transfer::Read(data),
361 ],
362 )
363 }
364 }
365}
366
367impl Driver for I2cDriver {
368 fn read_register(&self, register: Register, data: &mut [u8]) -> Result<()> {
369 const MAX_TRIES: usize = 10;
370 let mut count = 0;
371 let res = loop {
373 count += 1;
374 match self.try_read_register(register, data) {
375 Err(e) => {
376 log::trace!(
377 "Register 0x{:X} access error: {}",
378 Self::addr(register).unwrap(),
379 e
380 );
381 if count == MAX_TRIES {
382 break Err(e);
383 }
384 }
385 Ok(()) => {
386 if count > 1 {
387 log::trace!("Success after {} tries.", count);
388 }
389 break Ok(());
390 }
391 }
392 thread::sleep(Duration::from_millis(100));
393 };
394 if res.is_err() {
395 log::error!("Failed to read TPM register.");
396 }
397 res
398 }
399
400 fn write_register(&self, register: Register, data: &[u8]) -> Result<()> {
401 let mut buffer = vec![Self::addr(register).unwrap()];
402 buffer.extend_from_slice(data);
403 if !self.use_gsc_ready {
404 self.i2c.run_transaction(
405 None, &mut [i2c::Transfer::Write(&buffer)],
407 )
408 } else {
409 self.i2c.run_transaction(
410 None, &mut [i2c::Transfer::Write(&buffer), i2c::Transfer::GscReady],
412 )
413 }
414 }
415}