opentitanlib/util/
rom_detect.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::Result;
6use regex::Regex;
7use std::time::Duration;
8use std::time::Instant;
9
10use crate::io::uart::Uart;
11use crate::uart::console::{ExitStatus, UartConsole};
12use crate::util::usr_access::usr_access_get;
13
14pub struct RomDetect {
15    usr_access: u32,
16    console: UartConsole,
17}
18
19impl RomDetect {
20    pub fn new(bitstream: &[u8], timeout: Option<Duration>) -> Result<RomDetect> {
21        Ok(RomDetect {
22            usr_access: usr_access_get(bitstream)?,
23            console: UartConsole {
24                timeout,
25                exit_success: Some(Regex::new(r"(\w*ROM):([^\r\n]+)[\r\n]").unwrap()),
26                ..Default::default()
27            },
28        })
29    }
30
31    pub fn detect(&mut self, uart: &dyn Uart) -> Result<bool> {
32        let t0 = Instant::now();
33        let rc = self.console.interact(uart, None, None)?;
34        let t1 = Instant::now();
35        log::debug!("detect exit={:?}, duration={:?}", rc, t1 - t0);
36        if let Some(cap) = self.console.captures(ExitStatus::ExitSuccess) {
37            log::info!("Current bitstream: {:?}", cap.get(0).unwrap().as_str());
38            let fpga = cap
39                .get(2)
40                .map(|v| u32::from_str_radix(v.as_str(), 16))
41                .unwrap()?;
42            return Ok(fpga == self.usr_access);
43        }
44        log::info!("Did not detect the ROM identification message.");
45        Ok(false)
46    }
47}