|
1 | 1 | //! Global Allocator for UEFI.
|
2 | 2 | //! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc)
|
3 | 3 |
|
4 |
| -use crate::alloc::{GlobalAlloc, Layout, System}; |
| 4 | +use r_efi::protocols::loaded_image; |
5 | 5 |
|
6 |
| -const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA; |
| 6 | +use crate::alloc::{GlobalAlloc, Layout, System}; |
| 7 | +use crate::sync::OnceLock; |
| 8 | +use crate::sys::uefi::helpers; |
7 | 9 |
|
8 | 10 | #[stable(feature = "alloc_system_type", since = "1.28.0")]
|
9 | 11 | unsafe impl GlobalAlloc for System {
|
10 | 12 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
| 13 | + static EFI_MEMORY_TYPE: OnceLock<u32> = OnceLock::new(); |
| 14 | + |
11 | 15 | // Return null pointer if boot services are not available
|
12 | 16 | if crate::os::uefi::env::boot_services().is_none() {
|
13 | 17 | return crate::ptr::null_mut();
|
14 | 18 | }
|
15 | 19 |
|
16 | 20 | // If boot services is valid then SystemTable is not null.
|
17 | 21 | let system_table = crate::os::uefi::env::system_table().as_ptr().cast();
|
| 22 | + |
| 23 | + // Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this |
| 24 | + // will never fail. |
| 25 | + let mem_type = EFI_MEMORY_TYPE.get_or_init(|| { |
| 26 | + let protocol = helpers::image_handle_protocol::<loaded_image::Protocol>( |
| 27 | + loaded_image::PROTOCOL_GUID, |
| 28 | + ) |
| 29 | + .unwrap(); |
| 30 | + // Gives allocations the memory type that the data sections were loaded as. |
| 31 | + unsafe { (*protocol.as_ptr()).image_data_type } |
| 32 | + }); |
| 33 | + |
18 | 34 | // The caller must ensure non-0 layout
|
19 |
| - unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) } |
| 35 | + unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) } |
20 | 36 | }
|
21 | 37 |
|
22 | 38 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
0 commit comments