mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/9] Firmware: support compressing firmware files
@ 2026-03-16 17:21 Sascha Hauer
  2026-03-16 17:21 ` [PATCH 1/9] ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB Sascha Hauer
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX; +Cc: Sascha Hauer, Claude Opus 4.6

TF-A and OP-TEE can reach significant sizes nowadays and are currently
uncompressed in the PBL. This series supports including them in compressed
form in the PBL. To accomplish this we introduce a new macro
get_builtin_firmware_compressed() which returns the compressed firmware
image. This can be decompressed afterwards with fwobj_uncompress().
There are always both the compressed and uncompressed images generated,
so the code can decide which one to use. This series switches over the
Rockchip TF-A and OP-TEE binaries to use the compressed variants.

Also included in this series are some unrelated patches I stumbled upon
while creating this series.

Sascha

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Sascha Hauer (9):
      ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB
      ARM: radxa-rock5: Use compressed DTB
      ARM: Rockchip: Simplify retrieval of SoC specific addresses
      firmware: Move firmware assembly generation to scripts/gen-fw-s
      firmware: Use struct fwobj for get_builtin_firmware APIs
      firmware: Add compressed firmware symbols for PBL
      firmware: Add fwobj_uncompress() for decompressing firmware in PBL
      ARM: Rockchip: Use compressed OP-TEE binary
      ARM: Rockchip: Use compressed TF-A binary

 arch/arm/boards/radxa-rock5/lowlevel.c   |   8 +--
 arch/arm/boards/tqma6ulx/lowlevel.c      |   7 +--
 arch/arm/boards/webasto-ccbv2/lowlevel.c |   7 +--
 arch/arm/mach-imx/atf.c                  |  84 +++++++++++--------------
 arch/arm/mach-imx/ele.c                  |  12 ++--
 arch/arm/mach-imx/esdctl.c               |   7 +--
 arch/arm/mach-layerscape/tfa.c           |   7 +--
 arch/arm/mach-rockchip/atf.c             | 103 ++++++++++++++++++++-----------
 arch/arm/mach-socfpga/Kconfig            |   2 -
 arch/arm/mach-socfpga/atf.c              |   7 +--
 drivers/ddr/imx/ddrphy_train.c           |  97 ++++++++++-------------------
 drivers/mci/imx-esdhc-pbl.c              |   7 +--
 drivers/net/fsl-fman.c                   |  11 ++--
 firmware/Makefile                        |  65 ++++++-------------
 include/firmware.h                       |  37 ++++++++---
 pbl/decomp.c                             |   7 +++
 scripts/gen-fw-s                         |  87 ++++++++++++++++++++++++++
 17 files changed, 311 insertions(+), 244 deletions(-)
---
base-commit: 52bb6e0cada8a82cf665668cfbdfcd4e4854a027
change-id: 20260316-compressed-firmware-efa51a7bda9d

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/9] ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 2/9] ARM: radxa-rock5: Use compressed DTB Sascha Hauer
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX

USE_COMPRESSED_DTB is already selected at architecture level, so drop it
from the SoC.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-socfpga/Kconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 9818e7d9be..734d2c6d7a 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -23,7 +23,6 @@ config ARCH_SOCFPGA_ARRIA10
 	bool
 	select CPU_V7
 	select ARM_SMP_TWD
-	select USE_COMPRESSED_DTB
 	select RESET_CONTROLLER
 	select OFDEVICE
 	select OFTREE
@@ -76,7 +75,6 @@ if 64BIT
 config ARCH_SOCFPGA_AGILEX5
 	bool
 	select CPU_V8
-	select USE_COMPRESSED_DTB
 	select RESET_CONTROLLER
 	select RESET_SIMPLE
 	select OFDEVICE

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/9] ARM: radxa-rock5: Use compressed DTB
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
  2026-03-16 17:21 ` [PATCH 1/9] ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 3/9] ARM: Rockchip: Simplify retrieval of SoC specific addresses Sascha Hauer
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/radxa-rock5/lowlevel.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boards/radxa-rock5/lowlevel.c b/arch/arm/boards/radxa-rock5/lowlevel.c
index 373cc1ba4e..e70752be31 100644
--- a/arch/arm/boards/radxa-rock5/lowlevel.c
+++ b/arch/arm/boards/radxa-rock5/lowlevel.c
@@ -8,8 +8,8 @@
 #include <debug_ll.h>
 #include <mach/rockchip/rockchip.h>
 
-extern char __dtb_rk3588_rock_5b_start[];
-extern char __dtb_rk3588_rock_5t_start[];
+extern char __dtb_z_rk3588_rock_5b_start[];
+extern char __dtb_z_rk3588_rock_5t_start[];
 
 ENTRY_FUNCTION(start_rock5b, r0, r1, r2)
 {
@@ -22,7 +22,7 @@ ENTRY_FUNCTION(start_rock5b, r0, r1, r2)
 
 	setup_c();
 
-	rk3588_barebox_entry(__dtb_rk3588_rock_5b_start);
+	rk3588_barebox_entry(__dtb_z_rk3588_rock_5b_start);
 }
 
 ENTRY_FUNCTION(start_rock5t, r0, r1, r2)
@@ -36,5 +36,5 @@ ENTRY_FUNCTION(start_rock5t, r0, r1, r2)
 
 	setup_c();
 
-	rk3588_barebox_entry(__dtb_rk3588_rock_5t_start);
+	rk3588_barebox_entry(__dtb_z_rk3588_rock_5t_start);
 }

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 3/9] ARM: Rockchip: Simplify retrieval of SoC specific addresses
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
  2026-03-16 17:21 ` [PATCH 1/9] ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB Sascha Hauer
  2026-03-16 17:21 ` [PATCH 2/9] ARM: radxa-rock5: Use compressed DTB Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 4/9] firmware: Move firmware assembly generation to scripts/gen-fw-s Sascha Hauer
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX

due to the nature of get_builtin_firmware() and the preprocessor
resolving of defines rockchip_atf_load_bl31 needs to be a macro. This is
not nice to look at and shouldn't be extended. Extending it is what we
want to do in the next step, so rework this into a macro which only
retrieves the addresses and from the actual code create a function.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-rockchip/atf.c | 70 ++++++++++++++++++++++++++------------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
index a60b55ae24..8d7e505a99 100644
--- a/arch/arm/mach-rockchip/atf.c
+++ b/arch/arm/mach-rockchip/atf.c
@@ -108,34 +108,45 @@ static uintptr_t rk_load_optee(uintptr_t bl32, const void *bl32_image,
 	return bl32;
 }
 
-#define rockchip_atf_load_bl31(SOC, atf_bin, tee_bin, fdt) do {                 \
-	const void *bl31_elf, *optee;                                           \
-	unsigned long bl31;                                                     \
-	size_t bl31_elf_size, optee_size;                                       \
-	uintptr_t optee_load_address = 0;                                       \
-										\
-	get_builtin_firmware(atf_bin, &bl31_elf, &bl31_elf_size);               \
-										\
-	bl31 = load_elf64_image_phdr(bl31_elf);                                 \
-										\
-	if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE)) {                           \
-		get_builtin_firmware(tee_bin, &optee, &optee_size);             \
-		optee_load_address = rk_load_optee(SOC##_OPTEE_LOAD_ADDRESS,	\
-						   optee, optee_size);		\
-	}                                                                       \
-										\
-	/* Setup an initial stack for EL2 */                                    \
-	asm volatile("msr sp_el2, %0" : :                                       \
-			"r" ((ulong)SOC##_BAREBOX_LOAD_ADDRESS - 16) :		\
-			"cc");                                                  \
-										\
-	bl31_entry(bl31, optee_load_address,                                    \
-		   SOC##_BAREBOX_LOAD_ADDRESS, (uintptr_t)fdt);                 \
-} while (0)                                                                     \
+static uintptr_t barebox_load_address; /* where barebox is loaded and started */
+static uintptr_t optee_load_address; /* standard SoC specific OP-TEE load address */
+static const void *bl31; /* pointer to TF-A in barebox image */
+static size_t bl31_size; /* size of TF-A in barebox image */
+static const void *bl32; /* pointer to OP-TEE in barebox image */
+static size_t bl32_size; /* size of OP-TEE in barebox image */
+
+#define ROCKCHIP_GET_ADDRESSES(SOC, atf_bin, tee_bin)				\
+	do {									\
+		barebox_load_address = SOC##_BAREBOX_LOAD_ADDRESS;		\
+		optee_load_address = SOC##_OPTEE_LOAD_ADDRESS;			\
+		get_builtin_firmware(atf_bin, &bl31, &bl31_size);		\
+		if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))			\
+			get_builtin_firmware(tee_bin, &bl32, &bl32_size);	\
+	} while (0)
+
+
+static void rockchip_atf_load_bl31(void *fdt)
+{
+	unsigned long bl31_ep;
+
+	bl31_ep = load_elf64_image_phdr(bl31);
+
+	if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))
+		optee_load_address = rk_load_optee(optee_load_address, bl32, bl32_size);
+
+	/* Setup an initial stack for EL2 */
+	asm volatile("msr sp_el2, %0" : :
+			"r" ((ulong)barebox_load_address - 16) :
+			"cc");
+
+	bl31_entry(bl31_ep, optee_load_address,
+		   barebox_load_address, (uintptr_t)fdt);
+}
 
 void rk3562_atf_load_bl31(void *fdt)
 {
-	rockchip_atf_load_bl31(RK3562, rk3562_bl31_bin, rk3562_bl32_bin, fdt);
+	ROCKCHIP_GET_ADDRESSES(RK3562, rk3562_bl31_bin, rk3562_bl32_bin);
+	rockchip_atf_load_bl31(fdt);
 }
 
 void __noreturn rk3562_barebox_entry(void *fdt)
@@ -172,7 +183,8 @@ void __noreturn rk3562_barebox_entry(void *fdt)
 
 void rk3568_atf_load_bl31(void *fdt)
 {
-	rockchip_atf_load_bl31(RK3568, rk3568_bl31_bin, rk3568_bl32_bin, fdt);
+	ROCKCHIP_GET_ADDRESSES(RK3568, rk3568_bl31_bin, rk3568_bl32_bin);
+	rockchip_atf_load_bl31(fdt);
 }
 
 void __noreturn rk3568_barebox_entry(void *fdt)
@@ -209,7 +221,8 @@ void __noreturn rk3568_barebox_entry(void *fdt)
 
 void rk3588_atf_load_bl31(void *fdt)
 {
-	rockchip_atf_load_bl31(RK3588, rk3588_bl31_bin, rk3588_bl32_bin, fdt);
+	ROCKCHIP_GET_ADDRESSES(RK3588, rk3588_bl31_bin, rk3588_bl32_bin);
+	rockchip_atf_load_bl31(fdt);
 }
 
 static int rk3588_fixup_mem(void *fdt)
@@ -282,7 +295,8 @@ void __noreturn rk3588_barebox_entry(void *fdt)
 
 void rk3576_atf_load_bl31(void *fdt)
 {
-	rockchip_atf_load_bl31(RK3576, rk3576_bl31_bin, rk3576_bl32_bin, fdt);
+	ROCKCHIP_GET_ADDRESSES(RK3576, rk3576_bl31_bin, rk3576_bl32_bin);
+	rockchip_atf_load_bl31(fdt);
 }
 
 void __noreturn rk3576_barebox_entry(void *fdt)

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 4/9] firmware: Move firmware assembly generation to scripts/gen-fw-s
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (2 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 3/9] ARM: Rockchip: Simplify retrieval of SoC specific addresses Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 5/9] firmware: Use struct fwobj for get_builtin_firmware APIs Sascha Hauer
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX; +Cc: Sascha Hauer, Claude Opus 4.6

From: Sascha Hauer <sascha@saschahauer.de>

Extract the inline filechk_fwbin shell code from firmware/Makefile into
a standalone script at scripts/gen-fw-s, following the pattern of
scripts/gen-dtb-s.

The FWSTR and FWNAME_EXISTS variables are no longer needed in the
Makefile as they are now computed within the script.

Some #ifdefs are already known during execution of gen-fw-s. As it is
raw shell now instead of shell encapsulated in a Makefile we can improve
readability by replacing these #ifdefs with shell "if".

Also while at it add some comments what is happening as the missing
firmware handling is not entirely obvious.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de
---
 firmware/Makefile | 51 +++++---------------------------------------
 scripts/gen-fw-s  | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 46 deletions(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index a3b1887dc6..b247db8da2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -60,56 +60,15 @@ obj-pbl-y := $(addsuffix .gen.o, $(firmware-y))
 pbl-fwext-y := $(addsuffix .extgen.o, $(fw-external-y))
 
 FWNAME    = $(patsubst $(obj)/%.extgen.S,%,$(patsubst $(obj)/%.gen.S,%,$@))
-FWSTR     = $(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME))))
-FWNAME_EXISTS = $(if $(wildcard $(FIRMWARE_DIR)/$(FWNAME)),1,0)
-
-filechk_fwbin = { \
-	SHA=$$(sha256sum $(FIRMWARE_DIR)/$(FWNAME) |		\
-		sed 's/ .*$$//;s/../0x&, /g;s/, $$//')		\
-		2>/dev/null					;\
-	\
-	echo "/* Generated by $(src)/Makefile */"		;\
-	echo "\#include <asm-generic/pointer.h>"		;\
-	echo ".section .note.GNU-stack,\"\",%progbits"		;\
-	echo "    .section $2,\"$3\""				;\
-	echo "    .p2align ASM_LGPTR"				;\
-	echo ".global _fw_$(FWSTR)_start"			;\
-	echo "_fw_$(FWSTR)_start:"				;\
-	echo "\#if $(FWNAME_EXISTS)"				;\
-	echo "    .incbin \"$(FIRMWARE_DIR)/$(FWNAME)\""		;\
-	echo "\#elif defined(__PBL__)"				;\
-	echo "ASM_PTR _fwname_$(FWSTR)"				;\
-	echo "\#endif"						;\
-	echo ".global _fw_$(FWSTR)_end"				;\
-	echo "_fw_$(FWSTR)_end:"				;\
-	echo "\#ifdef __PBL__"					;\
-	echo "    .section .missing_fw,\"a\""			;\
-	echo "_fwname_$(FWSTR):"				;\
-	printf '.ascii "%s"\n' 'firmware/$(FWNAME)\n'		;\
-	echo "\#endif" 						;\
-	echo "    .section .rodata.$(FWSTR).sha"		;\
-	echo "    .p2align ASM_LGPTR"				;\
-	echo ".global _fw_$(FWSTR)_sha_start"			;\
-	echo "_fw_$(FWSTR)_sha_start:"				;\
-	echo "    .byte $${SHA}"				;\
-	echo ".global _fw_$(FWSTR)_sha_end"			;\
-	echo "_fw_$(FWSTR)_sha_end:"				;\
-	echo "\#if $(FWNAME_EXISTS)"				;\
-	echo ".if _fw_$(FWSTR)_sha_start + 32 - _fw_$(FWSTR)_sha_end";\
-	echo ".error \"sha256sum invalid\""			;\
-	echo ".endif"						;\
-	echo "\#endif"						;\
-}
-
-filechk_fwbin_ext = { \
-	$(filechk_fwbin)					;\
-}
+
+filechk_fwbin = $(srctree)/scripts/gen-fw-s $(FWNAME) $(FIRMWARE_DIR) .rodata
+filechk_fwbin_ext = $(srctree)/scripts/gen-fw-s $(FWNAME) $(FIRMWARE_DIR) .pblext a
 
 $(obj)/%.gen.S: FORCE
-	$(call filechk,fwbin,.rodata.$(FWSTR),)
+	$(call filechk,fwbin)
 
 $(obj)/%.extgen.S: FORCE
-	$(call filechk,fwbin_ext,.pblext.$(FWSTR),a)
+	$(call filechk,fwbin_ext)
 
 # This dependency is used if missing firmware should fail the build immediately
 fwdep-required-y = $(FIRMWARE_DIR)/%
diff --git a/scripts/gen-fw-s b/scripts/gen-fw-s
new file mode 100755
index 0000000000..653e6f013a
--- /dev/null
+++ b/scripts/gen-fw-s
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generate assembly source to embed firmware binary
+#
+# Usage: gen-fw-s <fwname> <fwdir> <secprefix> [secflags]
+
+fwname=$1
+fwdir=$2
+secprefix=$3
+secflags=$4
+
+fwstr=$(echo "$fwname" | tr '/.-' '___')
+fwpath="$fwdir/$fwname"
+
+sha=$(sha256sum "$fwpath" 2>/dev/null | sed 's/ .*$//;s/../0x&, /g;s/, $//')
+
+echo "/* Generated by scripts/gen-fw-s */"
+echo "#include <asm-generic/pointer.h>"
+echo ".section .note.GNU-stack,\"\",%progbits"
+
+# include firmware if exists, otherwise include a reference to
+# the firmware filename in the .missing_fw section
+echo "    .section ${secprefix}.${fwstr},\"${secflags}\""
+echo "    .p2align ASM_LGPTR"
+echo ".global _fw_${fwstr}_start"
+echo "_fw_${fwstr}_start:"
+if [ -f "$fwpath" ]; then
+	echo ".incbin \"${fwpath}\""
+else
+	echo "#if defined(__PBL__)"
+	echo "ASM_PTR _fwname_${fwstr}"
+	echo "#endif"
+fi
+echo ".global _fw_${fwstr}_end"
+echo "_fw_${fwstr}_end:"
+
+# include sha256, needed for external firmware
+echo "    .section .rodata.${fwstr}.sha"
+echo "    .p2align ASM_LGPTR"
+echo ".global _fw_${fwstr}_sha_start"
+echo "_fw_${fwstr}_sha_start:"
+echo "    .byte ${sha}"
+echo ".global _fw_${fwstr}_sha_end"
+echo "_fw_${fwstr}_sha_end:"
+if [ -f "$fwpath" ]; then
+	echo ".if _fw_${fwstr}_sha_start + 32 - _fw_${fwstr}_sha_end"
+	echo ".error \"sha256sum invalid\""
+	echo ".endif"
+fi
+
+# include a string containing the firmware name. When a non existing
+# firmware is referenced in the PBL then _fwname_${fwstr} is referenced
+# above rather than the firmware itself. The barebox build system checks
+# if the missing_fw section is empty. If it is, then we have all necessary
+# firmware files. If not, then we either fail the compilation
+# (CONFIG_MISSING_FIRMWARE_ERROR=y) or print a missing firmware warning
+# (CONFIG_MISSING_FIRMWARE_ERROR=n).
+echo "#ifdef __PBL__"
+echo "    .section .missing_fw,\"a\""
+echo "_fwname_${fwstr}:"
+printf '.ascii "%s"\n' "firmware/${fwname}\\n"
+echo "#endif"

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 5/9] firmware: Use struct fwobj for get_builtin_firmware APIs
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (3 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 4/9] firmware: Move firmware assembly generation to scripts/gen-fw-s Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 6/9] firmware: Add compressed firmware symbols for PBL Sascha Hauer
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX; +Cc: Sascha Hauer, Claude Opus 4.6

From: Sascha Hauer <sascha@saschahauer.de>

Replace the separate start/size output parameters of
get_builtin_firmware() and get_builtin_firmware_ext() with a single
struct fwobj pointer. This groups the firmware data pointer and size
together, reducing the number of variables at call sites.

Update all callers across imx, rockchip, layerscape, socfpga, and
board-specific code to use the new struct-based interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/tqma6ulx/lowlevel.c      |  7 +--
 arch/arm/boards/webasto-ccbv2/lowlevel.c |  7 +--
 arch/arm/mach-imx/atf.c                  | 84 ++++++++++++---------------
 arch/arm/mach-imx/ele.c                  | 12 ++--
 arch/arm/mach-imx/esdctl.c               |  7 +--
 arch/arm/mach-layerscape/tfa.c           |  7 +--
 arch/arm/mach-rockchip/atf.c             | 14 ++---
 arch/arm/mach-socfpga/atf.c              |  7 +--
 drivers/ddr/imx/ddrphy_train.c           | 97 +++++++++++---------------------
 drivers/mci/imx-esdhc-pbl.c              |  7 +--
 drivers/net/fsl-fman.c                   | 11 ++--
 include/firmware.h                       | 23 +++++---
 12 files changed, 120 insertions(+), 163 deletions(-)

diff --git a/arch/arm/boards/tqma6ulx/lowlevel.c b/arch/arm/boards/tqma6ulx/lowlevel.c
index 57639f8a84..6981a96926 100644
--- a/arch/arm/boards/tqma6ulx/lowlevel.c
+++ b/arch/arm/boards/tqma6ulx/lowlevel.c
@@ -71,8 +71,7 @@ static void *read_eeprom(void)
 static void noinline start_mba6ulx(void)
 {
 	void *fdt;
-	int tee_size;
-	void *tee;
+	struct fwobj tee;
 
 	setup_uart();
 
@@ -84,9 +83,9 @@ static void noinline start_mba6ulx(void)
 	 */
 	if (IS_ENABLED(CONFIG_FIRMWARE_TQMA6UL_OPTEE) && imx6_can_access_tzasc()) {
 
-		get_builtin_firmware(mba6ul_optee_bin, &tee, &tee_size);
+		get_builtin_firmware(mba6ul_optee_bin, &tee);
 
-		imx6ul_start_optee_early(NULL, tee, (void *)OPTEE_OVERLAY_LOCATION, 0x1000);
+		imx6ul_start_optee_early(NULL, tee.data, (void *)OPTEE_OVERLAY_LOCATION, 0x1000);
 	}
 
 	imx6ul_barebox_entry(fdt);
diff --git a/arch/arm/boards/webasto-ccbv2/lowlevel.c b/arch/arm/boards/webasto-ccbv2/lowlevel.c
index c25f8a9cb3..a5dd156473 100644
--- a/arch/arm/boards/webasto-ccbv2/lowlevel.c
+++ b/arch/arm/boards/webasto-ccbv2/lowlevel.c
@@ -34,8 +34,7 @@ static void configure_uart(void)
 
 static void noinline start_ccbv2(unsigned long mem_size, char *fdt)
 {
-	int tee_size;
-	void *tee;
+	struct fwobj tee;
 
 	configure_uart();
 
@@ -44,9 +43,9 @@ static void noinline start_ccbv2(unsigned long mem_size, char *fdt)
 	 * if we can access the TZASC.
 	 */
 	if (IS_ENABLED(CONFIG_FIRMWARE_TQMA6UL_OPTEE) && imx6_can_access_tzasc()) {
-		get_builtin_firmware(ccbv2_optee_bin, &tee, &tee_size);
+		get_builtin_firmware(ccbv2_optee_bin, &tee);
 
-		imx6ul_start_optee_early(NULL, tee, (void *)OPTEE_OVERLAY_LOCATION, 0x1000);
+		imx6ul_start_optee_early(NULL, tee.data, (void *)OPTEE_OVERLAY_LOCATION, 0x1000);
 	}
 
 	imx6ul_barebox_entry(fdt);
diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index 34893c3a04..ecc8aaa4fb 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -273,10 +273,8 @@ __noreturn void imx8mm_load_and_start_image_via_tfa(void)
 
 __noreturn void __imx8mm_load_and_start_image_via_tfa(void *fdt, void *bl33)
 {
-	const void *bl31;
-	size_t bl31_size;
-	void *bl32 = NULL;
-	size_t bl32_size = 0;
+	struct fwobj bl31;
+	struct fwobj bl32 = {};
 
 	imx_set_cpu_type(IMX_CPU_IMX8MM);
 	imx8mm_init_scratch_space();
@@ -285,14 +283,14 @@ __noreturn void __imx8mm_load_and_start_image_via_tfa(void *fdt, void *bl33)
 	imx8mm_load_bl33(bl33);
 
 	if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MM_OPTEE)) {
-		get_builtin_firmware_ext(imx8mm_bl32_bin, bl33, &bl32, &bl32_size);
-		get_builtin_firmware(imx8mm_bl31_bin_optee, &bl31, &bl31_size);
+		get_builtin_firmware_ext(imx8mm_bl32_bin, bl33, &bl32);
+		get_builtin_firmware(imx8mm_bl31_bin_optee, &bl31);
 	} else {
-		get_builtin_firmware(imx8mm_bl31_bin, &bl31, &bl31_size);
+		get_builtin_firmware(imx8mm_bl31_bin, &bl31);
 	}
 
-	imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MM_ATF_BL31_BASE_ADDR,
-			     bl32, bl32_size, bl33, fdt);
+	imx8m_tfa_start_bl31(bl31.data, bl31.size, (void *)MX8MM_ATF_BL31_BASE_ADDR,
+			     bl32.data, bl32.size, bl33, fdt);
 }
 
 void imx8mp_load_bl33(void *bl33)
@@ -338,10 +336,8 @@ __noreturn void imx8mp_load_and_start_image_via_tfa(void)
 
 __noreturn void __imx8mp_load_and_start_image_via_tfa(void *fdt, void *bl33)
 {
-	const void *bl31;
-	size_t bl31_size;
-	void *bl32 = NULL;
-	size_t bl32_size = 0;
+	struct fwobj bl31;
+	struct fwobj bl32 = {};
 
 	imx_set_cpu_type(IMX_CPU_IMX8MP);
 	imx8mp_init_scratch_space();
@@ -350,14 +346,14 @@ __noreturn void __imx8mp_load_and_start_image_via_tfa(void *fdt, void *bl33)
 	imx8mp_load_bl33(bl33);
 
 	if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MP_OPTEE)) {
-		get_builtin_firmware_ext(imx8mp_bl32_bin, bl33, &bl32, &bl32_size);
-		get_builtin_firmware(imx8mp_bl31_bin_optee, &bl31, &bl31_size);
+		get_builtin_firmware_ext(imx8mp_bl32_bin, bl33, &bl32);
+		get_builtin_firmware(imx8mp_bl31_bin_optee, &bl31);
 	} else {
-		get_builtin_firmware(imx8mp_bl31_bin, &bl31, &bl31_size);
+		get_builtin_firmware(imx8mp_bl31_bin, &bl31);
 	}
 
-	imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MP_ATF_BL31_BASE_ADDR,
-			     bl32, bl32_size, bl33, fdt);
+	imx8m_tfa_start_bl31(bl31.data, bl31.size, (void *)MX8MP_ATF_BL31_BASE_ADDR,
+			     bl32.data, bl32.size, bl33, fdt);
 }
 
 void imx8mn_load_bl33(void *bl33)
@@ -403,10 +399,8 @@ __noreturn void imx8mn_load_and_start_image_via_tfa(void)
 
 __noreturn void __imx8mn_load_and_start_image_via_tfa(void *fdt, void *bl33)
 {
-	const void *bl31;
-	size_t bl31_size;
-	void *bl32 = NULL;
-	size_t bl32_size = 0;
+	struct fwobj bl31;
+	struct fwobj bl32 = {};
 
 	imx_set_cpu_type(IMX_CPU_IMX8MN);
 	imx8mn_init_scratch_space();
@@ -415,14 +409,14 @@ __noreturn void __imx8mn_load_and_start_image_via_tfa(void *fdt, void *bl33)
 	imx8mn_load_bl33(bl33);
 
 	if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MN_OPTEE)) {
-		get_builtin_firmware_ext(imx8mn_bl32_bin, bl33, &bl32, &bl32_size);
-		get_builtin_firmware(imx8mn_bl31_bin_optee, &bl31, &bl31_size);
+		get_builtin_firmware_ext(imx8mn_bl32_bin, bl33, &bl32);
+		get_builtin_firmware(imx8mn_bl31_bin_optee, &bl31);
 	} else {
-		get_builtin_firmware(imx8mn_bl31_bin, &bl31, &bl31_size);
+		get_builtin_firmware(imx8mn_bl31_bin, &bl31);
 	}
 
-	imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MN_ATF_BL31_BASE_ADDR,
-			     bl32, bl32_size, bl33, fdt);
+	imx8m_tfa_start_bl31(bl31.data, bl31.size, (void *)MX8MN_ATF_BL31_BASE_ADDR,
+			     bl32.data, bl32.size, bl33, fdt);
 }
 
 void imx8mq_load_bl33(void *bl33)
@@ -462,10 +456,8 @@ __noreturn void imx8mq_load_and_start_image_via_tfa(void)
 
 __noreturn void __imx8mq_load_and_start_image_via_tfa(void *fdt, void *bl33)
 {
-	const void *bl31;
-	size_t bl31_size;
-	void *bl32 = NULL;
-	size_t bl32_size = 0;
+	struct fwobj bl31;
+	struct fwobj bl32 = {};
 
 	imx_set_cpu_type(IMX_CPU_IMX8MQ);
 	imx8mq_init_scratch_space();
@@ -474,14 +466,14 @@ __noreturn void __imx8mq_load_and_start_image_via_tfa(void *fdt, void *bl33)
 	imx8mq_load_bl33(bl33);
 
 	if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MQ_OPTEE)) {
-		get_builtin_firmware_ext(imx8mq_bl32_bin, bl33, &bl32, &bl32_size);
-		get_builtin_firmware(imx8mq_bl31_bin_optee, &bl31, &bl31_size);
+		get_builtin_firmware_ext(imx8mq_bl32_bin, bl33, &bl32);
+		get_builtin_firmware(imx8mq_bl31_bin_optee, &bl31);
 	} else {
-		get_builtin_firmware(imx8mq_bl31_bin, &bl31, &bl31_size);
+		get_builtin_firmware(imx8mq_bl31_bin, &bl31);
 	}
 
-	imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR,
-			     bl32, bl32_size, bl33, fdt);
+	imx8m_tfa_start_bl31(bl31.data, bl31.size, (void *)MX8MQ_ATF_BL31_BASE_ADDR,
+			     bl32.data, bl32.size, bl33, fdt);
 }
 
 void __noreturn imx93_load_and_start_image_via_tfa(void)
@@ -493,8 +485,7 @@ void __noreturn __imx93_load_and_start_image_via_tfa(void *bl33)
 {
 	unsigned long atf_dest = MX93_ATF_BL31_BASE_ADDR;
 	void __noreturn (*bl31)(void) = (void *)atf_dest;
-	const void *tfa;
-	size_t tfa_size;
+	struct fwobj tfa;
 	unsigned long endmem = MX9_DDR_CSD1_BASE_ADDR + imx9_ddrc_sdram_size();
 
 	imx_set_cpu_type(IMX_CPU_IMX93);
@@ -503,22 +494,19 @@ void __noreturn __imx93_load_and_start_image_via_tfa(void *bl33)
 
 	if (IS_ENABLED(CONFIG_FIRMWARE_IMX93_OPTEE)) {
 		void *bl32 = (void *)arm_mem_optee(endmem);
-		size_t bl32_size;
-		void *bl32_image;
+		struct fwobj bl32_fw;
 
 		imx93_ele_load_fw(bl33);
 
-		get_builtin_firmware_ext(imx93_bl32_bin,
-				bl33, &bl32_image,
-				&bl32_size);
+		get_builtin_firmware_ext(imx93_bl32_bin, bl33, &bl32_fw);
 
-		imx_adjust_optee_memory(&bl32, &bl32_image, &bl32_size);
+		imx_adjust_optee_memory(&bl32, &bl32_fw.data, &bl32_fw.size);
 
-		memcpy(bl32, bl32_image, bl32_size);
+		memcpy(bl32, bl32_fw.data, bl32_fw.size);
 
-		get_builtin_firmware(imx93_bl31_bin_optee, &tfa, &tfa_size);
+		get_builtin_firmware(imx93_bl31_bin_optee, &tfa);
 	} else {
-		get_builtin_firmware(imx93_bl31_bin, &tfa, &tfa_size);
+		get_builtin_firmware(imx93_bl31_bin, &tfa);
 	}
 
 	handoff_data_move(bl33 - ALIGN(handoff_data_size(), 0x1000));
@@ -539,7 +527,7 @@ void __noreturn __imx93_load_and_start_image_via_tfa(void *bl33)
 	 */
 	memcpy(bl33, __image_start, ALIGN(barebox_pbl_size, 1024));
 
-	memcpy(bl31, tfa, tfa_size);
+	memcpy(bl31, tfa.data, tfa.size);
 
 	asm volatile("msr sp_el2, %0" : :
 		     "r" (bl33 - 16) :
diff --git a/arch/arm/mach-imx/ele.c b/arch/arm/mach-imx/ele.c
index c0d1ab605d..02e4deafb0 100644
--- a/arch/arm/mach-imx/ele.c
+++ b/arch/arm/mach-imx/ele.c
@@ -191,8 +191,8 @@ int imx93_ele_load_fw(void *bl33)
 		.size = 4,
 		.command = ELE_FW_AUTH_REQ,
 	};
-	void *firmware;
-	int size, ret;
+	struct fwobj fw;
+	int ret;
 	int rev = 0;
 
 	ele_get_info(&info);
@@ -202,11 +202,11 @@ int imx93_ele_load_fw(void *bl33)
 	switch (rev) {
 #ifdef CONFIG_FIRMWARE_IMX93_OPTEE_A0
 	case 0xa0:
-		get_builtin_firmware_ext(mx93a0_ahab_container_img, bl33, &firmware, &size);
+		get_builtin_firmware_ext(mx93a0_ahab_container_img, bl33, &fw);
 		break;
 #endif
 	case 0xa1:
-		get_builtin_firmware_ext(mx93a1_ahab_container_img, bl33, &firmware, &size);
+		get_builtin_firmware_ext(mx93a1_ahab_container_img, bl33, &fw);
 		break;
 	default:
 		pr_err("Unknown unhandled SoC revision %2x\n", rev);
@@ -214,9 +214,9 @@ int imx93_ele_load_fw(void *bl33)
 	}
 
 	/* Address of the container header */
-	msg.data[0] = lower_32_bits((unsigned long)firmware);
+	msg.data[0] = lower_32_bits((unsigned long)fw.data);
 	/* Actual address of the container header */
-	msg.data[2] = lower_32_bits((unsigned long)firmware);
+	msg.data[2] = lower_32_bits((unsigned long)fw.data);
 
 	ret = ele_call(&msg);
 	if (ret)
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 6dc92e90fc..a34bdd3389 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -1024,10 +1024,9 @@ imx6_barebox_entry(unsigned long membase, void *boarddata)
 	    IS_ENABLED(CONFIG_PBL_OPTEE) && imx6_can_access_tzasc()) {
 		void *fdto;
 		unsigned int fdto_size;
-		int tee_size;
-		void *tee;
+		struct fwobj tee;
 
-		get_builtin_firmware(imx6_optee_bin, &tee, &tee_size);
+		get_builtin_firmware(imx6_optee_bin, &tee);
 
 		imx_init_scratch_space(membase + memsize, 1);
 		fdto = imx_scratch_get_fdt(&fdto_size);
@@ -1037,7 +1036,7 @@ imx6_barebox_entry(unsigned long membase, void *boarddata)
 		} else if (fdto == NULL)
 			pr_warn("No space configured for OP-TEE devicetree\n");
 
-		start_optee_early(fdto, tee);
+		start_optee_early(fdto, tee.data);
 		if (!IS_ERR(fdto))
 			optee_handoff_overlay(fdto, fdto_size);
 	}
diff --git a/arch/arm/mach-layerscape/tfa.c b/arch/arm/mach-layerscape/tfa.c
index d9c4abdd90..e69bbd8c4e 100644
--- a/arch/arm/mach-layerscape/tfa.c
+++ b/arch/arm/mach-layerscape/tfa.c
@@ -11,12 +11,11 @@
 void ls1046_start_tfa(void *barebox, struct dram_regions_info *dram_info)
 {
 	void (*bl31)(void) = (void *)0xfbe00000;
-	size_t bl31_size;
-	void *bl31_image;
+	struct fwobj bl31_fw;
 	struct bl2_to_bl31_params_mem_v2 *params;
 
-	get_builtin_firmware_ext(ls1046a_bl31_bin, barebox, &bl31_image, &bl31_size);
-	memcpy(bl31, bl31_image, bl31_size);
+	get_builtin_firmware_ext(ls1046a_bl31_bin, barebox, &bl31_fw);
+	memcpy(bl31, bl31_fw.data, bl31_fw.size);
 
 	sync_caches_for_execution();
 
diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
index 8d7e505a99..0d26dfb740 100644
--- a/arch/arm/mach-rockchip/atf.c
+++ b/arch/arm/mach-rockchip/atf.c
@@ -110,18 +110,16 @@ static uintptr_t rk_load_optee(uintptr_t bl32, const void *bl32_image,
 
 static uintptr_t barebox_load_address; /* where barebox is loaded and started */
 static uintptr_t optee_load_address; /* standard SoC specific OP-TEE load address */
-static const void *bl31; /* pointer to TF-A in barebox image */
-static size_t bl31_size; /* size of TF-A in barebox image */
-static const void *bl32; /* pointer to OP-TEE in barebox image */
-static size_t bl32_size; /* size of OP-TEE in barebox image */
+static struct fwobj bl31; /* TF-A in barebox image */
+static struct fwobj bl32; /* OP-TEE in barebox image */
 
 #define ROCKCHIP_GET_ADDRESSES(SOC, atf_bin, tee_bin)				\
 	do {									\
 		barebox_load_address = SOC##_BAREBOX_LOAD_ADDRESS;		\
 		optee_load_address = SOC##_OPTEE_LOAD_ADDRESS;			\
-		get_builtin_firmware(atf_bin, &bl31, &bl31_size);		\
+		get_builtin_firmware(atf_bin, &bl31);				\
 		if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))			\
-			get_builtin_firmware(tee_bin, &bl32, &bl32_size);	\
+			get_builtin_firmware(tee_bin, &bl32);			\
 	} while (0)
 
 
@@ -129,10 +127,10 @@ static void rockchip_atf_load_bl31(void *fdt)
 {
 	unsigned long bl31_ep;
 
-	bl31_ep = load_elf64_image_phdr(bl31);
+	bl31_ep = load_elf64_image_phdr(bl31.data);
 
 	if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))
-		optee_load_address = rk_load_optee(optee_load_address, bl32, bl32_size);
+		optee_load_address = rk_load_optee(optee_load_address, bl32.data, bl32.size);
 
 	/* Setup an initial stack for EL2 */
 	asm volatile("msr sp_el2, %0" : :
diff --git a/arch/arm/mach-socfpga/atf.c b/arch/arm/mach-socfpga/atf.c
index 23e2fffdce..d0f57d9541 100644
--- a/arch/arm/mach-socfpga/atf.c
+++ b/arch/arm/mach-socfpga/atf.c
@@ -13,16 +13,15 @@ void __noreturn agilex5_load_and_start_image_via_tfa(unsigned long memsize)
 {
 	unsigned long atf_dest = AGILEX5_ATF_BL31_BASE_ADDR;
 	void __noreturn (*bl31)(void) = (void *)atf_dest;
-	const void *tfa;
-	size_t tfa_size;
+	struct fwobj tfa;
 
 	pr_debug("Load TFA\n");
 
 	memcpy((void *)AGILEX5_ATF_BL33_BASE_ADDR, __image_start, barebox_image_size);
 
-	get_builtin_firmware(agilex5_bl31_bin, &tfa, &tfa_size);
+	get_builtin_firmware(agilex5_bl31_bin, &tfa);
 
-	memcpy(bl31, tfa, tfa_size);
+	memcpy(bl31, tfa.data, tfa.size);
 
 	asm volatile("msr sp_el2, %0" : :
 		     "r" (AGILEX5_ATF_BL33_BASE_ADDR - 16) :
diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index 3185aaf61e..4f78d49228 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -10,103 +10,72 @@
 #include <soc/imx8m/ddr.h>
 #include <firmware.h>
 
-static const u16 *lpddr4_imem_1d;
-static size_t lpddr4_imem_1d_size;
-static const u16 *lpddr4_dmem_1d;
-static size_t lpddr4_dmem_1d_size;
-static const u16 *lpddr4_imem_2d;
-static size_t lpddr4_imem_2d_size;
-static const u16 *lpddr4_dmem_2d;
-static size_t lpddr4_dmem_2d_size;
+static struct fwobj lpddr4_imem_1d;
+static struct fwobj lpddr4_dmem_1d;
+static struct fwobj lpddr4_imem_2d;
+static struct fwobj lpddr4_dmem_2d;
 
 void ddr_get_firmware_lpddr4(void)
 {
-	get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &lpddr4_imem_1d,
-			     &lpddr4_imem_1d_size);
-	get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &lpddr4_dmem_1d,
-			     &lpddr4_dmem_1d_size);
-	get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &lpddr4_imem_2d,
-			     &lpddr4_imem_2d_size);
-	get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &lpddr4_dmem_2d,
-			     &lpddr4_dmem_2d_size);
+	get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &lpddr4_imem_1d);
+	get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &lpddr4_dmem_1d);
+	get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &lpddr4_imem_2d);
+	get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &lpddr4_dmem_2d);
 }
 
-static const u16 *ddr4_imem_1d;
-static size_t ddr4_imem_1d_size;
-static const u16 *ddr4_dmem_1d;
-static size_t ddr4_dmem_1d_size;
-static const u16 *ddr4_imem_2d;
-static size_t ddr4_imem_2d_size;
-static const u16 *ddr4_dmem_2d;
-static size_t ddr4_dmem_2d_size;
+static struct fwobj ddr4_imem_1d;
+static struct fwobj ddr4_dmem_1d;
+static struct fwobj ddr4_imem_2d;
+static struct fwobj ddr4_dmem_2d;
 
 void ddr_get_firmware_ddr4(void)
 {
-	get_builtin_firmware(ddr4_imem_1d_bin, &ddr4_imem_1d,
-			     &ddr4_imem_1d_size);
-	get_builtin_firmware(ddr4_dmem_1d_bin, &ddr4_dmem_1d,
-			     &ddr4_dmem_1d_size);
-	get_builtin_firmware(ddr4_imem_2d_bin, &ddr4_imem_2d,
-			     &ddr4_imem_2d_size);
-	get_builtin_firmware(ddr4_dmem_2d_bin, &ddr4_dmem_2d,
-			     &ddr4_dmem_2d_size);
+	get_builtin_firmware(ddr4_imem_1d_bin, &ddr4_imem_1d);
+	get_builtin_firmware(ddr4_dmem_1d_bin, &ddr4_dmem_1d);
+	get_builtin_firmware(ddr4_imem_2d_bin, &ddr4_imem_2d);
+	get_builtin_firmware(ddr4_dmem_2d_bin, &ddr4_dmem_2d);
 }
 
-static const u16 *ddr3_imem_1d;
-static size_t ddr3_imem_1d_size;
-static const u16 *ddr3_dmem_1d;
-static size_t ddr3_dmem_1d_size;
+static struct fwobj ddr3_imem_1d;
+static struct fwobj ddr3_dmem_1d;
 
 void ddr_get_firmware_ddr3(void)
 {
-	get_builtin_firmware(ddr3_imem_1d_bin, &ddr3_imem_1d,
-			     &ddr3_imem_1d_size);
-	get_builtin_firmware(ddr3_dmem_1d_bin, &ddr3_dmem_1d,
-			     &ddr3_dmem_1d_size);
+	get_builtin_firmware(ddr3_imem_1d_bin, &ddr3_imem_1d);
+	get_builtin_firmware(ddr3_dmem_1d_bin, &ddr3_dmem_1d);
 }
 
 void ddr_load_train_code(struct dram_controller *dram, enum dram_type dram_type,
 			 enum fw_type fw_type)
 {
-	const u16 *imem, *dmem;
-	size_t isize, dsize;
+	struct fwobj *imem, *dmem;
 
 	if (dram_is_lpddr4(dram_type)) {
 		if (fw_type == FW_1D_IMAGE) {
-			imem = lpddr4_imem_1d;
-			isize = lpddr4_imem_1d_size;
-			dmem = lpddr4_dmem_1d;
-			dsize = lpddr4_dmem_1d_size;
+			imem = &lpddr4_imem_1d;
+			dmem = &lpddr4_dmem_1d;
 		} else {
-			imem = lpddr4_imem_2d;
-			isize = lpddr4_imem_2d_size;
-			dmem = lpddr4_dmem_2d;
-			dsize = lpddr4_dmem_2d_size;
+			imem = &lpddr4_imem_2d;
+			dmem = &lpddr4_dmem_2d;
 		}
 	} else if (dram_is_ddr4(dram_type)) {
 		if (fw_type == FW_1D_IMAGE) {
-			imem = ddr4_imem_1d;
-			isize = ddr4_imem_1d_size;
-			dmem = ddr4_dmem_1d;
-			dsize = ddr4_dmem_1d_size;
+			imem = &ddr4_imem_1d;
+			dmem = &ddr4_dmem_1d;
 		} else {
-			imem = ddr4_imem_2d;
-			isize = ddr4_imem_2d_size;
-			dmem = ddr4_dmem_2d;
-			dsize = ddr4_dmem_2d_size;
+			imem = &ddr4_imem_2d;
+			dmem = &ddr4_dmem_2d;
 		}
 	} else if (dram_is_ddr3(dram_type)) {
-		imem = ddr3_imem_1d;
-		isize = ddr3_imem_1d_size;
-		dmem = ddr3_dmem_1d;
-		dsize = ddr3_dmem_1d_size;
+		imem = &ddr3_imem_1d;
+		dmem = &ddr3_dmem_1d;
 	} else {
 		panic("No matching DDR PHY firmware found");
 	}
 
-	ddrc_phy_load_firmware(dram, DDRC_PHY_IMEM, imem, isize);
+	ddrc_phy_load_firmware(dram, DDRC_PHY_IMEM, imem->data, imem->size);
 
-	ddrc_phy_load_firmware(dram, DDRC_PHY_DMEM, dmem, dsize);
+	ddrc_phy_load_firmware(dram, DDRC_PHY_DMEM, dmem->data, dmem->size);
 }
 
 int ddr_cfg_phy(struct dram_controller *dram, struct dram_timing_info *dram_timing)
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 1040a0dfc9..fe06d418b0 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -391,8 +391,7 @@ static int ls1028a_esdhc_start_image(void __iomem *base, struct dram_regions_inf
 	};
 	void *sdram = (void *)0x80000000;
 	void (*bl31)(void) = (void *)LS1028A_TFA_RESERVED_START;
-	size_t bl31_size;
-	void *bl31_image;
+	struct fwobj bl31_fw;
 	struct bl2_to_bl31_params_mem_v2 *params;
 	unsigned long size = ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512);
 	void (*barebox)(void) = (sdram + LS1046A_SD_IMAGE_OFFSET);
@@ -402,8 +401,8 @@ static int ls1028a_esdhc_start_image(void __iomem *base, struct dram_regions_inf
 	if (ret)
 		return ret;
 
-	get_builtin_firmware_ext(ls1028a_bl31_bin, barebox, &bl31_image, &bl31_size);
-	memcpy(bl31, bl31_image, bl31_size);
+	get_builtin_firmware_ext(ls1028a_bl31_bin, barebox, &bl31_fw);
+	memcpy(bl31, bl31_fw.data, bl31_fw.size);
 
 	/* Setup an initial stack for EL2 */
 	asm volatile("msr sp_el2, %0" : : "r" ((unsigned long)barebox - 16) : "cc");
diff --git a/drivers/net/fsl-fman.c b/drivers/net/fsl-fman.c
index bde054d751..f70af5ff14 100644
--- a/drivers/net/fsl-fman.c
+++ b/drivers/net/fsl-fman.c
@@ -209,16 +209,19 @@ static int fm_upload_ucode(struct fm_imem *imem,
 
 static int fman_upload_firmware(struct device *dev, struct fm_imem *fm_imem)
 {
-	int i, size, ret;
+	int i, ret;
+	struct fwobj fw;
 	const struct qe_firmware *firmware;
 
-	get_builtin_firmware(fsl_fman_ucode_ls1046_r1_0_106_4_18_bin, &firmware, &size);
-	if (!size) {
+	get_builtin_firmware(fsl_fman_ucode_ls1046_r1_0_106_4_18_bin, &fw);
+	if (!fw.size) {
 		dev_err(dev, "FMan Firmware was not included in build\n");
 		return -ENOSYS;
 	}
 
-	ret = qe_validate_firmware(firmware, size);
+	firmware = fw.data;
+
+	ret = qe_validate_firmware(firmware, fw.size);
 	if (ret)
 		return ret;
 
diff --git a/include/firmware.h b/include/firmware.h
index ab518cb432..6609bdbc9e 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -90,30 +90,35 @@ static inline void firmware_ext_verify(const void *data_start, size_t data_size,
 	}
 }
 
-#define __get_builtin_firmware(name, offset, start, size)		\
+struct fwobj {
+	size_t size;
+	void *data;
+};
+
+#define __get_builtin_firmware(name, offset, fwobj)			\
 	do {								\
 		extern char _fw_##name##_start[];			\
 		extern char _fw_##name##_end[];				\
 		extern char _fw_##name##_sha_start[];			\
 		extern char _fw_##name##_sha_end[];			\
-		*start = (typeof(*start)) _fw_##name##_start;		\
-		*size = _fw_##name##_end - _fw_##name##_start;		\
+		(fwobj)->data = _fw_##name##_start;			\
+		(fwobj)->size = _fw_##name##_end - _fw_##name##_start;	\
 		if (!(offset))						\
 			break;						\
-		*start += (offset);					\
+		(fwobj)->data += (offset);				\
 		firmware_ext_verify(					\
-			*start, *size,					\
+			(fwobj)->data, (fwobj)->size,			\
 			_fw_##name##_sha_start,				\
 			_fw_##name##_sha_end - _fw_##name##_sha_start	\
 		);							\
 	} while (0)
 
 
-#define get_builtin_firmware(name, start, size) \
-	__get_builtin_firmware(name, 0, start, size)
+#define get_builtin_firmware(name, fwobj) \
+	__get_builtin_firmware(name, 0, fwobj)
 
-#define get_builtin_firmware_ext(name, base, start, size)		\
-	__get_builtin_firmware(name, (long)base - (long)_text, start, size)
+#define get_builtin_firmware_ext(name, base, fwobj)			\
+	__get_builtin_firmware(name, (long)base - (long)_text, fwobj)
 
 static inline int firmware_next_image_check_sha256(const void *hash, bool verbose)
 {

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 6/9] firmware: Add compressed firmware symbols for PBL
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (4 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 5/9] firmware: Use struct fwobj for get_builtin_firmware APIs Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-19 14:19   ` [PATCH] fixup! " Sascha Hauer
  2026-03-20  8:54   ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 7/9] firmware: Add fwobj_uncompress() for decompressing firmware in PBL Sascha Hauer
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX; +Cc: Sascha Hauer, Claude Opus 4.6

From: Sascha Hauer <sascha@saschahauer.de>

Similar to how device trees get both compressed and uncompressed
symbols (__dtb_<name>_start vs __dtb_z_<name>_start), generate
compressed variants of firmware blobs for PBL use.

When a firmware binary exists, it is compressed using the configured
IMAGE_COMPRESSION algorithm and linked into a separate .fwz.rodata
section with _fw_z_<name>_start/_fw_z_<name>_end symbols. The
uncompressed size is available as _fw_z_<name>_uncompressed_size.

The compressed symbols are only available in PBL context
(guarded by __PBL__). A new get_builtin_firmware_compressed()
macro is provided for C consumers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 firmware/Makefile  | 18 +++++++++++++++---
 include/firmware.h | 12 ++++++++++++
 scripts/gen-fw-s   | 26 +++++++++++++++++++++++++-
 3 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index b247db8da2..00412042b7 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -61,8 +61,8 @@ pbl-fwext-y := $(addsuffix .extgen.o, $(fw-external-y))
 
 FWNAME    = $(patsubst $(obj)/%.extgen.S,%,$(patsubst $(obj)/%.gen.S,%,$@))
 
-filechk_fwbin = $(srctree)/scripts/gen-fw-s $(FWNAME) $(FIRMWARE_DIR) .rodata
-filechk_fwbin_ext = $(srctree)/scripts/gen-fw-s $(FWNAME) $(FIRMWARE_DIR) .pblext a
+filechk_fwbin = $(srctree)/scripts/gen-fw-s $(FWNAME) $(FIRMWARE_DIR) .rodata '' $(fwobjdir)
+filechk_fwbin_ext = $(srctree)/scripts/gen-fw-s $(FWNAME) $(FIRMWARE_DIR) .pblext a $(fwobjdir)
 
 $(obj)/%.gen.S: FORCE
 	$(call filechk,fwbin)
@@ -70,6 +70,10 @@ $(obj)/%.gen.S: FORCE
 $(obj)/%.extgen.S: FORCE
 	$(call filechk,fwbin_ext)
 
+# Compress firmware files
+$(fwobjdir)/%.z: $(FIRMWARE_DIR)/% FORCE
+	$(call if_changed,$(suffix_y))
+
 # This dependency is used if missing firmware should fail the build immediately
 fwdep-required-y = $(FIRMWARE_DIR)/%
 # This dependency expands to nothing if the file doesn't exist. This allows
@@ -82,9 +86,15 @@ fwdep-required-y = $(FIRMWARE_DIR)/%
 # them to install all firmware for all platforms if only few are of interest.
 fwdep-required-n = $$(wildcard $(FIRMWARE_DIR)/%)
 
+# Compressed firmware dependency: only if the firmware binary exists.
+# Use $$* (stem) instead of % because % is not substituted inside $$(if ...).
+fwzdep-n = $$(if $$(wildcard $(FIRMWARE_DIR)/$$*),$(fwobjdir)/$$*.z)
+
 .SECONDEXPANSION:
+# .gen.S files depend on compressed firmware for correct size computation
+$(patsubst %.gen.o,$(obj)/%.gen.S, $(obj-pbl-y) $(pbl-y)): $(obj)/%.gen.S: $(fwzdep-n)
 # The .o files depend on the binaries directly if available; the .S files don't.
-$(patsubst %.gen.o,$(obj)/%.gen.pbl.o, $(obj-pbl-y) $(pbl-y)): $(obj)/%.gen.pbl.o: $(fwdep-required-n)
+$(patsubst %.gen.o,$(obj)/%.gen.pbl.o, $(obj-pbl-y) $(pbl-y)): $(obj)/%.gen.pbl.o: $(fwdep-required-n) $(fwzdep-n)
 $(patsubst %.extgen.o,$(obj)/%.extgen.pbl.o, $(pbl-fwext-y)): $(obj)/%.extgen.pbl.o: $(fwdep-required-n)
 # For barebox proper, firmware existance is either checked here
 # or in driver code by checking whether size != 0
@@ -96,6 +106,8 @@ targets := $(patsubst $(obj)/%,%, \
 	                        $(shell find $(obj) -name \*.gen.S 2>/dev/null))
 targets += $(patsubst $(obj)/%,%, \
 	                        $(shell find $(obj) -name \*.extgen.S 2>/dev/null))
+targets += $(patsubst $(obj)/%,%, \
+	                        $(shell find $(obj) -name \*.z 2>/dev/null))
 
 # just to build a built-in.o. Otherwise compilation fails when no
 # firmware is built.
diff --git a/include/firmware.h b/include/firmware.h
index 6609bdbc9e..2f75ded82b 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -92,6 +92,7 @@ static inline void firmware_ext_verify(const void *data_start, size_t data_size,
 
 struct fwobj {
 	size_t size;
+	size_t uncompressed_size;
 	void *data;
 };
 
@@ -120,6 +121,17 @@ struct fwobj {
 #define get_builtin_firmware_ext(name, base, fwobj)			\
 	__get_builtin_firmware(name, (long)base - (long)_text, fwobj)
 
+#define get_builtin_firmware_compressed(name, fwobj)			\
+	do {								\
+		extern char _fw_z_##name##_start[];			\
+		extern char _fw_z_##name##_end[];			\
+		extern unsigned long _fw_z_##name##_uncompressed_size;	\
+		(fwobj)->data = _fw_z_##name##_start;			\
+		(fwobj)->size = _fw_z_##name##_end - _fw_z_##name##_start;\
+		(fwobj)->uncompressed_size =				\
+			(size_t)_fw_z_##name##_uncompressed_size;	\
+	} while (0)
+
 static inline int firmware_next_image_check_sha256(const void *hash, bool verbose)
 {
 	extern char _fw_next_image_bin_sha_start[];
diff --git a/scripts/gen-fw-s b/scripts/gen-fw-s
index 653e6f013a..78c3193479 100755
--- a/scripts/gen-fw-s
+++ b/scripts/gen-fw-s
@@ -3,16 +3,22 @@
 #
 # Generate assembly source to embed firmware binary
 #
-# Usage: gen-fw-s <fwname> <fwdir> <secprefix> [secflags]
+# Usage: gen-fw-s <fwname> <fwdir> <secprefix> [secflags] [fwobjdir]
 
 fwname=$1
 fwdir=$2
 secprefix=$3
 secflags=$4
+fwobjdir=$5
 
 fwstr=$(echo "$fwname" | tr '/.-' '___')
 fwpath="$fwdir/$fwname"
 
+fw_uncompressed=0
+if [ -f "$fwpath" ]; then
+	fw_uncompressed=$(stat -c %s "$fwpath")
+fi
+
 sha=$(sha256sum "$fwpath" 2>/dev/null | sed 's/ .*$//;s/../0x&, /g;s/, $//')
 
 echo "/* Generated by scripts/gen-fw-s */"
@@ -35,6 +41,24 @@ fi
 echo ".global _fw_${fwstr}_end"
 echo "_fw_${fwstr}_end:"
 
+# include compressed firmware if exists, otherwise include a reference to
+# the firmware filename in the .missing_fw section
+echo "#if defined(__PBL__)"
+echo "    .section .fwz.rodata.${fwstr},\"a\""
+echo "    .p2align ASM_LGPTR"
+echo ".global _fw_z_${fwstr}_uncompressed_size"
+echo ".set _fw_z_${fwstr}_uncompressed_size, ${fw_uncompressed}"
+echo ".global _fw_z_${fwstr}_start"
+echo "_fw_z_${fwstr}_start:"
+if [ -f "$fwpath" ]; then
+	echo ".incbin \"${fwobjdir}/${fwname}.z\""
+else
+	echo "ASM_PTR _fwname_${fwstr}"
+fi
+echo ".global _fw_z_${fwstr}_end"
+echo "_fw_z_${fwstr}_end:"
+echo "#endif"
+
 # include sha256, needed for external firmware
 echo "    .section .rodata.${fwstr}.sha"
 echo "    .p2align ASM_LGPTR"

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 7/9] firmware: Add fwobj_uncompress() for decompressing firmware in PBL
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (5 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 6/9] firmware: Add compressed firmware symbols for PBL Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 8/9] ARM: Rockchip: Use compressed OP-TEE binary Sascha Hauer
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX; +Cc: Sascha Hauer, Claude Opus 4.6

From: Sascha Hauer <sascha@saschahauer.de>

Add fwobj_uncompress() which decompresses a firmware object into a
destination buffer. This pairs with get_builtin_firmware_compressed()
to provide a simple API for loading compressed firmware in PBL context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/firmware.h | 2 ++
 pbl/decomp.c       | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/include/firmware.h b/include/firmware.h
index 2f75ded82b..07651f1a93 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -121,6 +121,8 @@ struct fwobj {
 #define get_builtin_firmware_ext(name, base, fwobj)			\
 	__get_builtin_firmware(name, (long)base - (long)_text, fwobj)
 
+int fwobj_uncompress(struct fwobj *fwobj, void *dest);
+
 #define get_builtin_firmware_compressed(name, fwobj)			\
 	do {								\
 		extern char _fw_z_##name##_start[];			\
diff --git a/pbl/decomp.c b/pbl/decomp.c
index 532e9d460f..1539a6b67e 100644
--- a/pbl/decomp.c
+++ b/pbl/decomp.c
@@ -9,6 +9,7 @@
 #include <crypto/sha.h>
 #include <crypto/pbl-sha.h>
 #include <digest.h>
+#include <firmware.h>
 #include <asm/sections.h>
 #include <pbl.h>
 #include <debug_ll.h>
@@ -116,3 +117,9 @@ int pbl_dtbz_uncompress(void *dest, void *compressed_start, unsigned long len)
 	return decompress(compressed_start, len, NULL, NULL, dest, NULL,
 			  errorfn);
 }
+
+int fwobj_uncompress(struct fwobj *fwobj, void *dest)
+{
+	return decompress(fwobj->data, fwobj->size, NULL, NULL, dest, NULL,
+			  errorfn);
+}

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 8/9] ARM: Rockchip: Use compressed OP-TEE binary
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (6 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 7/9] firmware: Add fwobj_uncompress() for decompressing firmware in PBL Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-18  8:10   ` Sascha Hauer
  2026-03-16 17:21 ` [PATCH 9/9] ARM: Rockchip: Use compressed TF-A binary Sascha Hauer
  2026-03-19  6:53 ` [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
  9 siblings, 1 reply; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX

Rockchip images are often size constraint due to the ROM limiting the
maximum image size to 2MiB, at least when redundant copies on SD/eMMC
are desired. For this reason use the compressed variant of the OP-TEE
image.

FIXME: Uncompress address currently hardcoded.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-rockchip/atf.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
index 0d26dfb740..2ba7f074ce 100644
--- a/arch/arm/mach-rockchip/atf.c
+++ b/arch/arm/mach-rockchip/atf.c
@@ -8,6 +8,7 @@
 #include <asm/atf_common.h>
 #include <asm/barebox-arm.h>
 #include <asm-generic/memory_layout.h>
+#include <asm-generic/sections.h>
 #include <mach/rockchip/dmc.h>
 #include <mach/rockchip/rockchip.h>
 #include <mach/rockchip/bootrom.h>
@@ -29,7 +30,12 @@ static void rk_scratch_save_optee_hdr(const struct optee_header *hdr)
 	rk_scratch->optee_hdr = *hdr;
 }
 
-static unsigned long load_elf64_image_phdr(const void *elf)
+static void *free_mem(void)
+{
+	return (void *)PTR_ALIGN(&__image_end, SZ_1M);
+}
+
+static unsigned long load_elf64_image_phdr(struct fwobj *bl31)
 {
 	const Elf64_Ehdr *ehdr; /* Elf header structure pointer */
 	const Elf64_Phdr *phdr; /* Program header structure pointer */
@@ -56,11 +62,17 @@ static unsigned long load_elf64_image_phdr(const void *elf)
 	return ehdr->e_entry;
 }
 
-static uintptr_t rk_load_optee(uintptr_t bl32, const void *bl32_image,
-			       size_t bl32_size)
+static uintptr_t rk_load_optee(uintptr_t bl32, struct fwobj *bl32_fw)
 {
-	const struct optee_header *hdr = bl32_image;
+	const struct optee_header *hdr;
 	struct optee_header dummy_hdr;
+	int ret;
+	void *bl32_image = free_mem();
+	size_t bl32_size = bl32_fw->uncompressed_size;
+
+	ret = fwobj_uncompress(bl32_fw, bl32_image);
+	if (ret)
+		panic("Failed to uncompress OP-TEE\n");
 
 	/* We already have ELF support for BL31, but adding it for BL32,
 	 * would require us to identify a range that fits all ELF
@@ -70,6 +82,8 @@ static uintptr_t rk_load_optee(uintptr_t bl32, const void *bl32_image,
 	 */
 	BUG_ON(memcmp(bl32_image, ELFMAG, 4) == 0);
 
+	hdr = bl32_image;
+
 	if (optee_verify_header(hdr) == 0) {
 		bl32_size -= sizeof(*hdr);
 		bl32_image += sizeof(*hdr);
@@ -119,7 +133,7 @@ static struct fwobj bl32; /* OP-TEE in barebox image */
 		optee_load_address = SOC##_OPTEE_LOAD_ADDRESS;			\
 		get_builtin_firmware(atf_bin, &bl31);				\
 		if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))			\
-			get_builtin_firmware(tee_bin, &bl32);			\
+			get_builtin_firmware_compressed(tee_bin, &bl32);	\
 	} while (0)
 
 
@@ -130,7 +144,7 @@ static void rockchip_atf_load_bl31(void *fdt)
 	bl31_ep = load_elf64_image_phdr(bl31.data);
 
 	if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))
-		optee_load_address = rk_load_optee(optee_load_address, bl32.data, bl32.size);
+		optee_load_address = rk_load_optee(optee_load_address, &bl32);
 
 	/* Setup an initial stack for EL2 */
 	asm volatile("msr sp_el2, %0" : :

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 9/9] ARM: Rockchip: Use compressed TF-A binary
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (7 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 8/9] ARM: Rockchip: Use compressed OP-TEE binary Sascha Hauer
@ 2026-03-16 17:21 ` Sascha Hauer
  2026-03-19  6:53 ` [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-16 17:21 UTC (permalink / raw)
  To: BAREBOX

Rockchip images are often size constraint due to the ROM limiting the
maximum image size to 2MiB, at least when redundant copies on SD/eMMC
are desired. For this reason use the compressed variant of the TF-A
image.

FIXME: Uncompress address currently hardcoded.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-rockchip/atf.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
index 2ba7f074ce..3e0a14292b 100644
--- a/arch/arm/mach-rockchip/atf.c
+++ b/arch/arm/mach-rockchip/atf.c
@@ -39,15 +39,20 @@ static unsigned long load_elf64_image_phdr(struct fwobj *bl31)
 {
 	const Elf64_Ehdr *ehdr; /* Elf header structure pointer */
 	const Elf64_Phdr *phdr; /* Program header structure pointer */
-	int i;
+	int i, ret;
+	void *bl31_image = free_mem();
 
-	ehdr = elf;
-	phdr = elf + ehdr->e_phoff;
+	ret = fwobj_uncompress(bl31, bl31_image);
+	if (ret)
+		panic("Failed to uncompress TF-A\n");
+
+	ehdr = bl31_image;
+	phdr = bl31_image + ehdr->e_phoff;
 
 	/* Load each program header */
 	for (i = 0; i < ehdr->e_phnum; ++i) {
 		void *dst = (void *)(ulong)phdr->p_paddr;
-		const void *src = elf + phdr->p_offset;
+		const void *src = bl31_image + phdr->p_offset;
 
 		pr_debug("Loading phdr %i to 0x%p (%lu bytes)\n",
 			 i, dst, (ulong)phdr->p_filesz);
@@ -131,7 +136,7 @@ static struct fwobj bl32; /* OP-TEE in barebox image */
 	do {									\
 		barebox_load_address = SOC##_BAREBOX_LOAD_ADDRESS;		\
 		optee_load_address = SOC##_OPTEE_LOAD_ADDRESS;			\
-		get_builtin_firmware(atf_bin, &bl31);				\
+		get_builtin_firmware_compressed(atf_bin, &bl31);		\
 		if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))			\
 			get_builtin_firmware_compressed(tee_bin, &bl32);	\
 	} while (0)
@@ -141,7 +146,7 @@ static void rockchip_atf_load_bl31(void *fdt)
 {
 	unsigned long bl31_ep;
 
-	bl31_ep = load_elf64_image_phdr(bl31.data);
+	bl31_ep = load_elf64_image_phdr(&bl31);
 
 	if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP_OPTEE))
 		optee_load_address = rk_load_optee(optee_load_address, &bl32);

-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 8/9] ARM: Rockchip: Use compressed OP-TEE binary
  2026-03-16 17:21 ` [PATCH 8/9] ARM: Rockchip: Use compressed OP-TEE binary Sascha Hauer
@ 2026-03-18  8:10   ` Sascha Hauer
  0 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-18  8:10 UTC (permalink / raw)
  To: BAREBOX

On Mon, Mar 16, 2026 at 06:21:21PM +0100, Sascha Hauer wrote:
> Rockchip images are often size constraint due to the ROM limiting the
> maximum image size to 2MiB, at least when redundant copies on SD/eMMC
> are desired. For this reason use the compressed variant of the OP-TEE
> image.
> 
> FIXME: Uncompress address currently hardcoded.

This comment is not true anymore. In the current patch I use the memory
directly behind the image aligned up to the next 1MiB boundary.

> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/mach-rockchip/atf.c | 26 ++++++++++++++++++++------
>  1 file changed, 20 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
> index 0d26dfb740..2ba7f074ce 100644
> --- a/arch/arm/mach-rockchip/atf.c
> +++ b/arch/arm/mach-rockchip/atf.c
> @@ -8,6 +8,7 @@
>  #include <asm/atf_common.h>
>  #include <asm/barebox-arm.h>
>  #include <asm-generic/memory_layout.h>
> +#include <asm-generic/sections.h>
>  #include <mach/rockchip/dmc.h>
>  #include <mach/rockchip/rockchip.h>
>  #include <mach/rockchip/bootrom.h>
> @@ -29,7 +30,12 @@ static void rk_scratch_save_optee_hdr(const struct optee_header *hdr)
>  	rk_scratch->optee_hdr = *hdr;
>  }
>  
> -static unsigned long load_elf64_image_phdr(const void *elf)
> +static void *free_mem(void)
> +{
> +	return (void *)PTR_ALIGN(&__image_end, SZ_1M);
> +}
> +
> +static unsigned long load_elf64_image_phdr(struct fwobj *bl31)

This last line should be changed in the next patch, not this one.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/9] Firmware: support compressing firmware files
  2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
                   ` (8 preceding siblings ...)
  2026-03-16 17:21 ` [PATCH 9/9] ARM: Rockchip: Use compressed TF-A binary Sascha Hauer
@ 2026-03-19  6:53 ` Sascha Hauer
  9 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-19  6:53 UTC (permalink / raw)
  To: BAREBOX, Sascha Hauer; +Cc: Sascha Hauer, Claude Opus 4.6


On Mon, 16 Mar 2026 18:21:13 +0100, Sascha Hauer wrote:
> TF-A and OP-TEE can reach significant sizes nowadays and are currently
> uncompressed in the PBL. This series supports including them in compressed
> form in the PBL. To accomplish this we introduce a new macro
> get_builtin_firmware_compressed() which returns the compressed firmware
> image. This can be decompressed afterwards with fwobj_uncompress().
> There are always both the compressed and uncompressed images generated,
> so the code can decide which one to use. This series switches over the
> Rockchip TF-A and OP-TEE binaries to use the compressed variants.
> 
> [...]

Applied, thanks!

[1/9] ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB
      https://git.pengutronix.de/cgit/barebox/commit/?id=a80e7e667bb3 (link may not be stable)
[2/9] ARM: radxa-rock5: Use compressed DTB
      https://git.pengutronix.de/cgit/barebox/commit/?id=39a49ed80f85 (link may not be stable)
[3/9] ARM: Rockchip: Simplify retrieval of SoC specific addresses
      https://git.pengutronix.de/cgit/barebox/commit/?id=01df55fc7f52 (link may not be stable)
[4/9] firmware: Move firmware assembly generation to scripts/gen-fw-s
      https://git.pengutronix.de/cgit/barebox/commit/?id=1e01e95f56e1 (link may not be stable)
[5/9] firmware: Use struct fwobj for get_builtin_firmware APIs
      https://git.pengutronix.de/cgit/barebox/commit/?id=8fd5c3f501fe (link may not be stable)
[6/9] firmware: Add compressed firmware symbols for PBL
      https://git.pengutronix.de/cgit/barebox/commit/?id=29697c7543b6 (link may not be stable)
[7/9] firmware: Add fwobj_uncompress() for decompressing firmware in PBL
      https://git.pengutronix.de/cgit/barebox/commit/?id=b7f40c12d509 (link may not be stable)
[8/9] ARM: Rockchip: Use compressed OP-TEE binary
      https://git.pengutronix.de/cgit/barebox/commit/?id=a5abd4b6f7f4 (link may not be stable)
[9/9] ARM: Rockchip: Use compressed TF-A binary
      https://git.pengutronix.de/cgit/barebox/commit/?id=8968135d1634 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] fixup! firmware: Add compressed firmware symbols for PBL
  2026-03-16 17:21 ` [PATCH 6/9] firmware: Add compressed firmware symbols for PBL Sascha Hauer
@ 2026-03-19 14:19   ` Sascha Hauer
  2026-03-20  8:54   ` Sascha Hauer
  1 sibling, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-19 14:19 UTC (permalink / raw)
  To: Barebox List

_fw_z_##name##_uncompressed_size is an absolute symbol, we must use its
address, not interpret as a memory location.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/firmware.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/firmware.h b/include/firmware.h
index 07651f1a93..6511d56b2e 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -127,7 +127,7 @@ int fwobj_uncompress(struct fwobj *fwobj, void *dest);
 	do {								\
 		extern char _fw_z_##name##_start[];			\
 		extern char _fw_z_##name##_end[];			\
-		extern unsigned long _fw_z_##name##_uncompressed_size;	\
+		extern char _fw_z_##name##_uncompressed_size[];		\
 		(fwobj)->data = _fw_z_##name##_start;			\
 		(fwobj)->size = _fw_z_##name##_end - _fw_z_##name##_start;\
 		(fwobj)->uncompressed_size =				\
-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] fixup! firmware: Add compressed firmware symbols for PBL
  2026-03-16 17:21 ` [PATCH 6/9] firmware: Add compressed firmware symbols for PBL Sascha Hauer
  2026-03-19 14:19   ` [PATCH] fixup! " Sascha Hauer
@ 2026-03-20  8:54   ` Sascha Hauer
  1 sibling, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2026-03-20  8:54 UTC (permalink / raw)
  To: Barebox List

Add missing dependency to build the compressed firmware files also for
fw-external-y firmware.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index 00412042b7..7e433a1824 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -93,9 +93,10 @@ fwzdep-n = $$(if $$(wildcard $(FIRMWARE_DIR)/$$*),$(fwobjdir)/$$*.z)
 .SECONDEXPANSION:
 # .gen.S files depend on compressed firmware for correct size computation
 $(patsubst %.gen.o,$(obj)/%.gen.S, $(obj-pbl-y) $(pbl-y)): $(obj)/%.gen.S: $(fwzdep-n)
+$(patsubst %.extgen.o,$(obj)/%.extgen.S, $(pbl-fwext-y)): $(obj)/%.extgen.S: $(fwzdep-n)
 # The .o files depend on the binaries directly if available; the .S files don't.
 $(patsubst %.gen.o,$(obj)/%.gen.pbl.o, $(obj-pbl-y) $(pbl-y)): $(obj)/%.gen.pbl.o: $(fwdep-required-n) $(fwzdep-n)
-$(patsubst %.extgen.o,$(obj)/%.extgen.pbl.o, $(pbl-fwext-y)): $(obj)/%.extgen.pbl.o: $(fwdep-required-n)
+$(patsubst %.extgen.o,$(obj)/%.extgen.pbl.o, $(pbl-fwext-y)): $(obj)/%.extgen.pbl.o: $(fwdep-required-n) $(fwzdep-n)
 # For barebox proper, firmware existance is either checked here
 # or in driver code by checking whether size != 0
 $(patsubst %.gen.o,$(obj)/%.gen.o, $(obj-pbl-y)): $(obj)/%.gen.o: $(fwdep-required-$(CONFIG_MISSING_FIRMWARE_ERROR))
-- 
2.47.3




^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-03-20  8:55 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-16 17:21 [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer
2026-03-16 17:21 ` [PATCH 1/9] ARM: socfpga: Drop unnecessary select USE_COMPRESSED_DTB Sascha Hauer
2026-03-16 17:21 ` [PATCH 2/9] ARM: radxa-rock5: Use compressed DTB Sascha Hauer
2026-03-16 17:21 ` [PATCH 3/9] ARM: Rockchip: Simplify retrieval of SoC specific addresses Sascha Hauer
2026-03-16 17:21 ` [PATCH 4/9] firmware: Move firmware assembly generation to scripts/gen-fw-s Sascha Hauer
2026-03-16 17:21 ` [PATCH 5/9] firmware: Use struct fwobj for get_builtin_firmware APIs Sascha Hauer
2026-03-16 17:21 ` [PATCH 6/9] firmware: Add compressed firmware symbols for PBL Sascha Hauer
2026-03-19 14:19   ` [PATCH] fixup! " Sascha Hauer
2026-03-20  8:54   ` Sascha Hauer
2026-03-16 17:21 ` [PATCH 7/9] firmware: Add fwobj_uncompress() for decompressing firmware in PBL Sascha Hauer
2026-03-16 17:21 ` [PATCH 8/9] ARM: Rockchip: Use compressed OP-TEE binary Sascha Hauer
2026-03-18  8:10   ` Sascha Hauer
2026-03-16 17:21 ` [PATCH 9/9] ARM: Rockchip: Use compressed TF-A binary Sascha Hauer
2026-03-19  6:53 ` [PATCH 0/9] Firmware: support compressing firmware files Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox