• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Module for the traits [`MemoryMap`] and [`MemoryMapMut`].
2 
3 use super::*;
4 use core::fmt::Debug;
5 use core::ops::{Index, IndexMut};
6 
7 /// An accessory to the UEFI memory map and associated metadata that can be
8 /// either iterated or indexed like an array.
9 ///
10 /// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`]
11 /// bundled with the map.
12 ///
13 /// To iterate over the entries, call [`MemoryMap::entries`].
14 ///
15 /// ## UEFI pitfalls
16 /// Note that a MemoryMap can quickly become outdated, as soon as any explicit
17 /// or hidden allocation happens.
18 ///
19 /// As soon as boot services are excited, all previous obtained memory maps must
20 /// be considered as outdated, except if the [`MemoryMapKey`] equals the one
21 /// returned by `exit_boot_services()`.
22 ///
23 /// **Please note** that when working with memory maps, the `entry_size` is
24 /// usually larger than `size_of::<MemoryDescriptor` [[0]]. So to be safe,
25 /// always use `entry_size` as step-size when interfacing with the memory map on
26 /// a low level.
27 ///
28 /// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
29 pub trait MemoryMap: Debug + Index<usize, Output = MemoryDescriptor> {
30     /// Returns the associated [`MemoryMapMeta`].
31     #[must_use]
meta(&self) -> MemoryMapMeta32     fn meta(&self) -> MemoryMapMeta;
33 
34     /// Returns the associated [`MemoryMapKey`]. Note that this isn't
35     /// necessarily the key of the latest valid UEFI memory map.
36     #[must_use]
key(&self) -> MemoryMapKey37     fn key(&self) -> MemoryMapKey;
38 
39     /// Returns the number of keys in the map.
40     #[must_use]
len(&self) -> usize41     fn len(&self) -> usize;
42 
43     /// Returns if the memory map is empty.
44     #[must_use]
is_empty(&self) -> bool45     fn is_empty(&self) -> bool {
46         self.len() == 0
47     }
48 
49     /// Returns a reference to the [`MemoryDescriptor`] at the given index, if
50     /// present.
51     #[must_use]
get(&self, index: usize) -> Option<&MemoryDescriptor>52     fn get(&self, index: usize) -> Option<&MemoryDescriptor> {
53         if index >= self.len() {
54             None
55         } else {
56             let offset = index * self.meta().desc_size;
57             unsafe {
58                 self.buffer()
59                     .as_ptr()
60                     .add(offset)
61                     .cast::<MemoryDescriptor>()
62                     .as_ref()
63             }
64         }
65     }
66 
67     /// Returns a reference to the underlying memory.
68     #[must_use]
buffer(&self) -> &[u8]69     fn buffer(&self) -> &[u8];
70 
71     /// Returns an Iterator of type [`MemoryMapIter`].
72     #[must_use]
entries(&self) -> MemoryMapIter<'_>73     fn entries(&self) -> MemoryMapIter<'_>;
74 
75     /// Returns if the underlying memory map is sorted regarding the physical
76     /// address start.
77     #[must_use]
is_sorted(&self) -> bool78     fn is_sorted(&self) -> bool {
79         let iter = self.entries();
80         let iter = iter.clone().zip(iter.skip(1));
81 
82         for (curr, next) in iter {
83             if next.phys_start < curr.phys_start {
84                 log::debug!("next.phys_start < curr.phys_start: curr={curr:?}, next={next:?}");
85                 return false;
86             }
87         }
88         true
89     }
90 }
91 
92 /// Extension to [`MemoryMap`] that adds mutable operations. This also includes
93 /// the ability to sort the memory map.
94 pub trait MemoryMapMut: MemoryMap + IndexMut<usize> {
95     /// Returns a mutable reference to the [`MemoryDescriptor`] at the given
96     /// index, if present.
97     #[must_use]
get_mut(&mut self, index: usize) -> Option<&mut MemoryDescriptor>98     fn get_mut(&mut self, index: usize) -> Option<&mut MemoryDescriptor> {
99         if index >= self.len() {
100             None
101         } else {
102             let offset = index * self.meta().desc_size;
103             unsafe {
104                 self.buffer_mut()
105                     .as_mut_ptr()
106                     .add(offset)
107                     .cast::<MemoryDescriptor>()
108                     .as_mut()
109             }
110         }
111     }
112 
113     /// Sorts the memory map by physical address in place. This operation is
114     /// optional and should be invoked only once.
sort(&mut self)115     fn sort(&mut self);
116 
117     /// Returns a reference to the underlying memory.
118     ///
119     /// # Safety
120     ///
121     /// This is unsafe as there is a potential to create invalid entries.
buffer_mut(&mut self) -> &mut [u8]122     unsafe fn buffer_mut(&mut self) -> &mut [u8];
123 }
124