Skip to content

Commit 64c26a4

Browse files
authored
Merge pull request #1255 from nicholasbishop/bishop-add-boot-mod
Add uefi::boot module
2 parents 8a6085a + f1c9f28 commit 64c26a4

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

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

+33
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
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 ptr =
22+
boot::allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, num_pages).unwrap();
23+
let addr = ptr.as_ptr() as usize;
24+
assert_eq!(addr % 4096, 0, "Page pointer is not page-aligned");
25+
26+
// Verify the page can be written to.
27+
{
28+
let ptr = ptr.as_ptr();
29+
unsafe { ptr.write_volatile(0xff) };
30+
unsafe { ptr.add(4095).write_volatile(0xff) };
31+
}
32+
33+
unsafe { boot::free_pages(ptr, num_pages) }.unwrap();
34+
}
35+
36+
fn test_allocate_pool_freestanding() {
37+
let ptr = boot::allocate_pool(MemoryType::LOADER_DATA, 10).unwrap();
38+
39+
// Verify the allocation can be written to.
40+
{
41+
let ptr = ptr.as_ptr();
42+
unsafe { ptr.write_volatile(0xff) };
43+
unsafe { ptr.add(9).write_volatile(0xff) };
44+
}
45+
unsafe { boot::free_pool(ptr) }.unwrap();
46+
}
47+
1548
fn allocate_pages(bt: &BootServices) {
1649
info!("Allocating some pages of memory");
1750

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

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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`.
25+
///
26+
/// # Errors
27+
///
28+
/// * [`Status::OUT_OF_RESOURCES`]: allocation failed.
29+
/// * [`Status::INVALID_PARAMETER`]: `mem_ty` is [`MemoryType::PERSISTENT_MEMORY`],
30+
/// [`MemoryType::UNACCEPTED`], or in the range [`MemoryType::MAX`]`..=0x6fff_ffff`.
31+
/// * [`Status::NOT_FOUND`]: the requested pages could not be found.
32+
pub fn allocate_pages(ty: AllocateType, mem_ty: MemoryType, count: usize) -> Result<NonNull<u8>> {
33+
let bt = boot_services_raw_panicking();
34+
let bt = unsafe { bt.as_ref() };
35+
36+
let (ty, mut addr) = match ty {
37+
AllocateType::AnyPages => (0, 0),
38+
AllocateType::MaxAddress(addr) => (1, addr),
39+
AllocateType::Address(addr) => (2, addr),
40+
};
41+
let addr =
42+
unsafe { (bt.allocate_pages)(ty, mem_ty, count, &mut addr) }.to_result_with_val(|| addr)?;
43+
let ptr = addr as *mut u8;
44+
Ok(NonNull::new(ptr).expect("allocate_pages must not return a null pointer if successful"))
45+
}
46+
47+
/// Frees memory pages allocated by [`allocate_pages`].
48+
///
49+
/// # Safety
50+
///
51+
/// The caller must ensure that no references into the allocation remain,
52+
/// and that the memory at the allocation is not used after it is freed.
53+
///
54+
/// # Errors
55+
///
56+
/// * [`Status::NOT_FOUND`]: `ptr` was not allocated by [`allocate_pages`].
57+
/// * [`Status::INVALID_PARAMETER`]: `ptr` is not page aligned or is otherwise invalid.
58+
pub unsafe fn free_pages(ptr: NonNull<u8>, count: usize) -> Result {
59+
let bt = boot_services_raw_panicking();
60+
let bt = unsafe { bt.as_ref() };
61+
62+
let addr = ptr.as_ptr() as PhysicalAddress;
63+
unsafe { (bt.free_pages)(addr, count) }.to_result()
64+
}
65+
66+
/// Allocates from a memory pool. The pointer will be 8-byte aligned.
67+
///
68+
/// # Errors
69+
///
70+
/// * [`Status::OUT_OF_RESOURCES`]: allocation failed.
71+
/// * [`Status::INVALID_PARAMETER`]: `mem_ty` is [`MemoryType::PERSISTENT_MEMORY`],
72+
/// [`MemoryType::UNACCEPTED`], or in the range [`MemoryType::MAX`]`..=0x6fff_ffff`.
73+
pub fn allocate_pool(mem_ty: MemoryType, size: usize) -> Result<NonNull<u8>> {
74+
let bt = boot_services_raw_panicking();
75+
let bt = unsafe { bt.as_ref() };
76+
77+
let mut buffer = ptr::null_mut();
78+
let ptr =
79+
unsafe { (bt.allocate_pool)(mem_ty, size, &mut buffer) }.to_result_with_val(|| buffer)?;
80+
81+
Ok(NonNull::new(ptr).expect("allocate_pool must not return a null pointer if successful"))
82+
}
83+
84+
/// Frees memory allocated by [`allocate_pool`].
85+
///
86+
/// # Safety
87+
///
88+
/// The caller must ensure that no references into the allocation remain,
89+
/// and that the memory at the allocation is not used after it is freed.
90+
///
91+
/// # Errors
92+
///
93+
/// * [`Status::INVALID_PARAMETER`]: `ptr` is invalid.
94+
pub unsafe fn free_pool(ptr: NonNull<u8>) -> Result {
95+
let bt = boot_services_raw_panicking();
96+
let bt = unsafe { bt.as_ref() };
97+
98+
unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result()
99+
}

uefi/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ extern crate uefi_raw;
104104
#[macro_use]
105105
pub mod data_types;
106106
pub mod allocator;
107+
pub mod boot;
107108
#[cfg(feature = "alloc")]
108109
pub mod fs;
109110
pub mod helpers;

0 commit comments

Comments
 (0)