[PATCH v1 1/2] efi_loader: improve device path matching for partition lookup
Ilias Apalodimas
ilias.apalodimas at linaro.org
Tue Aug 5 09:47:47 CEST 2025
Hi Balaji
On Thu, 24 Jul 2025 at 12:00, Balaji Selvanathan
<balaji.selvanathan at oss.qualcomm.com> wrote:
>
> - Refactor find_handle() to improve device path comparison logic.
> - Original logic only compared paths when len_current <= len.
> - This fails when searching for ESP inside a larger boot device.
> - ESP partition path is longer than boot device path by design.
> - New logic allows matching when dp is a prefix of dp_current.
> - Without this change, it was not able to find ESP and capsule
> update fails to start.
>
> - Also update efi_fs_from_path() to use system partition GUID.
> - Above ensures ESP's EFI handle is returned which contains
> file system protocol.
> - Without this change, it was returning a wrong EFI handle
> that was not ESP handle.
I am not sure this is a bug. The EFI spec says that in order to
trigger a capsule update you need to have an active boot option
pointing to the same ESP the capsule is installed.
Is your boot0000 automatically generated? If so it doesnt point to the
ESP and the capsule update doesn't trigger correctly. Does it work if
you manually add a boot option pointing to the ESP?
Thanks
/Ilias
>
> - These changes improves reliability for capsule updates.
>
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan at oss.qualcomm.com>
> ---
> lib/efi_loader/efi_device_path.c | 62 ++++++++++++++++++++++----------
> lib/efi_loader/efi_disk.c | 2 +-
> 2 files changed, 45 insertions(+), 19 deletions(-)
>
> diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
> index b3fb20b2501..3716165e963 100644
> --- a/lib/efi_loader/efi_device_path.c
> +++ b/lib/efi_loader/efi_device_path.c
> @@ -107,54 +107,80 @@ struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp)
> * @rem: pointer to receive remaining device path
> * Return: matching handle
> */
> +
> static efi_handle_t find_handle(struct efi_device_path *dp,
> const efi_guid_t *guid, bool short_path,
> struct efi_device_path **rem)
> {
> efi_handle_t handle, best_handle = NULL;
> - efi_uintn_t len, best_len = 0;
> + efi_uintn_t len, len_current, best_len = 0;
> + efi_status_t ret;
> + struct efi_device_path *dp_current;
> + struct efi_handler *handler;
>
> len = efi_dp_instance_size(dp);
>
> list_for_each_entry(handle, &efi_obj_list, link) {
> - struct efi_handler *handler;
> - struct efi_device_path *dp_current;
> - efi_uintn_t len_current;
> - efi_status_t ret;
> -
> if (guid) {
> ret = efi_search_protocol(handle, guid, &handler);
> if (ret != EFI_SUCCESS)
> continue;
> }
> - ret = efi_search_protocol(handle, &efi_guid_device_path,
> - &handler);
> +
> + ret = efi_search_protocol(handle, &efi_guid_device_path, &handler);
> if (ret != EFI_SUCCESS)
> continue;
> +
> dp_current = handler->protocol_interface;
> if (short_path) {
> dp_current = efi_dp_shorten(dp_current);
> if (!dp_current)
> continue;
> }
> +
> len_current = efi_dp_instance_size(dp_current);
> +
> if (rem) {
> - if (len_current > len)
> + /* If current path is shorter than or equal to input path */
> + if (len_current <= len) {
> + if (memcmp(dp_current, dp, len_current))
> + continue;
> + if (!rem)
> + return handle;
> + if (len_current > best_len) {
> + best_len = len_current;
> + best_handle = handle;
> + *rem = (void *)((u8 *)dp + len_current);
> + }
> + }
> + /* If current path is greater than input path */
> + else if (len_current > len) {
> + if (memcmp(dp, dp_current, len))
> + continue;
> + if (len > best_len) {
> + best_len = len;
> + best_handle = handle;
> + *rem = (struct efi_device_path *)((u8 *)dp_current + len);
> + }
> + } else {
> continue;
> + }
> } else {
> - if (len_current != len)
> + if (len_current == len) {
> + if (memcmp(dp_current, dp, len_current))
> + continue;
> + }
> + /* If current path is greater than input path */
> + else if (len_current > len) {
> + if (memcmp(dp, dp_current, len))
> + continue;
> + } else {
> continue;
> - }
> - if (memcmp(dp_current, dp, len_current))
> - continue;
> - if (!rem)
> + }
> return handle;
> - if (len_current > best_len) {
> - best_len = len_current;
> - best_handle = handle;
> - *rem = (void*)((u8 *)dp + len_current);
> }
> }
> +
> return best_handle;
> }
>
> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
> index 130c4db9606..49f8b5935f4 100644
> --- a/lib/efi_loader/efi_disk.c
> +++ b/lib/efi_loader/efi_disk.c
> @@ -339,7 +339,7 @@ efi_fs_from_path(struct efi_device_path *full_path)
> efi_free_pool(file_path);
>
> /* Get the EFI object for the partition */
> - efiobj = efi_dp_find_obj(device_path, NULL, NULL);
> + efiobj = efi_dp_find_obj(device_path, &efi_system_partition_guid, NULL);
> efi_free_pool(device_path);
> if (!efiobj)
> return NULL;
> --
> 2.34.1
>
More information about the U-Boot
mailing list