Skip to content

Commit 8012fa9

Browse files
committed
multiboot2: fix handling of efi memory map construction
1 parent b71f855 commit 8012fa9

File tree

2 files changed

+72
-11
lines changed

2 files changed

+72
-11
lines changed

multiboot2/Changelog.md

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
## 0.20.1
44

55
- fixed the handling of `EFIMemoryMapTag` and `EFIMemoryAreaIter`
6+
- **BREAKING** Fixed wrong creation of `EFIMemoryMapTag`.
7+
`EFIMemoryMapTag::new` was replaced by `EFIMemoryMapTag::new_from_descs` and
8+
`EFIMemoryMapTag::new_from_map`.
69

710
## 0.20.0 (2024-05-01)
811

multiboot2/src/memory_map.rs

+69-11
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ const EFI_METADATA_SIZE: usize = mem::size_of::<TagTypeId>() + 3 * mem::size_of:
281281
#[cfg(feature = "builder")]
282282
impl AsBytes for EFIMemoryDesc {}
283283

284-
/// EFI memory map tag. The [`EFIMemoryDesc`] follows the EFI specification.
284+
/// EFI memory map tag. The embedded [`EFIMemoryDesc`]s follows the EFI
285+
/// specification.
285286
#[derive(ptr_meta::Pointee, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
286287
#[repr(C)]
287288
pub struct EFIMemoryMapTag {
@@ -308,18 +309,40 @@ impl EFIMemoryMapTag {
308309
/// Create a new EFI memory map tag with the given memory descriptors.
309310
/// Version and size can't be set because you're passing a slice of
310311
/// EFIMemoryDescs, not the ones you might have gotten from the firmware.
311-
pub fn new(descs: &[EFIMemoryDesc]) -> BoxedDst<Self> {
312-
// update this when updating EFIMemoryDesc
313-
const MEMORY_DESCRIPTOR_VERSION: u32 = 1;
314-
let mut bytes = [
315-
(mem::size_of::<EFIMemoryDesc>() as u32).to_le_bytes(),
316-
MEMORY_DESCRIPTOR_VERSION.to_le_bytes(),
317-
]
318-
.concat();
312+
pub fn new_from_descs(descs: &[EFIMemoryDesc]) -> BoxedDst<Self> {
313+
let size_base = mem::size_of::<EFIMemoryDesc>();
314+
// Taken from https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
315+
let desc_size_diff = mem::size_of::<u64>() - size_base % mem::size_of::<u64>();
316+
let desc_size = size_base + desc_size_diff;
317+
318+
assert!(desc_size >= size_base);
319+
320+
let mut efi_mmap = alloc::vec::Vec::with_capacity(descs.len() * desc_size);
319321
for desc in descs {
320-
bytes.extend(desc.as_bytes());
322+
efi_mmap.extend(desc.as_bytes());
323+
// fill with zeroes
324+
efi_mmap.extend([0].repeat(desc_size_diff));
321325
}
322-
BoxedDst::new(bytes.as_slice())
326+
327+
Self::new_from_map(
328+
desc_size as u32,
329+
EFIMemoryDesc::VERSION,
330+
efi_mmap.as_slice(),
331+
)
332+
}
333+
334+
#[cfg(feature = "builder")]
335+
/// Create a new EFI memory map tag from the given EFI memory map.
336+
pub fn new_from_map(desc_size: u32, desc_version: u32, efi_mmap: &[u8]) -> BoxedDst<Self> {
337+
assert!(desc_size > 0);
338+
assert_eq!(efi_mmap.len() % desc_size as usize, 0);
339+
let bytes = [
340+
&desc_size.to_le_bytes(),
341+
&desc_version.to_le_bytes(),
342+
efi_mmap,
343+
]
344+
.concat();
345+
BoxedDst::new(&bytes)
323346
}
324347

325348
/// Returns an iterator over the provided memory areas.
@@ -401,3 +424,38 @@ impl<'a> ExactSizeIterator for EFIMemoryAreaIter<'a> {
401424
self.entries
402425
}
403426
}
427+
428+
#[cfg(test)]
429+
mod tests {
430+
use super::*;
431+
432+
#[test]
433+
fn construction_and_parsing() {
434+
let descs = [
435+
EFIMemoryDesc {
436+
ty: EFIMemoryAreaType::CONVENTIONAL,
437+
phys_start: 0x1000,
438+
virt_start: 0x1000,
439+
page_count: 1,
440+
att: Default::default(),
441+
},
442+
EFIMemoryDesc {
443+
ty: EFIMemoryAreaType::LOADER_DATA,
444+
phys_start: 0x2000,
445+
virt_start: 0x2000,
446+
page_count: 3,
447+
att: Default::default(),
448+
},
449+
];
450+
let efi_mmap_tag = EFIMemoryMapTag::new_from_descs(&descs);
451+
452+
assert_eq!(efi_mmap_tag.desc_size, 48 /* 40 + 8 */);
453+
454+
let mut iter = efi_mmap_tag.memory_areas();
455+
456+
assert_eq!(iter.next(), Some(&descs[0]));
457+
assert_eq!(iter.next(), Some(&descs[1]));
458+
459+
assert_eq!(iter.next(), None);
460+
}
461+
}

0 commit comments

Comments
 (0)