forked from pool/u-boot
c5a1053428
1 OBS-URL: https://build.opensuse.org/request/show/405463 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/u-boot?expand=0&rev=76
113 lines
3.4 KiB
Diff
113 lines
3.4 KiB
Diff
From e73c13b8b235ade604cb3a6c7ff8da4ef1038b58 Mon Sep 17 00:00:00 2001
|
|
From: Alexander Graf <agraf@suse.de>
|
|
Date: Fri, 20 May 2016 23:24:20 +0200
|
|
Subject: [PATCH] efi_loader: Add exit support
|
|
|
|
Some times you may want to exit an EFI payload again, for example
|
|
to default boot into a PXE installation and decide that you would
|
|
rather want to boot from the local disk instead.
|
|
|
|
This patch adds exit functionality to the EFI implementation, allowing
|
|
EFI payloads to exit.
|
|
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
cmd/bootefi.c | 6 ++++++
|
|
include/efi_api.h | 10 ++++++++++
|
|
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 7546d0a..27ac242 100644
|
|
--- a/cmd/bootefi.c
|
|
+++ b/cmd/bootefi.c
|
|
@@ -206,6 +206,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 51d7586..029c830 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,
|