diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 66803f4b997..60296d55f23 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -228,6 +228,52 @@ int request_firmware_into_buf(struct udevice *dev, return ret; } +int request_firmware_into_buf_via_script(void **buf, size_t max_size, + const char *script_name) +{ + ulong addr, size; + int ret; + char cmd[32]; + + if (!buf || !script_name || !max_size) + return -EINVAL; + + /* Create command to run the firmware loading script */ + snprintf(cmd, sizeof(cmd), "run %s", script_name); + + /* Run the firmware loading script */ + ret = run_command_list(cmd, -1, 0); + if (ret) { + log_err("Firmware loading script '%s' not defined or failed.\n", + script_name); + return -EINVAL; + } + + /* Find out where the firmware got loaded and how long it is */ + addr = env_get_hex("fw_addr", 0); + size = env_get_hex("fw_size", 0); + + /* Clear the variables set by the firmware loading script */ + env_set("fw_addr", NULL); + env_set("fw_size", NULL); + + if (!addr || !size) { + log_err("Firmware address (0x%lx) or size (0x%lx) are invalid.\n", + addr, size); + return -EINVAL; + } + + if (size > max_size) { + log_err("Loaded firmware size 0x%lx exceeded maximum allowed size 0x%zx.\n", + size, max_size); + return -E2BIG; + } + + memcpy(*buf, (void *)addr, size); + + return 0; +} + 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..a433be1eb99 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -64,4 +64,28 @@ 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_script() - + * Load firmware using a U-Boot script and copy to buffer + * @buf: Pointer to a pointer where the firmware buffer will be stored. + * @max_size: Maximum allowed size for the firmware to be loaded. + * @script_name: Name of the U-Boot script to execute for firmware loading. + * + * Executes a U-Boot script (@script_name) that loads firmware into + * memory and sets the environment variables 'fw_addr' (address) and + * 'fw_size' (size in bytes). On success, copies the firmware + * from the given address to user buffer @buf. + * + * The script must set these environment variables: + * fw_addr - Address where firmware is loaded in memory + * fw_size - Size of the firmware in bytes + * + * The script should be defined in the U-Boot environment, for example: + * env set script_name 'load mmc 0:1 ${loadaddr} firmware.bin && + * env set fw_addr ${loadaddr} && env set fw_size ${filesize} + * Return: 0 on success, negative value on error. + */ +int request_firmware_into_buf_via_script(void **buf, size_t max_size, + const char *script_name); #endif