spl: atf: fix BL32 entry point for multi-segment TEE images

binman's split-elf operation records one FIT image node per ELF
segment, all with os = "tee", and only the segment containing the ELF
entry point carries an entry property. Since fdt_add_subnode() inserts
new subnodes in front of existing ones, the /fit-images nodes end up in
reverse recording order, so spl_fit_images_find() would return the
*last* TEE segment and its load address was passed to BL31 as the BL32
entry point.

On RK3588 with an OP-TEE tee.elf consisting of two PT_LOAD segments
this made BL31 (SPD=opteed) ERET into OP-TEE's data segment at
0x30200000 instead of the entry point at 0x30000000, hanging the boot
right after 'BL31: Initializing BL32'.

Prefer the FIT image node which provides an entry property and only
fall back to the first matching node when none of them has one.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle
2026-07-29 14:52:23 -06:00
committed by Tom Rini
parent 06c49ce4f1
commit de61c59164
+16 -2
View File
@@ -212,7 +212,9 @@ static void __noreturn bl31_entry(ulong bl31_entry, ulong bl32_entry,
static int spl_fit_images_find(void *blob, int os)
{
int parent, node, ndepth = 0;
int found = -FDT_ERR_NOTFOUND;
const void *data;
ulong val;
if (!blob)
return -FDT_ERR_BADMAGIC;
@@ -231,11 +233,23 @@ static int spl_fit_images_find(void *blob, int os)
if (!data)
continue;
if (genimg_get_os_id(data) == os)
if (genimg_get_os_id(data) != os)
continue;
/*
* A multi-segment image, e.g. an OP-TEE ELF split by
* binman, is recorded as one node per segment, all with
* the same os. Only the segment holding the ELF entry
* point carries an entry property, so prefer that node.
*/
if (!fit_image_get_entry(blob, node, &val))
return node;
if (found < 0)
found = node;
};
return -FDT_ERR_NOTFOUND;
return found;
}
ulong spl_fit_images_get_entry(void *blob, int node)