1- use crate :: tag_type:: { TagType , TagTypeId } ;
1+ use crate :: { Tag , TagTrait , TagType , TagTypeId } ;
2+
23use core:: convert:: TryInto ;
34use core:: marker:: PhantomData ;
45use core:: mem;
56
7+ #[ cfg( feature = "builder" ) ]
8+ use { crate :: builder:: boxed_dst_tag, crate :: builder:: traits:: StructAsBytes , alloc:: boxed:: Box } ;
9+
10+ const METADATA_SIZE : usize = mem:: size_of :: < TagTypeId > ( ) + 3 * mem:: size_of :: < u32 > ( ) ;
11+
612/// This tag provides an initial host memory map.
713///
814/// The map provided is guaranteed to list all standard RAM that should be
@@ -13,17 +19,28 @@ use core::mem;
1319/// This tag may not be provided by some boot loaders on EFI platforms if EFI
1420/// boot services are enabled and available for the loaded image (The EFI boot
1521/// services tag may exist in the Multiboot2 boot information structure).
16- #[ derive( Debug ) ]
22+ #[ derive( Debug , ptr_meta :: Pointee ) ]
1723#[ repr( C ) ]
1824pub struct MemoryMapTag {
1925 typ : TagTypeId ,
2026 size : u32 ,
2127 entry_size : u32 ,
2228 entry_version : u32 ,
23- first_area : [ MemoryArea ; 0 ] ,
29+ areas : [ MemoryArea ] ,
2430}
2531
2632impl MemoryMapTag {
33+ #[ cfg( feature = "builder" ) ]
34+ pub fn new ( areas : & [ MemoryArea ] ) -> Box < Self > {
35+ let entry_size: u32 = mem:: size_of :: < MemoryArea > ( ) . try_into ( ) . unwrap ( ) ;
36+ let entry_version: u32 = 0 ;
37+ let mut bytes = [ entry_size. to_le_bytes ( ) , entry_version. to_le_bytes ( ) ] . concat ( ) ;
38+ for area in areas {
39+ bytes. extend ( area. struct_as_bytes ( ) ) ;
40+ }
41+ boxed_dst_tag ( TagType :: Mmap , bytes. as_slice ( ) )
42+ }
43+
2744 /// Return an iterator over all memory areas that have the type
2845 /// [`MemoryAreaType::Available`].
2946 pub fn available_memory_areas ( & self ) -> impl Iterator < Item = & MemoryArea > {
@@ -34,21 +51,26 @@ impl MemoryMapTag {
3451 /// Return an iterator over all memory areas.
3552 pub fn memory_areas ( & self ) -> MemoryAreaIter {
3653 let self_ptr = self as * const MemoryMapTag ;
37- let start_area = self . first_area . as_ptr ( ) ;
38-
54+ let start_area = ( & self . areas [ 0 ] ) as * const MemoryArea ;
3955 MemoryAreaIter {
4056 current_area : start_area as u64 ,
4157 // NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
42- last_area : ( self_ptr as u64
43- + ( self . size as u64 - core:: mem:: size_of :: < MemoryMapTag > ( ) as u64 ) ) ,
58+ last_area : ( self_ptr as * const ( ) as u64 + ( self . size - self . entry_size ) as u64 ) ,
4459 entry_size : self . entry_size ,
4560 phantom : PhantomData ,
4661 }
4762 }
4863}
4964
65+ impl TagTrait for MemoryMapTag {
66+ fn dst_size ( base_tag : & Tag ) -> usize {
67+ assert ! ( base_tag. size as usize >= METADATA_SIZE ) ;
68+ base_tag. size as usize - METADATA_SIZE
69+ }
70+ }
71+
5072/// A memory area entry descriptor.
51- #[ derive( Debug ) ]
73+ #[ derive( Debug , Clone ) ]
5274#[ repr( C ) ]
5375pub struct MemoryArea {
5476 base_addr : u64 ,
@@ -58,6 +80,16 @@ pub struct MemoryArea {
5880}
5981
6082impl MemoryArea {
83+ /// Create a new MemoryArea.
84+ pub fn new ( base_addr : u64 , length : u64 , typ : MemoryAreaType ) -> Self {
85+ Self {
86+ base_addr,
87+ length,
88+ typ,
89+ _reserved : 0 ,
90+ }
91+ }
92+
6193 /// The start address of the memory region.
6294 pub fn start_address ( & self ) -> u64 {
6395 self . base_addr
@@ -79,6 +111,8 @@ impl MemoryArea {
79111 }
80112}
81113
114+ impl StructAsBytes for MemoryArea { }
115+
82116/// An enum of possible reported region types.
83117/// Inside the Multiboot2 spec this is kind of hidden
84118/// inside the implementation of `struct multiboot_mmap_entry`.
0 commit comments