@@ -55,7 +55,10 @@ impl MemoryMapTag {
55
55
self . entry_version
56
56
}
57
57
58
- /// Return the slice with all memory areas.
58
+ /// Return the slice of the provided [`MemoryArea`]s.
59
+ ///
60
+ /// Usually, this should already reflect the memory consumed by the
61
+ /// code running this.
59
62
pub fn memory_areas ( & self ) -> & [ MemoryArea ] {
60
63
// If this ever fails, we need to model this differently in this crate.
61
64
assert_eq ! ( self . entry_size as usize , mem:: size_of:: <MemoryArea >( ) ) ;
@@ -74,7 +77,7 @@ impl TagTrait for MemoryMapTag {
74
77
}
75
78
}
76
79
77
- /// A memory area entry descriptor .
80
+ /// A descriptor for an available or taken area of physical memory .
78
81
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
79
82
#[ repr( C ) ]
80
83
pub struct MemoryArea {
@@ -284,9 +287,20 @@ impl AsBytes for EFIMemoryDesc {}
284
287
pub struct EFIMemoryMapTag {
285
288
typ : TagTypeId ,
286
289
size : u32 ,
290
+ /// Most likely a little more than the size of a [`EFIMemoryDesc`].
291
+ /// This is always the reference, and `size_of` never.
292
+ /// See <https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059>.
287
293
desc_size : u32 ,
294
+ /// Version of the tag. The spec leaves it open to extend the memory
295
+ /// descriptor in the future. However, this never happened so far.
296
+ /// At the moment, only version "1" is supported.
288
297
desc_version : u32 ,
289
- descs : [ EFIMemoryDesc ] ,
298
+ /// Contains the UEFI memory map.
299
+ ///
300
+ /// To follow the UEFI spec and to allow extendability for future UEFI
301
+ /// revisions, the length is a multiple of `desc_size` and not a multiple
302
+ /// of `size_of::<EfiMemoryDescriptor>()`.
303
+ memory_map : [ u8 ] ,
290
304
}
291
305
292
306
impl EFIMemoryMapTag {
@@ -308,20 +322,22 @@ impl EFIMemoryMapTag {
308
322
BoxedDst :: new ( bytes. as_slice ( ) )
309
323
}
310
324
311
- /// Return an iterator over ALL marked memory areas.
325
+ /// Returns an iterator over the provided memory areas.
326
+ ///
327
+ /// Usually, this should already reflect the memory consumed by the
328
+ /// code running this.
312
329
///
313
- /// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
314
- /// available memory areas for tables and such.
330
+ /// See [`EFIMemoryAreaIter`] for more info.
315
331
pub fn memory_areas ( & self ) -> EFIMemoryAreaIter {
316
- let self_ptr = self as * const EFIMemoryMapTag ;
317
- let start_area = ( & self . descs [ 0 ] ) as * const EFIMemoryDesc ;
318
- EFIMemoryAreaIter {
319
- current_area : start_area as u64 ,
320
- // NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
321
- last_area : ( self_ptr as * const ( ) as u64 + self . size as u64 ) ,
322
- entry_size : self . desc_size ,
323
- phantom : PhantomData ,
332
+ // If this ever fails, this needs to be refactored in a joint-effort
333
+ // with the uefi-rs project to have all corresponding typings.
334
+ assert_eq ! ( self . desc_version, EFIMemoryDesc :: VERSION ) ;
335
+
336
+ if self . desc_size as usize > mem:: size_of :: < EFIMemoryDesc > ( ) {
337
+ log:: debug!( "desc_size larger than expected typing. We might miss a few fields." ) ;
324
338
}
339
+
340
+ EFIMemoryAreaIter :: new ( self )
325
341
}
326
342
}
327
343
@@ -330,30 +346,55 @@ impl TagTrait for EFIMemoryMapTag {
330
346
331
347
fn dst_size ( base_tag : & Tag ) -> usize {
332
348
assert ! ( base_tag. size as usize >= EFI_METADATA_SIZE ) ;
333
- let size = base_tag. size as usize - EFI_METADATA_SIZE ;
334
- assert_eq ! ( size % mem:: size_of:: <EFIMemoryDesc >( ) , 0 ) ;
335
- size / mem:: size_of :: < EFIMemoryDesc > ( )
349
+ base_tag. size as usize - EFI_METADATA_SIZE
336
350
}
337
351
}
338
352
339
- /// An iterator over ALL EFI memory areas.
353
+ /// An iterator over the EFI memory areas emitting [`EFIMemoryDesc`] items .
340
354
#[ derive( Clone , Debug ) ]
341
355
pub struct EFIMemoryAreaIter < ' a > {
342
- current_area : u64 ,
343
- last_area : u64 ,
344
- entry_size : u32 ,
356
+ mmap_tag : & ' a EFIMemoryMapTag ,
357
+ i : usize ,
358
+ entries : usize ,
345
359
phantom : PhantomData < & ' a EFIMemoryDesc > ,
346
360
}
347
361
362
+ impl < ' a > EFIMemoryAreaIter < ' a > {
363
+ fn new ( mmap_tag : & ' a EFIMemoryMapTag ) -> Self {
364
+ Self {
365
+ mmap_tag,
366
+ i : 0 ,
367
+ entries : mmap_tag. memory_map . len ( ) / mmap_tag. desc_size as usize ,
368
+ phantom : PhantomData ,
369
+ }
370
+ }
371
+ }
372
+
348
373
impl < ' a > Iterator for EFIMemoryAreaIter < ' a > {
349
374
type Item = & ' a EFIMemoryDesc ;
350
375
fn next ( & mut self ) -> Option < & ' a EFIMemoryDesc > {
351
- if self . current_area > self . last_area {
352
- None
353
- } else {
354
- let area = unsafe { & * ( self . current_area as * const EFIMemoryDesc ) } ;
355
- self . current_area += self . entry_size as u64 ;
356
- Some ( area)
376
+ if self . i >= self . entries {
377
+ return None ;
357
378
}
379
+
380
+ let desc = unsafe {
381
+ self . mmap_tag
382
+ . memory_map
383
+ . as_ptr ( )
384
+ . add ( self . i * self . mmap_tag . desc_size as usize )
385
+ . cast :: < EFIMemoryDesc > ( )
386
+ . as_ref ( )
387
+ . unwrap ( )
388
+ } ;
389
+
390
+ self . i += 1 ;
391
+
392
+ Some ( desc)
393
+ }
394
+ }
395
+
396
+ impl < ' a > ExactSizeIterator for EFIMemoryAreaIter < ' a > {
397
+ fn len ( & self ) -> usize {
398
+ self . entries
358
399
}
359
400
}
0 commit comments