blob: af455d6c82e979b0775df8d11064584fcafa5c02 [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! Boot sequence traits for SPI monitor.
//!
//! This module provides the trait-based interface used by boot code to interact
//! with SPI monitor hardware during platform initialization.
use super::types::{
BootError, BootResult, MonitorInstance, MonitorStatus, MuxSelect, PrivilegeDirection,
PrivilegeOp,
};
/// Abstract hardware interface for SPI monitor boot operations.
///
/// Implementations of this trait provide register-level access to SPI monitor
/// blocks via PAC or other register models. Boot code uses this trait to remain
/// independent of the concrete register implementation.
pub trait Monitor {
/// Set monitor mux to ROT or Host control.
fn set_mux(&mut self, instance: MonitorInstance, mux: MuxSelect) -> BootResult<()>;
/// Read current mux setting.
fn read_mux(&self, instance: MonitorInstance) -> BootResult<MuxSelect>;
/// Soft reset monitor (clears status/logs, preserves policy).
fn soft_reset(&mut self, instance: MonitorInstance) -> BootResult<()>;
/// Hardware reset monitor (full reset of all state).
fn hardware_reset(&mut self, instance: MonitorInstance) -> BootResult<()>;
/// Configure an address privilege region.
///
/// # Arguments
/// * `instance` - Monitor instance to configure
/// * `start_addr` - Start address (inclusive)
/// * `end_addr` - End address (inclusive)
/// * `direction` - Read or Write direction
/// * `op` - Allow or Block access
fn set_address_privilege(
&mut self,
instance: MonitorInstance,
start_addr: u32,
end_addr: u32,
direction: PrivilegeDirection,
op: PrivilegeOp,
) -> BootResult<()>;
/// Read number of configured address privilege regions.
fn read_region_count(&self, instance: MonitorInstance) -> BootResult<u32>;
/// Read monitor status snapshot.
fn read_status(&self, instance: MonitorInstance) -> BootResult<MonitorStatus>;
/// Check if policy write-lock is supported by this monitor.
fn supports_policy_lock(&self) -> bool {
false
}
/// Lock policy tables to prevent further modification.
///
/// Returns error if not supported by hardware.
fn lock_policy(&mut self, _instance: MonitorInstance) -> BootResult<()> {
if !self.supports_policy_lock() {
return Err(BootError::LockedOutFromMonitor);
}
Ok(())
}
/// Verify that policy is locked (if supported).
///
/// No-op if policy lock is not supported.
fn verify_policy_locked(&self, instance: MonitorInstance) -> BootResult<()> {
if !self.supports_policy_lock() {
return Ok(());
}
let status = self.read_status(instance)?;
if status.policy_locked {
Ok(())
} else {
Err(BootError::PolicyVerificationFailed)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mux_select_conversion() {
assert_eq!(ExtMuxSel::from(MuxSelect::RotControl), ExtMuxSel::Sel0);
assert_eq!(ExtMuxSel::from(MuxSelect::HostControl), ExtMuxSel::Sel1);
}
#[test]
fn test_mux_select_round_trip() {
let orig = MuxSelect::RotControl;
let ext = ExtMuxSel::from(orig);
let restored: MuxSelect = ext.into();
assert_eq!(orig, restored);
}
}