13
13
14
14
use core:: alloc:: { GlobalAlloc , Layout } ;
15
15
use core:: ffi:: c_void;
16
- use core:: ptr;
16
+ use core:: ptr:: { self , NonNull } ;
17
17
use core:: sync:: atomic:: { AtomicPtr , AtomicU32 , Ordering } ;
18
18
19
+ use crate :: boot;
19
20
use crate :: mem:: memory_map:: MemoryType ;
20
21
use crate :: proto:: loaded_image:: LoadedImage ;
21
- use crate :: table:: boot:: BootServices ;
22
22
use crate :: table:: { Boot , SystemTable } ;
23
23
24
24
/// Reference to the system table, used to call the boot services pool memory
@@ -42,20 +42,12 @@ pub unsafe fn init(system_table: &mut SystemTable<Boot>) {
42
42
43
43
let boot_services = system_table. boot_services ( ) ;
44
44
if let Ok ( loaded_image) =
45
- boot_services . open_protocol_exclusive :: < LoadedImage > ( boot_services. image_handle ( ) )
45
+ boot :: open_protocol_exclusive :: < LoadedImage > ( boot_services. image_handle ( ) )
46
46
{
47
47
MEMORY_TYPE . store ( loaded_image. data_type ( ) . 0 , Ordering :: Release ) ;
48
48
}
49
49
}
50
50
51
- /// Access the boot services
52
- fn boot_services ( ) -> * const BootServices {
53
- let ptr = SYSTEM_TABLE . load ( Ordering :: Acquire ) ;
54
- let system_table =
55
- unsafe { SystemTable :: from_ptr ( ptr) } . expect ( "The system table handle is not available" ) ;
56
- system_table. boot_services ( )
57
- }
58
-
59
51
/// Notify the allocator library that boot services are not safe to call anymore
60
52
///
61
53
/// You must arrange for this function to be called on exit from UEFI boot services
@@ -70,27 +62,24 @@ pub fn exit_boot_services() {
70
62
pub struct Allocator ;
71
63
72
64
unsafe impl GlobalAlloc for Allocator {
73
- /// Allocate memory using [`BootServices ::allocate_pool`]. The allocation is
65
+ /// Allocate memory using [`boot ::allocate_pool`]. The allocation is
74
66
/// of type [`MemoryType::LOADER_DATA`] for UEFI applications, [`MemoryType::BOOT_SERVICES_DATA`]
75
67
/// for UEFI boot drivers and [`MemoryType::RUNTIME_SERVICES_DATA`] for UEFI runtime drivers.
76
68
unsafe fn alloc ( & self , layout : Layout ) -> * mut u8 {
77
69
let size = layout. size ( ) ;
78
70
let align = layout. align ( ) ;
79
71
let memory_type = MemoryType ( MEMORY_TYPE . load ( Ordering :: Acquire ) ) ;
80
72
81
- let boot_services = & * boot_services ( ) ;
82
-
83
73
if align > 8 {
84
74
// The requested alignment is greater than 8, but `allocate_pool` is
85
75
// only guaranteed to provide eight-byte alignment. Allocate extra
86
76
// space so that we can return an appropriately-aligned pointer
87
77
// within the allocation.
88
- let full_alloc_ptr =
89
- if let Ok ( ptr) = boot_services. allocate_pool ( memory_type, size + align) {
90
- ptr. as_ptr ( )
91
- } else {
92
- return ptr:: null_mut ( ) ;
93
- } ;
78
+ let full_alloc_ptr = if let Ok ( ptr) = boot:: allocate_pool ( memory_type, size + align) {
79
+ ptr. as_ptr ( )
80
+ } else {
81
+ return ptr:: null_mut ( ) ;
82
+ } ;
94
83
95
84
// Calculate the offset needed to get an aligned pointer within the
96
85
// full allocation. If that offset is zero, increase it to `align`
@@ -115,20 +104,24 @@ unsafe impl GlobalAlloc for Allocator {
115
104
// The requested alignment is less than or equal to eight, and
116
105
// `allocate_pool` always provides eight-byte alignment, so we can
117
106
// use `allocate_pool` directly.
118
- boot_services
119
- . allocate_pool ( memory_type, size)
107
+ boot:: allocate_pool ( memory_type, size)
120
108
. map ( |ptr| ptr. as_ptr ( ) )
121
109
. unwrap_or ( ptr:: null_mut ( ) )
122
110
}
123
111
}
124
112
125
- /// Deallocate memory using [`BootServices ::free_pool`].
113
+ /// Deallocate memory using [`boot ::free_pool`].
126
114
unsafe fn dealloc ( & self , mut ptr : * mut u8 , layout : Layout ) {
127
115
if layout. align ( ) > 8 {
128
116
// Retrieve the pointer to the full allocation that was packed right
129
117
// before the aligned allocation in `alloc`.
130
118
ptr = ( ptr as * const * mut u8 ) . sub ( 1 ) . read ( ) ;
131
119
}
132
- ( * boot_services ( ) ) . free_pool ( ptr) . unwrap ( ) ;
120
+
121
+ // OK to unwrap: `ptr` is required to be a valid allocation by the trait API.
122
+ let ptr = NonNull :: new ( ptr) . unwrap ( ) ;
123
+
124
+ // Warning: this will panic after exiting boot services.
125
+ boot:: free_pool ( ptr) . unwrap ( ) ;
133
126
}
134
127
}
0 commit comments