@@ -11,7 +11,7 @@ use crate::{Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
1111use core:: cell:: UnsafeCell ;
1212use core:: ffi:: c_void;
1313use core:: mem:: { self , MaybeUninit } ;
14- use core:: ops:: { Deref , DerefMut } ;
14+ use core:: ops:: { Deref , DerefMut , Index , IndexMut } ;
1515use core:: ptr:: NonNull ;
1616use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
1717use core:: { ptr, slice} ;
@@ -1804,6 +1804,95 @@ impl MemoryMapMeta {
18041804 }
18051805}
18061806
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+
18071896/// An accessory to the memory map that can be either iterated or
18081897/// indexed like an array.
18091898///
0 commit comments