[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