summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2019-05-01 18:25:45 +0200
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2019-05-07 21:10:03 +0200
commitdf116e81ea62cf2fcc0f0f89ed328fe27e64ca67 (patch)
tree6a175ebc265ea67855f2ac7a1c0da7f0a0cfed39
parent46e99a9cf7ea06837184da766b5a43065c523d10 (diff)
efi_loader: implement UnloadImage()
Implement the UnloadImage() boot service Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
-rw-r--r--include/efi_api.h2
-rw-r--r--lib/efi_loader/efi_boottime.c55
2 files changed, 52 insertions, 5 deletions
diff --git a/include/efi_api.h b/include/efi_api.h
index 472160cb30..b2ae279747 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -348,7 +348,7 @@ struct efi_loaded_image {
aligned_u64 image_size;
unsigned int image_code_type;
unsigned int image_data_type;
- unsigned long unload;
+ efi_status_t (EFIAPI *unload)(efi_handle_t image_handle);
};
#define EFI_DEVICE_PATH_PROTOCOL_GUID \
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 8f2c610b86..0385883ded 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2670,6 +2670,20 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
}
/**
+ * efi_delete_image() - delete loaded image from memory)
+ *
+ * @image_obj: handle of the loaded image
+ * @loaded_image_protocol: loaded image protocol
+ */
+static void efi_delete_image(struct efi_loaded_image_obj *image_obj,
+ struct efi_loaded_image *loaded_image_protocol)
+{
+ efi_free_pages((uintptr_t)loaded_image_protocol->image_base,
+ efi_size_in_pages(loaded_image_protocol->image_size));
+ efi_delete_handle(&image_obj->header);
+}
+
+/**
* efi_unload_image() - unload an EFI image
* @image_handle: handle of the image to be unloaded
*
@@ -2682,14 +2696,47 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
*/
efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
{
+ efi_status_t ret = EFI_SUCCESS;
struct efi_object *efiobj;
+ struct efi_loaded_image *loaded_image_protocol;
EFI_ENTRY("%p", image_handle);
- efiobj = efi_search_obj(image_handle);
- if (efiobj)
- list_del(&efiobj->link);
- return EFI_EXIT(EFI_SUCCESS);
+ efiobj = efi_search_obj(image_handle);
+ if (!efiobj) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ /* Find the loaded image protocol */
+ ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
+ (void **)&loaded_image_protocol,
+ NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (ret != EFI_SUCCESS) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ switch (efiobj->type) {
+ case EFI_OBJECT_TYPE_STARTED_IMAGE:
+ /* Call the unload function */
+ if (!loaded_image_protocol->unload) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ ret = EFI_CALL(loaded_image_protocol->unload(image_handle));
+ if (ret != EFI_SUCCESS)
+ goto out;
+ break;
+ case EFI_OBJECT_TYPE_LOADED_IMAGE:
+ break;
+ default:
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ efi_delete_image((struct efi_loaded_image_obj *)efiobj,
+ loaded_image_protocol);
+out:
+ return EFI_EXIT(ret);
}
/**