diff options
-rw-r--r-- | cmd/bootefi.c | 6 | ||||
-rw-r--r-- | include/efi_api.h | 10 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 21 |
3 files changed, 32 insertions, 5 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d3a2331..2a62dce 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -209,6 +209,12 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) #ifdef DEBUG_EFI printf("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); #endif + + if (setjmp(&loaded_image_info.exit_jmp)) { + efi_status_t status = loaded_image_info.exit_status; + return status == EFI_SUCCESS ? 0 : -EINVAL; + } + return entry(&loaded_image_info, &systab); } diff --git a/include/efi_api.h b/include/efi_api.h index 20035d7..f572b88 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -17,6 +17,10 @@ #include <efi.h> +#ifdef CONFIG_EFI_LOADER +#include <asm/setjmp.h> +#endif + /* Types and defines for EFI CreateEvent */ enum efi_event_type { EFI_TIMER_STOP = 0, @@ -239,6 +243,12 @@ struct efi_loaded_image { unsigned int image_code_type; unsigned int image_data_type; unsigned long unload; + + /* Below are efi loader private fields */ +#ifdef CONFIG_EFI_LOADER + efi_status_t exit_status; + struct jmp_buf_data exit_jmp; +#endif }; #define DEVICE_PATH_GUID \ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 9daca50..15a1b90 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -458,19 +458,30 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, efi_is_direct_boot = false; /* call the image! */ + if (setjmp(&info->exit_jmp)) { + /* We returned from the child image */ + return EFI_EXIT(info->exit_status); + } + entry(image_handle, &systab); /* Should usually never get here */ return EFI_EXIT(EFI_SUCCESS); } -static efi_status_t EFIAPI efi_exit(void *image_handle, long exit_status, - unsigned long exit_data_size, - uint16_t *exit_data) +static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, + efi_status_t exit_status, unsigned long exit_data_size, + int16_t *exit_data) { + struct efi_loaded_image *loaded_image_info = (void*)image_handle; + EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data); - return EFI_EXIT(efi_unsupported(__func__)); + + loaded_image_info->exit_status = exit_status; + longjmp(&loaded_image_info->exit_jmp); + + panic("EFI application exited"); } static struct efi_object *efi_search_obj(void *handle) @@ -746,7 +757,7 @@ static const struct efi_boot_services efi_boot_services = { .install_configuration_table = efi_install_configuration_table, .load_image = efi_load_image, .start_image = efi_start_image, - .exit = (void*)efi_exit, + .exit = efi_exit, .unload_image = efi_unload_image, .exit_boot_services = efi_exit_boot_services, .get_next_monotonic_count = efi_get_next_monotonic_count, |