@@ -134,15 +134,40 @@ pub fn allocate_pages(ty: AllocateType, mem_ty: MemoryType, count: usize) -> Res
134
134
let bt = boot_services_raw_panicking ( ) ;
135
135
let bt = unsafe { bt. as_ref ( ) } ;
136
136
137
- let ( ty, mut addr ) = match ty {
137
+ let ( ty, initial_addr ) = match ty {
138
138
AllocateType :: AnyPages => ( 0 , 0 ) ,
139
139
AllocateType :: MaxAddress ( addr) => ( 1 , addr) ,
140
140
AllocateType :: Address ( addr) => ( 2 , addr) ,
141
141
} ;
142
- let addr =
143
- unsafe { ( bt. allocate_pages ) ( ty, mem_ty, count, & mut addr) } . to_result_with_val ( || addr) ?;
144
- let ptr = addr as * mut u8 ;
145
- Ok ( NonNull :: new ( ptr) . expect ( "allocate_pages must not return a null pointer if successful" ) )
142
+
143
+ let mut addr1 = initial_addr;
144
+ unsafe { ( bt. allocate_pages ) ( ty, mem_ty, count, & mut addr1) } . to_result ( ) ?;
145
+
146
+ // The UEFI spec allows `allocate_pages` to return a valid allocation at
147
+ // address zero. Rust does not allow writes through a null pointer (which
148
+ // Rust defines as address zero), so this is not very useful. Only return
149
+ // the allocation if the address is non-null.
150
+ if let Some ( ptr) = NonNull :: new ( addr1 as * mut u8 ) {
151
+ return Ok ( ptr) ;
152
+ }
153
+
154
+ // Attempt a second allocation. The first allocation (at address zero) has
155
+ // not yet been freed, so if this allocation succeeds it should be at a
156
+ // non-zero address.
157
+ let mut addr2 = initial_addr;
158
+ let r = unsafe { ( bt. allocate_pages ) ( ty, mem_ty, count, & mut addr2) } . to_result ( ) ;
159
+
160
+ // Free the original allocation (ignoring errors).
161
+ let _unused = unsafe { ( bt. free_pages ) ( addr1, count) } ;
162
+
163
+ // Return an error if the second allocation failed, or if it is still at
164
+ // address zero. Otherwise, return a pointer to the second allocation.
165
+ r?;
166
+ if let Some ( ptr) = NonNull :: new ( addr2 as * mut u8 ) {
167
+ Ok ( ptr)
168
+ } else {
169
+ Err ( Status :: OUT_OF_RESOURCES . into ( ) )
170
+ }
146
171
}
147
172
148
173
/// Frees memory pages allocated by [`allocate_pages`].
0 commit comments