[PATCH v2 5/5] misc: fw_loader: implement request_firmware_size() OP

Francis, Neha n-francis at ti.com
Tue Mar 17 08:02:47 CET 2026


On 3/7/2026 12:35 AM, Christian Marangi wrote:
> It might be useful to get the firmware size before reading it to allocate the
> correct size. This is needed for case where the firmware size change across
> different firmware version and is not always the same. In such case the only way
> to handle this scenario is to allocate a big-enough buffer to read the firmware.
> 
> To better handle this, introduce the request_firmware_size() OP to get the
> firmware size before reading it. This way proper buffer can be allocated and
> dynamic firmware size can be better supported.
> 
> Both FS and FIP lodaer are updated to handle the new .get_size() handler.
> 
> Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> ---
>  drivers/misc/fw_loader/fip_loader.c | 35 +++++++++++++++
>  drivers/misc/fw_loader/fs_loader.c  | 70 ++++++++++++++++++++++++-----
>  drivers/misc/fw_loader/fw_loader.c  | 20 +++++++++
>  drivers/misc/fw_loader/internal.h   |  1 +
>  include/fw_loader.h                 |  9 ++++
>  5 files changed, 124 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/misc/fw_loader/fip_loader.c b/drivers/misc/fw_loader/fip_loader.c
> index 376e1d2a59d8..a285f785db37 100644
> --- a/drivers/misc/fw_loader/fip_loader.c
> +++ b/drivers/misc/fw_loader/fip_loader.c
> @@ -523,6 +523,40 @@ out:
>  	return ret;
>  }
>  
> +/**
> + * fw_get_fip_firmware_size - get firmware size.
> + * @dev: An instance of a driver.
> + *
> + * Return: Size of firmware, negative value when error.
> + */
> +static int fw_get_fip_firmware_size(struct udevice *dev)
> +{
> +	struct fip_toc_entry ent;
> +	struct fip_storage_info info = { };
> +	int ret;
> +
> +	ret = fw_parse_storage_info(dev, &info);
> +	if (ret)
> +		goto out;
> +
> +	struct firmware *firmwarep = dev_get_priv(dev);
> +
> +	if (!firmwarep) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	ret = parse_fip_firmware(firmwarep, &info, &ent);
> +	if (ret)
> +		goto out;
> +
> +	ret = ent.size;
> +
> +out:
> +	fw_storage_info_release(dev, &info);
> +	return ret;
> +}
> +
>  static int fip_loader_probe(struct udevice *dev)
>  {
>  	struct device_plat *plat = dev_get_plat(dev);
> @@ -533,6 +567,7 @@ static int fip_loader_probe(struct udevice *dev)
>  		return ret;
>  
>  	plat->get_firmware = fw_get_fip_firmware;
> +	plat->get_size = fw_get_fip_firmware_size;
>  
>  	return 0;
>  };
> diff --git a/drivers/misc/fw_loader/fs_loader.c b/drivers/misc/fw_loader/fs_loader.c
> index 4ae01b9c8f0d..d6b9f4998815 100644
> --- a/drivers/misc/fw_loader/fs_loader.c
> +++ b/drivers/misc/fw_loader/fs_loader.c
> @@ -93,15 +93,8 @@ static int select_fs_dev(struct device_plat *plat)
>  	return ret;
>  }
>  
> -/**
> - * fw_get_filesystem_firmware - load firmware into an allocated buffer.
> - * @dev: An instance of a driver.
> - *
> - * Return: Size of total read, negative value when error.
> - */
> -static int fw_get_filesystem_firmware(struct udevice *dev)
> +static int __fw_get_filesystem_firmware_prepare(struct udevice *dev)
>  {
> -	loff_t actread = 0;
>  	char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;
>  	int ret;
>  
> @@ -126,6 +119,28 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
>  		ret = select_fs_dev(dev_get_plat(dev));
>  	}
>  
> +	return ret;
> +}
> +
> +static void __fw_get_filesystem_firmware_release(struct udevice *dev)
> +{
> +#ifdef CONFIG_CMD_UBIFS
> +	umount_ubifs();
> +#endif
> +}
> +
> +/**
> + * fw_get_filesystem_firmware - load firmware into an allocated buffer.
> + * @dev: An instance of a driver.
> + *
> + * Return: Size of total read, negative value when error.
> + */
> +static int fw_get_filesystem_firmware(struct udevice *dev)
> +{
> +	loff_t actread = 0;
> +	int ret;
> +
> +	ret = __fw_get_filesystem_firmware_prepare(dev);
>  	if (ret)
>  		goto out;
>  
> @@ -147,9 +162,41 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
>  	}
>  
>  out:
> -#ifdef CONFIG_CMD_UBIFS
> -	umount_ubifs();
> -#endif
> +	__fw_get_filesystem_firmware_release(dev);
> +	return ret;
> +}
> +
> +/**
> + * fw_get_filesystem_firmware_size - get firmware size.
> + * @dev: An instance of a driver.
> + *
> + * Return: Size of firmware, negative value when error.
> + */
> +static int fw_get_filesystem_firmware_size(struct udevice *dev)
> +{
> +	loff_t size = 0;
> +	int ret;
> +
> +	ret = __fw_get_filesystem_firmware_prepare(dev);
> +	if (ret)
> +		goto out;
> +
> +	struct firmware *firmwarep = dev_get_priv(dev);
> +
> +	if (!firmwarep)
> +		return -ENOMEM;

goto out?

> +
> +	ret = fs_size(firmwarep->name, &size);
> +
> +	if (ret) {
> +		debug("Error: %d Failed to get size for %s.\n",
> +		      ret, firmwarep->name);
> +	} else {
> +		ret = size;
> +	}
> +
> +out:
> +	__fw_get_filesystem_firmware_release(dev);
>  	return ret;
>  }
>  
> @@ -163,6 +210,7 @@ static int fs_loader_probe(struct udevice *dev)
>  		return ret;
>  
>  	plat->get_firmware = fw_get_filesystem_firmware;
> +	plat->get_size = fw_get_filesystem_firmware_size;
>  
>  	return 0;
>  };
> diff --git a/drivers/misc/fw_loader/fw_loader.c b/drivers/misc/fw_loader/fw_loader.c
> index d2446fdc07da..d5973fce4b9c 100644
> --- a/drivers/misc/fw_loader/fw_loader.c
> +++ b/drivers/misc/fw_loader/fw_loader.c
> @@ -162,3 +162,23 @@ int request_firmware_into_buf(struct udevice *dev,
>  
>  	return plat->get_firmware(dev);
>  }
> +
> +int request_firmware_size(struct udevice *dev, const char *name)
> +{
> +	struct device_plat *plat;
> +	int ret;
> +
> +	if (!dev)
> +		return -EINVAL;
> +
> +	ret = _request_firmware_prepare(dev, name, NULL, 0, 0);
> +	if (ret < 0) /* error */
> +		return ret;
> +
> +	plat = dev_get_plat(dev);
> +
> +	if (!plat->get_size)
> +		return -EOPNOTSUPP;
> +
> +	return plat->get_size(dev);
> +}
> diff --git a/drivers/misc/fw_loader/internal.h b/drivers/misc/fw_loader/internal.h
> index 5513e043925f..4701b494bf3f 100644
> --- a/drivers/misc/fw_loader/internal.h
> +++ b/drivers/misc/fw_loader/internal.h
> @@ -36,6 +36,7 @@ struct device_plat {
>  	char *ubivol;
>  
>  	int (*get_firmware)(struct udevice *dev);
> +	int (*get_size)(struct udevice *dev);
>  };
>  
>  /**
> diff --git a/include/fw_loader.h b/include/fw_loader.h
> index 7053c7bc6f05..1af3db385161 100644
> --- a/include/fw_loader.h
> +++ b/include/fw_loader.h
> @@ -39,6 +39,15 @@ int request_firmware_into_buf(struct udevice *dev,
>  			      const char *name,
>  			      void *buf, size_t size, u32 offset);
>  
> +/**
> + * request_firmware_size - Get firmware size.
> + * @dev: An instance of a driver.
> + * @name: Name of firmware file.
> + *
> + * Return: Size of firmware, negative value when error.
> + */
> +int request_firmware_size(struct udevice *dev, const char *name);
> +
>  /**
>   * request_firmware_into_buf_via_script() -
>   * Load firmware using a U-Boot script and copy to buffer

Thanks for this series. I think this starts to pave the way for us to move away
from using vendor specific drivers scattered around (like
arch/arm/mach-k3/r5/sysfw-loader.c) and eventually come into fw_loader.

-- 
Thanking You
Neha Malcom Francis



More information about the U-Boot mailing list