| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| use crate::interface::serve_command; |
| use log::LevelFilter; |
| use mio::{Events, Interest, Poll, Token}; |
| use opentitanlib::backend; |
| use opentitanlib::io::i2c::I2cParams; |
| use opentitanlib::io::spi::SpiParams; |
| use opentitanlib::tpm::{Driver, I2cDriver, SpiDriver}; |
| use std::net::{SocketAddr, TcpListener}; |
| use structopt::StructOpt; |
| |
| mod interface; |
| |
| #[derive(Debug, StructOpt)] |
| pub enum TpmBus { |
| Spi { |
| #[structopt(flatten)] |
| params: SpiParams, |
| }, |
| I2C { |
| #[structopt(flatten)] |
| params: I2cParams, |
| }, |
| } |
| |
| #[derive(Debug, StructOpt)] |
| #[structopt( |
| name = "tpm2-test-server", |
| about = "A tool for processing TPM commands over a TCP port." |
| )] |
| struct Opts { |
| #[structopt(subcommand)] |
| bus: TpmBus, |
| |
| #[structopt(long, default_value = "off")] |
| logging: LevelFilter, |
| |
| #[structopt(flatten)] |
| backend_opts: backend::BackendOpts, |
| |
| #[structopt( |
| short, |
| long, |
| default_value = "9883", |
| help = "TCP port for incoming connections." |
| )] |
| tpm_port: u16, |
| } |
| |
| const CMD_TOKEN: Token = Token(0); |
| const PLATFORM_TOKEN: Token = Token(1); |
| |
| pub fn main() -> std::io::Result<()> { |
| let options = Opts::from_args(); |
| env_logger::Builder::from_default_env() |
| .filter(None, options.logging) |
| .init(); |
| let cmd_addr = SocketAddr::from(([127, 0, 0, 1], options.tpm_port)); |
| let platform_addr = SocketAddr::from(([127, 0, 0, 1], options.tpm_port + 1)); |
| let cmd_listener = TcpListener::bind(cmd_addr)?; |
| let platform_listener = TcpListener::bind(platform_addr)?; |
| |
| let mut cmd_stream = mio::net::TcpStream::from_std(cmd_listener.accept()?.0); |
| let mut platform_stream = mio::net::TcpStream::from_std(platform_listener.accept()?.0); |
| |
| let mut poll = Poll::new()?; |
| let mut events = Events::with_capacity(128); |
| poll.registry() |
| .register(&mut platform_stream, PLATFORM_TOKEN, Interest::READABLE)?; |
| |
| poll.registry() |
| .register(&mut cmd_stream, CMD_TOKEN, Interest::READABLE)?; |
| |
| let transport = backend::create(&options.backend_opts).unwrap(); |
| let bus: Box<dyn Driver> = match options.bus { |
| TpmBus::Spi { params } => { |
| let spi = params.create(&transport, "").unwrap(); |
| Box::new(SpiDriver::new(spi)) |
| } |
| TpmBus::I2C { params } => { |
| let i2c = params.create(&transport).unwrap(); |
| Box::new(I2cDriver::new(i2c, 0)) |
| } |
| }; |
| bus.init().unwrap(); |
| |
| loop { |
| poll.poll(&mut events, None)?; |
| |
| for event in events.iter() { |
| match event.token() { |
| CMD_TOKEN => { |
| if serve_command(&mut cmd_stream, &*bus).unwrap() { |
| return Ok(()); |
| } |
| } |
| PLATFORM_TOKEN => { |
| if serve_command(&mut platform_stream, &*bus).unwrap() { |
| return Ok(()); |
| } |
| } |
| Token(_) => todo!(), |
| } |
| } |
| } |
| } |