using binman sym for size of u-boot itb

Rasmus Villemoes rasmus.villemoes at
Fri Mar 3 11:24:55 CET 2023

On imx8mp, binman is heavily used for the assembling of all the various
pieces. Partly for my own future reference:

There's u-boot-spl-ddr which is u-boot-spl.bin with the DDR firmware
blobs tacked on at the end, and the sizes and positions of those blobs
then updated via the binman syms mechanism.

This file, u-boot-spl-ddr.bin, is then passed through mkimage to compute
and generate the imx-specific header, resulting in the final spl.bin.

Parallel to that, U-Boot proper and its .dtb along with ATF/bl31.bin is
wrapped in an itb image.

And finally, spl.bin and u-boot.itb are concatenated, with u-boot.itb
landing on a known offset, to produce the final "flash.bin", which can
then be written to eMMC (user or boot partition) or even booted over usb
with uuu. So far so good.

Currently, the spl_imx_romapi.c contains a somewhat delicate
tiptoeing-around algorithm for determining the size of the itb, in the
case where we're booting over USB. (1) read from the stream 1K at a time
looking for the 0xd00dfeed marker. (2) if that was found too close to
the end of the 1K block we just fetched so we don't have a full struct
fdt_header, we fetch another 1K. (3) So now we have a struct fdt_header
and can thus read the .totalsize member, so now we can go on and read
from the stream until we've read that much in total. (4) But that just
gives us the size of the DTB structure; the itb is built with "external
data", so now we abuse spl_load_simple_fit() and call it twice, the
first time with some extra private data that make the .read callback
stash the maximum offset it ever saw while most likely also copying
garbage (never initialized RAM) to whatever the loadaddr= properties
specify, then use that info to actually read that much data from the usb
stream so we now do have a full, including all the external data, FIT
image at CONFIG_SPL_IMX_ROMAPI_LOADADDR, and then do
spl_load_simple_fit() again.

Now I have two ideas: First, all of this complexity could go away if we
could just do

binman_sym_declare(ulong, itb, size);

in spl_imx_romapi.c. But that fails with

binman: Section '/binman/u-boot-spl-ddr': Symbol '_binman_itb_prop_size'
   in entry '/binman/u-boot-spl-ddr/u-boot-spl/u-boot-spl-nodtb': Entry
'itb' not found in list

So I know that tools/binman/binman.rst says that binman currently
doesn't support images that depend on each other, but as can be seen
above, imx8mp actually defines several images that do depend on each other:

  u-boot-spl-ddr.bin <- spl.bin <---\
              u-boot.itb <----------/

Perhaps this just works by chance, because binman happens to build the
images in the order defined in the binman node. I want to add a new

       u-boot-spl-ddr.bin <- spl.bin <---\
           v                              flash.bin
        u-boot.itb <---------------------/

and I don't mind if one has to manually do a topological sort of
subnodes of the binman node [so this would mean moving the itb node to
the top]. Or we could introduce an

  image-deps = <&itb>;

property and let binman do the topological sorting for us. Regardless,
obviously some work on the python side would be needed; perhaps (and I'm
really not familiar with the binman code) Entry_section should grow an
".external_entries" member that could be populated from such an
image-deps property, and then LookupSymbol() would need to be taught to
also look through .external_entries - only allowing prop_name==size for

And now to the second idea: If we could to this, then we could
definitely also do

typedef struct { uchar x[32]; } sha256_digest;
binman_sym_declare(sha256_digest, itb, sha256);

and teach LookupSymbol also to handle size==32 and prop_name=='sha256'
(I guess the pack format would be 32B). And then SPL could verify the
whole ITB payload with just a single sha256 call, and one wouldn't have
to deal with all the complexity of FIT image verification in SPL and
code size constraints and whatnot. This hash would be baked into
u-boot-spl-ddr.bin before mkimage is invoked to produce the imx header
and possibly HAB signature etc., so we do have chain of trust preserved.

Thoughts? Any pointers on how I could start doing that external_entries


More information about the U-Boot mailing list