[U-Boot] [RFC 10/10] efi_loader: support load_image() from a file-path

Rob Clark robdclark at gmail.com
Thu Jul 27 22:50:51 UTC 2017


On Thu, Jul 27, 2017 at 5:38 PM, Rob Clark <robdclark at gmail.com> wrote:
> Previously we only supported the case when the EFI application loaded
> the image into memory for us.  But fallback.efi does not do this.
>
> Signed-off-by: Rob Clark <robdclark at gmail.com>
> ---
>  lib/efi_loader/efi_boottime.c | 91 ++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 76 insertions(+), 15 deletions(-)
>
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index aa342670c2..326a428a57 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -749,6 +749,45 @@ void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *ob
>         list_add_tail(&obj->link, &efi_obj_list);
>  }
>
> +static efi_status_t load_image_from_path(struct efi_device_path *file_path,
> +                                        void **buffer)
> +{
> +       struct efi_file_info *info = NULL;
> +       struct efi_file_handle *f;
> +       static efi_status_t ret;
> +       uint64_t bs;
> +
> +       f = efi_file_from_path(file_path);
> +       if (!f)
> +               return EFI_DEVICE_ERROR;
> +
> +       bs = sizeof(info);

oh, this should actually be: bs = 0;

already fixed up locally

BR,
-R

> +       EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs, info));
> +       if (ret == EFI_BUFFER_TOO_SMALL) {
> +               info = malloc(bs);
> +               EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs, info));
> +       }
> +       if (ret != EFI_SUCCESS)
> +               goto error;
> +
> +       ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer);
> +       if (ret)
> +               goto error;
> +
> +       EFI_CALL(ret = f->read(f, &info->file_size, *buffer));
> +
> +error:
> +       free(info);
> +       EFI_CALL(f->close(f));
> +
> +       if (ret != EFI_SUCCESS) {
> +               efi_free_pool(*buffer);
> +               *buffer = NULL;
> +       }
> +
> +       return ret;
> +}
> +
>  static efi_status_t EFIAPI efi_load_image(bool boot_policy,
>                                           efi_handle_t parent_image,
>                                           struct efi_device_path *file_path,
> @@ -756,25 +795,48 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
>                                           unsigned long source_size,
>                                           efi_handle_t *image_handle)
>  {
> -       static struct efi_object loaded_image_info_obj = {
> -               .protocols = {
> -                       {
> -                               .guid = &efi_guid_loaded_image,
> -                       },
> -               },
> -       };
>         struct efi_loaded_image *info;
>         struct efi_object *obj;
>
>         EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
>                   file_path, source_buffer, source_size, image_handle);
> -       info = malloc(sizeof(*info));
> -       loaded_image_info_obj.protocols[0].protocol_interface = info;
> -       obj = malloc(sizeof(loaded_image_info_obj));
> -       memset(info, 0, sizeof(*info));
> -       memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
> -       obj->handle = info;
> -       info->file_path = file_path;
> +
> +       info = calloc(1, sizeof(*info));
> +       obj = calloc(1, sizeof(*obj));
> +
> +       if (!source_buffer) {
> +               struct efi_device_path *dp, *fp, *p;
> +               efi_status_t ret;
> +
> +               ret = load_image_from_path(file_path, &source_buffer);
> +               if (ret != EFI_SUCCESS) {
> +                       free(info);
> +                       free(obj);
> +                       return EFI_EXIT(ret);
> +               }
> +
> +               /*
> +                * split file_path which contains both the device and
> +                * file parts:
> +                */
> +               dp = efi_dp_dup(file_path);
> +               p = dp;
> +               while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH))
> +                       p = efi_dp_next(p);
> +               fp = efi_dp_dup(p);
> +
> +               p->type = DEVICE_PATH_TYPE_END;
> +               p->sub_type = DEVICE_PATH_SUB_TYPE_END;
> +               p->length = sizeof(*p);
> +
> +               efi_setup_loaded_image(info, obj, dp, fp);
> +       } else {
> +               /* In this case, file_path is the "device" path, ie.
> +                * something like a HARDWARE_DEVICE:MEMORY_MAPPED
> +                */
> +               efi_setup_loaded_image(info, obj, file_path, NULL);
> +       }
> +
>         info->reserved = efi_load_pe(source_buffer, info);
>         if (!info->reserved) {
>                 free(info);
> @@ -783,7 +845,6 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
>         }
>
>         *image_handle = info;
> -       list_add_tail(&obj->link, &efi_obj_list);
>
>         return EFI_EXIT(EFI_SUCCESS);
>  }
> --
> 2.13.0
>


More information about the U-Boot mailing list