Skip to content

Commit 479868f

Browse files
Merge pull request #1240 from phip1611/mem-follow-up
cleanup/follow-up: memory_map
2 parents 50fc455 + d2498dc commit 479868f

File tree

17 files changed

+945
-885
lines changed

17 files changed

+945
-885
lines changed

uefi-test-runner/src/boot/memory.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use uefi::boot;
2-
use uefi::table::boot::{AllocateType, BootServices, MemoryMap, MemoryMapMut, MemoryType};
3-
41
use alloc::vec::Vec;
2+
use uefi::boot;
3+
use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryType};
4+
use uefi::table::boot::{AllocateType, BootServices};
55

66
pub fn test(bt: &BootServices) {
77
info!("Testing memory functions");

uefi-test-runner/src/boot/misc.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use core::ffi::c_void;
22
use core::ptr::{self, NonNull};
33

44
use core::mem;
5+
use uefi::mem::memory_map::MemoryType;
56
use uefi::proto::unsafe_protocol;
67
use uefi::table::boot::{
7-
BootServices, EventType, MemoryType, OpenProtocolAttributes, OpenProtocolParams, SearchType,
8-
TimerTrigger, Tpl,
8+
BootServices, EventType, OpenProtocolAttributes, OpenProtocolParams, SearchType, TimerTrigger,
9+
Tpl,
910
};
1011
use uefi::table::{Boot, SystemTable};
1112
use uefi::{guid, Event, Guid, Identify};

uefi-test-runner/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ extern crate alloc;
88

99
use alloc::string::ToString;
1010
use alloc::vec::Vec;
11+
use uefi::mem::memory_map::{MemoryMap, MemoryType};
1112
use uefi::prelude::*;
1213
use uefi::proto::console::serial::Serial;
1314
use uefi::proto::device_path::build::{self, DevicePathBuilder};
1415
use uefi::proto::device_path::messaging::Vendor;
15-
use uefi::table::boot::{MemoryMap, MemoryType};
1616
use uefi::{print, println, system, Result};
1717

1818
mod boot;

uefi/CHANGELOG.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,16 @@
2424
- **Breaking:** `PcrEvent::new_in_buffer` and `PcrEventInputs::new_in_buffer`
2525
now take an initialized buffer (`[u8`] instead of `[MaybeUninit<u8>]`), and if
2626
the buffer is too small the required size is returned in the error data.
27-
27+
- **Breaking** Exports of Memory Map-related types from `uefi::table::boot` are
28+
now removed. Use `uefi::mem::memory_map` instead. The patch you have to apply
29+
to the `use` statements of your code might look as follows:
30+
```diff
31+
1c1,2
32+
< use uefi::table::boot::{BootServices, MemoryMap, MemoryMapMut, MemoryType};
33+
---
34+
> use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryType};
35+
> use uefi::table::boot::BootServices;
36+
```
2837

2938
# uefi - 0.29.0 (2024-07-02)
3039

uefi/src/allocator.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ use core::ffi::c_void;
1616
use core::ptr;
1717
use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
1818

19+
use crate::mem::memory_map::MemoryType;
1920
use crate::proto::loaded_image::LoadedImage;
20-
use crate::table::boot::{BootServices, MemoryType};
21+
use crate::table::boot::BootServices;
2122
use crate::table::{Boot, SystemTable};
2223

2324
/// Reference to the system table, used to call the boot services pool memory

uefi/src/mem/memory_map/api.rs

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//! Module for the traits [`MemoryMap`] and [`MemoryMapMut`].
2+
3+
use super::*;
4+
use core::fmt::Debug;
5+
use core::ops::{Index, IndexMut};
6+
7+
/// An accessory to the UEFI memory map and associated metadata that can be
8+
/// either iterated or indexed like an array.
9+
///
10+
/// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`]
11+
/// bundled with the map.
12+
///
13+
/// To iterate over the entries, call [`MemoryMap::entries`].
14+
///
15+
/// ## UEFI pitfalls
16+
/// Note that a MemoryMap can quickly become outdated, as soon as any explicit
17+
/// or hidden allocation happens.
18+
///
19+
/// As soon as boot services are excited, all previous obtained memory maps must
20+
/// be considered as outdated, except if the [`MemoryMapKey`] equals the one
21+
/// returned by `exit_boot_services()`.
22+
///
23+
/// **Please note** that when working with memory maps, the `entry_size` is
24+
/// usually larger than `size_of::<MemoryDescriptor` [[0]]. So to be safe,
25+
/// always use `entry_size` as step-size when interfacing with the memory map on
26+
/// a low level.
27+
///
28+
/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059
29+
pub trait MemoryMap: Debug + Index<usize, Output = MemoryDescriptor> {
30+
/// Returns the associated [`MemoryMapMeta`].
31+
#[must_use]
32+
fn meta(&self) -> MemoryMapMeta;
33+
34+
/// Returns the associated [`MemoryMapKey`].
35+
#[must_use]
36+
fn key(&self) -> MemoryMapKey;
37+
38+
/// Returns the number of keys in the map.
39+
#[must_use]
40+
fn len(&self) -> usize;
41+
42+
/// Returns if the memory map is empty.
43+
#[must_use]
44+
fn is_empty(&self) -> bool {
45+
self.len() == 0
46+
}
47+
48+
/// Returns a reference to the [`MemoryDescriptor`] at the given index, if
49+
/// present.
50+
#[must_use]
51+
fn get(&self, index: usize) -> Option<&MemoryDescriptor> {
52+
if index >= self.len() {
53+
None
54+
} else {
55+
let offset = index * self.meta().desc_size;
56+
unsafe {
57+
self.buffer()
58+
.as_ptr()
59+
.add(offset)
60+
.cast::<MemoryDescriptor>()
61+
.as_ref()
62+
}
63+
}
64+
}
65+
66+
/// Returns a reference to the underlying memory.
67+
fn buffer(&self) -> &[u8];
68+
69+
/// Returns an Iterator of type [`MemoryMapIter`].
70+
fn entries(&self) -> MemoryMapIter<'_>;
71+
}
72+
73+
/// Extension to [`MemoryMap`] that adds mutable operations. This also includes
74+
/// the ability to sort the memory map.
75+
pub trait MemoryMapMut: MemoryMap + IndexMut<usize> {
76+
/// Returns a mutable reference to the [`MemoryDescriptor`] at the given
77+
/// index, if present.
78+
#[must_use]
79+
fn get_mut(&mut self, index: usize) -> Option<&mut MemoryDescriptor> {
80+
if index >= self.len() {
81+
None
82+
} else {
83+
let offset = index * self.meta().desc_size;
84+
unsafe {
85+
self.buffer_mut()
86+
.as_mut_ptr()
87+
.add(offset)
88+
.cast::<MemoryDescriptor>()
89+
.as_mut()
90+
}
91+
}
92+
}
93+
94+
/// Sorts the memory map by physical address in place. This operation is
95+
/// optional and should be invoked only once.
96+
fn sort(&mut self);
97+
98+
/// Returns a reference to the underlying memory.
99+
///
100+
/// # Safety
101+
///
102+
/// This is unsafe as there is a potential to create invalid entries.
103+
unsafe fn buffer_mut(&mut self) -> &mut [u8];
104+
}

0 commit comments

Comments
 (0)