1
1
//! 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)
4
3
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 } ;
8
5
9
6
pub ( crate ) const POOL_ALIGNMENT : usize = 8 ;
10
7
@@ -13,87 +10,25 @@ const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA;
13
10
#[ stable( feature = "alloc_system_type" , since = "1.28.0" ) ]
14
11
unsafe impl GlobalAlloc for System {
15
12
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 _ ,
24
16
} ;
25
17
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 ( )
35
22
}
36
-
37
- unsafe { align_ptr ( ptr. cast ( ) , align) }
38
23
}
39
24
40
25
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 _ ,
44
29
} ;
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
+ }
98
33
}
99
34
}
0 commit comments