22
33#![ unstable( feature = "uefi_std" , issue = "100499" ) ]
44
5- use crate :: { cell:: Cell , ffi:: c_void, ptr:: NonNull } ;
5+ use crate :: sync:: atomic:: { AtomicBool , AtomicPtr , Ordering } ;
6+ use crate :: { ffi:: c_void, ptr:: NonNull } ;
67
7- // Since UEFI is single-threaded, making the global variables thread local should be safe.
8- thread_local ! {
9- // Flag to check if BootServices are still valid.
10- // Start with assuming that they are not available
11- static BOOT_SERVICES_FLAG : Cell <bool > = Cell :: new( false ) ;
12- // Position 0 = SystemTable
13- // Position 1 = ImageHandle
14- static GLOBALS : Cell <Option <( NonNull <c_void>, NonNull <c_void>) >> = Cell :: new( None ) ;
15- }
8+ static SYSTEM_TABLE : AtomicPtr < c_void > = AtomicPtr :: new ( crate :: ptr:: null_mut ( ) ) ;
9+ static IMAGE_HANDLE : AtomicPtr < c_void > = AtomicPtr :: new ( crate :: ptr:: null_mut ( ) ) ;
10+ // Flag to check if BootServices are still valid.
11+ // Start with assuming that they are not available
12+ static BOOT_SERVICES_FLAG : AtomicBool = AtomicBool :: new ( false ) ;
1613
1714/// Initializes the global System Table and Image Handle pointers.
1815///
1916/// The standard library requires access to the UEFI System Table and the Application Image Handle
2017/// to operate. Those are provided to UEFI Applications via their application entry point. By
2118/// calling `init_globals()`, those pointers are retained by the standard library for future use.
19+ /// Thus this function must be called before any of the standard library services are used.
20+ ///
2221/// The pointers are never exposed to any entity outside of this application and it is guaranteed
2322/// that, once the application exited, these pointers are never dereferenced again.
2423///
2524/// Callers are required to ensure the pointers are valid for the entire lifetime of this
2625/// application. In particular, UEFI Boot Services must not be exited while an application with the
2726/// standard library is loaded.
2827///
29- /// This function must not be called more than once.
30- pub unsafe fn init_globals ( handle : NonNull < c_void > , system_table : NonNull < c_void > ) {
31- GLOBALS . set ( Some ( ( system_table, handle) ) ) ;
28+ /// # SAFETY
29+ /// Calling this function more than once will panic
30+ pub ( crate ) unsafe fn init_globals ( handle : NonNull < c_void > , system_table : NonNull < c_void > ) {
31+ IMAGE_HANDLE
32+ . compare_exchange (
33+ crate :: ptr:: null_mut ( ) ,
34+ handle. as_ptr ( ) ,
35+ Ordering :: Release ,
36+ Ordering :: Acquire ,
37+ )
38+ . unwrap ( ) ;
39+ SYSTEM_TABLE
40+ . compare_exchange (
41+ crate :: ptr:: null_mut ( ) ,
42+ system_table. as_ptr ( ) ,
43+ Ordering :: Release ,
44+ Ordering :: Acquire ,
45+ )
46+ . unwrap ( ) ;
47+ BOOT_SERVICES_FLAG . store ( true , Ordering :: Release )
3248}
3349
3450/// Get the SystemTable Pointer.
@@ -50,7 +66,7 @@ pub fn image_handle() -> NonNull<c_void> {
5066/// Get the BootServices Pointer.
5167/// This function also checks if `ExitBootServices` has already been called.
5268pub fn boot_services ( ) -> Option < NonNull < c_void > > {
53- if BOOT_SERVICES_FLAG . get ( ) {
69+ if BOOT_SERVICES_FLAG . load ( Ordering :: Acquire ) {
5470 let system_table: NonNull < r_efi:: efi:: SystemTable > = try_system_table ( ) ?. cast ( ) ;
5571 let boot_services = unsafe { ( * system_table. as_ptr ( ) ) . boot_services } ;
5672 NonNull :: new ( boot_services) . map ( |x| x. cast ( ) )
@@ -62,19 +78,15 @@ pub fn boot_services() -> Option<NonNull<c_void>> {
6278/// Get the SystemTable Pointer.
6379/// This function is mostly intended for places where panic is not an option
6480pub ( crate ) fn try_system_table ( ) -> Option < NonNull < c_void > > {
65- GLOBALS . get ( ) . map ( |x| x . 0 )
81+ NonNull :: new ( SYSTEM_TABLE . load ( Ordering :: Acquire ) )
6682}
6783
6884/// Get the SystemHandle Pointer.
6985/// This function is mostly intended for places where panicking is not an option
7086pub ( crate ) fn try_image_handle ( ) -> Option < NonNull < c_void > > {
71- GLOBALS . get ( ) . map ( |x| x. 1 )
72- }
73-
74- pub ( crate ) fn enable_boot_services ( ) {
75- BOOT_SERVICES_FLAG . set ( true ) ;
87+ NonNull :: new ( IMAGE_HANDLE . load ( Ordering :: Acquire ) )
7688}
7789
7890pub ( crate ) fn disable_boot_services ( ) {
79- BOOT_SERVICES_FLAG . set ( false ) ;
91+ BOOT_SERVICES_FLAG . store ( false , Ordering :: Release )
8092}
0 commit comments