@@ -11,7 +11,7 @@ use crate::{Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
11
11
use core:: cell:: UnsafeCell ;
12
12
use core:: ffi:: c_void;
13
13
use core:: mem:: { self , MaybeUninit } ;
14
- use core:: ops:: { Deref , DerefMut } ;
14
+ use core:: ops:: { Deref , DerefMut , Index , IndexMut } ;
15
15
use core:: ptr:: NonNull ;
16
16
use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
17
17
use core:: { ptr, slice} ;
@@ -1804,6 +1804,95 @@ impl MemoryMapMeta {
1804
1804
}
1805
1805
}
1806
1806
1807
+ /// An accessory to the UEFI memory map that can be either iterated or indexed
1808
+ /// like an array.
1809
+ ///
1810
+ /// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`]
1811
+ /// bundled with the ma.
1812
+ ///
1813
+ /// To iterate over the entries, call [`MemoryMap::entries`].
1814
+ ///
1815
+ /// ## UEFI pitfalls
1816
+ /// **Please note** that when working with memory maps, the `entry_size` is
1817
+ /// usually larger than `size_of::<MemoryDescriptor` [[0]]. So to be safe,
1818
+ /// always use `entry_size` as step-size when interfacing with the memory map on
1819
+ /// a low level.
1820
+ ///
1821
+ /// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
1822
+ pub trait MemoryMap : Index < usize , Output = MemoryDescriptor > {
1823
+ // TODO also require IntoIterator?! :)
1824
+
1825
+ /// Returns the associated [`MemoryMapMeta`].
1826
+ #[ must_use]
1827
+ fn meta ( & self ) -> MemoryMapMeta ;
1828
+
1829
+ /// Returns the associated [`MemoryMapKey`].
1830
+ #[ must_use]
1831
+ fn key ( & self ) -> MemoryMapKey ;
1832
+
1833
+ /// Returns the number of keys in the map.
1834
+ #[ must_use]
1835
+ fn len ( & self ) -> usize ;
1836
+
1837
+ /// Returns a reference to the [`MemoryDescriptor`] at the given index, if
1838
+ /// present.
1839
+ #[ must_use]
1840
+ fn get ( & self , index : usize ) -> Option < & MemoryDescriptor > {
1841
+ if index >= self . len ( ) {
1842
+ None
1843
+ } else {
1844
+ let offset = index * self . meta ( ) . desc_size ;
1845
+ unsafe {
1846
+ self . buffer ( )
1847
+ . as_ptr ( )
1848
+ . add ( offset)
1849
+ . cast :: < MemoryDescriptor > ( )
1850
+ . as_ref ( )
1851
+ }
1852
+ }
1853
+ }
1854
+
1855
+ /// Returns a reference to the underlying memory.
1856
+ fn buffer ( & self ) -> & [ u8 ] ;
1857
+
1858
+ /// Returns an Iterator of type [`MemoryMapIter`].
1859
+ fn entries ( & self ) -> MemoryMapIter < ' _ > ;
1860
+ }
1861
+
1862
+ /// Extension to [`MemoryMap`] that adds mutable operations. This also includes
1863
+ /// the ability to sort the memory map.
1864
+ pub trait MemoryMapMut : MemoryMap + IndexMut < usize > {
1865
+ /// Returns a mutable reference to the [`MemoryDescriptor`] at the given
1866
+ /// index, if present.
1867
+ #[ must_use]
1868
+ fn get_mut ( & mut self , index : usize ) -> Option < & mut MemoryDescriptor > {
1869
+ if index >= self . len ( ) {
1870
+ None
1871
+ } else {
1872
+ let offset = index * self . meta ( ) . desc_size ;
1873
+ unsafe {
1874
+ self . buffer_mut ( )
1875
+ . as_mut_ptr ( )
1876
+ . add ( offset)
1877
+ . cast :: < MemoryDescriptor > ( )
1878
+ . as_mut ( )
1879
+ }
1880
+ }
1881
+ }
1882
+
1883
+ /// Sorts the memory map by physical address in place. This operation is
1884
+ /// optional and should be invoked only once.
1885
+ #[ must_use]
1886
+ fn sort ( & mut self ) ;
1887
+
1888
+ /// Returns a reference to the underlying memory.
1889
+ ///
1890
+ /// # Safety
1891
+ ///
1892
+ /// This is unsafe as there is a potential to create invalid entries.
1893
+ unsafe fn buffer_mut ( & self ) -> & mut [ u8 ] ;
1894
+ }
1895
+
1807
1896
/// An accessory to the memory map that can be either iterated or
1808
1897
/// indexed like an array.
1809
1898
///
0 commit comments