Skip to content

Commit 3840437

Browse files
committed
load function returns result
1 parent 12ae262 commit 3840437

File tree

1 file changed

+68
-32
lines changed

1 file changed

+68
-32
lines changed

src/lib.rs

Lines changed: 68 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)