@@ -215,37 +215,46 @@ impl BootServices {
215215 }
216216 }
217217
218- /// Stores the current UEFI memory map in the provided buffer.
219- ///
220- /// The allocated buffer must be at least aligned to a [`MemoryDescriptor`]
221- /// and should be big enough to store the whole map. To estimating how big
222- /// the map will be, you can call [`Self::memory_map_size`].
223- ///
224- /// The memory map contains entries of type [`MemoryDescriptor`]. However,
225- /// the relevant step size is always the reported `desc_size` but never
226- /// `size_of::<MemoryDescriptor>()`.
227- ///
228- /// The returned key is a unique identifier of the current configuration of
229- /// memory. Any allocations or such will change the memory map's key.
230- ///
231- /// If you want to store the resulting memory map without having to keep
232- /// the buffer around, you can use `.copied().collect()` on the iterator.
233- /// Note that this will change the current memory map again, if the UEFI
234- /// allocator is used under the hood.
218+ /// Stores the current UEFI memory map in an UEFI-heap allocated buffer
219+ /// and returns a [`MemoryMap`].
235220 ///
236221 /// # Errors
237222 ///
238- /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification for more details.
223+ /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification
224+ /// for more details.
239225 ///
240226 /// * [`uefi::Status::BUFFER_TOO_SMALL`]
241227 /// * [`uefi::Status::INVALID_PARAMETER`]
242- pub fn memory_map < ' buf > ( & self , buffer : & ' buf mut [ u8 ] ) -> Result < MemoryMap < ' buf > > {
243- let mut map_size = buffer. len ( ) ;
244- MemoryDescriptor :: assert_aligned ( buffer) ;
245- let map_buffer = buffer. as_mut_ptr ( ) . cast :: < MemoryDescriptor > ( ) ;
228+ pub fn memory_map ( & self , mt : MemoryType ) -> Result < MemoryMap > {
229+ let mut buffer = MemoryMapBackingMemory :: new ( mt) ?;
230+
231+ let GetMemoryMapResult {
232+ map_size,
233+ map_key,
234+ desc_size,
235+ desc_version,
236+ } = self . get_memory_map ( buffer. as_mut_slice ( ) ) ?;
237+
238+ let len = map_size / desc_size;
239+ assert_eq ! ( map_size % desc_size, 0 ) ;
240+ assert_eq ! ( desc_version, MemoryDescriptor :: VERSION ) ;
241+ Ok ( MemoryMap {
242+ key : map_key,
243+ buf : buffer,
244+ desc_size,
245+ len,
246+ } )
247+ }
248+
249+ /// Calls the underlying `GetMemoryMap` function of UEFI. On success,
250+ /// the buffer is mutated and contains the map. The map might be shorter
251+ /// than the buffer, which is reflected by the return value.
252+ pub ( crate ) fn get_memory_map ( & self , buf : & mut [ u8 ] ) -> Result < GetMemoryMapResult > {
253+ let mut map_size = buf. len ( ) ;
254+ let map_buffer = buf. as_mut_ptr ( ) . cast :: < MemoryDescriptor > ( ) ;
246255 let mut map_key = MemoryMapKey ( 0 ) ;
247256 let mut desc_size = 0 ;
248- let mut entry_version = 0 ;
257+ let mut desc_version = 0 ;
249258
250259 assert_eq ! (
251260 ( map_buffer as usize ) % mem:: align_of:: <MemoryDescriptor >( ) ,
@@ -259,18 +268,14 @@ impl BootServices {
259268 map_buffer,
260269 & mut map_key. 0 ,
261270 & mut desc_size,
262- & mut entry_version ,
271+ & mut desc_version ,
263272 )
264273 }
265- . to_result_with_val ( move || {
266- let len = map_size / desc_size;
267-
268- MemoryMap {
269- key : map_key,
270- buf : buffer,
271- desc_size,
272- len,
273- }
274+ . to_result_with_val ( || GetMemoryMapResult {
275+ map_size,
276+ desc_size,
277+ map_key,
278+ desc_version,
274279 } )
275280 }
276281
@@ -1637,31 +1642,45 @@ pub struct MemoryMapKey(usize);
16371642/// When this type is dropped and boot services are not exited yet, the memory
16381643/// is freed.
16391644#[ derive( Debug ) ]
1640- pub struct MemoryMapBackingMemory ( NonNull < [ u8 ] > /* buffer on UEFI heap */ ) ;
1645+ pub struct MemoryMapBackingMemory ( NonNull < [ u8 ] > ) ;
16411646
16421647impl MemoryMapBackingMemory {
16431648 /// Constructs a new [`MemoryMapBackingMemory`].
16441649 ///
1645- /// # Parameters
1650+ /// # Parameters
16461651 /// - `memory_type`: The memory type for the memory map allocation.
16471652 /// Typically, [`MemoryType::LOADER_DATA`] for regular UEFI applications.
16481653 pub ( crate ) fn new ( memory_type : MemoryType ) -> Result < Self > {
16491654 let st = system_table_boot ( ) . expect ( "Should have boot services activated" ) ;
16501655 let bs = st. boot_services ( ) ;
16511656
16521657 let memory_map_size = bs. memory_map_size ( ) ;
1653- let alloc_size = Self :: allocation_size_hint ( memory_map_size) ;
1654- let ptr = bs. allocate_pool ( memory_type, alloc_size) ?;
1658+ let len = Self :: allocation_size_hint ( memory_map_size) ;
1659+ let ptr = bs. allocate_pool ( memory_type, len) ?;
1660+ assert_eq ! ( ptr. align_offset( mem:: align_of:: <MemoryDescriptor >( ) ) , 0 ) ;
1661+ Ok ( Self :: from_raw ( ptr, len) )
1662+ }
1663+
1664+ fn from_raw ( ptr : * mut u8 , len : usize ) -> Self {
16551665 assert_eq ! ( ptr. align_offset( mem:: align_of:: <MemoryDescriptor >( ) ) , 0 ) ;
16561666
16571667 let ptr = NonNull :: new ( ptr) . expect ( "UEFI should never return a null ptr. An error should have been reflected via an Err earlier." ) ;
1658- let slice = NonNull :: slice_from_raw_parts ( ptr, alloc_size ) ;
1668+ let slice = NonNull :: slice_from_raw_parts ( ptr, len ) ;
16591669
1660- Ok ( Self ( slice) )
1670+ Self ( slice)
1671+ }
1672+
1673+ /// Creates an instance from the provided memory, which is not necessarily
1674+ /// on the UEFI heap.
1675+ #[ cfg( test) ]
1676+ fn from_slice ( buffer : & mut [ u8 ] ) -> Self {
1677+ let len = buffer. len ( ) ;
1678+ Self :: from_raw ( buffer. as_mut_ptr ( ) , len)
16611679 }
16621680
16631681 /// Returns a best-effort size hint of the memory map size. This is
16641682 /// especially created with exiting boot services in mind.
1683+ #[ must_use]
16651684 pub fn allocation_size_hint ( mms : MemoryMapSize ) -> usize {
16661685 let MemoryMapSize {
16671686 desc_size,
@@ -1689,16 +1708,34 @@ impl MemoryMapBackingMemory {
16891708 let allocation_size = map_size + extra_size;
16901709 allocation_size
16911710 }
1692-
1693- /// Returns the raw pointer to the beginning of the allocation.
1694- pub fn as_ptr_mut ( & mut self ) -> * mut u8 {
1711+
1712+ /// Returns a raw pointer to the beginning of the allocation.
1713+ #[ must_use]
1714+ pub fn as_ptr ( & self ) -> * const u8 {
16951715 self . 0 . as_ptr ( ) . cast ( )
16961716 }
1697-
1717+
1718+ /// Returns a mutable raw pointer to the beginning of the allocation.
1719+ #[ must_use]
1720+ pub fn as_mut_ptr ( & mut self ) -> * mut u8 {
1721+ self . 0 . as_ptr ( ) . cast ( )
1722+ }
1723+
16981724 /// Returns the length of the allocation.
1725+ #[ must_use]
16991726 pub fn len ( & self ) -> usize {
17001727 self . 0 . len ( )
1701- }
1728+ }
1729+
1730+ /*#[must_use]
1731+ pub fn as_slice(&self) -> &[u8] {
1732+ self.0.as_ref()
1733+ }*/
1734+
1735+ #[ must_use]
1736+ pub fn as_mut_slice ( & mut self ) -> & mut [ u8 ] {
1737+ unsafe { self . 0 . as_mut ( ) }
1738+ }
17021739}
17031740
17041741impl Drop for MemoryMapBackingMemory {
@@ -1724,6 +1761,14 @@ pub struct MemoryMapSize {
17241761 pub map_size : usize ,
17251762}
17261763
1764+ #[ derive( Copy , Clone , Debug ) ]
1765+ pub struct GetMemoryMapResult {
1766+ pub map_size : usize ,
1767+ pub desc_size : usize ,
1768+ pub map_key : MemoryMapKey ,
1769+ pub desc_version : u32 ,
1770+ }
1771+
17271772/// An accessory to the memory map that can be either iterated or
17281773/// indexed like an array.
17291774///
@@ -1739,35 +1784,36 @@ pub struct MemoryMapSize {
17391784/// always use `entry_size` as step-size when interfacing with the memory map on
17401785/// a low level.
17411786///
1742- ///
1743- ///
17441787/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
17451788#[ derive( Debug ) ]
1746- pub struct MemoryMap < ' buf > {
1789+ pub struct MemoryMap {
1790+ /// Backing memory, properly initialized at this point.
1791+ buf : MemoryMapBackingMemory ,
17471792 key : MemoryMapKey ,
1748- buf : & ' buf mut [ u8 ] ,
17491793 /// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if
17501794 /// this field is ever extended by a new UEFI standard.
17511795 desc_size : usize ,
17521796 len : usize ,
17531797}
17541798
1755- impl < ' buf > MemoryMap < ' buf > {
1756- /// Creates a [`MemoryMap`] from the given buffer and entry size.
1757- /// The entry size is usually bound to the size of a [`MemoryDescriptor`]
1758- /// but can indicate if this field is ever extended by a new UEFI standard.
1759- ///
1760- /// This allows parsing a memory map provided by a kernel after boot
1761- /// services have already exited.
1762- pub fn from_raw ( buf : & ' buf mut [ u8 ] , desc_size : usize ) -> Self {
1763- assert ! ( !buf. is_empty( ) ) ;
1764- assert_eq ! (
1765- buf. len( ) % desc_size,
1766- 0 ,
1767- "The buffer length must be a multiple of the desc_size"
1768- ) ;
1799+ impl MemoryMap {
1800+ /*pub fn new() -> Self {
1801+
1802+ }*/
1803+
1804+ /// Creates a [`MemoryMap`] from the give initialized memory map behind
1805+ /// the buffer and the reported `desc_size` from UEFI.
1806+ pub ( crate ) fn from_initialized_mem (
1807+ buf : MemoryMapBackingMemory ,
1808+ props : GetMemoryMapResult ,
1809+ ) -> Self {
1810+ let GetMemoryMapResult {
1811+ map_size,
1812+ desc_size,
1813+ ..
1814+ } = props;
17691815 assert ! ( desc_size >= mem:: size_of:: <MemoryDescriptor >( ) ) ;
1770- let len = buf . len ( ) / desc_size;
1816+ let len = map_size / desc_size;
17711817 MemoryMap {
17721818 key : MemoryMapKey ( 0 ) ,
17731819 buf,
@@ -1776,6 +1822,20 @@ impl<'buf> MemoryMap<'buf> {
17761822 }
17771823 }
17781824
1825+ #[ cfg( test) ]
1826+ fn from_raw ( buf : & mut [ u8 ] , desc_size : usize ) -> Self {
1827+ let mem = MemoryMapBackingMemory :: from_slice ( buf) ;
1828+ Self :: from_initialized_mem (
1829+ mem,
1830+ GetMemoryMapResult {
1831+ map_size : buf. len ( ) ,
1832+ desc_size,
1833+ map_key : MemoryMapKey ( 0 ) ,
1834+ desc_version : MemoryDescriptor :: VERSION ,
1835+ } ,
1836+ )
1837+ }
1838+
17791839 #[ must_use]
17801840 /// Returns the unique [`MemoryMapKey`] associated with the memory map.
17811841 pub fn key ( & self ) -> MemoryMapKey {
@@ -1870,7 +1930,7 @@ impl<'buf> MemoryMap<'buf> {
18701930
18711931 /// Returns a reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds.
18721932 #[ must_use]
1873- pub fn get ( & self , index : usize ) -> Option < & ' buf MemoryDescriptor > {
1933+ pub fn get ( & self , index : usize ) -> Option < & MemoryDescriptor > {
18741934 if index >= self . len {
18751935 return None ;
18761936 }
@@ -1888,7 +1948,7 @@ impl<'buf> MemoryMap<'buf> {
18881948
18891949 /// Returns a mut reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds.
18901950 #[ must_use]
1891- pub fn get_mut ( & mut self , index : usize ) -> Option < & ' buf mut MemoryDescriptor > {
1951+ pub fn get_mut ( & mut self , index : usize ) -> Option < & mut MemoryDescriptor > {
18921952 if index >= self . len {
18931953 return None ;
18941954 }
@@ -1905,15 +1965,15 @@ impl<'buf> MemoryMap<'buf> {
19051965 }
19061966}
19071967
1908- impl core:: ops:: Index < usize > for MemoryMap < ' _ > {
1968+ impl core:: ops:: Index < usize > for MemoryMap {
19091969 type Output = MemoryDescriptor ;
19101970
19111971 fn index ( & self , index : usize ) -> & Self :: Output {
19121972 self . get ( index) . unwrap ( )
19131973 }
19141974}
19151975
1916- impl core:: ops:: IndexMut < usize > for MemoryMap < ' _ > {
1976+ impl core:: ops:: IndexMut < usize > for MemoryMap {
19171977 fn index_mut ( & mut self , index : usize ) -> & mut Self :: Output {
19181978 self . get_mut ( index) . unwrap ( )
19191979 }
@@ -1922,13 +1982,13 @@ impl core::ops::IndexMut<usize> for MemoryMap<'_> {
19221982/// An iterator of [`MemoryDescriptor`]. The underlying memory map is always
19231983/// associated with a unique [`MemoryMapKey`].
19241984#[ derive( Debug , Clone ) ]
1925- pub struct MemoryMapIter < ' buf > {
1926- memory_map : & ' buf MemoryMap < ' buf > ,
1985+ pub struct MemoryMapIter < ' a > {
1986+ memory_map : & ' a MemoryMap ,
19271987 index : usize ,
19281988}
19291989
1930- impl < ' buf > Iterator for MemoryMapIter < ' buf > {
1931- type Item = & ' buf MemoryDescriptor ;
1990+ impl < ' a > Iterator for MemoryMapIter < ' a > {
1991+ type Item = & ' a MemoryDescriptor ;
19321992
19331993 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
19341994 let sz = self . memory_map . len - self . index ;
@@ -2179,7 +2239,7 @@ mod tests {
21792239 }
21802240
21812241 // Added for debug purposes on test failure
2182- impl core:: fmt:: Display for MemoryMap < ' _ > {
2242+ impl core:: fmt:: Display for MemoryMap {
21832243 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
21842244 writeln ! ( f) ?;
21852245 for desc in self . entries ( ) {
0 commit comments