1
+ //! Module for the traits [`MemoryMap`] and [`MemoryMapMut`].
2
+
3
+ use super :: * ;
4
+ use core:: fmt:: Debug ;
5
+
6
+ /// An accessory to the UEFI memory map and associated metadata that can be
7
+ /// either iterated or indexed like an array.
8
+ ///
9
+ /// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`]
10
+ /// bundled with the map.
11
+ ///
12
+ /// To iterate over the entries, call [`MemoryMap::entries`].
13
+ ///
14
+ /// ## UEFI pitfalls
15
+ /// Note that a MemoryMap can quickly become outdated, as soon as any explicit
16
+ /// or hidden allocation happens.
17
+ ///
18
+ /// As soon as boot services are excited, all previous obtained memory maps must
19
+ /// be considered as outdated, except if the [`MemoryMapKey`] equals the one
20
+ /// returned by `exit_boot_services()`.
21
+ ///
22
+ /// **Please note** that when working with memory maps, the `entry_size` is
23
+ /// usually larger than `size_of::<MemoryDescriptor` [[0]]. So to be safe,
24
+ /// always use `entry_size` as step-size when interfacing with the memory map on
25
+ /// a low level.
26
+ ///
27
+ /// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
28
+ pub trait MemoryMap : Debug {
29
+ // TODO also require IntoIterator?! :)
30
+
31
+ /// Returns the associated [`MemoryMapMeta`].
32
+ #[ must_use]
33
+ fn meta ( & self ) -> MemoryMapMeta ;
34
+
35
+ /// Returns the associated [`MemoryMapKey`].
36
+ #[ must_use]
37
+ fn key ( & self ) -> MemoryMapKey ;
38
+
39
+ /// Returns the number of keys in the map.
40
+ #[ must_use]
41
+ fn len ( & self ) -> usize ;
42
+
43
+ /// Returns if the memory map is empty.
44
+ #[ must_use]
45
+ 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]
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
+ fn buffer ( & self ) -> & [ u8 ] ;
69
+
70
+ /// Returns an Iterator of type [`MemoryMapIter`].
71
+ fn entries ( & self ) -> MemoryMapIter < ' _ > ;
72
+ }
73
+
74
+ /// Extension to [`MemoryMap`] that adds mutable operations. This also includes
75
+ /// the ability to sort the memory map.
76
+ pub trait MemoryMapMut : MemoryMap {
77
+ /// Returns a mutable reference to the [`MemoryDescriptor`] at the given
78
+ /// index, if present.
79
+ #[ must_use]
80
+ fn get_mut ( & mut self , index : usize ) -> Option < & mut MemoryDescriptor > {
81
+ if index >= self . len ( ) {
82
+ None
83
+ } else {
84
+ let offset = index * self . meta ( ) . desc_size ;
85
+ unsafe {
86
+ self . buffer_mut ( )
87
+ . as_mut_ptr ( )
88
+ . add ( offset)
89
+ . cast :: < MemoryDescriptor > ( )
90
+ . as_mut ( )
91
+ }
92
+ }
93
+ }
94
+
95
+ /// Sorts the memory map by physical address in place. This operation is
96
+ /// optional and should be invoked only once.
97
+ fn sort ( & mut self ) ;
98
+
99
+ /// Returns a reference to the underlying memory.
100
+ ///
101
+ /// # Safety
102
+ ///
103
+ /// This is unsafe as there is a potential to create invalid entries.
104
+ unsafe fn buffer_mut ( & mut self ) -> & mut [ u8 ] ;
105
+ }
0 commit comments