Skip to content

Commit 990a2c0

Browse files
authored
Merge pull request #1272 from nicholasbishop/bishop-boot-mod-2
boot: Add freestanding version of open_protocol_exclusive
2 parents 1f8cdfc + 0f9b394 commit 990a2c0

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

uefi-test-runner/src/bin/shell_launcher.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern crate alloc;
1313

1414
use alloc::vec::Vec;
1515
use log::info;
16+
use uefi::boot;
1617
use uefi::prelude::*;
1718
use uefi::proto::device_path::build::{self, DevicePathBuilder};
1819
use uefi::proto::device_path::{DevicePath, DeviceSubType, DeviceType, LoadedImageDevicePath};
@@ -21,13 +22,10 @@ use uefi::table::boot::LoadImageSource;
2122

2223
/// Get the device path of the shell app. This is the same as the
2324
/// currently-loaded image's device path, but with the file path part changed.
24-
fn get_shell_app_device_path<'a>(
25-
boot_services: &BootServices,
26-
storage: &'a mut Vec<u8>,
27-
) -> &'a DevicePath {
28-
let loaded_image_device_path = boot_services
29-
.open_protocol_exclusive::<LoadedImageDevicePath>(boot_services.image_handle())
30-
.expect("failed to open LoadedImageDevicePath protocol");
25+
fn get_shell_app_device_path(storage: &mut Vec<u8>) -> &DevicePath {
26+
let loaded_image_device_path =
27+
boot::open_protocol_exclusive::<LoadedImageDevicePath>(boot::image_handle())
28+
.expect("failed to open LoadedImageDevicePath protocol");
3129

3230
let mut builder = DevicePathBuilder::with_vec(storage);
3331
for node in loaded_image_device_path.node_iter() {
@@ -50,7 +48,7 @@ fn efi_main(image: Handle, st: SystemTable<Boot>) -> Status {
5048
let boot_services = st.boot_services();
5149

5250
let mut storage = Vec::new();
53-
let shell_image_path = get_shell_app_device_path(boot_services, &mut storage);
51+
let shell_image_path = get_shell_app_device_path(&mut storage);
5452

5553
// Load the shell app.
5654
let shell_image_handle = boot_services
@@ -65,8 +63,7 @@ fn efi_main(image: Handle, st: SystemTable<Boot>) -> Status {
6563

6664
// Set the command line passed to the shell app so that it will run the
6765
// test-runner app. This automatically turns off the five-second delay.
68-
let mut shell_loaded_image = boot_services
69-
.open_protocol_exclusive::<LoadedImage>(shell_image_handle)
66+
let mut shell_loaded_image = boot::open_protocol_exclusive::<LoadedImage>(shell_image_handle)
7067
.expect("failed to open LoadedImage protocol");
7168
let load_options = cstr16!(r"shell.efi test_runner.efi arg1 arg2");
7269
unsafe {

uefi/src/boot.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub fn image_handle() -> Handle {
3838
///
3939
/// This function should only be called as described above, and the
4040
/// `image_handle` must be a valid image [`Handle`]. The safety guarantees of
41-
/// `open_protocol_exclusive` rely on the global image handle being correct.
41+
/// [`open_protocol_exclusive`] rely on the global image handle being correct.
4242
pub unsafe fn set_image_handle(image_handle: Handle) {
4343
IMAGE_HANDLE.store(image_handle.as_ptr(), Ordering::Release);
4444
}
@@ -162,7 +162,7 @@ pub fn locate_handle_buffer(search_ty: SearchType) -> Result<HandleBuffer> {
162162

163163
/// Opens a protocol interface for a handle.
164164
///
165-
/// See also `open_protocol_exclusive`, which provides a safe subset of this
165+
/// See also [`open_protocol_exclusive`], which provides a safe subset of this
166166
/// functionality.
167167
///
168168
/// This function attempts to get the protocol implementation of a handle, based
@@ -214,6 +214,34 @@ pub unsafe fn open_protocol<P: ProtocolPointer + ?Sized>(
214214
})
215215
}
216216

217+
/// Opens a protocol interface for a handle in exclusive mode.
218+
///
219+
/// If successful, a [`ScopedProtocol`] is returned that will automatically
220+
/// close the protocol interface when dropped.
221+
///
222+
/// # Errors
223+
///
224+
/// * [`Status::UNSUPPORTED`]: the handle does not support the protocol.
225+
/// * [`Status::ACCESS_DENIED`]: the protocol is already open in a way that is
226+
/// incompatible with the new request.
227+
pub fn open_protocol_exclusive<P: ProtocolPointer + ?Sized>(
228+
handle: Handle,
229+
) -> Result<ScopedProtocol<P>> {
230+
// Safety: opening in exclusive mode with the correct agent
231+
// handle set ensures that the protocol cannot be modified or
232+
// removed while it is open, so this usage is safe.
233+
unsafe {
234+
open_protocol::<P>(
235+
OpenProtocolParams {
236+
handle,
237+
agent: image_handle(),
238+
controller: None,
239+
},
240+
OpenProtocolAttributes::Exclusive,
241+
)
242+
}
243+
}
244+
217245
/// A buffer returned by [`locate_handle_buffer`] that contains an array of
218246
/// [`Handle`]s that support the requested protocol.
219247
#[derive(Debug, Eq, PartialEq)]

0 commit comments

Comments
 (0)