|
20 | 20 | pub use uefi::table::boot::{
|
21 | 21 | AllocateType, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, SearchType,
|
22 | 22 | };
|
23 |
| -pub use uefi_raw::table::boot::MemoryType; |
| 23 | +pub use uefi_raw::table::boot::{MemoryType, Tpl}; |
24 | 24 |
|
25 | 25 | /// Global image handle. This is only set by [`set_image_handle`], and it is
|
26 | 26 | /// only read by [`image_handle`].
|
@@ -58,6 +58,30 @@ fn boot_services_raw_panicking() -> NonNull<uefi_raw::table::boot::BootServices>
|
58 | 58 | NonNull::new(st.boot_services).expect("boot services are not active")
|
59 | 59 | }
|
60 | 60 |
|
| 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 | + |
61 | 85 | /// Allocates memory pages from the system.
|
62 | 86 | ///
|
63 | 87 | /// UEFI OS loaders should allocate memory of the type `LoaderData`.
|
@@ -451,3 +475,22 @@ impl<P: Protocol + ?Sized> ScopedProtocol<P> {
|
451 | 475 | self.interface.map(|mut p| unsafe { p.as_mut() })
|
452 | 476 | }
|
453 | 477 | }
|
| 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