Skip to main content

leodos_libcfs/psp/
mem.rs

1//! Low-level PSP wrappers for memory information and access.
2
3use crate::error::Result;
4use crate::ffi;
5use crate::status::check;
6use core::mem::MaybeUninit;
7
8/// Type of memory in the PSP memory table.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[repr(u32)]
11pub enum MemoryType {
12    /// Volatile random-access memory.
13    Ram = ffi::CFE_PSP_MEM_RAM,
14    /// Non-volatile electrically erasable memory.
15    Eeprom = ffi::CFE_PSP_MEM_EEPROM,
16    /// Matches any memory type during validation.
17    Any = ffi::CFE_PSP_MEM_ANY,
18    /// Invalid / unrecognized memory type.
19    Invalid = ffi::CFE_PSP_MEM_INVALID,
20}
21
22impl From<u32> for MemoryType {
23    fn from(val: u32) -> Self {
24        match val {
25            ffi::CFE_PSP_MEM_RAM => Self::Ram,
26            ffi::CFE_PSP_MEM_EEPROM => Self::Eeprom,
27            ffi::CFE_PSP_MEM_ANY => Self::Any,
28            _ => Self::Invalid,
29        }
30    }
31}
32
33impl From<MemoryType> for u32 {
34    fn from(val: MemoryType) -> u32 {
35        val as u32
36    }
37}
38
39/// Information about a specific memory range defined in the PSP memory table.
40#[derive(Debug, Clone, Copy)]
41pub struct MemRangeInfo {
42    /// The type of memory (e.g., RAM, EEPROM).
43    pub memory_type: MemoryType,
44    /// The starting address of the memory range.
45    pub start_addr: usize,
46    /// The size of the memory range in bytes.
47    pub size: usize,
48    /// The word size of the memory (e.g., 1, 2, 4 bytes).
49    pub word_size: usize,
50    /// The attributes of the memory (e.g., read, write).
51    pub attributes: u32,
52}
53
54/// Returns the location and size of the ES Reset information area.
55///
56/// This area is preserved across processor resets. It stores the
57/// ER Log, System Log, and reset-related variables.
58pub fn get_reset_area() -> Result<(usize, usize)> {
59    let mut ptr = MaybeUninit::uninit();
60    let mut size = MaybeUninit::uninit();
61    check(unsafe { ffi::CFE_PSP_GetResetArea(ptr.as_mut_ptr(), size.as_mut_ptr()) })?;
62    Ok((unsafe { ptr.assume_init() }, unsafe { size.assume_init() }
63        as usize))
64}
65
66/// Returns the location and size of the user-reserved memory area.
67pub fn get_user_reserved_area() -> Result<(usize, usize)> {
68    let mut ptr = MaybeUninit::uninit();
69    let mut size = MaybeUninit::uninit();
70    check(unsafe { ffi::CFE_PSP_GetUserReservedArea(ptr.as_mut_ptr(), size.as_mut_ptr()) })?;
71    Ok((unsafe { ptr.assume_init() }, unsafe { size.assume_init() }
72        as usize))
73}
74
75/// Returns the location and size of the memory used for the cFE volatile disk.
76pub fn get_volatile_disk_mem() -> Result<(usize, usize)> {
77    let mut ptr = MaybeUninit::uninit();
78    let mut size = MaybeUninit::uninit();
79    check(unsafe { ffi::CFE_PSP_GetVolatileDiskMem(ptr.as_mut_ptr(), size.as_mut_ptr()) })?;
80    Ok((unsafe { ptr.assume_init() }, unsafe { size.assume_init() }
81        as usize))
82}
83
84/// Validates a memory range against the PSP's memory map.
85///
86/// May return `INVALID_MEM_ADDR` (bad start address),
87/// `INVALID_MEM_TYPE` (type mismatch), or `INVALID_MEM_RANGE`
88/// (range too small for address + size).
89pub fn mem_validate_range(address: usize, size: usize, memory_type: MemoryType) -> Result<()> {
90    check(unsafe { ffi::CFE_PSP_MemValidateRange(address, size, memory_type as u32) })?;
91    Ok(())
92}
93
94/// Returns the number of memory ranges defined in the PSP's memory table.
95pub fn get_mem_ranges() -> u32 {
96    unsafe { ffi::CFE_PSP_MemRanges() }
97}
98
99/// Retrieves one of the records from the PSP's memory table.
100pub fn get_mem_range(range_num: u32) -> Result<MemRangeInfo> {
101    let mut mem_type = MaybeUninit::uninit();
102    let mut start_addr = MaybeUninit::uninit();
103    let mut size = MaybeUninit::uninit();
104    let mut word_size = MaybeUninit::uninit();
105    let mut attributes = MaybeUninit::uninit();
106    check(unsafe {
107        ffi::CFE_PSP_MemRangeGet(
108            range_num,
109            mem_type.as_mut_ptr(),
110            start_addr.as_mut_ptr(),
111            size.as_mut_ptr(),
112            word_size.as_mut_ptr(),
113            attributes.as_mut_ptr(),
114        )
115    })?;
116    Ok(MemRangeInfo {
117        memory_type: MemoryType::from(unsafe { mem_type.assume_init() }),
118        start_addr: unsafe { start_addr.assume_init() },
119        size: unsafe { size.assume_init() },
120        word_size: unsafe { word_size.assume_init() },
121        attributes: unsafe { attributes.assume_init() },
122    })
123}
124
125/// Returns the location and size of the kernel text segment.
126///
127/// This may not be implemented on all platforms.
128pub fn get_kernel_text_segment_info() -> Result<(usize, usize)> {
129    let mut ptr = MaybeUninit::uninit();
130    let mut size = MaybeUninit::uninit();
131    check(unsafe { ffi::CFE_PSP_GetKernelTextSegmentInfo(ptr.as_mut_ptr(), size.as_mut_ptr()) })?;
132    Ok((unsafe { ptr.assume_init() }, unsafe { size.assume_init() }
133        as usize))
134}
135
136/// Returns the location and size of the CFE text segment.
137///
138/// This may not be implemented on all platforms.
139pub fn get_cfe_text_segment_info() -> Result<(usize, usize)> {
140    let mut ptr = MaybeUninit::uninit();
141    let mut size = MaybeUninit::uninit();
142    check(unsafe { ffi::CFE_PSP_GetCFETextSegmentInfo(ptr.as_mut_ptr(), size.as_mut_ptr()) })?;
143    Ok((unsafe { ptr.assume_init() }, unsafe { size.assume_init() }
144        as usize))
145}