From 126a43f15b3627d39e71636f93c500d57adeb28a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 1 May 2019 20:07:04 +0200 Subject: efi_loader: unload applications upon Exit() Implement unloading of images in the Exit() boot services: * unload images that are not yet started, * unload started applications, * unload drivers returning an error. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'lib/efi_loader/efi_boottime.c') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 0385883ded2..1ea96dab6c3 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -13,6 +13,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -2798,7 +2799,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, * image protocol. */ efi_status_t ret; - void *info; + struct efi_loaded_image *loaded_image_protocol; struct efi_loaded_image_obj *image_obj = (struct efi_loaded_image_obj *)image_handle; @@ -2806,13 +2807,33 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, exit_data_size, exit_data); /* Check parameters */ - if (image_handle != current_image) - goto out; ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image, - &info, NULL, NULL, + (void **)&loaded_image_protocol, + NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)); - if (ret != EFI_SUCCESS) + if (ret != EFI_SUCCESS) { + ret = EFI_INVALID_PARAMETER; goto out; + } + + /* Unloading of unstarted images */ + switch (image_obj->header.type) { + case EFI_OBJECT_TYPE_STARTED_IMAGE: + break; + case EFI_OBJECT_TYPE_LOADED_IMAGE: + efi_delete_image(image_obj, loaded_image_protocol); + ret = EFI_SUCCESS; + goto out; + default: + /* Handle does not refer to loaded image */ + ret = EFI_INVALID_PARAMETER; + goto out; + } + /* A started image can only be unloaded it is the last one started. */ + if (image_handle != current_image) { + ret = EFI_INVALID_PARAMETER; + goto out; + } /* Exit data is only foreseen in case of failure. */ if (exit_status != EFI_SUCCESS) { @@ -2822,6 +2843,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, if (ret != EFI_SUCCESS) EFI_PRINT("%s: out of memory\n", __func__); } + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION || + exit_status != EFI_SUCCESS) + efi_delete_image(image_obj, loaded_image_protocol); /* Make sure entry/exit counts for EFI world cross-overs match */ EFI_EXIT(exit_status); @@ -2837,7 +2861,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, panic("EFI application exited"); out: - return EFI_EXIT(EFI_INVALID_PARAMETER); + return EFI_EXIT(ret); } /** -- cgit v1.2.3