[PATCH] efi_loader: capsule: detect possible ESP device path
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed May 8 14:09:36 CEST 2024
On 5/8/24 14:04, Dan Carpenter wrote:
> On Wed, May 08, 2024 at 07:24:01PM +0800, Weizhao Ouyang wrote:
>> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
>> index de0d49ebebda..919e3cba071b 100644
>> --- a/lib/efi_loader/efi_capsule.c
>> +++ b/lib/efi_loader/efi_capsule.c
>> @@ -922,6 +922,105 @@ static bool device_is_present_and_system_part(struct efi_device_path *dp)
>> return true;
>> }
>>
>> +/**
>> + * get_esp_from_boot_option_file_path - get the expand device path
>> + *
>> + * Get a possible efi system partition by expanding a boot option
>> + * file path.
>> + *
>> + * @boot_dev The device path pointing to a boot option
>> + * Return: The full ESP device path or NULL if fail
>> + */
>> +static struct efi_device_path *get_esp_from_boot_option_file_path(struct efi_device_path *boot_dev)
>> +{
>> + efi_status_t ret = EFI_SUCCESS;
>> + efi_handle_t handle;
>> + struct efi_device_path *dp = boot_dev;
>> + struct efi_device_path *full_path = NULL;
>> +
>> + ret = EFI_CALL(efi_locate_device_path(&efi_simple_file_system_protocol_guid,
>> + &dp,
>> + &handle));
>> + if (ret != EFI_SUCCESS)
>> + ret = EFI_CALL(efi_locate_device_path(&efi_block_io_guid, &dp, &handle));
>> +
>> + /* Expand Media Device Path */
>> + if (ret == EFI_SUCCESS && EFI_DP_TYPE(dp, END, END)) {
>
> Flip this around. Always do failure handling. Never do success
> handling. full_path is always NULL. Just return that. Delete
> the variable.
>
> if (ret != EFI_SUCCESS ||
> !EFI_DP_TYPE(dp, END, END))
> return NULL;
>
>
>> + struct efi_device_path *temp_dp;
>> + struct efi_block_io *block_io;
>> + void *buffer;
>> + efi_handle_t *simple_file_system_handle;
>> + efi_uintn_t number_handles, index;
>> + u32 size;
>> + u32 temp_size;
>> +
>> + temp_dp = boot_dev;
>> + ret = EFI_CALL(efi_locate_device_path(&efi_simple_file_system_protocol_guid,
>> + &temp_dp,
>> + &handle));
>> + /*
>> + * For device path pointing to simple file system, it only expands to one
>> + * full path
>> + */
>> + if (ret == EFI_SUCCESS && EFI_DP_TYPE(temp_dp, END, END)) {
>
> "Always" was hyperbole. This success handling is fine.
>
>> + if (device_is_present_and_system_part(temp_dp))
>> + return temp_dp;
>> + }
>> +
>> + /*
>> + * For device path only pointing to the removable device handle, try to
>> + * search all its children handles
>> + */
>> + ret = EFI_CALL(efi_locate_device_path(&efi_block_io_guid, &temp_dp, &handle));
>
> ret is not used. Delete.
Errors should be handled and not ignored.
>
>> + EFI_CALL(efi_connect_controller(handle, NULL, NULL, true));
>> +
>> + /* Align with edk2, issue a dummy read to the device to check the device change */
>> + ret = EFI_CALL(efi_handle_protocol(handle, &efi_block_io_guid, (void **)&block_io));
>> + if (ret == EFI_SUCCESS) {
>
> if (ret != EFI_SUCCESS)
> return NULL;
>
>> + buffer = memalign(block_io->media->io_align, block_io->media->block_size);
>> + if (buffer) {
>
> if (!buffer)
> return NULL;
>
>
>> + ret = EFI_CALL(block_io->read_blocks(block_io,
>> + block_io->media->media_id,
>> + 0,
>> + block_io->media->block_size,
>> + buffer));
>
> Delete the unused "ret = " assignment.
ditto
Best regards
Heinrich
>
>> + free(buffer);
>> + } else {
>> + return full_path;
>> + }
>> + } else {
>> + return full_path;
>> + }
>> +
>> + /* detect the default boot file from removable media */
>> + size = efi_dp_size(boot_dev) - sizeof(struct efi_device_path);
>> + EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL,
>> + &efi_simple_file_system_protocol_guid,
>> + NULL,
>> + &number_handles,
>> + &simple_file_system_handle));
>> + for (index = 0; index < number_handles; index++) {
>> + EFI_CALL(efi_handle_protocol(simple_file_system_handle[index],
>> + &efi_guid_device_path,
>> + (void **)&temp_dp));
>> +
>> + log_debug("Search ESP %pD\n", temp_dp);
>> + temp_size = efi_dp_size(temp_dp) - sizeof(struct efi_device_path);
>> + if (size <= temp_size && !memcmp(temp_dp, boot_dev, size)) {
>> + if (device_is_present_and_system_part(temp_dp)) {
>
> You could combine these conditions:
>
> if (size <= temp_size &&
> memcmp(temp_dp, boot_dev, size) == 0 &&
> device_is_present_and_system_part(temp_dp)) {
> efi_free_pool(simple_file_system_handle);
> return temp_dp;
> }
>
>
>> + efi_free_pool(simple_file_system_handle);
>> + return temp_dp;
>> + }
>> + }
>> + }
>> +
>> + if (simple_file_system_handle)
>> + efi_free_pool(simple_file_system_handle);
>> + }
>> +
>> + return full_path;
>> +}
>> +
>> /**
>> * find_boot_device - identify the boot device
>> *
>> @@ -938,6 +1037,7 @@ static efi_status_t find_boot_device(void)
>> int i, num;
>> struct efi_simple_file_system_protocol *volume;
>> struct efi_device_path *boot_dev = NULL;
>> + struct efi_device_path *full_path = NULL;
>
> No need to initialize this to NULL, it disables static checker warnings
> for uninitialized variables so it can lead to bugs.
>
>> efi_status_t ret;
>>
>> /* find active boot device in BootNext */
>> @@ -961,8 +1061,14 @@ static efi_status_t find_boot_device(void)
>> if (device_is_present_and_system_part(boot_dev)) {
>> goto found;
>> } else {
>> - efi_free_pool(boot_dev);
>> - boot_dev = NULL;
>> + full_path = get_esp_from_boot_option_file_path(boot_dev);
>> + if (full_path) {
>> + boot_dev = full_path;
>
> Later, we free full_path but do we ever free the original boot_dev?
>
>> + goto found;
>> + } else {
>> + efi_free_pool(boot_dev);
>> + boot_dev = NULL;
>> + }
>
> Better to delete indenting where you can:
>
> full_path = get_esp_from_boot_option_file_path(boot_dev);
> if (full_path) {
> boot_dev = full_path;
> goto found;
> }
> efi_free_pool(boot_dev);
> boot_dev = NULL;
>
> regards,
> dan carpenter
>
>
More information about the U-Boot
mailing list