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_utils.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/image.h>
34 #include <ipxe/init.h>
35 #include <ipxe/features.h>
36 #include <ipxe/uri.h>
37 #include <ipxe/console.h>
38 
40 
41 /* Disambiguate the various error causes */
42 #define EINFO_EEFI_LOAD \
43  __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
44  "Could not load image" )
45 #define EINFO_EEFI_LOAD_PROHIBITED \
46  __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION, \
47  "Image prohibited by security policy" )
48 #define EEFI_LOAD_PROHIBITED \
49  __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )
50 #define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \
51  EEFI_LOAD_PROHIBITED )
52 #define EINFO_EEFI_START \
53  __einfo_uniqify ( EINFO_EPLATFORM, 0x02, \
54  "Could not start image" )
55 #define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc )
56 
57 /**
58  * Create device path for image
59  *
60  * @v image EFI image
61  * @v parent Parent device path
62  * @ret path Device path, or NULL on failure
63  *
64  * The caller must eventually free() the device path.
65  */
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 }
104 
105 /**
106  * Create command line for image
107  *
108  * @v image EFI image
109  * @ret cmdline Command line, or NULL on failure
110  */
111 static wchar_t * efi_image_cmdline ( struct image *image ) {
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 }
127 
128 /**
129  * Execute EFI image
130  *
131  * @v image EFI image
132  * @ret rc Return status code
133  */
134 static int efi_image_exec ( struct image *image ) {
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 }
287 
288 /**
289  * Probe EFI image
290  *
291  * @v image EFI file
292  * @ret rc Return status code
293  */
294 static int efi_image_probe ( struct image *image ) {
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 }
323 
324 /** EFI image type */
325 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
326  .name = "EFI",
327  .probe = efi_image_probe,
328  .exec = efi_image_exec,
329 };
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:233
EFI file protocols.
#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
#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
#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
An executable image type.
Definition: image.h:76
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:129
size_t efi_devpath_len(EFI_DEVICE_PATH_PROTOCOL *path)
Find length of device path (excluding terminator)
Definition: efi_utils.c:59
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
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
EFI utilities.
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: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
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: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
Executable images.
void efi_wrap(EFI_HANDLE handle)
Wrap the calls made by a loaded image.
Definition: efi_wrap.c:550
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
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
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: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
size_t strlen(const char *src)
Get length of string.
Definition: string.c:213
static int efi_image_exec(struct image *image)
Execute EFI image.
Definition: efi_image.c:134
static void console_reset(void)
Reset console.
Definition: console.h:214
EFI_IMAGE_START StartImage
Definition: UefiSpec.h:1884
#define MEDIA_DEVICE_PATH
Definition: DevicePath.h:946
EFI API.
static wchar_t * efi_image_cmdline(struct image *image)
Create command line for image.
Definition: efi_image.c:111
#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:67
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:208
#define FALSE
Definition: tlan.h:45
static int efi_image_probe(struct image *image)
Probe EFI image.
Definition: efi_image.c:294
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:55
#define MEDIA_FILEPATH_DP
File Path Media Device Path SubType.
Definition: DevicePath.h:1035