Skip to content

Commit 7f9d2dd

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

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

uefi/src/boot.rs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@ 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+
#[cfg(doc)]
15+
use {
16+
crate::proto::device_path::LoadedImageDevicePath, crate::proto::loaded_image::LoadedImage,
17+
crate::proto::media::fs::SimpleFileSystem,
18+
};
19+
20+
pub use uefi::table::boot::{
21+
AllocateType, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, SearchType,
22+
};
1523
pub use uefi_raw::table::boot::MemoryType;
1624

1725
/// Global image handle. This is only set by [`set_image_handle`], and it is
@@ -242,6 +250,77 @@ pub fn open_protocol_exclusive<P: ProtocolPointer + ?Sized>(
242250
}
243251
}
244252

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

0 commit comments

Comments
 (0)