Skip to content

Commit fb7c805

Browse files
committed
multiboot2: consume multiboot2-common (2/N): BootInformation
We get rid of BootInformationInner and use BootInformation as wrapper around our new common type.
1 parent 02fe305 commit fb7c805

File tree

1 file changed

+41
-39
lines changed

1 file changed

+41
-39
lines changed

multiboot2/src/boot_information.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ use crate::{
1212
};
1313
use core::fmt;
1414
use core::mem;
15-
use core::ptr;
15+
use core::slice;
1616
use derive_more::Display;
17+
use multiboot2_common::{BytesRef, DynSizedStructure, Header};
1718

1819
/// Error type that describes errors while loading/parsing a multiboot2 information structure
1920
/// from a given address.
@@ -62,40 +63,18 @@ impl BootInformationHeader {
6263
}
6364
}
6465

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>()
9369
}
9470
}
9571

72+
#[cfg(feature = "builder")]
73+
impl AsBytes for BootInformationHeader {}
74+
9675
/// A Multiboot 2 Boot Information (MBI) accessor.
9776
#[repr(transparent)]
98-
pub struct BootInformation<'a>(&'a BootInformationInner);
77+
pub struct BootInformation<'a>(&'a DynSizedStructure<BootInformationHeader>);
9978

10079
impl<'a> BootInformation<'a> {
10180
/// Loads the [`BootInformation`] from a pointer. The pointer must be valid
@@ -115,7 +94,7 @@ impl<'a> BootInformation<'a> {
11594
/// ```
11695
///
11796
/// ## 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
11998
/// invalid machine state or crash your binary (kernel). This can be the
12099
/// case in environments with standard environment (segfault), but also in
121100
/// boot environments, such as UEFI.
@@ -135,16 +114,39 @@ impl<'a> BootInformation<'a> {
135114
return Err(MbiLoadError::IllegalTotalSize(mbi.total_size));
136115
}
137116

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+
})?;
142126

143-
if !mbi.has_valid_end_tag() {
127+
let this = Self(inner);
128+
129+
if !this.has_valid_end_tag() {
144130
return Err(MbiLoadError::NoEndTag);
145131
}
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 };
146148

147-
Ok(Self(mbi))
149+
end_tag.typ == EndTag::ID && end_tag.size as usize == mem::size_of::<EndTag>()
148150
}
149151

150152
/// Get the start address of the boot info.
@@ -177,7 +179,7 @@ impl<'a> BootInformation<'a> {
177179
/// Get the total size of the boot info struct.
178180
#[must_use]
179181
pub const fn total_size(&self) -> usize {
180-
self.0.header.total_size as usize
182+
self.0.header().total_size as usize
181183
}
182184

183185
// ######################################################
@@ -408,7 +410,7 @@ impl<'a> BootInformation<'a> {
408410

409411
/// Returns an iterator over all tags.
410412
fn tags(&self) -> TagIter {
411-
TagIter::new(&self.0.tags)
413+
TagIter::new(&self.0.payload())
412414
}
413415
}
414416

0 commit comments

Comments
 (0)