* [PATCH v3 01/14] ARM: i.MX8M: add support to pass DT via lowlevel __imx8m*_load_and_start_image_via_tfa()
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 02/14] ARM: i.MX8M: move BL32 setup into imx8m_tfa_start_bl31() Marco Felsch
` (12 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
The internal barebox DTB isn't passed to other BL3x stages albeit it can
be very useful, e.g. OP-TEE (as BL32) could parse the memory
configuration from the DTB.
To avoid unnecessary API breakage, the FDT support is only added to the
lowlevel __imx8m*_load_and_start_image_via_tfa() TF-A load
helpers. This is the first step to be able to pass the board DTB to
other BL3x firmware images.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/atf.c | 16 ++++++++--------
include/mach/imx/xload.h | 8 ++++----
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index 3e1eac66f41456c24e5e0fbfa78c30211db1bcba..a8fc017fb6c86b807aef465226808144514c28f7 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -160,10 +160,10 @@ static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32
__noreturn void imx8mm_load_and_start_image_via_tfa(void)
{
- __imx8mm_load_and_start_image_via_tfa((void *)MX8M_ATF_BL33_BASE_ADDR);
+ __imx8mm_load_and_start_image_via_tfa(NULL, (void *)MX8M_ATF_BL33_BASE_ADDR);
}
-__noreturn void __imx8mm_load_and_start_image_via_tfa(void *bl33)
+__noreturn void __imx8mm_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
@@ -235,10 +235,10 @@ void imx8mp_load_bl33(void *bl33)
__noreturn void imx8mp_load_and_start_image_via_tfa(void)
{
- __imx8mp_load_and_start_image_via_tfa((void *)MX8M_ATF_BL33_BASE_ADDR);
+ __imx8mp_load_and_start_image_via_tfa(NULL, (void *)MX8M_ATF_BL33_BASE_ADDR);
}
-__noreturn void __imx8mp_load_and_start_image_via_tfa(void *bl33)
+__noreturn void __imx8mp_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
@@ -310,10 +310,10 @@ void imx8mn_load_bl33(void *bl33)
__noreturn void imx8mn_load_and_start_image_via_tfa(void)
{
- __imx8mn_load_and_start_image_via_tfa((void *)MX8M_ATF_BL33_BASE_ADDR);
+ __imx8mn_load_and_start_image_via_tfa(NULL, (void *)MX8M_ATF_BL33_BASE_ADDR);
}
-__noreturn void __imx8mn_load_and_start_image_via_tfa(void *bl33)
+__noreturn void __imx8mn_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
@@ -379,10 +379,10 @@ void imx8mq_load_bl33(void *bl33)
__noreturn void imx8mq_load_and_start_image_via_tfa(void)
{
- __imx8mq_load_and_start_image_via_tfa((void *)MX8M_ATF_BL33_BASE_ADDR);
+ __imx8mq_load_and_start_image_via_tfa(NULL, (void *)MX8M_ATF_BL33_BASE_ADDR);
}
-__noreturn void __imx8mq_load_and_start_image_via_tfa(void *bl33)
+__noreturn void __imx8mq_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
diff --git a/include/mach/imx/xload.h b/include/mach/imx/xload.h
index 396c728547614091fc710de50dc1583c6b6e2a68..9a9827156257847411ac34f02c6fe6633f6fb11a 100644
--- a/include/mach/imx/xload.h
+++ b/include/mach/imx/xload.h
@@ -33,10 +33,10 @@ void __noreturn imx8mm_load_and_start_image_via_tfa(void);
void __noreturn imx8mn_load_and_start_image_via_tfa(void);
void __noreturn imx8mp_load_and_start_image_via_tfa(void);
void __noreturn imx8mq_load_and_start_image_via_tfa(void);
-void __noreturn __imx8mm_load_and_start_image_via_tfa(void *bl33);
-void __noreturn __imx8mn_load_and_start_image_via_tfa(void *bl33);
-void __noreturn __imx8mp_load_and_start_image_via_tfa(void *bl33);
-void __noreturn __imx8mq_load_and_start_image_via_tfa(void *bl33);
+void __noreturn __imx8mm_load_and_start_image_via_tfa(void *fdt, void *bl33);
+void __noreturn __imx8mn_load_and_start_image_via_tfa(void *fdt, void *bl33);
+void __noreturn __imx8mp_load_and_start_image_via_tfa(void *fdt, void *bl33);
+void __noreturn __imx8mq_load_and_start_image_via_tfa(void *fdt, void *bl33);
void __noreturn imx93_load_and_start_image_via_tfa(void);
void __noreturn __imx93_load_and_start_image_via_tfa(void *bl33);
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 02/14] ARM: i.MX8M: move BL32 setup into imx8m_tfa_start_bl31()
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
2026-02-11 22:41 ` [PATCH v3 01/14] ARM: i.MX8M: add support to pass DT via lowlevel __imx8m*_load_and_start_image_via_tfa() Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 03/14] ARM: i.MX8M: imx8m_tfa_start_bl31() add support for bl33 and fdt Marco Felsch
` (11 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
Each i.MX8M platform repeated the same pattern for loading the optional
BL32 image because of the firmware name handling and the BL32 location
(end of memory).
The firmware name handling can't be generalized without change the logic
to function-like macros but the rest can be handled within the common
imx8m_tfa_start_bl31() function.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/atf.c | 153 ++++++++++++++++++++++--------------------------
1 file changed, 70 insertions(+), 83 deletions(-)
diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index a8fc017fb6c86b807aef465226808144514c28f7..a7ec09ea7e9a90e3af7c01126bb6da9626d2d09d 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -19,30 +19,75 @@
#include <mach/imx/xload.h>
#include <mach/imx/snvs.h>
+static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32_size)
+{
+ struct optee_header *hdr = *bl32_image;
+ u64 membase;
+
+ if (optee_verify_header(hdr))
+ return;
+
+ imx_scratch_save_optee_hdr(hdr);
+
+ membase = (u64)hdr->init_load_addr_hi << 32;
+ membase |= hdr->init_load_addr_lo;
+
+ *bl32 = (void *)membase;
+ *bl32_size -= sizeof(*hdr);
+ *bl32_image += sizeof(*hdr);
+}
+
/**
* imx8m_tfa_start_bl31 - Load TF-A BL31 blob and transfer control to it
*
* @tfa: Pointer to the BL31 blob
* @tfa_size: Size of the BL31 blob
* @tfa_dest: Place where the BL31 is copied to and executed
+ * @tee: Pointer to the optional BL32 blob
+ * @tee_size: Size of the optional BL32 blob
*
* This function:
*
- * 1. Copies built-in BL31 blob to an address i.MX8M's BL31
+ * 1. Copies built-in BL32 blob (if any) to the well-known OP-TEE address
+ * (end of RAM) or the address specified via the OP-TEE v2 header if
+ * found.
+ *
+ * 2. Copies built-in BL31 blob to an address i.MX8M's BL31
* expects to be placed (TF-A v2.8+ is position-independent)
*
- * 2. Sets up temporary stack pointer for EL2, which is execution
+ * 3. Sets up temporary stack pointer for EL2, which is execution
* level that BL31 will drop us off at after it completes its
* initialization routine
*
- * 3. Transfers control to BL31
+ * 4. Transfers control to BL31
*/
-static __noreturn void imx8m_tfa_start_bl31(const void *tfa_bin, size_t tfa_size, void *tfa_dest)
+static __noreturn void
+imx8m_tfa_start_bl31(const void *tfa_bin, size_t tfa_size, void *tfa_dest,
+ void *tee_bin, size_t tee_size)
{
void __noreturn (*bl31)(void) = tfa_dest;
+ unsigned long endmem;
+ void *bl32 = NULL;
int ret;
+ endmem = MX8M_DDR_CSD1_BASE_ADDR;
+ if (cpu_is_mx8mn())
+ endmem += imx8m_barebox_earlymem_size(16);
+ else
+ endmem += imx8m_barebox_earlymem_size(32);
+
+ /* TEE (BL32) handling */
+ if (tee_bin && tee_size) {
+ imx8m_tzc380_init();
+
+ bl32 = (void *)arm_mem_optee(endmem);
+ imx_adjust_optee_memory(&bl32, &tee_bin, &tee_size);
+
+ memcpy(bl32, tee_bin, tee_size);
+ }
+
+ /* TF-A (BL31) handling */
BUG_ON(tfa_size > MX8M_ATF_BL31_SIZE_LIMIT);
if (IS_ENABLED(CONFIG_FSL_CAAM_RNG_PBL_INIT)) {
@@ -70,7 +115,7 @@ static __noreturn void imx8m_tfa_start_bl31(const void *tfa_bin, size_t tfa_size
*/
pr_debug("and jumping with SP: %p\n", tfa_dest - 16);
-
+ /* Stack setup and BL31 jump */
asm volatile("msr sp_el2, %0" : :
"r" (tfa_dest - 16) :
"cc");
@@ -140,24 +185,6 @@ void imx8mm_load_bl33(void *bl33)
memcpy(bl33, __image_start, barebox_pbl_size);
}
-static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32_size)
-{
- struct optee_header *hdr = *bl32_image;
- u64 membase;
-
- if (optee_verify_header(hdr))
- return;
-
- imx_scratch_save_optee_hdr(hdr);
-
- membase = (u64)hdr->init_load_addr_hi << 32;
- membase |= hdr->init_load_addr_lo;
-
- *bl32 = (void *)membase;
- *bl32_size -= sizeof(*hdr);
- *bl32_image += sizeof(*hdr);
-}
-
__noreturn void imx8mm_load_and_start_image_via_tfa(void)
{
__imx8mm_load_and_start_image_via_tfa(NULL, (void *)MX8M_ATF_BL33_BASE_ADDR);
@@ -167,7 +194,8 @@ __noreturn void __imx8mm_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
- unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + imx8m_barebox_earlymem_size(32);
+ void *bl32 = NULL;
+ size_t bl32_size = 0;
imx_set_cpu_type(IMX_CPU_IMX8MM);
imx8mm_init_scratch_space();
@@ -176,25 +204,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)) {
- void *bl32 = (void *)arm_mem_optee(endmem);
- size_t bl32_size;
- void *bl32_image;
-
- imx8m_tzc380_init();
- get_builtin_firmware_ext(imx8mm_bl32_bin,
- bl33, &bl32_image,
- &bl32_size);
-
- imx_adjust_optee_memory(&bl32, &bl32_image, &bl32_size);
-
- memcpy(bl32, bl32_image, bl32_size);
-
+ get_builtin_firmware_ext(imx8mm_bl32_bin, bl33, &bl32, &bl32_size);
get_builtin_firmware(imx8mm_bl31_bin_optee, &bl31, &bl31_size);
} else {
get_builtin_firmware(imx8mm_bl31_bin, &bl31, &bl31_size);
}
- imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MM_ATF_BL31_BASE_ADDR);
+ imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MM_ATF_BL31_BASE_ADDR,
+ bl32, bl32_size);
}
void imx8mp_load_bl33(void *bl33)
@@ -242,7 +259,8 @@ __noreturn void __imx8mp_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
- unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + imx8m_barebox_earlymem_size(32);
+ void *bl32 = NULL;
+ size_t bl32_size = 0;
imx_set_cpu_type(IMX_CPU_IMX8MP);
imx8mp_init_scratch_space();
@@ -251,25 +269,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)) {
- void *bl32 = (void *)arm_mem_optee(endmem);
- size_t bl32_size;
- void *bl32_image;
-
- imx8m_tzc380_init();
- get_builtin_firmware_ext(imx8mp_bl32_bin,
- bl33, &bl32_image,
- &bl32_size);
-
- imx_adjust_optee_memory(&bl32, &bl32_image, &bl32_size);
-
- memcpy(bl32, bl32_image, bl32_size);
-
+ get_builtin_firmware_ext(imx8mp_bl32_bin, bl33, &bl32, &bl32_size);
get_builtin_firmware(imx8mp_bl31_bin_optee, &bl31, &bl31_size);
} else {
get_builtin_firmware(imx8mp_bl31_bin, &bl31, &bl31_size);
}
- imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MP_ATF_BL31_BASE_ADDR);
+ imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MP_ATF_BL31_BASE_ADDR,
+ bl32, bl32_size);
}
void imx8mn_load_bl33(void *bl33)
@@ -317,7 +324,8 @@ __noreturn void __imx8mn_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
- unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + imx8m_barebox_earlymem_size(16);
+ void *bl32 = NULL;
+ size_t bl32_size = 0;
imx_set_cpu_type(IMX_CPU_IMX8MN);
imx8mn_init_scratch_space();
@@ -326,25 +334,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)) {
- void *bl32 = (void *)arm_mem_optee(endmem);
- size_t bl32_size;
- void *bl32_image;
-
- imx8m_tzc380_init();
- get_builtin_firmware_ext(imx8mn_bl32_bin,
- bl33, &bl32_image,
- &bl32_size);
-
- imx_adjust_optee_memory(&bl32, &bl32_image, &bl32_size);
-
- memcpy(bl32, bl32_image, bl32_size);
-
+ get_builtin_firmware_ext(imx8mn_bl32_bin, bl33, &bl32, &bl32_size);
get_builtin_firmware(imx8mn_bl31_bin_optee, &bl31, &bl31_size);
} else {
get_builtin_firmware(imx8mn_bl31_bin, &bl31, &bl31_size);
}
- imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MN_ATF_BL31_BASE_ADDR);
+ imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MN_ATF_BL31_BASE_ADDR,
+ bl32, bl32_size);
}
void imx8mq_load_bl33(void *bl33)
@@ -386,7 +383,8 @@ __noreturn void __imx8mq_load_and_start_image_via_tfa(void *fdt, void *bl33)
{
const void *bl31;
size_t bl31_size;
- unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + imx8m_barebox_earlymem_size(32);
+ void *bl32 = NULL;
+ size_t bl32_size = 0;
imx_set_cpu_type(IMX_CPU_IMX8MQ);
imx8mq_init_scratch_space();
@@ -395,25 +393,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)) {
- void *bl32 = (void *)arm_mem_optee(endmem);
- size_t bl32_size;
- void *bl32_image;
-
- imx8m_tzc380_init();
- get_builtin_firmware_ext(imx8mq_bl32_bin,
- bl33, &bl32_image,
- &bl32_size);
-
- imx_adjust_optee_memory(&bl32, &bl32_image, &bl32_size);
-
- memcpy(bl32, bl32_image, bl32_size);
-
+ get_builtin_firmware_ext(imx8mq_bl32_bin, bl33, &bl32, &bl32_size);
get_builtin_firmware(imx8mq_bl31_bin_optee, &bl31, &bl31_size);
} else {
get_builtin_firmware(imx8mq_bl31_bin, &bl31, &bl31_size);
}
- imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR);
+ imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR,
+ bl32, bl32_size);
}
void __noreturn imx93_load_and_start_image_via_tfa(void)
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 03/14] ARM: i.MX8M: imx8m_tfa_start_bl31() add support for bl33 and fdt
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
2026-02-11 22:41 ` [PATCH v3 01/14] ARM: i.MX8M: add support to pass DT via lowlevel __imx8m*_load_and_start_image_via_tfa() Marco Felsch
2026-02-11 22:41 ` [PATCH v3 02/14] ARM: i.MX8M: move BL32 setup into imx8m_tfa_start_bl31() Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 04/14] pbl: decomp: add pbl_dtbz_uncompress helper Marco Felsch
` (10 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
This adds the support to pass the bl33 entry and the fdt to
imx8m_tfa_start_bl31() which is required to pass it later on the the
bl31 via the bl_params.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/atf.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index a7ec09ea7e9a90e3af7c01126bb6da9626d2d09d..11d26607bc2ea449402d9cb8e20fbb44f425989c 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -45,6 +45,9 @@ static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32
* @tfa_dest: Place where the BL31 is copied to and executed
* @tee: Pointer to the optional BL32 blob
* @tee_size: Size of the optional BL32 blob
+ * @bl33: Pointer to the already loaded BL33 blob
+ * @fdt: Pointer to the barebox internal DT (either compressed or not
+ * compressed)
*
* This function:
*
@@ -64,7 +67,7 @@ static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32
static __noreturn void
imx8m_tfa_start_bl31(const void *tfa_bin, size_t tfa_size, void *tfa_dest,
- void *tee_bin, size_t tee_size)
+ void *tee_bin, size_t tee_size, void *bl33, void *fdt)
{
void __noreturn (*bl31)(void) = tfa_dest;
unsigned long endmem;
@@ -211,7 +214,7 @@ __noreturn void __imx8mm_load_and_start_image_via_tfa(void *fdt, void *bl33)
}
imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MM_ATF_BL31_BASE_ADDR,
- bl32, bl32_size);
+ bl32, bl32_size, bl33, fdt);
}
void imx8mp_load_bl33(void *bl33)
@@ -276,7 +279,7 @@ __noreturn void __imx8mp_load_and_start_image_via_tfa(void *fdt, void *bl33)
}
imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MP_ATF_BL31_BASE_ADDR,
- bl32, bl32_size);
+ bl32, bl32_size, bl33, fdt);
}
void imx8mn_load_bl33(void *bl33)
@@ -341,7 +344,7 @@ __noreturn void __imx8mn_load_and_start_image_via_tfa(void *fdt, void *bl33)
}
imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MN_ATF_BL31_BASE_ADDR,
- bl32, bl32_size);
+ bl32, bl32_size, bl33, fdt);
}
void imx8mq_load_bl33(void *bl33)
@@ -400,7 +403,7 @@ __noreturn void __imx8mq_load_and_start_image_via_tfa(void *fdt, void *bl33)
}
imx8m_tfa_start_bl31(bl31, bl31_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR,
- bl32, bl32_size);
+ bl32, bl32_size, bl33, fdt);
}
void __noreturn imx93_load_and_start_image_via_tfa(void)
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 04/14] pbl: decomp: add pbl_dtbz_uncompress helper
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (2 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 03/14] ARM: i.MX8M: imx8m_tfa_start_bl31() add support for bl33 and fdt Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 05/14] pbl: fdt: add pbl_load_fdt helper Marco Felsch
` (9 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch
Add a pbl dtbz uncompress helper since uncompress() can't be used
directly within pbl.
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
include/pbl.h | 1 +
pbl/decomp.c | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/include/pbl.h b/include/pbl.h
index b330010562c4aba5fccbb4c421bb95291fa0bea1..9db4652e833bf5e82fd42a1cae19e94c4f2f868f 100644
--- a/include/pbl.h
+++ b/include/pbl.h
@@ -15,6 +15,7 @@ extern unsigned long free_mem_ptr;
extern unsigned long free_mem_end_ptr;
void pbl_barebox_uncompress(void *dest, void *compressed_start, unsigned int len);
+int pbl_dtbz_uncompress(void *dest, void *compressed_start, unsigned long len);
void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsize);
int fdt_fixup_mem(void *fdt, unsigned long membase[], unsigned long memsize[], size_t num);
diff --git a/pbl/decomp.c b/pbl/decomp.c
index ebdf81ddfbe5af65a382b7221c7102dcc791e5b9..8609ea2a46d2bcad6be8ad97e234f3af52c2145e 100644
--- a/pbl/decomp.c
+++ b/pbl/decomp.c
@@ -110,3 +110,9 @@ void pbl_barebox_uncompress(void *dest, void *compressed_start, unsigned int len
NULL, NULL,
dest, NULL, errorfn);
}
+
+int pbl_dtbz_uncompress(void *dest, void *compressed_start, unsigned long len)
+{
+ return decompress(compressed_start, len, NULL, NULL, dest, NULL,
+ errorfn);
+}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 05/14] pbl: fdt: add pbl_load_fdt helper
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (3 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 04/14] pbl: decomp: add pbl_dtbz_uncompress helper Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 06/14] ARM: i.MX: scratch: add FDT support Marco Felsch
` (8 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
The helper provides a common FDT load mechanism to load the (optional
compressed) DTB to the provided destination address in a user agnostic
manner.
Early FDTs may be useful for other firmware binaries like TEEs (e.g.
OP-TEE) which are loaded and started during the barebox boot phase.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
include/pbl.h | 2 ++
pbl/fdt.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
diff --git a/include/pbl.h b/include/pbl.h
index 9db4652e833bf5e82fd42a1cae19e94c4f2f868f..bf0c9e2ba29428361cb16a572295e66f20acdd82 100644
--- a/include/pbl.h
+++ b/include/pbl.h
@@ -31,6 +31,8 @@ fdt_device_get_match_data(const void *fdt, const char *nodepath,
int pbl_barebox_verify(const void *compressed_start, unsigned int len,
const void *hash, unsigned int hash_len);
+int pbl_load_fdt(const void *fdt, void *dest, int destsize);
+
#endif
void __noreturn barebox_pbl_entry(ulong, ulong, void *);
diff --git a/pbl/fdt.c b/pbl/fdt.c
index ac377446caeafb1beaeb211aa8bdec8767ae21fe..3c90959f8e73ea7310248f9b31359d6e8a86ae57 100644
--- a/pbl/fdt.c
+++ b/pbl/fdt.c
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
+#include <compressed-dtb.h>
#include <linux/libfdt.h>
#include <pbl.h>
#include <linux/printk.h>
#include <stdio.h>
+#include <uncompress.h>
static const __be32 *fdt_parse_reg(const __be32 *reg, uint32_t n,
uint64_t *val)
@@ -185,3 +187,80 @@ const void *fdt_device_get_match_data(const void *fdt, const char *nodepath,
return NULL;
}
+
+static int pbl_open_dtbz_into(const void *fdt, void *buf, int bufsize)
+{
+ const struct barebox_boarddata_compressed_dtb *compressed_dtb;
+ int error;
+
+ if (!fdt_blob_can_be_decompressed(fdt)) {
+ pr_warn("DTB can't be decompressed\n");
+ return -EINVAL;
+ }
+
+ compressed_dtb = fdt;
+
+ if (IS_ENABLED(CONFIG_IMAGE_COMPRESSION_NONE)) {
+ error = fdt_open_into(compressed_dtb->data, buf, bufsize);
+ if (error) {
+ pr_warn("Failed to open uncompressed DTB with %s\n",
+ fdt_strerror(error));
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ if (bufsize < compressed_dtb->datalen_uncompressed) {
+ pr_warn("FDT buffer to small, min. %u bytes required\n",
+ compressed_dtb->datalen_uncompressed);
+ return -EINVAL;
+ }
+
+ /*
+ * No error handling required, since this will hang() if uncompress
+ * fails.
+ */
+ pbl_dtbz_uncompress(buf, (void *)compressed_dtb->data,
+ compressed_dtb->datalen);
+
+ if (!blob_is_fdt(buf)) {
+ pr_warn("Failed to determine FDT type for uncompressed DTB\n");
+ return -EINVAL;
+ }
+
+ /* Required to setup size data structures to allow runtime adaptions */
+ error = fdt_open_into(buf, buf, bufsize);
+ if (error) {
+ pr_warn("Failed to open decompressed DTB with %s\n",
+ fdt_strerror(error));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int pbl_load_fdt(const void *fdt, void *dest, int destsize)
+{
+ if (destsize == 0 || !dest || !fdt) {
+ pr_warn("Skip early FDT load, invalid input\n");
+ return -EINVAL;
+ }
+
+ if (blob_is_fdt(fdt)) {
+ int error;
+
+ error = fdt_open_into(fdt, dest, destsize);
+ if (error) {
+ pr_warn("Failed to uncompressed DTB with %s\n",
+ fdt_strerror(error));
+ return -EINVAL;
+ }
+ return 0;
+ } else if (blob_is_compressed_fdt(fdt)) {
+ return pbl_open_dtbz_into(fdt, dest, destsize);
+ }
+
+ pr_warn("FDT detection failed\n");
+
+ return -EINVAL;
+}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 06/14] ARM: i.MX: scratch: add FDT support
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (4 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 05/14] pbl: fdt: add pbl_load_fdt helper Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-12 9:11 ` Ahmad Fatoum
2026-02-11 22:41 ` [PATCH v3 07/14] ARM: i.MX8M: esdctl: drop ddrc base from imx8m_ddrc_sdram_size Marco Felsch
` (7 subsequent siblings)
13 siblings, 1 reply; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch
Add support to store a FDT within the scratch area. The user needs to
query the location and size via imx_scratch_get_fdt() which can be used
afterwards to write the actual FDT into it.
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/scratch.c | 44 ++++++++++++++++++++++++++++++++++---
include/asm-generic/memory_layout.h | 6 +++++
include/mach/imx/scratch.h | 2 ++
security/Kconfig | 15 +++++++++++++
4 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-imx/scratch.c b/arch/arm/mach-imx/scratch.c
index e4e2d25969f061c9fcdfd7c3d87701b715eb2805..fba4b41040a500e31dc4afae2cdcafed0763af6b 100644
--- a/arch/arm/mach-imx/scratch.c
+++ b/arch/arm/mach-imx/scratch.c
@@ -13,10 +13,22 @@
#include <pbl.h>
struct imx_scratch_space {
- u32 bootrom_log[128];
- u32 reserved[128]; /* reserve for bootrom log */
- struct optee_header optee_hdr;
+ union {
+ /* Internal buffer, never use directly! */
+ u8 __buf[CONFIG_SCRATCH_SIZE];
+ struct {
+ u32 bootrom_log[128];
+ /* reserve for bootrom log */
+ u32 reserved[128];
+ struct optee_header optee_hdr;
+ /* FDT needs an 8 byte alignment, always last element! */
+ u8 fdt[] __aligned(8);
+ };
+ };
};
+/* Ensure that 'fdt' size fits into OP-TEE DTB_MAX_SIZE size */
+static_assert(sizeof(struct imx_scratch_space) -
+ offsetof(struct imx_scratch_space, fdt) >= PBL_OPTEE_DTB_MAX_SIZE);
static struct imx_scratch_space *scratch;
@@ -92,3 +104,29 @@ const struct optee_header *imx_scratch_get_optee_hdr(void)
return &scratch->optee_hdr;
}
+
+u8 *imx_scratch_get_fdt(unsigned int *fdt_sz)
+{
+ unsigned int sz;
+
+ if (!scratch) {
+ if (IN_PBL)
+ return ERR_PTR(-EINVAL);
+ else
+ scratch = (void *)arm_mem_scratch_get();
+ }
+
+ if (PBL_OPTEE_DTB_MAX_SIZE == 0)
+ return NULL;
+
+ sz = sizeof(struct imx_scratch_space) -
+ offsetof(struct imx_scratch_space, fdt);
+
+ if (sz > PBL_OPTEE_DTB_MAX_SIZE)
+ sz = PBL_OPTEE_DTB_MAX_SIZE;
+
+ if (fdt_sz)
+ *fdt_sz = sz;
+
+ return scratch->fdt;
+}
diff --git a/include/asm-generic/memory_layout.h b/include/asm-generic/memory_layout.h
index 39af73849796fd1954521f0b53bf38fcb0984cef..d477f7bbdbf769a61392da06f2a7b665ce86f5ca 100644
--- a/include/asm-generic/memory_layout.h
+++ b/include/asm-generic/memory_layout.h
@@ -25,6 +25,12 @@
#define OPTEE_SHM_SIZE 0
#endif
+#ifdef CONFIG_PBL_OPTEE_DTB_MAX_SIZE
+#define PBL_OPTEE_DTB_MAX_SIZE CONFIG_PBL_OPTEE_DTB_MAX_SIZE
+#else
+#define PBL_OPTEE_DTB_MAX_SIZE 0
+#endif
+
#define HEAD_TEXT_BASE MALLOC_BASE
#define MALLOC_SIZE CONFIG_MALLOC_SIZE
#define STACK_SIZE CONFIG_STACK_SIZE
diff --git a/include/mach/imx/scratch.h b/include/mach/imx/scratch.h
index 6c2cecabcd80f71aa754736322151d63f2711745..b74d19a560f33da0a11621af7e11abdce6d1c295 100644
--- a/include/mach/imx/scratch.h
+++ b/include/mach/imx/scratch.h
@@ -14,6 +14,8 @@ struct optee_header;
const struct optee_header *imx_scratch_get_optee_hdr(void);
void imx_scratch_save_optee_hdr(const struct optee_header *hdr);
+u8 *imx_scratch_get_fdt(unsigned int *fdt_sz);
+
#define imx8mq_init_scratch_space() imx8m_init_scratch_space(32, true)
#define imx8mm_init_scratch_space() imx8m_init_scratch_space(32, true)
#define imx8mn_init_scratch_space() imx8m_init_scratch_space(16, true)
diff --git a/security/Kconfig b/security/Kconfig
index 40d468ae07d2b1d4357542df88a0a92eeb3d365f..338bc1e5a72d91bc1617865cacd9d2d8941ca8f5 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -178,6 +178,21 @@ config PBL_OPTEE
to barebox in THUMB2 mode. Make sure you do not compile barebox in THUMB2
mode for OP-TEE versions older than this.
+config PBL_OPTEE_DTB_MAX_SIZE
+ hex
+ default 0x0
+ prompt "OP-TEE FDT Size"
+ help
+ The size of the DTB which is passed by the PBL to OP-TEE. This option
+ can be left unchanged if OP-TEE DTB support isn't required. If OP-TEE
+ DTB support is used, this option must match OP-TEE's CFG_DTB_MAX_SIZE
+ configuration.
+
+ Note: passing the DTB from the PBL to OP-TEE requires platform
+ support. Currently only the i.MX8MMini/Nano/Plus SoCs support this.
+ Furthermore your board code must be modified to pass the FDT
+ accordingly.
+
endmenu
source "lib/Kconfig.hardening"
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v3 06/14] ARM: i.MX: scratch: add FDT support
2026-02-11 22:41 ` [PATCH v3 06/14] ARM: i.MX: scratch: add FDT support Marco Felsch
@ 2026-02-12 9:11 ` Ahmad Fatoum
0 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2026-02-12 9:11 UTC (permalink / raw)
To: barebox
On 2/11/26 11:41 PM, Marco Felsch wrote:
> Add support to store a FDT within the scratch area. The user needs to
> query the location and size via imx_scratch_get_fdt() which can be used
> afterwards to write the actual FDT into it.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Thanks,
Ahmad
> ---
> arch/arm/mach-imx/scratch.c | 44 ++++++++++++++++++++++++++++++++++---
> include/asm-generic/memory_layout.h | 6 +++++
> include/mach/imx/scratch.h | 2 ++
> security/Kconfig | 15 +++++++++++++
> 4 files changed, 64 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-imx/scratch.c b/arch/arm/mach-imx/scratch.c
> index e4e2d25969f061c9fcdfd7c3d87701b715eb2805..fba4b41040a500e31dc4afae2cdcafed0763af6b 100644
> --- a/arch/arm/mach-imx/scratch.c
> +++ b/arch/arm/mach-imx/scratch.c
> @@ -13,10 +13,22 @@
> #include <pbl.h>
>
> struct imx_scratch_space {
> - u32 bootrom_log[128];
> - u32 reserved[128]; /* reserve for bootrom log */
> - struct optee_header optee_hdr;
> + union {
> + /* Internal buffer, never use directly! */
> + u8 __buf[CONFIG_SCRATCH_SIZE];
> + struct {
> + u32 bootrom_log[128];
> + /* reserve for bootrom log */
> + u32 reserved[128];
> + struct optee_header optee_hdr;
> + /* FDT needs an 8 byte alignment, always last element! */
> + u8 fdt[] __aligned(8);
> + };
> + };
> };
> +/* Ensure that 'fdt' size fits into OP-TEE DTB_MAX_SIZE size */
> +static_assert(sizeof(struct imx_scratch_space) -
> + offsetof(struct imx_scratch_space, fdt) >= PBL_OPTEE_DTB_MAX_SIZE);
>
> static struct imx_scratch_space *scratch;
>
> @@ -92,3 +104,29 @@ const struct optee_header *imx_scratch_get_optee_hdr(void)
>
> return &scratch->optee_hdr;
> }
> +
> +u8 *imx_scratch_get_fdt(unsigned int *fdt_sz)
> +{
> + unsigned int sz;
> +
> + if (!scratch) {
> + if (IN_PBL)
> + return ERR_PTR(-EINVAL);
> + else
> + scratch = (void *)arm_mem_scratch_get();
> + }
> +
> + if (PBL_OPTEE_DTB_MAX_SIZE == 0)
> + return NULL;
> +
> + sz = sizeof(struct imx_scratch_space) -
> + offsetof(struct imx_scratch_space, fdt);
> +
> + if (sz > PBL_OPTEE_DTB_MAX_SIZE)
> + sz = PBL_OPTEE_DTB_MAX_SIZE;
> +
> + if (fdt_sz)
> + *fdt_sz = sz;
> +
> + return scratch->fdt;
> +}
> diff --git a/include/asm-generic/memory_layout.h b/include/asm-generic/memory_layout.h
> index 39af73849796fd1954521f0b53bf38fcb0984cef..d477f7bbdbf769a61392da06f2a7b665ce86f5ca 100644
> --- a/include/asm-generic/memory_layout.h
> +++ b/include/asm-generic/memory_layout.h
> @@ -25,6 +25,12 @@
> #define OPTEE_SHM_SIZE 0
> #endif
>
> +#ifdef CONFIG_PBL_OPTEE_DTB_MAX_SIZE
> +#define PBL_OPTEE_DTB_MAX_SIZE CONFIG_PBL_OPTEE_DTB_MAX_SIZE
> +#else
> +#define PBL_OPTEE_DTB_MAX_SIZE 0
> +#endif
> +
> #define HEAD_TEXT_BASE MALLOC_BASE
> #define MALLOC_SIZE CONFIG_MALLOC_SIZE
> #define STACK_SIZE CONFIG_STACK_SIZE
> diff --git a/include/mach/imx/scratch.h b/include/mach/imx/scratch.h
> index 6c2cecabcd80f71aa754736322151d63f2711745..b74d19a560f33da0a11621af7e11abdce6d1c295 100644
> --- a/include/mach/imx/scratch.h
> +++ b/include/mach/imx/scratch.h
> @@ -14,6 +14,8 @@ struct optee_header;
> const struct optee_header *imx_scratch_get_optee_hdr(void);
> void imx_scratch_save_optee_hdr(const struct optee_header *hdr);
>
> +u8 *imx_scratch_get_fdt(unsigned int *fdt_sz);
> +
> #define imx8mq_init_scratch_space() imx8m_init_scratch_space(32, true)
> #define imx8mm_init_scratch_space() imx8m_init_scratch_space(32, true)
> #define imx8mn_init_scratch_space() imx8m_init_scratch_space(16, true)
> diff --git a/security/Kconfig b/security/Kconfig
> index 40d468ae07d2b1d4357542df88a0a92eeb3d365f..338bc1e5a72d91bc1617865cacd9d2d8941ca8f5 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -178,6 +178,21 @@ config PBL_OPTEE
> to barebox in THUMB2 mode. Make sure you do not compile barebox in THUMB2
> mode for OP-TEE versions older than this.
>
> +config PBL_OPTEE_DTB_MAX_SIZE
> + hex
> + default 0x0
> + prompt "OP-TEE FDT Size"
> + help
> + The size of the DTB which is passed by the PBL to OP-TEE. This option
> + can be left unchanged if OP-TEE DTB support isn't required. If OP-TEE
> + DTB support is used, this option must match OP-TEE's CFG_DTB_MAX_SIZE
> + configuration.
> +
> + Note: passing the DTB from the PBL to OP-TEE requires platform
> + support. Currently only the i.MX8MMini/Nano/Plus SoCs support this.
> + Furthermore your board code must be modified to pass the FDT
> + accordingly.
> +
> endmenu
>
> source "lib/Kconfig.hardening"
>
--
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] 16+ messages in thread
* [PATCH v3 07/14] ARM: i.MX8M: esdctl: drop ddrc base from imx8m_ddrc_sdram_size
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (5 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 06/14] ARM: i.MX: scratch: add FDT support Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 08/14] ARM: i.MX8M: esdctl: export imx8m_ddrc_sdram_size() Marco Felsch
` (6 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
All i.MX8M use the same DDRC MMIO address. Therefore drop the ddrc param
from imx8m_ddrc_sdram_size() and set it locally.
While on it drop the param from _imx8m_ddrc_add_mem() as well since it
is no longer needed to be passed to imx8m_ddrc_sdram_size().
Acked-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/esdctl.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 935c3d32571dfa6a2a6252f981054b2e8f7c4cbd..d89755f672b5e12e6be44dae14b58931548dd889 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -468,8 +468,9 @@ static void imx_ddrc_set_mstr_device_config(u32 *mstr, unsigned bits)
*mstr |= FIELD_PREP(DDRC_MSTR_DEVICE_CONFIG, fls(bits / 8));
}
-static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswidth)
+static resource_size_t imx8m_ddrc_sdram_size(unsigned buswidth)
{
+ void __iomem *ddrc = IOMEM(MX8M_DDRC_CTL_BASE_ADDR);
const u32 addrmap[DDRC_ADDRMAP_LENGTH] = {
readl(ddrc + DDRC_ADDRMAP(0)),
readl(ddrc + DDRC_ADDRMAP(1)),
@@ -519,10 +520,10 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
reduced_adress_space, mstr);
}
-static int _imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data,
+static int _imx8m_ddrc_add_mem(const struct imx_esdctl_data *data,
unsigned int buswidth)
{
- resource_size_t size = imx8m_ddrc_sdram_size(mmdcbase, buswidth);
+ resource_size_t size = imx8m_ddrc_sdram_size(buswidth);
resource_size_t size0, size1;
int ret;
@@ -556,12 +557,12 @@ static int _imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *dat
static int imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)
{
- return _imx8m_ddrc_add_mem(mmdcbase, data, 32);
+ return _imx8m_ddrc_add_mem(data, 32);
}
static int imx8mn_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)
{
- return _imx8m_ddrc_add_mem(mmdcbase, data, 16);
+ return _imx8m_ddrc_add_mem(data, 16);
}
#define IMX9_DDRC_CS_CONFIG(n) (0x80 + (n) * 4)
@@ -1002,7 +1003,7 @@ resource_size_t imx8m_barebox_earlymem_size(unsigned buswidth)
{
resource_size_t size;
- size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), buswidth);
+ size = imx8m_ddrc_sdram_size(buswidth);
/*
* We artificially limit detected memory size to force malloc
* pool placement to be within 4GiB address space, so as to
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 08/14] ARM: i.MX8M: esdctl: export imx8m_ddrc_sdram_size()
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (6 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 07/14] ARM: i.MX8M: esdctl: drop ddrc base from imx8m_ddrc_sdram_size Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 09/14] ARM: i.MX8M: add support to pass BL3x bl_params Marco Felsch
` (5 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
imx8m_ddrc_sdram_size() returns the full memory size whereas
imx8m_barebox_earlymem_size() limits the size to 4GiB.
This can be useful in cases like fixing up the FDT memory size for
OP-TEE which uses the information to configure the TZASC accordingly.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/esdctl.c | 2 +-
include/mach/imx/esdctl.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index d89755f672b5e12e6be44dae14b58931548dd889..e4b4ca561094e2dac99f475b93efc8fc7e962d9e 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -468,7 +468,7 @@ static void imx_ddrc_set_mstr_device_config(u32 *mstr, unsigned bits)
*mstr |= FIELD_PREP(DDRC_MSTR_DEVICE_CONFIG, fls(bits / 8));
}
-static resource_size_t imx8m_ddrc_sdram_size(unsigned buswidth)
+resource_size_t imx8m_ddrc_sdram_size(unsigned buswidth)
{
void __iomem *ddrc = IOMEM(MX8M_DDRC_CTL_BASE_ADDR);
const u32 addrmap[DDRC_ADDRMAP_LENGTH] = {
diff --git a/include/mach/imx/esdctl.h b/include/mach/imx/esdctl.h
index 97bd444b1a4ca2defdeb9f82180c0366296a32a0..47fb665a861bf2105b4d606ea1672caf27d8e285 100644
--- a/include/mach/imx/esdctl.h
+++ b/include/mach/imx/esdctl.h
@@ -153,6 +153,7 @@ void __noreturn imx93_barebox_entry(void *boarddata);
void imx_esdctl_disable(void);
resource_size_t imx6_get_mmdc_sdram_size(void);
resource_size_t imx8m_barebox_earlymem_size(unsigned buswidth);
+resource_size_t imx8m_ddrc_sdram_size(unsigned buswidth);
resource_size_t imx9_ddrc_sdram_size(void);
#endif
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 09/14] ARM: i.MX8M: add support to pass BL3x bl_params
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (7 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 08/14] ARM: i.MX8M: esdctl: export imx8m_ddrc_sdram_size() Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 10/14] handoff-data: Add TEE_DT_OVL entry Marco Felsch
` (4 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
Add support to handover the BL32 and BL33 entrypoints via the TF-A
struct::bl_params in arg0. This eliminates the requirement to share the
different load addresses between multiple binaries to lower the BSP
integration effort.
In addition to the entriespoints, this commit also adds the support to
pass the builtin barebox DTB to OP-TEE if enabled.
Acked-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/Kconfig | 16 ++++++++++
arch/arm/mach-imx/atf.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 95 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index eb947e67fb57a8f020604d6be4888a613e735fed..ef181d3868abe1a92c106f5a0577633c7e341032 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -38,6 +38,22 @@ config ARCH_IMX_ATF
def_bool y
depends on ARCH_IMX8M || ARCH_IMX9
+config ARCH_IMX_ATF_PASS_BL_PARAMS
+ bool "Pass BL3x bl_params as arg0 to TF-A"
+ depends on ARCH_IMX_ATF
+ select ARM_ATF
+ select LIBFDT
+ help
+ Enable this option if you are using an upstream TF-A that uses
+ the struct::bl_params to handover all required BL32 and BL33
+ information required to start the BL32 and BL33 image.
+
+ Since upstream TF-A v2.12 all i.MX8M support this feature except for
+ the i.MX8MQ.
+
+ This option is required if the barebox DT should be passed to the
+ BL32 firmware.
+
config ARCH_IMX_ROMAPI
def_bool y
depends on ARCH_IMX8M || ARCH_IMX9
diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index 11d26607bc2ea449402d9cb8e20fbb44f425989c..34893c3a04616a9fbf2648a58940bec793ae04c8 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <asm/atf_common.h>
#include <asm/sections.h>
#include <common.h>
#include <firmware.h>
@@ -18,6 +19,7 @@
#include <mach/imx/ele.h>
#include <mach/imx/xload.h>
#include <mach/imx/snvs.h>
+#include <pbl.h>
static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32_size)
{
@@ -37,6 +39,68 @@ static void imx_adjust_optee_memory(void **bl32, void **bl32_image, size_t *bl32
*bl32_image += sizeof(*hdr);
}
+static __noreturn void bl31_via_bl_params(void *bl31, void *bl32, void *bl33,
+ void *fdt)
+{
+ struct bl2_to_bl31_params_mem_v2 *params;
+
+ /* Prepare bl_params for BL32 */
+ params = bl2_plat_get_bl31_params_v2((uintptr_t)bl32,
+ (uintptr_t)bl33, (uintptr_t)fdt);
+
+ pr_debug("Jump to BL31 with bl-params (%s BL32-FDT)\n",
+ fdt ? "including" : "excluding");
+ /*
+ * Start BL31 without passing the FDT via x1 since the mainline
+ * TF-A doesn't support it yet.
+ */
+ bl31_entry_v2((uintptr_t)bl31, ¶ms->bl_params, NULL);
+
+ __builtin_unreachable();
+}
+
+static __noreturn void start_bl31_via_bl_params(void *bl31, void *bl32,
+ void *bl33, void *fdt)
+{
+ unsigned long mem_base = MX8M_DDR_CSD1_BASE_ADDR;
+ unsigned long mem_sz;
+ unsigned int bufsz = 0;
+ int error;
+ u8 *buf;
+
+ if (!fdt)
+ bl31_via_bl_params(bl31, bl32, bl33, NULL);
+
+ buf = imx_scratch_get_fdt(&bufsz);
+ if (IS_ERR_OR_NULL(buf)) {
+ if (!buf)
+ pr_debug("No FDT scratch mem configured, continue without FDT\n");
+ else
+ pr_warn("Failed to get FDT scratch mem, continue without FDT\n");
+ bl31_via_bl_params(bl31, bl32, bl33, NULL);
+ }
+
+ error = pbl_load_fdt(fdt, buf, bufsz);
+ if (error) {
+ pr_warn("Failed to load FDT, continue without FDT\n");
+ bl31_via_bl_params(bl31, bl32, bl33, NULL);
+ }
+
+ if (cpu_is_mx8mn())
+ mem_sz = imx8m_ddrc_sdram_size(16);
+ else
+ mem_sz = imx8m_ddrc_sdram_size(32);
+
+ fdt = buf;
+ error = fdt_fixup_mem(fdt, &mem_base, &mem_sz, 1);
+ if (error) {
+ pr_warn("Failed to fixup FDT memory node, continue without FDT\n");
+ bl31_via_bl_params(bl31, bl32, bl33, NULL);
+ }
+
+ bl31_via_bl_params(bl31, bl32, bl33, fdt);
+}
+
/**
* imx8m_tfa_start_bl31 - Load TF-A BL31 blob and transfer control to it
*
@@ -122,7 +186,21 @@ imx8m_tfa_start_bl31(const void *tfa_bin, size_t tfa_size, void *tfa_dest,
asm volatile("msr sp_el2, %0" : :
"r" (tfa_dest - 16) :
"cc");
- bl31();
+
+ /*
+ * If enabled the bl_params are passed via x0 to the TF-A, except for
+ * the i.MX8MQ which doesn't support bl_params yet.
+ * Passing the bl_params must be explicit enabled to be backward
+ * compatible with downstream TF-A versions, which may have problems
+ * with the bl_params.
+ */
+ if (!IS_ENABLED(CONFIG_ARCH_IMX_ATF_PASS_BL_PARAMS) || cpu_is_mx8mq()) {
+ pr_debug("Jump to BL31 without bl-params\n");
+ bl31();
+ } else {
+ start_bl31_via_bl_params(bl31, bl32, bl33, fdt);
+ }
+
__builtin_unreachable();
}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 10/14] handoff-data: Add TEE_DT_OVL entry
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (8 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 09/14] ARM: i.MX8M: add support to pass BL3x bl_params Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 11/14] security: optee: add optee_handoff_overlay helper Marco Felsch
` (3 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
Add support to pass a TEE provided FDT overlay from pbl to barebox.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
include/pbl/handoff-data.h | 1 +
pbl/handoff-data.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/include/pbl/handoff-data.h b/include/pbl/handoff-data.h
index bfb1985b998c8de16d06314f3ff5d3b7753eac9b..81cb0880ad4a384d633a3983ea99d82df4f47d06 100644
--- a/include/pbl/handoff-data.h
+++ b/include/pbl/handoff-data.h
@@ -14,6 +14,7 @@ struct handoff_data {
#define HANDOFF_DATA_EXTERNAL_DT HANDOFF_DATA_BAREBOX(2)
#define HANDOFF_DATA_ARM_MACHINE HANDOFF_DATA_BAREBOX(3)
#define HANDOFF_DATA_EFI HANDOFF_DATA_BAREBOX(4)
+#define HANDOFF_DATA_TEE_DT_OVL HANDOFF_DATA_BAREBOX(5)
#define HANDOFF_DATA_BOARD(n) (0x951726fb + (n))
diff --git a/pbl/handoff-data.c b/pbl/handoff-data.c
index 42e53f986bf14408f25cdf4434a5c284f8361401..9a24b82ef64a355b38bf436c03bece05cb1b77c5 100644
--- a/pbl/handoff-data.c
+++ b/pbl/handoff-data.c
@@ -189,6 +189,8 @@ static const char *handoff_data_entry_name(struct handoff_data_entry *hde)
return "handoff FDT (external)";
case HANDOFF_DATA_ARM_MACHINE:
return "ARM machine number";
+ case HANDOFF_DATA_TEE_DT_OVL:
+ return "handoff TEE FDTO";
default:
sprintf(name, "handoff %08x", hde->cookie);
return name;
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 11/14] security: optee: add optee_handoff_overlay helper
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (9 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 10/14] handoff-data: Add TEE_DT_OVL entry Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 12/14] security: optee: add helpers to register OF overlays Marco Felsch
` (2 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
Add a helper to pass the OP-TEE provided overlay to barebox via the
handoff mechanism. This can be useful to generalize the reserved-memory
node handling since OP-TEE can provide this information via the overlay
if configured in OP-TEE.
While on it sort the include headers in alphabetical order.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
include/tee/optee.h | 5 +++++
security/Kconfig | 9 +++++++++
security/optee.c | 15 ++++++++++++++-
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/include/tee/optee.h b/include/tee/optee.h
index 10e829c04f8832c4c04771800f1963e25f425482..ba3de3e410c84619cd2baea27fc89e2901df6ecf 100644
--- a/include/tee/optee.h
+++ b/include/tee/optee.h
@@ -37,6 +37,7 @@ int optee_verify_header (const struct optee_header *hdr);
void optee_set_membase(const struct optee_header *hdr);
int optee_get_membase(u64 *membase);
+void optee_handoff_overlay(void *ovl, unsigned int ovl_sz);
#else
@@ -49,6 +50,10 @@ static inline int optee_get_membase(u64 *membase)
return -ENOSYS;
}
+static inline void optee_handoff_overlay(void *ovl, unsigned int ovl_sz)
+{
+}
+
#endif /* CONFIG_HAVE_OPTEE */
#ifdef __PBL__
diff --git a/security/Kconfig b/security/Kconfig
index 338bc1e5a72d91bc1617865cacd9d2d8941ca8f5..c90f2bbacf266ee0dcb7f494279843be65f5fec1 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -117,6 +117,15 @@ config HAVE_OPTEE
bidirectional communication with OP-TEE is enabled via
CONFIG_OPTEE.
+config OPTEE_APPLY_OVERLAY
+ bool "Apply OP-TEE DTBO to barebox and kernel DT"
+ depends on HAVE_OPTEE
+ help
+ Apply the OP-TEE provided device-tree overlay to internal barebox DT
+ and the kernel DT if this option is enabled. This requires barebox
+ machine support and the board lowlevel code to pass the barebox
+ internal DT to OP-TEE while booting.
+
config OPTEE_SIZE
hex
default 0x02000000
diff --git a/security/optee.c b/security/optee.c
index 422bc1c90924ba8ab266b1aa8d06e52c819d2010..d2cda9d77b85947ff222390177666e75e54f9adb 100644
--- a/security/optee.c
+++ b/security/optee.c
@@ -2,10 +2,12 @@
#define pr_fmt(fmt) "optee: " fmt
-#include <tee/optee.h>
+#include <compressed-dtb.h>
#include <linux/printk.h>
#include <linux/errno.h>
#include <linux/limits.h>
+#include <pbl/handoff-data.h>
+#include <tee/optee.h>
static u64 optee_membase = U64_MAX;
@@ -60,3 +62,14 @@ void optee_set_membase(const struct optee_header *hdr)
optee_membase = (u64)hdr->init_load_addr_hi << 32;
optee_membase |= hdr->init_load_addr_lo;
}
+
+void optee_handoff_overlay(void *ovl, unsigned int ovl_sz)
+{
+ if (!IS_ENABLED(CONFIG_OPTEE_APPLY_OVERLAY))
+ return;
+
+ if (!blob_is_fdt(ovl))
+ return;
+
+ handoff_data_add(HANDOFF_DATA_TEE_DT_OVL, ovl, ovl_sz);
+}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 12/14] security: optee: add helpers to register OF overlays
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (10 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 11/14] security: optee: add optee_handoff_overlay helper Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 13/14] ARM: i.MX8M: Pass optional OP-TEE overlay to barebox Marco Felsch
2026-02-11 22:41 ` [PATCH v3 14/14] of: base: register optional OP-TEE overlay Marco Felsch
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
Add two helpers to make the OP-TEE overlay handling more convenient.
The first helper registers an optional OF overlay provided by
barebox-pbl.
The second helper can be used to query the status of the OF overlay, e.g
registered or not-registered.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
drivers/tee/optee/of_fixup.c | 42 ++++++++++++++++++++++++++++++++++++++++++
include/tee/optee.h | 11 +++++++++++
2 files changed, 53 insertions(+)
diff --git a/drivers/tee/optee/of_fixup.c b/drivers/tee/optee/of_fixup.c
index 152322901a7e6af9c83da4c6a2d43f6e2c9af329..35403c93dc54b5a5afab5f569e2921248cd68f53 100644
--- a/drivers/tee/optee/of_fixup.c
+++ b/drivers/tee/optee/of_fixup.c
@@ -1,7 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#define pr_fmt(fmt) "OP-TEE OF: " fmt
+
#include <of.h>
#include <linux/ioport.h>
+#include <linux/printk.h>
#include <asm/barebox-arm.h>
#include <tee/optee.h>
@@ -64,3 +67,42 @@ int of_optee_fixup(struct device_node *root, void *_data)
return of_fixup_reserved_memory(root, &res_shm);
}
+
+static bool optee_ovl_registered;
+
+void optee_register_overlay(void)
+{
+ struct device_node *overlay;
+ size_t size = 0;
+ void *fdto;
+ int err;
+
+ if (optee_ovl_registered) {
+ pr_warn("overlay already registered, skip\n");
+ return;
+ }
+
+ fdto = handoff_data_get_entry(HANDOFF_DATA_TEE_DT_OVL, &size);
+ if (!fdto || size == 0)
+ return;
+
+ overlay = of_unflatten_dtb(fdto, size);
+ if (IS_ERR(overlay)) {
+ pr_warn("failed to unflatten overlay: %pe\n", overlay);
+ return;
+ }
+
+ err = of_register_overlay(overlay);
+ if (err) {
+ pr_warn("failed to register overlay: %pe\n", ERR_PTR(err));
+ of_delete_node(overlay);
+ return;
+ }
+
+ optee_ovl_registered = true;
+}
+
+bool optee_overlay_registered(void)
+{
+ return optee_ovl_registered;
+}
diff --git a/include/tee/optee.h b/include/tee/optee.h
index ba3de3e410c84619cd2baea27fc89e2901df6ecf..45e042cbcc0eef4e6ab30381a7b9139e0ca03f4e 100644
--- a/include/tee/optee.h
+++ b/include/tee/optee.h
@@ -38,6 +38,8 @@ int optee_verify_header (const struct optee_header *hdr);
void optee_set_membase(const struct optee_header *hdr);
int optee_get_membase(u64 *membase);
void optee_handoff_overlay(void *ovl, unsigned int ovl_sz);
+void optee_register_overlay(void);
+bool optee_overlay_registered(void);
#else
@@ -54,6 +56,15 @@ static inline void optee_handoff_overlay(void *ovl, unsigned int ovl_sz)
{
}
+static inline void optee_register_overlay(void)
+{
+}
+
+static inline bool optee_overlay_registered(void)
+{
+ return false;
+}
+
#endif /* CONFIG_HAVE_OPTEE */
#ifdef __PBL__
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 13/14] ARM: i.MX8M: Pass optional OP-TEE overlay to barebox
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (11 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 12/14] security: optee: add helpers to register OF overlays Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
2026-02-11 22:41 ` [PATCH v3 14/14] of: base: register optional OP-TEE overlay Marco Felsch
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
This commit adds the support to pass the optional OP-TEE overlay from
pbl to barebox for all i.MX8M SoCs.
There is no difference between ARMv7 and ARMv8, therefore the helper
name to pass the overlay is generic.
That being said, on ARMv8 it's required to use the
ARCH_IMX_ATF_PASS_BL_PARAMS mechanism, else the devicetree location
can't be passed to OP-TEE. Therefore a sanity check for ARMv8 is added.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/esdctl.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index e4b4ca561094e2dac99f475b93efc8fc7e962d9e..f8b8089cb03f3d80e6684fc01d5d19cafd1d7856 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -877,6 +877,45 @@ upper_or_coalesced_range(unsigned long base0, unsigned long size0,
}
}
+static void imx_optee_handoff_overlay(void)
+{
+ unsigned int early_fdt_sz;
+ u8 *early_fdt;
+
+ /*
+ * On ARMv8 i.MX SoCs CONFIG_ARCH_IMX_ATF_PASS_BL_PARAMS must be enabled
+ * else no FDT is passed to OP-TEE.
+ */
+ if (IS_ENABLED(CONFIG_CPU_V8) &&
+ !IS_ENABLED(CONFIG_ARCH_IMX_ATF_PASS_BL_PARAMS))
+ return;
+
+ early_fdt = imx_scratch_get_fdt(&early_fdt_sz);
+ if (IS_ERR(early_fdt)) {
+ pr_warn("Failed to get FDT scratch mem, skip register OP-TEE DTBO\n");
+ return;
+ }
+
+ /* Early FDT is optional */
+ if (!early_fdt)
+ return;
+
+ /*
+ * OP-TEE DT handling is really cumbersome. In case an external DT was
+ * supplied, OP-TEE re-use this DT and appends overlays if enabled.
+ *
+ * Register the whole early FDT as overlay and let the barebox common
+ * code extract the __fragment__'s from the early FDT which should be
+ * faster than doing it here manually via libfdt and no MMU.
+ *
+ * Note: This assumes that OP-TEE is the only one adding __fragment__'s.
+ * This is always the case on ARMv7, but on ARMv8 the BL31 (TF-A) could
+ * add __fragment__'s too. Since the barebox i.MX port doesn't pass the
+ * FDT to the TF-A this is fine for now.
+ */
+ optee_handoff_overlay(early_fdt, early_fdt_sz);
+}
+
void __noreturn imx1_barebox_entry(void *boarddata)
{
unsigned long base, size;
@@ -1020,6 +1059,7 @@ static void __noreturn imx8m_barebox_entry(void *boarddata, unsigned buswidth)
{
imx8m_init_scratch_space(buswidth, false);
optee_set_membase(imx_scratch_get_optee_hdr());
+ imx_optee_handoff_overlay();
barebox_arm_entry(MX8M_DDR_CSD1_BASE_ADDR,
imx8m_barebox_earlymem_size(buswidth), boarddata);
}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 14/14] of: base: register optional OP-TEE overlay
2026-02-11 22:41 [PATCH v3 00/14] Improve OP-TEE handling Marco Felsch
` (12 preceding siblings ...)
2026-02-11 22:41 ` [PATCH v3 13/14] ARM: i.MX8M: Pass optional OP-TEE overlay to barebox Marco Felsch
@ 2026-02-11 22:41 ` Marco Felsch
13 siblings, 0 replies; 16+ messages in thread
From: Marco Felsch @ 2026-02-11 22:41 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Marco Felsch, Ahmad Fatoum
The BL32 OP-TEE binary can provide an overlay which contains all
required configurations made by the secure-os, e.g. reserved-memory
nodes, the firmware-interface (smc) and so on.
This overlay can be used to uniform the OP-TEE configuration handling
for all OF platforms. While this patch is platform agnostic, the OP-TEE
overlay handling still depends on platform and machine specific
integrations.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
arch/arm/mach-imx/imx9.c | 2 +-
arch/arm/mach-rockchip/rockchip.c | 3 ++-
drivers/of/base.c | 3 +++
drivers/soc/imx/soc-imx8m.c | 3 ++-
4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-imx/imx9.c b/arch/arm/mach-imx/imx9.c
index 25ba7e444843ea5ae817dd8103074e5a50fb48f0..ada4048d4ca07b5a2f8a5ee5ceb3e3b3ecb24af8 100644
--- a/arch/arm/mach-imx/imx9.c
+++ b/arch/arm/mach-imx/imx9.c
@@ -174,7 +174,7 @@ int imx93_init(void)
imx93_set_arm_clock();
imx93_bootsource();
- if (IS_ENABLED(CONFIG_PBL_OPTEE)) {
+ if (IS_ENABLED(CONFIG_PBL_OPTEE) && !optee_overlay_registered()) {
static struct of_optee_fixup_data optee_fixup_data = {
.shm_size = OPTEE_SHM_SIZE,
.method = "smc",
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 0828f0fa72a9ad2495e012a42918c4b5431652e7..6ed7802cc695a61253c937b24f5b1c2a1eea7732 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -33,7 +33,8 @@ static int rockchip_init(void)
{
const struct optee_header *hdr = rk_scratch_get_optee_hdr();
- if (IS_ENABLED(CONFIG_PBL_OPTEE) && optee_verify_header(hdr) == 0) {
+ if (IS_ENABLED(CONFIG_PBL_OPTEE) && !optee_overlay_registered() &&
+ optee_verify_header(hdr) == 0) {
static struct of_optee_fixup_data optee_fixup_data = {
.shm_size = OPTEE_SHM_SIZE,
.method = "smc",
diff --git a/drivers/of/base.c b/drivers/of/base.c
index a26c1faa41d5a7acea4f71126ff553cf7b0bae86..1c81383d84cb66e900eb2b33d3be03239abd056a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -23,6 +23,7 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <pm_domain.h>
+#include <tee/optee.h>
static struct device_node *root_node;
@@ -2132,6 +2133,8 @@ int barebox_register_fdt(const void *dtb)
return PTR_ERR(root);
}
+ optee_register_overlay();
+
return barebox_register_of(root);
}
diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
index 3b83284fcbfd56d543cc300b8d42771202aa0bbb..695fc3b027ae81cc8c83cbf27aff261c0459aa8a 100644
--- a/drivers/soc/imx/soc-imx8m.c
+++ b/drivers/soc/imx/soc-imx8m.c
@@ -207,7 +207,8 @@ static int imx8_soc_imx8m_init(struct soc_device_attribute *soc_dev_attr)
imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons);
pr_info("%s unique ID: %s\n", cputypestr, uid);
- if (IS_ENABLED(CONFIG_PBL_OPTEE) && imx8m_tzc380_is_enabled()) {
+ if (IS_ENABLED(CONFIG_PBL_OPTEE) && imx8m_tzc380_is_enabled() &&
+ !optee_overlay_registered()) {
static struct of_optee_fixup_data optee_fixup_data = {
.shm_size = OPTEE_SHM_SIZE,
.method = "smc",
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread