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/efi/efi_utils.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_uripath (struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent)
 Create a URI device path for image.
static EFI_DEVICE_PATH_PROTOCOLefi_image_filepath (struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent)
 Create a file 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 49 of file efi_image.c.

49#define EINFO_EEFI_LOAD \
50 __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
51 "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:49
#define __einfo_platformify(einfo_base, platform, desc)
Declare platform-generated error.
Definition errno.h:194

Definition at line 52 of file efi_image.c.

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

◆ EEFI_LOAD_PROHIBITED

#define EEFI_LOAD_PROHIBITED    __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )

Definition at line 55 of file efi_image.c.

55#define EEFI_LOAD_PROHIBITED \
56 __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )

◆ EEFI_LOAD

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

Definition at line 57 of file efi_image.c.

57#define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \
58 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 59 of file efi_image.c.

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

◆ EEFI_START

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

Definition at line 62 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_uripath()

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

Create a URI 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 74 of file efi_image.c.

74 {
76 URI_DEVICE_PATH *uripath;
78 size_t uri_len;
79 size_t prefix_len;
80 size_t uripath_len;
81 size_t len;
82
83 /* Calculate device path lengths */
84 prefix_len = efi_path_len ( parent );
85 uri_len = format_uri ( image->uri, NULL, 0 );
86 uripath_len = ( sizeof ( *uripath ) + uri_len + 1 /* NUL */ );
87 len = ( prefix_len + uripath_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 uripath = ( ( ( void * ) path ) + prefix_len );
98 uripath->Header.SubType = MSG_URI_DP;
99 uripath->Header.Length[0] = ( uripath_len & 0xff );
100 uripath->Header.Length[1] = ( uripath_len >> 8 );
101 format_uri ( image->uri, uripath->Uri, ( uri_len + 1 /* NUL */ ) );
102 end = ( ( ( void * ) uripath ) + uripath_len );
104
105 return path;
106}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define MSG_URI_DP
Uniform Resource Identifiers (URI) Device Path SubType.
Definition DevicePath.h:882
#define MESSAGING_DEVICE_PATH
Messaging Device Paths.
Definition DevicePath.h:324
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
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
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
EFI_DEVICE_PATH_PROTOCOL Header
Definition DevicePath.h:884
CHAR8 Uri[]
Instance of the URI pursuant to RFC 3986.
Definition DevicePath.h:888
An executable image.
Definition image.h:24
struct uri * uri
URI of image.
Definition image.h:32
size_t format_uri(const struct uri *uri, char *buf, size_t len)
Format URI.
Definition uri.c:473

References efi_path_len(), efi_path_terminate(), end, format_uri(), URI_DEVICE_PATH::Header, len, EFI_DEVICE_PATH_PROTOCOL::Length, memcpy(), MESSAGING_DEVICE_PATH, MSG_URI_DP, NULL, EFI_DEVICE_PATH_PROTOCOL::SubType, EFI_DEVICE_PATH_PROTOCOL::Type, URI_DEVICE_PATH::Uri, image::uri, and zalloc().

Referenced by efi_image_exec().

◆ efi_image_filepath()

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

Create a file 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 118 of file efi_image.c.

118 {
120 FILEPATH_DEVICE_PATH *filepath;
122 size_t name_len;
123 size_t prefix_len;
124 size_t filepath_len;
125 size_t len;
126
127 /* Calculate device path lengths */
128 prefix_len = efi_path_len ( parent );
129 name_len = strlen ( image->name );
130 filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
131 ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
132 len = ( prefix_len + filepath_len + sizeof ( *end ) );
133
134 /* Allocate device path */
135 path = zalloc ( len );
136 if ( ! path )
137 return NULL;
138
139 /* Construct device path */
140 memcpy ( path, parent, prefix_len );
141 filepath = ( ( ( void * ) path ) + prefix_len );
142 filepath->Header.Type = MEDIA_DEVICE_PATH;
143 filepath->Header.SubType = MEDIA_FILEPATH_DP;
144 filepath->Header.Length[0] = ( filepath_len & 0xff );
145 filepath->Header.Length[1] = ( filepath_len >> 8 );
146 efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
147 "%s", image->name );
148 end = ( ( ( void * ) filepath ) + filepath_len );
150
151 return path;
152}
#define MEDIA_FILEPATH_DP
File Path Media Device Path SubType.
#define SIZE_OF_FILEPATH_DEVICE_PATH
#define MEDIA_DEVICE_PATH
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
__WCHAR_TYPE__ wchar_t
Definition stddef.h:50
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
CHAR16 PathName[1]
A NULL-terminated Path string including directory and file names.
EFI_DEVICE_PATH_PROTOCOL Header
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 160 of file efi_image.c.

160 {
161 wchar_t *cmdline;
162
163 /* Allocate and construct command line */
164 if ( efi_asprintf ( &cmdline, "%s%s%s", image->name,
165 ( image->cmdline ? " " : "" ),
166 ( image->cmdline ? image->cmdline : "" ) ) < 0 ) {
167 return NULL;
168 }
169
170 return cmdline;
171}
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 179 of file efi_image.c.

179 {
180 return 0;
181}

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 188 of file efi_image.c.

188 {
189 return 0;
190}

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 198 of file efi_image.c.

198 {
199 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
200 struct efi_snp_device *snpdev;
201 struct net_device *netdev;
202 EFI_DEVICE_PATH_PROTOCOL *basepath;
206 struct image *shim;
207 struct image *exec;
208 EFI_HANDLE parent;
212 wchar_t *cmdline;
213 unsigned int toggle;
214 EFI_STATUS efirc;
215 int rc;
216
217 /* Find an appropriate parent device handle to use */
218 snpdev = last_opened_snpdev();
219 if ( snpdev ) {
220 /* We have a netX: use this as the base device */
221 parent = snpdev->handle;
222 basepath = snpdev->path;
223 netdev = netdev_get ( snpdev->netdev );
224 DBGC ( image, "EFIIMAGE %s using %s %s\n", image->name,
225 netdev->name, efi_devpath_text ( basepath ) );
226 } else {
227 /* We have no netX: fall back to using our own loaded
228 * image's device.
229 */
230 parent = efi_loaded_image->DeviceHandle;
231 basepath = efi_loaded_image_path;
232 netdev = NULL;
233 if ( efi_test ( parent, &efi_device_path_protocol_guid ) != 0 )
234 parent = NULL;
235 DBGC ( image, "EFIIMAGE %s using %s%s\n",
236 image->name, efi_devpath_text ( basepath ),
237 ( parent ? "" : " (removed)" ) );
238 }
239
240 /* Construct URI device path */
241 devpath = efi_image_uripath ( image, basepath );
242 if ( ! devpath ) {
243 DBGC ( image, "EFIIMAGE %s could not create URI device path\n",
244 image->name );
245 rc = -ENOMEM;
246 goto err_device_path;
247 }
248
249 /* Create device handle */
250 device = NULL;
251 if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
252 &device,
254 NULL ) ) != 0 ) {
255 rc = -EEFI ( efirc );
256 DBGC ( image, "EFIIMAGE %s could not install %s: %s\n",
257 image->name, efi_devpath_text ( devpath ),
258 strerror ( rc ) );
259 goto err_path_install;
260 }
261 DBGC ( image, "EFIIMAGE %s device is %s\n",
263
264 /* Add as a child of the parent device */
265 if ( ( parent != NULL ) &&
266 ( rc = efi_child_add ( parent, device ) ) != 0 ) {
267 DBGC ( image, "EFIIMAGE %s could not become child of %s: %s\n",
268 image->name, efi_handle_name ( parent ),
269 strerror ( rc ) );
270 goto err_child_add;
271 }
272
273 /* Use shim instead of directly executing image if applicable */
274 shim = ( efi_can_load ( image ) ?
275 NULL : find_image_tag ( &efi_shim ) );
276 exec = ( shim ? shim : image );
277 if ( shim ) {
278 DBGC ( image, "EFIIMAGE %s executing via %s\n",
279 image->name, shim->name );
280 }
281
282 /* Re-register as a hidden image to allow for access via file I/O */
283 toggle = ( ~image->flags & IMAGE_HIDDEN );
285 if ( ( rc = register_image ( image ) ) != 0 )
286 goto err_register_image;
287
288 /* Install file I/O protocols */
289 if ( ( rc = efi_file_install ( device ) ) != 0 ) {
290 DBGC ( image, "EFIIMAGE %s could not install file protocol: "
291 "%s\n", image->name, strerror ( rc ) );
292 goto err_file_install;
293 }
294
295 /* Install PXE base code protocol */
296 if ( ( netdev != NULL ) &&
297 ( rc = efi_pxe_install ( device, netdev ) ) != 0 ) {
298 DBGC ( image, "EFIIMAGE %s could not install PXE protocol: "
299 "%s\n", image->name, strerror ( rc ) );
300 goto err_pxe_install;
301 }
302
303 /* Install iPXE download protocol */
304 if ( ( rc = efi_download_install ( device ) ) != 0 ) {
305 DBGC ( image, "EFIIMAGE %s could not install iPXE download "
306 "protocol: %s\n", image->name, strerror ( rc ) );
307 goto err_download_install;
308 }
309
310 /* Install Flattened Device Tree table */
311 if ( ( rc = efi_fdt_install ( image->cmdline ) ) != 0 ) {
312 DBGC ( image, "EFIIMAGE %s could not install FDT: %s\n",
313 image->name, strerror ( rc ) );
314 goto err_fdt_install;
315 }
316
317 /* Create file device path for image */
318 imgpath = efi_image_filepath ( exec, devpath );
319 if ( ! imgpath ) {
320 DBGC ( image, "EFIIMAGE %s could not create file device "
321 "path\n", image->name );
322 rc = -ENOMEM;
323 goto err_image_path;
324 }
325 DBGC ( image, "EFIIMAGE %s file is %s\n",
326 image->name, efi_devpath_text ( imgpath ) );
327
328 /* Create command line for image */
330 if ( ! cmdline ) {
331 DBGC ( image, "EFIIMAGE %s could not create command line\n",
332 image->name );
333 rc = -ENOMEM;
334 goto err_cmdline;
335 }
336
337 /* Install shim special handling if applicable */
338 if ( shim &&
339 ( ( rc = efi_shim_install ( shim, device, &cmdline ) ) != 0 ) ) {
340 DBGC ( image, "EFIIMAGE %s could not install shim handling: "
341 "%s\n", image->name, strerror ( rc ) );
342 goto err_shim_install;
343 }
344
345 /* Attempt loading image
346 *
347 * LoadImage() does not (allegedly) modify the image content,
348 * but requires a non-const pointer to SourceBuffer. We
349 * therefore use the .rwdata field rather than .data.
350 */
351 handle = NULL;
352 if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, imgpath,
353 exec->rwdata, exec->len,
354 &handle ) ) != 0 ) {
355 /* Not an EFI image */
356 rc = -EEFI_LOAD ( efirc );
357 DBGC ( image, "EFIIMAGE %s could not load: %s\n",
358 image->name, strerror ( rc ) );
359 if ( efirc == EFI_SECURITY_VIOLATION ) {
360 goto err_load_image_security_violation;
361 } else {
362 goto err_load_image;
363 }
364 }
365
366 /* Get the loaded image protocol for the newly loaded image */
368 &loaded ) ) != 0 ) {
369 /* Should never happen */
370 goto err_open_protocol;
371 }
372
373 /* Some EFI 1.10 implementations seem not to fill in DeviceHandle */
374 if ( loaded->DeviceHandle == NULL ) {
375 DBGC ( image, "EFIIMAGE %s filling in missing DeviceHandle\n",
376 image->name );
377 loaded->DeviceHandle = device;
378 }
379
380 /* Sanity checks */
381 assert ( loaded->ParentHandle == efi_image_handle );
382 assert ( loaded->DeviceHandle == device );
383 assert ( loaded->LoadOptionsSize == 0 );
384 assert ( loaded->LoadOptions == NULL );
385
386 /* Record image code type */
387 type = loaded->ImageCodeType;
388
389 /* Set command line */
390 loaded->LoadOptions = cmdline;
391 loaded->LoadOptionsSize =
392 ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) );
393
394 /* Release network devices for use via SNP */
396
397 /* Wrap calls made by the loaded image (for debugging) */
399
400 /* Reset console since image will probably use it */
402
403 /* Start the image */
404 if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
405 rc = -EEFI_START ( efirc );
406 DBGC ( image, "EFIIMAGE %s could not start (or returned with "
407 "error): %s\n", image->name, strerror ( rc ) );
408 goto err_start_image;
409 }
410
411 /* If image was a driver, connect it up to anything available */
412 if ( type == EfiBootServicesCode ) {
413 DBGC ( image, "EFIIMAGE %s connecting drivers\n", image->name );
415 }
416
417 /* Success */
418 rc = 0;
419
420 err_start_image:
421 efi_unwrap();
423 err_open_protocol:
424 /* If there was no error, then the image must have been
425 * started and returned successfully. It either unloaded
426 * itself, or it intended to remain loaded (e.g. it was a
427 * driver). We therefore do not unload successful images.
428 *
429 * If there was an error, attempt to unload the image. This
430 * may not work. In particular, there is no way to tell
431 * whether an error returned from StartImage() was due to
432 * being unable to start the image (in which case we probably
433 * should call UnloadImage()), or due to the image itself
434 * returning an error (in which case we probably should not
435 * call UnloadImage()). We therefore ignore any failures from
436 * the UnloadImage() call itself.
437 */
438 err_load_image_security_violation:
439 if ( rc != 0 )
440 bs->UnloadImage ( handle );
441 err_load_image:
442 if ( shim )
444 err_shim_install:
445 free ( cmdline );
446 err_cmdline:
447 free ( imgpath );
448 err_image_path:
450 err_fdt_install:
452 err_download_install:
453 if ( netdev )
455 err_pxe_install:
457 err_file_install:
459 err_register_image:
460 image->flags ^= toggle;
461 if ( parent )
462 efi_child_del ( parent, device );
463 err_child_add:
465 device,
467 NULL );
468 err_path_install:
469 free ( devpath );
470 err_device_path:
471 netdev_put ( netdev );
472 return rc;
473}
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
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition efi_debug.c:652
const char * efi_devpath_text(EFI_DEVICE_PATH_PROTOCOL *path)
Get textual representation of device path.
Definition efi_debug.c:247
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
EFI_GUID efi_device_path_protocol_guid
Device path protocol GUID.
Definition efi_guid.c:169
static EFI_DEVICE_PATH_PROTOCOL * efi_image_uripath(struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent)
Create a URI device path for image.
Definition efi_image.c:74
__weak int efi_fdt_uninstall(void)
Uninstall EFI Flattened Device Tree table (when no FDT support is present)
Definition efi_image.c:188
__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:179
#define EEFI_LOAD(efirc)
Definition efi_image.c:57
static wchar_t * efi_image_cmdline(struct image *image)
Create command line for image.
Definition efi_image.c:160
static EFI_DEVICE_PATH_PROTOCOL * efi_image_filepath(struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent)
Create a file device path for image.
Definition efi_image.c:118
#define EEFI_START(efirc)
Definition efi_image.c:62
static int efi_can_load(struct image *image)
Check if EFI image can be loaded directly.
Definition efi_image.h:23
EFI_DEVICE_PATH_PROTOCOL * efi_loaded_image_path
Device path for the loaded image's device handle.
Definition efi_init.c:42
EFI_LOADED_IMAGE_PROTOCOL * efi_loaded_image
Loaded image protocol for this image.
Definition efi_init.c:39
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:1650
int efi_pxe_install(EFI_HANDLE handle, struct net_device *netdev)
Install PXE base code protocol.
Definition efi_pxe.c:1567
void efi_shim_uninstall(void)
Uninstall UEFI shim special handling.
Definition efi_shim.c:400
int efi_shim_install(struct image *shim, EFI_HANDLE handle, wchar_t **cmdline)
Install UEFI shim special handling.
Definition efi_shim.c:366
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_child_del(EFI_HANDLE parent, EFI_HANDLE child)
Remove EFI device as child of another EFI device.
Definition efi_utils.c:138
int efi_child_add(EFI_HANDLE parent, EFI_HANDLE child)
Add EFI device as child of another EFI device.
Definition efi_utils.c:111
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
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
#define ENOMEM
Not enough space.
Definition errno.h:535
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:452
#define EFI_HANDLE
Definition efi.h:53
#define efi_test(handle, protocol)
Test protocol existence.
Definition efi.h:441
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:181
EFI_SYSTEM_TABLE * efi_systab
uint16_t handle
Handle.
Definition smbios.h:5
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:568
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:579
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_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces
Definition UefiSpec.h:2011
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces
Definition UefiSpec.h:2010
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
A network device.
Definition netdevice.h:353
#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, EEFI_LOAD, EEFI_START, efi_can_load(), efi_child_add(), efi_child_del(), efi_device_path_protocol_guid, efi_devpath_text(), 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_handle_name(), efi_image_cmdline(), efi_image_filepath(), efi_image_handle, efi_image_uripath(), efi_loaded_image, efi_loaded_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_test, efi_unwrap(), efi_wrap_image(), EfiBootServicesCode, ENOMEM, FALSE, find_image_tag(), image::flags, free, efi_snp_device::handle, handle, IMAGE_HIDDEN, EFI_LOADED_IMAGE_PROTOCOL::ImageCodeType, EFI_BOOT_SERVICES::InstallMultipleProtocolInterfaces, 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, netdev, netdev_get(), netdev_put(), 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::UninstallMultipleProtocolInterfaces, 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 481 of file efi_image.c.

481 {
482 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
483 static EFI_DEVICE_PATH_PROTOCOL empty_path = {
484 .Type = END_DEVICE_PATH_TYPE,
486 .Length[0] = sizeof ( empty_path ),
487 };
489 EFI_STATUS efirc;
490 int rc;
491
492 /* Attempt loading image
493 *
494 * LoadImage() does not (allegedly) modify the image content,
495 * but requires a non-const pointer to SourceBuffer. We
496 * therefore use the .rwdata field rather than .data.
497 */
498 handle = NULL;
499 if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, &empty_path,
501 &handle ) ) != 0 ) {
502 /* Not an EFI image */
503 rc = -EEFI_LOAD ( efirc );
504 DBGC ( image, "EFIIMAGE %s could not load: %s\n",
505 image->name, strerror ( rc ) );
506 if ( efirc == EFI_SECURITY_VIOLATION ) {
507 goto err_load_image_security_violation;
508 } else {
509 goto err_load_image;
510 }
511 }
512
513 /* Unload the image. We can't leave it loaded, because we
514 * have no "unload" operation.
515 */
516 bs->UnloadImage ( handle );
517
518 return 0;
519
520 err_load_image_security_violation:
521 bs->UnloadImage ( handle );
522 err_load_image:
523 return rc;
524}
#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 539 of file efi_image.c.

539 {
540 const UINT16 magic = ( ( sizeof ( UINTN ) == sizeof ( uint32_t ) ) ?
543 const EFI_IMAGE_DOS_HEADER *dos;
545
546 /* Check for existence of DOS header */
547 if ( image->len < sizeof ( *dos ) ) {
548 DBGC ( image, "EFIIMAGE %s too short for DOS header\n",
549 image->name );
550 return -ENOEXEC;
551 }
552 dos = image->data;
553 if ( dos->e_magic != EFI_IMAGE_DOS_SIGNATURE ) {
554 DBGC ( image, "EFIIMAGE %s missing MZ signature\n",
555 image->name );
556 return -ENOEXEC;
557 }
558
559 /* Check for existence of PE header */
560 if ( ( image->len < dos->e_lfanew ) ||
561 ( ( image->len - dos->e_lfanew ) < sizeof ( *pe ) ) ) {
562 DBGC ( image, "EFIIMAGE %s too short for PE header\n",
563 image->name );
564 return -ENOEXEC;
565 }
566 pe = ( image->data + dos->e_lfanew );
568 DBGC ( image, "EFIIMAGE %s missing PE signature\n",
569 image->name );
570 return -ENOEXEC;
571 }
572
573 /* Check PE header magic */
574 if ( pe->Pe32.OptionalHeader.Magic != magic ) {
575 DBGC ( image, "EFIIMAGE %s incorrect magic %04x\n",
577 return -ENOEXEC;
578 }
579
580 return 0;
581}
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 )