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
96pub ( 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" ) ]
1411unsafe 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}
0 commit comments