1
- use crate :: tag_type:: { TagType , TagTypeId } ;
1
+ use crate :: { Tag , TagTrait , TagType , TagTypeId } ;
2
+
2
3
use core:: convert:: TryInto ;
3
4
use core:: marker:: PhantomData ;
4
5
use core:: mem;
5
6
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
+
6
12
/// This tag provides an initial host memory map.
7
13
///
8
14
/// The map provided is guaranteed to list all standard RAM that should be
@@ -13,17 +19,28 @@ use core::mem;
13
19
/// This tag may not be provided by some boot loaders on EFI platforms if EFI
14
20
/// boot services are enabled and available for the loaded image (The EFI boot
15
21
/// services tag may exist in the Multiboot2 boot information structure).
16
- #[ derive( Debug ) ]
22
+ #[ derive( Debug , ptr_meta :: Pointee ) ]
17
23
#[ repr( C ) ]
18
24
pub struct MemoryMapTag {
19
25
typ : TagTypeId ,
20
26
size : u32 ,
21
27
entry_size : u32 ,
22
28
entry_version : u32 ,
23
- first_area : [ MemoryArea ; 0 ] ,
29
+ areas : [ MemoryArea ] ,
24
30
}
25
31
26
32
impl 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
+
27
44
/// Return an iterator over all memory areas that have the type
28
45
/// [`MemoryAreaType::Available`].
29
46
pub fn available_memory_areas ( & self ) -> impl Iterator < Item = & MemoryArea > {
@@ -34,21 +51,26 @@ impl MemoryMapTag {
34
51
/// Return an iterator over all memory areas.
35
52
pub fn memory_areas ( & self ) -> MemoryAreaIter {
36
53
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 ;
39
55
MemoryAreaIter {
40
56
current_area : start_area as u64 ,
41
57
// 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 ) ,
44
59
entry_size : self . entry_size ,
45
60
phantom : PhantomData ,
46
61
}
47
62
}
48
63
}
49
64
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
+
50
72
/// A memory area entry descriptor.
51
- #[ derive( Debug ) ]
73
+ #[ derive( Debug , Clone ) ]
52
74
#[ repr( C ) ]
53
75
pub struct MemoryArea {
54
76
base_addr : u64 ,
@@ -58,6 +80,16 @@ pub struct MemoryArea {
58
80
}
59
81
60
82
impl 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
+
61
93
/// The start address of the memory region.
62
94
pub fn start_address ( & self ) -> u64 {
63
95
self . base_addr
@@ -79,6 +111,8 @@ impl MemoryArea {
79
111
}
80
112
}
81
113
114
+ impl StructAsBytes for MemoryArea { }
115
+
82
116
/// An enum of possible reported region types.
83
117
/// Inside the Multiboot2 spec this is kind of hidden
84
118
/// inside the implementation of `struct multiboot_mmap_entry`.
0 commit comments