
On Thu, Jul 27, 2017 at 5:38 PM, Rob Clark robdclark@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@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