xref: /aosp_15_r20/bootable/libbootloader/gbl/libefi/src/allocation.rs (revision 5225e6b173e52d2efc6bcf950c27374fd72adabc)
1*5225e6b1SAndroid Build Coastguard Worker // Copyright 2023, The Android Open Source Project
2*5225e6b1SAndroid Build Coastguard Worker //
3*5225e6b1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*5225e6b1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*5225e6b1SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*5225e6b1SAndroid Build Coastguard Worker //
7*5225e6b1SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*5225e6b1SAndroid Build Coastguard Worker //
9*5225e6b1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*5225e6b1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*5225e6b1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5225e6b1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*5225e6b1SAndroid Build Coastguard Worker // limitations under the License.
14*5225e6b1SAndroid Build Coastguard Worker 
15*5225e6b1SAndroid Build Coastguard Worker use crate::{EfiEntry, RuntimeServices};
16*5225e6b1SAndroid Build Coastguard Worker use efi_types::EFI_MEMORY_TYPE_LOADER_DATA;
17*5225e6b1SAndroid Build Coastguard Worker 
18*5225e6b1SAndroid Build Coastguard Worker use core::mem::size_of_val;
19*5225e6b1SAndroid Build Coastguard Worker use core::ptr::null_mut;
20*5225e6b1SAndroid Build Coastguard Worker use core::{
21*5225e6b1SAndroid Build Coastguard Worker     alloc::{GlobalAlloc, Layout},
22*5225e6b1SAndroid Build Coastguard Worker     fmt::Write,
23*5225e6b1SAndroid Build Coastguard Worker };
24*5225e6b1SAndroid Build Coastguard Worker use liberror::{Error, Result};
25*5225e6b1SAndroid Build Coastguard Worker use safemath::SafeNum;
26*5225e6b1SAndroid Build Coastguard Worker 
27*5225e6b1SAndroid Build Coastguard Worker /// Implements a global allocator using `EFI_BOOT_SERVICES.AllocatePool()/FreePool()`
28*5225e6b1SAndroid Build Coastguard Worker ///
29*5225e6b1SAndroid Build Coastguard Worker /// To use, add this exact declaration to the application code:
30*5225e6b1SAndroid Build Coastguard Worker ///
31*5225e6b1SAndroid Build Coastguard Worker /// ```
32*5225e6b1SAndroid Build Coastguard Worker /// #[no_mangle]
33*5225e6b1SAndroid Build Coastguard Worker /// #[global_allocator]
34*5225e6b1SAndroid Build Coastguard Worker /// static mut EFI_GLOBAL_ALLOCATOR: EfiAllocator = EfiState::new();
35*5225e6b1SAndroid Build Coastguard Worker /// ```
36*5225e6b1SAndroid Build Coastguard Worker ///
37*5225e6b1SAndroid Build Coastguard Worker /// This is only useful for real UEFI applications; attempting to install the `EFI_GLOBAL_ALLOCATOR`
38*5225e6b1SAndroid Build Coastguard Worker /// for host-side unit tests will cause the test to panic immediately.
39*5225e6b1SAndroid Build Coastguard Worker pub struct EfiAllocator {
40*5225e6b1SAndroid Build Coastguard Worker     state: EfiState,
41*5225e6b1SAndroid Build Coastguard Worker     runtime_services: Option<RuntimeServices>,
42*5225e6b1SAndroid Build Coastguard Worker }
43*5225e6b1SAndroid Build Coastguard Worker 
44*5225e6b1SAndroid Build Coastguard Worker /// Represents the global EFI state.
45*5225e6b1SAndroid Build Coastguard Worker enum EfiState {
46*5225e6b1SAndroid Build Coastguard Worker     /// Initial state, no UEFI entry point has been set, global hooks will not work.
47*5225e6b1SAndroid Build Coastguard Worker     Uninitialized,
48*5225e6b1SAndroid Build Coastguard Worker     /// [EfiEntry] is registered, global hooks are active.
49*5225e6b1SAndroid Build Coastguard Worker     Initialized(EfiEntry),
50*5225e6b1SAndroid Build Coastguard Worker     /// ExitBootServices has been called, global hooks will not work.
51*5225e6b1SAndroid Build Coastguard Worker     Exited,
52*5225e6b1SAndroid Build Coastguard Worker }
53*5225e6b1SAndroid Build Coastguard Worker 
54*5225e6b1SAndroid Build Coastguard Worker impl EfiState {
55*5225e6b1SAndroid Build Coastguard Worker     /// Returns a reference to the EfiEntry.
efi_entry(&self) -> Option<&EfiEntry>56*5225e6b1SAndroid Build Coastguard Worker     fn efi_entry(&self) -> Option<&EfiEntry> {
57*5225e6b1SAndroid Build Coastguard Worker         match self {
58*5225e6b1SAndroid Build Coastguard Worker             EfiState::Initialized(ref entry) => Some(entry),
59*5225e6b1SAndroid Build Coastguard Worker             _ => None,
60*5225e6b1SAndroid Build Coastguard Worker         }
61*5225e6b1SAndroid Build Coastguard Worker     }
62*5225e6b1SAndroid Build Coastguard Worker }
63*5225e6b1SAndroid Build Coastguard Worker 
64*5225e6b1SAndroid Build Coastguard Worker // This is a bit ugly, but we only expect this library to be used by our EFI application so it
65*5225e6b1SAndroid Build Coastguard Worker // doesn't need to be super clean or scalable. The user has to declare the global variable
66*5225e6b1SAndroid Build Coastguard Worker // exactly as written in the [EfiAllocator] docs for this to link properly.
67*5225e6b1SAndroid Build Coastguard Worker extern "Rust" {
68*5225e6b1SAndroid Build Coastguard Worker     static mut EFI_GLOBAL_ALLOCATOR: EfiAllocator;
69*5225e6b1SAndroid Build Coastguard Worker }
70*5225e6b1SAndroid Build Coastguard Worker 
71*5225e6b1SAndroid Build Coastguard Worker /// An internal API to obtain library internal global EfiEntry and RuntimeServices.
internal_efi_entry_and_rt( ) -> (Option<&'static EfiEntry>, Option<&'static RuntimeServices>)72*5225e6b1SAndroid Build Coastguard Worker pub(crate) fn internal_efi_entry_and_rt(
73*5225e6b1SAndroid Build Coastguard Worker ) -> (Option<&'static EfiEntry>, Option<&'static RuntimeServices>) {
74*5225e6b1SAndroid Build Coastguard Worker     // SAFETY:
75*5225e6b1SAndroid Build Coastguard Worker     // EFI_GLOBAL_ALLOCATOR is only read by `internal_efi_entry_and_rt()` and modified by
76*5225e6b1SAndroid Build Coastguard Worker     // `init_efi_global_alloc()` and `exit_efi_global_alloc()`. The safety requirements of
77*5225e6b1SAndroid Build Coastguard Worker     // `init_efi_global_alloc()` and `exit_efi_global_alloc()` mandate that there can be no EFI
78*5225e6b1SAndroid Build Coastguard Worker     // event/notification/interrupt that can be triggered when they are called. This suggests that
79*5225e6b1SAndroid Build Coastguard Worker     // there cannot be concurrent read and modification on `EFI_GLOBAL_ALLOCATOR` possible. Thus its
80*5225e6b1SAndroid Build Coastguard Worker     // access is safe from race condition.
81*5225e6b1SAndroid Build Coastguard Worker     unsafe { EFI_GLOBAL_ALLOCATOR.get_efi_entry_and_rt() }
82*5225e6b1SAndroid Build Coastguard Worker }
83*5225e6b1SAndroid Build Coastguard Worker 
84*5225e6b1SAndroid Build Coastguard Worker /// Try to print via `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` in `EFI_SYSTEM_TABLE.ConOut`.
85*5225e6b1SAndroid Build Coastguard Worker ///
86*5225e6b1SAndroid Build Coastguard Worker /// Errors are ignored.
87*5225e6b1SAndroid Build Coastguard Worker #[macro_export]
88*5225e6b1SAndroid Build Coastguard Worker macro_rules! efi_try_print {
89*5225e6b1SAndroid Build Coastguard Worker     ($( $x:expr ),* $(,)? ) => {
90*5225e6b1SAndroid Build Coastguard Worker         {
91*5225e6b1SAndroid Build Coastguard Worker             let _ = (|| -> Result<()> {
92*5225e6b1SAndroid Build Coastguard Worker                 if let Some(entry) = crate::allocation::internal_efi_entry_and_rt().0 {
93*5225e6b1SAndroid Build Coastguard Worker                     write!(entry.system_table_checked()?.con_out()?, $($x,)*)?;
94*5225e6b1SAndroid Build Coastguard Worker                 }
95*5225e6b1SAndroid Build Coastguard Worker                 Ok(())
96*5225e6b1SAndroid Build Coastguard Worker             })();
97*5225e6b1SAndroid Build Coastguard Worker         }
98*5225e6b1SAndroid Build Coastguard Worker     };
99*5225e6b1SAndroid Build Coastguard Worker }
100*5225e6b1SAndroid Build Coastguard Worker 
101*5225e6b1SAndroid Build Coastguard Worker /// Initializes global allocator.
102*5225e6b1SAndroid Build Coastguard Worker ///
103*5225e6b1SAndroid Build Coastguard Worker /// # Safety
104*5225e6b1SAndroid Build Coastguard Worker ///
105*5225e6b1SAndroid Build Coastguard Worker /// This function modifies global variable `EFI_GLOBAL_ALLOCATOR`. It should only be called when
106*5225e6b1SAndroid Build Coastguard Worker /// there is no event/notification function that can be triggered or modify it. Otherwise there
107*5225e6b1SAndroid Build Coastguard Worker /// is a risk of race condition.
init_efi_global_alloc(efi_entry: EfiEntry) -> Result<()>108*5225e6b1SAndroid Build Coastguard Worker pub(crate) unsafe fn init_efi_global_alloc(efi_entry: EfiEntry) -> Result<()> {
109*5225e6b1SAndroid Build Coastguard Worker     // SAFETY: See SAFETY of `internal_efi_entry_and_rt()`
110*5225e6b1SAndroid Build Coastguard Worker     unsafe {
111*5225e6b1SAndroid Build Coastguard Worker         EFI_GLOBAL_ALLOCATOR.runtime_services =
112*5225e6b1SAndroid Build Coastguard Worker             efi_entry.system_table_checked().and_then(|v| v.runtime_services_checked()).ok();
113*5225e6b1SAndroid Build Coastguard Worker         match EFI_GLOBAL_ALLOCATOR.state {
114*5225e6b1SAndroid Build Coastguard Worker             EfiState::Uninitialized => {
115*5225e6b1SAndroid Build Coastguard Worker                 EFI_GLOBAL_ALLOCATOR.state = EfiState::Initialized(efi_entry);
116*5225e6b1SAndroid Build Coastguard Worker                 Ok(())
117*5225e6b1SAndroid Build Coastguard Worker             }
118*5225e6b1SAndroid Build Coastguard Worker             _ => Err(Error::AlreadyStarted),
119*5225e6b1SAndroid Build Coastguard Worker         }
120*5225e6b1SAndroid Build Coastguard Worker     }
121*5225e6b1SAndroid Build Coastguard Worker }
122*5225e6b1SAndroid Build Coastguard Worker 
123*5225e6b1SAndroid Build Coastguard Worker /// Internal API to invalidate global allocator after ExitBootService().
124*5225e6b1SAndroid Build Coastguard Worker ///
125*5225e6b1SAndroid Build Coastguard Worker /// # Safety
126*5225e6b1SAndroid Build Coastguard Worker ///
127*5225e6b1SAndroid Build Coastguard Worker /// This function modifies global variable `EFI_GLOBAL_ALLOCATOR`. It should only be called when
128*5225e6b1SAndroid Build Coastguard Worker /// there is no event/notification function that can be triggered or modify it. Otherwise there
129*5225e6b1SAndroid Build Coastguard Worker /// is a risk of race condition.
exit_efi_global_alloc()130*5225e6b1SAndroid Build Coastguard Worker pub(crate) unsafe fn exit_efi_global_alloc() {
131*5225e6b1SAndroid Build Coastguard Worker     // SAFETY: See SAFETY of `internal_efi_entry_and_rt()`
132*5225e6b1SAndroid Build Coastguard Worker     unsafe {
133*5225e6b1SAndroid Build Coastguard Worker         EFI_GLOBAL_ALLOCATOR.state = EfiState::Exited;
134*5225e6b1SAndroid Build Coastguard Worker     }
135*5225e6b1SAndroid Build Coastguard Worker }
136*5225e6b1SAndroid Build Coastguard Worker 
137*5225e6b1SAndroid Build Coastguard Worker impl EfiAllocator {
138*5225e6b1SAndroid Build Coastguard Worker     /// Creates a new instance.
new() -> Self139*5225e6b1SAndroid Build Coastguard Worker     pub const fn new() -> Self {
140*5225e6b1SAndroid Build Coastguard Worker         Self { state: EfiState::Uninitialized, runtime_services: None }
141*5225e6b1SAndroid Build Coastguard Worker     }
142*5225e6b1SAndroid Build Coastguard Worker 
143*5225e6b1SAndroid Build Coastguard Worker     /// Gets EfiEntry and RuntimeServices
get_efi_entry_and_rt(&self) -> (Option<&EfiEntry>, Option<&RuntimeServices>)144*5225e6b1SAndroid Build Coastguard Worker     fn get_efi_entry_and_rt(&self) -> (Option<&EfiEntry>, Option<&RuntimeServices>) {
145*5225e6b1SAndroid Build Coastguard Worker         (self.state.efi_entry(), self.runtime_services.as_ref())
146*5225e6b1SAndroid Build Coastguard Worker     }
147*5225e6b1SAndroid Build Coastguard Worker 
148*5225e6b1SAndroid Build Coastguard Worker     /// Allocate memory via EFI_BOOT_SERVICES.
allocate(&self, size: usize) -> *mut u8149*5225e6b1SAndroid Build Coastguard Worker     fn allocate(&self, size: usize) -> *mut u8 {
150*5225e6b1SAndroid Build Coastguard Worker         self.state
151*5225e6b1SAndroid Build Coastguard Worker             .efi_entry()
152*5225e6b1SAndroid Build Coastguard Worker             .ok_or(Error::InvalidState)
153*5225e6b1SAndroid Build Coastguard Worker             .and_then(|v| v.system_table_checked())
154*5225e6b1SAndroid Build Coastguard Worker             .and_then(|v| v.boot_services_checked())
155*5225e6b1SAndroid Build Coastguard Worker             .and_then(|v| v.allocate_pool(EFI_MEMORY_TYPE_LOADER_DATA, size))
156*5225e6b1SAndroid Build Coastguard Worker             .inspect_err(|e| efi_try_print!("failed to allocate: {e}"))
157*5225e6b1SAndroid Build Coastguard Worker             .unwrap_or(null_mut()) as _
158*5225e6b1SAndroid Build Coastguard Worker     }
159*5225e6b1SAndroid Build Coastguard Worker 
160*5225e6b1SAndroid Build Coastguard Worker     /// Deallocate memory previously allocated by `Self::allocate()`.
161*5225e6b1SAndroid Build Coastguard Worker     ///
162*5225e6b1SAndroid Build Coastguard Worker     /// Errors are logged but ignored.
deallocate(&self, ptr: *mut u8)163*5225e6b1SAndroid Build Coastguard Worker     fn deallocate(&self, ptr: *mut u8) {
164*5225e6b1SAndroid Build Coastguard Worker         match self.state.efi_entry() {
165*5225e6b1SAndroid Build Coastguard Worker             Some(ref entry) => {
166*5225e6b1SAndroid Build Coastguard Worker                 let _ = entry
167*5225e6b1SAndroid Build Coastguard Worker                     .system_table_checked()
168*5225e6b1SAndroid Build Coastguard Worker                     .and_then(|v| v.boot_services_checked())
169*5225e6b1SAndroid Build Coastguard Worker                     .and_then(|v| v.free_pool(ptr as *mut _))
170*5225e6b1SAndroid Build Coastguard Worker                     .inspect_err(|e| efi_try_print!("failed to deallocate: {e}"));
171*5225e6b1SAndroid Build Coastguard Worker             }
172*5225e6b1SAndroid Build Coastguard Worker             // After EFI_BOOT_SERVICES.ExitBootServices(), all allocated memory is considered
173*5225e6b1SAndroid Build Coastguard Worker             // leaked and under full ownership of subsequent OS loader code.
174*5225e6b1SAndroid Build Coastguard Worker             _ => {}
175*5225e6b1SAndroid Build Coastguard Worker         }
176*5225e6b1SAndroid Build Coastguard Worker     }
177*5225e6b1SAndroid Build Coastguard Worker }
178*5225e6b1SAndroid Build Coastguard Worker 
179*5225e6b1SAndroid Build Coastguard Worker // Alignment guaranteed by EFI AllocatePoll()
180*5225e6b1SAndroid Build Coastguard Worker const EFI_ALLOCATE_POOL_ALIGNMENT: usize = 8;
181*5225e6b1SAndroid Build Coastguard Worker 
182*5225e6b1SAndroid Build Coastguard Worker unsafe impl GlobalAlloc for EfiAllocator {
alloc(&self, layout: Layout) -> *mut u8183*5225e6b1SAndroid Build Coastguard Worker     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
184*5225e6b1SAndroid Build Coastguard Worker         (|| -> Result<*mut u8> {
185*5225e6b1SAndroid Build Coastguard Worker             let align = layout.align();
186*5225e6b1SAndroid Build Coastguard Worker 
187*5225e6b1SAndroid Build Coastguard Worker             // EFI AllocatePoll() must be at 8-bytes aligned so we can just use returned pointer.
188*5225e6b1SAndroid Build Coastguard Worker             if align <= EFI_ALLOCATE_POOL_ALIGNMENT {
189*5225e6b1SAndroid Build Coastguard Worker                 let ptr = self.allocate(layout.size());
190*5225e6b1SAndroid Build Coastguard Worker                 assert_eq!(ptr as usize % EFI_ALLOCATE_POOL_ALIGNMENT, 0);
191*5225e6b1SAndroid Build Coastguard Worker                 return Ok(ptr);
192*5225e6b1SAndroid Build Coastguard Worker             }
193*5225e6b1SAndroid Build Coastguard Worker 
194*5225e6b1SAndroid Build Coastguard Worker             // If requested alignment is > EFI_ALLOCATE_POOL_ALIGNMENT then make sure to allocate
195*5225e6b1SAndroid Build Coastguard Worker             // bigger buffer and adjust ptr to be aligned.
196*5225e6b1SAndroid Build Coastguard Worker             let mut offset: usize = 0usize;
197*5225e6b1SAndroid Build Coastguard Worker             let extra_size = SafeNum::from(align) + size_of_val(&offset);
198*5225e6b1SAndroid Build Coastguard Worker             let size = SafeNum::from(layout.size()) + extra_size;
199*5225e6b1SAndroid Build Coastguard Worker 
200*5225e6b1SAndroid Build Coastguard Worker             // TODO(300168989):
201*5225e6b1SAndroid Build Coastguard Worker             // `AllocatePool()` can be slow for allocating large buffers. In this case,
202*5225e6b1SAndroid Build Coastguard Worker             // `AllocatePages()` is recommended.
203*5225e6b1SAndroid Build Coastguard Worker             let unaligned_ptr = self.allocate(size.try_into()?);
204*5225e6b1SAndroid Build Coastguard Worker             if unaligned_ptr.is_null() {
205*5225e6b1SAndroid Build Coastguard Worker                 return Err(Error::Other(Some("Allocation failed")));
206*5225e6b1SAndroid Build Coastguard Worker             }
207*5225e6b1SAndroid Build Coastguard Worker             offset = align - (unaligned_ptr as usize % align);
208*5225e6b1SAndroid Build Coastguard Worker 
209*5225e6b1SAndroid Build Coastguard Worker             // SAFETY:
210*5225e6b1SAndroid Build Coastguard Worker             // - `unaligned_ptr` is guaranteed to point to buffer big enough to contain offset+size
211*5225e6b1SAndroid Build Coastguard Worker             // bytes since this is the size passed to `allocate`
212*5225e6b1SAndroid Build Coastguard Worker             // - ptr+layout.size() is also pointing to valid buffer since actual allocate size takes
213*5225e6b1SAndroid Build Coastguard Worker             // into account additional suffix for usize variable
214*5225e6b1SAndroid Build Coastguard Worker             unsafe {
215*5225e6b1SAndroid Build Coastguard Worker                 let ptr = unaligned_ptr.add(offset);
216*5225e6b1SAndroid Build Coastguard Worker                 core::slice::from_raw_parts_mut(ptr.add(layout.size()), size_of_val(&offset))
217*5225e6b1SAndroid Build Coastguard Worker                     .copy_from_slice(&offset.to_ne_bytes());
218*5225e6b1SAndroid Build Coastguard Worker                 Ok(ptr)
219*5225e6b1SAndroid Build Coastguard Worker             }
220*5225e6b1SAndroid Build Coastguard Worker         })()
221*5225e6b1SAndroid Build Coastguard Worker         .unwrap_or(null_mut()) as _
222*5225e6b1SAndroid Build Coastguard Worker     }
223*5225e6b1SAndroid Build Coastguard Worker 
dealloc(&self, ptr: *mut u8, layout: Layout)224*5225e6b1SAndroid Build Coastguard Worker     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
225*5225e6b1SAndroid Build Coastguard Worker         // If alignment is EFI_ALLOCATE_POOL_ALIGNMENT or less, then we can just used ptr directly
226*5225e6b1SAndroid Build Coastguard Worker         if layout.align() <= EFI_ALLOCATE_POOL_ALIGNMENT {
227*5225e6b1SAndroid Build Coastguard Worker             self.deallocate(ptr);
228*5225e6b1SAndroid Build Coastguard Worker             return;
229*5225e6b1SAndroid Build Coastguard Worker         }
230*5225e6b1SAndroid Build Coastguard Worker 
231*5225e6b1SAndroid Build Coastguard Worker         let mut offset: usize = 0usize;
232*5225e6b1SAndroid Build Coastguard Worker         offset = usize::from_ne_bytes(
233*5225e6b1SAndroid Build Coastguard Worker             // SAFETY:
234*5225e6b1SAndroid Build Coastguard Worker             // * `ptr` is allocated by `alloc` and has enough padding after `ptr`+size to hold
235*5225e6b1SAndroid Build Coastguard Worker             // suffix `offset: usize`.
236*5225e6b1SAndroid Build Coastguard Worker             // * Alignment of `ptr` is 1 for &[u8]
237*5225e6b1SAndroid Build Coastguard Worker             unsafe { core::slice::from_raw_parts(ptr.add(layout.size()), size_of_val(&offset)) }
238*5225e6b1SAndroid Build Coastguard Worker                 .try_into()
239*5225e6b1SAndroid Build Coastguard Worker                 .unwrap(),
240*5225e6b1SAndroid Build Coastguard Worker         );
241*5225e6b1SAndroid Build Coastguard Worker 
242*5225e6b1SAndroid Build Coastguard Worker         // SAFETY:
243*5225e6b1SAndroid Build Coastguard Worker         // (`ptr` - `offset`) must be valid unaligned pointer to buffer allocated by `alloc`
244*5225e6b1SAndroid Build Coastguard Worker         let real_start_ptr = unsafe { ptr.sub(offset) };
245*5225e6b1SAndroid Build Coastguard Worker         self.deallocate(real_start_ptr);
246*5225e6b1SAndroid Build Coastguard Worker     }
247*5225e6b1SAndroid Build Coastguard Worker }
248*5225e6b1SAndroid Build Coastguard Worker 
249*5225e6b1SAndroid Build Coastguard Worker /// API for allocating raw memory via EFI_BOOT_SERVICES
efi_malloc(size: usize) -> *mut u8250*5225e6b1SAndroid Build Coastguard Worker pub fn efi_malloc(size: usize) -> *mut u8 {
251*5225e6b1SAndroid Build Coastguard Worker     // SAFETY: See SAFETY of `internal_efi_entry()`.
252*5225e6b1SAndroid Build Coastguard Worker     unsafe { EFI_GLOBAL_ALLOCATOR.allocate(size) }
253*5225e6b1SAndroid Build Coastguard Worker }
254*5225e6b1SAndroid Build Coastguard Worker 
255*5225e6b1SAndroid Build Coastguard Worker /// API for deallocating raw memory previously allocated by `efi_malloc()`. Passing invalid
256*5225e6b1SAndroid Build Coastguard Worker /// pointer will cause the function to panic.
efi_free(ptr: *mut u8)257*5225e6b1SAndroid Build Coastguard Worker pub fn efi_free(ptr: *mut u8) {
258*5225e6b1SAndroid Build Coastguard Worker     // SAFETY: See SAFETY of `internal_efi_entry()`.
259*5225e6b1SAndroid Build Coastguard Worker     unsafe { EFI_GLOBAL_ALLOCATOR.deallocate(ptr) }
260*5225e6b1SAndroid Build Coastguard Worker }
261