iPXE
Macros | Functions
efi_image.c File Reference
#include <errno.h>
#include <stdlib.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_utils.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_wrap.h>
#include <ipxe/efi/efi_pxe.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)   EPLATFORM ( EINFO_EEFI_START, efirc )
 

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 
 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. More...
 
static wchar_tefi_image_cmdline (struct image *image)
 Create command line for image. More...
 
static int efi_image_exec (struct image *image)
 Execute EFI image. More...
 
static int efi_image_probe (struct image *image)
 Probe EFI image. More...
 
struct image_type efi_image_type __image_type (PROBE_NORMAL)
 EFI image type. More...
 

Macro Definition Documentation

◆ EINFO_EEFI_LOAD

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

Definition at line 42 of file efi_image.c.

◆ EINFO_EEFI_LOAD_PROHIBITED

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

Definition at line 45 of file efi_image.c.

◆ EEFI_LOAD_PROHIBITED

#define EEFI_LOAD_PROHIBITED   __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )

Definition at line 48 of file efi_image.c.

◆ EEFI_LOAD

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

Definition at line 50 of file efi_image.c.

◆ EINFO_EEFI_START

#define EINFO_EEFI_START
Value:
"Could not start image" )
#define EINFO_EPLATFORM
Platform-generated base error.
Definition: errno.h:691
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition: errno.h:180

Definition at line 52 of file efi_image.c.

◆ EEFI_START

#define EEFI_START (   efirc)    EPLATFORM ( EINFO_EEFI_START, efirc )

Definition at line 55 of file efi_image.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER  )

◆ FEATURE()

FEATURE ( FEATURE_IMAGE  ,
"EFI"  ,
DHCP_EB_FEATURE_EFI  ,
 
)

◆ efi_image_path()

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

67  {
69  FILEPATH_DEVICE_PATH *filepath;
71  size_t name_len;
72  size_t prefix_len;
73  size_t filepath_len;
74  size_t len;
75 
76  /* Calculate device path lengths */
77  prefix_len = efi_devpath_len ( parent );
78  name_len = strlen ( image->name );
79  filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
80  ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
81  len = ( prefix_len + filepath_len + sizeof ( *end ) );
82 
83  /* Allocate device path */
84  path = zalloc ( len );
85  if ( ! path )
86  return NULL;
87 
88  /* Construct device path */
89  memcpy ( path, parent, prefix_len );
90  filepath = ( ( ( void * ) path ) + prefix_len );
91  filepath->Header.Type = MEDIA_DEVICE_PATH;
92  filepath->Header.SubType = MEDIA_FILEPATH_DP;
93  filepath->Header.Length[0] = ( filepath_len & 0xff );
94  filepath->Header.Length[1] = ( filepath_len >> 8 );
95  efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
96  "%s", image->name );
97  end = ( ( ( void * ) filepath ) + filepath_len );
98  end->Type = END_DEVICE_PATH_TYPE;
100  end->Length[0] = sizeof ( *end );
101 
102  return path;
103 }
#define END_DEVICE_PATH_TYPE
Definition: DevicePath.h:1327
size_t efi_devpath_len(EFI_DEVICE_PATH_PROTOCOL *path)
Find length of device path (excluding terminator)
Definition: efi_utils.c:59
An executable image.
Definition: image.h:24
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:51
CHAR16 PathName[1]
A NULL-terminated Path string including directory and file names.
Definition: DevicePath.h:1041
EFI_DEVICE_PATH_PROTOCOL Header
Definition: DevicePath.h:1037
void * memcpy(void *dest, const void *src, size_t len) __nonnull
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
Definition: efi_strings.c:104
#define SIZE_OF_FILEPATH_DEVICE_PATH
Definition: DevicePath.h:1044
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
size_t strlen(const char *src)
Get length of string.
Definition: string.c:213
#define MEDIA_DEVICE_PATH
Definition: DevicePath.h:946
#define END_ENTIRE_DEVICE_PATH_SUBTYPE
Definition: DevicePath.h:1328
UINT8 Length[2]
Specific Device Path data.
Definition: DevicePath.h:64
uint32_t len
Length.
Definition: ena.h:14
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:59
uint32_t end
Ending offset.
Definition: netvsc.h:18
UINT8 Type
0x01 Hardware Device Path.
Definition: DevicePath.h:52
char * name
Name.
Definition: image.h:34
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define MEDIA_FILEPATH_DP
File Path Media Device Path SubType.
Definition: DevicePath.h:1035

References efi_devpath_len(), efi_snprintf(), end, END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, 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()

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

111  {
112  wchar_t *cmdline;
113  size_t len;
114 
115  len = ( strlen ( image->name ) +
116  ( image->cmdline ?
117  ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
118  cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
119  if ( ! cmdline )
120  return NULL;
121  efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s",
122  image->name,
123  ( image->cmdline ? " " : "" ),
124  ( image->cmdline ? image->cmdline : "" ) );
125  return cmdline;
126 }
An executable image.
Definition: image.h:24
char * cmdline
Command line to pass to image.
Definition: image.h:39
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
Definition: efi_strings.c:104
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
size_t strlen(const char *src)
Get length of string.
Definition: string.c:213
uint32_t len
Length.
Definition: ena.h:14
uint32_t cmdline
Definition: multiboot.h:16
char * name
Name.
Definition: image.h:34
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References cmdline, image::cmdline, efi_snprintf(), len, image::name, NULL, strlen(), and zalloc().

Referenced by efi_image_exec().

◆ efi_image_exec()

static int efi_image_exec ( struct image image)
static

Execute EFI image.

Parameters
imageEFI image
Return values
rcReturn status code

Definition at line 134 of file efi_image.c.

134  {
136  struct efi_snp_device *snpdev;
138  union {
140  void *interface;
141  } loaded;
143  wchar_t *cmdline;
144  EFI_STATUS efirc;
145  int rc;
146 
147  /* Find an appropriate device handle to use */
148  snpdev = last_opened_snpdev();
149  if ( ! snpdev ) {
150  DBGC ( image, "EFIIMAGE %p could not identify SNP device\n",
151  image );
152  rc = -ENODEV;
153  goto err_no_snpdev;
154  }
155 
156  /* Install file I/O protocols */
157  if ( ( rc = efi_file_install ( snpdev->handle ) ) != 0 ) {
158  DBGC ( image, "EFIIMAGE %p could not install file protocol: "
159  "%s\n", image, strerror ( rc ) );
160  goto err_file_install;
161  }
162 
163  /* Install PXE base code protocol */
164  if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
165  DBGC ( image, "EFIIMAGE %p could not install PXE protocol: "
166  "%s\n", image, strerror ( rc ) );
167  goto err_pxe_install;
168  }
169 
170  /* Install iPXE download protocol */
171  if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
172  DBGC ( image, "EFIIMAGE %p could not install iPXE download "
173  "protocol: %s\n", image, strerror ( rc ) );
174  goto err_download_install;
175  }
176 
177  /* Create device path for image */
178  path = efi_image_path ( image, snpdev->path );
179  if ( ! path ) {
180  DBGC ( image, "EFIIMAGE %p could not create device path\n",
181  image );
182  rc = -ENOMEM;
183  goto err_image_path;
184  }
185 
186  /* Create command line for image */
188  if ( ! cmdline ) {
189  DBGC ( image, "EFIIMAGE %p could not create command line\n",
190  image );
191  rc = -ENOMEM;
192  goto err_cmdline;
193  }
194 
195  /* Attempt loading image */
196  if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
197  user_to_virt ( image->data, 0 ),
198  image->len, &handle ) ) != 0 ) {
199  /* Not an EFI image */
200  rc = -EEFI_LOAD ( efirc );
201  DBGC ( image, "EFIIMAGE %p could not load: %s\n",
202  image, strerror ( rc ) );
203  goto err_load_image;
204  }
205 
206  /* Get the loaded image protocol for the newly loaded image */
208  &loaded.interface, efi_image_handle,
210  if ( efirc ) {
211  /* Should never happen */
212  rc = -EEFI ( efirc );
213  goto err_open_protocol;
214  }
215 
216  /* Some EFI 1.10 implementations seem not to fill in DeviceHandle */
217  if ( loaded.image->DeviceHandle == NULL ) {
218  DBGC ( image, "EFIIMAGE %p filling in missing DeviceHandle\n",
219  image );
220  loaded.image->DeviceHandle = snpdev->handle;
221  }
222 
223  /* Sanity checks */
224  assert ( loaded.image->ParentHandle == efi_image_handle );
225  assert ( loaded.image->DeviceHandle == snpdev->handle );
226  assert ( loaded.image->LoadOptionsSize == 0 );
227  assert ( loaded.image->LoadOptions == NULL );
228 
229  /* Set command line */
230  loaded.image->LoadOptions = cmdline;
231  loaded.image->LoadOptionsSize =
232  ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) );
233 
234  /* Release network devices for use via SNP */
235  efi_snp_release();
236 
237  /* Wrap calls made by the loaded image (for debugging) */
238  efi_wrap ( handle );
239 
240  /* Reset console since image will probably use it */
241  console_reset();
242 
243  /* Start the image */
244  if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
245  rc = -EEFI_START ( efirc );
246  DBGC ( image, "EFIIMAGE %p could not start (or returned with "
247  "error): %s\n", image, strerror ( rc ) );
248  goto err_start_image;
249  }
250 
251  /* Success */
252  rc = 0;
253 
254  err_start_image:
255  efi_snp_claim();
256  err_open_protocol:
257  /* If there was no error, then the image must have been
258  * started and returned successfully. It either unloaded
259  * itself, or it intended to remain loaded (e.g. it was a
260  * driver). We therefore do not unload successful images.
261  *
262  * If there was an error, attempt to unload the image. This
263  * may not work. In particular, there is no way to tell
264  * whether an error returned from StartImage() was due to
265  * being unable to start the image (in which case we probably
266  * should call UnloadImage()), or due to the image itself
267  * returning an error (in which case we probably should not
268  * call UnloadImage()). We therefore ignore any failures from
269  * the UnloadImage() call itself.
270  */
271  if ( rc != 0 )
272  bs->UnloadImage ( handle );
273  err_load_image:
274  free ( cmdline );
275  err_cmdline:
276  free ( path );
277  err_image_path:
278  efi_download_uninstall ( snpdev->handle );
279  err_download_install:
280  efi_pxe_uninstall ( snpdev->handle );
281  err_pxe_install:
282  efi_file_uninstall ( snpdev->handle );
283  err_file_install:
284  err_no_snpdev:
285  return rc;
286 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void efi_download_uninstall(EFI_HANDLE handle)
Uninstall iPXE download protocol.
Definition: efi_download.c:233
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
userptr_t data
Raw file image.
Definition: image.h:41
EFI_IMAGE_LOAD LoadImage
Definition: UefiSpec.h:1883
#define EEFI_START(efirc)
Definition: efi_image.c:55
#define DBGC(...)
Definition: compiler.h:505
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition: efi_guid.c:184
void efi_file_uninstall(EFI_HANDLE handle)
Uninstall EFI simple file system protocol.
Definition: efi_file.c:688
EFI_IMAGE_UNLOAD UnloadImage
Definition: UefiSpec.h:1886
An executable image.
Definition: image.h:24
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:51
static void efi_snp_claim(void)
Claim network devices for use by iPXE.
Definition: efi_snp.h:88
EFI_HANDLE handle
EFI device handle.
Definition: efi_snp.h:35
size_t wcslen(const wchar_t *string)
Calculate length of wide-character string.
Definition: wchar.c:41
int efi_file_install(EFI_HANDLE handle)
Install EFI simple file system protocol.
Definition: efi_file.c:602
struct net_device * netdev
The underlying iPXE network device.
Definition: efi_snp.h:31
struct efi_snp_device * last_opened_snpdev(void)
Get most recently opened SNP device.
Definition: efi_snp.c:1954
#define ENOMEM
Not enough space.
Definition: errno.h:534
Can be used on any image handle to obtain information about the loaded image.
Definition: LoadedImage.h:51
void efi_pxe_uninstall(EFI_HANDLE handle)
Uninstall PXE base code protocol.
Definition: efi_pxe.c:1662
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define EEFI_LOAD(efirc)
Definition: efi_image.c:50
An object interface.
Definition: interface.h:109
void efi_wrap(EFI_HANDLE handle)
Wrap the calls made by a loaded image.
Definition: efi_wrap.c:550
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
int efi_pxe_install(EFI_HANDLE handle, struct net_device *netdev)
Install PXE base code protocol.
Definition: efi_pxe.c:1588
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:30
size_t len
Length of raw file image.
Definition: image.h:43
An SNP device.
Definition: efi_snp.h:27
#define ENODEV
No such device.
Definition: errno.h:509
static void efi_snp_release(void)
Release network devices for use via SNP.
Definition: efi_snp.h:96
static void console_reset(void)
Reset console.
Definition: console.h:214
EFI_IMAGE_START StartImage
Definition: UefiSpec.h:1884
static wchar_t * efi_image_cmdline(struct image *image)
Create command line for image.
Definition: efi_image.c:111
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:67
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
void * user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
int efi_download_install(EFI_HANDLE handle)
Install iPXE download protocol.
Definition: efi_download.c:208
#define FALSE
Definition: tlan.h:45
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
uint32_t cmdline
Definition: multiboot.h:16
EFI_DEVICE_PATH_PROTOCOL * path
The device path.
Definition: efi_snp.h:75
uint16_t handle
Handle.
Definition: smbios.h:16
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
Definition: efi.h:55

References assert(), EFI_SYSTEM_TABLE::BootServices, cmdline, console_reset(), image::data, DBGC, EEFI, EEFI_LOAD, EEFI_START, efi_download_install(), efi_download_uninstall(), efi_file_install(), efi_file_uninstall(), efi_image_cmdline(), efi_image_handle, efi_image_path(), efi_loaded_image_protocol_guid, EFI_OPEN_PROTOCOL_GET_PROTOCOL, efi_pxe_install(), efi_pxe_uninstall(), efi_snp_claim(), efi_snp_release(), efi_systab, efi_wrap(), ENODEV, ENOMEM, FALSE, free, handle, efi_snp_device::handle, last_opened_snpdev(), image::len, EFI_BOOT_SERVICES::LoadImage, efi_snp_device::netdev, NULL, EFI_BOOT_SERVICES::OpenProtocol, efi_snp_device::path, rc, EFI_BOOT_SERVICES::StartImage, strerror(), EFI_BOOT_SERVICES::UnloadImage, user_to_virt(), and wcslen().

◆ efi_image_probe()

static int efi_image_probe ( struct image image)
static

Probe EFI image.

Parameters
imageEFI file
Return values
rcReturn status code

Definition at line 294 of file efi_image.c.

294  {
296  static EFI_DEVICE_PATH_PROTOCOL empty_path = {
299  .Length[0] = sizeof ( empty_path ),
300  };
302  EFI_STATUS efirc;
303  int rc;
304 
305  /* Attempt loading image */
306  if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, &empty_path,
307  user_to_virt ( image->data, 0 ),
308  image->len, &handle ) ) != 0 ) {
309  /* Not an EFI image */
310  rc = -EEFI_LOAD ( efirc );
311  DBGC ( image, "EFIIMAGE %p could not load: %s\n",
312  image, strerror ( rc ) );
313  return rc;
314  }
315 
316  /* Unload the image. We can't leave it loaded, because we
317  * have no "unload" operation.
318  */
319  bs->UnloadImage ( handle );
320 
321  return 0;
322 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
userptr_t data
Raw file image.
Definition: image.h:41
#define END_DEVICE_PATH_TYPE
Definition: DevicePath.h:1327
EFI_IMAGE_LOAD LoadImage
Definition: UefiSpec.h:1883
#define DBGC(...)
Definition: compiler.h:505
EFI_IMAGE_UNLOAD UnloadImage
Definition: UefiSpec.h:1886
An executable image.
Definition: image.h:24
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:51
#define EEFI_LOAD(efirc)
Definition: efi_image.c:50
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:30
size_t len
Length of raw file image.
Definition: image.h:43
#define END_ENTIRE_DEVICE_PATH_SUBTYPE
Definition: DevicePath.h:1328
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
void * user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
#define FALSE
Definition: tlan.h:45
UINT8 Type
0x01 Hardware Device Path.
Definition: DevicePath.h:52
EFI_SYSTEM_TABLE * efi_systab
uint16_t handle
Handle.
Definition: smbios.h:16
Definition: efi.h:55

References EFI_SYSTEM_TABLE::BootServices, image::data, DBGC, EEFI_LOAD, efi_image_handle, efi_systab, END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, FALSE, handle, image::len, EFI_BOOT_SERVICES::LoadImage, rc, strerror(), EFI_DEVICE_PATH_PROTOCOL::Type, EFI_BOOT_SERVICES::UnloadImage, and user_to_virt().

◆ __image_type()

struct image_type efi_image_type __image_type ( PROBE_NORMAL  )

EFI image type.