iPXE
efi_image.c File Reference
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_snp.h>
#include <ipxe/efi/efi_download.h>
#include <ipxe/efi/efi_file.h>
#include <ipxe/efi/efi_path.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_wrap.h>
#include <ipxe/efi/efi_pxe.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_image.h>
#include <ipxe/efi/efi_shim.h>
#include <ipxe/efi/efi_fdt.h>
#include <ipxe/image.h>
#include <ipxe/init.h>
#include <ipxe/features.h>
#include <ipxe/uri.h>
#include <ipxe/console.h>

Go to the source code of this file.

Macros

#define EINFO_EEFI_LOAD
#define EINFO_EEFI_LOAD_PROHIBITED
#define EEFI_LOAD_PROHIBITED    __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )
#define EEFI_LOAD(efirc)
#define EINFO_EEFI_START
#define EEFI_START(efirc)

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (PERMITTED)
 FEATURE (FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1)
static EFI_DEVICE_PATH_PROTOCOLefi_image_path (struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent)
 Create device path for image.
static wchar_tefi_image_cmdline (struct image *image)
 Create command line for image.
__weak int efi_fdt_install (const char *cmdline __unused)
 Install EFI Flattened Device Tree table (when no FDT support is present)
__weak int efi_fdt_uninstall (void)
 Uninstall EFI Flattened Device Tree table (when no FDT support is present)
static int efi_image_exec (struct image *image)
 Execute EFI image.
static int efi_image_probe (struct image *image)
 Probe EFI image.
static int efi_pe_image_probe (struct image *image)
 Probe EFI PE image.
struct image_type efi_image_type[] __image_type (PROBE_NORMAL)
 EFI image types.

Macro Definition Documentation

◆ EINFO_EEFI_LOAD

#define EINFO_EEFI_LOAD
Value:
"Could not load image" )
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition errno.h:181
#define EINFO_EPLATFORM
Platform-generated base error.
Definition errno.h:692

Definition at line 48 of file efi_image.c.

48#define EINFO_EEFI_LOAD \
49 __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
50 "Could not load image" )

◆ EINFO_EEFI_LOAD_PROHIBITED

#define EINFO_EEFI_LOAD_PROHIBITED
Value:
"Image prohibited by security policy" )
#define EFI_SECURITY_VIOLATION
Enumeration of EFI_STATUS.
#define EINFO_EEFI_LOAD
Definition efi_image.c:48
#define __einfo_platformify(einfo_base, platform, desc)
Declare platform-generated error.
Definition errno.h:194

Definition at line 51 of file efi_image.c.

51#define EINFO_EEFI_LOAD_PROHIBITED \
52 __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION, \
53 "Image prohibited by security policy" )

◆ EEFI_LOAD_PROHIBITED

#define EEFI_LOAD_PROHIBITED    __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )

Definition at line 54 of file efi_image.c.

54#define EEFI_LOAD_PROHIBITED \
55 __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )

◆ EEFI_LOAD

#define EEFI_LOAD ( efirc)
Value:
#define EEFI_LOAD_PROHIBITED
Definition efi_image.c:54
#define EPLATFORM(einfo_base, platform,...)
Generate an error based on an external platform error code.
Definition errno.h:249

Definition at line 56 of file efi_image.c.

56#define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \
57 EEFI_LOAD_PROHIBITED )

Referenced by efi_image_exec(), and efi_image_probe().

◆ EINFO_EEFI_START

#define EINFO_EEFI_START
Value:
"Could not start image" )

Definition at line 58 of file efi_image.c.

58#define EINFO_EEFI_START \
59 __einfo_uniqify ( EINFO_EPLATFORM, 0x02, \
60 "Could not start image" )

◆ EEFI_START

#define EEFI_START ( efirc)
Value:
#define EINFO_EEFI_START
Definition efi_image.c:58

Definition at line 61 of file efi_image.c.

Referenced by efi_image_exec().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ FEATURE()

FEATURE ( FEATURE_IMAGE ,
"EFI" ,
DHCP_EB_FEATURE_EFI ,
1  )

◆ efi_image_path()

EFI_DEVICE_PATH_PROTOCOL * efi_image_path ( struct image * image,
EFI_DEVICE_PATH_PROTOCOL * parent )
static

Create device path for image.

Parameters
imageEFI image
parentParent device path
Return values
pathDevice path, or NULL on failure

The caller must eventually free() the device path.

Definition at line 73 of file efi_image.c.

73 {
75 FILEPATH_DEVICE_PATH *filepath;
77 size_t name_len;
78 size_t prefix_len;
79 size_t filepath_len;
80 size_t len;
81
82 /* Calculate device path lengths */
83 prefix_len = efi_path_len ( parent );
84 name_len = strlen ( image->name );
85 filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
86 ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
87 len = ( prefix_len + filepath_len + sizeof ( *end ) );
88
89 /* Allocate device path */
90 path = zalloc ( len );
91 if ( ! path )
92 return NULL;
93
94 /* Construct device path */
95 memcpy ( path, parent, prefix_len );
96 filepath = ( ( ( void * ) path ) + prefix_len );
97 filepath->Header.Type = MEDIA_DEVICE_PATH;
99 filepath->Header.Length[0] = ( filepath_len & 0xff );
100 filepath->Header.Length[1] = ( filepath_len >> 8 );
101 efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
102 "%s", image->name );
103 end = ( ( ( void * ) filepath ) + filepath_len );
105
106 return path;
107}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define MEDIA_FILEPATH_DP
File Path Media Device Path SubType.
#define SIZE_OF_FILEPATH_DEVICE_PATH
#define MEDIA_DEVICE_PATH
ring len
Length.
Definition dwmac.h:226
size_t efi_path_len(EFI_DEVICE_PATH_PROTOCOL *path)
Find length of device path (excluding terminator)
Definition efi_path.c:174
static void efi_path_terminate(EFI_DEVICE_PATH_PROTOCOL *end)
Terminate device path.
Definition efi_path.h:31
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
uint32_t end
Ending offset.
Definition netvsc.h:7
__WCHAR_TYPE__ wchar_t
Definition stddef.h:50
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition DevicePath.h:46
UINT8 Type
0x01 Hardware Device Path.
Definition DevicePath.h:47
UINT8 Length[2]
Specific Device Path data.
Definition DevicePath.h:59
UINT8 SubType
Varies by Type 0xFF End Entire Device Path, or 0x01 End This Instance of a Device Path and start a ne...
Definition DevicePath.h:54
CHAR16 PathName[1]
A NULL-terminated Path string including directory and file names.
EFI_DEVICE_PATH_PROTOCOL Header
An executable image.
Definition image.h:24
char * name
Name.
Definition image.h:38

References efi_path_len(), efi_path_terminate(), efi_snprintf(), end, FILEPATH_DEVICE_PATH::Header, len, EFI_DEVICE_PATH_PROTOCOL::Length, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, memcpy(), image::name, NULL, FILEPATH_DEVICE_PATH::PathName, SIZE_OF_FILEPATH_DEVICE_PATH, strlen(), EFI_DEVICE_PATH_PROTOCOL::SubType, EFI_DEVICE_PATH_PROTOCOL::Type, and zalloc().

Referenced by efi_image_exec().

◆ efi_image_cmdline()

wchar_t * efi_image_cmdline ( struct image * image)
static

Create command line for image.

Parameters
imageEFI image
Return values
cmdlineCommand line, or NULL on failure

Definition at line 115 of file efi_image.c.

115 {
116 wchar_t *cmdline;
117
118 /* Allocate and construct command line */
119 if ( efi_asprintf ( &cmdline, "%s%s%s", image->name,
120 ( image->cmdline ? " " : "" ),
121 ( image->cmdline ? image->cmdline : "" ) ) < 0 ) {
122 return NULL;
123 }
124
125 return cmdline;
126}
int efi_asprintf(wchar_t **wstrp, const char *fmt,...)
Write a formatted string to newly allocated memory.
uint32_t cmdline
Definition multiboot.h:4
char * cmdline
Command line to pass to image.
Definition image.h:43

References cmdline, image::cmdline, efi_asprintf(), image::name, and NULL.

Referenced by efi_image_exec().

◆ efi_fdt_install()

__weak int efi_fdt_install ( const char *cmdline __unused)

Install EFI Flattened Device Tree table (when no FDT support is present)

Parameters
cmdlineCommand line, or NULL
Return values
rcReturn status code

Definition at line 134 of file efi_image.c.

134 {
135 return 0;
136}

References __unused, __weak, and cmdline.

Referenced by efi_image_exec().

◆ efi_fdt_uninstall()

__weak int efi_fdt_uninstall ( void )

Uninstall EFI Flattened Device Tree table (when no FDT support is present)

Return values
rcReturn status code

Definition at line 143 of file efi_image.c.

143 {
144 return 0;
145}

References __weak.

Referenced by efi_image_exec().

◆ efi_image_exec()

int efi_image_exec ( struct image * image)
static

Execute EFI image.

Parameters
imageEFI image
Return values
rcReturn status code

Definition at line 153 of file efi_image.c.

153 {
154 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
155 struct efi_snp_device *snpdev;
158 struct image *shim;
159 struct image *exec;
163 wchar_t *cmdline;
164 unsigned int toggle;
165 EFI_STATUS efirc;
166 int rc;
167
168 /* Find an appropriate device handle to use */
169 snpdev = last_opened_snpdev();
170 if ( ! snpdev ) {
171 DBGC ( image, "EFIIMAGE %s could not identify SNP device\n",
172 image->name );
173 rc = -ENODEV;
174 goto err_no_snpdev;
175 }
176 device = snpdev->handle;
177
178 /* Use shim instead of directly executing image if applicable */
179 shim = ( efi_can_load ( image ) ?
180 NULL : find_image_tag ( &efi_shim ) );
181 exec = ( shim ? shim : image );
182 if ( shim ) {
183 DBGC ( image, "EFIIMAGE %s executing via %s\n",
184 image->name, shim->name );
185 }
186
187 /* Re-register as a hidden image to allow for access via file I/O */
188 toggle = ( ~image->flags & IMAGE_HIDDEN );
190 if ( ( rc = register_image ( image ) ) != 0 )
191 goto err_register_image;
192
193 /* Install file I/O protocols */
194 if ( ( rc = efi_file_install ( device ) ) != 0 ) {
195 DBGC ( image, "EFIIMAGE %s could not install file protocol: "
196 "%s\n", image->name, strerror ( rc ) );
197 goto err_file_install;
198 }
199
200 /* Install PXE base code protocol */
201 if ( ( rc = efi_pxe_install ( device, snpdev->netdev ) ) != 0 ){
202 DBGC ( image, "EFIIMAGE %s could not install PXE protocol: "
203 "%s\n", image->name, strerror ( rc ) );
204 goto err_pxe_install;
205 }
206
207 /* Install iPXE download protocol */
208 if ( ( rc = efi_download_install ( device ) ) != 0 ) {
209 DBGC ( image, "EFIIMAGE %s could not install iPXE download "
210 "protocol: %s\n", image->name, strerror ( rc ) );
211 goto err_download_install;
212 }
213
214 /* Install Flattened Device Tree table */
215 if ( ( rc = efi_fdt_install ( image->cmdline ) ) != 0 ) {
216 DBGC ( image, "EFIIMAGE %s could not install FDT: %s\n",
217 image->name, strerror ( rc ) );
218 goto err_fdt_install;
219 }
220
221 /* Create device path for image */
222 path = efi_image_path ( exec, snpdev->path );
223 if ( ! path ) {
224 DBGC ( image, "EFIIMAGE %s could not create device path\n",
225 image->name );
226 rc = -ENOMEM;
227 goto err_image_path;
228 }
229
230 /* Create command line for image */
232 if ( ! cmdline ) {
233 DBGC ( image, "EFIIMAGE %s could not create command line\n",
234 image->name );
235 rc = -ENOMEM;
236 goto err_cmdline;
237 }
238
239 /* Install shim special handling if applicable */
240 if ( shim &&
241 ( ( rc = efi_shim_install ( shim, device, &cmdline ) ) != 0 ) ) {
242 DBGC ( image, "EFIIMAGE %s could not install shim handling: "
243 "%s\n", image->name, strerror ( rc ) );
244 goto err_shim_install;
245 }
246
247 /* Attempt loading image
248 *
249 * LoadImage() does not (allegedly) modify the image content,
250 * but requires a non-const pointer to SourceBuffer. We
251 * therefore use the .rwdata field rather than .data.
252 */
253 handle = NULL;
254 if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
255 exec->rwdata, exec->len,
256 &handle ) ) != 0 ) {
257 /* Not an EFI image */
258 rc = -EEFI_LOAD ( efirc );
259 DBGC ( image, "EFIIMAGE %s could not load: %s\n",
260 image->name, strerror ( rc ) );
261 if ( efirc == EFI_SECURITY_VIOLATION ) {
262 goto err_load_image_security_violation;
263 } else {
264 goto err_load_image;
265 }
266 }
267
268 /* Get the loaded image protocol for the newly loaded image */
270 &loaded ) ) != 0 ) {
271 /* Should never happen */
272 goto err_open_protocol;
273 }
274
275 /* Some EFI 1.10 implementations seem not to fill in DeviceHandle */
276 if ( loaded->DeviceHandle == NULL ) {
277 DBGC ( image, "EFIIMAGE %s filling in missing DeviceHandle\n",
278 image->name );
279 loaded->DeviceHandle = device;
280 }
281
282 /* Sanity checks */
283 assert ( loaded->ParentHandle == efi_image_handle );
284 assert ( loaded->DeviceHandle == device );
285 assert ( loaded->LoadOptionsSize == 0 );
286 assert ( loaded->LoadOptions == NULL );
287
288 /* Record image code type */
289 type = loaded->ImageCodeType;
290
291 /* Set command line */
292 loaded->LoadOptions = cmdline;
293 loaded->LoadOptionsSize =
294 ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) );
295
296 /* Release network devices for use via SNP */
298
299 /* Wrap calls made by the loaded image (for debugging) */
301
302 /* Reset console since image will probably use it */
304
305 /* Assume that image may cause SNP device to be removed */
306 snpdev = NULL;
307
308 /* Start the image */
309 if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
310 rc = -EEFI_START ( efirc );
311 DBGC ( image, "EFIIMAGE %s could not start (or returned with "
312 "error): %s\n", image->name, strerror ( rc ) );
313 goto err_start_image;
314 }
315
316 /* If image was a driver, connect it up to anything available */
317 if ( type == EfiBootServicesCode ) {
318 DBGC ( image, "EFIIMAGE %s connecting drivers\n", image->name );
320 }
321
322 /* Success */
323 rc = 0;
324
325 err_start_image:
326 efi_unwrap();
328 err_open_protocol:
329 /* If there was no error, then the image must have been
330 * started and returned successfully. It either unloaded
331 * itself, or it intended to remain loaded (e.g. it was a
332 * driver). We therefore do not unload successful images.
333 *
334 * If there was an error, attempt to unload the image. This
335 * may not work. In particular, there is no way to tell
336 * whether an error returned from StartImage() was due to
337 * being unable to start the image (in which case we probably
338 * should call UnloadImage()), or due to the image itself
339 * returning an error (in which case we probably should not
340 * call UnloadImage()). We therefore ignore any failures from
341 * the UnloadImage() call itself.
342 */
343 err_load_image_security_violation:
344 if ( rc != 0 )
345 bs->UnloadImage ( handle );
346 err_load_image:
347 if ( shim )
349 err_shim_install:
350 free ( cmdline );
351 err_cmdline:
352 free ( path );
353 err_image_path:
355 err_fdt_install:
357 err_download_install:
359 err_pxe_install:
361 err_file_install:
363 err_register_image:
364 image->flags ^= toggle;
365 err_no_snpdev:
366 return rc;
367}
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
EFI_MEMORY_TYPE
Enumeration of memory types introduced in UEFI.
@ EfiBootServicesCode
The code portions of a loaded Boot Services Driver.
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
void efi_download_uninstall(EFI_HANDLE handle)
Uninstall iPXE download protocol.
int efi_download_install(EFI_HANDLE handle)
Install iPXE download protocol.
void efi_driver_reconnect_all(void)
Reconnect original EFI drivers to all possible devices.
Definition efi_driver.c:659
int efi_file_install(EFI_HANDLE handle)
Install EFI simple file system protocol.
Definition efi_file.c:1116
void efi_file_uninstall(EFI_HANDLE handle)
Uninstall EFI simple file system protocol.
Definition efi_file.c:1212
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition efi_guid.c:273
__weak int efi_fdt_uninstall(void)
Uninstall EFI Flattened Device Tree table (when no FDT support is present)
Definition efi_image.c:143
__weak int efi_fdt_install(const char *cmdline __unused)
Install EFI Flattened Device Tree table (when no FDT support is present)
Definition efi_image.c:134
#define EEFI_LOAD(efirc)
Definition efi_image.c:56
static wchar_t * efi_image_cmdline(struct image *image)
Create command line for image.
Definition efi_image.c:115
static EFI_DEVICE_PATH_PROTOCOL * efi_image_path(struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent)
Create device path for image.
Definition efi_image.c:73
#define EEFI_START(efirc)
Definition efi_image.c:61
static int efi_can_load(struct image *image)
Check if EFI image can be loaded directly.
Definition efi_image.h:23
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition efi_init.c:36
void efi_pxe_uninstall(EFI_HANDLE handle)
Uninstall PXE base code protocol.
Definition efi_pxe.c:1632
int efi_pxe_install(EFI_HANDLE handle, struct net_device *netdev)
Install PXE base code protocol.
Definition efi_pxe.c:1549
void efi_shim_uninstall(void)
Uninstall UEFI shim special handling.
Definition efi_shim.c:375
int efi_shim_install(struct image *shim, EFI_HANDLE handle, wchar_t **cmdline)
Install UEFI shim special handling.
Definition efi_shim.c:341
struct efi_snp_device * last_opened_snpdev(void)
Get most recently opened SNP device.
Definition efi_snp.c:2119
static void efi_snp_claim(void)
Claim network devices for use by iPXE.
Definition efi_snp.h:92
static void efi_snp_release(void)
Release network devices for use via SNP.
Definition efi_snp.h:100
void efi_unwrap(void)
Remove boot services table wrapper.
Definition efi_wrap.c:1543
void efi_wrap_image(EFI_HANDLE handle)
Wrap calls made by a newly loaded image.
Definition efi_wrap.c:1567
uint32_t type
Operating system type.
Definition ena.h:1
#define DBGC(...)
Definition compiler.h:505
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENODEV
No such device.
Definition errno.h:510
void unregister_image(struct image *image)
Unregister executable image.
Definition image.c:358
struct image * find_image_tag(struct image_tag *tag)
Find image by tag.
Definition image.c:393
int register_image(struct image *image)
Register executable image.
Definition image.c:315
#define IMAGE_HIDDEN
Image will be hidden from enumeration.
Definition image.h:86
static void console_reset(void)
Reset console.
Definition console.h:215
#define efi_open(handle, protocol, interface)
Open protocol for ephemeral use.
Definition efi.h:444
#define EFI_HANDLE
Definition efi.h:53
EFI_SYSTEM_TABLE * efi_systab
uint16_t handle
Handle.
Definition smbios.h:5
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
int shim(struct image *image, int require_loader, int allow_pxe, int allow_sbat)
Set shim image.
Definition shimmgmt.c:46
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
EFI Boot Services Table.
Definition UefiSpec.h:1931
EFI_IMAGE_START StartImage
Definition UefiSpec.h:1979
EFI_IMAGE_UNLOAD UnloadImage
Definition UefiSpec.h:1981
EFI_IMAGE_LOAD LoadImage
Definition UefiSpec.h:1978
Can be used on any image handle to obtain information about the loaded image.
Definition LoadedImage.h:46
VOID * LoadOptions
A pointer to the image's binary load options.
Definition LoadedImage.h:65
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition LoadedImage.h:56
UINT32 LoadOptionsSize
The size in bytes of LoadOptions.
Definition LoadedImage.h:64
EFI_MEMORY_TYPE ImageCodeType
The memory type that the code sections were loaded as.
Definition LoadedImage.h:72
EFI_HANDLE ParentHandle
Parent image's image handle.
Definition LoadedImage.h:49
A hardware device.
Definition device.h:77
An SNP device.
Definition efi_snp.h:29
EFI_HANDLE handle
EFI device handle.
Definition efi_snp.h:37
EFI_DEVICE_PATH_PROTOCOL * path
The device path.
Definition efi_snp.h:79
struct net_device * netdev
The underlying iPXE network device.
Definition efi_snp.h:33
unsigned int flags
Flags.
Definition image.h:40
size_t len
Length of raw file image.
Definition image.h:56
void * rwdata
Writable data.
Definition image.h:53
#define FALSE
Definition tlan.h:45
size_t wcslen(const wchar_t *string)
Calculate length of wide-character string.
Definition wchar.c:57

References assert, cmdline, image::cmdline, console_reset(), DBGC, EFI_LOADED_IMAGE_PROTOCOL::DeviceHandle, EEFI_LOAD, EEFI_START, efi_can_load(), efi_download_install(), efi_download_uninstall(), efi_driver_reconnect_all(), efi_fdt_install(), efi_fdt_uninstall(), efi_file_install(), efi_file_uninstall(), EFI_HANDLE, efi_image_cmdline(), efi_image_handle, efi_image_path(), efi_loaded_image_protocol_guid, efi_open, efi_pxe_install(), efi_pxe_uninstall(), EFI_SECURITY_VIOLATION, efi_shim_install(), efi_shim_uninstall(), efi_snp_claim(), efi_snp_release(), efi_systab, efi_unwrap(), efi_wrap_image(), EfiBootServicesCode, ENODEV, ENOMEM, FALSE, find_image_tag(), image::flags, free, efi_snp_device::handle, handle, IMAGE_HIDDEN, EFI_LOADED_IMAGE_PROTOCOL::ImageCodeType, last_opened_snpdev(), image::len, EFI_BOOT_SERVICES::LoadImage, EFI_LOADED_IMAGE_PROTOCOL::LoadOptions, EFI_LOADED_IMAGE_PROTOCOL::LoadOptionsSize, image::name, efi_snp_device::netdev, NULL, EFI_LOADED_IMAGE_PROTOCOL::ParentHandle, efi_snp_device::path, rc, register_image(), image::rwdata, shim(), EFI_BOOT_SERVICES::StartImage, strerror(), type, EFI_BOOT_SERVICES::UnloadImage, unregister_image(), and wcslen().

Referenced by __image_type().

◆ efi_image_probe()

int efi_image_probe ( struct image * image)
static

Probe EFI image.

Parameters
imageEFI file
Return values
rcReturn status code

Definition at line 375 of file efi_image.c.

375 {
376 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
377 static EFI_DEVICE_PATH_PROTOCOL empty_path = {
378 .Type = END_DEVICE_PATH_TYPE,
380 .Length[0] = sizeof ( empty_path ),
381 };
383 EFI_STATUS efirc;
384 int rc;
385
386 /* Attempt loading image
387 *
388 * LoadImage() does not (allegedly) modify the image content,
389 * but requires a non-const pointer to SourceBuffer. We
390 * therefore use the .rwdata field rather than .data.
391 */
392 handle = NULL;
393 if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, &empty_path,
395 &handle ) ) != 0 ) {
396 /* Not an EFI image */
397 rc = -EEFI_LOAD ( efirc );
398 DBGC ( image, "EFIIMAGE %s could not load: %s\n",
399 image->name, strerror ( rc ) );
400 if ( efirc == EFI_SECURITY_VIOLATION ) {
401 goto err_load_image_security_violation;
402 } else {
403 goto err_load_image;
404 }
405 }
406
407 /* Unload the image. We can't leave it loaded, because we
408 * have no "unload" operation.
409 */
410 bs->UnloadImage ( handle );
411
412 return 0;
413
414 err_load_image_security_violation:
415 bs->UnloadImage ( handle );
416 err_load_image:
417 return rc;
418}
#define END_ENTIRE_DEVICE_PATH_SUBTYPE
#define END_DEVICE_PATH_TYPE

References DBGC, EEFI_LOAD, EFI_HANDLE, efi_image_handle, EFI_SECURITY_VIOLATION, efi_systab, END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, FALSE, handle, image::len, EFI_BOOT_SERVICES::LoadImage, image::name, NULL, rc, image::rwdata, strerror(), and EFI_BOOT_SERVICES::UnloadImage.

Referenced by __image_type().

◆ efi_pe_image_probe()

int efi_pe_image_probe ( struct image * image)
static

Probe EFI PE image.

Parameters
imageEFI file
Return values
rcReturn status code

The extremely broken UEFI Secure Boot model provides no way for us to unambiguously determine that a valid EFI executable image was rejected by LoadImage() because it failed signature verification. We must therefore use heuristics to guess whether not an image that was rejected by LoadImage() could still be loaded via a separate PE loader such as the UEFI shim.

Definition at line 433 of file efi_image.c.

433 {
434 const UINT16 magic = ( ( sizeof ( UINTN ) == sizeof ( uint32_t ) ) ?
437 const EFI_IMAGE_DOS_HEADER *dos;
439
440 /* Check for existence of DOS header */
441 if ( image->len < sizeof ( *dos ) ) {
442 DBGC ( image, "EFIIMAGE %s too short for DOS header\n",
443 image->name );
444 return -ENOEXEC;
445 }
446 dos = image->data;
447 if ( dos->e_magic != EFI_IMAGE_DOS_SIGNATURE ) {
448 DBGC ( image, "EFIIMAGE %s missing MZ signature\n",
449 image->name );
450 return -ENOEXEC;
451 }
452
453 /* Check for existence of PE header */
454 if ( ( image->len < dos->e_lfanew ) ||
455 ( ( image->len - dos->e_lfanew ) < sizeof ( *pe ) ) ) {
456 DBGC ( image, "EFIIMAGE %s too short for PE header\n",
457 image->name );
458 return -ENOEXEC;
459 }
460 pe = ( image->data + dos->e_lfanew );
462 DBGC ( image, "EFIIMAGE %s missing PE signature\n",
463 image->name );
464 return -ENOEXEC;
465 }
466
467 /* Check PE header magic */
468 if ( pe->Pe32.OptionalHeader.Magic != magic ) {
469 DBGC ( image, "EFIIMAGE %s incorrect magic %04x\n",
471 return -ENOEXEC;
472 }
473
474 return 0;
475}
unsigned short UINT16
2-byte unsigned value.
UINT64 UINTN
Unsigned value of native width.
#define EFI_IMAGE_NT_SIGNATURE
Definition PeImage.h:53
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition PeImage.h:145
#define EFI_IMAGE_DOS_SIGNATURE
Definition PeImage.h:50
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition PeImage.h:196
unsigned int uint32_t
Definition stdint.h:12
uint16_t magic
Magic signature.
Definition bzimage.h:1
#define ENOEXEC
Exec format error.
Definition errno.h:520
PE images can start with an optional DOS header, so if an image is run under DOS it can print an erro...
Definition PeImage.h:59
UINT32 e_lfanew
File address of new exe header.
Definition PeImage.h:78
UINT16 e_magic
Magic number.
Definition PeImage.h:60
EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition PeImage.h:247
UINT16 Magic
Standard fields.
Definition PeImage.h:154
const void * data
Read-only data.
Definition image.h:51
Union of PE32, PE32+, and TE headers.
Definition PeImage.h:805
EFI_IMAGE_NT_HEADERS32 Pe32
Definition PeImage.h:806

References image::data, DBGC, EFI_IMAGE_DOS_HEADER::e_lfanew, EFI_IMAGE_DOS_HEADER::e_magic, EFI_IMAGE_DOS_SIGNATURE, EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC, EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC, EFI_IMAGE_NT_SIGNATURE, ENOEXEC, image::len, EFI_IMAGE_OPTIONAL_HEADER32::Magic, magic, image::name, EFI_IMAGE_NT_HEADERS32::OptionalHeader, EFI_IMAGE_OPTIONAL_HEADER_UNION::Pe32, and EFI_IMAGE_NT_HEADERS32::Signature.

Referenced by __image_type().

◆ __image_type()

struct image_type efi_image_type[] __image_type ( PROBE_NORMAL )