@@ -46,7 +46,7 @@ mod vbe_info;
4646
4747/// Load the multiboot boot information struct from an address.
4848///
49- /// This is the same as `load_with_offset` but the offset is ommitted and set
49+ /// This is the same as `load_with_offset` but the offset is omitted and set
5050/// to zero.
5151///
5252/// Examples
@@ -55,19 +55,12 @@ mod vbe_info;
5555/// use multiboot::load;
5656///
5757/// fn kmain(multiboot_info_ptr: u32) {
58- /// let boot_info = load(ptr as usize);
58+ /// let boot_info = load(ptr as usize).unwrap() ;
5959/// println!("{:?}", boot_info);
6060/// }
6161/// ```
62- pub unsafe fn load ( address : usize ) -> BootInformation {
63- assert_eq ! ( 0 , address & 0b111 ) ;
64- let multiboot = & * ( address as * const BootInformationInner ) ;
65- assert_eq ! ( 0 , multiboot. total_size & 0b111 ) ;
66- assert ! ( multiboot. has_valid_end_tag( ) ) ;
67- BootInformation {
68- inner : multiboot,
69- offset : 0 ,
70- }
62+ pub unsafe fn load ( address : usize ) -> Result < BootInformation , MbiLoadError > {
63+ load_with_offset ( address, 0 )
7164}
7265
7366/// Load the multiboot boot information struct from an address at an offset.
@@ -78,21 +71,48 @@ pub unsafe fn load(address: usize) -> BootInformation {
7871/// use multiboot::load;
7972///
8073/// let ptr = 0xDEADBEEF as *const _;
81- /// let boot_info = load_with_offset(ptr as usize, 0xCAFEBABE);
74+ /// let boot_info = load_with_offset(ptr as usize, 0xCAFEBABE).unwrap() ;
8275/// println!("{:?}", boot_info);
8376/// ```
84- pub unsafe fn load_with_offset ( address : usize , offset : usize ) -> BootInformation {
85- if !cfg ! ( test) {
86- assert_eq ! ( 0 , address & 0b111 ) ;
87- assert_eq ! ( 0 , offset & 0b111 ) ;
77+ pub unsafe fn load_with_offset ( address : usize , offset : usize ) -> Result < BootInformation , MbiLoadError > {
78+ let address = address + offset;
79+ let null_ptr = address == 0 ;
80+ let eight_byte_aligned = address & 0b111 == 0 ;
81+ if null_ptr || !eight_byte_aligned {
82+ return Err ( MbiLoadError :: IllegalAddress ) ;
8883 }
89- let multiboot = & * ( ( address + offset ) as * const BootInformationInner ) ;
90- assert_eq ! ( 0 , multiboot. total_size & 0b111 ) ;
91- assert ! ( multiboot . has_valid_end_tag ( ) ) ;
92- BootInformation {
93- inner : multiboot ,
94- offset ,
84+
85+ let multiboot = & * ( address as * const BootInformationInner ) ;
86+ // Check if total size is a multiple of 8.
87+ // See MbiLoadError::IllegalTotalSize for comments
88+ if multiboot . total_size & 0b111 != 0 {
89+ return Err ( MbiLoadError :: IllegalTotalSize ( multiboot . total_size ) ) ;
9590 }
91+ if !multiboot. has_valid_end_tag ( ) {
92+ return Err ( MbiLoadError :: NoEndTag ) ;
93+ }
94+
95+ Ok (
96+ BootInformation {
97+ inner : multiboot,
98+ offset,
99+ }
100+ )
101+ }
102+
103+ /// Error type that describes errors while loading/parsing a multiboot2 information structure
104+ /// from a given address.
105+ #[ derive( Debug ) ]
106+ pub enum MbiLoadError {
107+ /// The address is invalid. Make sure that the address is 8-byte aligned,
108+ /// according to the spec.
109+ IllegalAddress ,
110+ /// The total size of the multiboot2 information structure must be a multiple of 8.
111+ /// (Not in spec, but it is implicitly the case, because the begin of MBI
112+ /// and all tags are 8-byte aligned and the end tag is exactly 8 byte long).
113+ IllegalTotalSize ( u32 ) ,
114+ /// End tag missing. Each multiboot2 header requires to have an end tag.
115+ NoEndTag ,
96116}
97117
98118/// A Multiboot 2 Boot Information struct.
@@ -367,6 +387,7 @@ mod tests {
367387 ] ) ;
368388 let addr = bytes. 0 . as_ptr ( ) as usize ;
369389 let bi = unsafe { load ( addr) } ;
390+ let bi = bi. unwrap ( ) ;
370391 assert_eq ! ( addr, bi. start_address( ) ) ;
371392 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
372393 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -390,6 +411,7 @@ mod tests {
390411 ] ) ;
391412 let addr = bytes. 0 . as_ptr ( ) as usize ;
392413 let bi = unsafe { load ( addr) } ;
414+ let bi = bi. unwrap ( ) ;
393415 assert_eq ! ( addr, bi. start_address( ) ) ;
394416 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
395417 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -413,6 +435,7 @@ mod tests {
413435 ] ) ;
414436 let addr = bytes. 0 . as_ptr ( ) as usize ;
415437 let bi = unsafe { load ( addr) } ;
438+ let bi = bi. unwrap ( ) ;
416439 assert_eq ! ( addr, bi. start_address( ) ) ;
417440 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
418441 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -439,6 +462,7 @@ mod tests {
439462 ] ) ;
440463 let addr = bytes. 0 . as_ptr ( ) as usize ;
441464 let bi = unsafe { load ( addr) } ;
465+ let bi = bi. unwrap ( ) ;
442466 assert_eq ! ( addr, bi. start_address( ) ) ;
443467 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
444468 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -483,6 +507,7 @@ mod tests {
483507 ] ) ;
484508 let addr = bytes. 0 . as_ptr ( ) as usize ;
485509 let bi = unsafe { load ( addr) } ;
510+ let bi = bi. unwrap ( ) ;
486511 assert_eq ! ( addr, bi. start_address( ) ) ;
487512 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
488513 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -538,6 +563,7 @@ mod tests {
538563 ] ) ;
539564 let addr = bytes. 0 . as_ptr ( ) as usize ;
540565 let bi = unsafe { load ( addr) } ;
566+ let bi = bi. unwrap ( ) ;
541567 assert_eq ! ( addr, bi. start_address( ) ) ;
542568 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
543569 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -660,6 +686,7 @@ mod tests {
660686
661687 let addr = bytes. 0 . as_ptr ( ) as usize ;
662688 let bi = unsafe { load ( addr) } ;
689+ let bi = bi. unwrap ( ) ;
663690 assert_eq ! ( addr, bi. start_address( ) ) ;
664691 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
665692 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) ) ;
@@ -1015,15 +1042,19 @@ mod tests {
10151042 bytes. 0 [ 796 + i] = ( string_addr >> ( i * 8 ) ) as u8 ;
10161043 }
10171044 let addr = bytes. 0 . as_ptr ( ) as usize ;
1045+ let bi = unsafe { load ( addr) } ;
1046+ let bi = bi. unwrap ( ) ;
10181047 test_grub2_boot_info (
1019- unsafe { load ( addr ) } ,
1048+ bi ,
10201049 addr,
10211050 string_addr,
10221051 & bytes. 0 ,
10231052 & string_bytes. 0 ,
10241053 ) ;
1054+ let bi = unsafe { load_with_offset ( addr, 0 ) } ;
1055+ let bi = bi. unwrap ( ) ;
10251056 test_grub2_boot_info (
1026- unsafe { load_with_offset ( addr , 0 ) } ,
1057+ bi ,
10271058 addr,
10281059 string_addr,
10291060 & bytes. 0 ,
@@ -1033,8 +1064,10 @@ mod tests {
10331064 for i in 0 ..8 {
10341065 bytes. 0 [ 796 + i] = ( ( string_addr - offset as u64 ) >> ( i * 8 ) ) as u8 ;
10351066 }
1067+ let bi = unsafe { load_with_offset ( addr - offset, offset) } ;
1068+ let bi = bi. unwrap ( ) ;
10361069 test_grub2_boot_info (
1037- unsafe { load_with_offset ( addr - offset , offset ) } ,
1070+ bi ,
10381071 addr,
10391072 string_addr - offset as u64 ,
10401073 & bytes. 0 ,
@@ -1221,6 +1254,7 @@ mod tests {
12211254 }
12221255 let addr = bytes. 0 . as_ptr ( ) as usize ;
12231256 let bi = unsafe { load ( addr) } ;
1257+ let bi = bi. unwrap ( ) ;
12241258 assert_eq ! ( addr, bi. start_address( ) ) ;
12251259 assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
12261260 assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) as usize ) ;
@@ -1273,11 +1307,12 @@ mod tests {
12731307 8 , 0 , 0 , 0 , // end tag size.
12741308 ] ) ;
12751309 let addr = bytes. 0 . as_ptr ( ) as usize ;
1276- let boot_info = unsafe { load ( addr) } ;
1277- assert_eq ! ( addr, boot_info. start_address( ) ) ;
1278- assert_eq ! ( addr + bytes. 0 . len( ) , boot_info. end_address( ) ) ;
1279- assert_eq ! ( bytes. 0 . len( ) , boot_info. total_size( ) as usize ) ;
1280- let efi_memory_map = boot_info. efi_memory_map_tag ( ) . unwrap ( ) ;
1310+ let bi = unsafe { load ( addr) } ;
1311+ let bi = bi. unwrap ( ) ;
1312+ assert_eq ! ( addr, bi. start_address( ) ) ;
1313+ assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
1314+ assert_eq ! ( bytes. 0 . len( ) , bi. total_size( ) as usize ) ;
1315+ let efi_memory_map = bi. efi_memory_map_tag ( ) . unwrap ( ) ;
12811316 let mut efi_mmap_iter = efi_memory_map. memory_areas ( ) ;
12821317 let desc = efi_mmap_iter. next ( ) . unwrap ( ) ;
12831318 assert_eq ! ( desc. physical_address( ) , 0x100000 ) ;
@@ -1308,8 +1343,9 @@ mod tests {
13081343 0 , 0 , 0 , 0 , // end tag type.
13091344 8 , 0 , 0 , 0 , // end tag size.
13101345 ] ) ;
1311- let boot_info = unsafe { load ( bytes2. 0 . as_ptr ( ) as usize ) } ;
1312- let efi_mmap = boot_info. efi_memory_map_tag ( ) ;
1346+ let bi = unsafe { load ( bytes2. 0 . as_ptr ( ) as usize ) } ;
1347+ let bi = bi. unwrap ( ) ;
1348+ let efi_mmap = bi. efi_memory_map_tag ( ) ;
13131349 assert ! ( efi_mmap. is_none( ) ) ;
13141350 }
13151351
0 commit comments