fake_mmio/inject/
range_override.rs1use std::ops::Range;
6
7use crate::inject::{GenericVmoMemoryHandler, VmoMemoryHandler, VmoOpHelper};
8use crate::operand::MmioOperand;
9
10pub struct RangeOverride<P, O> {
13 maybe_override: O,
14 parent: P,
15}
16
17impl<P, O> RangeOverride<P, O> {
18 pub fn new(parent: P, maybe_override: O) -> Self {
21 Self { maybe_override, parent }
22 }
23}
24
25impl<P: VmoMemoryHandler, O: MaybeVmoMemoryHandler> GenericVmoMemoryHandler
26 for RangeOverride<P, O>
27{
28 fn load<T: MmioOperand>(&self, op: VmoOpHelper<'_, T>) -> T {
29 match self.maybe_override.get_handler(op.range()) {
30 Some(handler) => T::load(handler, op),
31 None => T::load(&self.parent, op),
32 }
33 }
34
35 fn store<T: MmioOperand>(&self, op: VmoOpHelper<'_, T>, value: T) {
36 match self.maybe_override.get_handler(op.range()) {
37 Some(handler) => T::store(handler, op, value),
38 None => T::store(&self.parent, op, value),
39 }
40 }
41}
42
43pub trait MaybeVmoMemoryHandler {
45 fn get_handler(&self, range: Range<usize>) -> Option<&(impl VmoMemoryHandler + ?Sized)>;
48}
49
50#[cfg(test)]
55mod mock {
56 use super::*;
57
58 mockall::mock! {
59 pub MaybeVmoMemoryHandler<T: VmoMemoryHandler + 'static> {
60 pub fn get_handler<'a>(&'a self, range: Range<usize>) -> Option<&'a T>;
61 }
62 }
63
64 impl<T: VmoMemoryHandler + 'static> MaybeVmoMemoryHandler for MockMaybeVmoMemoryHandler<T> {
65 fn get_handler(&self, range: Range<usize>) -> Option<&(impl VmoMemoryHandler + ?Sized)> {
66 self.get_handler(range)
67 }
68 }
69}
70#[cfg(test)]
71pub use mock::*;
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use crate::CachedVmoMemory;
77 use crate::inject::dispatch::DispatchBuilder;
78 use crate::inject::passthrough::Passthrough;
79 use crate::inject::{MockVmoMemoryHandler, VmoMemory};
80 use mmio::MmioExt as _;
81
82 #[test]
83 fn test_range_override() {
84 let expected_val = 0xcafe_babe_u32;
85 let mut mock = MockVmoMemoryHandler::new();
86 let _ = mock
87 .expect_load32()
88 .once()
89 .withf(|op| op.offset() == 0 && op.range() == (0..4))
90 .return_const(expected_val);
91
92 let dispatch = DispatchBuilder::new().insert_node(0..4, mock).build();
93 let handler = RangeOverride::new(Passthrough, dispatch);
94
95 let mut mmio = CachedVmoMemory::new_mapped(4096)
96 .expect("Failed to map VMO.")
97 .map(|vmo| VmoMemory::new(handler, vmo));
98
99 assert_eq!(mmio.load::<u32>(0), expected_val);
101
102 let val_outside = 0x1234_5678_u32;
104 mmio.store::<u32>(4, val_outside);
105 assert_eq!(mmio.load::<u32>(4), val_outside);
106 }
107}