@@ -8,7 +8,6 @@ use crate::{
88 EntryAddressHeaderTag , EntryEfi32HeaderTag , EntryEfi64HeaderTag , FramebufferHeaderTag ,
99 ModuleAlignHeaderTag , Multiboot2BasicHeader , RelocatableHeaderTag ,
1010} ;
11- use alloc:: boxed:: Box ;
1211use alloc:: vec:: Vec ;
1312use core:: mem:: size_of;
1413use core:: ops:: Deref ;
@@ -22,7 +21,7 @@ pub struct HeaderBytes {
2221 // guarantee alignment at the moment.
2322 offset : usize ,
2423 structure_len : usize ,
25- bytes : Box < [ u8 ] > ,
24+ bytes : Vec < u8 > ,
2625}
2726
2827impl HeaderBytes {
@@ -163,7 +162,7 @@ impl HeaderBuilder {
163162 pub fn build ( mut self ) -> HeaderBytes {
164163 const ALIGN : usize = 8 ;
165164
166- // PHASE 1/3 : Prepare Vector
165+ // PHASE 1/2 : Prepare Vector
167166
168167 // We allocate more than necessary so that we can ensure an correct
169168 // alignment within this data.
@@ -184,17 +183,9 @@ impl HeaderBuilder {
184183 bytes. extend ( [ 0 ] . repeat ( offset) ) ;
185184
186185 // -----------------------------------------------
187- // PHASE 2/3 : Add Tags
186+ // PHASE 2/2 : Add Tags
188187 self . build_add_tags ( & mut bytes) ;
189188
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-
198189 assert_eq ! (
199190 alloc_ptr,
200191 bytes. as_ptr( ) ,
@@ -206,11 +197,6 @@ impl HeaderBuilder {
206197 "The offset to alignment area should be zero."
207198 ) ;
208199
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-
214200 HeaderBytes {
215201 offset,
216202 bytes,
@@ -316,6 +302,42 @@ mod tests {
316302 RelocatableHeaderTagPreference ,
317303 } ;
318304
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+
319341 #[ test]
320342 fn test_size_or_up_aligned ( ) {
321343 assert_eq ! ( 0 , HeaderBuilder :: size_or_up_aligned( 0 ) ) ;
@@ -324,73 +346,44 @@ mod tests {
324346 assert_eq ! ( 16 , HeaderBuilder :: size_or_up_aligned( 9 ) ) ;
325347 }
326348
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+
327358 #[ test]
328359 fn test_builder ( ) {
329360 // 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 ( ) ;
370362
371363 // 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();*/
395388 }
396389}
0 commit comments