Skip to content

Commit 86727ee

Browse files
authored
Merge pull request #1312 from nicholasbishop/bishop-free-memmap
boot: Add freestanding memory_map
2 parents 374dad9 + cbbc348 commit 86727ee

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

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

+22-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use alloc::vec::Vec;
22
use uefi::boot;
3-
use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryType};
3+
use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryMapOwned, MemoryType};
44
use uefi::table::boot::{AllocateType, BootServices};
55

66
pub fn test(bt: &BootServices) {
@@ -14,6 +14,7 @@ pub fn test(bt: &BootServices) {
1414
alloc_alignment();
1515

1616
memory_map(bt);
17+
memory_map_freestanding();
1718
}
1819

1920
fn test_allocate_pages_freestanding() {
@@ -93,13 +94,7 @@ fn alloc_alignment() {
9394
assert_eq!(value.as_ptr() as usize % 0x100, 0, "Wrong alignment");
9495
}
9596

96-
fn memory_map(bt: &BootServices) {
97-
info!("Testing memory map functions");
98-
99-
let mut memory_map = bt
100-
.memory_map(MemoryType::LOADER_DATA)
101-
.expect("Failed to retrieve UEFI memory map");
102-
97+
fn check_memory_map(mut memory_map: MemoryMapOwned) {
10398
memory_map.sort();
10499

105100
// Collect the descriptors into a vector
@@ -130,3 +125,22 @@ fn memory_map(bt: &BootServices) {
130125
let page_count = first_desc.page_count;
131126
assert!(page_count != 0, "Memory map entry has size zero");
132127
}
128+
129+
fn memory_map(bt: &BootServices) {
130+
info!("Testing memory map functions");
131+
132+
let memory_map = bt
133+
.memory_map(MemoryType::LOADER_DATA)
134+
.expect("Failed to retrieve UEFI memory map");
135+
136+
check_memory_map(memory_map);
137+
}
138+
139+
fn memory_map_freestanding() {
140+
info!("Testing memory map functions (freestanding)");
141+
142+
let memory_map =
143+
boot::memory_map(MemoryType::LOADER_DATA).expect("Failed to retrieve UEFI memory map");
144+
145+
check_memory_map(memory_map);
146+
}

uefi/src/boot.rs

+59-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! These functions will panic if called after exiting boot services.
44
55
use crate::data_types::PhysicalAddress;
6+
use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned};
67
use crate::proto::device_path::DevicePath;
78
use crate::proto::{Protocol, ProtocolPointer};
89
use crate::util::opt_nonnull_to_ptr;
@@ -24,7 +25,7 @@ pub use uefi::table::boot::{
2425
AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams,
2526
SearchType, TimerTrigger,
2627
};
27-
pub use uefi_raw::table::boot::{EventType, MemoryType, Tpl};
28+
pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl};
2829

2930
/// Global image handle. This is only set by [`set_image_handle`], and it is
3031
/// only read by [`image_handle`].
@@ -165,6 +166,63 @@ pub unsafe fn free_pool(ptr: NonNull<u8>) -> Result {
165166
unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result()
166167
}
167168

169+
/// Stores the current UEFI memory map in an UEFI-heap allocated buffer
170+
/// and returns a [`MemoryMapOwned`].
171+
///
172+
/// # Parameters
173+
///
174+
/// - `mt`: The memory type for the backing memory on the UEFI heap.
175+
/// Usually, this is [`MemoryType::LOADER_DATA`]. You can also use a
176+
/// custom type.
177+
///
178+
/// # Errors
179+
///
180+
/// * [`Status::BUFFER_TOO_SMALL`]
181+
/// * [`Status::INVALID_PARAMETER`]
182+
pub fn memory_map(mt: MemoryType) -> Result<MemoryMapOwned> {
183+
let mut buffer = MemoryMapBackingMemory::new(mt)?;
184+
185+
let meta = get_memory_map(buffer.as_mut_slice())?;
186+
187+
Ok(MemoryMapOwned::from_initialized_mem(buffer, meta))
188+
}
189+
190+
/// Calls the underlying `GetMemoryMap` function of UEFI. On success,
191+
/// the buffer is mutated and contains the map. The map might be shorter
192+
/// than the buffer, which is reflected by the return value.
193+
pub(crate) fn get_memory_map(buf: &mut [u8]) -> Result<MemoryMapMeta> {
194+
let bt = boot_services_raw_panicking();
195+
let bt = unsafe { bt.as_ref() };
196+
197+
let mut map_size = buf.len();
198+
let map_buffer = buf.as_mut_ptr().cast::<MemoryDescriptor>();
199+
let mut map_key = MemoryMapKey(0);
200+
let mut desc_size = 0;
201+
let mut desc_version = 0;
202+
203+
assert_eq!(
204+
(map_buffer as usize) % mem::align_of::<MemoryDescriptor>(),
205+
0,
206+
"Memory map buffers must be aligned like a MemoryDescriptor"
207+
);
208+
209+
unsafe {
210+
(bt.get_memory_map)(
211+
&mut map_size,
212+
map_buffer,
213+
&mut map_key.0,
214+
&mut desc_size,
215+
&mut desc_version,
216+
)
217+
}
218+
.to_result_with_val(|| MemoryMapMeta {
219+
map_size,
220+
desc_size,
221+
map_key,
222+
desc_version,
223+
})
224+
}
225+
168226
/// Creates an event.
169227
///
170228
/// This function creates a new event of the specified type and returns it.

0 commit comments

Comments
 (0)