Skip to content

Commit c921207

Browse files
committed
uefi-services: deprecation: move to uefi::helpers
uefi_services::init temporarily stays API compatible to prevent breaking changes. But we've added deprecation warnings. The new uefi::helpers tool is mostly an unchanged code import. Cleanup will happen in a follow-up.
1 parent 92ba86e commit c921207

File tree

10 files changed

+273
-268
lines changed

10 files changed

+273
-268
lines changed

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

uefi-services/CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# uefi-services - [Unreleased]
22

33
## Changed
4-
- The implicit `qemu-exit` crate feature has been removed. (Note that this is
5-
different from the `qemu` crate feature, which is unchanged.)
4+
- `uefi-services` is deprecated and should be removed. All functionality was
5+
moved to `uefi::helpers::init()`
66

77
# uefi-services - 0.23.0 (2023-11-12)
88

uefi-services/Cargo.toml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "uefi-services"
33
version = "0.24.0"
44
readme = "README.md"
5-
description = "Higher-level utilities for the `uefi` crate."
5+
description = "Deprecated. Please migrate to `uefi::helpers`."
66

77
authors.workspace = true
88
categories.workspace = true
@@ -14,13 +14,10 @@ rust-version.workspace = true
1414

1515
[dependencies]
1616
uefi = { version = "0.27.0", features = ["global_allocator"] }
17-
log.workspace = true
18-
cfg-if = "1.0.0"
19-
qemu-exit = { version = "3.0.1", optional = true }
2017

2118
[features]
2219
default = ["panic_handler", "logger"]
2320
# Enable QEMU-specific functionality
24-
qemu = ["dep:qemu-exit"]
25-
panic_handler = []
21+
qemu = ["uefi/qemu"]
22+
panic_handler = [ "uefi/panic_handler" ]
2623
logger = ["uefi/logger"]

uefi-services/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("cargo:warning=WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`.");
3+
}

uefi-services/src/lib.rs

Lines changed: 7 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -1,253 +1,13 @@
1-
//! This crate simplifies the writing of higher-level code for UEFI.
2-
//!
3-
//! It initializes the memory allocation and logging crates,
4-
//! allowing code to use Rust's data structures and to log errors.
5-
//!
6-
//! Logging and allocation are only allowed while boot services are
7-
//! active. Once runtime services are activated by calling
8-
//! [`exit_boot_services`], the logger will be disabled and the
9-
//! allocator will always return null.
10-
//!
11-
//! It also stores a global reference to the UEFI system table,
12-
//! in order to reduce the redundant passing of references to it.
13-
//!
14-
//! Library code can simply use global UEFI functions
15-
//! through the reference provided by `system_table`.
16-
//!
17-
//! ## Optional crate features
18-
//!
19-
//! - `logger` (enabled by default): Initialize a global logger.
20-
//! - `panic_handler` (enabled by default): Register a panic handler. A
21-
//! panic handler must be provided for your program to compile, but
22-
//! you can choose to provide your own if you don't want to use this
23-
//! one.
24-
//! - `qemu`: On x86_64, make qemu exit with code 3 if a panic
25-
//! occurs. This feature assumes the program is running under QEMU.
26-
//!
27-
//! [`exit_boot_services`]: uefi::table::SystemTable::exit_boot_services
28-
1+
//! WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`.
292
#![no_std]
30-
#![deny(clippy::must_use_candidate)]
31-
#![deny(missing_debug_implementations)]
32-
33-
extern crate log;
34-
// Core types.
35-
extern crate uefi;
36-
37-
use core::ffi::c_void;
38-
use core::fmt::Write;
39-
use core::ptr::{self, NonNull};
40-
use core::sync::atomic::{AtomicPtr, Ordering};
41-
42-
#[cfg(feature = "panic_handler")]
43-
use cfg_if::cfg_if;
44-
45-
use uefi::table::boot::{EventType, Tpl};
46-
use uefi::table::{Boot, SystemTable};
47-
use uefi::{Event, Result, Status, StatusExt};
483

49-
/// Reference to the system table.
50-
///
51-
/// This table is only fully safe to use until UEFI boot services have been exited.
52-
/// After that, some fields and methods are unsafe to use, see the documentation of
53-
/// UEFI's ExitBootServices entry point for more details.
54-
static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
4+
use uefi::prelude::*;
5+
use uefi::Event;
6+
use uefi::Result;
557

56-
/// Global logger object
57-
#[cfg(feature = "logger")]
58-
static LOGGER: uefi::logger::Logger = uefi::logger::Logger::new();
59-
60-
#[must_use]
61-
fn system_table_opt() -> Option<SystemTable<Boot>> {
62-
let ptr = SYSTEM_TABLE.load(Ordering::Acquire);
63-
// Safety: the `SYSTEM_TABLE` pointer either be null or a valid system
64-
// table.
65-
//
66-
// Null is the initial value, as well as the value set when exiting boot
67-
// services. Otherwise, the value is set by the call to `init`, which
68-
// requires a valid system table reference as input.
69-
unsafe { SystemTable::from_ptr(ptr) }
70-
}
71-
72-
/// Obtains a pointer to the system table.
73-
///
74-
/// This is meant to be used by higher-level libraries,
75-
/// which want a convenient way to access the system table singleton.
76-
///
77-
/// `init` must have been called first by the UEFI app.
78-
///
79-
/// The returned pointer is only valid until boot services are exited.
80-
#[must_use]
81-
pub fn system_table() -> SystemTable<Boot> {
82-
system_table_opt().expect("The system table handle is not available")
83-
}
8+
pub use uefi::{print, println};
849

85-
/// Initialize the UEFI utility library.
86-
///
87-
/// This must be called as early as possible,
88-
/// before trying to use logging or memory allocation capabilities.
10+
#[deprecated = "WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`."]
8911
pub fn init(st: &mut SystemTable<Boot>) -> Result<Option<Event>> {
90-
if system_table_opt().is_some() {
91-
// Avoid double initialization.
92-
return Status::SUCCESS.to_result_with_val(|| None);
93-
}
94-
95-
// Setup the system table singleton
96-
SYSTEM_TABLE.store(st.as_ptr().cast_mut(), Ordering::Release);
97-
98-
unsafe {
99-
// Setup logging and memory allocation
100-
101-
#[cfg(feature = "logger")]
102-
init_logger(st);
103-
104-
uefi::allocator::init(st);
105-
106-
// Schedule these tools to be disabled on exit from UEFI boot services
107-
let boot_services = st.boot_services();
108-
boot_services
109-
.create_event(
110-
EventType::SIGNAL_EXIT_BOOT_SERVICES,
111-
Tpl::NOTIFY,
112-
Some(exit_boot_services),
113-
None,
114-
)
115-
.map(Some)
116-
}
117-
}
118-
119-
// Internal function for print macros.
120-
#[doc(hidden)]
121-
pub fn _print(args: core::fmt::Arguments) {
122-
system_table()
123-
.stdout()
124-
.write_fmt(args)
125-
.expect("Failed to write to stdout");
126-
}
127-
128-
/// Prints to the standard output.
129-
///
130-
/// # Panics
131-
/// Will panic if `SYSTEM_TABLE` is `None` (Before [init()] and after [uefi::prelude::SystemTable::exit_boot_services()]).
132-
///
133-
/// # Examples
134-
/// ```
135-
/// print!("");
136-
/// print!("Hello World\n");
137-
/// print!("Hello {}", "World");
138-
/// ```
139-
#[macro_export]
140-
macro_rules! print {
141-
($($arg:tt)*) => ($crate::_print(core::format_args!($($arg)*)));
142-
}
143-
144-
/// Prints to the standard output, with a newline.
145-
///
146-
/// # Panics
147-
/// Will panic if `SYSTEM_TABLE` is `None` (Before [init()] and after [uefi::prelude::SystemTable::exit_boot_services()]).
148-
///
149-
/// # Examples
150-
/// ```
151-
/// println!();
152-
/// println!("Hello World");
153-
/// println!("Hello {}", "World");
154-
/// ```
155-
#[macro_export]
156-
macro_rules! println {
157-
() => ($crate::print!("\n"));
158-
($($arg:tt)*) => ($crate::_print(core::format_args!("{}{}", core::format_args!($($arg)*), "\n")));
159-
}
160-
161-
/// Set up logging
162-
///
163-
/// This is unsafe because you must arrange for the logger to be reset with
164-
/// disable() on exit from UEFI boot services.
165-
#[cfg(feature = "logger")]
166-
unsafe fn init_logger(st: &mut SystemTable<Boot>) {
167-
// Connect the logger to stdout.
168-
LOGGER.set_output(st.stdout());
169-
170-
// Set the logger.
171-
log::set_logger(&LOGGER).unwrap(); // Can only fail if already initialized.
172-
173-
// Set logger max level to level specified by log features
174-
log::set_max_level(log::STATIC_MAX_LEVEL);
175-
}
176-
177-
/// Notify the utility library that boot services are not safe to call anymore
178-
/// As this is a callback, it must be `extern "efiapi"`.
179-
unsafe extern "efiapi" fn exit_boot_services(_e: Event, _ctx: Option<NonNull<c_void>>) {
180-
// DEBUG: The UEFI spec does not guarantee that this printout will work, as
181-
// the services used by logging might already have been shut down.
182-
// But it works on current OVMF, and can be used as a handy way to
183-
// check that the callback does get called.
184-
//
185-
// info!("Shutting down the UEFI utility library");
186-
SYSTEM_TABLE.store(ptr::null_mut(), Ordering::Release);
187-
188-
#[cfg(feature = "logger")]
189-
LOGGER.disable();
190-
191-
uefi::allocator::exit_boot_services();
192-
}
193-
194-
#[cfg(feature = "panic_handler")]
195-
#[panic_handler]
196-
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
197-
println!("[PANIC]: {}", info);
198-
199-
// Give the user some time to read the message
200-
if let Some(st) = system_table_opt() {
201-
st.boot_services().stall(10_000_000);
202-
} else {
203-
let mut dummy = 0u64;
204-
// FIXME: May need different counter values in debug & release builds
205-
for i in 0..300_000_000 {
206-
unsafe {
207-
core::ptr::write_volatile(&mut dummy, i);
208-
}
209-
}
210-
}
211-
212-
cfg_if! {
213-
if #[cfg(all(target_arch = "x86_64", feature = "qemu"))] {
214-
// If running in QEMU, use the f4 exit port to signal the error and exit
215-
use qemu_exit::QEMUExit;
216-
let custom_exit_success = 3;
217-
let qemu_exit_handle = qemu_exit::X86::new(0xF4, custom_exit_success);
218-
qemu_exit_handle.exit_failure();
219-
} else {
220-
// If the system table is available, use UEFI's standard shutdown mechanism
221-
if let Some(st) = system_table_opt() {
222-
use uefi::table::runtime::ResetType;
223-
st.runtime_services()
224-
.reset(ResetType::SHUTDOWN, uefi::Status::ABORTED, None);
225-
}
226-
227-
// If we don't have any shutdown mechanism handy, the best we can do is loop
228-
log::error!("Could not shut down, please power off the system manually...");
229-
230-
cfg_if! {
231-
if #[cfg(target_arch = "x86_64")] {
232-
loop {
233-
unsafe {
234-
// Try to at least keep CPU from running at 100%
235-
core::arch::asm!("hlt", options(nomem, nostack));
236-
}
237-
}
238-
} else if #[cfg(target_arch = "aarch64")] {
239-
loop {
240-
unsafe {
241-
// Try to at least keep CPU from running at 100%
242-
core::arch::asm!("hlt 420", options(nomem, nostack));
243-
}
244-
}
245-
} else {
246-
loop {
247-
// just run forever dammit how do you return never anyway
248-
}
249-
}
250-
}
251-
}
252-
}
12+
uefi::helpers::init(st)
25313
}

uefi/Cargo.toml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,30 @@ rust-version.workspace = true
1515
[features]
1616
default = ["panic-on-logger-errors"]
1717
alloc = []
18-
global_allocator = []
18+
19+
# Generic gate to code that uses unstable features of Rust. You usually need a nightly toolchain.
20+
unstable = []
21+
22+
# Helper features:
1923
logger = []
24+
global_allocator = []
25+
panic_handler = []
2026
# Ignore text output errors in logger as a workaround for firmware issues that
2127
# were observed on the VirtualBox UEFI implementation (see uefi-rs#121).
2228
# In those cases, this feature can be excluded by removing the default features.
2329
panic-on-logger-errors = []
24-
# Generic gate to code that uses unstable features of Rust. You usually need a nightly toolchain.
25-
unstable = []
30+
qemu = ["dep:qemu-exit"]
2631

2732
[dependencies]
2833
bitflags.workspace = true
2934
log.workspace = true
3035
ptr_meta.workspace = true
36+
uguid.workspace = true
37+
cfg-if = "1.0.0"
3138
ucs2 = "0.3.2"
3239
uefi-macros = "0.13.0"
3340
uefi-raw = "0.5.1"
34-
uguid.workspace = true
41+
qemu-exit = { version = "3.0.2", optional = true }
3542

3643
[package.metadata.docs.rs]
3744
all-features = true

uefi/src/allocator.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,4 @@ unsafe impl GlobalAlloc for Allocator {
131131
}
132132
}
133133

134-
#[cfg(feature = "global_allocator")]
135-
#[global_allocator]
136-
static ALLOCATOR: Allocator = Allocator;
134+
File renamed without changes.

0 commit comments

Comments
 (0)