Skip to content

Commit d48d07d

Browse files
committed
Use r-efi-alloc for allocator
Switch to using r-efi-alloc for allocation. This is useful since a lot of UEFI projects will probably end up using this allocator anyway to have custom allocation types or to simply not use std. Signed-off-by: Ayush Singh <[email protected]>
1 parent 000228b commit d48d07d

File tree

4 files changed

+29
-80
lines changed

4 files changed

+29
-80
lines changed

Cargo.lock

+12
Original file line numberDiff line numberDiff line change
@@ -2953,6 +2953,17 @@ dependencies = [
29532953
"rustc-std-workspace-core",
29542954
]
29552955

2956+
[[package]]
2957+
name = "r-efi-alloc"
2958+
version = "1.0.0"
2959+
source = "registry+https://github.com/rust-lang/crates.io-index"
2960+
checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7"
2961+
dependencies = [
2962+
"compiler_builtins",
2963+
"r-efi",
2964+
"rustc-std-workspace-core",
2965+
]
2966+
29562967
[[package]]
29572968
name = "rand"
29582969
version = "0.7.3"
@@ -4909,6 +4920,7 @@ dependencies = [
49094920
"panic_unwind",
49104921
"profiler_builtins",
49114922
"r-efi",
4923+
"r-efi-alloc",
49124924
"rand 0.7.3",
49134925
"rustc-demangle",
49144926
"std_detect",

library/std/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features =
4949

5050
[target.'cfg(target_os = "uefi")'.dependencies]
5151
r-efi = { version = "4.1.0", features = ['rustc-dep-of-std', 'efiapi']}
52+
r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std']}
5253

5354
[features]
5455
backtrace = [

library/std/src/sys/uefi/alloc.rs

+15-80
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
//! Global Allocator for UEFI.
2-
//! Uses `EFI_BOOT_SERVICES.AllocatePool()` and `EFI_BOOT_SERVICES.FreePool()`.
3-
//! Takes a lot of inspiration from Windows allocator for Alignment > 8.
2+
//! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc)
43
5-
use crate::alloc::{GlobalAlloc, Layout, System};
6-
use crate::ptr;
7-
use crate::sys::uefi::common;
4+
use crate::alloc::{handle_alloc_error, GlobalAlloc, Layout, System};
85

96
pub(crate) const POOL_ALIGNMENT: usize = 8;
107

@@ -13,87 +10,25 @@ const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA;
1310
#[stable(feature = "alloc_system_type", since = "1.28.0")]
1411
unsafe impl GlobalAlloc for System {
1512
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
16-
let align = layout.align();
17-
let size = layout.size();
18-
19-
// Return NULL pointer if boot_services pointer cannot be obtained. The only time this
20-
// should happen is if SystemTable has not been initialized
21-
let boot_services = match common::try_boot_services() {
22-
Some(x) => x,
23-
None => return ptr::null_mut(),
13+
let system_table = match crate::os::uefi::env::try_system_table() {
14+
None => return crate::ptr::null_mut(),
15+
Some(x) => x.as_ptr() as *mut _,
2416
};
2517

26-
let allocate_pool_ptr = unsafe { (*boot_services.as_ptr()).allocate_pool };
27-
28-
let mut ptr: *mut crate::ffi::c_void = ptr::null_mut();
29-
let aligned_size = align_size(size, align);
30-
31-
let r = (allocate_pool_ptr)(MEMORY_TYPE, aligned_size, &mut ptr);
32-
33-
if r.is_error() || ptr.is_null() {
34-
return ptr::null_mut();
18+
if layout.size() > 0 {
19+
unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) }
20+
} else {
21+
layout.dangling().as_ptr()
3522
}
36-
37-
unsafe { align_ptr(ptr.cast(), align) }
3823
}
3924

4025
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
41-
let boot_services = match common::try_boot_services() {
42-
Some(x) => x,
43-
None => return,
26+
let system_table = match crate::os::uefi::env::try_system_table() {
27+
None => handle_alloc_error(layout),
28+
Some(x) => x.as_ptr() as *mut _,
4429
};
45-
46-
let free_pool_ptr = unsafe { (*boot_services.as_ptr()).free_pool };
47-
48-
let ptr = unsafe { unalign_ptr(ptr, layout.align()) };
49-
let r = (free_pool_ptr)(ptr.cast());
50-
51-
assert!(!r.is_error());
52-
}
53-
}
54-
55-
#[inline]
56-
fn align_size(size: usize, align: usize) -> usize {
57-
if align > POOL_ALIGNMENT {
58-
// Allocate extra padding in order to be able to satisfy the alignment.
59-
size + align
60-
} else {
61-
size
62-
}
63-
}
64-
65-
#[repr(C)]
66-
struct Header(*mut u8);
67-
68-
#[inline]
69-
unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
70-
if align > POOL_ALIGNMENT {
71-
let offset = ptr.align_offset(align);
72-
73-
// SAFETY: `MIN_ALIGN` <= `offset` <= `layout.align()` and the size of the allocated
74-
// block is `layout.align() + layout.size()`. `aligned` will thus be a correctly aligned
75-
// pointer inside the allocated block with at least `layout.size()` bytes after it and at
76-
// least `MIN_ALIGN` bytes of padding before it.
77-
let aligned = unsafe { ptr.add(offset) };
78-
79-
// SAFETY: Because the size and alignment of a header is <= `MIN_ALIGN` and `aligned`
80-
// is aligned to at least `MIN_ALIGN` and has at least `MIN_ALIGN` bytes of padding before
81-
// it, it is safe to write a header directly before it.
82-
unsafe { crate::ptr::write((aligned as *mut Header).offset(-1), Header(ptr)) };
83-
84-
aligned
85-
} else {
86-
ptr
87-
}
88-
}
89-
90-
#[inline]
91-
unsafe fn unalign_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
92-
if align > POOL_ALIGNMENT {
93-
// SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null
94-
// and have a header readable directly before it.
95-
unsafe { crate::ptr::read((ptr as *mut Header).offset(-1)).0 }
96-
} else {
97-
ptr
30+
if layout.size() > 0 {
31+
unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) }
32+
}
9833
}
9934
}

src/tools/tidy/src/deps.rs

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
273273
"zerovec",
274274
"zerovec-derive",
275275
"r-efi",
276+
"r-efi-alloc",
276277
];
277278

278279
const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[

0 commit comments

Comments
 (0)