iPXE
efi_init.c File Reference
#include <string.h>
#include <errno.h>
#include <endian.h>
#include <ipxe/init.h>
#include <ipxe/rotate.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_table.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_path.h>
#include <ipxe/efi/efi_cmdline.h>
#include <ipxe/efi/Protocol/LoadedImage.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (PERMITTED)
EFI_SYSTEM_TABLE_C2 (PLATFORM, _systab)
 System table passed to entry point.
static EFI_STATUS EFIAPI efi_unload (EFI_HANDLE image_handle __unused)
 Shut down EFI environment.
static EFIAPI void efi_shutdown_hook (EFI_EVENT event __unused, void *context __unused)
 Shut down in preparation for booting an OS.
unsigned long efi_stack_cookie (EFI_HANDLE handle)
 Construct a stack cookie value.
EFI_STATUS efi_init (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
 Initialise EFI environment.
void __stack_chk_fail (void)
 Abort on stack check failure.
void efi_raise_tpl (struct efi_saved_tpl *tpl)
 Raise task priority level to internal level.
void efi_restore_tpl (struct efi_saved_tpl *tpl)
 Restore task priority level.

Variables

EFI_HANDLE efi_image_handle
 Image handle passed to entry point.
EFI_LOADED_IMAGE_PROTOCOLefi_loaded_image
 Loaded image protocol for this image.
EFI_DEVICE_PATH_PROTOCOLefi_loaded_image_path
 Device path for the loaded image's device handle.
EFI_TPL efi_internal_tpl = TPL_CALLBACK
 Internal task priority level.
EFI_TPL efi_external_tpl = TPL_APPLICATION
 External task priority level.
int efi_shutdown_in_progress
 EFI shutdown is in progress.
static EFI_EVENT efi_shutdown_event
 Event used to signal shutdown.
unsigned long __stack_chk_guard
 Stack cookie.
static EFI_EXIT efi_exit
 Exit function.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ _C2()

EFI_SYSTEM_TABLE * _C2 ( PLATFORM ,
_systab  )

System table passed to entry point.

We construct the symbol name efi_systab via the PLATFORM macro. This ensures that the symbol is defined only in EFI builds, and so prevents EFI code from being incorrectly linked in to a non-EFI build.

◆ efi_unload()

EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused)
static

Shut down EFI environment.

Parameters
image_handleImage handle

Definition at line 319 of file efi_init.c.

319 {
320 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
322 struct efi_saved_tpl tpl;
323
324 DBGC ( systab, "EFI image unloading\n" );
325
326 /* Raise TPL */
327 efi_raise_tpl ( &tpl );
328
329 /* Shut down */
331
332 /* Disconnect any remaining devices */
334
335 /* Uninstall driver binding protocol */
337
338 /* Uninstall exit boot services event */
340
341 /* Free copy of loaded image's device handle's device path */
343
344 DBGC ( systab, "EFI image unloaded\n" );
345
346 /* Restore TPL */
347 efi_restore_tpl ( &tpl );
348
349 return 0;
350}
void efi_driver_disconnect_all(void)
Disconnect EFI driver from all possible devices.
Definition efi_driver.c:648
void efi_driver_uninstall(void)
Uninstall EFI driver.
Definition efi_driver.c:421
EFI_DEVICE_PATH_PROTOCOL * efi_loaded_image_path
Device path for the loaded image's device handle.
Definition efi_init.c:42
void efi_raise_tpl(struct efi_saved_tpl *tpl)
Raise task priority level to internal level.
Definition efi_init.c:383
static EFI_EVENT efi_shutdown_event
Event used to signal shutdown.
Definition efi_init.c:63
void efi_restore_tpl(struct efi_saved_tpl *tpl)
Restore task priority level.
Definition efi_init.c:399
#define DBGC(...)
Definition compiler.h:505
EFI_SYSTEM_TABLE * efi_systab
static void shutdown_exit(void)
Shut down system for exit back to firmware.
Definition init.h:86
EFI Boot Services Table.
Definition UefiSpec.h:1931
EFI_FREE_POOL FreePool
Definition UefiSpec.h:1950
EFI_CLOSE_EVENT CloseEvent
Definition UefiSpec.h:1959
EFI System Table.
Definition UefiSpec.h:2044
An EFI saved task priority level.
Definition efi.h:80

References __unused, EFI_BOOT_SERVICES::CloseEvent, DBGC, efi_driver_disconnect_all(), efi_driver_uninstall(), EFI_HANDLE, efi_loaded_image_path, efi_raise_tpl(), efi_restore_tpl(), efi_shutdown_event, efi_systab, EFIAPI, EFI_BOOT_SERVICES::FreePool, and shutdown_exit().

Referenced by efi_init().

◆ efi_shutdown_hook()

EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
void *context __unused )
static

Shut down in preparation for booting an OS.

This hook gets called at ExitBootServices time in order to make sure that everything is properly shut down before the OS takes over.

Definition at line 85 of file efi_init.c.

86 {
87
88 /* This callback is invoked at TPL_NOTIFY in order to ensure
89 * that we have an opportunity to shut down cleanly before
90 * other shutdown hooks perform destructive operations such as
91 * disabling the IOMMU.
92 *
93 * Modify the internal task priority level so that no code
94 * attempts to raise from TPL_NOTIFY to TPL_CALLBACK (which
95 * would trigger a fatal exception).
96 */
98
99 /* Mark shutdown as being in progress, to indicate that large
100 * parts of the system (e.g. timers) are no longer functional.
101 */
103
104 /* Shut down iPXE */
106}
#define TPL_NOTIFY
Definition UefiSpec.h:650
EFI_TPL efi_internal_tpl
Internal task priority level.
Definition efi_init.c:54
int efi_shutdown_in_progress
EFI shutdown is in progress.
Definition efi_init.c:60
static void shutdown_boot(void)
Shut down system for OS boot.
Definition init.h:78

References __unused, EFI_EVENT, efi_internal_tpl, efi_shutdown_in_progress, EFIAPI, shutdown_boot(), and TPL_NOTIFY.

Referenced by efi_init().

◆ efi_stack_cookie()

unsigned long efi_stack_cookie ( EFI_HANDLE handle)

Construct a stack cookie value.

Parameters
handleImage handle
Return values
cookieStack cookie

Definition at line 115 of file efi_init.c.

115 {
116 unsigned long cookie = 0;
117 unsigned int rotation = ( 8 * sizeof ( cookie ) / 4 );
118
119 /* There is no viable source of entropy available at this
120 * point. Construct a value that is at least likely to vary
121 * between platforms and invocations.
122 */
123 cookie ^= ( ( unsigned long ) handle );
124 cookie = roll ( cookie, rotation );
125 cookie ^= ( ( unsigned long ) &handle );
126 cookie = roll ( cookie, rotation );
127 cookie ^= profile_timestamp();
128 cookie = roll ( cookie, rotation );
129 cookie ^= build_id;
130
131 /* Ensure that the value contains a NUL byte, to act as a
132 * runaway string terminator. Construct the NUL using a shift
133 * rather than a mask, to avoid losing valuable entropy in the
134 * lower-order bits.
135 */
136 cookie <<= 8;
137
138 /* Ensure that the NUL byte is placed at the bottom of the
139 * stack cookie, to avoid potential disclosure via an
140 * unterminated string.
141 */
142 if ( __BYTE_ORDER == __BIG_ENDIAN )
143 cookie >>= 8;
144
145 return cookie;
146}
#define __BYTE_ORDER
Definition endian.h:7
#define __BIG_ENDIAN
Constant representing big-endian byte order.
Definition endian.h:22
unsigned long profile_timestamp(void)
uint16_t handle
Handle.
Definition smbios.h:5
static unsigned int rotation
Definition rotate.h:23
unsigned long build_id
Build ID.
Definition version.c:62

References __BIG_ENDIAN, __BYTE_ORDER, build_id, EFI_HANDLE, handle, profile_timestamp(), and rotation.

Referenced by efi_init_stack_guard().

◆ efi_init()

EFI_STATUS efi_init ( EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE * systab )

Initialise EFI environment.

Parameters
image_handleImage handle
systabSystem table
Return values
efircEFI return status code

Definition at line 155 of file efi_init.c.

156 {
158 struct efi_protocol *prot;
159 struct efi_config_table *tab;
161 void *device_path_copy;
162 size_t device_path_len;
163 EFI_STATUS efirc;
164 int rc;
165
166 /* Store image handle and system table pointer for future use */
167 efi_image_handle = image_handle;
168 efi_systab = systab;
169
170 /* Sanity checks */
171 if ( ! systab ) {
172 efirc = EFI_NOT_AVAILABLE_YET;
173 goto err_sanity;
174 }
175 if ( ! systab->ConOut ) {
176 efirc = EFI_NOT_AVAILABLE_YET;
177 goto err_sanity;
178 }
179 if ( ! systab->BootServices ) {
180 DBGC ( systab, "EFI provided no BootServices entry point\n" );
181 efirc = EFI_NOT_AVAILABLE_YET;
182 goto err_sanity;
183 }
184 if ( ! systab->RuntimeServices ) {
185 DBGC ( systab, "EFI provided no RuntimeServices entry "
186 "point\n" );
187 efirc = EFI_NOT_AVAILABLE_YET;
188 goto err_sanity;
189 }
190 DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
191 bs = systab->BootServices;
192
193 /* Store abort function pointer */
194 efi_exit = bs->Exit;
195
196 /* Look up used protocols */
198 if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL,
199 prot->protocol ) ) == 0 ) {
200 DBGC ( systab, "EFI protocol %s is at %p\n",
201 efi_guid_ntoa ( &prot->guid ),
202 *(prot->protocol) );
203 } else {
204 DBGC ( systab, "EFI does not provide protocol %s\n",
205 efi_guid_ntoa ( &prot->guid ) );
206 /* Fail if protocol is required */
207 if ( prot->required )
208 goto err_missing_protocol;
209 }
210 }
211
212 /* Look up used configuration tables */
214 if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) {
215 DBGC ( systab, "EFI configuration table %s is at %p\n",
216 efi_guid_ntoa ( &tab->guid ), *(tab->table) );
217 } else {
218 DBGC ( systab, "EFI does not provide configuration "
219 "table %s\n", efi_guid_ntoa ( &tab->guid ) );
220 if ( tab->required ) {
221 efirc = EFI_NOT_AVAILABLE_YET;
222 goto err_missing_table;
223 }
224 }
225 }
226
227 /* Get loaded image protocol
228 *
229 * We assume that our loaded image protocol will not be
230 * uninstalled while our image code is still running.
231 */
232 if ( ( rc = efi_open_unsafe ( image_handle,
234 &efi_loaded_image ) ) != 0 ) {
235 DBGC ( systab, "EFI could not get loaded image protocol: %s",
236 strerror ( rc ) );
237 efirc = EFIRC ( rc );
238 goto err_no_loaded_image;
239 }
240 DBGC ( systab, "EFI image base address %p\n",
241 efi_loaded_image->ImageBase );
242
243 /* Record command line */
244 efi_cmdline = efi_loaded_image->LoadOptions;
245 efi_cmdline_len = efi_loaded_image->LoadOptionsSize;
246
247 /* Get loaded image's device handle's device path */
248 if ( ( rc = efi_open ( efi_loaded_image->DeviceHandle,
250 &device_path ) ) != 0 ) {
251 DBGC ( systab, "EFI could not get loaded image's device path: "
252 "%s", strerror ( rc ) );
253 efirc = EFIRC ( rc );
254 goto err_no_device_path;
255 }
256
257 /* Make a copy of the loaded image's device handle's device
258 * path, since the device handle itself may become invalidated
259 * when we load our own drivers.
260 */
261 device_path_len = ( efi_path_len ( device_path ) +
262 sizeof ( EFI_DEVICE_PATH_PROTOCOL ) );
263 if ( ( efirc = bs->AllocatePool ( EfiBootServicesData, device_path_len,
264 &device_path_copy ) ) != 0 ) {
265 rc = -EEFI ( efirc );
266 goto err_alloc_device_path;
267 }
268 memcpy ( device_path_copy, device_path, device_path_len );
269 efi_loaded_image_path = device_path_copy;
270 DBGC ( systab, "EFI image device path %s\n",
272
273 /* EFI is perfectly capable of gracefully shutting down any
274 * loaded devices if it decides to fall back to a legacy boot.
275 * For no particularly comprehensible reason, it doesn't
276 * bother doing so when ExitBootServices() is called.
277 */
278 if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
280 NULL, &efi_shutdown_event ) ) != 0 ) {
281 rc = -EEFI ( efirc );
282 DBGC ( systab, "EFI could not create ExitBootServices event: "
283 "%s\n", strerror ( rc ) );
284 goto err_create_event;
285 }
286
287 /* Install driver binding protocol */
288 if ( ( rc = efi_driver_install() ) != 0 ) {
289 DBGC ( systab, "EFI could not install driver: %s\n",
290 strerror ( rc ) );
291 efirc = EFIRC ( rc );
292 goto err_driver_install;
293 }
294
295 /* Install image unload method */
297
298 return 0;
299
301 err_driver_install:
303 err_create_event:
305 err_alloc_device_path:
306 err_no_device_path:
307 err_no_loaded_image:
308 err_missing_table:
309 err_missing_protocol:
310 err_sanity:
311 return efirc;
312}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define EFI_NOT_AVAILABLE_YET
If this value is returned by an API, it means the capability is not yet installed/available/ready to ...
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
@ EfiBootServicesData
The data portions of a loaded Boot Serves Driver, and the default data allocation type used by a Boot...
#define EVT_SIGNAL_EXIT_BOOT_SERVICES
Definition UefiSpec.h:456
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
union edd_device_path device_path
Device path.
Definition edd.h:13
size_t efi_cmdline_len
Length of EFI command line (in bytes)
Definition efi_cmdline.c:49
const wchar_t * efi_cmdline
EFI command line (may not be wNUL-terminated.
Definition efi_cmdline.c:46
const char * efi_devpath_text(EFI_DEVICE_PATH_PROTOCOL *path)
Get textual representation of device path.
Definition efi_debug.c:247
int efi_driver_install(void)
Install EFI driver.
Definition efi_driver.c:388
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition efi_guid.c:273
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition efi_guid.c:726
EFI_GUID efi_device_path_protocol_guid
Device path protocol GUID.
Definition efi_guid.c:169
static EFI_EXIT efi_exit
Exit function.
Definition efi_init.c:73
static EFI_STATUS EFIAPI efi_unload(EFI_HANDLE image_handle)
Shut down EFI environment.
Definition efi_init.c:319
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:85
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
size_t efi_path_len(EFI_DEVICE_PATH_PROTOCOL *path)
Find length of device path (excluding terminator)
Definition efi_path.c:174
void * efi_find_table(EFI_GUID *guid)
Look up EFI configuration table.
Definition efi_table.c:45
#define EFI_PROTOCOLS
EFI protocol table.
Definition efi.h:98
#define efi_open(handle, protocol, interface)
Open protocol for ephemeral use.
Definition efi.h:444
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition efi.h:167
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:175
#define efi_open_unsafe(handle, protocol, interface)
Open protocol for unsafe persistent use.
Definition efi.h:459
#define EFI_CONFIG_TABLES
EFI configuration table table.
Definition efi.h:142
void * memcpy(void *dest, const void *src, size_t len) __nonnull
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
EFI_CREATE_EVENT CreateEvent
Definition UefiSpec.h:1955
EFI_LOCATE_PROTOCOL LocateProtocol
Definition UefiSpec.h:2009
EFI_ALLOCATE_POOL AllocatePool
Definition UefiSpec.h:1949
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition DevicePath.h:46
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition UefiSpec.h:2099
EFI_RUNTIME_SERVICES * RuntimeServices
A pointer to the EFI Runtime Services Table.
Definition UefiSpec.h:2095
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with ConsoleOutHandle.
Definition UefiSpec.h:2080
An EFI configuration table used by iPXE.
Definition efi.h:132
int required
Table is required for operation.
Definition efi.h:138
void ** table
Variable containing pointer to configuration table.
Definition efi.h:136
EFI_GUID guid
GUID.
Definition efi.h:134
An EFI protocol used by iPXE.
Definition efi.h:88
EFI_GUID guid
GUID.
Definition efi.h:90
int required
Protocol is required.
Definition efi.h:94
void ** protocol
Variable containing pointer to protocol structure.
Definition efi.h:92
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References EFI_BOOT_SERVICES::AllocatePool, EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseEvent, EFI_SYSTEM_TABLE::ConOut, EFI_BOOT_SERVICES::CreateEvent, DBGC, device_path, EEFI, efi_cmdline, efi_cmdline_len, EFI_CONFIG_TABLES, efi_device_path_protocol_guid, efi_devpath_text(), efi_driver_install(), efi_driver_uninstall(), efi_exit, efi_find_table(), efi_guid_ntoa(), EFI_HANDLE, efi_image_handle, efi_loaded_image, efi_loaded_image_path, efi_loaded_image_protocol_guid, EFI_NOT_AVAILABLE_YET, efi_open, efi_open_unsafe, efi_path_len(), EFI_PROTOCOLS, efi_shutdown_event, efi_shutdown_hook(), efi_systab, efi_unload(), EfiBootServicesData, EFIRC, EVT_SIGNAL_EXIT_BOOT_SERVICES, EFI_BOOT_SERVICES::Exit, for_each_table_entry, EFI_BOOT_SERVICES::FreePool, efi_config_table::guid, efi_protocol::guid, EFI_BOOT_SERVICES::LocateProtocol, memcpy(), NULL, efi_protocol::protocol, rc, efi_config_table::required, efi_protocol::required, EFI_SYSTEM_TABLE::RuntimeServices, strerror(), efi_config_table::table, and TPL_NOTIFY.

Referenced by _efi_start(), and _efidrv_start().

◆ __stack_chk_fail()

void __stack_chk_fail ( void )

Abort on stack check failure.

Definition at line 356 of file efi_init.c.

356 {
357 EFI_STATUS efirc;
358 int rc;
359
360 /* Report failure (when debugging) */
361 DBGC ( efi_systab, "EFI stack check failed (cookie %#lx); aborting\n",
363
364 /* Attempt to exit cleanly with an error status */
365 if ( efi_exit ) {
367 0, NULL );
368 rc = -EEFI ( efirc );
369 DBGC ( efi_systab, "EFI stack check exit failed: %s\n",
370 strerror ( rc ) );
371 }
372
373 /* If the exit fails for any reason, lock the system */
374 while ( 1 ) {}
375
376}
#define EFI_COMPROMISED_DATA
Enumeration of EFI_STATUS.
unsigned long __stack_chk_guard
Stack cookie.
Definition efi_init.c:66

References __stack_chk_guard, DBGC, EEFI, EFI_COMPROMISED_DATA, efi_exit, efi_image_handle, efi_systab, NULL, rc, and strerror().

◆ efi_raise_tpl()

void efi_raise_tpl ( struct efi_saved_tpl * tpl)

Raise task priority level to internal level.

Parameters
tplSaved TPL

Definition at line 383 of file efi_init.c.

383 {
384 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
385
386 /* Record current external TPL */
388
389 /* Raise TPL and record previous TPL as new external TPL */
390 tpl->current = bs->RaiseTPL ( efi_internal_tpl );
392}
EFI_TPL efi_external_tpl
External task priority level.
Definition efi_init.c:57
EFI_RAISE_TPL RaiseTPL
Definition UefiSpec.h:1940
EFI_TPL previous
Previous external TPL.
Definition efi.h:84
EFI_TPL current
Current external TPL.
Definition efi.h:82

References efi_saved_tpl::current, efi_external_tpl, efi_internal_tpl, efi_systab, efi_saved_tpl::previous, and EFI_BOOT_SERVICES::RaiseTPL.

Referenced by _efidrv_start(), efi_driver_start(), efi_driver_stop(), efi_snp_add_claim(), efi_snp_get_status(), efi_snp_initialize(), efi_snp_receive(), efi_snp_reset(), efi_snp_shutdown(), efi_snp_transmit(), efi_snp_wait_for_packet(), efi_unload(), efi_usb_async_interrupt_transfer(), efi_usb_bulk_transfer(), efi_usb_control_transfer(), efi_usb_get_string_descriptor(), efi_usb_sync_interrupt_transfer(), efi_vlan_find(), efi_vlan_remove(), and efi_vlan_set().

◆ efi_restore_tpl()

Variable Documentation

◆ efi_image_handle

◆ efi_loaded_image

◆ efi_loaded_image_path

EFI_DEVICE_PATH_PROTOCOL* efi_loaded_image_path

Device path for the loaded image's device handle.

Definition at line 42 of file efi_init.c.

Referenced by efi_init(), efi_init_application(), efi_local_open_volume(), efi_path_net_probe(), and efi_unload().

◆ efi_internal_tpl

EFI_TPL efi_internal_tpl = TPL_CALLBACK

Internal task priority level.

Definition at line 54 of file efi_init.c.

Referenced by efi_connect(), efi_currticks(), efi_disconnect(), efi_entropy_disable(), efi_raise_tpl(), efi_shutdown_hook(), and nii_issue_cpb_db().

◆ efi_external_tpl

EFI_TPL efi_external_tpl = TPL_APPLICATION

External task priority level.

Definition at line 57 of file efi_init.c.

Referenced by efi_connect(), efi_currticks(), efi_disconnect(), efi_entropy_enable(), efi_raise_tpl(), and efi_restore_tpl().

◆ efi_shutdown_in_progress

◆ efi_shutdown_event

EFI_EVENT efi_shutdown_event
static

Event used to signal shutdown.

Definition at line 63 of file efi_init.c.

Referenced by efi_init(), and efi_unload().

◆ __stack_chk_guard

unsigned long __stack_chk_guard

Stack cookie.

Definition at line 66 of file efi_init.c.

Referenced by __stack_chk_fail(), and efi_init_stack_guard().

◆ efi_exit

EFI_EXIT efi_exit
static

Exit function.

Cached to minimise external dependencies when a stack check failure is triggered.

Definition at line 73 of file efi_init.c.

Referenced by __stack_chk_fail(), and efi_init().