efi_loader: support booting via short-form device-path

The boot manager must support loading from boot options using a short-form
device-path, e.g. one where the first element is a hard drive media path.

See '3.1.2 Load Options Processing' in UEFI specification version 2.9.

Fixes: 0e074d1239 ("efi_loader: carve out efi_load_image_from_file()")
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
This commit is contained in:
Heinrich Schuchardt 2022-02-26 12:05:30 +01:00
parent e46ef1db9e
commit 9cdf470274

View file

@ -1940,7 +1940,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
{ {
efi_handle_t device; efi_handle_t device;
efi_status_t ret; efi_status_t ret;
struct efi_device_path *dp; struct efi_device_path *dp, *rem;
struct efi_load_file_protocol *load_file_protocol = NULL; struct efi_load_file_protocol *load_file_protocol = NULL;
efi_uintn_t buffer_size; efi_uintn_t buffer_size;
uint64_t addr, pages; uint64_t addr, pages;
@ -1951,18 +1951,18 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
*size = 0; *size = 0;
dp = file_path; dp = file_path;
ret = EFI_CALL(efi_locate_device_path( device = efi_dp_find_obj(dp, NULL, &rem);
&efi_simple_file_system_protocol_guid, &dp, &device)); ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid,
NULL);
if (ret == EFI_SUCCESS) if (ret == EFI_SUCCESS)
return efi_load_image_from_file(file_path, buffer, size); return efi_load_image_from_file(file_path, buffer, size);
ret = EFI_CALL(efi_locate_device_path( ret = efi_search_protocol(device, &efi_guid_load_file_protocol, NULL);
&efi_guid_load_file_protocol, &dp, &device));
if (ret == EFI_SUCCESS) { if (ret == EFI_SUCCESS) {
guid = &efi_guid_load_file_protocol; guid = &efi_guid_load_file_protocol;
} else if (!boot_policy) { } else if (!boot_policy) {
guid = &efi_guid_load_file2_protocol; guid = &efi_guid_load_file2_protocol;
ret = EFI_CALL(efi_locate_device_path(guid, &dp, &device)); ret = efi_search_protocol(device, guid, NULL);
} }
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
@ -1971,9 +1971,9 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
buffer_size = 0; buffer_size = 0;
ret = load_file_protocol->load_file(load_file_protocol, dp, ret = EFI_CALL(load_file_protocol->load_file(
boot_policy, &buffer_size, load_file_protocol, rem, boot_policy,
NULL); &buffer_size, NULL));
if (ret != EFI_BUFFER_TOO_SMALL) if (ret != EFI_BUFFER_TOO_SMALL)
goto out; goto out;
pages = efi_size_in_pages(buffer_size); pages = efi_size_in_pages(buffer_size);
@ -1984,7 +1984,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy,
goto out; goto out;
} }
ret = EFI_CALL(load_file_protocol->load_file( ret = EFI_CALL(load_file_protocol->load_file(
load_file_protocol, dp, boot_policy, load_file_protocol, rem, boot_policy,
&buffer_size, (void *)(uintptr_t)addr)); &buffer_size, (void *)(uintptr_t)addr));
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)
efi_free_pages(addr, pages); efi_free_pages(addr, pages);