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