opentitanlib/test_utils/
init.rs1use anyhow::Result;
6use clap::Args;
7use directories::ProjectDirs;
8use log::LevelFilter;
9use serde_annotate::Annotate;
10use std::env::ArgsOs;
11use std::ffi::OsString;
12use std::io::ErrorKind;
13use std::iter::Iterator;
14use std::path::PathBuf;
15use std::str::FromStr;
16
17use super::bootstrap::Bootstrap;
18use super::load_bitstream::LoadBitstream;
19use crate::app::TransportWrapper;
20use crate::backend;
21use crate::io::jtag::JtagParams;
22#[derive(Debug, Args)]
25pub struct InitializeTest {
26 #[arg(long, value_parser = PathBuf::from_str, default_value = "config")]
28 pub rcfile: PathBuf,
29
30 #[arg(long, default_value = "off")]
31 pub logging: LevelFilter,
32
33 #[command(flatten)]
34 pub backend_opts: backend::BackendOpts,
35
36 #[command(flatten)]
41 pub load_bitstream: LoadBitstream,
42
43 #[command(flatten)]
44 pub bootstrap: Bootstrap,
45
46 #[command(flatten)]
47 pub jtag_params: JtagParams,
48}
49
50impl InitializeTest {
51 pub fn init_logging(&self) {
52 let level = self.logging;
53 if level != LevelFilter::Off {
56 env_logger::Builder::from_default_env()
57 .format_target(true)
58 .format_module_path(false)
59 .format_timestamp_millis()
60 .filter(None, level)
61 .init();
62 }
63 }
64
65 pub fn parse_command_line(&self, mut args: ArgsOs) -> Result<Vec<OsString>> {
68 self.init_logging();
70 if self.rcfile.as_os_str().is_empty() {
71 return Ok(Vec::new());
73 }
74
75 let rcfile = if let Some(base) = ProjectDirs::from("org", "opentitan", "opentitantool") {
78 base.config_dir().join(&self.rcfile)
79 } else {
80 self.rcfile.clone()
81 };
82
83 let mut arguments = vec![args.next().unwrap()];
85
86 match std::fs::read_to_string(&rcfile) {
88 Ok(content) => {
89 for line in content.split('\n') {
90 let (line, _) = line.split_once('#').unwrap_or((line, ""));
92 arguments.extend(shellwords::split(line)?.iter().map(OsString::from));
93 }
94 Ok(())
95 }
96 Err(e) if e.kind() == ErrorKind::NotFound => {
97 log::warn!("Could not read {:?}. Ignoring.", rcfile);
98 Ok(())
99 }
100 Err(e) => Err(anyhow::Error::new(e).context(format!("Reading file {:?}", rcfile))),
101 }?;
102
103 arguments.extend(args);
105 Ok(arguments)
106 }
107
108 pub fn print_result(operation: &str, result: Result<Option<Box<dyn Annotate>>>) -> Result<()> {
111 match result {
112 Ok(Some(value)) => {
113 log::info!("{}: success.", operation);
114 println!(
115 "\"{}\": {}",
116 operation,
117 serde_json::to_string_pretty(&value)?
118 );
119 Ok(())
120 }
121 Ok(None) => {
122 log::info!("{}: success.", operation);
123 println!("\"{}\": true", operation);
124 Ok(())
125 }
126 Err(e) => {
127 log::info!("{}: {:?}.", operation, e);
128 println!("\"{}\": false", operation);
129 Err(e)
130 }
131 }
132 }
133
134 pub fn init_target(&self) -> Result<TransportWrapper> {
135 let transport = backend::create(&self.backend_opts)?;
137
138 transport.apply_default_configuration(None)?;
140
141 let _uart = self.bootstrap.options.uart_params.create(&transport)?;
143
144 Self::print_result("load_bitstream", self.load_bitstream.init(&transport))?;
146
147 Self::print_result("bootstrap", self.bootstrap.init(&transport))?;
149 Ok(transport)
150 }
151}