@@ -215,37 +215,46 @@ impl BootServices {
215
215
}
216
216
}
217
217
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`].
235
220
///
236
221
/// # Errors
237
222
///
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.
239
225
///
240
226
/// * [`uefi::Status::BUFFER_TOO_SMALL`]
241
227
/// * [`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 > ( ) ;
246
255
let mut map_key = MemoryMapKey ( 0 ) ;
247
256
let mut desc_size = 0 ;
248
- let mut entry_version = 0 ;
257
+ let mut desc_version = 0 ;
249
258
250
259
assert_eq ! (
251
260
( map_buffer as usize ) % mem:: align_of:: <MemoryDescriptor >( ) ,
@@ -259,18 +268,14 @@ impl BootServices {
259
268
map_buffer,
260
269
& mut map_key. 0 ,
261
270
& mut desc_size,
262
- & mut entry_version ,
271
+ & mut desc_version ,
263
272
)
264
273
}
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,
274
279
} )
275
280
}
276
281
@@ -1637,31 +1642,45 @@ pub struct MemoryMapKey(usize);
1637
1642
/// When this type is dropped and boot services are not exited yet, the memory
1638
1643
/// is freed.
1639
1644
#[ derive( Debug ) ]
1640
- pub struct MemoryMapBackingMemory ( NonNull < [ u8 ] > /* buffer on UEFI heap */ ) ;
1645
+ pub struct MemoryMapBackingMemory ( NonNull < [ u8 ] > ) ;
1641
1646
1642
1647
impl MemoryMapBackingMemory {
1643
1648
/// Constructs a new [`MemoryMapBackingMemory`].
1644
1649
///
1645
- /// # Parameters
1650
+ /// # Parameters
1646
1651
/// - `memory_type`: The memory type for the memory map allocation.
1647
1652
/// Typically, [`MemoryType::LOADER_DATA`] for regular UEFI applications.
1648
1653
pub ( crate ) fn new ( memory_type : MemoryType ) -> Result < Self > {
1649
1654
let st = system_table_boot ( ) . expect ( "Should have boot services activated" ) ;
1650
1655
let bs = st. boot_services ( ) ;
1651
1656
1652
1657
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 {
1655
1665
assert_eq ! ( ptr. align_offset( mem:: align_of:: <MemoryDescriptor >( ) ) , 0 ) ;
1656
1666
1657
1667
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 ) ;
1659
1669
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)
1661
1679
}
1662
1680
1663
1681
/// Returns a best-effort size hint of the memory map size. This is
1664
1682
/// especially created with exiting boot services in mind.
1683
+ #[ must_use]
1665
1684
pub fn allocation_size_hint ( mms : MemoryMapSize ) -> usize {
1666
1685
let MemoryMapSize {
1667
1686
desc_size,
@@ -1689,16 +1708,34 @@ impl MemoryMapBackingMemory {
1689
1708
let allocation_size = map_size + extra_size;
1690
1709
allocation_size
1691
1710
}
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 {
1695
1715
self . 0 . as_ptr ( ) . cast ( )
1696
1716
}
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
+
1698
1724
/// Returns the length of the allocation.
1725
+ #[ must_use]
1699
1726
pub fn len ( & self ) -> usize {
1700
1727
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
+ }
1702
1739
}
1703
1740
1704
1741
impl Drop for MemoryMapBackingMemory {
@@ -1724,6 +1761,14 @@ pub struct MemoryMapSize {
1724
1761
pub map_size : usize ,
1725
1762
}
1726
1763
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
+
1727
1772
/// An accessory to the memory map that can be either iterated or
1728
1773
/// indexed like an array.
1729
1774
///
@@ -1739,35 +1784,36 @@ pub struct MemoryMapSize {
1739
1784
/// always use `entry_size` as step-size when interfacing with the memory map on
1740
1785
/// a low level.
1741
1786
///
1742
- ///
1743
- ///
1744
1787
/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
1745
1788
#[ derive( Debug ) ]
1746
- pub struct MemoryMap < ' buf > {
1789
+ pub struct MemoryMap {
1790
+ /// Backing memory, properly initialized at this point.
1791
+ buf : MemoryMapBackingMemory ,
1747
1792
key : MemoryMapKey ,
1748
- buf : & ' buf mut [ u8 ] ,
1749
1793
/// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if
1750
1794
/// this field is ever extended by a new UEFI standard.
1751
1795
desc_size : usize ,
1752
1796
len : usize ,
1753
1797
}
1754
1798
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;
1769
1815
assert ! ( desc_size >= mem:: size_of:: <MemoryDescriptor >( ) ) ;
1770
- let len = buf . len ( ) / desc_size;
1816
+ let len = map_size / desc_size;
1771
1817
MemoryMap {
1772
1818
key : MemoryMapKey ( 0 ) ,
1773
1819
buf,
@@ -1776,6 +1822,20 @@ impl<'buf> MemoryMap<'buf> {
1776
1822
}
1777
1823
}
1778
1824
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
+
1779
1839
#[ must_use]
1780
1840
/// Returns the unique [`MemoryMapKey`] associated with the memory map.
1781
1841
pub fn key ( & self ) -> MemoryMapKey {
@@ -1870,7 +1930,7 @@ impl<'buf> MemoryMap<'buf> {
1870
1930
1871
1931
/// Returns a reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds.
1872
1932
#[ must_use]
1873
- pub fn get ( & self , index : usize ) -> Option < & ' buf MemoryDescriptor > {
1933
+ pub fn get ( & self , index : usize ) -> Option < & MemoryDescriptor > {
1874
1934
if index >= self . len {
1875
1935
return None ;
1876
1936
}
@@ -1888,7 +1948,7 @@ impl<'buf> MemoryMap<'buf> {
1888
1948
1889
1949
/// Returns a mut reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds.
1890
1950
#[ 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 > {
1892
1952
if index >= self . len {
1893
1953
return None ;
1894
1954
}
@@ -1905,15 +1965,15 @@ impl<'buf> MemoryMap<'buf> {
1905
1965
}
1906
1966
}
1907
1967
1908
- impl core:: ops:: Index < usize > for MemoryMap < ' _ > {
1968
+ impl core:: ops:: Index < usize > for MemoryMap {
1909
1969
type Output = MemoryDescriptor ;
1910
1970
1911
1971
fn index ( & self , index : usize ) -> & Self :: Output {
1912
1972
self . get ( index) . unwrap ( )
1913
1973
}
1914
1974
}
1915
1975
1916
- impl core:: ops:: IndexMut < usize > for MemoryMap < ' _ > {
1976
+ impl core:: ops:: IndexMut < usize > for MemoryMap {
1917
1977
fn index_mut ( & mut self , index : usize ) -> & mut Self :: Output {
1918
1978
self . get_mut ( index) . unwrap ( )
1919
1979
}
@@ -1922,13 +1982,13 @@ impl core::ops::IndexMut<usize> for MemoryMap<'_> {
1922
1982
/// An iterator of [`MemoryDescriptor`]. The underlying memory map is always
1923
1983
/// associated with a unique [`MemoryMapKey`].
1924
1984
#[ derive( Debug , Clone ) ]
1925
- pub struct MemoryMapIter < ' buf > {
1926
- memory_map : & ' buf MemoryMap < ' buf > ,
1985
+ pub struct MemoryMapIter < ' a > {
1986
+ memory_map : & ' a MemoryMap ,
1927
1987
index : usize ,
1928
1988
}
1929
1989
1930
- impl < ' buf > Iterator for MemoryMapIter < ' buf > {
1931
- type Item = & ' buf MemoryDescriptor ;
1990
+ impl < ' a > Iterator for MemoryMapIter < ' a > {
1991
+ type Item = & ' a MemoryDescriptor ;
1932
1992
1933
1993
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1934
1994
let sz = self . memory_map . len - self . index ;
@@ -2179,7 +2239,7 @@ mod tests {
2179
2239
}
2180
2240
2181
2241
// Added for debug purposes on test failure
2182
- impl core:: fmt:: Display for MemoryMap < ' _ > {
2242
+ impl core:: fmt:: Display for MemoryMap {
2183
2243
fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
2184
2244
writeln ! ( f) ?;
2185
2245
for desc in self . entries ( ) {
0 commit comments