Skip to content

Commit a2b5544

Browse files
committed
uefi: introduce traits MemoryMap and MemoryMapMut
1 parent 69bea25 commit a2b5544

File tree

1 file changed

+90
-1
lines changed

1 file changed

+90
-1
lines changed

uefi/src/table/boot.rs

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
1111
use core::cell::UnsafeCell;
1212
use core::ffi::c_void;
1313
use core::mem::{self, MaybeUninit};
14-
use core::ops::{Deref, DerefMut};
14+
use core::ops::{Deref, DerefMut, Index, IndexMut};
1515
use core::ptr::NonNull;
1616
use core::sync::atomic::{AtomicPtr, Ordering};
1717
use core::{ptr, slice};
@@ -1804,6 +1804,95 @@ impl MemoryMapMeta {
18041804
}
18051805
}
18061806

1807+
/// An accessory to the UEFI memory map that can be either iterated or indexed
1808+
/// like an array.
1809+
///
1810+
/// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`]
1811+
/// bundled with the ma.
1812+
///
1813+
/// To iterate over the entries, call [`MemoryMap::entries`].
1814+
///
1815+
/// ## UEFI pitfalls
1816+
/// **Please note** that when working with memory maps, the `entry_size` is
1817+
/// usually larger than `size_of::<MemoryDescriptor` [[0]]. So to be safe,
1818+
/// always use `entry_size` as step-size when interfacing with the memory map on
1819+
/// a low level.
1820+
///
1821+
/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
1822+
pub trait MemoryMap: Index<usize, Output = MemoryDescriptor> {
1823+
// TODO also require IntoIterator?! :)
1824+
1825+
/// Returns the associated [`MemoryMapMeta`].
1826+
#[must_use]
1827+
fn meta(&self) -> MemoryMapMeta;
1828+
1829+
/// Returns the associated [`MemoryMapKey`].
1830+
#[must_use]
1831+
fn key(&self) -> MemoryMapKey;
1832+
1833+
/// Returns the number of keys in the map.
1834+
#[must_use]
1835+
fn len(&self) -> usize;
1836+
1837+
/// Returns a reference to the [`MemoryDescriptor`] at the given index, if
1838+
/// present.
1839+
#[must_use]
1840+
fn get(&self, index: usize) -> Option<&MemoryDescriptor> {
1841+
if index >= self.len() {
1842+
None
1843+
} else {
1844+
let offset = index * self.meta().desc_size;
1845+
unsafe {
1846+
self.buffer()
1847+
.as_ptr()
1848+
.add(offset)
1849+
.cast::<MemoryDescriptor>()
1850+
.as_ref()
1851+
}
1852+
}
1853+
}
1854+
1855+
/// Returns a reference to the underlying memory.
1856+
fn buffer(&self) -> &[u8];
1857+
1858+
/// Returns an Iterator of type [`MemoryMapIter`].
1859+
fn entries(&self) -> MemoryMapIter<'_>;
1860+
}
1861+
1862+
/// Extension to [`MemoryMap`] that adds mutable operations. This also includes
1863+
/// the ability to sort the memory map.
1864+
pub trait MemoryMapMut: MemoryMap + IndexMut<usize> {
1865+
/// Returns a mutable reference to the [`MemoryDescriptor`] at the given
1866+
/// index, if present.
1867+
#[must_use]
1868+
fn get_mut(&mut self, index: usize) -> Option<&mut MemoryDescriptor> {
1869+
if index >= self.len() {
1870+
None
1871+
} else {
1872+
let offset = index * self.meta().desc_size;
1873+
unsafe {
1874+
self.buffer_mut()
1875+
.as_mut_ptr()
1876+
.add(offset)
1877+
.cast::<MemoryDescriptor>()
1878+
.as_mut()
1879+
}
1880+
}
1881+
}
1882+
1883+
/// Sorts the memory map by physical address in place. This operation is
1884+
/// optional and should be invoked only once.
1885+
#[must_use]
1886+
fn sort(&mut self);
1887+
1888+
/// Returns a reference to the underlying memory.
1889+
///
1890+
/// # Safety
1891+
///
1892+
/// This is unsafe as there is a potential to create invalid entries.
1893+
unsafe fn buffer_mut(&self) -> &mut [u8];
1894+
}
1895+
18071896
/// An accessory to the memory map that can be either iterated or
18081897
/// indexed like an array.
18091898
///

0 commit comments

Comments
 (0)