1 //! LoadFile and LoadFile2 protocols. 2 3 use crate::proto::unsafe_protocol; 4 #[cfg(all(feature = "alloc", feature = "unstable"))] 5 use alloc::alloc::Global; 6 use uefi_raw::protocol::media::{LoadFile2Protocol, LoadFileProtocol}; 7 #[cfg(feature = "alloc")] 8 use { 9 crate::{mem::make_boxed, proto::device_path::DevicePath, Result, StatusExt}, 10 alloc::boxed::Box, 11 uefi::proto::BootPolicy, 12 }; 13 14 /// Load File Protocol. 15 /// 16 /// Used to obtain files, that are primarily boot options, from arbitrary 17 /// devices. 18 /// 19 /// # UEFI Spec Description 20 /// The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from 21 /// arbitrary devices. 22 /// 23 /// When the firmware is attempting to load a file, it first attempts to use the 24 /// device’s Simple File System protocol to read the file. If the file system 25 /// protocol is found, the firmware implements the policy of interpreting the 26 /// File Path value of the file being loaded. If the device does not support the 27 /// file system protocol, the firmware then attempts to read the file via the 28 /// EFI_LOAD_FILE_PROTOCOL and the LoadFile() function. In this case the 29 /// LoadFile() function implements the policy of interpreting the File Path 30 /// value. 31 #[derive(Debug)] 32 #[repr(transparent)] 33 #[unsafe_protocol(LoadFileProtocol::GUID)] 34 pub struct LoadFile(LoadFileProtocol); 35 36 impl LoadFile { 37 /// Causes the driver to load a specified file. 38 /// 39 /// # Parameters 40 /// - `file_path` The device specific path of the file to load. 41 /// - `boot_policy` The [`BootPolicy`] to use. 42 /// 43 /// # Errors 44 /// - `uefi::status::EFI_SUCCESS` The file was loaded. 45 /// - `uefi::status::EFI_UNSUPPORTED` The device does not support the 46 /// provided BootPolicy. 47 /// - `uefi::status::EFI_INVALID_PARAMETER` FilePath is not a valid device 48 /// path, or BufferSize is NULL. 49 /// - `uefi::status::EFI_NO_MEDIA` No medium was present to load the file. 50 /// - `uefi::status::EFI_DEVICE_ERROR` The file was not loaded due to a 51 /// device error. 52 /// - `uefi::status::EFI_NO_RESPONSE` The remote system did not respond. 53 /// - `uefi::status::EFI_NOT_FOUND` The file was not found. 54 /// - `uefi::status::EFI_ABORTED` The file load process was manually 55 /// cancelled. 56 /// - `uefi::status::EFI_BUFFER_TOO_SMALL` The BufferSize is too small to 57 /// read the current directory entry. BufferSize has been updated with the 58 /// size needed to complete the request. 59 /// - `uefi::status::EFI_WARN_FILE_SYSTEM` The resulting Buffer contains 60 /// UEFI-compliant file system. 61 /// 62 /// [`BootPolicy`]: uefi::proto::BootPolicy 63 #[cfg(feature = "alloc")] 64 #[allow(clippy::extra_unused_lifetimes)] // false positive, it is used load_file<'a>( &mut self, file_path: &DevicePath, boot_policy: BootPolicy, ) -> Result<Box<[u8]>>65 pub fn load_file<'a>( 66 &mut self, 67 file_path: &DevicePath, 68 boot_policy: BootPolicy, 69 ) -> Result<Box<[u8]>> { 70 let this = core::ptr::addr_of_mut!(*self).cast(); 71 72 let fetch_data_fn = |buf: &'a mut [u8]| { 73 let mut size = buf.len(); 74 let status = unsafe { 75 (self.0.load_file)( 76 this, 77 file_path.as_ffi_ptr().cast(), 78 boot_policy.into(), 79 &mut size, 80 buf.as_mut_ptr().cast(), 81 ) 82 }; 83 status.to_result_with_err(|_| Some(size)).map(|_| buf) 84 }; 85 86 #[cfg(not(feature = "unstable"))] 87 let file: Box<[u8]> = make_boxed::<[u8], _>(fetch_data_fn)?; 88 89 #[cfg(feature = "unstable")] 90 let file = make_boxed::<[u8], _, _>(fetch_data_fn, Global)?; 91 92 Ok(file) 93 } 94 } 95 96 /// Load File2 Protocol. 97 /// 98 /// The Load File2 protocol is used to obtain files from arbitrary devices that 99 /// are not boot options. 100 /// 101 /// # UEFI Spec Description 102 /// 103 /// The EFI_LOAD_FILE2_PROTOCOL is a simple protocol used to obtain files from 104 /// arbitrary devices that are not boot options. It is used by LoadImage() when 105 /// its BootOption parameter is FALSE and the FilePath does not have an instance 106 /// of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. 107 #[derive(Debug)] 108 #[repr(transparent)] 109 #[unsafe_protocol(LoadFile2Protocol::GUID)] 110 pub struct LoadFile2(LoadFile2Protocol); 111 112 impl LoadFile2 { 113 /// Causes the driver to load a specified file. 114 /// 115 /// # Parameters 116 /// - `file_path` The device specific path of the file to load. 117 /// 118 /// # Errors 119 /// - `uefi::status::EFI_SUCCESS` The file was loaded. 120 /// - `uefi::status::EFI_UNSUPPORTED` BootPolicy is TRUE. 121 /// - `uefi::status::EFI_INVALID_PARAMETER` FilePath is not a valid device 122 /// path, or BufferSize is NULL. 123 /// - `uefi::status::EFI_NO_MEDIA` No medium was present to load the file. 124 /// - `uefi::status::EFI_DEVICE_ERROR` The file was not loaded due to a 125 /// device error. 126 /// - `uefi::status::EFI_NO_RESPONSE` The remote system did not respond. 127 /// - `uefi::status::EFI_NOT_FOUND` The file was not found. 128 /// - `uefi::status::EFI_ABORTED` The file load process was manually 129 /// cancelled. 130 /// - `uefi::status::EFI_BUFFER_TOO_SMALL` The BufferSize is too small to 131 /// read the current directory entry. BufferSize has been updated with the 132 /// size needed to complete the request. 133 #[cfg(feature = "alloc")] 134 #[allow(clippy::extra_unused_lifetimes)] // false positive, it is used load_file<'a>(&mut self, file_path: &DevicePath) -> Result<Box<[u8]>>135 pub fn load_file<'a>(&mut self, file_path: &DevicePath) -> Result<Box<[u8]>> { 136 let this = core::ptr::addr_of_mut!(*self).cast(); 137 138 let fetch_data_fn = |buf: &'a mut [u8]| { 139 let mut size = buf.len(); 140 let status = unsafe { 141 (self.0.load_file)( 142 this, 143 file_path.as_ffi_ptr().cast(), 144 false, /* always false - see spec */ 145 &mut size, 146 buf.as_mut_ptr().cast(), 147 ) 148 }; 149 status.to_result_with_err(|_| Some(size)).map(|_| buf) 150 }; 151 152 #[cfg(not(feature = "unstable"))] 153 let file: Box<[u8]> = make_boxed::<[u8], _>(fetch_data_fn)?; 154 155 #[cfg(feature = "unstable")] 156 let file = make_boxed::<[u8], _, _>(fetch_data_fn, Global)?; 157 158 Ok(file) 159 } 160 } 161