浏览代码

Merge pull request #119 from A0lson/efi_fix

multiboot2: Fix EFI Memory Map 'last_area' calculation
Philipp Schuster 2 年之前
父节点
当前提交
f71aedc53d

+ 1 - 1
multiboot2-header/src/builder/information_request.rs

@@ -21,7 +21,7 @@ pub struct InformationRequestHeaderTagBuilder {
 #[cfg(feature = "builder")]
 impl InformationRequestHeaderTagBuilder {
     /// New builder.
-    pub fn new(flag: HeaderTagFlag) -> Self {
+    pub const fn new(flag: HeaderTagFlag) -> Self {
         Self {
             irs: BTreeSet::new(),
             flag,

+ 1 - 2
multiboot2-header/src/header.rs

@@ -47,8 +47,7 @@ impl<'a> Multiboot2Header<'a> {
         assert_eq!(
             reference.header_magic(),
             MULTIBOOT2_HEADER_MAGIC,
-            "The Multiboot2 header must contain the MULTIBOOT2_HEADER_MAGIC={:x}",
-            MULTIBOOT2_HEADER_MAGIC
+            "The Multiboot2 header must contain the MULTIBOOT2_HEADER_MAGIC={MULTIBOOT2_HEADER_MAGIC:x}"
         );
         assert!(
             reference.verify_checksum(),

+ 12 - 2
multiboot2/src/lib.rs

@@ -1415,13 +1415,23 @@ mod tests {
         assert!(efi_mmap.is_none());
     }
 
+    #[test]
+    /// Compile time test for `MemoryMapTag`.
+    fn e820_memory_map_tag_size() {
+        use super::MemoryMapTag;
+        unsafe {
+            // `MemoryMapTag` is 16 bytes without the 1st entry
+            core::mem::transmute::<[u8; 16], MemoryMapTag>([0u8; 16]);
+        }
+    }
+
     #[test]
     /// Compile time test for `EFIMemoryMapTag`.
     fn efi_memory_map_tag_size() {
         use super::EFIMemoryMapTag;
         unsafe {
-            // `EFIMemoryMapTag` is 16 bytes + `EFIMemoryDesc` is 40 bytes.
-            core::mem::transmute::<[u8; 56], EFIMemoryMapTag>([0u8; 56]);
+            // `EFIMemoryMapTag` is 16 bytes without the 1st entry
+            core::mem::transmute::<[u8; 16], EFIMemoryMapTag>([0u8; 16]);
         }
     }
 }

+ 11 - 6
multiboot2/src/memory_map.rs

@@ -18,7 +18,7 @@ pub struct MemoryMapTag {
     size: u32,
     entry_size: u32,
     entry_version: u32,
-    first_area: MemoryArea,
+    first_area: [MemoryArea; 0],
 }
 
 impl MemoryMapTag {
@@ -31,10 +31,13 @@ impl MemoryMapTag {
     /// Return an iterator over all marked memory areas.
     pub fn all_memory_areas(&self) -> impl Iterator<Item = &MemoryArea> {
         let self_ptr = self as *const MemoryMapTag;
-        let start_area = (&self.first_area) as *const MemoryArea;
+        let start_area = self.first_area.as_ptr();
+
         MemoryAreaIter {
             current_area: start_area as u64,
-            last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64),
+            // NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
+            last_area: (self_ptr as u64
+                + (self.size as u64 - core::mem::size_of::<MemoryMapTag>() as u64)),
             entry_size: self.entry_size,
             phantom: PhantomData,
         }
@@ -127,7 +130,7 @@ pub struct EFIMemoryMapTag {
     size: u32,
     desc_size: u32,
     desc_version: u32,
-    first_desc: EFIMemoryDesc,
+    first_desc: [EFIMemoryDesc; 0],
 }
 
 impl EFIMemoryMapTag {
@@ -137,10 +140,12 @@ impl EFIMemoryMapTag {
     /// available memory areas for tables and such.
     pub fn memory_areas(&self) -> EFIMemoryAreaIter {
         let self_ptr = self as *const EFIMemoryMapTag;
-        let start_area = (&self.first_desc) as *const EFIMemoryDesc;
+        let start_area = self.first_desc.as_ptr();
         EFIMemoryAreaIter {
             current_area: start_area as u64,
-            last_area: (self_ptr as u64 + self.size as u64),
+            // NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
+            last_area: (self_ptr as u64
+                + (self.size as u64 - core::mem::size_of::<EFIMemoryMapTag>() as u64)),
             entry_size: self.desc_size,
             phantom: PhantomData,
         }