Skip to content

Commit a4135b1

Browse files
boot: Add freestanding version of load_image
1 parent f2ace36 commit a4135b1

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

uefi/src/boot.rs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use core::slice;
1111
use core::sync::atomic::{AtomicPtr, Ordering};
1212
use uefi::{table, Handle, Result, Status, StatusExt};
1313

14-
pub use uefi::table::boot::{AllocateType, OpenProtocolAttributes, OpenProtocolParams, SearchType};
14+
pub use uefi::table::boot::{
15+
AllocateType, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, SearchType,
16+
};
1517
pub use uefi_raw::table::boot::MemoryType;
1618

1719
/// Global image handle. This is only set by [`set_image_handle`], and it is
@@ -242,6 +244,81 @@ pub fn open_protocol_exclusive<P: ProtocolPointer + ?Sized>(
242244
}
243245
}
244246

247+
/// Loads a UEFI image into memory and return a [`Handle`] to the image.
248+
///
249+
/// There are two ways to load the image: by copying raw image data
250+
/// from a source buffer, or by loading the image via the
251+
/// [`SimpleFileSystem`] protocol. See [`LoadImageSource`] for more
252+
/// details of the `source` parameter.
253+
///
254+
/// The `parent_image_handle` is used to initialize the
255+
/// `parent_handle` field of the [`LoadedImage`] protocol for the
256+
/// image.
257+
///
258+
/// If the image is successfully loaded, a [`Handle`] supporting the
259+
/// [`LoadedImage`] and [`LoadedImageDevicePath`] protocols is returned. The
260+
/// image can be started with [`start_image`] and unloaded with
261+
/// [`unload_image`].
262+
///
263+
/// [`LoadedImageDevicePath`]: crate::proto::device_path::LoadedImageDevicePath
264+
/// [`start_image`]: BootServices::start_image
265+
/// [`unload_image`]: BootServices::unload_image
266+
///
267+
/// # Errors
268+
///
269+
/// * [`Status::INVALID_PARAMETER`]: `source` contains an invalid value.
270+
/// * [`Status::UNSUPPORTED`]: the image type is not supported.
271+
/// * [`Status::OUT_OF_RESOURCES`]: insufficient resources to load the image.
272+
/// * [`Status::LOAD_ERROR`]: the image is invalid.
273+
/// * [`Status::DEVICE_ERROR`]: failed to load image due to a read error.
274+
/// * [`Status::ACCESS_DENIED`]: failed to load image due to a security policy.
275+
/// * [`Status::SECURITY_VIOLATION`]: a security policy specifies that the image
276+
/// should not be started.
277+
pub fn load_image(parent_image_handle: Handle, source: LoadImageSource) -> Result<Handle> {
278+
let bt = boot_services_raw_panicking();
279+
let bt = unsafe { bt.as_ref() };
280+
281+
let boot_policy;
282+
let device_path;
283+
let source_buffer;
284+
let source_size;
285+
match source {
286+
LoadImageSource::FromBuffer { buffer, file_path } => {
287+
// Boot policy is ignored when loading from source buffer.
288+
boot_policy = 0;
289+
290+
device_path = file_path.map(|p| p.as_ffi_ptr()).unwrap_or(ptr::null());
291+
source_buffer = buffer.as_ptr();
292+
source_size = buffer.len();
293+
}
294+
LoadImageSource::FromDevicePath {
295+
device_path: file_path,
296+
from_boot_manager,
297+
} => {
298+
boot_policy = u8::from(from_boot_manager);
299+
device_path = file_path.as_ffi_ptr();
300+
source_buffer = ptr::null();
301+
source_size = 0;
302+
}
303+
};
304+
305+
let mut image_handle = ptr::null_mut();
306+
unsafe {
307+
(bt.load_image)(
308+
boot_policy,
309+
parent_image_handle.as_ptr(),
310+
device_path.cast(),
311+
source_buffer,
312+
source_size,
313+
&mut image_handle,
314+
)
315+
.to_result_with_val(
316+
// OK to unwrap: image handle is non-null for Status::SUCCESS.
317+
|| Handle::from_ptr(image_handle).unwrap(),
318+
)
319+
}
320+
}
321+
245322
/// A buffer returned by [`locate_handle_buffer`] that contains an array of
246323
/// [`Handle`]s that support the requested protocol.
247324
#[derive(Debug, Eq, PartialEq)]

0 commit comments

Comments
 (0)