diff --git a/uefi-raw/src/table/boot.rs b/uefi-raw/src/table/boot.rs index 5e325d189..f0d3bbf02 100644 --- a/uefi-raw/src/table/boot.rs +++ b/uefi-raw/src/table/boot.rs @@ -326,12 +326,30 @@ bitflags! { } } -/// A structure describing a region of memory. +/// A structure describing a region of memory. This type corresponds to [version] +/// of this struct in the UEFI spec and is always bound to a corresponding +/// UEFI memory map. +/// +/// # UEFI pitfalls +/// As of May 2024: +/// The memory descriptor struct might be extended in the future by a new UEFI +/// spec revision, which will be reflected in another `version` of that +/// descriptor. The version is reported when using `get_memory_map` of +/// [`BootServices`]. +/// +/// Also note that you **must never** work with `size_of::` +/// but always with `desc_size`, which is reported when using `get_memory_map` +/// as well [[0]]. For example, although the actual size is of version 1 +/// descriptors is `40`, the reported `desc_size` is `48`. +/// +/// [version]: MemoryDescriptor::VERSION +/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct MemoryDescriptor { /// Type of memory occupying this range. pub ty: MemoryType, + // Implicit 32-bit padding. /// Starting physical address. pub phys_start: PhysicalAddress, /// Starting virtual address. diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 8cc34e1fd..6d9b74289 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1617,21 +1617,35 @@ pub struct MemoryMapSize { /// An accessory to the memory map that can be either iterated or /// indexed like an array. /// -/// A [`MemoryMap`] is always associated with the -/// unique [`MemoryMapKey`] contained in the struct. +/// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`] +/// contained in the struct. /// /// To iterate over the entries, call [`MemoryMap::entries`]. To get a sorted /// map, you manually have to call [`MemoryMap::sort`] first. +/// +/// ## UEFI pitfalls +/// **Please note that when working with memory maps, the `entry_size` is +/// usually larger than `size_of:: { key: MemoryMapKey, buf: &'buf mut [u8], + /// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if + /// this field is ever extended by a new UEFI standard. entry_size: usize, len: usize, } impl<'buf> MemoryMap<'buf> { /// Creates a [`MemoryMap`] from the given buffer and entry size. + /// The entry size is usually bound to the size of a [`MemoryDescriptor`] + /// but can indicate if this field is ever extended by a new UEFI standard. /// /// This allows parsing a memory map provided by a kernel after boot /// services have already exited. @@ -1722,8 +1736,14 @@ impl<'buf> MemoryMap<'buf> { elem.phys_start } - /// Returns an iterator over the contained memory map. To get a sorted map, - /// call [`MemoryMap::sort`] first. + /// Returns an [`MemoryMapIter`] emitting [`MemoryDescriptor`]s. + /// + /// To get a sorted map, call [`MemoryMap::sort`] first. + /// + /// # UEFI pitfalls + /// Currently, only the descriptor version specified in + /// [`MemoryDescriptor`] is supported. This is going to change if the UEFI + /// spec ever introduces a new memory descriptor version. #[must_use] pub fn entries(&self) -> MemoryMapIter { MemoryMapIter {