Skip to content

Commit 9b75540

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 9b75540

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-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

+62
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,68 @@ 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 image [`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 active.
42+
pub fn system_table_boot() -> SystemTable<Boot> {
43+
let st = SYSTEM_TABLE.load(Ordering::Acquire);
44+
assert!(!st.is_null());
45+
46+
// SAFETY: the system table is valid per the requirements of `set_system_table`.
47+
unsafe {
48+
if (*st).boot_services.is_null() {
49+
panic!("boot services are not active");
50+
}
51+
52+
SystemTable::<Boot>::from_ptr(st.cast()).unwrap()
53+
}
54+
}
55+
56+
/// Get the system table while runtime services are active.
57+
///
58+
/// # Panics
59+
///
60+
/// Panics if the system table has not been set with `set_system_table`, or if
61+
/// runtime services are not active.
62+
pub fn system_table_runtime() -> SystemTable<Runtime> {
63+
let st = SYSTEM_TABLE.load(Ordering::Acquire);
64+
assert!(!st.is_null());
65+
66+
// SAFETY: the system table is valid per the requirements of `set_system_table`.
67+
unsafe {
68+
if (*st).runtime_services.is_null() {
69+
panic!("boot services are not active");
70+
}
71+
72+
SystemTable::<Runtime>::from_ptr(st.cast()).unwrap()
73+
}
74+
}
75+
1476
/// Common trait implemented by all standard UEFI tables.
1577
pub trait Table {
1678
/// A unique number assigned by the UEFI specification

0 commit comments

Comments
 (0)