Skip to content

Commit

Permalink
Merge pull request rust-osdev#1262 from rust-osdev/bishop-move-image-…
Browse files Browse the repository at this point in the history
…handle

Move the global image handle to uefi::boot
  • Loading branch information
phip1611 authored Jul 28, 2024
2 parents 479868f + 59b9d0b commit f7f4fa8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 23 deletions.
33 changes: 32 additions & 1 deletion uefi/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,46 @@
//! These functions will panic if called after exiting boot services.

use crate::data_types::PhysicalAddress;
use core::ffi::c_void;
use core::ptr::{self, NonNull};
use uefi::{table, Result, StatusExt};
use core::sync::atomic::{AtomicPtr, Ordering};
use uefi::{table, Handle, Result, StatusExt};

#[cfg(doc)]
use uefi::Status;

pub use uefi::table::boot::AllocateType;
pub use uefi_raw::table::boot::MemoryType;

/// Global image handle. This is only set by [`set_image_handle`], and it is
/// only read by [`image_handle`].
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());

/// Get the [`Handle`] of the currently-executing image.
#[must_use]
pub fn image_handle() -> Handle {
let ptr = IMAGE_HANDLE.load(Ordering::Acquire);
// Safety: the image handle must be valid. We know it is, because it was set
// by `set_image_handle`, which has that same safety requirement.
unsafe { Handle::from_ptr(ptr) }.expect("set_image_handle has not been called")
}

/// Update the global image [`Handle`].
///
/// This is called automatically in the `main` entry point as part of
/// [`uefi::entry`]. It should not be called at any other point in time, unless
/// the executable does not use [`uefi::entry`], in which case it should be
/// called once before calling other boot services functions.
///
/// # Safety
///
/// This function should only be called as described above, and the
/// `image_handle` must be a valid image [`Handle`]. The safety guarantees of
/// `open_protocol_exclusive` rely on the global image handle being correct.
pub unsafe fn set_image_handle(image_handle: Handle) {
IMAGE_HANDLE.store(image_handle.as_ptr(), Ordering::Release);
}

fn boot_services_raw_panicking() -> NonNull<uefi_raw::table::boot::BootServices> {
let st = table::system_table_raw_panicking();
// SAFETY: valid per requirements of `set_system_table`.
Expand Down
28 changes: 6 additions & 22 deletions uefi/src/table/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@ use core::fmt::Debug;
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::ptr::NonNull;
use core::sync::atomic::{AtomicPtr, Ordering};
use core::{ptr, slice};

/// Global image handle. This is only set by `BootServices::set_image_handle`,
/// and it is only read by `BootServices::image_handle`.
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());

/// Size in bytes of a UEFI page.
///
/// Note that this is not necessarily the processor's page size. The UEFI page
Expand Down Expand Up @@ -84,32 +79,21 @@ pub struct BootServices(uefi_raw::table::boot::BootServices);

impl BootServices {
/// Get the [`Handle`] of the currently-executing image.
#[must_use]
pub fn image_handle(&self) -> Handle {
let ptr = IMAGE_HANDLE.load(Ordering::Acquire);
// Safety: the image handle must be valid. We know it is, because it was
// set by `set_image_handle`, which has that same safety requirement.
unsafe { Handle::from_ptr(ptr) }.expect("set_image_handle has not been called")
uefi::boot::image_handle()
}

/// Update the global image [`Handle`].
///
/// This is called automatically in the `main` entry point as part
/// of [`uefi::entry`]. It should not be called at any other
/// point in time, unless the executable does not use
/// [`uefi::entry`], in which case it should be called once
/// before calling other `BootServices` functions.
/// This is the same as calling [`uefi::boot::set_image_handle`]. See that
/// function for details.
///
/// # Safety
///
/// This function should only be called as described above,
/// and the `image_handle` must be a valid image [`Handle`]. Then
/// safety guarantees of [`BootServices::open_protocol_exclusive`]
/// rely on the global image handle being correct.
/// See [`uefi::boot::set_image_handle`] for safety requirements.
pub unsafe fn set_image_handle(&self, image_handle: Handle) {
// As with `image_handle`, `&self` isn't actually used, but it
// enforces that this function is only called while boot
// services are active.
IMAGE_HANDLE.store(image_handle.as_ptr(), Ordering::Release);
uefi::boot::set_image_handle(image_handle)
}

/// Raises a task's priority level and returns its previous level.
Expand Down

0 comments on commit f7f4fa8

Please sign in to comment.