[PATCH v1 1/2] efi_loader: improve device path matching for partition lookup
Heinrich Schuchardt
xypron.glpk at gmx.de
Fri Jul 25 16:01:19 CEST 2025
On 24.07.25 11:00, Balaji Selvanathan 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.
Thank you for reporting an issue you have with capsule updates.
Could you, please, describe how to reproduce the issue you are seeing.
Which caller fails for you?
What are the values of the UEFI Boot####, BootNext variables that you
use to find the capsule?
What is the device-path of the ESP?
Best regards
Heinrich
> - 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.
>
> - 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;
More information about the U-Boot
mailing list