This commit adds request_firmware_into_buf_via_env() to the fs_loader driver, enabling firmware loading into a buffer using environment variables for path and size. It supports multiple entries via indexed variable names (e.g., "fw_dir0", "fw_size0"). This provides flexible, scriptable firmware loading without hardcoded details.
Signed-off-by: Lucien.Jheng <lucienzx...@gmail.com> --- Change log: - Re-sending as previous version and add more maintainers to review. drivers/misc/fs_loader.c | 59 ++++++++++++++++++++++++++++++++++++++++ include/fs_loader.h | 18 ++++++++++++ 2 files changed, 77 insertions(+) diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 66803f4b997..a4f4448f5cc 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -228,6 +228,65 @@ int request_firmware_into_buf(struct udevice *dev, return ret; } +/** + * request_firmware_into_buf_via_env - Load firmware using environment variables. + * @dev: An instance of a driver. + * @buf: Address of buffer to load firmware into. + * @offset: Offset of a file for start reading into buffer. + * @fw_index: Index of the firmware entry to load. + * + * This function loads firmware into the provided buffer using environment + * variables to determine the firmware file path, address, and size. It supports + * multiple firmware entries by using indexed environment variable names such as + * "fw_dir0", "fw_size0", etc. + * + * Return: Size of total read, negative value when error. + */ +int request_firmware_into_buf_via_env(struct udevice *dev, + void *buf, u32 offset, + unsigned int fw_index) +{ + char var_name[32]; + size_t size; + int ret; + + for (unsigned int index = 0; index < fw_index; index++) { + snprintf(var_name, sizeof(var_name), "fw_dir%u", index); + const char *name = env_get(var_name); + + if (!name) { + printf("Error: env var %s not set.\n", var_name); + goto fail; + } + + snprintf(var_name, sizeof(var_name), "fw_size%u", index); + size = env_get_hex(var_name, 0); + if (!size) { + printf("Error: env var %s is invalid or zero.\n", var_name); + goto fail; + } + + ret = request_firmware_into_buf(dev, name, buf, size, offset); + if (ret < 0) { + printf("Error: Failed to load firmware %s, size 0x%zx.\n", + name, size); + return ret; + } + + buf = (void *)((uintptr_t)buf + size); + } + + return 0; +fail: + printf("Error: Failed to load firmware via environment variables.\n" + "Set these environment variables for each firmware index:\n" + " fw_dirN - path to firmware file (e.g., fw_dir0)\n" + " fw_sizeN - size of firmware (e.g., fw_size0)\n" + "Where N is the firmware index (0, 1, ...).\n"); + + return -EINVAL; +} + static int fs_loader_of_to_plat(struct udevice *dev) { u32 phandlepart[2]; diff --git a/include/fs_loader.h b/include/fs_loader.h index 5eb5b7ab4a1..0d130daacfc 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -64,4 +64,22 @@ int request_firmware_into_buf(struct udevice *dev, * Return: 0 on success, negative value on error */ int get_fs_loader(struct udevice **dev); + +/** + * request_firmware_into_buf_via_env - Load firmware using environment variables. + * @dev: An instance of a driver. + * @buf: Address of buffer to load firmware into. + * @offset: Offset of a file for start reading into buffer. + * @fw_index: Index of the firmware entry to load. + * + * This function loads firmware into the provided buffer using environment + * variables to determine the firmware file path, address, and size. It supports + * multiple firmware entries by using indexed environment variable names such as + * "fw_dir0", "fw_size0", etc. + * + * Return: Size of total read, negative value when error. + */ +int request_firmware_into_buf_via_env(struct udevice *dev, + void *buf, u32 offset, + unsigned int fw_index); #endif -- 2.34.1