Skip to content

Commit d986905

Browse files
Add uefi::boot module
The initial version contains allocate_pages/allocate_pool and the corresponding `free` functions.
1 parent 4fd9aed commit d986905

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

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

+29
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,46 @@
1+
use uefi::boot;
12
use uefi::table::boot::{AllocateType, BootServices, MemoryMap, MemoryMapMut, MemoryType};
23

34
use alloc::vec::Vec;
45

56
pub fn test(bt: &BootServices) {
67
info!("Testing memory functions");
78

9+
test_allocate_pages_freestanding();
10+
test_allocate_pool_freestanding();
11+
812
allocate_pages(bt);
913
vec_alloc();
1014
alloc_alignment();
1115

1216
memory_map(bt);
1317
}
1418

19+
fn test_allocate_pages_freestanding() {
20+
let num_pages = 1;
21+
let addr =
22+
boot::allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, num_pages).unwrap();
23+
assert_eq!(addr % 4096, 0, "Page pointer is not page-aligned");
24+
25+
// Verify the page can be written to.
26+
{
27+
let buf = unsafe { &mut *(addr as *mut [u8; 4096]) };
28+
*buf = [0xff; 4096];
29+
}
30+
31+
unsafe { boot::free_pages(addr, num_pages) }.unwrap();
32+
}
33+
34+
fn test_allocate_pool_freestanding() {
35+
let allocation = boot::allocate_pool(MemoryType::LOADER_DATA, 10).unwrap();
36+
// Verify the allocation can be written to.
37+
{
38+
let buf: &mut [u8; 10] = unsafe { &mut *allocation.as_ptr().cast() };
39+
*buf = [0xff; 10];
40+
}
41+
unsafe { boot::free_pool(allocation.as_ptr()) }.unwrap();
42+
}
43+
1544
fn allocate_pages(bt: &BootServices) {
1645
info!("Allocating some pages of memory");
1746

uefi/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## Added
44
- `uefi::system` is a new module that provides freestanding functions for
55
accessing fields of the global system table.
6+
- `uefi::boot` is a new module that provides freestanding functions for
7+
boot services using the global system table.
68
- `uefi::runtime` is a new module that provides freestanding functions for
79
runtime services using the global system table.
810
- Add standard derives for `ConfigTableEntry`.

uefi/src/boot.rs

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//! UEFI boot services.
2+
//!
3+
//! These functions will panic if called after exiting boot services.
4+
5+
use crate::data_types::PhysicalAddress;
6+
use core::ptr::{self, NonNull};
7+
use uefi::{table, Result, StatusExt};
8+
9+
#[cfg(doc)]
10+
use uefi::Status;
11+
12+
pub use uefi::table::boot::AllocateType;
13+
pub use uefi_raw::table::boot::MemoryType;
14+
15+
fn boot_services_raw_panicking() -> NonNull<uefi_raw::table::boot::BootServices> {
16+
let st = table::system_table_raw_panicking();
17+
// SAFETY: valid per requirements of `set_system_table`.
18+
let st = unsafe { st.as_ref() };
19+
NonNull::new(st.boot_services).expect("boot services are not active")
20+
}
21+
22+
/// Allocates memory pages from the system.
23+
///
24+
/// UEFI OS loaders should allocate memory of the type `LoaderData`. A `u64`
25+
/// is returned even on 32-bit platforms because some hardware configurations
26+
/// like Intel PAE enable 64-bit physical addressing on a 32-bit processor.
27+
///
28+
/// # Errors
29+
///
30+
/// * [`Status::OUT_OF_RESOURCES`]: allocation failed.
31+
/// * [`Status::INVALID_PARAMETER`]: `mem_ty` is [`MemoryType::PERSISTENT_MEMORY`],
32+
/// [`MemoryType::UNACCEPTED`], or in the range [`MemoryType::MAX`]`..=0x6fff_ffff`.
33+
/// * [`Status::NOT_FOUND`]: the requested pages could not be found.
34+
pub fn allocate_pages(
35+
ty: AllocateType,
36+
mem_ty: MemoryType,
37+
count: usize,
38+
) -> Result<PhysicalAddress> {
39+
let bt = boot_services_raw_panicking();
40+
let bt = unsafe { bt.as_ref() };
41+
42+
let (ty, mut addr) = match ty {
43+
AllocateType::AnyPages => (0, 0),
44+
AllocateType::MaxAddress(addr) => (1, addr),
45+
AllocateType::Address(addr) => (2, addr),
46+
};
47+
unsafe { (bt.allocate_pages)(ty, mem_ty, count, &mut addr) }.to_result_with_val(|| addr)
48+
}
49+
50+
/// Frees memory pages allocated by [`allocate_pages`].
51+
///
52+
/// # Safety
53+
///
54+
/// The caller must ensure that no references into the allocation remain,
55+
/// and that the memory at the allocation is not used after it is freed.
56+
///
57+
/// # Errors
58+
///
59+
/// * [`Status::NOT_FOUND`]: `addr` was not allocated by [`allocate_pages`].
60+
/// * [`Status::INVALID_PARAMETER`]: `addr` is not page aligned or is otherwise invalid.
61+
pub unsafe fn free_pages(addr: PhysicalAddress, count: usize) -> Result {
62+
let bt = boot_services_raw_panicking();
63+
let bt = unsafe { bt.as_ref() };
64+
65+
unsafe { (bt.free_pages)(addr, count) }.to_result()
66+
}
67+
68+
/// Allocates from a memory pool. The pointer will be 8-byte aligned.
69+
///
70+
/// # Errors
71+
///
72+
/// * [`Status::OUT_OF_RESOURCES`]: allocation failed.
73+
/// * [`Status::INVALID_PARAMETER`]: `mem_ty` is [`MemoryType::PERSISTENT_MEMORY`],
74+
/// [`MemoryType::UNACCEPTED`], or in the range [`MemoryType::MAX`]`..=0x6fff_ffff`.
75+
pub fn allocate_pool(mem_ty: MemoryType, size: usize) -> Result<NonNull<u8>> {
76+
let bt = boot_services_raw_panicking();
77+
let bt = unsafe { bt.as_ref() };
78+
79+
let mut buffer = ptr::null_mut();
80+
let ptr =
81+
unsafe { (bt.allocate_pool)(mem_ty, size, &mut buffer) }.to_result_with_val(|| buffer)?;
82+
83+
Ok(NonNull::new(ptr).expect("allocate_pool must not return a null pointer if successful"))
84+
}
85+
86+
/// Frees memory allocated by [`allocate_pool`].
87+
///
88+
/// # Safety
89+
///
90+
/// The caller must ensure that no references into the allocation remain,
91+
/// and that the memory at the allocation is not used after it is freed.
92+
///
93+
/// # Errors
94+
///
95+
/// * [`Status::INVALID_PARAMETER`]: `addr` is invalid.
96+
pub unsafe fn free_pool(addr: *mut u8) -> Result {
97+
let bt = boot_services_raw_panicking();
98+
let bt = unsafe { bt.as_ref() };
99+
100+
unsafe { (bt.free_pool)(addr) }.to_result()
101+
}

uefi/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ pub use uguid::guid;
119119
mod result;
120120
pub use result::{Error, Result, ResultExt, Status, StatusExt};
121121

122+
pub mod boot;
122123
pub mod runtime;
123124
pub mod system;
124125
pub mod table;

0 commit comments

Comments
 (0)