diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2019-05-01 18:25:45 +0200 |
---|---|---|
committer | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2019-05-07 21:10:03 +0200 |
commit | df116e81ea62cf2fcc0f0f89ed328fe27e64ca67 (patch) | |
tree | 6a175ebc265ea67855f2ac7a1c0da7f0a0cfed39 | |
parent | 46e99a9cf7ea06837184da766b5a43065c523d10 (diff) | |
download | u-boot-df116e81ea62cf2fcc0f0f89ed328fe27e64ca67.tar.gz |
efi_loader: implement UnloadImage()
Implement the UnloadImage() boot service
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
-rw-r--r-- | include/efi_api.h | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 55 |
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); } /** |