cyclone_v/memory/
dev_mem.rs1#![cfg(feature = "std")]
2use crate::memory::MemoryMapper;
3use std::fmt;
4use std::ops::{Index, RangeBounds};
5use std::os::fd::AsRawFd;
6use std::os::unix::fs::OpenOptionsExt;
7
8pub struct DevMemMemoryMapper {
11 region: &'static [u8],
12 physical: (usize, usize),
13}
14
15impl fmt::Debug for DevMemMemoryMapper {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 f.debug_struct("DevMemMemoryMapper")
18 .field(
19 "region",
20 &format_args!("0x{:p}..0x{:p}", self.region.as_ptr(), unsafe {
21 self.region.as_ptr().add(self.region.len())
22 }),
23 )
24 .field(
25 "physical",
26 &format_args!("{:#X} ({} bytes)", self.physical.0, self.physical.1),
27 )
28 .finish()
29 }
30}
31
32impl MemoryMapper for DevMemMemoryMapper {
33 fn create(address: usize, size: usize) -> Result<Self, &'static str> {
34 unsafe {
35 let file = std::fs::OpenOptions::new()
36 .read(true)
37 .write(true)
38 .custom_flags(libc::O_SYNC | libc::O_CLOEXEC)
39 .open("/dev/mem")
40 .map_err(|_| "Unable to open /dev/mem")?;
41 let fd = file.as_raw_fd();
42
43 let res = libc::mmap(
44 std::ptr::null_mut(),
45 size as libc::size_t,
46 libc::PROT_READ | libc::PROT_WRITE,
47 libc::MAP_SHARED,
48 fd,
49 address as libc::off_t,
50 );
51
52 if res == libc::MAP_FAILED {
53 return Err("Unable to map memory region");
54 }
55
56 Ok(Self {
57 region: core::slice::from_raw_parts_mut(res as *mut u8, size),
58 physical: (address, size),
59 })
60 }
61 }
62
63 fn len(&self) -> usize {
64 self.region.len()
65 }
66
67 fn as_ptr<T>(&self) -> *const T {
68 self.region.as_ptr() as *const T
69 }
70
71 fn as_mut_ptr<T>(&mut self) -> *mut T {
72 self.region.as_ptr() as *mut T
73 }
74}
75
76impl Drop for DevMemMemoryMapper {
77 fn drop(&mut self) {
78 unsafe {
79 let _ = libc::munmap(self.region.as_ptr() as *mut libc::c_void, self.region.len());
81 }
82 }
83}
84
85impl<R: RangeBounds<usize>> Index<R> for DevMemMemoryMapper {
86 type Output = [u8];
87
88 fn index(&self, index: R) -> &Self::Output {
89 self.as_range(index)
90 }
91}