@@ -208,6 +208,46 @@ impl SystemTable<Runtime> {
208
208
pub unsafe fn runtime_services ( & self ) -> & RuntimeServices {
209
209
self . table . runtime
210
210
}
211
+
212
+ /// Changes the runtime addressing mode of EFI firmware from physical to virtual.
213
+ /// It is up to the caller to translate the old SystemTable address to a new virtual
214
+ /// address and provide it for this function.
215
+ /// See [`get_current_system_table_addr`]
216
+ ///
217
+ /// # Safety
218
+ ///
219
+ /// Setting new virtual memory map is unsafe and may cause undefined behaviors.
220
+ ///
221
+ /// [`get_current_system_table_addr`]: SystemTable::get_current_system_table_addr
222
+ pub unsafe fn set_virtual_address_map (
223
+ self ,
224
+ map : & mut [ MemoryDescriptor ] ,
225
+ new_system_table_virtual_addr : u64 ,
226
+ ) -> Result < Self > {
227
+ // Unsafe Code Guidelines guarantees that there is no padding in an array or a slice
228
+ // between its elements if the element type is `repr(C)`, which is our case.
229
+ //
230
+ // See https://rust-lang.github.io/unsafe-code-guidelines/layout/arrays-and-slices.html
231
+ let map_size = core:: mem:: size_of_val ( map) ;
232
+ let entry_size = core:: mem:: size_of :: < MemoryDescriptor > ( ) ;
233
+ let entry_version = crate :: table:: boot:: MEMORY_DESCRIPTOR_VERSION ;
234
+ let map_ptr = map. as_mut_ptr ( ) ;
235
+ ( self . table . runtime . set_virtual_address_map ) ( map_size, entry_size, entry_version, map_ptr)
236
+ . into_with_val ( || {
237
+ let new_table_ref =
238
+ & mut * ( new_system_table_virtual_addr as usize as * mut SystemTableImpl ) ;
239
+ Self {
240
+ table : new_table_ref,
241
+ _marker : PhantomData ,
242
+ }
243
+ } )
244
+ }
245
+
246
+ /// Return the address of the SystemTable that resides in a UEFI runtime services
247
+ /// memory region.
248
+ pub fn get_current_system_table_addr ( & self ) -> u64 {
249
+ self . table as * const _ as usize as u64
250
+ }
211
251
}
212
252
213
253
/// The actual UEFI system table
0 commit comments