From 335a62bb06f090a43f9afe7c3de8373a76adf2f0 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 15:53:31 +0100 Subject: [PATCH 1/7] [bazel,qemu] Add UART break toggle QEMU properties These will be required to support using break for Serial Rescue 1.0 in the ROM_EXT, as we need to mock values in the oversampled UART `VAL` register based upon the transmission of break conditions via the QEMU monitor, which when received are controlled by these properties. Signed-off-by: Alex Jones --- rules/opentitan/qemu.bzl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rules/opentitan/qemu.bzl b/rules/opentitan/qemu.bzl index 95a3fd16e5349..18476c2418970 100644 --- a/rules/opentitan/qemu.bzl +++ b/rules/opentitan/qemu.bzl @@ -494,6 +494,12 @@ def _test_dispatch(ctx, exec_env, firmware): # to run, finish, and exit, which we don't want to happen. qemu_args += ["-global", "ot-ibex_wrapper.dv-sim-status-exit=off"] + # To enable limited support for UART rescue in the ROM_EXT, we need to + # be able to toggle break signals on/off in QEMU's UART and mock this + # in the oversampled `VAL` register. + qemu_args += ["-global", "ot-uart.oversample-break=true"] + qemu_args += ["-global", "ot-uart.toggle-break=true"] + # Add parameter-specified globals. if param["globals"]: globals = json.decode(param["globals"]) From d1eb19edb2348a8d6dd0290e355e1499aa440c13 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 15:57:53 +0100 Subject: [PATCH 2/7] [otlib,qemu] Quit QEMU on dropping monitor instead of transport If any QEMU devices need to hold a reference to the QEMU monitor then dropping the QEMU transport could result in the monitor being used to quit QEMU before the devices can cleanup on drop. Instead, quit QEMU via the monitor when dropping the Monitor. Signed-off-by: Alex Jones --- .../opentitanlib/src/transport/qemu/mod.rs | 15 +------------- .../src/transport/qemu/monitor.rs | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/sw/host/opentitanlib/src/transport/qemu/mod.rs b/sw/host/opentitanlib/src/transport/qemu/mod.rs index 593988e936286..0f1dd9fe4f89f 100644 --- a/sw/host/opentitanlib/src/transport/qemu/mod.rs +++ b/sw/host/opentitanlib/src/transport/qemu/mod.rs @@ -48,9 +48,6 @@ pub struct Qemu { /// QEMU log modelled as a UART. log: Option>, - - /// Whether to quit QEMU when dropped. - quit: bool, } impl Qemu { @@ -66,7 +63,7 @@ impl Qemu { /// to a device using one of the flags in the list above. The kind must /// match what OpenTitanLib expects to be accepted. pub fn from_options(options: QemuOpts) -> anyhow::Result { - let mut monitor = Monitor::new(options.qemu_monitor_tty.unwrap())?; + let mut monitor = Monitor::new(options.qemu_monitor_tty.unwrap(), options.qemu_quit)?; // Get list of configured chardevs from QEMU. let chardevs = monitor.query_chardevs()?; @@ -131,20 +128,10 @@ impl Qemu { console, log, spi, - quit: options.qemu_quit, }) } } -impl Drop for Qemu { - fn drop(&mut self) { - // Quit QEMU when dropped if requested. - if self.quit { - self.monitor.borrow_mut().quit().ok(); - } - } -} - impl Transport for Qemu { fn capabilities(&self) -> anyhow::Result { // We have to unconditionally claim to support GPIO because of the reset diff --git a/sw/host/opentitanlib/src/transport/qemu/monitor.rs b/sw/host/opentitanlib/src/transport/qemu/monitor.rs index 7e777d259f447..8c57686fceece 100644 --- a/sw/host/opentitanlib/src/transport/qemu/monitor.rs +++ b/sw/host/opentitanlib/src/transport/qemu/monitor.rs @@ -24,11 +24,14 @@ pub struct Monitor { /// Incrementing ID attached to each command and checked with each response. id_counter: usize, + + /// Whether to quit QEMU when dropped. + quit_qemu: bool, } impl Monitor { /// Connect to the QEMU monitor over a given TTY. - pub fn new>(tty_path: P) -> anyhow::Result { + pub fn new>(tty_path: P, quit_qemu: bool) -> anyhow::Result { let tty = serialport::new( tty_path.as_ref().to_str().context("TTY path not UTF8")?, 115200, @@ -55,7 +58,11 @@ impl Monitor { micro = version.qemu.micro ); - let mut monitor = Monitor { tty, id_counter: 0 }; + let mut monitor = Monitor { + tty, + id_counter: 0, + quit_qemu, + }; // Negotiate capabilities. // We don't need any, but the protocol requires us to do this. @@ -164,6 +171,15 @@ impl Monitor { } } +impl Drop for Monitor { + fn drop(&mut self) { + // Quit QEMU when dropped if requested. + if self.quit_qemu { + self.quit().ok(); + } + } +} + /// Possible responses from the server. #[derive(Deserialize)] #[serde(untagged)] From 1c6e053fb167d7871745aa18aa44482edd80f4a0 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 16:01:30 +0100 Subject: [PATCH 3/7] [otlib,qemu] Add optional arguments when sending QEMU Monitor cmd Some commands might need to supply optional arguments as some JSON serialized string. Add an optional `arguments` field to the QEMU Monitor's `send_cmd` function that supports this functionality. Signed-off-by: Alex Jones --- .../src/transport/qemu/monitor.rs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/sw/host/opentitanlib/src/transport/qemu/monitor.rs b/sw/host/opentitanlib/src/transport/qemu/monitor.rs index 8c57686fceece..a248de0589934 100644 --- a/sw/host/opentitanlib/src/transport/qemu/monitor.rs +++ b/sw/host/opentitanlib/src/transport/qemu/monitor.rs @@ -66,42 +66,42 @@ impl Monitor { // Negotiate capabilities. // We don't need any, but the protocol requires us to do this. - monitor.send_cmd("qmp_capabilities")?; + monitor.send_cmd("qmp_capabilities", None)?; Ok(monitor) } /// Send a continue command either starting or resuming the emulation. pub fn cont(&mut self) -> anyhow::Result<()> { - self.send_cmd("cont")?; + self.send_cmd("cont", None)?; Ok(()) } /// Stop the emulation (resumable, does not quit QEMU). pub fn stop(&mut self) -> anyhow::Result<()> { - self.send_cmd("stop")?; + self.send_cmd("stop", None)?; Ok(()) } /// Reset the system within the emulation. pub fn reset(&mut self) -> anyhow::Result<()> { - self.send_cmd("system_reset")?; + self.send_cmd("system_reset", None)?; Ok(()) } /// Gracefully shut down QEMU and terminate the process. pub fn quit(&mut self) -> anyhow::Result<()> { - self.send_cmd("quit")?; + self.send_cmd("quit", None)?; Ok(()) } /// List the IDs of the currently configured `chardev`s. pub fn query_chardevs(&mut self) -> anyhow::Result> { - let response = self.send_cmd("query-chardev")?; + let response = self.send_cmd("query-chardev", None)?; let serde_json::Value::Array(response) = response else { bail!("expected array of chardevs"); }; @@ -125,13 +125,17 @@ impl Monitor { /// /// We only support synchronous commands, i.e. we wait for a response before /// sending anything new. - fn send_cmd(&mut self, cmd: &str) -> anyhow::Result { + fn send_cmd(&mut self, cmd: &str, args: Option<&str>) -> anyhow::Result { let id = self.id_counter; - writeln!( - self.tty.get_mut(), - r#"{{ "execute": "{cmd}", "id": {id} }}"# - )?; + let command = match args { + Some(arguments) => { + format!(r#"{{ "execute": "{cmd}", "arguments": {arguments}, "id": {id} }}"#) + } + None => format!(r#"{{ "execute": "{cmd}", "id": {id} }}"#), + }; + + writeln!(self.tty.get_mut(), "{}", command.as_str())?; // Increment the ID for the next message. self.id_counter += 1; From ac6d0f4946f2a08acdc92bf931cf678da166328b Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 16:02:58 +0100 Subject: [PATCH 4/7] [otlib,qemu] Add monitor command for sending a UART break This command can be used to send a UART break condition to a CharDev identified by a given identifier. Signed-off-by: Alex Jones --- sw/host/opentitanlib/src/transport/qemu/monitor.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sw/host/opentitanlib/src/transport/qemu/monitor.rs b/sw/host/opentitanlib/src/transport/qemu/monitor.rs index a248de0589934..590113b75de3b 100644 --- a/sw/host/opentitanlib/src/transport/qemu/monitor.rs +++ b/sw/host/opentitanlib/src/transport/qemu/monitor.rs @@ -115,6 +115,15 @@ impl Monitor { Ok(chardevs) } + pub fn send_chardev_break(&mut self, id: &str) -> anyhow::Result<()> { + self.send_cmd( + "chardev-send-break", + Some(format!(r#"{{"id": "{id}"}}"#).as_str()), + )?; + + Ok(()) + } + /// Send a command over the JSON QMP interface. /// /// The protocol goes: From 0830f3293a3fc406e6318cf75f87e26cfab087ba Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 16:05:30 +0100 Subject: [PATCH 5/7] [otlib,qemu] Wrap QEMU UART implementation to send breaks via monitor TO support the requires use of Serial Break for rescue via reading the UART's oversampled `VAL` register in the ROM_EXT, introduce a mechanism that uses the QEMU monitor to send break conditions to the UART, which are subsequently tracked by the QEMU UART device to mock the required behaviour. Signed-off-by: Alex Jones --- sw/host/opentitanlib/BUILD | 1 + .../opentitanlib/src/transport/qemu/mod.rs | 18 +-- .../opentitanlib/src/transport/qemu/uart.rs | 114 ++++++++++++++++++ 3 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 sw/host/opentitanlib/src/transport/qemu/uart.rs diff --git a/sw/host/opentitanlib/BUILD b/sw/host/opentitanlib/BUILD index e0608feb994e9..15e142e84ad59 100644 --- a/sw/host/opentitanlib/BUILD +++ b/sw/host/opentitanlib/BUILD @@ -219,6 +219,7 @@ rust_library( "src/transport/qemu/monitor.rs", "src/transport/qemu/reset.rs", "src/transport/qemu/spi.rs", + "src/transport/qemu/uart.rs", "src/transport/ti50emulator/emu.rs", "src/transport/ti50emulator/gpio.rs", "src/transport/ti50emulator/i2c.rs", diff --git a/sw/host/opentitanlib/src/transport/qemu/mod.rs b/sw/host/opentitanlib/src/transport/qemu/mod.rs index 0f1dd9fe4f89f..65545637c79cd 100644 --- a/sw/host/opentitanlib/src/transport/qemu/mod.rs +++ b/sw/host/opentitanlib/src/transport/qemu/mod.rs @@ -5,6 +5,7 @@ pub mod monitor; pub mod reset; pub mod spi; +pub mod uart; use std::cell::RefCell; use std::rc::Rc; @@ -20,6 +21,7 @@ use crate::transport::common::uart::SerialPortUart; use crate::transport::qemu::monitor::{Chardev, ChardevKind, Monitor}; use crate::transport::qemu::reset::QemuReset; use crate::transport::qemu::spi::QemuSpi; +use crate::transport::qemu::uart::QemuUart; use crate::transport::{ Capabilities, Capability, Transport, TransportError, TransportInterfaceType, }; @@ -63,10 +65,13 @@ impl Qemu { /// to a device using one of the flags in the list above. The kind must /// match what OpenTitanLib expects to be accepted. pub fn from_options(options: QemuOpts) -> anyhow::Result { - let mut monitor = Monitor::new(options.qemu_monitor_tty.unwrap(), options.qemu_quit)?; + let monitor = Rc::new(RefCell::new(Monitor::new( + options.qemu_monitor_tty.unwrap(), + options.qemu_quit, + )?)); // Get list of configured chardevs from QEMU. - let chardevs = monitor.query_chardevs()?; + let chardevs = monitor.borrow_mut().query_chardevs()?; fn find_chardev<'a>(chardevs: &'a [Chardev], id: &str) -> Option<&'a ChardevKind> { chardevs .iter() @@ -76,10 +81,11 @@ impl Qemu { // Console UART: let console = match find_chardev(&chardevs, "console") { Some(ChardevKind::Pty { path }) => { - let uart: Rc = Rc::new( + let serial_port = SerialPortUart::open_pseudo(path.to_str().unwrap(), CONSOLE_BAUDRATE) - .context("failed to open QEMU console PTY")?, - ); + .context("failed to open QEMU console PTY")?; + let uart: Rc = + Rc::new(QemuUart::new(Rc::clone(&monitor), "console", serial_port)); Some(uart) } _ => { @@ -116,8 +122,6 @@ impl Qemu { } }; - let monitor = Rc::new(RefCell::new(monitor)); - // Resetting is done over the monitor, but we model it like a pin to enable strapping it. let reset = QemuReset::new(Rc::clone(&monitor)); let reset = Rc::new(reset); diff --git a/sw/host/opentitanlib/src/transport/qemu/uart.rs b/sw/host/opentitanlib/src/transport/qemu/uart.rs new file mode 100644 index 0000000000000..3b2aec740a855 --- /dev/null +++ b/sw/host/opentitanlib/src/transport/qemu/uart.rs @@ -0,0 +1,114 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +use std::cell::RefCell; +use std::os::fd::BorrowedFd; +use std::rc::Rc; +use std::time::Duration; + +use anyhow::Result; +use serialport::Parity; + +use crate::io::uart::Uart; +use crate::transport::NonblockingHelp; +use crate::transport::common::uart::SerialPortUart; +use crate::transport::qemu::monitor::Monitor; + +pub struct QemuUart { + /// Connection to the QEMU monitor which can control the emulator. + pub monitor: Rc>, + + // The UART CharDev's id + id: String, + + // Underlying SerialPort used for the UART. + serial_port: SerialPortUart, + + // Whether the UART is currently transmitting a break condition or not. + in_break: RefCell, +} + +impl QemuUart { + pub fn new(monitor: Rc>, id: &str, serial_port: SerialPortUart) -> Self { + Self { + monitor, + id: id.into(), + serial_port, + in_break: RefCell::new(false), + } + } +} + +impl Uart for QemuUart { + fn get_baudrate(&self) -> Result { + self.serial_port.get_baudrate() + } + + fn set_baudrate(&self, baudrate: u32) -> Result<()> { + self.serial_port.set_baudrate(baudrate) + } + + fn set_flow_control(&self, flow_control: bool) -> Result<()> { + self.serial_port.set_flow_control(flow_control) + } + + fn get_device_path(&self) -> Result { + self.serial_port.get_device_path() + } + + fn read(&self, buf: &mut [u8]) -> Result { + self.serial_port.read(buf) + } + + fn read_timeout(&self, buf: &mut [u8], timeout: Duration) -> Result { + self.serial_port.read_timeout(buf, timeout) + } + + fn write(&self, buf: &[u8]) -> Result<()> { + self.serial_port.write(buf) + } + + fn clear_rx_buffer(&self) -> Result<()> { + self.serial_port.clear_rx_buffer() + } + + fn set_break(&self, enable: bool) -> Result<()> { + // Assumes we have ot-uart.toggle-break=true, so always send break + if *self.in_break.borrow() ^ enable { + self.monitor.borrow_mut().send_chardev_break(&self.id)?; + *self.in_break.borrow_mut() = enable; + } + Ok(()) + } + + fn set_parity(&self, parity: Parity) -> Result<()> { + self.serial_port.set_parity(parity) + } + + fn supports_nonblocking_read(&self) -> Result { + self.serial_port.supports_nonblocking_read() + } + + fn register_nonblocking_read(&self, registry: &mio::Registry, token: mio::Token) -> Result<()> { + self.serial_port.register_nonblocking_read(registry, token) + } + + fn nonblocking_help(&self) -> Result> { + self.serial_port.nonblocking_help() + } + + fn borrow_fd(&self) -> Result { + self.serial_port.borrow_fd() + } +} + +impl Drop for QemuUart { + fn drop(&mut self) { + // Stop transmitting break before deleting the UART + if *self.in_break.borrow() { + let _ = self.monitor.borrow_mut().send_chardev_break(&self.id); + *self.in_break.borrow_mut() = false; + } + } +} From 95319c42a699d20d38051b51129c593bf7806696 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 16:07:24 +0100 Subject: [PATCH 6/7] [otlib,qemu] Add RESET strapping definition for QEMU devices Signed-off-by: Alex Jones --- .../opentitanlib/src/app/config/opentitan_qemu.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sw/host/opentitanlib/src/app/config/opentitan_qemu.json b/sw/host/opentitanlib/src/app/config/opentitan_qemu.json index 9f5951fade49c..9a3bd8a284405 100644 --- a/sw/host/opentitanlib/src/app/config/opentitan_qemu.json +++ b/sw/host/opentitanlib/src/app/config/opentitan_qemu.json @@ -10,6 +10,17 @@ "level": true, }, ], + "strappings": [ + { + "name": "RESET", + "pins": [ + { + "name": "RESET", + "level": false + } + ] + } + ], "uarts": [ { "name": "console", From c4bff2b4ec88c2758806480c1f11b7fbc17a44b6 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 00:10:18 +0100 Subject: [PATCH 7/7] [bazel,qemu] Add QEMU envs for E2E boot service tests This commit only includes the non-ownership (activate, unlock) tests, as the ownership tests are separated due to their need for more complicated test infrastructure. All tests are supported and passing in QEMU with the exception of the `boot_service_wakeup` test, which is not expected to work, as QEMU's pwrmgr currently does not model low power entry/exit. Signed-off-by: Alex Jones --- .../rom_ext/e2e/boot_svc/BUILD | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD b/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD index c060655f07504..c16b8e6cfbb4a 100644 --- a/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD +++ b/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD @@ -11,6 +11,7 @@ load( "fpga_params", "opentitan_binary", "opentitan_test", + "qemu_params", ) load("//rules:manifest.bzl", "manifest") @@ -40,6 +41,7 @@ opentitan_test( exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", @@ -47,6 +49,11 @@ opentitan_test( exit_success = "FinalBootLog: 4:AAAA\r\n", ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", + qemu = qemu_params( + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", + exit_failure = "BFV|PASS|FAIL", + exit_success = "FinalBootLog: 4:AAAA\r\n", + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status", @@ -66,6 +73,7 @@ opentitan_test( exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( timeout = "moderate", @@ -83,6 +91,20 @@ opentitan_test( """, ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", + qemu = qemu_params( + timeout = "moderate", + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", + exit_failure = "BFV|PASS|FAIL", + exit_success = "mode: RESQ\r\n", + # TODO: add bootstrap when QEMU bootstraps instead of splicing firmware + test_cmd = """ + --exec="transport init" + --exec="console --non-interactive --exit-success='{exit_success}' --exit-failure='{exit_failure}'" + # Try the `REBO` mode and make sure it works. + --exec="rescue no-op --reset-target=reboot" + no-op + """, + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status", @@ -102,6 +124,7 @@ opentitan_test( exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + # Not supported in QEMU whilst low power is not modelled }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a}", @@ -139,6 +162,7 @@ NEXT_TEST_SEQUENCES = [ exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", @@ -147,6 +171,11 @@ NEXT_TEST_SEQUENCES = [ exit_success = "FinalBootLog: 3:{}\r\n".format(test_sequence), ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", + qemu = qemu_params( + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", + exit_failure = "BFV:.*|PASS|FAIL", + exit_success = "FinalBootLog: 3:{}\r\n".format(test_sequence), + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status", @@ -169,6 +198,7 @@ opentitan_test( exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", @@ -184,6 +214,12 @@ opentitan_test( """, ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", + qemu = qemu_params( + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", + exit_failure = "BFV:.*|PASS|FAIL", + exit_success = "FinalBootLog: 5:ABBBA\r\n", + # TODO: add bootstrap when QEMU bootstraps instead of splicing firmware + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status", @@ -204,6 +240,7 @@ opentitan_test( exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", @@ -211,6 +248,11 @@ opentitan_test( exit_success = "FinalBootLog: 3:AAA\r\n", ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", + qemu = qemu_params( + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", + exit_failure = "BFV:.*|PASS|FAIL", + exit_success = "FinalBootLog: 3:AAA\r\n", + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status", @@ -231,6 +273,7 @@ opentitan_test( exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", @@ -238,6 +281,11 @@ opentitan_test( exit_success = "FinalBootLog: 3:ABA\r\n", ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", + qemu = qemu_params( + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{owner_slot_a} {firmware}@{owner_slot_b}", + exit_failure = "BFV:.*|PASS|FAIL", + exit_success = "FinalBootLog: 3:ABA\r\n", + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status", @@ -273,6 +321,7 @@ opentitan_binary( exec_env = [ "//hw/top_earlgrey:fpga_hyper310_rom_ext", "//hw/top_earlgrey:fpga_cw340_rom_ext", + "//hw/top_earlgrey:sim_qemu_rom_ext", ], linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", manifest = ":manifest_version_5", @@ -302,6 +351,7 @@ MIN_SEC_VER_SLOTS = [ exec_env = { "//hw/top_earlgrey:fpga_hyper310_rom_ext": None, "//hw/top_earlgrey:fpga_cw340_rom_ext": None, + "//hw/top_earlgrey:sim_qemu_rom_ext": None, }, fpga = fpga_params( assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{v0_slot} {min_sec_ver_5:signed_bin}@{v5_slot}", @@ -322,6 +372,14 @@ MIN_SEC_VER_SLOTS = [ ), linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual", manifest = ":manifest_version_4", + qemu = qemu_params( + assemble = "{rom_ext}@{rom_ext_slot_a} {firmware}@{v0_slot} {min_sec_ver_5:signed_bin}@{v5_slot}", + binaries = { + ":min_sec_ver_5": "min_sec_ver_5", + }, + v0_slot = "{{owner_slot_{}}}".format(slots[0]), + v5_slot = "{{owner_slot_{}}}".format(slots[1]), + ), deps = [ ":boot_svc_test_lib", "//sw/device/lib/base:status",