summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2025-10-09 13:50:59 -0600
committerTom Rini <trini@konsulko.com>2025-10-09 13:50:59 -0600
commit8cc77c78b0bc44aab44aa00e9a0ceab14ffe2017 (patch)
treed2d86c319404adb0d6311615c9c513983dcfc51d /lib
parenta1fd7a9589bf150c6f79d3a37fbc426f00a8af94 (diff)
parent50fc92938623be4a1cf1993c703812643afc9cdd (diff)
Merge patch series "fw_loader: Split from fs_loader into separate library file"
This series from Marek Vasut <marek.vasut+renesas@mailbox.org> splits the fw_loader "script" code out from the fs_loader code as the former does not require the latter. Link: https://lore.kernel.org/r/20250922114926.51984-1-marek.vasut+renesas@mailbox.org
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig8
-rw-r--r--lib/Makefile2
-rw-r--r--lib/fw_loader.c63
3 files changed, 73 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 7e48b179f6d..f5c1731f456 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -71,6 +71,14 @@ config DYNAMIC_CRC_TABLE
Enable this option to calculate entries for CRC tables at runtime.
This can be helpful when reducing the size of the build image
+config FW_LOADER
+ bool "Enable firmware loader using environment script"
+ depends on CMDLINE
+ depends on ENV_SUPPORT
+ help
+ Enable this option to make firmware loading using user-provided
+ U-Boot environment script functionality accessible to U-Boot code.
+
config HAVE_ARCH_IOMAP
bool
help
diff --git a/lib/Makefile b/lib/Makefile
index 2643bfc867c..a2e60668864 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_AES) += aes.o
obj-$(CONFIG_AES) += aes/
obj-$(CONFIG_$(PHASE_)BINMAN_FDT) += binman.o
+obj-$(CONFIG_FW_LOADER) += fw_loader.o
+
ifndef API_BUILD
ifneq ($(CONFIG_CHARSET),)
obj-y += charset.o
diff --git a/lib/fw_loader.c b/lib/fw_loader.c
new file mode 100644
index 00000000000..f776e09523a
--- /dev/null
+++ b/lib/fw_loader.c
@@ -0,0 +1,63 @@
+// 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;
+}