Skip to content

Commit 71ebba1

Browse files
authored
Merge pull request #1276 from nicholasbishop/bishop-raise-tpl
boot: Add freestanding version of raise_tpl
2 parents 32b83ec + 7b53512 commit 71ebba1

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

uefi-test-runner/src/boot/misc.rs

+7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use uefi::{boot, guid, Event, Guid, Identify};
1313

1414
pub fn test(st: &SystemTable<Boot>) {
1515
let bt = st.boot_services();
16+
test_tpl();
1617
info!("Testing timer...");
1718
test_timer(bt);
1819
info!("Testing events...");
@@ -28,6 +29,12 @@ pub fn test(st: &SystemTable<Boot>) {
2829
test_install_configuration_table(st);
2930
}
3031

32+
fn test_tpl() {
33+
info!("Testing watchdog...");
34+
// There's no way to query the TPL, so we can't assert that this does anything.
35+
let _guard = unsafe { boot::raise_tpl(Tpl::NOTIFY) };
36+
}
37+
3138
fn test_timer(bt: &BootServices) {
3239
let timer_event = unsafe { bt.create_event(EventType::TIMER, Tpl::APPLICATION, None, None) }
3340
.expect("Failed to create TIMER event");

uefi/src/boot.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use {
2020
pub use uefi::table::boot::{
2121
AllocateType, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, SearchType,
2222
};
23-
pub use uefi_raw::table::boot::MemoryType;
23+
pub use uefi_raw::table::boot::{MemoryType, Tpl};
2424

2525
/// Global image handle. This is only set by [`set_image_handle`], and it is
2626
/// only read by [`image_handle`].
@@ -58,6 +58,30 @@ fn boot_services_raw_panicking() -> NonNull<uefi_raw::table::boot::BootServices>
5858
NonNull::new(st.boot_services).expect("boot services are not active")
5959
}
6060

61+
/// Raises a task's priority level and returns a [`TplGuard`].
62+
///
63+
/// The effect of calling `raise_tpl` with a `Tpl` that is below the current
64+
/// one (which, sadly, cannot be queried) is undefined by the UEFI spec,
65+
/// which also warns against remaining at high `Tpl`s for a long time.
66+
///
67+
/// This function returns an RAII guard that will automatically restore the
68+
/// original `Tpl` when dropped.
69+
///
70+
/// # Safety
71+
///
72+
/// Raising a task's priority level can affect other running tasks and
73+
/// critical processes run by UEFI. The highest priority level is the
74+
/// most dangerous, since it disables interrupts.
75+
#[must_use]
76+
pub unsafe fn raise_tpl(tpl: Tpl) -> TplGuard {
77+
let bt = boot_services_raw_panicking();
78+
let bt = unsafe { bt.as_ref() };
79+
80+
TplGuard {
81+
old_tpl: (bt.raise_tpl)(tpl),
82+
}
83+
}
84+
6185
/// Allocates memory pages from the system.
6286
///
6387
/// UEFI OS loaders should allocate memory of the type `LoaderData`.
@@ -451,3 +475,22 @@ impl<P: Protocol + ?Sized> ScopedProtocol<P> {
451475
self.interface.map(|mut p| unsafe { p.as_mut() })
452476
}
453477
}
478+
479+
/// RAII guard for task priority level changes.
480+
///
481+
/// Will automatically restore the former task priority level when dropped.
482+
#[derive(Debug)]
483+
pub struct TplGuard {
484+
old_tpl: Tpl,
485+
}
486+
487+
impl Drop for TplGuard {
488+
fn drop(&mut self) {
489+
let bt = boot_services_raw_panicking();
490+
let bt = unsafe { bt.as_ref() };
491+
492+
unsafe {
493+
(bt.restore_tpl)(self.old_tpl);
494+
}
495+
}
496+
}

0 commit comments

Comments
 (0)