iPXE
efi_init.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 <string.h>
23 #include <errno.h>
24 #include <endian.h>
25 #include <ipxe/init.h>
26 #include <ipxe/rotate.h>
27 #include <ipxe/efi/efi.h>
28 #include <ipxe/efi/efi_driver.h>
30 
31 /** Image handle passed to entry point */
33 
34 /** Loaded image protocol for this image */
36 
37 /** System table passed to entry point
38  *
39  * We construct the symbol name efi_systab via the PLATFORM macro.
40  * This ensures that the symbol is defined only in EFI builds, and so
41  * prevents EFI code from being incorrectly linked in to a non-EFI
42  * build.
43  */
44 EFI_SYSTEM_TABLE * _C2 ( PLATFORM, _systab );
45 
46 /** EFI shutdown is in progress */
48 
49 /** Event used to signal shutdown */
51 
52 /** Stack cookie */
53 unsigned long __stack_chk_guard;
54 
55 /** Exit function
56  *
57  * Cached to minimise external dependencies when a stack check
58  * failure is triggered.
59  */
61 
62 /* Forward declarations */
63 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
64 
65 /**
66  * Shut down in preparation for booting an OS.
67  *
68  * This hook gets called at ExitBootServices time in order to make
69  * sure that everything is properly shut down before the OS takes
70  * over.
71  */
73  void *context __unused ) {
74 
75  /* Mark shutdown as being in progress, to indicate that large
76  * parts of the system (e.g. timers) are no longer functional.
77  */
79 
80  /* Shut down iPXE */
81  shutdown_boot();
82 }
83 
84 /**
85  * Look up EFI configuration table
86  *
87  * @v guid Configuration table GUID
88  * @ret table Configuration table, or NULL
89  */
90 static void * efi_find_table ( EFI_GUID *guid ) {
91  unsigned int i;
92 
93  for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
95  guid, sizeof ( *guid ) ) == 0 )
97  }
98 
99  return NULL;
100 }
101 
102 /**
103  * Construct a stack cookie value
104  *
105  * @v handle Image handle
106  * @ret cookie Stack cookie
107  */
108 __attribute__ (( noinline )) unsigned long
110  unsigned long cookie = 0;
111  unsigned int rotation = ( 8 * sizeof ( cookie ) / 4 );
112 
113  /* There is no viable source of entropy available at this
114  * point. Construct a value that is at least likely to vary
115  * between platforms and invocations.
116  */
117  cookie ^= ( ( unsigned long ) handle );
118  cookie = roll ( cookie, rotation );
119  cookie ^= ( ( unsigned long ) &handle );
120  cookie = roll ( cookie, rotation );
121  cookie ^= profile_timestamp();
122  cookie = roll ( cookie, rotation );
123  cookie ^= build_id;
124 
125  /* Ensure that the value contains a NUL byte, to act as a
126  * runaway string terminator. Construct the NUL using a shift
127  * rather than a mask, to avoid losing valuable entropy in the
128  * lower-order bits.
129  */
130  cookie <<= 8;
131 
132  /* Ensure that the NUL byte is placed at the bottom of the
133  * stack cookie, to avoid potential disclosure via an
134  * unterminated string.
135  */
136  if ( __BYTE_ORDER == __BIG_ENDIAN )
137  cookie >>= 8;
138 
139  return cookie;
140 }
141 
142 /**
143  * Initialise EFI environment
144  *
145  * @v image_handle Image handle
146  * @v systab System table
147  * @ret efirc EFI return status code
148  */
150  EFI_SYSTEM_TABLE *systab ) {
151  EFI_BOOT_SERVICES *bs;
152  struct efi_protocol *prot;
153  struct efi_config_table *tab;
154  void *loaded_image;
155  EFI_STATUS efirc;
156  int rc;
157 
158  /* Store image handle and system table pointer for future use */
159  efi_image_handle = image_handle;
160  efi_systab = systab;
161 
162  /* Sanity checks */
163  if ( ! systab ) {
164  efirc = EFI_NOT_AVAILABLE_YET;
165  goto err_sanity;
166  }
167  if ( ! systab->ConOut ) {
168  efirc = EFI_NOT_AVAILABLE_YET;
169  goto err_sanity;
170  }
171  if ( ! systab->BootServices ) {
172  DBGC ( systab, "EFI provided no BootServices entry point\n" );
173  efirc = EFI_NOT_AVAILABLE_YET;
174  goto err_sanity;
175  }
176  if ( ! systab->RuntimeServices ) {
177  DBGC ( systab, "EFI provided no RuntimeServices entry "
178  "point\n" );
179  efirc = EFI_NOT_AVAILABLE_YET;
180  goto err_sanity;
181  }
182  DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
183  bs = systab->BootServices;
184 
185  /* Store abort function pointer */
186  efi_exit = bs->Exit;
187 
188  /* Look up used protocols */
190  if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL,
191  prot->protocol ) ) == 0 ) {
192  DBGC ( systab, "EFI protocol %s is at %p\n",
193  efi_guid_ntoa ( &prot->guid ),
194  *(prot->protocol) );
195  } else {
196  DBGC ( systab, "EFI does not provide protocol %s\n",
197  efi_guid_ntoa ( &prot->guid ) );
198  /* Fail if protocol is required */
199  if ( prot->required )
200  goto err_missing_protocol;
201  }
202  }
203 
204  /* Look up used configuration tables */
206  if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) {
207  DBGC ( systab, "EFI configuration table %s is at %p\n",
208  efi_guid_ntoa ( &tab->guid ), *(tab->table) );
209  } else {
210  DBGC ( systab, "EFI does not provide configuration "
211  "table %s\n", efi_guid_ntoa ( &tab->guid ) );
212  if ( tab->required ) {
213  efirc = EFI_NOT_AVAILABLE_YET;
214  goto err_missing_table;
215  }
216  }
217  }
218 
219  /* Get loaded image protocol */
220  if ( ( efirc = bs->OpenProtocol ( image_handle,
222  &loaded_image, image_handle, NULL,
223  EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
224  rc = -EEFI ( efirc );
225  DBGC ( systab, "EFI could not get loaded image protocol: %s",
226  strerror ( rc ) );
227  goto err_no_loaded_image;
228  }
229  efi_loaded_image = loaded_image;
230  DBGC ( systab, "EFI image base address %p\n",
232 
233  /* EFI is perfectly capable of gracefully shutting down any
234  * loaded devices if it decides to fall back to a legacy boot.
235  * For no particularly comprehensible reason, it doesn't
236  * bother doing so when ExitBootServices() is called.
237  */
238  if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
240  NULL, &efi_shutdown_event ) ) != 0 ) {
241  rc = -EEFI ( efirc );
242  DBGC ( systab, "EFI could not create ExitBootServices event: "
243  "%s\n", strerror ( rc ) );
244  goto err_create_event;
245  }
246 
247  /* Install driver binding protocol */
248  if ( ( rc = efi_driver_install() ) != 0 ) {
249  DBGC ( systab, "EFI could not install driver: %s\n",
250  strerror ( rc ) );
251  efirc = EFIRC ( rc );
252  goto err_driver_install;
253  }
254 
255  /* Install image unload method */
257 
258  return 0;
259 
261  err_driver_install:
263  err_create_event:
264  err_no_loaded_image:
265  err_missing_table:
266  err_missing_protocol:
267  err_sanity:
268  return efirc;
269 }
270 
271 /**
272  * Shut down EFI environment
273  *
274  * @v image_handle Image handle
275  */
276 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
278  EFI_SYSTEM_TABLE *systab = efi_systab;
279 
280  DBGC ( systab, "EFI image unloading\n" );
281 
282  /* Shut down */
283  shutdown_exit();
284 
285  /* Disconnect any remaining devices */
287 
288  /* Uninstall driver binding protocol */
290 
291  /* Uninstall exit boot services event */
293 
294  DBGC ( systab, "EFI image unloaded\n" );
295 
296  return 0;
297 }
298 
299 /**
300  * Abort on stack check failure
301  *
302  */
303 __attribute__ (( noreturn )) void __stack_chk_fail ( void ) {
304  EFI_STATUS efirc;
305  int rc;
306 
307  /* Report failure (when debugging) */
308  DBGC ( efi_systab, "EFI stack check failed (cookie %#lx); aborting\n",
310 
311  /* Attempt to exit cleanly with an error status */
312  if ( efi_exit ) {
314  0, NULL );
315  rc = -EEFI ( efirc );
316  DBGC ( efi_systab, "EFI stack check exit failed: %s\n",
317  strerror ( rc ) );
318  }
319 
320  /* If the exit fails for any reason, lock the system */
321  while ( 1 ) {}
322 
323 }
void efi_driver_uninstall(void)
Uninstall EFI driver.
Definition: efi_driver.c:419
#define __attribute__(x)
Definition: compiler.h:10
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
void ** protocol
Variable containing pointer to protocol structure.
Definition: efi.h:76
EFI_LOADED_IMAGE_PROTOCOL * efi_loaded_image
Loaded image protocol for this image.
Definition: efi_init.c:35
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:159
EFI driver interface.
EFI_LOCATE_PROTOCOL LocateProtocol
Definition: UefiSpec.h:1914
128 bit buffer containing a unique identifier value.
Definition: Base.h:263
Error codes.
VOID * EFI_EVENT
Handle to an event structure.
Definition: UefiBaseType.h:43
EFI_GUID VendorGuid
The 128-bit GUID value that uniquely identifies the system configuration table.
Definition: UefiSpec.h:1939
EFI_GUID guid
GUID.
Definition: efi.h:74
#define __BYTE_ORDER
Definition: endian.h:6
#define DBGC(...)
Definition: compiler.h:505
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition: efi_guid.c:184
EFI_CLOSE_EVENT CloseEvent
Definition: UefiSpec.h:1864
VOID * ImageBase
The base address at which the image was loaded.
Definition: LoadedImage.h:75
#define EFI_PROTOCOLS
EFI protocol table.
Definition: efi.h:82
FILE_LICENCE(GPL2_OR_LATER)
#define EVT_SIGNAL_EXIT_BOOT_SERVICES
Definition: UefiSpec.h:396
UEFI 2.0 Loaded image protocol definition.
#define EFI_CONFIG_TABLES
EFI configuration table table.
Definition: efi.h:126
An EFI configuration table used by iPXE.
Definition: efi.h:116
EFI_STATUS(EFIAPI * EFI_EXIT)(IN EFI_HANDLE ImageHandle, IN EFI_STATUS ExitStatus, IN UINTN ExitDataSize, IN CHAR16 *ExitData OPTIONAL)
Terminates a loaded EFI image and returns control to boot services.
Definition: UefiSpec.h:925
#define EFI_NOT_AVAILABLE_YET
If this value is returned by an API, it means the capability is not yet installed/available/ready to ...
Definition: PiMultiPhase.h:55
Can be used on any image handle to obtain information about the loaded image.
Definition: LoadedImage.h:51
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with ConsoleOutHandle.
Definition: UefiSpec.h:1982
static EFI_EVENT efi_shutdown_event
Event used to signal shutdown.
Definition: efi_init.c:50
unsigned long build_id
Build ID.
Definition: version.c:60
static EFIAPI void efi_shutdown_hook(EFI_EVENT event __unused, void *context __unused)
Shut down in preparation for booting an OS.
Definition: efi_init.c:72
#define EFI_COMPROMISED_DATA
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:151
EFI_CREATE_EVENT CreateEvent
Definition: UefiSpec.h:1860
static void * efi_find_table(EFI_GUID *guid)
Look up EFI configuration table.
Definition: efi_init.c:90
static void shutdown_exit(void)
Shut down system for exit back to firmware.
Definition: init.h:84
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
#define __BIG_ENDIAN
Constant representing big-endian byte order.
Definition: endian.h:18
An EFI protocol used by iPXE.
Definition: efi.h:72
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define EFIAPI
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:32
EFI_IMAGE_UNLOAD Unload
Definition: LoadedImage.h:79
void efi_driver_disconnect_all(void)
Disconnect EFI driver from all possible devices.
Definition: efi_driver.c:585
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
#define TPL_CALLBACK
Definition: UefiSpec.h:591
EFI System Table.
Definition: UefiSpec.h:1949
unsigned long __stack_chk_guard
Stack cookie.
Definition: efi_init.c:53
static unsigned int rotation
Definition: rotate.h:22
EFI API.
void ** table
Variable containing pointer to configuration table.
Definition: efi.h:120
uint64_t guid
GUID.
Definition: edd.h:30
int required
Protocol is required.
Definition: efi.h:78
const char * efi_guid_ntoa(EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_debug.c:192
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
EFI_RUNTIME_SERVICES * RuntimeServices
A pointer to the EFI Runtime Services Table.
Definition: UefiSpec.h:1996
EFI_GUID guid
GUID.
Definition: efi.h:118
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
UINTN NumberOfTableEntries
The number of system configuration tables in the buffer ConfigurationTable.
Definition: UefiSpec.h:2004
EFI_STATUS efi_init(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
Initialise EFI environment.
Definition: efi_init.c:149
static EFI_EXIT efi_exit
Exit function.
Definition: efi_init.c:60
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
EFI_SYSTEM_TABLE * _C2(PLATFORM, _systab)
System table passed to entry point.
unsigned long efi_stack_cookie(EFI_HANDLE handle)
Construct a stack cookie value.
Definition: efi_init.c:109
int required
Table is required for operation.
Definition: efi.h:122
static EFI_STATUS EFIAPI efi_unload(EFI_HANDLE image_handle)
Shut down EFI environment.
Definition: efi_init.c:276
void __stack_chk_fail(void)
Abort on stack check failure.
Definition: efi_init.c:303
static void shutdown_boot(void)
Shut down system for OS boot.
Definition: init.h:76
uint16_t handle
Handle.
Definition: smbios.h:16
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:113
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
String functions.
int efi_driver_install(void)
Install EFI driver.
Definition: efi_driver.c:386
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition: efi.h:151
Definition: efi.h:55
Bit operations.
EFI_CONFIGURATION_TABLE * ConfigurationTable
A pointer to the system configuration tables.
Definition: UefiSpec.h:2009
int efi_shutdown_in_progress
EFI shutdown is in progress.
Definition: efi_init.c:47
VOID * VendorTable
A pointer to the table associated with VendorGuid.
Definition: UefiSpec.h:1943