@@ -8,7 +8,6 @@ use crate::{
8
8
EntryAddressHeaderTag , EntryEfi32HeaderTag , EntryEfi64HeaderTag , FramebufferHeaderTag ,
9
9
ModuleAlignHeaderTag , Multiboot2BasicHeader , RelocatableHeaderTag ,
10
10
} ;
11
- use alloc:: boxed:: Box ;
12
11
use alloc:: vec:: Vec ;
13
12
use core:: mem:: size_of;
14
13
use core:: ops:: Deref ;
@@ -22,7 +21,7 @@ pub struct HeaderBytes {
22
21
// guarantee alignment at the moment.
23
22
offset : usize ,
24
23
structure_len : usize ,
25
- bytes : Box < [ u8 ] > ,
24
+ bytes : Vec < u8 > ,
26
25
}
27
26
28
27
impl HeaderBytes {
@@ -163,7 +162,7 @@ impl HeaderBuilder {
163
162
pub fn build ( mut self ) -> HeaderBytes {
164
163
const ALIGN : usize = 8 ;
165
164
166
- // PHASE 1/3 : Prepare Vector
165
+ // PHASE 1/2 : Prepare Vector
167
166
168
167
// We allocate more than necessary so that we can ensure an correct
169
168
// alignment within this data.
@@ -184,17 +183,9 @@ impl HeaderBuilder {
184
183
bytes. extend ( [ 0 ] . repeat ( offset) ) ;
185
184
186
185
// -----------------------------------------------
187
- // PHASE 2/3 : Add Tags
186
+ // PHASE 2/2 : Add Tags
188
187
self . build_add_tags ( & mut bytes) ;
189
188
190
- // -----------------------------------------------
191
- // PHASE 3/3: Finalize Vector
192
-
193
- // Ensure that the vector has the same length as it's capacity. This is
194
- // important so that miri doesn't complain that the boxed memory is
195
- // smaller than the original allocation.
196
- bytes. extend ( [ 0 ] . repeat ( bytes. capacity ( ) - bytes. len ( ) ) ) ;
197
-
198
189
assert_eq ! (
199
190
alloc_ptr,
200
191
bytes. as_ptr( ) ,
@@ -206,11 +197,6 @@ impl HeaderBuilder {
206
197
"The offset to alignment area should be zero."
207
198
) ;
208
199
209
- // Construct a box from a vec without `into_boxed_slice`. The latter
210
- // calls `shrink` on the allocator, which might reallocate this memory.
211
- // We don't want that!
212
- let bytes = unsafe { Box :: from_raw ( bytes. leak ( ) ) } ;
213
-
214
200
HeaderBytes {
215
201
offset,
216
202
bytes,
@@ -316,6 +302,42 @@ mod tests {
316
302
RelocatableHeaderTagPreference ,
317
303
} ;
318
304
305
+ fn create_builder ( ) -> HeaderBuilder {
306
+ let builder = HeaderBuilder :: new ( HeaderTagISA :: I386 ) ;
307
+ // Multiboot2 basic header + end tag
308
+ let mut expected_len = 16 + 8 ;
309
+ assert_eq ! ( builder. expected_len( ) , expected_len) ;
310
+
311
+ // add information request tag
312
+ let ifr_builder =
313
+ InformationRequestHeaderTagBuilder :: new ( HeaderTagFlag :: Required ) . add_irs ( & [
314
+ MbiTagType :: EfiMmap ,
315
+ MbiTagType :: Cmdline ,
316
+ MbiTagType :: ElfSections ,
317
+ ] ) ;
318
+ let ifr_tag_size_with_padding = ifr_builder. expected_len ( ) + 4 ;
319
+ assert_eq ! (
320
+ ifr_tag_size_with_padding % 8 ,
321
+ 0 ,
322
+ "the length of the IFR tag with padding must be a multiple of 8"
323
+ ) ;
324
+ expected_len += ifr_tag_size_with_padding;
325
+ let builder = builder. information_request_tag ( ifr_builder) ;
326
+ assert_eq ! ( builder. expected_len( ) , expected_len) ;
327
+
328
+ let builder = builder. relocatable_tag ( RelocatableHeaderTag :: new (
329
+ HeaderTagFlag :: Required ,
330
+ 0x1337 ,
331
+ 0xdeadbeef ,
332
+ 4096 ,
333
+ RelocatableHeaderTagPreference :: None ,
334
+ ) ) ;
335
+ expected_len += 0x18 ;
336
+ assert_eq ! ( builder. expected_len( ) , expected_len) ;
337
+
338
+ builder
339
+ }
340
+
319
341
#[ test]
320
342
fn test_size_or_up_aligned ( ) {
321
343
assert_eq ! ( 0 , HeaderBuilder :: size_or_up_aligned( 0 ) ) ;
@@ -324,73 +346,44 @@ mod tests {
324
346
assert_eq ! ( 16 , HeaderBuilder :: size_or_up_aligned( 9 ) ) ;
325
347
}
326
348
349
+ /// Test of the `build` method in isolation specifically for miri to check
350
+ /// for memory issues.
351
+ #[ test]
352
+ fn test_builder_miri ( ) {
353
+ let builder = create_builder ( ) ;
354
+ let expected_len = builder. expected_len ( ) ;
355
+ assert_eq ! ( builder. build( ) . as_bytes( ) . len( ) , expected_len) ;
356
+ }
357
+
327
358
#[ test]
328
359
fn test_builder ( ) {
329
360
// Step 1/2: Build Header
330
- let ( mb2_hdr_data, expected_len) = {
331
- let builder = HeaderBuilder :: new ( HeaderTagISA :: I386 ) ;
332
- // Multiboot2 basic header + end tag
333
- let mut expected_len = 16 + 8 ;
334
- assert_eq ! ( builder. expected_len( ) , expected_len) ;
335
-
336
- // add information request tag
337
- let ifr_builder = InformationRequestHeaderTagBuilder :: new ( HeaderTagFlag :: Required )
338
- . add_irs ( & [
339
- MbiTagType :: EfiMmap ,
340
- MbiTagType :: Cmdline ,
341
- MbiTagType :: ElfSections ,
342
- ] ) ;
343
- let ifr_tag_size_with_padding = ifr_builder. expected_len ( ) + 4 ;
344
- assert_eq ! (
345
- ifr_tag_size_with_padding % 8 ,
346
- 0 ,
347
- "the length of the IFR tag with padding must be a multiple of 8"
348
- ) ;
349
- expected_len += ifr_tag_size_with_padding;
350
- let builder = builder. information_request_tag ( ifr_builder) ;
351
- assert_eq ! ( builder. expected_len( ) , expected_len) ;
352
-
353
- let builder = builder. relocatable_tag ( RelocatableHeaderTag :: new (
354
- HeaderTagFlag :: Required ,
355
- 0x1337 ,
356
- 0xdeadbeef ,
357
- 4096 ,
358
- RelocatableHeaderTagPreference :: None ,
359
- ) ) ;
360
- expected_len += 0x18 ;
361
- assert_eq ! ( builder. expected_len( ) , expected_len) ;
362
-
363
- println ! ( "builder: {:#?}" , builder) ;
364
- println ! ( "expected_len: {} bytes" , builder. expected_len( ) ) ;
365
-
366
- ( builder. build ( ) , expected_len)
367
- } ;
368
-
369
- assert_eq ! ( mb2_hdr_data. as_bytes( ) . len( ) , expected_len) ;
361
+ let mb2_hdr_data = create_builder ( ) . build ( ) ;
370
362
371
363
// Step 2/2: Test the built Header
372
- {
373
- let mb2_hdr = mb2_hdr_data. as_ptr ( ) . cast ( ) ;
374
- let mb2_hdr = unsafe { Multiboot2Header :: load ( mb2_hdr) }
375
- . expect ( "the generated header to be loadable" ) ;
376
- println ! ( "{:#?}" , mb2_hdr) ;
377
- assert_eq ! (
378
- mb2_hdr. relocatable_tag( ) . unwrap( ) . flags( ) ,
379
- HeaderTagFlag :: Required
380
- ) ;
381
- assert_eq ! ( mb2_hdr. relocatable_tag( ) . unwrap( ) . min_addr( ) , 0x1337 ) ;
382
- assert_eq ! ( mb2_hdr. relocatable_tag( ) . unwrap( ) . max_addr( ) , 0xdeadbeef ) ;
383
- assert_eq ! ( mb2_hdr. relocatable_tag( ) . unwrap( ) . align( ) , 4096 ) ;
384
- assert_eq ! (
385
- mb2_hdr. relocatable_tag( ) . unwrap( ) . preference( ) ,
386
- RelocatableHeaderTagPreference :: None
387
- ) ;
388
-
389
- /* you can write the binary to a file and a tool such as crate "bootinfo"
390
- will be able to fully parse the MB2 header
391
- let mut file = std::file::File::create("mb2_hdr.bin").unwrap();
392
- use std::io::Write;
393
- file.write_all(mb2_hdr_data.as_slice()).unwrap();*/
394
- }
364
+ let mb2_hdr = mb2_hdr_data. as_ptr ( ) . cast ( ) ;
365
+ let mb2_hdr = unsafe { Multiboot2Header :: load ( mb2_hdr) }
366
+ . expect ( "the generated header to be loadable" ) ;
367
+ println ! ( "{:#?}" , mb2_hdr) ;
368
+ assert_eq ! (
369
+ mb2_hdr. relocatable_tag( ) . unwrap( ) . flags( ) ,
370
+ HeaderTagFlag :: Required
371
+ ) ;
372
+ assert_eq ! ( mb2_hdr. relocatable_tag( ) . unwrap( ) . min_addr( ) , 0x1337 ) ;
373
+ assert_eq ! ( mb2_hdr. relocatable_tag( ) . unwrap( ) . max_addr( ) , 0xdeadbeef ) ;
374
+ assert_eq ! ( mb2_hdr. relocatable_tag( ) . unwrap( ) . align( ) , 4096 ) ;
375
+ assert_eq ! (
376
+ mb2_hdr. relocatable_tag( ) . unwrap( ) . preference( ) ,
377
+ RelocatableHeaderTagPreference :: None
378
+ ) ;
379
+
380
+ // Printing the header transitively ensures that a lot of stuff works.
381
+ println ! ( "{:#?}" , mb2_hdr) ;
382
+
383
+ /* you can write the binary to a file and a tool such as crate "bootinfo"
384
+ will be able to fully parse the MB2 header
385
+ let mut file = std::file::File::create("mb2_hdr.bin").unwrap();
386
+ use std::io::Write;
387
+ file.write_all(mb2_hdr_data.as_slice()).unwrap();*/
395
388
}
396
389
}
0 commit comments