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:
Heinrich Schuchardt
2019-04-30 17:57:30 +02:00
parent 45203e0ccb
commit 556d8dc937
3 changed files with 60 additions and 3 deletions

View File

@@ -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);