@@ -13,6 +13,7 @@ use core::ffi::c_void;
13
13
use core:: mem:: { self , MaybeUninit } ;
14
14
use core:: ops:: { Deref , DerefMut } ;
15
15
use core:: ptr:: NonNull ;
16
+ use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
16
17
use core:: { ptr, slice} ;
17
18
18
19
#[ cfg( feature = "alloc" ) ]
@@ -22,19 +23,9 @@ pub use uefi_raw::table::boot::{
22
23
EventType , InterfaceType , MemoryAttribute , MemoryDescriptor , MemoryType , Tpl ,
23
24
} ;
24
25
25
- // TODO: this similar to `SyncUnsafeCell`. Once that is stabilized we
26
- // can use it instead.
27
- struct GlobalImageHandle {
28
- handle : UnsafeCell < Option < Handle > > ,
29
- }
30
-
31
- // Safety: reads and writes are managed via `set_image_handle` and
32
- // `BootServices::image_handle`.
33
- unsafe impl Sync for GlobalImageHandle { }
34
-
35
- static IMAGE_HANDLE : GlobalImageHandle = GlobalImageHandle {
36
- handle : UnsafeCell :: new ( None ) ,
37
- } ;
26
+ /// Global image handle. This is only set by `BootServices::set_image_handle`,
27
+ /// and it is only read by `BootServices::image_handle`.
28
+ static IMAGE_HANDLE : AtomicPtr < c_void > = AtomicPtr :: new ( ptr:: null_mut ( ) ) ;
38
29
39
30
/// Size in bytes of a UEFI page.
40
31
///
@@ -95,22 +86,10 @@ pub struct BootServices(uefi_raw::table::boot::BootServices);
95
86
impl BootServices {
96
87
/// Get the [`Handle`] of the currently-executing image.
97
88
pub fn image_handle ( & self ) -> Handle {
98
- // Safety:
99
- //
100
- // `IMAGE_HANDLE` is only set by `set_image_handle`, see that
101
- // documentation for more details.
102
- //
103
- // Additionally, `image_handle` takes a `&self` which ensures it
104
- // can only be called while boot services are active. (After
105
- // exiting boot services, the image handle should not be
106
- // considered valid.)
107
- unsafe {
108
- IMAGE_HANDLE
109
- . handle
110
- . get ( )
111
- . read ( )
112
- . expect ( "set_image_handle has not been called" )
113
- }
89
+ let ptr = IMAGE_HANDLE . load ( Ordering :: Acquire ) ;
90
+ // Safety: the image handle must be valid. We know it is, because it was
91
+ // set by `set_image_handle`, which has that same safety requirement.
92
+ unsafe { Handle :: from_ptr ( ptr) } . expect ( "set_image_handle has not been called" )
114
93
}
115
94
116
95
/// Update the global image [`Handle`].
@@ -123,14 +102,15 @@ impl BootServices {
123
102
///
124
103
/// # Safety
125
104
///
126
- /// This function should only be called as described above. The
105
+ /// This function should only be called as described above,
106
+ /// and the `image_handle` must be a valid image [`Handle`]. Then
127
107
/// safety guarantees of [`BootServices::open_protocol_exclusive`]
128
108
/// rely on the global image handle being correct.
129
109
pub unsafe fn set_image_handle ( & self , image_handle : Handle ) {
130
110
// As with `image_handle`, `&self` isn't actually used, but it
131
111
// enforces that this function is only called while boot
132
112
// services are active.
133
- IMAGE_HANDLE . handle . get ( ) . write ( Some ( image_handle ) ) ;
113
+ IMAGE_HANDLE . store ( image_handle . as_ptr ( ) , Ordering :: Release ) ;
134
114
}
135
115
136
116
/// Raises a task's priority level and returns its previous level.
0 commit comments