| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * Copyright (C) 2025 Lucien Jheng <lucienzx159@gmail.com> | |
| */ | |
| #include <command.h> | |
| #include <env.h> | |
| #include <errno.h> | |
| #include <linux/types.h> | |
| #include <log.h> | |
| int request_firmware_into_buf_via_script(void *buf, size_t max_size, | |
| const char *script_name, | |
| size_t *retsize) | |
| { | |
| char env_addr[CONFIG_SYS_CBSIZE] = { 0 }; | |
| char env_size[CONFIG_SYS_CBSIZE] = { 0 }; | |
| char *args[2] = { "run", (char *)script_name }; | |
| int ret, repeatable; | |
| ulong addr, size; | |
| if (!buf || !script_name || !max_size) | |
| return -EINVAL; | |
| /* Run the firmware loading script */ | |
| ret = cmd_process(0, 2, args, &repeatable, NULL); | |
| if (ret) { | |
| log_err("Firmware loading script '%s' not defined or failed.\n", | |
| script_name); | |
| return -EINVAL; | |
| } | |
| /* Prefix the FW loader variables with the script prefix */ | |
| snprintf(env_addr, sizeof(env_addr), "%s_addr", script_name); | |
| snprintf(env_size, sizeof(env_size), "%s_size", script_name); | |
| /* Find out where the firmware got loaded and how long it is */ | |
| addr = env_get_hex(env_addr, 0); | |
| size = env_get_hex(env_size, 0); | |
| /* Clear the variables set by the firmware loading script */ | |
| env_set(env_addr, NULL); | |
| env_set(env_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; | |
| } | |
| if (retsize) | |
| *retsize = size; | |
| memcpy(buf, (void *)addr, size); | |
| return 0; | |
| } |