@@ -12,8 +12,9 @@ use crate::{
12
12
} ;
13
13
use core:: fmt;
14
14
use core:: mem;
15
- use core:: ptr ;
15
+ use core:: slice ;
16
16
use derive_more:: Display ;
17
+ use multiboot2_common:: { BytesRef , DynSizedStructure , Header } ;
17
18
18
19
/// Error type that describes errors while loading/parsing a multiboot2 information structure
19
20
/// from a given address.
@@ -62,40 +63,18 @@ impl BootInformationHeader {
62
63
}
63
64
}
64
65
65
- #[ cfg( feature = "builder" ) ]
66
- impl AsBytes for BootInformationHeader { }
67
-
68
- /// This type holds the whole data of the MBI. This helps to better satisfy miri
69
- /// when it checks for memory issues.
70
- #[ derive( ptr_meta:: Pointee ) ]
71
- #[ repr( C , align( 8 ) ) ]
72
- struct BootInformationInner {
73
- header : BootInformationHeader ,
74
- tags : [ u8 ] ,
75
- }
76
-
77
- impl BootInformationInner {
78
- /// Checks if the MBI has a valid end tag by checking the end of the mbi's
79
- /// bytes.
80
- fn has_valid_end_tag ( & self ) -> bool {
81
- let self_ptr = ptr:: addr_of!( * self ) ;
82
-
83
- let end_tag_ptr = unsafe {
84
- self_ptr
85
- . cast :: < u8 > ( )
86
- . add ( self . header . total_size as usize )
87
- . sub ( mem:: size_of :: < EndTag > ( ) )
88
- . cast :: < TagHeader > ( )
89
- } ;
90
- let end_tag = unsafe { & * end_tag_ptr } ;
91
-
92
- end_tag. typ == EndTag :: ID && end_tag. size as usize == mem:: size_of :: < EndTag > ( )
66
+ impl Header for BootInformationHeader {
67
+ fn payload_len ( & self ) -> usize {
68
+ self . total_size as usize - size_of :: < Self > ( )
93
69
}
94
70
}
95
71
72
+ #[ cfg( feature = "builder" ) ]
73
+ impl AsBytes for BootInformationHeader { }
74
+
96
75
/// A Multiboot 2 Boot Information (MBI) accessor.
97
76
#[ repr( transparent) ]
98
- pub struct BootInformation < ' a > ( & ' a BootInformationInner ) ;
77
+ pub struct BootInformation < ' a > ( & ' a DynSizedStructure < BootInformationHeader > ) ;
99
78
100
79
impl < ' a > BootInformation < ' a > {
101
80
/// Loads the [`BootInformation`] from a pointer. The pointer must be valid
@@ -115,7 +94,7 @@ impl<'a> BootInformation<'a> {
115
94
/// ```
116
95
///
117
96
/// ## Safety
118
- /// * `ptr` must be valid for reading. Otherwise this function might cause
97
+ /// * `ptr` must be valid for reading. Otherwise, this function might cause
119
98
/// invalid machine state or crash your binary (kernel). This can be the
120
99
/// case in environments with standard environment (segfault), but also in
121
100
/// boot environments, such as UEFI.
@@ -135,16 +114,39 @@ impl<'a> BootInformation<'a> {
135
114
return Err ( MbiLoadError :: IllegalTotalSize ( mbi. total_size ) ) ;
136
115
}
137
116
138
- let slice_size = mbi. total_size as usize - mem:: size_of :: < BootInformationHeader > ( ) ;
139
- // mbi: reference to full mbi
140
- let mbi = ptr_meta:: from_raw_parts :: < BootInformationInner > ( ptr. cast ( ) , slice_size) ;
141
- let mbi = & * mbi;
117
+ let slice = unsafe { slice:: from_raw_parts ( ptr. cast :: < u8 > ( ) , mbi. total_size as usize ) } ;
118
+ let bytes = BytesRef :: < BootInformationHeader > :: try_from ( slice) . map_err ( |e| {
119
+ log:: error!( "Load error: {e:#?}" ) ;
120
+ MbiLoadError :: IllegalAddress
121
+ } ) ?;
122
+ let inner = DynSizedStructure :: ref_from ( bytes) . map_err ( |e| {
123
+ log:: error!( "Load error: {e:#?}" ) ;
124
+ MbiLoadError :: IllegalTotalSize ( mbi. total_size )
125
+ } ) ?;
142
126
143
- if !mbi. has_valid_end_tag ( ) {
127
+ let this = Self ( inner) ;
128
+
129
+ if !this. has_valid_end_tag ( ) {
144
130
return Err ( MbiLoadError :: NoEndTag ) ;
145
131
}
132
+ Ok ( this)
133
+ }
134
+
135
+ /// Checks if the MBI has a valid end tag by checking the end of the mbi's
136
+ /// bytes.
137
+ fn has_valid_end_tag ( & self ) -> bool {
138
+ let header = self . 0 . header ( ) ;
139
+ let end_tag_ptr = unsafe {
140
+ self . 0
141
+ . payload ( )
142
+ . as_ptr ( )
143
+ . add ( header. payload_len ( ) )
144
+ . sub ( mem:: size_of :: < EndTag > ( ) )
145
+ . cast :: < TagHeader > ( )
146
+ } ;
147
+ let end_tag = unsafe { & * end_tag_ptr } ;
146
148
147
- Ok ( Self ( mbi ) )
149
+ end_tag . typ == EndTag :: ID && end_tag . size as usize == mem :: size_of :: < EndTag > ( )
148
150
}
149
151
150
152
/// Get the start address of the boot info.
@@ -177,7 +179,7 @@ impl<'a> BootInformation<'a> {
177
179
/// Get the total size of the boot info struct.
178
180
#[ must_use]
179
181
pub const fn total_size ( & self ) -> usize {
180
- self . 0 . header . total_size as usize
182
+ self . 0 . header ( ) . total_size as usize
181
183
}
182
184
183
185
// ######################################################
@@ -408,7 +410,7 @@ impl<'a> BootInformation<'a> {
408
410
409
411
/// Returns an iterator over all tags.
410
412
fn tags ( & self ) -> TagIter {
411
- TagIter :: new ( & self . 0 . tags )
413
+ TagIter :: new ( & self . 0 . payload ( ) )
412
414
}
413
415
}
414
416
0 commit comments