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 /lib/efi_loader | |
parent | 46e99a9cf7ea06837184da766b5a43065c523d10 (diff) |
efi_loader: implement UnloadImage()
Implement the UnloadImage() boot service
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 55 |
1 files changed, 51 insertions, 4 deletions
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); } /** |