@@ -11,7 +11,15 @@ use core::slice;
11
11
use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
12
12
use uefi:: { table, Handle , Result , Status , StatusExt } ;
13
13
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
+ } ;
15
23
pub use uefi_raw:: table:: boot:: MemoryType ;
16
24
17
25
/// 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>(
242
250
}
243
251
}
244
252
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
+
245
358
/// A buffer returned by [`locate_handle_buffer`] that contains an array of
246
359
/// [`Handle`]s that support the requested protocol.
247
360
#[ derive( Debug , Eq , PartialEq ) ]
0 commit comments