[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