[U-Boot] [PATCH v2 05/18] efi_loader: reimplement LocateDevicePath

Simon Glass sjg at chromium.org
Fri Nov 17 14:06:31 UTC 2017


Hi Heinrich,

On 12 November 2017 at 07:02, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
> The current implementation of efi_locate_device_path does not match
> the UEFI specification. It completely ignores the protocol
> parameters.
>
> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
> ---
> v2
>         no change
> ---
>  lib/efi_loader/efi_boottime.c | 106 ++++++++++++++++++++++++++++++------------
>  1 file changed, 76 insertions(+), 30 deletions(-)

Reviewed-by: Simon Glass <sjg at chromium.org>

Nits below

>
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 9b5512f086..7457d54739 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -1080,36 +1080,6 @@ static efi_status_t EFIAPI efi_locate_handle_ext(
>                         buffer_size, buffer));
>  }
>
> -/*
> - * Get the device path and handle of an device implementing a protocol.
> - *
> - * This function implements the LocateDevicePath service.
> - * See the Unified Extensible Firmware Interface (UEFI) specification
> - * for details.

Oh yes, I will get right on that now :-)

> - *
> - * @protocol           GUID of the protocol
> - * @device_path                device path
> - * @device             handle of the device
> - * @return             status code
> - */
> -static efi_status_t EFIAPI efi_locate_device_path(
> -                       const efi_guid_t *protocol,
> -                       struct efi_device_path **device_path,
> -                       efi_handle_t *device)
> -{
> -       struct efi_object *efiobj;
> -
> -       EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
> -
> -       efiobj = efi_dp_find_obj(*device_path, device_path);
> -       if (!efiobj)
> -               return EFI_EXIT(EFI_NOT_FOUND);
> -
> -       *device = efiobj->handle;
> -
> -       return EFI_EXIT(EFI_SUCCESS);
> -}
> -
>  /* Collapses configuration table entries, removing index i */
>  static void efi_remove_configuration_table(int i)
>  {
> @@ -1813,6 +1783,82 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
>         return EFI_EXIT(EFI_NOT_FOUND);
>  }
>
> +/*
> + * Get the device path and handle of an device implementing a protocol.

a device?

> + *
> + * This function implements the LocateDevicePath service.
> + * See the Unified Extensible Firmware Interface (UEFI) specification
> + * for details.
> + *
> + * @protocol           GUID of the protocol
> + * @device_path                device path
> + * @device             handle of the device
> + * @return             status code
> + */
> +static efi_status_t EFIAPI efi_locate_device_path(
> +                       const efi_guid_t *protocol,
> +                       struct efi_device_path **device_path,
> +                       efi_handle_t *device)
> +{
> +       struct efi_device_path *dp;
> +       size_t i;
> +       struct efi_handler *handler;
> +       efi_handle_t *handles;
> +       size_t len, len_dp;
> +       size_t len_best = 0;
> +       efi_uintn_t no_handles;

Is there none?

I think num_handles is better, or handles_count.

> +       u8 *remainder;
> +       efi_status_t ret;
> +
> +       EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
> +
> +       if (!protocol || !device_path || !*device_path || !device) {
> +               ret = EFI_INVALID_PARAMETER;
> +               goto out;
> +       }
> +
> +       /* Find end of device path */
> +       len = efi_dp_size(*device_path);
> +
> +       /* Get all handles implementing the protocol */
> +       ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
> +                                               &no_handles, &handles));
> +       if (ret != EFI_SUCCESS)
> +               goto out;
> +
> +       for (i = 0; i < no_handles; ++i) {
> +               /* Find the device path protocol */
> +               ret = efi_search_protocol(handles[i], &efi_guid_device_path,
> +                                         &handler);
> +               if (ret != EFI_SUCCESS)
> +                       continue;
> +               dp = (struct efi_device_path *)handler->protocol_interface;
> +               len_dp = efi_dp_size(dp);
> +               /*
> +                * This handle can only be a better fit
> +                * if its device path length is longer then the best fit and
> +                * if its device path length is shorter of equal the searched
> +                * device path.

Format to ~77 cols?

> +                */
> +               if (len_dp <= len_best || len_dp > len)
> +                       continue;
> +               /* Check if dp is a subpath of device_path. */

Can you drop the period?

> +               if (memcmp(*device_path, dp, len_dp))
> +                       continue;
> +               *device = handles[i];
> +               len_best = len_dp;
> +       }
> +       if (len_best) {
> +               remainder = (u8 *)*device_path + len_best;
> +               *device_path = (struct efi_device_path *)remainder;
> +               ret = EFI_SUCCESS;
> +       } else {
> +               ret = EFI_NOT_FOUND;
> +       }
> +out:
> +       return EFI_EXIT(ret);
> +}
> +
>  /*
>   * Install multiple protocol interfaces.
>   *
> --
> 2.15.0
>
Regards,
Simon


More information about the U-Boot mailing list