[PATCH 1/2] efi_loader: delete handle from events when a protocol is uninstalled
Heinrich Schuchardt
xypron.glpk at gmx.de
Thu Jun 1 18:15:03 CEST 2023
On 6/1/23 14:06, Ilias Apalodimas wrote:
> When a notification event is registered for a protocol the handle of the
> protocol is added in our event notification list. When all the protocols
> of the handle are uninstalled we delete the handle but we do not remove
> it from the event notification list.
>
> Clean up the protocol removal functions and add a wrapper which
> - Removes the to-be deleted handle from any lists it participates
> - Remove the handle if no more protocols are present
>
> It's worth noting that all our variants of efi_uninstall_protocol_*()
> and uninstall_multiple_protocol_*() end up calling
> efi_uninstall_protocol(). We could add the cleanup in that function
> only, however efi_reinstall_protocol_interface() expects the handle not
> to be removed.
>
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> ---
> lib/efi_loader/efi_boottime.c | 45 +++++++++++++++++++++++++----------
> 1 file changed, 33 insertions(+), 12 deletions(-)
>
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index d5065f296aee..450524ddca2f 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -197,6 +197,35 @@ static bool efi_event_is_queued(struct efi_event *event)
> return !!event->queue_link.next;
> }
>
> +/**
> + * efi_handle_cleanup() - Clean the deleted handle from the various lists
> + * @handle: handle to remove
> + * @force: force removal even if protocols are still installed on the handle
> + *
> + * Return: status code
> + */
> +static void efi_handle_cleanup(efi_handle_t handle, bool force)
> +{
> + struct efi_register_notify_event *item, *next;
> +
> + if (!list_empty(&handle->protocols) || force)
I guess the parameter force can be dropped from the interface.
> + return;
Please, return a failure code.
> + /* The handle is about to be freed. Remove it from events */
> + list_for_each_entry_safe(item, next, &efi_register_notify_events, link) {
> + struct efi_protocol_notification *hitem, *hnext;
> +
> + list_for_each_entry_safe(hitem, hnext, &item->handles, link) {
> + if (handle == hitem->handle) {
> + list_del(&hitem->link);
> + free(hitem);
> + }
> + }
> + }
> + /* The last protocol has been removed, delete the handle. */
> + list_del(&handle->link);
> + free(handle);
> +}
> +
> /**
> * efi_process_event_queue() - process event queue
> */
> @@ -627,8 +656,7 @@ void efi_delete_handle(efi_handle_t handle)
> return;
> }
It would be safer to move the checks if a protocol interface can be
removed from efi_uninstall_protocol() to efi_remove_protocol(). That way
we are sure that no driver has attached to the protocols that we try to
remove.
>
> - list_del(&handle->link);
> - free(handle);
> + efi_handle_cleanup(handle, true);
I don't think we should use a special treatment here. If the protocols
cannot be deleted, because a driver has attached we should not delete
the handle.
The function should return a status code. Then efi_disk_delete_raw() can
return an error for EVT_DM_PRE_REMOVE and stop the device from being
deleted.
Best regards
Heinrich
> }
>
> /**
> @@ -1396,11 +1424,8 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface
> if (ret != EFI_SUCCESS)
> goto out;
>
> - /* If the last protocol has been removed, delete the handle. */
> - if (list_empty(&handle->protocols)) {
> - list_del(&handle->link);
> - free(handle);
> - }
> + /* Check if we have to purge the handle from various lists */
> + efi_handle_cleanup(handle, false);
> out:
> return EFI_EXIT(ret);
> }
> @@ -2777,11 +2802,7 @@ efi_uninstall_multiple_protocol_interfaces_int(efi_handle_t handle,
> i++;
> }
> if (ret == EFI_SUCCESS) {
> - /* If the last protocol has been removed, delete the handle. */
> - if (list_empty(&handle->protocols)) {
> - list_del(&handle->link);
> - free(handle);
> - }
> + efi_handle_cleanup(handle, false);
> goto out;
> }
>
More information about the U-Boot
mailing list