diff options
| author | Daniel Golle <[email protected]> | 2026-07-19 02:51:17 +0100 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-07-29 14:52:23 -0600 |
| commit | de61c59164e0aa1735d37db6ba0db1276e62ac61 (patch) | |
| tree | 06e931dc2234c980a979e9a6bf971d2009474c84 | |
| parent | 06c49ce4f1870718321bb502671c2ed0a42fd15e (diff) | |
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 <[email protected]>
| -rw-r--r-- | common/spl/spl_atf.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c index 8bc5db77395..17acd3665df 100644 --- a/common/spl/spl_atf.c +++ b/common/spl/spl_atf.c @@ -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) |
