33
44use super :: * ;
55use crate :: table:: system_table_boot;
6+ use core:: fmt:: { Debug , Display , Formatter } ;
67use core:: ops:: { Index , IndexMut } ;
78use core:: ptr:: NonNull ;
89use core:: { mem, ptr} ;
910use uefi_raw:: PhysicalAddress ;
1011
12+ /// Errors that may happen when constructing a [`MemoryMapRef`] or
13+ /// [`MemoryMapRefMut`].
14+ #[ derive( Copy , Clone , Debug ) ]
15+ pub enum MemoryMapError {
16+ /// The buffer is not 8-byte aligned.
17+ Misaligned ,
18+ /// The memory map size is invalid.
19+ InvalidSize ,
20+ }
21+
22+ impl Display for MemoryMapError {
23+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> core:: fmt:: Result {
24+ Debug :: fmt ( self , f)
25+ }
26+ }
27+
28+ #[ cfg( feature = "unstable" ) ]
29+ impl core:: error:: Error for MemoryMapError { }
30+
1131/// Implementation of [`MemoryMap`] for the given buffer.
1232#[ derive( Debug ) ]
13- #[ allow( dead_code) ] // TODO: github.com/rust-osdev/uefi-rs/issues/1247
1433pub struct MemoryMapRef < ' a > {
1534 buf : & ' a [ u8 ] ,
16- key : MemoryMapKey ,
1735 meta : MemoryMapMeta ,
1836 len : usize ,
1937}
2038
39+ impl < ' a > MemoryMapRef < ' a > {
40+ /// Constructs a new [`MemoryMapRef`].
41+ ///
42+ /// The underlying memory might contain an invalid/malformed memory map
43+ /// which can't be checked during construction of this type. The entry
44+ /// iterator might yield unexpected results.
45+ pub fn new ( buffer : & ' a [ u8 ] , meta : MemoryMapMeta ) -> Result < Self , MemoryMapError > {
46+ if buffer. as_ptr ( ) . align_offset ( 8 ) != 0 {
47+ return Err ( MemoryMapError :: Misaligned ) ;
48+ }
49+ if buffer. len ( ) < meta. map_size {
50+ return Err ( MemoryMapError :: InvalidSize ) ;
51+ }
52+ Ok ( Self {
53+ buf : buffer,
54+ meta,
55+ len : meta. entry_count ( ) ,
56+ } )
57+ }
58+ }
59+
2160impl < ' a > MemoryMap for MemoryMapRef < ' a > {
2261 fn meta ( & self ) -> MemoryMapMeta {
2362 self . meta
2463 }
2564
2665 fn key ( & self ) -> MemoryMapKey {
27- self . key
66+ self . meta . map_key
2867 }
2968
3069 fn len ( & self ) -> usize {
@@ -55,18 +94,38 @@ impl Index<usize> for MemoryMapRef<'_> {
5594#[ derive( Debug ) ]
5695pub struct MemoryMapRefMut < ' a > {
5796 buf : & ' a mut [ u8 ] ,
58- key : MemoryMapKey ,
5997 meta : MemoryMapMeta ,
6098 len : usize ,
6199}
62100
101+ impl < ' a > MemoryMapRefMut < ' a > {
102+ /// Constructs a new [`MemoryMapRefMut`].
103+ ///
104+ /// The underlying memory might contain an invalid/malformed memory map
105+ /// which can't be checked during construction of this type. The entry
106+ /// iterator might yield unexpected results.
107+ pub fn new ( buffer : & ' a mut [ u8 ] , meta : MemoryMapMeta ) -> Result < Self , MemoryMapError > {
108+ if buffer. as_ptr ( ) . align_offset ( 8 ) != 0 {
109+ return Err ( MemoryMapError :: Misaligned ) ;
110+ }
111+ if buffer. len ( ) < meta. map_size {
112+ return Err ( MemoryMapError :: InvalidSize ) ;
113+ }
114+ Ok ( Self {
115+ buf : buffer,
116+ meta,
117+ len : meta. entry_count ( ) ,
118+ } )
119+ }
120+ }
121+
63122impl < ' a > MemoryMap for MemoryMapRefMut < ' a > {
64123 fn meta ( & self ) -> MemoryMapMeta {
65124 self . meta
66125 }
67126
68127 fn key ( & self ) -> MemoryMapKey {
69- self . key
128+ self . meta . map_key
70129 }
71130
72131 fn len ( & self ) -> usize {
@@ -241,10 +300,12 @@ impl MemoryMapBackingMemory {
241300 Self ( slice)
242301 }
243302
303+ /// INTERNAL, for unit tests.
304+ ///
244305 /// Creates an instance from the provided memory, which is not necessarily
245306 /// on the UEFI heap.
246307 #[ cfg( test) ]
247- fn from_slice ( buffer : & mut [ u8 ] ) -> Self {
308+ pub ( crate ) fn from_slice ( buffer : & mut [ u8 ] ) -> Self {
248309 let len = buffer. len ( ) ;
249310 unsafe { Self :: from_raw ( buffer. as_mut_ptr ( ) , len) }
250311 }
@@ -287,6 +348,10 @@ impl Drop for MemoryMapBackingMemory {
287348 log:: error!( "Failed to deallocate memory map: {e:?}" ) ;
288349 }
289350 } else {
351+ #[ cfg( test) ]
352+ log:: debug!( "Boot services are not available in unit tests." ) ;
353+
354+ #[ cfg( not( test) ) ]
290355 log:: debug!( "Boot services are excited. Memory map won't be freed using the UEFI boot services allocator." ) ;
291356 }
292357 }
@@ -297,37 +362,18 @@ impl Drop for MemoryMapBackingMemory {
297362pub struct MemoryMapOwned {
298363 /// Backing memory, properly initialized at this point.
299364 pub ( crate ) buf : MemoryMapBackingMemory ,
300- pub ( crate ) key : MemoryMapKey ,
301365 pub ( crate ) meta : MemoryMapMeta ,
302366 pub ( crate ) len : usize ,
303367}
304368
305369impl MemoryMapOwned {
306- /// Creates a [`MemoryMapOwned`] from the give initialized memory map behind
307- /// the buffer and the reported `desc_size` from UEFI.
370+ /// Creates a [`MemoryMapOwned`] from the given **initialized** memory map
371+ /// (stored inside the provided buffer) and the corresponding
372+ /// [`MemoryMapMeta`].
308373 pub ( crate ) fn from_initialized_mem ( buf : MemoryMapBackingMemory , meta : MemoryMapMeta ) -> Self {
309374 assert ! ( meta. desc_size >= mem:: size_of:: <MemoryDescriptor >( ) ) ;
310375 let len = meta. entry_count ( ) ;
311- MemoryMapOwned {
312- key : MemoryMapKey ( 0 ) ,
313- buf,
314- meta,
315- len,
316- }
317- }
318-
319- #[ cfg( test) ]
320- pub ( super ) fn from_raw ( buf : & mut [ u8 ] , desc_size : usize ) -> Self {
321- let mem = MemoryMapBackingMemory :: from_slice ( buf) ;
322- Self :: from_initialized_mem (
323- mem,
324- MemoryMapMeta {
325- map_size : buf. len ( ) ,
326- desc_size,
327- map_key : MemoryMapKey ( 0 ) ,
328- desc_version : MemoryDescriptor :: VERSION ,
329- } ,
330- )
376+ MemoryMapOwned { buf, meta, len }
331377 }
332378}
333379
@@ -337,7 +383,7 @@ impl MemoryMap for MemoryMapOwned {
337383 }
338384
339385 fn key ( & self ) -> MemoryMapKey {
340- self . key
386+ self . meta . map_key
341387 }
342388
343389 fn len ( & self ) -> usize {
@@ -360,7 +406,6 @@ impl MemoryMapMut for MemoryMapOwned {
360406 fn sort ( & mut self ) {
361407 let mut reference = MemoryMapRefMut {
362408 buf : self . buf . as_mut_slice ( ) ,
363- key : self . key ,
364409 meta : self . meta ,
365410 len : self . len ,
366411 } ;
@@ -385,3 +430,103 @@ impl IndexMut<usize> for MemoryMapOwned {
385430 self . get_mut ( index) . unwrap ( )
386431 }
387432}
433+
434+ #[ cfg( test) ]
435+ mod tests {
436+ use super :: * ;
437+ use alloc:: vec:: Vec ;
438+ use core:: mem:: size_of;
439+
440+ const BASE_MMAP_UNSORTED : [ MemoryDescriptor ; 3 ] = [
441+ MemoryDescriptor {
442+ ty : MemoryType :: CONVENTIONAL ,
443+ phys_start : 0x3000 ,
444+ virt_start : 0x3000 ,
445+ page_count : 1 ,
446+ att : MemoryAttribute :: WRITE_BACK ,
447+ } ,
448+ MemoryDescriptor {
449+ ty : MemoryType :: CONVENTIONAL ,
450+ phys_start : 0x2000 ,
451+ virt_start : 0x2000 ,
452+ page_count : 1 ,
453+ att : MemoryAttribute :: WRITE_BACK ,
454+ } ,
455+ MemoryDescriptor {
456+ ty : MemoryType :: CONVENTIONAL ,
457+ phys_start : 0x1000 ,
458+ virt_start : 0x1000 ,
459+ page_count : 1 ,
460+ att : MemoryAttribute :: WRITE_BACK ,
461+ } ,
462+ ] ;
463+
464+ /// Returns a copy of [`BASE_MMAP_UNSORTED`] owned on the stack.
465+ fn new_mmap_memory ( ) -> [ MemoryDescriptor ; 3 ] {
466+ BASE_MMAP_UNSORTED
467+ }
468+
469+ fn mmap_raw < ' a > ( memory : & mut [ MemoryDescriptor ] ) -> ( & ' a mut [ u8 ] , MemoryMapMeta ) {
470+ let desc_size = size_of :: < MemoryDescriptor > ( ) ;
471+ let len = memory. len ( ) * desc_size;
472+ let ptr = memory. as_mut_ptr ( ) . cast :: < u8 > ( ) ;
473+ let slice = unsafe { core:: slice:: from_raw_parts_mut ( ptr, len) } ;
474+ let meta = MemoryMapMeta {
475+ map_size : len,
476+ desc_size,
477+ map_key : Default :: default ( ) ,
478+ desc_version : MemoryDescriptor :: VERSION ,
479+ } ;
480+ ( slice, meta)
481+ }
482+
483+ /// Basic sanity checks for the type [`MemoryMapRef`].
484+ #[ test]
485+ fn memory_map_ref ( ) {
486+ let mut memory = new_mmap_memory ( ) ;
487+ let ( mmap, meta) = mmap_raw ( & mut memory) ;
488+ let mmap = MemoryMapRef :: new ( mmap, meta) . unwrap ( ) ;
489+
490+ assert_eq ! ( mmap. entries( ) . count( ) , 3 ) ;
491+ assert_eq ! (
492+ mmap. entries( ) . copied( ) . collect:: <Vec <_>>( ) . as_slice( ) ,
493+ & BASE_MMAP_UNSORTED
494+ ) ;
495+ assert ! ( !mmap. is_sorted( ) ) ;
496+ }
497+
498+ /// Basic sanity checks for the type [`MemoryMapRefMut`].
499+ #[ test]
500+ fn memory_map_ref_mut ( ) {
501+ let mut memory = new_mmap_memory ( ) ;
502+ let ( mmap, meta) = mmap_raw ( & mut memory) ;
503+ let mut mmap = MemoryMapRefMut :: new ( mmap, meta) . unwrap ( ) ;
504+
505+ assert_eq ! ( mmap. entries( ) . count( ) , 3 ) ;
506+ assert_eq ! (
507+ mmap. entries( ) . copied( ) . collect:: <Vec <_>>( ) . as_slice( ) ,
508+ & BASE_MMAP_UNSORTED
509+ ) ;
510+ assert ! ( !mmap. is_sorted( ) ) ;
511+ mmap. sort ( ) ;
512+ assert ! ( mmap. is_sorted( ) ) ;
513+ }
514+
515+ /// Basic sanity checks for the type [`MemoryMapOwned`].
516+ #[ test]
517+ fn memory_map_owned ( ) {
518+ let mut memory = new_mmap_memory ( ) ;
519+ let ( mmap, meta) = mmap_raw ( & mut memory) ;
520+ let mmap = MemoryMapBackingMemory :: from_slice ( mmap) ;
521+ let mut mmap = MemoryMapOwned :: from_initialized_mem ( mmap, meta) ;
522+
523+ assert_eq ! ( mmap. entries( ) . count( ) , 3 ) ;
524+ assert_eq ! (
525+ mmap. entries( ) . copied( ) . collect:: <Vec <_>>( ) . as_slice( ) ,
526+ & BASE_MMAP_UNSORTED
527+ ) ;
528+ assert ! ( !mmap. is_sorted( ) ) ;
529+ mmap. sort ( ) ;
530+ assert ! ( mmap. is_sorted( ) ) ;
531+ }
532+ }
0 commit comments