[PATCH v6 4/6] misc: fw_loader: implement request_firmware_size() OP
Christian Marangi
ansuelsmth at gmail.com
Thu Apr 9 15:33:00 CEST 2026
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.
FS loader is updated to handle the new .get_size() handler.
Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
drivers/misc/fw_loader/fs_loader.c | 68 +++++++++++++++++++----
drivers/misc/fw_loader/fw_loader-uclass.c | 19 +++++++
drivers/misc/fw_loader/internal.h | 7 +++
include/fw_loader.h | 9 +++
4 files changed, 91 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/fw_loader/fs_loader.c b/drivers/misc/fw_loader/fs_loader.c
index 2694111d8396..8f549654a1be 100644
--- a/drivers/misc/fw_loader/fs_loader.c
+++ b/drivers/misc/fw_loader/fs_loader.c
@@ -89,18 +89,10 @@ 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_prepare(struct udevice *dev)
{
char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;
- struct firmware *upriv = dev_get_uclass_priv(dev);
struct device_plat *plat = dev_get_uclass_plat(dev);
- loff_t actread = 0;
int ret;
storage_interface = env_get("storage_interface");
@@ -124,6 +116,29 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
ret = select_fs_dev(plat);
}
+ return ret;
+}
+
+static void fw_get_filesystem_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)
+{
+ struct firmware *upriv = dev_get_uclass_priv(dev);
+ loff_t actread = 0;
+ int ret;
+
+ ret = fw_get_filesystem_prepare(dev);
if (ret)
goto out;
@@ -138,14 +153,43 @@ static int fw_get_filesystem_firmware(struct udevice *dev)
}
out:
-#ifdef CONFIG_CMD_UBIFS
- umount_ubifs();
-#endif
+ fw_get_filesystem_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)
+{
+ struct firmware *upriv = dev_get_uclass_priv(dev);
+ loff_t size = 0;
+ int ret;
+
+ ret = fw_get_filesystem_prepare(dev);
+ if (ret)
+ goto out;
+
+ ret = fs_size(upriv->name, &size);
+ if (ret) {
+ debug("Error: %d Failed to get size for %s.\n",
+ ret, upriv->name);
+ goto out;
+ }
+
+ ret = size;
+
+out:
+ fw_get_filesystem_release(dev);
return ret;
}
static const struct fw_loader_ops fs_loader_ops = {
.get_firmware = fw_get_filesystem_firmware,
+ .get_size = fw_get_filesystem_firmware_size,
};
static const struct udevice_id fs_loader_ids[] = {
diff --git a/drivers/misc/fw_loader/fw_loader-uclass.c b/drivers/misc/fw_loader/fw_loader-uclass.c
index c32c213b5b38..19379c23411b 100644
--- a/drivers/misc/fw_loader/fw_loader-uclass.c
+++ b/drivers/misc/fw_loader/fw_loader-uclass.c
@@ -168,3 +168,22 @@ int request_firmware_into_buf(struct udevice *dev,
return ops->get_firmware(dev);
}
+
+int request_firmware_size(struct udevice *dev, const char *name)
+{
+ struct fw_loader_ops *ops;
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ ret = _request_firmware_prepare(dev, name, NULL, 0, 0);
+ if (ret < 0) /* error */
+ return ret;
+
+ ops = fw_loader_get_ops(dev);
+ if (!ops->get_size)
+ return -EOPNOTSUPP;
+
+ return ops->get_size(dev);
+}
diff --git a/drivers/misc/fw_loader/internal.h b/drivers/misc/fw_loader/internal.h
index 2f93d0c706b6..9964dc436afb 100644
--- a/drivers/misc/fw_loader/internal.h
+++ b/drivers/misc/fw_loader/internal.h
@@ -32,6 +32,13 @@ struct fw_loader_ops {
* @dev: Firmware Loader device to read firmware from
*/
int (*get_firmware)(struct udevice *dev);
+
+ /**
+ * get_size() - get firmware size from Firmware Loader driver
+ *
+ * @dev: Firmware Loader device to get firmware size from
+ */
+ int (*get_size)(struct udevice *dev);
};
#define fw_loader_get_ops(dev) ((struct fw_loader_ops *)(dev)->driver->ops)
diff --git a/include/fw_loader.h b/include/fw_loader.h
index 99c47380a172..01f242dcbefd 100644
--- a/include/fw_loader.h
+++ b/include/fw_loader.h
@@ -38,6 +38,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
--
2.53.0
More information about the U-Boot
mailing list