efi_loader: new function efi_delete_handle()

Provide a function to remove a handle from the object list
after removing all protocols.

To avoid forward declarations other functions have to move up
in the coding.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Heinrich Schuchardt 2017-12-04 18:03:02 +01:00 committed by Alexander Graf
parent 56d9288858
commit 678e03a00c
2 changed files with 102 additions and 86 deletions

View File

@ -190,6 +190,8 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path);
void efi_add_handle(struct efi_object *obj);
/* Create handle */
efi_status_t efi_create_handle(void **handle);
/* Delete handle */
void efi_delete_handle(struct efi_object *obj);
/* Call this to validate a handle and find the EFI object for it */
struct efi_object *efi_search_obj(const void *handle);
/* Find a protocol on a handle */

View File

@ -359,6 +359,106 @@ efi_status_t efi_create_handle(void **handle)
return r;
}
/*
* Find a protocol on a handle.
*
* @handle handle
* @protocol_guid GUID of the protocol
* @handler reference to the protocol
* @return status code
*/
efi_status_t efi_search_protocol(const void *handle,
const efi_guid_t *protocol_guid,
struct efi_handler **handler)
{
struct efi_object *efiobj;
struct list_head *lhandle;
if (!handle || !protocol_guid)
return EFI_INVALID_PARAMETER;
efiobj = efi_search_obj(handle);
if (!efiobj)
return EFI_INVALID_PARAMETER;
list_for_each(lhandle, &efiobj->protocols) {
struct efi_handler *protocol;
protocol = list_entry(lhandle, struct efi_handler, link);
if (!guidcmp(protocol->guid, protocol_guid)) {
if (handler)
*handler = protocol;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/*
* Delete protocol from a handle.
*
* @handle handle from which the protocol shall be deleted
* @protocol GUID of the protocol to be deleted
* @protocol_interface interface of the protocol implementation
* @return status code
*/
efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol,
void *protocol_interface)
{
struct efi_handler *handler;
efi_status_t ret;
ret = efi_search_protocol(handle, protocol, &handler);
if (ret != EFI_SUCCESS)
return ret;
if (guidcmp(handler->guid, protocol))
return EFI_INVALID_PARAMETER;
list_del(&handler->link);
free(handler);
return EFI_SUCCESS;
}
/*
* Delete all protocols from a handle.
*
* @handle handle from which the protocols shall be deleted
* @return status code
*/
efi_status_t efi_remove_all_protocols(const void *handle)
{
struct efi_object *efiobj;
struct list_head *lhandle;
struct list_head *pos;
efiobj = efi_search_obj(handle);
if (!efiobj)
return EFI_INVALID_PARAMETER;
list_for_each_safe(lhandle, pos, &efiobj->protocols) {
struct efi_handler *protocol;
efi_status_t ret;
protocol = list_entry(lhandle, struct efi_handler, link);
ret = efi_remove_protocol(handle, protocol->guid,
protocol->protocol_interface);
if (ret != EFI_SUCCESS)
return ret;
}
return EFI_SUCCESS;
}
/*
* Delete handle.
*
* @handle handle to delete
*/
void efi_delete_handle(struct efi_object *obj)
{
if (!obj)
return;
efi_remove_all_protocols(obj->handle);
list_del(&obj->link);
free(obj);
}
/*
* Our event capabilities are very limited. Only a small limited
* number of events is allowed to coexist.
@ -717,39 +817,6 @@ struct efi_object *efi_search_obj(const void *handle)
return NULL;
}
/*
* Find a protocol on a handle.
*
* @handle handle
* @protocol_guid GUID of the protocol
* @handler reference to the protocol
* @return status code
*/
efi_status_t efi_search_protocol(const void *handle,
const efi_guid_t *protocol_guid,
struct efi_handler **handler)
{
struct efi_object *efiobj;
struct list_head *lhandle;
if (!handle || !protocol_guid)
return EFI_INVALID_PARAMETER;
efiobj = efi_search_obj(handle);
if (!efiobj)
return EFI_INVALID_PARAMETER;
list_for_each(lhandle, &efiobj->protocols) {
struct efi_handler *protocol;
protocol = list_entry(lhandle, struct efi_handler, link);
if (!guidcmp(protocol->guid, protocol_guid)) {
if (handler)
*handler = protocol;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/*
* Install new protocol on a handle.
*
@ -780,59 +847,6 @@ efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol,
return EFI_SUCCESS;
}
/*
* Delete protocol from a handle.
*
* @handle handle from which the protocol shall be deleted
* @protocol GUID of the protocol to be deleted
* @protocol_interface interface of the protocol implementation
* @return status code
*/
efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol,
void *protocol_interface)
{
struct efi_handler *handler;
efi_status_t ret;
ret = efi_search_protocol(handle, protocol, &handler);
if (ret != EFI_SUCCESS)
return ret;
if (guidcmp(handler->guid, protocol))
return EFI_INVALID_PARAMETER;
list_del(&handler->link);
free(handler);
return EFI_SUCCESS;
}
/*
* Delete all protocols from a handle.
*
* @handle handle from which the protocols shall be deleted
* @return status code
*/
efi_status_t efi_remove_all_protocols(const void *handle)
{
struct efi_object *efiobj;
struct list_head *lhandle;
struct list_head *pos;
efiobj = efi_search_obj(handle);
if (!efiobj)
return EFI_INVALID_PARAMETER;
list_for_each_safe(lhandle, pos, &efiobj->protocols) {
struct efi_handler *protocol;
efi_status_t ret;
protocol = list_entry(lhandle, struct efi_handler, link);
ret = efi_remove_protocol(handle, protocol->guid,
protocol->protocol_interface);
if (ret != EFI_SUCCESS)
return ret;
}
return EFI_SUCCESS;
}
/*
* Install protocol interface.
*