diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index d3a233187028a20991b06e79f6a1486865289f36..2a62dce702bb91fed403c2c63e521216ad2e7239 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 20035d727272966078a9f26627a2048b14d142e9..f572b8807983610851456d50893add1e1842ebae 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 9daca50a72fc1b7c92212c30bcbb7aed5d34e6b0..15a1b90d65a6b4a3987691b3933796d6c2d916fb 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,