Skip to content

Commit 1c7b8f1

Browse files
committed
uefi: mem: add public constructors for MemoryMapRef and MemoryMapRefMut
There is no public constructor for MemoryMapOwned, as the construction of it is quite complicated and therefore hidden behind BootServices::memory_map() respectively SystemTable::exit_boot_services. The real-world use case for the public constructors for the other types is when parsing the UEFI memory map from kernels after a bootloader, such as GRUB or Limine, passed the UEFI memory map via the corresponding boot information. This also streamlines the documentation.
1 parent fff01fd commit 1c7b8f1

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

uefi/src/mem/memory_map/api.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ pub trait MemoryMap: Debug + Index<usize, Output = MemoryDescriptor> {
3131
#[must_use]
3232
fn meta(&self) -> MemoryMapMeta;
3333

34-
/// Returns the associated [`MemoryMapKey`].
34+
/// Returns the associated [`MemoryMapKey`]. Note that this doesn't
35+
/// necessarily is the key of the latest valid UEFI memory map.
3536
#[must_use]
3637
fn key(&self) -> MemoryMapKey;
3738

@@ -67,6 +68,13 @@ pub trait MemoryMap: Debug + Index<usize, Output = MemoryDescriptor> {
6768
fn buffer(&self) -> &[u8];
6869

6970
/// Returns an Iterator of type [`MemoryMapIter`].
71+
///
72+
/// # Safety
73+
///
74+
/// The underlying memory might contain an invalid/malformed memory map
75+
/// which can't be checked during construction of this type. The iterator
76+
/// might yield unexpected results.
77+
#[must_use]
7078
fn entries(&self) -> MemoryMapIter<'_>;
7179
}
7280

uefi/src/mem/memory_map/impl_.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,62 @@
33
44
use super::*;
55
use crate::table::system_table_boot;
6+
use core::fmt::{Debug, Display, Formatter};
67
use core::ops::{Index, IndexMut};
78
use core::ptr::NonNull;
89
use core::{mem, ptr};
910
use uefi_raw::PhysicalAddress;
1011

12+
/// Errors that may happen when constructing a [`MemoryMapRef`] or
13+
/// [`MemoryMapRefMut`].
14+
#[derive(Copy, Clone, Debug)]
15+
pub enum MemoryMapError {
16+
/// The buffer is not 8-byte aligned.
17+
Misaligned,
18+
/// The memory map size is either null or otherwise invalid.
19+
InvalidSize,
20+
}
21+
22+
impl Display for MemoryMapError {
23+
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
24+
Debug::fmt(self, f)
25+
}
26+
}
27+
28+
#[cfg(feature = "unstable")]
29+
impl core::error::Error for MemoryMapError {}
30+
1131
/// Implementation of [`MemoryMap`] for the given buffer.
1232
#[derive(Debug)]
13-
#[allow(dead_code)] // TODO: github.com/rust-osdev/uefi-rs/issues/1247
1433
pub struct MemoryMapRef<'a> {
1534
buf: &'a [u8],
1635
meta: MemoryMapMeta,
1736
len: usize,
1837
}
1938

39+
impl<'a> MemoryMapRef<'a> {
40+
/// Constructs a new [`MemoryMapRef`].
41+
///
42+
/// # Safety
43+
///
44+
/// The underlying memory might contain an invalid/malformed memory map
45+
/// which can't be checked during construction of this type. The entry
46+
/// iterator might yield unexpected results.
47+
pub fn new(buffer: &'a [u8], meta: MemoryMapMeta) -> Result<Self, MemoryMapError> {
48+
if buffer.as_ptr().align_offset(8) != 0 {
49+
return Err(MemoryMapError::Misaligned);
50+
}
51+
if buffer.is_empty() || buffer.len() < meta.map_size {
52+
return Err(MemoryMapError::InvalidSize);
53+
}
54+
Ok(Self {
55+
buf: buffer,
56+
meta,
57+
len: meta.entry_count(),
58+
})
59+
}
60+
}
61+
2062
impl<'a> MemoryMap for MemoryMapRef<'a> {
2163
fn meta(&self) -> MemoryMapMeta {
2264
self.meta
@@ -58,6 +100,29 @@ pub struct MemoryMapRefMut<'a> {
58100
len: usize,
59101
}
60102

103+
impl<'a> MemoryMapRefMut<'a> {
104+
/// Constructs a new [`MemoryMapRefMut`].
105+
///
106+
/// # Safety
107+
///
108+
/// The underlying memory might contain an invalid/malformed memory map
109+
/// which can't be checked during construction of this type. The entry
110+
/// iterator might yield unexpected results.
111+
pub fn new(buffer: &'a mut [u8], meta: MemoryMapMeta) -> Result<Self, MemoryMapError> {
112+
if buffer.as_ptr().align_offset(8) != 0 {
113+
return Err(MemoryMapError::Misaligned);
114+
}
115+
if buffer.is_empty() || buffer.len() < meta.map_size {
116+
return Err(MemoryMapError::InvalidSize);
117+
}
118+
Ok(Self {
119+
buf: buffer,
120+
meta,
121+
len: meta.entry_count(),
122+
})
123+
}
124+
}
125+
61126
impl<'a> MemoryMap for MemoryMapRefMut<'a> {
62127
fn meta(&self) -> MemoryMapMeta {
63128
self.meta

uefi/src/mem/memory_map/iter.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
use super::*;
22

3-
/// An iterator of [`MemoryDescriptor`]. The underlying memory map is always
4-
/// associated with a unique [`MemoryMapKey`].
3+
/// An iterator for [`MemoryMap`].
4+
///
5+
/// # Safety
6+
///
7+
/// The underlying memory might contain an invalid/malformed memory map
8+
/// which can't be checked during construction of this type. The iterator
9+
/// might yield unexpected results.
510
#[derive(Debug, Clone)]
611
pub struct MemoryMapIter<'a> {
712
pub(crate) memory_map: &'a dyn MemoryMap,

uefi/src/mem/memory_map/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ impl Align for MemoryDescriptor {
5050
}
5151
}
5252

53-
/// A unique identifier of a memory map.
53+
/// A unique identifier of a memory map, necessary to tell proof UEFI that one
54+
/// has the latest valid UEFI memory map when exiting boot services.
5455
///
55-
/// If the memory map changes, this value is no longer valid.
56-
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
56+
/// If the memory map changes, due to any allocation or deallocation, this value
57+
/// is no longer valid.
58+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
5759
#[repr(C)]
58-
// TODO add some convenience?!
5960
pub struct MemoryMapKey(pub(crate) usize);
6061

6162
/// A structure containing the meta attributes associated with a call to

0 commit comments

Comments
 (0)