Skip to content

Commit e6803d7

Browse files
medhefgonicholasbishop
authored andcommitted
allocator: Use appropriate memory types
Boot/runtime driveres generally only want to allocate with their respective memory types. Using the wrong allocation types or mixing them can result in hard to debug issues (when loading linux).
1 parent 9dbdfe9 commit e6803d7

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
- Added `FileAttribute::is_directory(&self)` and
2929
`FileAttribute::is_regular_file(&self)`
3030
- Added `LoadedImage::code_type()` and `LoadedImage::data_type()`
31+
- `Allocator` will now use the memory type of the running UEFI binary:
32+
- `MemoryType::LOADER_DATA` for UEFI applications
33+
- `MemoryType::BOOT_SERVICES_DATA` for UEFI boot drivers
34+
- `MemoryType::RUNTIME_SERVICES_DATA` for UEFI runtime drivers
3135

3236
### Changed
3337

uefi/src/allocator.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use core::alloc::{GlobalAlloc, Layout};
1515
use core::ptr::{self, NonNull};
1616

17+
use crate::proto::loaded_image::LoadedImage;
1718
use crate::table::boot::{BootServices, MemoryType};
1819

1920
/// Reference to the boot services table, used to call the pool memory allocation functions.
@@ -22,6 +23,10 @@ use crate::table::boot::{BootServices, MemoryType};
2223
/// exited by the host application yet.
2324
static mut BOOT_SERVICES: Option<NonNull<BootServices>> = None;
2425

26+
/// The memory type used for pool memory allocations.
27+
/// TODO: Use OnceCell when stablilized.
28+
static mut MEMORY_TYPE: MemoryType = MemoryType::LOADER_DATA;
29+
2530
/// Initializes the allocator.
2631
///
2732
/// # Safety
@@ -30,6 +35,12 @@ static mut BOOT_SERVICES: Option<NonNull<BootServices>> = None;
3035
/// will be called when UEFI boot services will be exited.
3136
pub unsafe fn init(boot_services: &BootServices) {
3237
BOOT_SERVICES = NonNull::new(boot_services as *const _ as *mut _);
38+
39+
if let Ok(loaded_image) =
40+
boot_services.open_protocol_exclusive::<LoadedImage>(boot_services.image_handle())
41+
{
42+
MEMORY_TYPE = loaded_image.data_type()
43+
}
3344
}
3445

3546
/// Access the boot services
@@ -54,9 +65,9 @@ pub struct Allocator;
5465

5566
unsafe impl GlobalAlloc for Allocator {
5667
/// Allocate memory using [`BootServices::allocate_pool`]. The allocation is
57-
/// of type [`MemoryType::LOADER_DATA`].
68+
/// of type [`MemoryType::LOADER_DATA`] for UEFI applications, [`MemoryType::BOOT_SERVICES_DATA`]
69+
/// for UEFI boot drivers and [`MemoryType::RUNTIME_SERVICES_DATA`] for UEFI runtime drivers.
5870
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
59-
let mem_ty = MemoryType::LOADER_DATA;
6071
let size = layout.size();
6172
let align = layout.align();
6273

@@ -65,12 +76,14 @@ unsafe impl GlobalAlloc for Allocator {
6576
// only guaranteed to provide eight-byte alignment. Allocate extra
6677
// space so that we can return an appropriately-aligned pointer
6778
// within the allocation.
68-
let full_alloc_ptr =
69-
if let Ok(ptr) = boot_services().as_ref().allocate_pool(mem_ty, size + align) {
70-
ptr
71-
} else {
72-
return ptr::null_mut();
73-
};
79+
let full_alloc_ptr = if let Ok(ptr) = boot_services()
80+
.as_ref()
81+
.allocate_pool(MEMORY_TYPE, size + align)
82+
{
83+
ptr
84+
} else {
85+
return ptr::null_mut();
86+
};
7487

7588
// Calculate the offset needed to get an aligned pointer within the
7689
// full allocation. If that offset is zero, increase it to `align`
@@ -97,7 +110,7 @@ unsafe impl GlobalAlloc for Allocator {
97110
// use `allocate_pool` directly.
98111
boot_services()
99112
.as_ref()
100-
.allocate_pool(mem_ty, size)
113+
.allocate_pool(MEMORY_TYPE, size)
101114
.unwrap_or(ptr::null_mut())
102115
}
103116
}

0 commit comments

Comments
 (0)