Skip to content

Commit f14a72a

Browse files
uefi: Add global system table pointer and API
This is a minimal solution to providing a global system table so that users of the API don't have to pass around references to `SystemTable` / `BootServices` / `RuntimeServices` everywhere.
1 parent 4c2a005 commit f14a72a

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

uefi/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# uefi - [Unreleased]
22

3+
## Added
4+
- Added `table::{set_system_table, system_table_boot, system_table_runtime}`.
5+
This provides an initial API for global tables that do not require passing
6+
around a reference.
7+
38
## Removed
49
- Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger
510
errors are now silently ignored.

uefi/src/table/mod.rs

+65
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,71 @@ pub use header::Header;
1111
pub use system::{Boot, Runtime, SystemTable};
1212
pub use uefi_raw::table::Revision;
1313

14+
use core::ptr;
15+
use core::sync::atomic::{AtomicPtr, Ordering};
16+
17+
/// Global system table pointer. This is only modified by [`set_system_table`].
18+
static SYSTEM_TABLE: AtomicPtr<uefi_raw::table::system::SystemTable> =
19+
AtomicPtr::new(ptr::null_mut());
20+
21+
/// Update the global system table pointer.
22+
///
23+
/// This is called automatically in the `main` entry point as part of
24+
/// [`uefi::entry`]. It should not be called at any other point in time, unless
25+
/// the executable does not use [`uefi::entry`], in which case it should be
26+
/// called once before calling any other API in this crate.
27+
///
28+
/// # Safety
29+
///
30+
/// This function should only be called as described above, and the
31+
/// `ptr` must be a valid [`SystemTable`].
32+
pub unsafe fn set_system_table(ptr: *const uefi_raw::table::system::SystemTable) {
33+
SYSTEM_TABLE.store(ptr.cast_mut(), Ordering::Release);
34+
}
35+
36+
/// Get the system table while boot services are active.
37+
///
38+
/// # Panics
39+
///
40+
/// Panics if the system table has not been set with `set_system_table`, or if
41+
/// boot services are not available (e.g. if [`exit_boot_services`] has been
42+
/// called).
43+
///
44+
/// [`exit_boot_services`]: SystemTable::exit_boot_services
45+
pub fn system_table_boot() -> SystemTable<Boot> {
46+
let st = SYSTEM_TABLE.load(Ordering::Acquire);
47+
assert!(!st.is_null());
48+
49+
// SAFETY: the system table is valid per the requirements of `set_system_table`.
50+
unsafe {
51+
if (*st).boot_services.is_null() {
52+
panic!("boot services are not active");
53+
}
54+
55+
SystemTable::<Boot>::from_ptr(st.cast()).unwrap()
56+
}
57+
}
58+
59+
/// Get the system table while runtime services are active.
60+
///
61+
/// # Panics
62+
///
63+
/// Panics if the system table has not been set with `set_system_table`, or if
64+
/// runtime services are not available.
65+
pub fn system_table_runtime() -> SystemTable<Runtime> {
66+
let st = SYSTEM_TABLE.load(Ordering::Acquire);
67+
assert!(!st.is_null());
68+
69+
// SAFETY: the system table is valid per the requirements of `set_system_table`.
70+
unsafe {
71+
if (*st).runtime_services.is_null() {
72+
panic!("runtime services are not active");
73+
}
74+
75+
SystemTable::<Runtime>::from_ptr(st.cast()).unwrap()
76+
}
77+
}
78+
1479
/// Common trait implemented by all standard UEFI tables.
1580
pub trait Table {
1681
/// A unique number assigned by the UEFI specification

0 commit comments

Comments
 (0)