@@ -18,6 +18,20 @@ use core::ops::{Deref, DerefMut};
18
18
use core:: ptr:: NonNull ;
19
19
use core:: { ptr, slice} ;
20
20
21
+ // TODO: this similar to `SyncUnsafeCell`. Once that is stabilized we
22
+ // can use it instead.
23
+ struct GlobalImageHandle {
24
+ handle : UnsafeCell < Option < Handle > > ,
25
+ }
26
+
27
+ // Safety: reads and writes are managed via `set_image_handle` and
28
+ // `BootServices::image_handle`.
29
+ unsafe impl Sync for GlobalImageHandle { }
30
+
31
+ static IMAGE_HANDLE : GlobalImageHandle = GlobalImageHandle {
32
+ handle : UnsafeCell :: new ( None ) ,
33
+ } ;
34
+
21
35
/// Contains pointers to all of the boot services.
22
36
///
23
37
/// # Accessing `BootServices`
@@ -238,6 +252,46 @@ pub struct BootServices {
238
252
}
239
253
240
254
impl BootServices {
255
+ /// Get the [`Handle`] of the currently-executing image.
256
+ pub fn image_handle ( & self ) -> Handle {
257
+ // Safety:
258
+ //
259
+ // `IMAGE_HANDLE` is only set by `set_image_handle`, see that
260
+ // documentation for more details.
261
+ //
262
+ // Additionally, `image_handle` takes a `&self` which ensures it
263
+ // can only be called while boot services are active. (After
264
+ // exiting boot services, the image handle should not be
265
+ // considered valid.)
266
+ unsafe {
267
+ IMAGE_HANDLE
268
+ . handle
269
+ . get ( )
270
+ . read ( )
271
+ . expect ( "set_image_handle has not been called" )
272
+ }
273
+ }
274
+
275
+ /// Update the global image [`Handle`].
276
+ ///
277
+ /// This is called automatically in the `main` entry point as part
278
+ /// of [`uefi_macros::entry`]. It should not be called at any other
279
+ /// point in time, unless the executable does not use
280
+ /// [`uefi_macros::entry`], in which case it should be called once
281
+ /// before calling other `BootServices` functions.
282
+ ///
283
+ /// # Safety
284
+ ///
285
+ /// This function should only be called as described above. The
286
+ /// safety guarantees of [`BootServices::open_protocol_exclusive`]
287
+ /// rely on the global image handle being correct.
288
+ pub unsafe fn set_image_handle ( & self , image_handle : Handle ) {
289
+ // As with `image_handle`, `&self` isn't actually used, but it
290
+ // enforces that this function is only called while boot
291
+ // services are active.
292
+ IMAGE_HANDLE . handle . get ( ) . write ( Some ( image_handle) ) ;
293
+ }
294
+
241
295
/// Raises a task's priority level and returns its previous level.
242
296
///
243
297
/// The effect of calling `raise_tpl` with a `Tpl` that is below the current
0 commit comments