Hi Baaji, Thanks for testing, can you also send a reply with a tested-by: tag? /Ilias
On Thu, 4 Dec 2025 at 06:42, Balaji Selvanathan <[email protected]> wrote: > > > On 12/2/2025 2:20 PM, Ilias Apalodimas wrote: > > The EFI spec in ยง8.5.5 says > > "The directory \EFI\UpdateCapsule is checked for capsules only within > > the EFI system partition on the device specified in the active boot > > option determine by reference to BootNext variable or BootOrder variable > > processing." > > > > Automatically generated boot options don't point to the ESP, they point to > > the disk itself and find_handle() won't match when searching for an ESP > > during a capsule update. > > This happens because find_handle() only matches device paths that are > > shorter or equal to the device path passed as an argument. > > Since the EFI spec allows it we want to allow capsule updates, when the > > boot option points to a disk, but that disk contains an ESP with a > > \EFI\UpdateCapsule directory. > > > > find_handle() implicitly changes it's behavior depending on the passed > > arguments as well. If the 'rem' ptr is not valid it will only search for > > an exact match. Otherwise it will match on the best match and return the > > remaining portion of the matched device path to 'rem'. > > > > Tweak this slightly and pass an enum with 3 options > > - EXACT - Exact match, as if 'rem' was NULL > > - SHORTER - Match a shorter device path and put the remainder in 'rem' > > - LONGER - Inverse the logic and match a longer device path. Put the > > remainder into 'rem'. > > > > To avoid any regressions, LONGER is only used during capsule updates and > > since 'rem' always carries the remainder of the matched device path we > > can plug it in with minimal changes. > > > > Reported-by: Balaji Selvanathan <[email protected]> > > Reported-by: John Toomey <[email protected]> > > Signed-off-by: Ilias Apalodimas <[email protected]> > > --- > > > > John, Balaji, can you check if this fixes your problem? > > Hi Ilias, > > Thanks for this patch. This fixes the problem and have verified the patch. > > Regards, > > Balaji > > > > > cmd/eficonfig.c | 2 +- > > include/efi_device_path.h | 10 +++--- > > lib/efi_loader/efi_bootmgr.c | 6 ++-- > > lib/efi_loader/efi_boottime.c | 5 +-- > > lib/efi_loader/efi_capsule.c | 20 +++++++----- > > lib/efi_loader/efi_device_path.c | 55 +++++++++++++++++++++++++------- > > lib/efi_loader/efi_disk.c | 2 +- > > 7 files changed, 70 insertions(+), 30 deletions(-) > > > > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c > > index d8d946c87ac8..e317f3c90c14 100644 > > --- a/cmd/eficonfig.c > > +++ b/cmd/eficonfig.c > > @@ -1321,7 +1321,7 @@ static efi_status_t > > prepare_file_selection_entry(struct efimenu *efi_menu, char > > return EFI_OUT_OF_RESOURCES; > > > > /* get the device name only when the user already selected the file > > path */ > > - handle = efi_dp_find_obj(file_info->dp_volume, NULL, NULL); > > + handle = efi_dp_find_obj(file_info->dp_volume, NULL, NULL, false); > > if (handle) { > > ret = efi_disk_get_device_name(handle, devname, > > EFICONFIG_VOLUME_PATH_MAX); > > if (ret != EFI_SUCCESS) > > diff --git a/include/efi_device_path.h b/include/efi_device_path.h > > index aae85228f681..f9c538730c94 100644 > > --- a/include/efi_device_path.h > > +++ b/include/efi_device_path.h > > @@ -73,13 +73,15 @@ struct efi_device_path *efi_dp_shorten(struct > > efi_device_path *dp); > > * > > * If @rem is provided, the handle with the longest partial match is > > returned. > > * > > - * @dp: device path to search > > - * @guid: GUID of protocol that must be installed on path or NULL > > - * @rem: pointer to receive remaining device path > > + * @dp: device path to search > > + * @guid: GUID of protocol that must be installed on path or > > NULL > > + * @rem: pointer to receive remaining device path > > + * @inversed_match: Match even if the dp is shorter. rem will stil hoild > > the > > + * remaining device path > > * Return: matching handle > > */ > > efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, const efi_guid_t > > *guid, > > - struct efi_device_path **rem); > > + struct efi_device_path **rem, bool > > inversed_match); > > > > /** > > * efi_dp_last_node() - Determine the last device path node before the > > end node > > diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c > > index a687f4d8e85c..df7500a94876 100644 > > --- a/lib/efi_loader/efi_bootmgr.c > > +++ b/lib/efi_loader/efi_bootmgr.c > > @@ -84,7 +84,8 @@ struct efi_device_path *expand_media_path(struct > > efi_device_path *device_path) > > * booting from removable media. > > */ > > handle = efi_dp_find_obj(device_path, > > - &efi_simple_file_system_protocol_guid, &rem); > > + &efi_simple_file_system_protocol_guid, &rem, > > + false); > > if (handle) { > > if (rem->type == DEVICE_PATH_TYPE_END) { > > char fname[30]; > > @@ -625,7 +626,8 @@ static efi_status_t try_load_from_media(struct > > efi_device_path *file_path, > > struct efi_device_path *rem, *dp = NULL; > > struct efi_device_path *final_dp = file_path; > > > > - handle_blkdev = efi_dp_find_obj(file_path, &efi_block_io_guid, &rem); > > + handle_blkdev = efi_dp_find_obj(file_path, &efi_block_io_guid, &rem, > > + false); > > if (handle_blkdev) { > > if (rem->type == DEVICE_PATH_TYPE_END) { > > /* no file name present, try default file */ > > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > > index ddc935d22409..0391b92a8be4 100644 > > --- a/lib/efi_loader/efi_boottime.c > > +++ b/lib/efi_loader/efi_boottime.c > > @@ -1816,7 +1816,8 @@ efi_status_t efi_setup_loaded_image(struct > > efi_device_path *device_path, > > info->system_table = &systab; > > > > if (device_path) { > > - info->device_handle = efi_dp_find_obj(device_path, NULL, > > NULL); > > + info->device_handle = efi_dp_find_obj(device_path, NULL, NULL, > > + false); > > > > dp = efi_dp_concat(device_path, file_path, 0); > > if (!dp) { > > @@ -2016,7 +2017,7 @@ efi_status_t efi_load_image_from_path(bool > > boot_policy, > > *size = 0; > > > > dp = file_path; > > - device = efi_dp_find_obj(dp, NULL, &rem); > > + device = efi_dp_find_obj(dp, NULL, &rem, false); > > ret = efi_search_protocol(device, > > &efi_simple_file_system_protocol_guid, > > NULL); > > if (ret == EFI_SUCCESS) > > diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c > > index eafc647f558f..103328c76a6e 100644 > > --- a/lib/efi_loader/efi_capsule.c > > +++ b/lib/efi_loader/efi_capsule.c > > @@ -886,18 +886,18 @@ static efi_status_t get_dp_device(u16 *boot_var, > > * @dp device path > > * Return: true - yes, false - no > > */ > > -static bool device_is_present_and_system_part(struct efi_device_path *dp) > > +static bool device_is_present_and_system_part(struct efi_device_path *dp, > > + struct efi_device_path **rem) > > { > > efi_handle_t handle; > > - struct efi_device_path *rem; > > > > /* Check device exists */ > > - handle = efi_dp_find_obj(dp, NULL, NULL); > > + handle = efi_dp_find_obj(dp, NULL, NULL, false); > > if (!handle) > > return false; > > > > /* Check device is on system partition */ > > - handle = efi_dp_find_obj(dp, &efi_system_partition_guid, &rem); > > + handle = efi_dp_find_obj(dp, &efi_system_partition_guid, rem, true); > > if (!handle) > > return false; > > > > @@ -919,7 +919,7 @@ static efi_status_t find_boot_device(void) > > efi_uintn_t size; > > int i, num; > > struct efi_simple_file_system_protocol *volume; > > - struct efi_device_path *boot_dev = NULL; > > + struct efi_device_path *boot_dev = NULL, *rem = NULL; > > efi_status_t ret; > > > > /* find active boot device in BootNext */ > > @@ -940,7 +940,7 @@ static efi_status_t find_boot_device(void) > > > > ret = get_dp_device(boot_var16, &boot_dev); > > if (ret == EFI_SUCCESS) { > > - if (device_is_present_and_system_part(boot_dev)) { > > + if (device_is_present_and_system_part(boot_dev, > > &rem)) { > > goto found; > > } else { > > efi_free_pool(boot_dev); > > @@ -967,7 +967,7 @@ skip: > > if (ret != EFI_SUCCESS) > > continue; > > > > - if (device_is_present_and_system_part(boot_dev)) > > + if (device_is_present_and_system_part(boot_dev, &rem)) > > break; > > > > efi_free_pool(boot_dev); > > @@ -977,7 +977,11 @@ found: > > if (boot_dev) { > > log_debug("Boot device %pD\n", boot_dev); > > > > - volume = efi_fs_from_path(boot_dev); > > + if (rem->type == DEVICE_PATH_TYPE_END) > > + volume = efi_fs_from_path(boot_dev); > > + else > > + volume = efi_fs_from_path(rem); > > + > > if (!volume) > > ret = EFI_DEVICE_ERROR; > > else > > diff --git a/lib/efi_loader/efi_device_path.c > > b/lib/efi_loader/efi_device_path.c > > index b3fb20b2501e..ad7f452c411b 100644 > > --- a/lib/efi_loader/efi_device_path.c > > +++ b/lib/efi_loader/efi_device_path.c > > @@ -30,6 +30,12 @@ const struct efi_device_path EFI_DP_END = { > > .length = sizeof(EFI_DP_END), > > }; > > > > +enum match { > > + EXACT, > > + SHORTER, > > + LONGER > > +}; > > + > > #if defined(CONFIG_MMC) > > /* > > * Determine if an MMC device is an SD card. > > @@ -109,10 +115,11 @@ struct efi_device_path *efi_dp_shorten(struct > > efi_device_path *dp) > > */ > > static efi_handle_t find_handle(struct efi_device_path *dp, > > const efi_guid_t *guid, bool short_path, > > - struct efi_device_path **rem) > > + struct efi_device_path **rem, > > + enum match match) > > { > > efi_handle_t handle, best_handle = NULL; > > - efi_uintn_t len, best_len = 0; > > + efi_uintn_t len, match_len = 0, best_len = 0; > > > > len = efi_dp_instance_size(dp); > > > > @@ -137,22 +144,35 @@ static efi_handle_t find_handle(struct > > efi_device_path *dp, > > if (!dp_current) > > continue; > > } > > - len_current = efi_dp_instance_size(dp_current); > > - if (rem) { > > + > > + match_len = len_current = efi_dp_instance_size(dp_current); > > + switch (match) { > > + case EXACT: > > + if (len_current != len) > > + continue; > > + break; > > + case SHORTER: > > if (len_current > len) > > continue; > > - } else { > > - if (len_current != len) > > + break; > > + case LONGER: > > + if (len_current < len) > > continue; > > + match_len = len; > > + break; > > } > > - if (memcmp(dp_current, dp, len_current)) > > + > > + if (memcmp(dp_current, dp, match_len)) > > continue; > > if (!rem) > > return handle; > > if (len_current > best_len) { > > best_len = len_current; > > best_handle = handle; > > - *rem = (void*)((u8 *)dp + len_current); > > + if (len_current <= len) > > + *rem = (void *)((uintptr_t)dp + len_current); > > + else > > + *rem = (void *)((uintptr_t)dp_current + > > match_len); > > } > > } > > return best_handle; > > @@ -160,14 +180,25 @@ static efi_handle_t find_handle(struct > > efi_device_path *dp, > > > > efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, > > const efi_guid_t *guid, > > - struct efi_device_path **rem) > > + struct efi_device_path **rem, bool > > inversed_match) > > { > > efi_handle_t handle; > > > > - handle = find_handle(dp, guid, false, rem); > > + handle = find_handle(dp, guid, false, rem, EXACT); > > if (!handle) > > - /* Match short form device path */ > > - handle = find_handle(dp, guid, true, rem); > > + handle = find_handle(dp, guid, true, rem, EXACT); > > + if (handle) > > + return handle; > > + > > + handle = find_handle(dp, guid, false, rem, SHORTER); > > + if (!handle) > > + handle = find_handle(dp, guid, true, rem, SHORTER); > > + > > + if (inversed_match && !handle) { > > + handle = find_handle(dp, guid, false, rem, LONGER); > > + if (!handle) > > + handle = find_handle(dp, guid, true, rem, LONGER); > > + } > > > > return handle; > > } > > diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c > > index 130c4db9606f..0d3d7c187d72 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, NULL, NULL, false); > > efi_free_pool(device_path); > > if (!efiobj) > > return NULL; > > -- > > 2.51.0 > >

