Skip to content

Commit 5b33017

Browse files
committed
xxx
1 parent c7668ee commit 5b33017

File tree

4 files changed

+179
-2
lines changed

4 files changed

+179
-2
lines changed

uefi-raw/src/protocol/media.rs

+91
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,60 @@ use crate::protocol::device_path::DevicePathProtocol;
22
use crate::{guid, Guid, Status};
33
use core::ffi::c_void;
44

5+
/// Load File Protocol.
6+
///
7+
/// Used to obtain files, that are primarily boot options, from arbitrary
8+
/// devices.
9+
///
10+
/// # UEFI Spec Description
11+
/// The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from
12+
/// arbitrary devices.
13+
///
14+
/// When the firmware is attempting to load a file, it first attempts to use the
15+
/// device’s Simple File System protocol to read the file. If the file system
16+
/// protocol is found, the firmware implements the policy of interpreting the
17+
/// File Path value of the file being loaded. If the device does not support the
18+
/// file system protocol, the firmware then attempts to read the file via the
19+
/// EFI_LOAD_FILE_PROTOCOL and the LoadFile() function. In this case the
20+
/// LoadFile() function implements the policy of interpreting the File Path
21+
/// value.
522
#[derive(Debug)]
623
#[repr(C)]
724
pub struct LoadFileProtocol {
25+
/// Causes the driver to load a specified file.
26+
///
27+
/// # Parameters
28+
/// - `this` pointer to self
29+
/// - `file_path` The device specific path of the file to load.
30+
/// - `boot_policy` If TRUE, indicates that the request originates from the
31+
/// boot manager, and that the boot manager is attempting to load FilePath
32+
/// as a boot selection. If FALSE, then FilePath must match an exact file
33+
/// to be loaded.
34+
/// - `buffer_size` On input the size of Buffer in bytes. On output with a
35+
/// return code of EFI_SUCCESS, the amount of data transferred to Buffer.
36+
/// On output with a return code of EFI_BUFFER_TOO_SMALL, the size of
37+
/// Buffer required to retrieve the requested file.
38+
/// - `buffer` The memory buffer to transfer the file to. If Buffer is NULL,
39+
/// then the size of the requested file is returned in BufferSize.
40+
///
41+
/// # Errors
42+
/// - `uefi::status::EFI_SUCCESS` The file was loaded.
43+
/// - `uefi::status::EFI_UNSUPPORTED` The device does not support the
44+
/// provided BootPolicy.
45+
/// - `uefi::status::EFI_INVALID_PARAMETER` FilePath is not a valid device
46+
/// path, or BufferSize is NULL.
47+
/// - `uefi::status::EFI_NO_MEDIA` No medium was present to load the file.
48+
/// - `uefi::status::EFI_DEVICE_ERROR` The file was not loaded due to a
49+
/// device error.
50+
/// - `uefi::status::EFI_NO_RESPONSE` The remote system did not respond.
51+
/// - `uefi::status::EFI_NOT_FOUND` The file was not found.
52+
/// - `uefi::status::EFI_ABORTED` The file load process was manually
53+
/// cancelled.
54+
/// - `uefi::status::EFI_BUFFER_TOO_SMALL` The BufferSize is too small to
55+
/// read the current directory entry. BufferSize has been updated with the
56+
/// size needed to complete the request.
57+
/// - `uefi::status::EFI_WARN_FILE_SYSTEM` The resulting Buffer contains
58+
/// UEFI-compliant file system.
859
pub load_file: unsafe extern "efiapi" fn(
960
this: *mut LoadFileProtocol,
1061
file_path: *const DevicePathProtocol,
@@ -18,9 +69,49 @@ impl LoadFileProtocol {
1869
pub const GUID: Guid = guid!("56ec3091-954c-11d2-8e3f-00a0c969723b");
1970
}
2071

72+
/// Load File2 Protocol.
73+
///
74+
/// The Load File2 protocol is used to obtain files from arbitrary devices that
75+
/// are not boot options.
76+
///
77+
/// # UEFI Spec Description
78+
///
79+
/// The EFI_LOAD_FILE2_PROTOCOL is a simple protocol used to obtain files from
80+
/// arbitrary devices that are not boot options. It is used by LoadImage() when
81+
/// its BootOption parameter is FALSE and the FilePath does not have an instance
82+
/// of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.
2183
#[derive(Debug)]
2284
#[repr(C)]
2385
pub struct LoadFile2Protocol {
86+
/// Causes the driver to load a specified file.
87+
///
88+
/// # Parameters
89+
/// - `this` pointer to self
90+
/// - `file_path` The device specific path of the file to load.
91+
/// - `boot_policy` Should always be FALSE.
92+
/// to be loaded.
93+
/// - `buffer_size` On input the size of Buffer in bytes. On output with a
94+
/// return code of EFI_SUCCESS, the amount of data transferred to Buffer.
95+
/// On output with a return code of EFI_BUFFER_TOO_SMALL, the size of
96+
/// Buffer required to retrieve the requested file.
97+
/// - `buffer` The memory buffer to transfer the file to. If Buffer is NULL,
98+
/// then the size of the requested file is returned in BufferSize.
99+
///
100+
/// # Errors
101+
/// - `uefi::status::EFI_SUCCESS` The file was loaded.
102+
/// - `uefi::status::EFI_UNSUPPORTED` BootPolicy is TRUE.
103+
/// - `uefi::status::EFI_INVALID_PARAMETER` FilePath is not a valid device
104+
/// path, or BufferSize is NULL.
105+
/// - `uefi::status::EFI_NO_MEDIA` No medium was present to load the file.
106+
/// - `uefi::status::EFI_DEVICE_ERROR` The file was not loaded due to a
107+
/// device error.
108+
/// - `uefi::status::EFI_NO_RESPONSE` The remote system did not respond.
109+
/// - `uefi::status::EFI_NOT_FOUND` The file was not found.
110+
/// - `uefi::status::EFI_ABORTED` The file load process was manually
111+
/// cancelled.
112+
/// - `uefi::status::EFI_BUFFER_TOO_SMALL` The BufferSize is too small to
113+
/// read the current directory entry. BufferSize has been updated with the
114+
/// size needed to complete the request.
24115
pub load_file: unsafe extern "efiapi" fn(
25116
this: *mut LoadFile2Protocol,
26117
file_path: *const DevicePathProtocol,

uefi/src/mem/util.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ use core::fmt::Debug;
88
use core::slice;
99

1010
#[cfg(not(feature = "unstable"))]
11-
use ::alloc::alloc::{alloc, dealloc};
11+
use {
12+
::alloc::alloc::{alloc, dealloc}
13+
};
14+
#[cfg(feature = "unstable")]
15+
use {
16+
alloc::alloc::Global
17+
};
1218

1319
#[cfg(feature = "unstable")]
1420
use {core::alloc::Allocator, core::ptr::NonNull};
@@ -39,7 +45,7 @@ pub(crate) fn make_boxed<
3945
// The UEFI data structure.
4046
Data: Align + ?Sized + Debug + 'a,
4147
F: FnMut(&'a mut [u8]) -> Result<&'a mut Data, Option<usize>>,
42-
#[cfg(feature = "unstable")] A: Allocator,
48+
#[cfg(feature = "unstable")] A: Allocator = Global,
4349
>(
4450
// A function to read the UEFI data structure into a provided buffer.
4551
mut fetch_data_fn: F,

uefi/src/proto/media/load_file.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//! LoadFile and LoadFile2 protocols.
2+
3+
use crate::mem::make_boxed;
4+
use crate::proto::device_path::DevicePath;
5+
use crate::proto::unsafe_protocol;
6+
use crate::StatusExt;
7+
#[cfg(all(feature = "alloc", feature = "unstable"))]
8+
use alloc::alloc::Global;
9+
#[cfg(feature = "alloc")]
10+
use alloc::boxed::Box;
11+
use uefi::Result;
12+
use uefi_raw::protocol::media::{LoadFile2Protocol, LoadFileProtocol};
13+
14+
/// TODO.
15+
#[derive(Debug)]
16+
#[repr(transparent)]
17+
#[unsafe_protocol(LoadFileProtocol::GUID)]
18+
pub struct LoadFile(LoadFileProtocol);
19+
20+
impl LoadFile {
21+
/// TODO.
22+
#[cfg(feature = "alloc")]
23+
pub fn load_file<'a>(&mut self, file_path: &DevicePath, boot_policy: bool) -> Result<Box<[u8]>> {
24+
let fetch_data_fn = |buf: &'a mut [u8]| {
25+
let mut size = buf.len();
26+
let status = unsafe {
27+
(self.0.load_file)(
28+
core::ptr::addr_of_mut!(*self).cast(),
29+
file_path.as_ffi_ptr().cast(),
30+
boot_policy,
31+
&mut size,
32+
buf.as_mut_ptr().cast(),
33+
)
34+
};
35+
status.to_result_with_err(|_| Some(size)).map(|_| buf)
36+
};
37+
38+
#[cfg(not(feature = "unstable"))]
39+
let file: Box<[u8]> = make_boxed::<[u8], _>(fetch_data_fn)?;
40+
41+
#[cfg(feature = "unstable")]
42+
let file = make_boxed::<[u8], _, _>(fetch_data_fn, Global)?;
43+
44+
Ok(file)
45+
}
46+
}
47+
48+
/// The Block I/O protocol.
49+
#[derive(Debug)]
50+
#[repr(transparent)]
51+
#[unsafe_protocol(LoadFile2Protocol::GUID)]
52+
pub struct LoadFile2(LoadFile2Protocol);
53+
54+
impl LoadFile2 {
55+
/// TODO.
56+
pub fn load_file<'a>(&mut self, file_path: &DevicePath) -> Result<Box<[u8]>> {
57+
let fetch_data_fn = |buf: &'a mut [u8]| {
58+
let mut size = buf.len();
59+
let status = unsafe {
60+
(self.0.load_file)(
61+
core::ptr::addr_of_mut!(*self).cast(),
62+
file_path.as_ffi_ptr().cast(),
63+
false /* always false - see spec */,
64+
&mut size,
65+
buf.as_mut_ptr().cast(),
66+
)
67+
};
68+
status.to_result_with_err(|_| Some(size)).map(|_| buf)
69+
};
70+
71+
#[cfg(not(feature = "unstable"))]
72+
let file: Box<[u8]> = make_boxed::<[u8], _>(fetch_data_fn)?;
73+
74+
#[cfg(feature = "unstable")]
75+
let file = make_boxed::<[u8], _, _>(fetch_data_fn, Global)?;
76+
77+
Ok(file)
78+
}
79+
}

uefi/src/proto/media/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ pub mod file;
99
pub mod block;
1010
pub mod disk;
1111
pub mod fs;
12+
pub mod load_file;
1213
pub mod partition;

0 commit comments

Comments
 (0)