@@ -11,7 +11,15 @@ use core::slice;
1111use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
1212use 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+ } ;
1523pub 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,111 @@ 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+
324+ /// Unloads a UEFI image.
325+ ///
326+ /// # Errors
327+ ///
328+ /// * [`Status::UNSUPPORTED`]: the image has been started, and does not support unload.
329+ /// * [`Status::INVALID_PARAMETER`]: `image_handle` is not valid.
330+ pub fn unload_image ( image_handle : Handle ) -> Result {
331+ let bt = boot_services_raw_panicking ( ) ;
332+ let bt = unsafe { bt. as_ref ( ) } ;
333+
334+ unsafe { ( bt. unload_image ) ( image_handle. as_ptr ( ) ) } . to_result ( )
335+ }
336+
337+ /// Transfers control to a loaded image's entry point.
338+ ///
339+ /// # Errors
340+ ///
341+ /// * [`Status::INVALID_PARAMETER`]: `image_handle` is not valid, or the image
342+ /// has already been initialized with `start_image`.
343+ /// * [`Status::SECURITY_VIOLATION`]: a security policy specifies that the image
344+ /// should not be started.
345+ pub fn start_image ( image_handle : Handle ) -> Result {
346+ let bt = boot_services_raw_panicking ( ) ;
347+ let bt = unsafe { bt. as_ref ( ) } ;
348+
349+ // TODO: implement returning exit data to the caller.
350+ let mut exit_data_size: usize = 0 ;
351+ let mut exit_data: * mut u16 = ptr:: null_mut ( ) ;
352+
353+ unsafe {
354+ ( bt. start_image ) ( image_handle. as_ptr ( ) , & mut exit_data_size, & mut exit_data) . to_result ( )
355+ }
356+ }
357+
245358/// A buffer returned by [`locate_handle_buffer`] that contains an array of
246359/// [`Handle`]s that support the requested protocol.
247360#[ derive( Debug , Eq , PartialEq ) ]
0 commit comments