Skip to content

Commit 95a41df

Browse files
committed
uefi: allocate_pool() now returns NonNull<[u8]>
This aligns the signature with the Rust allocator API.
1 parent 8b9d83a commit 95a41df

File tree

6 files changed

+60
-20
lines changed

6 files changed

+60
-20
lines changed

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

+7-5
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,17 @@ fn test_allocate_pages() {
4343
}
4444

4545
fn test_allocate_pool() {
46-
let ptr = boot::allocate_pool(MemoryType::LOADER_DATA, 10).unwrap();
46+
let mut ptr = boot::allocate_pool(MemoryType::LOADER_DATA, 10).unwrap();
47+
let buffer = unsafe { ptr.as_mut() };
4748

4849
// Verify the allocation can be written to.
4950
{
50-
let ptr = ptr.as_ptr();
51-
unsafe { ptr.write_volatile(0xff) };
52-
unsafe { ptr.add(9).write_volatile(0xff) };
51+
buffer[0] = 0xff;
52+
buffer[9] = 0xff;
53+
assert_eq!(buffer[0], 0xff);
54+
assert_eq!(buffer[9], 0xff);
5355
}
54-
unsafe { boot::free_pool(ptr) }.unwrap();
56+
unsafe { boot::free_pool(ptr.cast()) }.unwrap();
5557
}
5658

5759
// Simple test to ensure our custom allocator works with the `alloc` crate.

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,14 @@ fn test_install_configuration_table() {
222222
let initial_table_count = system::with_config_table(|t| t.len());
223223

224224
// Create the entry data.
225-
let config: NonNull<u8> = boot::allocate_pool(MemoryType::RUNTIME_SERVICES_DATA, 1).unwrap();
226-
unsafe { config.write(123u8) };
225+
let mut config_ptr = boot::allocate_pool(MemoryType::RUNTIME_SERVICES_DATA, 1).unwrap();
226+
let buffer = unsafe { config_ptr.as_mut() };
227+
buffer[0] = 123;
227228

228229
// Install the table.
229230
const TABLE_GUID: Guid = guid!("4bec53c4-5fc1-48a1-ab12-df214907d29f");
230231
unsafe {
231-
boot::install_configuration_table(&TABLE_GUID, config.as_ptr().cast()).unwrap();
232+
boot::install_configuration_table(&TABLE_GUID, config_ptr.as_ptr().cast()).unwrap();
232233
}
233234

234235
// Verify the installation.
@@ -244,6 +245,6 @@ fn test_install_configuration_table() {
244245
// Uninstall the table and free the memory.
245246
unsafe {
246247
boot::install_configuration_table(&TABLE_GUID, ptr::null()).unwrap();
247-
boot::free_pool(config).unwrap();
248+
boot::free_pool(config_ptr.cast()).unwrap();
248249
}
249250
}

uefi/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
- **Breaking**: `allocate_pages` now returns `NonNull<[u8]>` to align it with
2828
the Rust allocator API. There is an example in the documentation of that
2929
function.
30+
- **Breaking**: `allocate_pool` now returns `NonNull<[u8]>` to align it with
31+
the Rust allocator API. There is an example in the documentation of that
32+
function.
3033
- `boot::memory_map()` will never return `Status::BUFFER_TOO_SMALL` from now on,
3134
as this is considered a hard internal error where users can't do anything
3235
about it anyway. It will panic instead.

uefi/src/allocator.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,12 @@ unsafe impl GlobalAlloc for Allocator {
6868
// only guaranteed to provide eight-byte alignment. Allocate extra
6969
// space so that we can return an appropriately-aligned pointer
7070
// within the allocation.
71-
let full_alloc_ptr = if let Ok(ptr) = boot::allocate_pool(memory_type, size + align) {
72-
ptr.as_ptr()
73-
} else {
74-
return ptr::null_mut();
71+
let full_alloc_ptr = match boot::allocate_pool(memory_type, size + align) {
72+
Ok(ptr) => ptr.cast::<u8>().as_ptr(),
73+
Err(e) => {
74+
log::error!("Failed to allocate pool: {:?}", e);
75+
return ptr::null_mut();
76+
}
7577
};
7678

7779
// Calculate the offset needed to get an aligned pointer within the
@@ -100,7 +102,8 @@ unsafe impl GlobalAlloc for Allocator {
100102
// `allocate_pool` always provides eight-byte alignment, so we can
101103
// use `allocate_pool` directly.
102104
boot::allocate_pool(memory_type, size)
103-
.map(|ptr| ptr.as_ptr())
105+
.map(|mut ptr: NonNull<[u8]>| unsafe { ptr.as_mut() })
106+
.map(|ptr: &mut [u8]| ptr.as_mut_ptr())
104107
.unwrap_or(ptr::null_mut())
105108
}
106109
}

uefi/src/boot.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -218,22 +218,53 @@ pub unsafe fn free_pages(ptr: NonNull<u8>, count: usize) -> Result {
218218
unsafe { (bt.free_pages)(addr, count) }.to_result()
219219
}
220220

221-
/// Allocates from a memory pool. The pointer will be 8-byte aligned.
221+
/// Allocates a consecutive region of bytes using the UEFI allocator. The buffer
222+
/// will be 8-byte aligned.
223+
///
224+
/// The caller is responsible to free the memory using [`free_pool`].
225+
///
226+
/// # Arguments
227+
/// - `memory_type`: The [`MemoryType`] used to persist the allocation in the
228+
/// UEFI memory map. Typically, UEFI OS loaders should allocate memory of
229+
/// type [`MemoryType::LOADER_DATA`].
230+
///- `size`: Amount of bytes to allocate.
231+
///
232+
/// # Example
233+
///```rust,no_run
234+
/// use uefi::boot::{self, AllocateType};
235+
/// use uefi_raw::table::boot::MemoryType;
236+
///
237+
/// let mut ptr = boot::allocate_pool(
238+
/// MemoryType::LOADER_DATA,
239+
/// 42
240+
/// ).unwrap();
241+
///
242+
/// let buffer: &mut [u8] = unsafe { ptr.as_mut() };
243+
/// // now do something with your buffer
244+
///
245+
/// // free the allocation
246+
/// unsafe { boot::free_pool(ptr.cast()) }.unwrap();
247+
/// ```
222248
///
223249
/// # Errors
224250
///
225251
/// * [`Status::OUT_OF_RESOURCES`]: allocation failed.
226252
/// * [`Status::INVALID_PARAMETER`]: `mem_ty` is [`MemoryType::PERSISTENT_MEMORY`],
227253
/// [`MemoryType::UNACCEPTED`], or in the range [`MemoryType::MAX`]`..=0x6fff_ffff`.
228-
pub fn allocate_pool(mem_ty: MemoryType, size: usize) -> Result<NonNull<u8>> {
254+
pub fn allocate_pool(memory_type: MemoryType, size: usize) -> Result<NonNull<[u8]>> {
229255
let bt = boot_services_raw_panicking();
230256
let bt = unsafe { bt.as_ref() };
231257

232258
let mut buffer = ptr::null_mut();
233-
let ptr =
234-
unsafe { (bt.allocate_pool)(mem_ty, size, &mut buffer) }.to_result_with_val(|| buffer)?;
259+
let ptr = unsafe { (bt.allocate_pool)(memory_type, size, &mut buffer) }
260+
.to_result_with_val(|| buffer)?;
235261

236-
Ok(NonNull::new(ptr).expect("allocate_pool must not return a null pointer if successful"))
262+
if let Some(ptr) = NonNull::new(ptr) {
263+
let slice = NonNull::slice_from_raw_parts(ptr, size);
264+
Ok(slice)
265+
} else {
266+
Err(Status::OUT_OF_RESOURCES.into())
267+
}
237268
}
238269

239270
/// Frees memory allocated by [`allocate_pool`].

uefi/src/mem/memory_map/impl_.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl MemoryMapBackingMemory {
281281
pub(crate) fn new(memory_type: MemoryType) -> crate::Result<Self> {
282282
let memory_map_meta = boot::memory_map_size();
283283
let len = Self::safe_allocation_size_hint(memory_map_meta);
284-
let ptr = boot::allocate_pool(memory_type, len)?.as_ptr();
284+
let ptr = boot::allocate_pool(memory_type, len)?.cast::<u8>().as_ptr();
285285

286286
// Should be fine as UEFI always has allocations with a guaranteed
287287
// alignment of 8 bytes.

0 commit comments

Comments
 (0)