@@ -217,37 +217,46 @@ impl BootServices {
217
217
}
218
218
}
219
219
220
- /// Stores the current UEFI memory map in the provided buffer.
221
- ///
222
- /// The allocated buffer must be at least aligned to a [`MemoryDescriptor`]
223
- /// and should be big enough to store the whole map. To estimating how big
224
- /// the map will be, you can call [`Self::memory_map_size`].
225
- ///
226
- /// The memory map contains entries of type [`MemoryDescriptor`]. However,
227
- /// the relevant step size is always the reported `desc_size` but never
228
- /// `size_of::<MemoryDescriptor>()`.
229
- ///
230
- /// The returned key is a unique identifier of the current configuration of
231
- /// memory. Any allocations or such will change the memory map's key.
232
- ///
233
- /// If you want to store the resulting memory map without having to keep
234
- /// the buffer around, you can use `.copied().collect()` on the iterator.
235
- /// Note that this will change the current memory map again, if the UEFI
236
- /// allocator is used under the hood.
220
+ /// Stores the current UEFI memory map in an UEFI-heap allocated buffer
221
+ /// and returns a [`MemoryMap`].
237
222
///
238
223
/// # Errors
239
224
///
240
- /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification for more details.
225
+ /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification
226
+ /// for more details.
241
227
///
242
228
/// * [`uefi::Status::BUFFER_TOO_SMALL`]
243
229
/// * [`uefi::Status::INVALID_PARAMETER`]
244
- pub fn memory_map < ' buf > ( & self , buffer : & ' buf mut [ u8 ] ) -> Result < MemoryMap < ' buf > > {
245
- let mut map_size = buffer. len ( ) ;
246
- MemoryDescriptor :: assert_aligned ( buffer) ;
247
- let map_buffer = buffer. as_mut_ptr ( ) . cast :: < MemoryDescriptor > ( ) ;
230
+ pub fn memory_map ( & self , mt : MemoryType ) -> Result < MemoryMap > {
231
+ let mut buffer = MemoryMapBackingMemory :: new ( mt) ?;
232
+
233
+ let GetMemoryMapMeta {
234
+ map_size,
235
+ map_key,
236
+ desc_size,
237
+ desc_version,
238
+ } = self . get_memory_map ( buffer. as_mut_slice ( ) ) ?;
239
+
240
+ let len = map_size / desc_size;
241
+ assert_eq ! ( map_size % desc_size, 0 ) ;
242
+ assert_eq ! ( desc_version, MemoryDescriptor :: VERSION ) ;
243
+ Ok ( MemoryMap {
244
+ key : map_key,
245
+ buf : buffer,
246
+ desc_size,
247
+ len,
248
+ } )
249
+ }
250
+
251
+ /// Calls the underlying `GetMemoryMap` function of UEFI. On success,
252
+ /// the buffer is mutated and contains the map. The map might be shorter
253
+ /// than the buffer, which is reflected by the return value.
254
+ pub ( crate ) fn get_memory_map ( & self , buf : & mut [ u8 ] ) -> Result < GetMemoryMapMeta > {
255
+ let mut map_size = buf. len ( ) ;
256
+ let map_buffer = buf. as_mut_ptr ( ) . cast :: < MemoryDescriptor > ( ) ;
248
257
let mut map_key = MemoryMapKey ( 0 ) ;
249
258
let mut desc_size = 0 ;
250
- let mut entry_version = 0 ;
259
+ let mut desc_version = 0 ;
251
260
252
261
assert_eq ! (
253
262
( map_buffer as usize ) % mem:: align_of:: <MemoryDescriptor >( ) ,
@@ -261,18 +270,14 @@ impl BootServices {
261
270
map_buffer,
262
271
& mut map_key. 0 ,
263
272
& mut desc_size,
264
- & mut entry_version ,
273
+ & mut desc_version ,
265
274
)
266
275
}
267
- . to_result_with_val ( move || {
268
- let len = map_size / desc_size;
269
-
270
- MemoryMap {
271
- key : map_key,
272
- buf : buffer,
273
- desc_size,
274
- len,
275
- }
276
+ . to_result_with_val ( || GetMemoryMapMeta {
277
+ map_size,
278
+ desc_size,
279
+ map_key,
280
+ desc_version,
276
281
} )
277
282
}
278
283
@@ -1639,7 +1644,7 @@ pub struct MemoryMapKey(usize);
1639
1644
/// When this type is dropped and boot services are not exited yet, the memory
1640
1645
/// is freed.
1641
1646
#[ derive( Debug ) ]
1642
- pub struct MemoryMapBackingMemory ( NonNull < [ u8 ] > /* buffer on UEFI heap */ ) ;
1647
+ pub struct MemoryMapBackingMemory ( NonNull < [ u8 ] > ) ;
1643
1648
1644
1649
impl MemoryMapBackingMemory {
1645
1650
/// Constructs a new [`MemoryMapBackingMemory`].
@@ -1652,18 +1657,32 @@ impl MemoryMapBackingMemory {
1652
1657
let bs = st. boot_services ( ) ;
1653
1658
1654
1659
let memory_map_size = bs. memory_map_size ( ) ;
1655
- let alloc_size = Self :: allocation_size_hint ( memory_map_size) ;
1656
- let ptr = bs. allocate_pool ( memory_type, alloc_size) ?;
1660
+ let len = Self :: allocation_size_hint ( memory_map_size) ;
1661
+ let ptr = bs. allocate_pool ( memory_type, len) ?;
1662
+ assert_eq ! ( ptr. align_offset( mem:: align_of:: <MemoryDescriptor >( ) ) , 0 ) ;
1663
+ Ok ( Self :: from_raw ( ptr, len) )
1664
+ }
1665
+
1666
+ fn from_raw ( ptr : * mut u8 , len : usize ) -> Self {
1657
1667
assert_eq ! ( ptr. align_offset( mem:: align_of:: <MemoryDescriptor >( ) ) , 0 ) ;
1658
1668
1659
1669
let ptr = NonNull :: new ( ptr) . expect ( "UEFI should never return a null ptr. An error should have been reflected via an Err earlier." ) ;
1660
- let slice = NonNull :: slice_from_raw_parts ( ptr, alloc_size ) ;
1670
+ let slice = NonNull :: slice_from_raw_parts ( ptr, len ) ;
1661
1671
1662
- Ok ( Self ( slice) )
1672
+ Self ( slice)
1673
+ }
1674
+
1675
+ /// Creates an instance from the provided memory, which is not necessarily
1676
+ /// on the UEFI heap.
1677
+ #[ cfg( test) ]
1678
+ fn from_slice ( buffer : & mut [ u8 ] ) -> Self {
1679
+ let len = buffer. len ( ) ;
1680
+ Self :: from_raw ( buffer. as_mut_ptr ( ) , len)
1663
1681
}
1664
1682
1665
1683
/// Returns a best-effort size hint of the memory map size. This is
1666
1684
/// especially created with exiting boot services in mind.
1685
+ #[ must_use]
1667
1686
pub fn allocation_size_hint ( mms : GetMemoryMapMeta ) -> usize {
1668
1687
let GetMemoryMapMeta {
1669
1688
desc_size,
@@ -1693,15 +1712,34 @@ impl MemoryMapBackingMemory {
1693
1712
allocation_size
1694
1713
}
1695
1714
1696
- /// Returns the raw pointer to the beginning of the allocation.
1697
- pub fn as_ptr_mut ( & mut self ) -> * mut u8 {
1715
+ /// Returns a raw pointer to the beginning of the allocation.
1716
+ #[ must_use]
1717
+ pub fn as_ptr ( & self ) -> * const u8 {
1718
+ self . 0 . as_ptr ( ) . cast ( )
1719
+ }
1720
+
1721
+ /// Returns a mutable raw pointer to the beginning of the allocation.
1722
+ #[ must_use]
1723
+ pub fn as_mut_ptr ( & mut self ) -> * mut u8 {
1698
1724
self . 0 . as_ptr ( ) . cast ( )
1699
1725
}
1700
1726
1701
1727
/// Returns the length of the allocation.
1728
+ #[ must_use]
1702
1729
pub fn len ( & self ) -> usize {
1703
1730
self . 0 . len ( )
1704
1731
}
1732
+
1733
+ /*#[must_use]
1734
+ pub fn as_slice(&self) -> &[u8] {
1735
+ self.0.as_ref()
1736
+ }*/
1737
+
1738
+ /// Returns a mutable slice to the underlying memory.
1739
+ #[ must_use]
1740
+ pub fn as_mut_slice ( & mut self ) -> & mut [ u8 ] {
1741
+ unsafe { self . 0 . as_mut ( ) }
1742
+ }
1705
1743
}
1706
1744
1707
1745
impl Drop for MemoryMapBackingMemory {
@@ -1751,31 +1789,34 @@ pub struct GetMemoryMapMeta {
1751
1789
///
1752
1790
/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
1753
1791
#[ derive( Debug ) ]
1754
- pub struct MemoryMap < ' buf > {
1792
+ pub struct MemoryMap {
1793
+ /// Backing memory, properly initialized at this point.
1794
+ buf : MemoryMapBackingMemory ,
1755
1795
key : MemoryMapKey ,
1756
- buf : & ' buf mut [ u8 ] ,
1757
1796
/// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if
1758
1797
/// this field is ever extended by a new UEFI standard.
1759
1798
desc_size : usize ,
1760
1799
len : usize ,
1761
1800
}
1762
1801
1763
- impl < ' buf > MemoryMap < ' buf > {
1764
- /// Creates a [`MemoryMap`] from the given buffer and entry size.
1765
- /// The entry size is usually bound to the size of a [`MemoryDescriptor`]
1766
- /// but can indicate if this field is ever extended by a new UEFI standard.
1767
- ///
1768
- /// This allows parsing a memory map provided by a kernel after boot
1769
- /// services have already exited.
1770
- pub fn from_raw ( buf : & ' buf mut [ u8 ] , desc_size : usize ) -> Self {
1771
- assert ! ( !buf. is_empty( ) ) ;
1772
- assert_eq ! (
1773
- buf. len( ) % desc_size,
1774
- 0 ,
1775
- "The buffer length must be a multiple of the desc_size"
1776
- ) ;
1802
+ impl MemoryMap {
1803
+ /*pub fn new() -> Self {
1804
+
1805
+ }*/
1806
+
1807
+ /// Creates a [`MemoryMap`] from the give initialized memory map behind
1808
+ /// the buffer and the reported `desc_size` from UEFI.
1809
+ pub ( crate ) fn from_initialized_mem (
1810
+ buf : MemoryMapBackingMemory ,
1811
+ props : GetMemoryMapMeta ,
1812
+ ) -> Self {
1813
+ let GetMemoryMapMeta {
1814
+ map_size,
1815
+ desc_size,
1816
+ ..
1817
+ } = props;
1777
1818
assert ! ( desc_size >= mem:: size_of:: <MemoryDescriptor >( ) ) ;
1778
- let len = buf . len ( ) / desc_size;
1819
+ let len = map_size / desc_size;
1779
1820
MemoryMap {
1780
1821
key : MemoryMapKey ( 0 ) ,
1781
1822
buf,
@@ -1784,6 +1825,20 @@ impl<'buf> MemoryMap<'buf> {
1784
1825
}
1785
1826
}
1786
1827
1828
+ #[ cfg( test) ]
1829
+ fn from_raw ( buf : & mut [ u8 ] , desc_size : usize ) -> Self {
1830
+ let mem = MemoryMapBackingMemory :: from_slice ( buf) ;
1831
+ Self :: from_initialized_mem (
1832
+ mem,
1833
+ GetMemoryMapMeta {
1834
+ map_size : buf. len ( ) ,
1835
+ desc_size,
1836
+ map_key : MemoryMapKey ( 0 ) ,
1837
+ desc_version : MemoryDescriptor :: VERSION ,
1838
+ } ,
1839
+ )
1840
+ }
1841
+
1787
1842
#[ must_use]
1788
1843
/// Returns the unique [`MemoryMapKey`] associated with the memory map.
1789
1844
pub fn key ( & self ) -> MemoryMapKey {
@@ -1878,7 +1933,7 @@ impl<'buf> MemoryMap<'buf> {
1878
1933
1879
1934
/// Returns a reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds.
1880
1935
#[ must_use]
1881
- pub fn get ( & self , index : usize ) -> Option < & ' buf MemoryDescriptor > {
1936
+ pub fn get ( & self , index : usize ) -> Option < & MemoryDescriptor > {
1882
1937
if index >= self . len {
1883
1938
return None ;
1884
1939
}
@@ -1896,7 +1951,7 @@ impl<'buf> MemoryMap<'buf> {
1896
1951
1897
1952
/// Returns a mut reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds.
1898
1953
#[ must_use]
1899
- pub fn get_mut ( & mut self , index : usize ) -> Option < & ' buf mut MemoryDescriptor > {
1954
+ pub fn get_mut ( & mut self , index : usize ) -> Option < & mut MemoryDescriptor > {
1900
1955
if index >= self . len {
1901
1956
return None ;
1902
1957
}
@@ -1913,15 +1968,15 @@ impl<'buf> MemoryMap<'buf> {
1913
1968
}
1914
1969
}
1915
1970
1916
- impl core:: ops:: Index < usize > for MemoryMap < ' _ > {
1971
+ impl core:: ops:: Index < usize > for MemoryMap {
1917
1972
type Output = MemoryDescriptor ;
1918
1973
1919
1974
fn index ( & self , index : usize ) -> & Self :: Output {
1920
1975
self . get ( index) . unwrap ( )
1921
1976
}
1922
1977
}
1923
1978
1924
- impl core:: ops:: IndexMut < usize > for MemoryMap < ' _ > {
1979
+ impl core:: ops:: IndexMut < usize > for MemoryMap {
1925
1980
fn index_mut ( & mut self , index : usize ) -> & mut Self :: Output {
1926
1981
self . get_mut ( index) . unwrap ( )
1927
1982
}
@@ -1930,13 +1985,13 @@ impl core::ops::IndexMut<usize> for MemoryMap<'_> {
1930
1985
/// An iterator of [`MemoryDescriptor`]. The underlying memory map is always
1931
1986
/// associated with a unique [`MemoryMapKey`].
1932
1987
#[ derive( Debug , Clone ) ]
1933
- pub struct MemoryMapIter < ' buf > {
1934
- memory_map : & ' buf MemoryMap < ' buf > ,
1988
+ pub struct MemoryMapIter < ' a > {
1989
+ memory_map : & ' a MemoryMap ,
1935
1990
index : usize ,
1936
1991
}
1937
1992
1938
- impl < ' buf > Iterator for MemoryMapIter < ' buf > {
1939
- type Item = & ' buf MemoryDescriptor ;
1993
+ impl < ' a > Iterator for MemoryMapIter < ' a > {
1994
+ type Item = & ' a MemoryDescriptor ;
1940
1995
1941
1996
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1942
1997
let sz = self . memory_map . len - self . index ;
@@ -2187,7 +2242,7 @@ mod tests {
2187
2242
}
2188
2243
2189
2244
// Added for debug purposes on test failure
2190
- impl core:: fmt:: Display for MemoryMap < ' _ > {
2245
+ impl core:: fmt:: Display for MemoryMap {
2191
2246
fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
2192
2247
writeln ! ( f) ?;
2193
2248
for desc in self . entries ( ) {
0 commit comments