|
@@ -22,9 +22,9 @@
|
|
|
//! ## Example
|
|
|
//!
|
|
|
//! ```rust
|
|
|
-//! use multiboot2::load;
|
|
|
+//! use multiboot2::BootInformation;
|
|
|
//! fn kmain(multiboot_info_ptr: u32) {
|
|
|
-//! let boot_info = unsafe { load(multiboot_info_ptr as usize).unwrap() };
|
|
|
+//! let boot_info = unsafe { BootInformation::load(multiboot_info_ptr as *const u8).unwrap() };
|
|
|
//! println!("{:?}", boot_info);
|
|
|
//! }
|
|
|
//! ```
|
|
@@ -98,77 +98,24 @@ pub mod builder;
|
|
|
/// that the Rust compiler output changes `eax` before you can access it.
|
|
|
pub const MAGIC: u32 = 0x36d76289;
|
|
|
|
|
|
-/// Load the multiboot boot information struct from an address.
|
|
|
-///
|
|
|
-/// This is the same as [`load_with_offset`] but the offset is omitted and set
|
|
|
-/// to zero.
|
|
|
-///
|
|
|
-/// ## Example
|
|
|
-///
|
|
|
-/// ```rust
|
|
|
-/// use multiboot2::load;
|
|
|
-///
|
|
|
-/// fn kmain(multiboot_info_ptr: u32) {
|
|
|
-/// let boot_info = unsafe { load(multiboot_info_ptr as usize).unwrap() };
|
|
|
-/// println!("{:?}", boot_info);
|
|
|
-/// }
|
|
|
-/// ```
|
|
|
-///
|
|
|
-/// ## Safety
|
|
|
-/// * `address` must be valid for reading. Otherwise this function might
|
|
|
-/// terminate the program. This can be the case in environments with standard
|
|
|
-/// environment (segfault) but also in UEFI-applications, where the referenced
|
|
|
-/// memory is not (identity) mapped (UEFI does only identity mapping).
|
|
|
-/// * The memory at `address` must not be modified after calling `load` or the
|
|
|
-/// program may observe unsynchronized mutation.
|
|
|
-pub unsafe fn load(address: usize) -> Result<BootInformation, MbiLoadError> {
|
|
|
- load_with_offset(address, 0)
|
|
|
+/// # Safety
|
|
|
+/// Deprecated. Please use BootInformation::load() instead.
|
|
|
+#[deprecated = "Please use BootInformation::load() instead."]
|
|
|
+pub unsafe fn load<'a>(address: usize) -> Result<BootInformation<'a>, MbiLoadError> {
|
|
|
+ let ptr = address as *const u8;
|
|
|
+ BootInformation::load(ptr)
|
|
|
}
|
|
|
|
|
|
-/// Load the multiboot boot information struct from an address at an offset.
|
|
|
-///
|
|
|
-/// ## Example
|
|
|
-///
|
|
|
-/// ```rust,no_run
|
|
|
-/// use multiboot2::load_with_offset;
|
|
|
-///
|
|
|
-/// let ptr = 0xDEADBEEF as *const u32;
|
|
|
-/// let boot_info = unsafe { load_with_offset(ptr as usize, 0xCAFEBABE).unwrap() };
|
|
|
-/// println!("{:?}", boot_info);
|
|
|
-/// ```
|
|
|
-///
|
|
|
-/// ## Safety
|
|
|
-/// * `address` must be valid for reading. Otherwise this function might
|
|
|
-/// terminate the program. This can be the case in environments with standard
|
|
|
-/// environment (segfault) but also in UEFI-applications, where the referenced
|
|
|
-/// memory is not (identity) mapped (UEFI does only identity mapping).
|
|
|
-/// * The memory at `address` must not be modified after calling `load` or the
|
|
|
-/// program may observe unsynchronized mutation.
|
|
|
-pub unsafe fn load_with_offset(
|
|
|
+/// # Safety
|
|
|
+/// Deprecated. Please use BootInformation::load() instead.
|
|
|
+#[deprecated = "Please use BootInformation::load() instead."]
|
|
|
+pub unsafe fn load_with_offset<'a>(
|
|
|
address: usize,
|
|
|
offset: usize,
|
|
|
-) -> Result<BootInformation, MbiLoadError> {
|
|
|
- let address = address + offset;
|
|
|
- let null_ptr = address == 0;
|
|
|
- let eight_byte_aligned = address & 0b111 == 0;
|
|
|
- if null_ptr || !eight_byte_aligned {
|
|
|
- return Err(MbiLoadError::IllegalAddress);
|
|
|
- }
|
|
|
-
|
|
|
- let multiboot = &*(address as *const BootInformationInner);
|
|
|
- // Check if total size is a multiple of 8.
|
|
|
- // See MbiLoadError::IllegalTotalSize for comments
|
|
|
- if multiboot.total_size & 0b111 != 0 {
|
|
|
- return Err(MbiLoadError::IllegalTotalSize(multiboot.total_size));
|
|
|
- }
|
|
|
- if !multiboot.has_valid_end_tag() {
|
|
|
- return Err(MbiLoadError::NoEndTag);
|
|
|
- }
|
|
|
-
|
|
|
- Ok(BootInformation {
|
|
|
- inner: multiboot,
|
|
|
- offset,
|
|
|
- })
|
|
|
+) -> Result<BootInformation<'a>, MbiLoadError> {
|
|
|
+ let ptr = address as *const u8;
|
|
|
+ let ptr = ptr.add(offset);
|
|
|
+ BootInformation::load(ptr.cast())
|
|
|
}
|
|
|
|
|
|
/// Error type that describes errors while loading/parsing a multiboot2 information structure
|
|
@@ -192,17 +139,66 @@ pub enum MbiLoadError {
|
|
|
#[cfg(feature = "unstable")]
|
|
|
impl core::error::Error for MbiLoadError {}
|
|
|
|
|
|
-/// A Multiboot 2 Boot Information struct.
|
|
|
-pub struct BootInformation {
|
|
|
- inner: *const BootInformationInner,
|
|
|
- offset: usize,
|
|
|
+/// A Multiboot 2 Boot Information (MBI) accessor.
|
|
|
+#[repr(transparent)]
|
|
|
+pub struct BootInformation<'a>(&'a BootInformationInner);
|
|
|
+
|
|
|
+impl BootInformation<'_> {
|
|
|
+ /// Loads the [`BootInformation`] from a pointer. The pointer must be valid
|
|
|
+ /// and aligned to an 8-byte boundary, as defined by the spec.
|
|
|
+ ///
|
|
|
+ /// ## Example
|
|
|
+ ///
|
|
|
+ /// ```rust
|
|
|
+ /// use multiboot2::BootInformation;
|
|
|
+ ///
|
|
|
+ /// fn kernel_entry(mb_magic: u32, mbi_ptr: u32) {
|
|
|
+ /// if mb_magic == multiboot2::MAGIC {
|
|
|
+ /// let boot_info = unsafe { BootInformation::load(mbi_ptr as *const u8).unwrap() };
|
|
|
+ /// let _cmd = boot_info.command_line_tag();
|
|
|
+ /// } else { /* Panic or use multiboot1 flow. */ }
|
|
|
+ /// }
|
|
|
+ /// ```
|
|
|
+ ///
|
|
|
+ /// ## Safety
|
|
|
+ /// * `ptr` must be valid for reading. Otherwise this function might cause
|
|
|
+ /// invalid machine state or crash your binary (kernel). This can be the
|
|
|
+ /// case in environments with standard environment (segfault), but also in
|
|
|
+ /// boot environments, such as UEFI.
|
|
|
+ /// * The memory at `ptr` must not be modified after calling `load` or the
|
|
|
+ /// program may observe unsynchronized mutation.
|
|
|
+ pub unsafe fn load(ptr: *const u8) -> Result<Self, MbiLoadError> {
|
|
|
+ if ptr.is_null() {
|
|
|
+ return Err(MbiLoadError::IllegalAddress);
|
|
|
+ }
|
|
|
+
|
|
|
+ // not aligned
|
|
|
+ if ptr.align_offset(8) != 0 {
|
|
|
+ return Err(MbiLoadError::IllegalAddress);
|
|
|
+ }
|
|
|
+
|
|
|
+ let mbi = &*ptr.cast::<BootInformationInner>();
|
|
|
+
|
|
|
+ // Check if total size is a multiple of 8.
|
|
|
+ // See MbiLoadError::IllegalTotalSize for comments
|
|
|
+ if mbi.total_size & 0b111 != 0 {
|
|
|
+ return Err(MbiLoadError::IllegalTotalSize(mbi.total_size));
|
|
|
+ }
|
|
|
+
|
|
|
+ if !mbi.has_valid_end_tag() {
|
|
|
+ return Err(MbiLoadError::NoEndTag);
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(Self(mbi))
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-#[derive(Clone, Copy)]
|
|
|
-#[repr(C)]
|
|
|
+#[repr(C, align(8))]
|
|
|
struct BootInformationInner {
|
|
|
total_size: u32,
|
|
|
_reserved: u32,
|
|
|
+ // followed by various, dynamically sized multiboot2 tags
|
|
|
+ tags: [Tag; 0],
|
|
|
}
|
|
|
|
|
|
impl BootInformationInner {
|
|
@@ -211,6 +207,7 @@ impl BootInformationInner {
|
|
|
Self {
|
|
|
total_size,
|
|
|
_reserved: 0,
|
|
|
+ tags: [],
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -222,10 +219,15 @@ impl StructAsBytes for BootInformationInner {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl BootInformation {
|
|
|
+impl BootInformation<'_> {
|
|
|
/// Get the start address of the boot info.
|
|
|
pub fn start_address(&self) -> usize {
|
|
|
- self.inner as usize
|
|
|
+ core::ptr::addr_of!(*self.0) as usize
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get the start address of the boot info as pointer.
|
|
|
+ pub fn as_ptr(&self) -> *const () {
|
|
|
+ core::ptr::addr_of!(*self.0).cast()
|
|
|
}
|
|
|
|
|
|
/// Get the end address of the boot info.
|
|
@@ -242,7 +244,7 @@ impl BootInformation {
|
|
|
|
|
|
/// Get the total size of the boot info struct.
|
|
|
pub fn total_size(&self) -> usize {
|
|
|
- self.get().total_size as usize
|
|
|
+ self.0.total_size as usize
|
|
|
}
|
|
|
|
|
|
/// Search for the basic memory info tag.
|
|
@@ -268,7 +270,7 @@ impl BootInformation {
|
|
|
let tag = self.get_tag::<ElfSectionsTag, _>(TagType::ElfSections);
|
|
|
tag.map(|t| {
|
|
|
assert!((t.entry_size * t.shndx) <= t.size);
|
|
|
- t.sections(self.offset)
|
|
|
+ t.sections()
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -365,10 +367,6 @@ impl BootInformation {
|
|
|
self.get_tag::<SmbiosTag, _>(TagType::Smbios)
|
|
|
}
|
|
|
|
|
|
- fn get(&self) -> &BootInformationInner {
|
|
|
- unsafe { &*self.inner }
|
|
|
- }
|
|
|
-
|
|
|
/// Public getter to find any Multiboot tag by its type, including
|
|
|
/// specified and custom ones.
|
|
|
///
|
|
@@ -434,7 +432,9 @@ impl BootInformation {
|
|
|
}
|
|
|
|
|
|
fn tags(&self) -> TagIter {
|
|
|
- TagIter::new(unsafe { self.inner.offset(1) } as *const _)
|
|
|
+ // The first tag starts 8 bytes after the begin of the boot info header
|
|
|
+ let ptr = core::ptr::addr_of!(self.0.tags).cast();
|
|
|
+ TagIter::new(ptr)
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -452,9 +452,9 @@ impl BootInformationInner {
|
|
|
|
|
|
// SAFETY: BootInformation contains a const ptr to memory that is never mutated.
|
|
|
// Sending this pointer to other threads is sound.
|
|
|
-unsafe impl Send for BootInformation {}
|
|
|
+unsafe impl Send for BootInformation<'_> {}
|
|
|
|
|
|
-impl fmt::Debug for BootInformation {
|
|
|
+impl fmt::Debug for BootInformation<'_> {
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
/// Limit how many Elf-Sections should be debug-formatted.
|
|
|
/// Can be thousands of sections for a Rust binary => this is useless output.
|
|
@@ -575,8 +575,9 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type
|
|
|
8, 0, 0, 0, // end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -599,8 +600,9 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type
|
|
|
8, 0, 0, // end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -623,8 +625,9 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type
|
|
|
9, 0, 0, 0, // end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -650,8 +653,9 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type
|
|
|
8, 0, 0, 0, // end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -692,8 +696,9 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type
|
|
|
8, 0, 0, 0, // end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -714,16 +719,16 @@ mod tests {
|
|
|
FramebufferType::RGB {
|
|
|
red: FramebufferField {
|
|
|
position: 16,
|
|
|
- size: 8
|
|
|
+ size: 8,
|
|
|
},
|
|
|
green: FramebufferField {
|
|
|
position: 8,
|
|
|
- size: 8
|
|
|
+ size: 8,
|
|
|
},
|
|
|
blue: FramebufferField {
|
|
|
position: 0,
|
|
|
- size: 8
|
|
|
- }
|
|
|
+ size: 8,
|
|
|
+ },
|
|
|
}
|
|
|
);
|
|
|
}
|
|
@@ -751,8 +756,9 @@ mod tests {
|
|
|
255, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, // end tag type
|
|
|
8, 0, 0, 0, // end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -775,22 +781,22 @@ mod tests {
|
|
|
FramebufferColor {
|
|
|
red: 255,
|
|
|
green: 0,
|
|
|
- blue: 0
|
|
|
+ blue: 0,
|
|
|
},
|
|
|
FramebufferColor {
|
|
|
red: 0,
|
|
|
green: 255,
|
|
|
- blue: 0
|
|
|
+ blue: 0,
|
|
|
},
|
|
|
FramebufferColor {
|
|
|
red: 0,
|
|
|
green: 0,
|
|
|
- blue: 255
|
|
|
+ blue: 255,
|
|
|
},
|
|
|
FramebufferColor {
|
|
|
red: 0,
|
|
|
green: 0,
|
|
|
- blue: 0
|
|
|
+ blue: 0,
|
|
|
}
|
|
|
]
|
|
|
),
|
|
@@ -867,8 +873,9 @@ mod tests {
|
|
|
8, 0, 0, 0, // End tag size.
|
|
|
]);
|
|
|
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -923,28 +930,28 @@ mod tests {
|
|
|
vbe.mode_info.red_field,
|
|
|
VBEField {
|
|
|
position: 16,
|
|
|
- size: 8
|
|
|
+ size: 8,
|
|
|
}
|
|
|
);
|
|
|
assert_eq!(
|
|
|
vbe.mode_info.green_field,
|
|
|
VBEField {
|
|
|
position: 8,
|
|
|
- size: 8
|
|
|
+ size: 8,
|
|
|
}
|
|
|
);
|
|
|
assert_eq!(
|
|
|
vbe.mode_info.blue_field,
|
|
|
VBEField {
|
|
|
position: 0,
|
|
|
- size: 8
|
|
|
+ size: 8,
|
|
|
}
|
|
|
);
|
|
|
assert_eq!(
|
|
|
vbe.mode_info.reserved_field,
|
|
|
VBEField {
|
|
|
position: 24,
|
|
|
- size: 8
|
|
|
+ size: 8,
|
|
|
}
|
|
|
);
|
|
|
assert_eq!(
|
|
@@ -965,6 +972,8 @@ mod tests {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// Tests to parse a MBI that was statically extracted from a test run with
|
|
|
+ /// GRUB as bootloader.
|
|
|
#[test]
|
|
|
fn grub2() {
|
|
|
#[repr(C, align(8))]
|
|
@@ -1223,27 +1232,20 @@ mod tests {
|
|
|
for i in 0..8 {
|
|
|
bytes.0[796 + i] = (string_addr >> (i * 8)) as u8;
|
|
|
}
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
-
|
|
|
test_grub2_boot_info(&bi, addr, string_addr, &bytes.0, &string_bytes.0);
|
|
|
+
|
|
|
let bi = unsafe { load_with_offset(addr, 0) };
|
|
|
let bi = bi.unwrap();
|
|
|
test_grub2_boot_info(&bi, addr, string_addr, &bytes.0, &string_bytes.0);
|
|
|
+
|
|
|
let offset = 8usize;
|
|
|
- for i in 0..8 {
|
|
|
- bytes.0[796 + i] = ((string_addr - offset as u64) >> (i * 8)) as u8;
|
|
|
- }
|
|
|
let bi = unsafe { load_with_offset(addr - offset, offset) };
|
|
|
let bi = bi.unwrap();
|
|
|
- test_grub2_boot_info(
|
|
|
- &bi,
|
|
|
- addr,
|
|
|
- string_addr - offset as u64,
|
|
|
- &bytes.0,
|
|
|
- &string_bytes.0,
|
|
|
- );
|
|
|
+ test_grub2_boot_info(&bi, addr, string_addr, &bytes.0, &string_bytes.0);
|
|
|
|
|
|
// Check that the MBI's debug output can be printed without SEGFAULT.
|
|
|
// If this works, it is a good indicator than transitively a lot of
|
|
@@ -1251,6 +1253,7 @@ mod tests {
|
|
|
println!("{bi:#?}");
|
|
|
}
|
|
|
|
|
|
+ /// Helper for [`grub2`].
|
|
|
fn test_grub2_boot_info(
|
|
|
bi: &BootInformation,
|
|
|
addr: usize,
|
|
@@ -1444,8 +1447,9 @@ mod tests {
|
|
|
assert_eq!(255, bytes.0[offset + i]);
|
|
|
bytes.0[offset + i] = (string_addr >> (i * 8)) as u8;
|
|
|
}
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -1486,8 +1490,9 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type.
|
|
|
8, 0, 0, 0, // end tag size.
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -1523,7 +1528,7 @@ mod tests {
|
|
|
0, 0, 0, 0, // end tag type.
|
|
|
8, 0, 0, 0, // end tag size.
|
|
|
]);
|
|
|
- let bi = unsafe { load(bytes2.0.as_ptr() as usize) };
|
|
|
+ let bi = unsafe { BootInformation::load(bytes2.0.as_ptr()) };
|
|
|
let bi = bi.unwrap();
|
|
|
let efi_mmap = bi.efi_memory_map_tag();
|
|
|
assert!(efi_mmap.is_none());
|
|
@@ -1586,8 +1591,9 @@ mod tests {
|
|
|
0,
|
|
|
0, // end: end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -1662,8 +1668,9 @@ mod tests {
|
|
|
0,
|
|
|
0, // end: end tag size
|
|
|
]);
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let addr = ptr as usize;
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
assert_eq!(addr, bi.start_address());
|
|
|
assert_eq!(addr + bytes.0.len(), bi.end_address());
|
|
@@ -1713,8 +1720,8 @@ mod tests {
|
|
|
0, // end tag size
|
|
|
]);
|
|
|
|
|
|
- let addr = bytes.0.as_ptr() as usize;
|
|
|
- let bi = unsafe { load(addr) };
|
|
|
+ let ptr = bytes.0.as_ptr();
|
|
|
+ let bi = unsafe { BootInformation::load(ptr.cast()) };
|
|
|
let bi = bi.unwrap();
|
|
|
|
|
|
let _tag = bi.get_tag::<CommandLineTag, _>(TagType::Cmdline).unwrap();
|