Skip to content

Commit 8653e75

Browse files
boot: Add freestanding version of raise_tpl
This comes with its own version of the `TplGuard` struct. This one has no `BootServices` reference and no lifetime param.
1 parent def0fc8 commit 8653e75

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

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)