iPXE
efi_image.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 FILE_LICENCE ( GPL2_OR_LATER );
21 
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <wchar.h>
25 #include <ipxe/efi/efi.h>
26 #include <ipxe/efi/efi_snp.h>
27 #include <ipxe/efi/efi_download.h>
28 #include <ipxe/efi/efi_file.h>
29 #include <ipxe/efi/efi_path.h>
30 #include <ipxe/efi/efi_strings.h>
31 #include <ipxe/efi/efi_wrap.h>
32 #include <ipxe/efi/efi_pxe.h>
33 #include <ipxe/efi/efi_driver.h>
34 #include <ipxe/image.h>
35 #include <ipxe/init.h>
36 #include <ipxe/features.h>
37 #include <ipxe/uri.h>
38 #include <ipxe/console.h>
39 
41 
42 /* Disambiguate the various error causes */
43 #define EINFO_EEFI_LOAD \
44  __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
45  "Could not load image" )
46 #define EINFO_EEFI_LOAD_PROHIBITED \
47  __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION, \
48  "Image prohibited by security policy" )
49 #define EEFI_LOAD_PROHIBITED \
50  __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )
51 #define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \
52  EEFI_LOAD_PROHIBITED )
53 #define EINFO_EEFI_START \
54  __einfo_uniqify ( EINFO_EPLATFORM, 0x02, \
55  "Could not start image" )
56 #define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc )
57 
58 /**
59  * Create device path for image
60  *
61  * @v image EFI image
62  * @v parent Parent device path
63  * @ret path Device path, or NULL on failure
64  *
65  * The caller must eventually free() the device path.
66  */
70  FILEPATH_DEVICE_PATH *filepath;
72  size_t name_len;
73  size_t prefix_len;
74  size_t filepath_len;
75  size_t len;
76 
77  /* Calculate device path lengths */
78  prefix_len = efi_path_len ( parent );
79  name_len = strlen ( image->name );
80  filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
81  ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
82  len = ( prefix_len + filepath_len + sizeof ( *end ) );
83 
84  /* Allocate device path */
85  path = zalloc ( len );
86  if ( ! path )
87  return NULL;
88 
89  /* Construct device path */
90  memcpy ( path, parent, prefix_len );
91  filepath = ( ( ( void * ) path ) + prefix_len );
92  filepath->Header.Type = MEDIA_DEVICE_PATH;
93  filepath->Header.SubType = MEDIA_FILEPATH_DP;
94  filepath->Header.Length[0] = ( filepath_len & 0xff );
95  filepath->Header.Length[1] = ( filepath_len >> 8 );
96  efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
97  "%s", image->name );
98  end = ( ( ( void * ) filepath ) + filepath_len );
99  end->Type = END_DEVICE_PATH_TYPE;
101  end->Length[0] = sizeof ( *end );
102 
103  return path;
104 }
105 
106 /**
107  * Create command line for image
108  *
109  * @v image EFI image
110  * @ret cmdline Command line, or NULL on failure
111  */
112 static wchar_t * efi_image_cmdline ( struct image *image ) {
113  wchar_t *cmdline;
114  size_t len;
115 
116  len = ( strlen ( image->name ) +
117  ( image->cmdline ?
118  ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
119  cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
120  if ( ! cmdline )
121  return NULL;
122  efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s",
123  image->name,
124  ( image->cmdline ? " " : "" ),
125  ( image->cmdline ? image->cmdline : "" ) );
126  return cmdline;
127 }
128 
129 /**
130  * Execute EFI image
131  *
132  * @v image EFI image
133  * @ret rc Return status code
134  */
135 static int efi_image_exec ( struct image *image ) {
137  struct efi_snp_device *snpdev;
139  union {
141  void *interface;
142  } loaded;
145  wchar_t *cmdline;
146  EFI_STATUS efirc;
147  int rc;
148 
149  /* Find an appropriate device handle to use */
150  snpdev = last_opened_snpdev();
151  if ( ! snpdev ) {
152  DBGC ( image, "EFIIMAGE %p could not identify SNP device\n",
153  image );
154  rc = -ENODEV;
155  goto err_no_snpdev;
156  }
157 
158  /* Install file I/O protocols */
159  if ( ( rc = efi_file_install ( snpdev->handle ) ) != 0 ) {
160  DBGC ( image, "EFIIMAGE %p could not install file protocol: "
161  "%s\n", image, strerror ( rc ) );
162  goto err_file_install;
163  }
164 
165  /* Install PXE base code protocol */
166  if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
167  DBGC ( image, "EFIIMAGE %p could not install PXE protocol: "
168  "%s\n", image, strerror ( rc ) );
169  goto err_pxe_install;
170  }
171 
172  /* Install iPXE download protocol */
173  if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
174  DBGC ( image, "EFIIMAGE %p could not install iPXE download "
175  "protocol: %s\n", image, strerror ( rc ) );
176  goto err_download_install;
177  }
178 
179  /* Create device path for image */
180  path = efi_image_path ( image, snpdev->path );
181  if ( ! path ) {
182  DBGC ( image, "EFIIMAGE %p could not create device path\n",
183  image );
184  rc = -ENOMEM;
185  goto err_image_path;
186  }
187 
188  /* Create command line for image */
190  if ( ! cmdline ) {
191  DBGC ( image, "EFIIMAGE %p could not create command line\n",
192  image );
193  rc = -ENOMEM;
194  goto err_cmdline;
195  }
196 
197  /* Attempt loading image */
198  handle = NULL;
199  if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
200  user_to_virt ( image->data, 0 ),
201  image->len, &handle ) ) != 0 ) {
202  /* Not an EFI image */
203  rc = -EEFI_LOAD ( efirc );
204  DBGC ( image, "EFIIMAGE %p could not load: %s\n",
205  image, strerror ( rc ) );
206  if ( efirc == EFI_SECURITY_VIOLATION ) {
207  goto err_load_image_security_violation;
208  } else {
209  goto err_load_image;
210  }
211  }
212 
213  /* Get the loaded image protocol for the newly loaded image */
215  &loaded.interface, efi_image_handle,
217  if ( efirc ) {
218  /* Should never happen */
219  rc = -EEFI ( efirc );
220  goto err_open_protocol;
221  }
222 
223  /* Some EFI 1.10 implementations seem not to fill in DeviceHandle */
224  if ( loaded.image->DeviceHandle == NULL ) {
225  DBGC ( image, "EFIIMAGE %p filling in missing DeviceHandle\n",
226  image );
227  loaded.image->DeviceHandle = snpdev->handle;
228  }
229 
230  /* Sanity checks */
231  assert ( loaded.image->ParentHandle == efi_image_handle );
232  assert ( loaded.image->DeviceHandle == snpdev->handle );
233  assert ( loaded.image->LoadOptionsSize == 0 );
234  assert ( loaded.image->LoadOptions == NULL );
235 
236  /* Record image code type */
237  type = loaded.image->ImageCodeType;
238 
239  /* Set command line */
240  loaded.image->LoadOptions = cmdline;
241  loaded.image->LoadOptionsSize =
242  ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) );
243 
244  /* Release network devices for use via SNP */
245  efi_snp_release();
246 
247  /* Wrap calls made by the loaded image (for debugging) */
248  efi_wrap ( handle );
249 
250  /* Reset console since image will probably use it */
251  console_reset();
252 
253  /* Start the image */
254  if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
255  rc = -EEFI_START ( efirc );
256  DBGC ( image, "EFIIMAGE %p could not start (or returned with "
257  "error): %s\n", image, strerror ( rc ) );
258  goto err_start_image;
259  }
260 
261  /* If image was a driver, connect it up to anything available */
262  if ( type == EfiBootServicesCode ) {
263  DBGC ( image, "EFIIMAGE %p connecting drivers\n", image );
265  }
266 
267  /* Success */
268  rc = 0;
269 
270  err_start_image:
271  efi_snp_claim();
272  err_open_protocol:
273  /* If there was no error, then the image must have been
274  * started and returned successfully. It either unloaded
275  * itself, or it intended to remain loaded (e.g. it was a
276  * driver). We therefore do not unload successful images.
277  *
278  * If there was an error, attempt to unload the image. This
279  * may not work. In particular, there is no way to tell
280  * whether an error returned from StartImage() was due to
281  * being unable to start the image (in which case we probably
282  * should call UnloadImage()), or due to the image itself
283  * returning an error (in which case we probably should not
284  * call UnloadImage()). We therefore ignore any failures from
285  * the UnloadImage() call itself.
286  */
287  err_load_image_security_violation:
288  if ( rc != 0 )
289  bs->UnloadImage ( handle );
290  err_load_image:
291  free ( cmdline );
292  err_cmdline:
293  free ( path );
294  err_image_path:
295  efi_download_uninstall ( snpdev->handle );
296  err_download_install:
297  efi_pxe_uninstall ( snpdev->handle );
298  err_pxe_install:
299  efi_file_uninstall ( snpdev->handle );
300  err_file_install:
301  err_no_snpdev:
302  return rc;
303 }
304 
305 /**
306  * Probe EFI image
307  *
308  * @v image EFI file
309  * @ret rc Return status code
310  */
311 static int efi_image_probe ( struct image *image ) {
313  static EFI_DEVICE_PATH_PROTOCOL empty_path = {
316  .Length[0] = sizeof ( empty_path ),
317  };
319  EFI_STATUS efirc;
320  int rc;
321 
322  /* Attempt loading image */
323  handle = NULL;
324  if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, &empty_path,
325  user_to_virt ( image->data, 0 ),
326  image->len, &handle ) ) != 0 ) {
327  /* Not an EFI image */
328  rc = -EEFI_LOAD ( efirc );
329  DBGC ( image, "EFIIMAGE %p could not load: %s\n",
330  image, strerror ( rc ) );
331  if ( efirc == EFI_SECURITY_VIOLATION ) {
332  goto err_load_image_security_violation;
333  } else {
334  goto err_load_image;
335  }
336  }
337 
338  /* Unload the image. We can't leave it loaded, because we
339  * have no "unload" operation.
340  */
341  bs->UnloadImage ( handle );
342 
343  return 0;
344 
345  err_load_image_security_violation:
346  bs->UnloadImage ( handle );
347  err_load_image:
348  return rc;
349 }
350 
351 /** EFI image type */
352 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
353  .name = "EFI",
354  .probe = efi_image_probe,
355  .exec = efi_image_exec,
356 };
iPXE Download Protocol
FILE_LICENCE(GPL2_OR_LATER)
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:236
EFI file protocols.
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:162
userptr_t data
Raw file image.
Definition: image.h:41
EFI driver interface.
#define END_DEVICE_PATH_TYPE
Definition: DevicePath.h:1327
EFI PXE base code protocol.
Error codes.
EFI strings.
EFI_IMAGE_LOAD LoadImage
Definition: UefiSpec.h:1883
uint32_t type
Operating system type.
Definition: ena.h:12
#define EEFI_START(efirc)
Definition: efi_image.c:56
#define DBGC(...)
Definition: compiler.h:505
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition: efi_guid.c:184
An executable image type.
Definition: image.h:76
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:137
size_t efi_path_len(EFI_DEVICE_PATH_PROTOCOL *path)
Find length of device path (excluding terminator)
Definition: efi_path.c:67
void efi_file_uninstall(EFI_HANDLE handle)
Uninstall EFI simple file system protocol.
Definition: efi_file.c:928
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
CHAR16 PathName[1]
A NULL-terminated Path string including directory and file names.
Definition: DevicePath.h:1041
#define FEATURE_IMAGE
Image formats.
Definition: features.h:22
static void efi_snp_claim(void)
Claim network devices for use by iPXE.
Definition: efi_snp.h:88
EFI_DEVICE_PATH_PROTOCOL Header
Definition: DevicePath.h:1037
Uniform Resource Identifiers.
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
char * name
Name of this image type.
Definition: image.h:78
char * cmdline
Command line to pass to image.
Definition: image.h:39
int efi_file_install(EFI_HANDLE handle)
Install EFI simple file system protocol.
Definition: efi_file.c:842
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:1955
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
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:1674
void efi_driver_reconnect_all(void)
Reconnect original EFI drivers to all possible devices.
Definition: efi_driver.c:595
EFI_MEMORY_TYPE
Enumeration of memory types introduced in UEFI.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define EEFI_LOAD(efirc)
Definition: efi_image.c:51
An object interface.
Definition: interface.h:124
Executable images.
void efi_wrap(EFI_HANDLE handle)
Wrap the calls made by a loaded image.
Definition: efi_wrap.c:1248
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
Definition: efi_strings.c:104
Feature list.
#define SIZE_OF_FILEPATH_DEVICE_PATH
Definition: DevicePath.h:1044
User interaction.
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
The code portions of a loaded Boot Services Driver.
int efi_pxe_install(EFI_HANDLE handle, struct net_device *netdev)
Install PXE base code protocol.
Definition: efi_pxe.c:1590
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:33
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
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
static int efi_image_exec(struct image *image)
Execute EFI image.
Definition: efi_image.c:135
static void console_reset(void)
Reset console.
Definition: console.h:214
EFI device paths.
EFI_IMAGE_START StartImage
Definition: UefiSpec.h:1884
#define MEDIA_DEVICE_PATH
Definition: DevicePath.h:946
EFI API.
#define EFI_SECURITY_VIOLATION
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:146
static wchar_t * efi_image_cmdline(struct image *image)
Create command line for image.
Definition: efi_image.c:112
#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
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:68
struct image_type efi_image_type __image_type(PROBE_NORMAL)
EFI image type.
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
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
void * user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
uint32_t end
Ending offset.
Definition: netvsc.h:18
int efi_download_install(EFI_HANDLE handle)
Install iPXE download protocol.
Definition: efi_download.c:211
#define FALSE
Definition: tlan.h:45
static int efi_image_probe(struct image *image)
Probe EFI image.
Definition: efi_image.c:311
UINT8 Type
0x01 Hardware Device Path.
Definition: DevicePath.h:52
FEATURE(FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1)
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
iPXE EFI SNP interface
#define DHCP_EB_FEATURE_EFI
EFI format.
Definition: features.h:52
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
char * name
Name.
Definition: image.h:34
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
EFI driver interface.
Definition: efi.h:50
#define MEDIA_FILEPATH_DP
File Path Media Device Path SubType.
Definition: DevicePath.h:1035