efi_loader: implement support of exit data
In case of a failure exit data may be passed to Exit() which in turn is returned by StartImage(). Let the `bootefi` command print the exit data string in case of an error. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
45203e0ccb
commit
556d8dc937
@ -297,6 +297,8 @@ static efi_status_t efi_install_fdt(const char *fdt_opt)
|
||||
static efi_status_t do_bootefi_exec(efi_handle_t handle)
|
||||
{
|
||||
efi_status_t ret;
|
||||
efi_uintn_t exit_data_size = 0;
|
||||
u16 *exit_data = NULL;
|
||||
|
||||
/* Transfer environment variable as load options */
|
||||
ret = set_load_options(handle, "bootargs");
|
||||
@ -304,7 +306,12 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle)
|
||||
return ret;
|
||||
|
||||
/* Call our payload! */
|
||||
ret = EFI_CALL(efi_start_image(handle, NULL, NULL));
|
||||
ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
|
||||
printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK);
|
||||
if (ret && exit_data) {
|
||||
printf("## %ls\n", exit_data);
|
||||
efi_free_pool(exit_data);
|
||||
}
|
||||
|
||||
efi_restore_gd();
|
||||
|
||||
@ -357,7 +364,6 @@ static int do_efibootmgr(const char *fdt_opt)
|
||||
}
|
||||
|
||||
ret = do_bootefi_exec(handle);
|
||||
printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK);
|
||||
|
||||
if (ret != EFI_SUCCESS)
|
||||
return CMD_RET_FAILURE;
|
||||
@ -472,7 +478,6 @@ static int do_bootefi_image(const char *image_opt, const char *fdt_opt)
|
||||
goto out;
|
||||
|
||||
ret = do_bootefi_exec(handle);
|
||||
printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK);
|
||||
|
||||
out:
|
||||
if (mem_handle)
|
||||
|
@ -207,12 +207,17 @@ struct efi_object {
|
||||
* struct efi_loaded_image_obj - handle of a loaded image
|
||||
*
|
||||
* @header: EFI object header
|
||||
* @exit_status: exit status passed to Exit()
|
||||
* @exit_data_size: exit data size passed to Exit()
|
||||
* @exit_data: exit data passed to Exit()
|
||||
* @exit_jmp: long jump buffer for returning form started image
|
||||
* @entry: entry address of the relocated image
|
||||
*/
|
||||
struct efi_loaded_image_obj {
|
||||
struct efi_object header;
|
||||
efi_status_t exit_status;
|
||||
efi_uintn_t *exit_data_size;
|
||||
u16 **exit_data;
|
||||
struct jmp_buf_data exit_jmp;
|
||||
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
|
||||
struct efi_system_table *st);
|
||||
|
@ -2626,6 +2626,9 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
||||
|
||||
efi_is_direct_boot = false;
|
||||
|
||||
image_obj->exit_data_size = exit_data_size;
|
||||
image_obj->exit_data = exit_data;
|
||||
|
||||
/* call the image! */
|
||||
if (setjmp(&image_obj->exit_jmp)) {
|
||||
/*
|
||||
@ -2669,6 +2672,41 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
||||
return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_update_exit_data() - fill exit data parameters of StartImage()
|
||||
*
|
||||
* @image_obj image handle
|
||||
* @exit_data_size size of the exit data buffer
|
||||
* @exit_data buffer with data returned by UEFI payload
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_update_exit_data(struct efi_loaded_image_obj *image_obj,
|
||||
efi_uintn_t exit_data_size,
|
||||
u16 *exit_data)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
/*
|
||||
* If exit_data is not provided to StartImage(), exit_data_size must be
|
||||
* ignored.
|
||||
*/
|
||||
if (!image_obj->exit_data)
|
||||
return EFI_SUCCESS;
|
||||
if (image_obj->exit_data_size)
|
||||
*image_obj->exit_data_size = exit_data_size;
|
||||
if (exit_data_size && exit_data) {
|
||||
ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
|
||||
exit_data_size,
|
||||
(void **)image_obj->exit_data);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
memcpy(*image_obj->exit_data, exit_data, exit_data_size);
|
||||
} else {
|
||||
image_obj->exit_data = NULL;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_exit() - leave an EFI application or driver
|
||||
* @image_handle: handle of the application or driver that is exiting
|
||||
@ -2709,6 +2747,15 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/* Exit data is only foreseen in case of failure. */
|
||||
if (exit_status != EFI_SUCCESS) {
|
||||
ret = efi_update_exit_data(image_obj, exit_data_size,
|
||||
exit_data);
|
||||
/* Exiting has priority. Don't return error to caller. */
|
||||
if (ret != EFI_SUCCESS)
|
||||
EFI_PRINT("%s: out of memory\n", __func__);
|
||||
}
|
||||
|
||||
/* Make sure entry/exit counts for EFI world cross-overs match */
|
||||
EFI_EXIT(exit_status);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user