@@ -40,6 +40,41 @@ fn get_memory_type() -> MemoryType {
4040 }
4141}
4242
43+ /// Helper to get a custom alignment out of an allocation with an alignment of
44+ /// eight (UEFI default alignment). This works by allocating extra space and
45+ /// storing a pointer to the actual allocation right above the allocation
46+ /// handed out via the public API.
47+ fn alloc_pool_aligned ( memory_type : MemoryType , size : usize , align : usize ) -> * mut u8 {
48+ let full_alloc_ptr = boot:: allocate_pool ( memory_type, size + align) ;
49+ let full_alloc_ptr = if let Ok ( ptr) = full_alloc_ptr {
50+ ptr. as_ptr ( )
51+ } else {
52+ return ptr:: null_mut ( ) ;
53+ } ;
54+
55+ // Calculate the offset needed to get an aligned pointer within the
56+ // full allocation. If that offset is zero, increase it to `align`
57+ // so that we still have space to store the extra pointer described
58+ // below.
59+ let mut offset = full_alloc_ptr. align_offset ( align) ;
60+ if offset == 0 {
61+ offset = align;
62+ }
63+
64+ // Before returning the aligned allocation, store a pointer to the
65+ // full unaligned allocation in the bytes just before the aligned
66+ // allocation. We know we have at least eight bytes there due to
67+ // adding `align` to the memory allocation size. We also know the
68+ // write is appropriately aligned for a `*mut u8` pointer because
69+ // `align_ptr` is aligned, and alignments are always powers of two
70+ // (as enforced by the `Layout` type).
71+ unsafe {
72+ let aligned_ptr = full_alloc_ptr. add ( offset) ;
73+ ( aligned_ptr. cast :: < * mut u8 > ( ) ) . sub ( 1 ) . write ( full_alloc_ptr) ;
74+ aligned_ptr
75+ }
76+ }
77+
4378/// Allocator using UEFI boot services.
4479///
4580/// This type implements [`GlobalAlloc`] and can be marked with the
@@ -75,39 +110,7 @@ unsafe impl GlobalAlloc for Allocator {
75110 . unwrap_or ( ptr:: null_mut ( ) )
76111 }
77112 9 .. => {
78- // The requested alignment is greater than 8, but `allocate_pool` is
79- // only guaranteed to provide eight-byte alignment. Allocate extra
80- // space so that we can return an appropriately-aligned pointer
81- // within the allocation.
82- let full_alloc_ptr = boot:: allocate_pool ( memory_type, size + align) ;
83- let full_alloc_ptr = if let Ok ( ptr) = full_alloc_ptr
84- {
85- ptr. as_ptr ( )
86- } else {
87- return ptr:: null_mut ( ) ;
88- } ;
89-
90- // Calculate the offset needed to get an aligned pointer within the
91- // full allocation. If that offset is zero, increase it to `align`
92- // so that we still have space to store the extra pointer described
93- // below.
94- let mut offset = full_alloc_ptr. align_offset ( align) ;
95- if offset == 0 {
96- offset = align;
97- }
98-
99- // Before returning the aligned allocation, store a pointer to the
100- // full unaligned allocation in the bytes just before the aligned
101- // allocation. We know we have at least eight bytes there due to
102- // adding `align` to the memory allocation size. We also know the
103- // write is appropriately aligned for a `*mut u8` pointer because
104- // `align_ptr` is aligned, and alignments are always powers of two
105- // (as enforced by the `Layout` type).
106- unsafe {
107- let aligned_ptr = full_alloc_ptr. add ( offset) ;
108- ( aligned_ptr. cast :: < * mut u8 > ( ) ) . sub ( 1 ) . write ( full_alloc_ptr) ;
109- aligned_ptr
110- }
113+ alloc_pool_aligned ( memory_type, size, align)
111114 }
112115 }
113116 }
0 commit comments