1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::convert::TryInto;
use std::result::Result;
pub trait RegmapAccessor<T> {
type Error;
fn peek(&mut self, addr: T) -> Result<T, Self::Error>;
fn poke(&mut self, addr: T, data: T) -> Result<(), Self::Error>;
}
pub struct MemoryAccessor {
base: *mut u8,
}
impl MemoryAccessor {
pub fn new(base: usize) -> MemoryAccessor {
MemoryAccessor {
base: base as *mut u8,
}
}
}
impl RegmapAccessor<u32> for MemoryAccessor {
type Error = ();
fn peek(&mut self, addr: u32) -> Result<u32, Self::Error> {
unsafe {
let ptr = self.base.offset(
addr.try_into()
.expect("Couldn't convert offset into isize in peek32"),
) as *mut u32;
Ok(*ptr)
}
}
fn poke(&mut self, addr: u32, data: u32) -> Result<(), Self::Error> {
unsafe {
let ptr = self.base.offset(
addr.try_into()
.expect("Couldn't convert offset into isize in poke32"),
) as *mut u32;
*ptr = data;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{MemoryAccessor, RegmapAccessor32Bit};
use std::convert::TryInto;
#[test]
fn can_peek() {
let mut backing = vec![0u8; 1024];
backing[12] = 5;
let mut accessor = MemoryAccessor::new(backing.as_ptr() as usize);
assert_eq!(accessor.peek32(12), 5);
}
#[test]
fn can_poke() {
let backing = vec![0u8; 1024];
let mut accessor = MemoryAccessor::new(backing.as_ptr() as usize);
accessor.poke32(40, 0x12345678);
assert_eq!(backing[40 + 0], 0x78);
assert_eq!(backing[40 + 1], 0x56);
assert_eq!(backing[40 + 2], 0x34);
assert_eq!(backing[40 + 3], 0x12);
}
}