@@ -302,6 +302,9 @@ pub struct EFIMemoryMapTag {
302
302
/// To follow the UEFI spec and to allow extendability for future UEFI
303
303
/// revisions, the length is a multiple of `desc_size` and not a multiple
304
304
/// of `size_of::<EfiMemoryDescriptor>()`.
305
+ ///
306
+ /// This tag is properly `align_of::<EFIMemoryDesc>` aligned, if the tag
307
+ /// itself is also 8 byte aligned, which every sane MBI guarantees.
305
308
memory_map : [ u8 ] ,
306
309
}
307
310
@@ -311,6 +314,9 @@ impl EFIMemoryMapTag {
311
314
/// Version and size can't be set because you're passing a slice of
312
315
/// EFIMemoryDescs, not the ones you might have gotten from the firmware.
313
316
pub fn new_from_descs ( descs : & [ EFIMemoryDesc ] ) -> BoxedDst < Self > {
317
+ // TODO replace this EfiMemorydesc::uefi_desc_size() in the next uefi_raw
318
+ // release.
319
+
314
320
let size_base = mem:: size_of :: < EFIMemoryDesc > ( ) ;
315
321
// Taken from https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
316
322
let desc_size_diff = mem:: size_of :: < u64 > ( ) - size_base % mem:: size_of :: < u64 > ( ) ;
@@ -337,6 +343,12 @@ impl EFIMemoryMapTag {
337
343
pub fn new_from_map ( desc_size : u32 , desc_version : u32 , efi_mmap : & [ u8 ] ) -> BoxedDst < Self > {
338
344
assert ! ( desc_size > 0 ) ;
339
345
assert_eq ! ( efi_mmap. len( ) % desc_size as usize , 0 ) ;
346
+ assert_eq ! (
347
+ efi_mmap
348
+ . as_ptr( )
349
+ . align_offset( mem:: align_of:: <EFIMemoryDesc >( ) ) ,
350
+ 0
351
+ ) ;
340
352
let bytes = [
341
353
& desc_size. to_le_bytes ( ) ,
342
354
& desc_version. to_le_bytes ( ) ,
@@ -354,6 +366,12 @@ impl EFIMemoryMapTag {
354
366
// If this ever fails, this needs to be refactored in a joint-effort
355
367
// with the uefi-rs project to have all corresponding typings.
356
368
assert_eq ! ( self . desc_version, EFIMemoryDesc :: VERSION ) ;
369
+ assert_eq ! (
370
+ self . memory_map
371
+ . as_ptr( )
372
+ . align_offset( mem:: align_of:: <EFIMemoryDesc >( ) ) ,
373
+ 0
374
+ ) ;
357
375
358
376
if self . desc_size as usize > mem:: size_of :: < EFIMemoryDesc > ( ) {
359
377
log:: debug!( "desc_size larger than expected typing. We might miss a few fields." ) ;
@@ -424,13 +442,12 @@ impl<'a> ExactSizeIterator for EFIMemoryAreaIter<'a> {
424
442
}
425
443
}
426
444
427
- #[ cfg( test) ]
445
+ #[ cfg( all ( test, feature = "builder" , not ( miri ) ) ) ]
428
446
mod tests {
429
447
use super :: * ;
448
+ use std:: mem:: size_of;
430
449
431
450
#[ test]
432
- #[ cfg( feature = "builder" ) ]
433
- #[ cfg_attr( miri, ignore) ]
434
451
fn construction_and_parsing ( ) {
435
452
let descs = [
436
453
EFIMemoryDesc {
@@ -459,4 +476,129 @@ mod tests {
459
476
460
477
assert_eq ! ( iter. next( ) , None ) ;
461
478
}
479
+
480
+ /// Tests the EFI memory map parsing using a real world efi memory map.
481
+ /// This is taken from the uefi-rs repository. See
482
+ /// <https://github.com/rust-osdev/uefi-rs/pull/1175> for more info.
483
+ #[ test]
484
+ fn test_real_data ( ) {
485
+ const DESC_SIZE : u32 = 48 ;
486
+ const DESC_VERSION : u32 = 1 ;
487
+ /// Sample with 10 entries of a real UEFI memory map extracted from our
488
+ /// UEFI test runner.
489
+ const MMAP_RAW : [ u64 ; 60 ] = [
490
+ 3 , 0 , 0 , 1 , 15 , 0 , 7 , 4096 , 0 , 134 , 15 , 0 , 4 , 552960 , 0 , 1 , 15 , 0 , 7 , 557056 , 0 , 24 ,
491
+ 15 , 0 , 7 , 1048576 , 0 , 1792 , 15 , 0 , 10 , 8388608 , 0 , 8 , 15 , 0 , 7 , 8421376 , 0 , 3 , 15 , 0 ,
492
+ 10 , 8433664 , 0 , 1 , 15 , 0 , 7 , 8437760 , 0 , 4 , 15 , 0 , 10 , 8454144 , 0 , 240 , 15 , 0 ,
493
+ ] ;
494
+ let buf = MMAP_RAW ;
495
+ let buf = unsafe {
496
+ core:: slice:: from_raw_parts ( buf. as_ptr ( ) . cast :: < u8 > ( ) , buf. len ( ) * size_of :: < u64 > ( ) )
497
+ } ;
498
+ let tag = EFIMemoryMapTag :: new_from_map ( DESC_SIZE , DESC_VERSION , buf) ;
499
+ let entries = tag. memory_areas ( ) . copied ( ) . collect :: < alloc:: vec:: Vec < _ > > ( ) ;
500
+ let expected = [
501
+ EFIMemoryDesc {
502
+ ty : EFIMemoryAreaType :: BOOT_SERVICES_CODE ,
503
+ phys_start : 0x0 ,
504
+ virt_start : 0x0 ,
505
+ page_count : 0x1 ,
506
+ att : EFIMemoryAttribute :: UNCACHEABLE
507
+ | EFIMemoryAttribute :: WRITE_COMBINE
508
+ | EFIMemoryAttribute :: WRITE_THROUGH
509
+ | EFIMemoryAttribute :: WRITE_BACK ,
510
+ } ,
511
+ EFIMemoryDesc {
512
+ ty : EFIMemoryAreaType :: CONVENTIONAL ,
513
+ phys_start : 0x1000 ,
514
+ virt_start : 0x0 ,
515
+ page_count : 0x86 ,
516
+ att : EFIMemoryAttribute :: UNCACHEABLE
517
+ | EFIMemoryAttribute :: WRITE_COMBINE
518
+ | EFIMemoryAttribute :: WRITE_THROUGH
519
+ | EFIMemoryAttribute :: WRITE_BACK ,
520
+ } ,
521
+ EFIMemoryDesc {
522
+ ty : EFIMemoryAreaType :: BOOT_SERVICES_DATA ,
523
+ phys_start : 0x87000 ,
524
+ virt_start : 0x0 ,
525
+ page_count : 0x1 ,
526
+ att : EFIMemoryAttribute :: UNCACHEABLE
527
+ | EFIMemoryAttribute :: WRITE_COMBINE
528
+ | EFIMemoryAttribute :: WRITE_THROUGH
529
+ | EFIMemoryAttribute :: WRITE_BACK ,
530
+ } ,
531
+ EFIMemoryDesc {
532
+ ty : EFIMemoryAreaType :: CONVENTIONAL ,
533
+ phys_start : 0x88000 ,
534
+ virt_start : 0x0 ,
535
+ page_count : 0x18 ,
536
+ att : EFIMemoryAttribute :: UNCACHEABLE
537
+ | EFIMemoryAttribute :: WRITE_COMBINE
538
+ | EFIMemoryAttribute :: WRITE_THROUGH
539
+ | EFIMemoryAttribute :: WRITE_BACK ,
540
+ } ,
541
+ EFIMemoryDesc {
542
+ ty : EFIMemoryAreaType :: CONVENTIONAL ,
543
+ phys_start : 0x100000 ,
544
+ virt_start : 0x0 ,
545
+ page_count : 0x700 ,
546
+ att : EFIMemoryAttribute :: UNCACHEABLE
547
+ | EFIMemoryAttribute :: WRITE_COMBINE
548
+ | EFIMemoryAttribute :: WRITE_THROUGH
549
+ | EFIMemoryAttribute :: WRITE_BACK ,
550
+ } ,
551
+ EFIMemoryDesc {
552
+ ty : EFIMemoryAreaType :: ACPI_NON_VOLATILE ,
553
+ phys_start : 0x800000 ,
554
+ virt_start : 0x0 ,
555
+ page_count : 0x8 ,
556
+ att : EFIMemoryAttribute :: UNCACHEABLE
557
+ | EFIMemoryAttribute :: WRITE_COMBINE
558
+ | EFIMemoryAttribute :: WRITE_THROUGH
559
+ | EFIMemoryAttribute :: WRITE_BACK ,
560
+ } ,
561
+ EFIMemoryDesc {
562
+ ty : EFIMemoryAreaType :: CONVENTIONAL ,
563
+ phys_start : 0x808000 ,
564
+ virt_start : 0x0 ,
565
+ page_count : 0x3 ,
566
+ att : EFIMemoryAttribute :: UNCACHEABLE
567
+ | EFIMemoryAttribute :: WRITE_COMBINE
568
+ | EFIMemoryAttribute :: WRITE_THROUGH
569
+ | EFIMemoryAttribute :: WRITE_BACK ,
570
+ } ,
571
+ EFIMemoryDesc {
572
+ ty : EFIMemoryAreaType :: ACPI_NON_VOLATILE ,
573
+ phys_start : 0x80b000 ,
574
+ virt_start : 0x0 ,
575
+ page_count : 0x1 ,
576
+ att : EFIMemoryAttribute :: UNCACHEABLE
577
+ | EFIMemoryAttribute :: WRITE_COMBINE
578
+ | EFIMemoryAttribute :: WRITE_THROUGH
579
+ | EFIMemoryAttribute :: WRITE_BACK ,
580
+ } ,
581
+ EFIMemoryDesc {
582
+ ty : EFIMemoryAreaType :: CONVENTIONAL ,
583
+ phys_start : 0x80c000 ,
584
+ virt_start : 0x0 ,
585
+ page_count : 0x4 ,
586
+ att : EFIMemoryAttribute :: UNCACHEABLE
587
+ | EFIMemoryAttribute :: WRITE_COMBINE
588
+ | EFIMemoryAttribute :: WRITE_THROUGH
589
+ | EFIMemoryAttribute :: WRITE_BACK ,
590
+ } ,
591
+ EFIMemoryDesc {
592
+ ty : EFIMemoryAreaType :: ACPI_NON_VOLATILE ,
593
+ phys_start : 0x810000 ,
594
+ virt_start : 0x0 ,
595
+ page_count : 0xf0 ,
596
+ att : EFIMemoryAttribute :: UNCACHEABLE
597
+ | EFIMemoryAttribute :: WRITE_COMBINE
598
+ | EFIMemoryAttribute :: WRITE_THROUGH
599
+ | EFIMemoryAttribute :: WRITE_BACK ,
600
+ } ,
601
+ ] ;
602
+ assert_eq ! ( entries. as_slice( ) , & expected) ;
603
+ }
462
604
}
0 commit comments