[U-Boot] passing info from SPL to U-Boot

Simon Glass sjg at chromium.org
Thu Mar 14 10:02:29 UTC 2019


Hi Heiko,

On Tue, 12 Mar 2019 at 02:50, Heiko Schocher <hs at denx.de> wrote:
>
> Hello Simon, Tom,
>
> Am 12.03.2019 um 09:21 schrieb Heiko Schocher:
> > Hello Simon, Tom,
> >
> > I am just stumbeld on an am437x basd board over the problem to pass
> > the bootmode from SPL to U-Boot. On am437x the bootmode info get
> > overwritten from SPL stack, and I need this info in U-Boot.
> >
> > Hack would be to move SPL stack to another address, but we loose
> > than 0xa000 size for stack ... I do not want to go this way..
> >
> > I thought gd info is passed from SPL to U-Boot, but this is not the case!
> >
> > Looking into
> >
> > ...
> >   75         bic     r0, r0, #7      /* 8-byte alignment for ABI compliance */
> >   76         mov     sp, r0
> >   77         bl      board_init_f_alloc_reserve
> >   78         mov     sp, r0
> >   79         /* set up gd here, outside any C code */
> >   80         mov     r9, r0
> >   81         bl      board_init_f_init_reserve
> >
> > and common/init/board_init.c:
> >
> >   99 void board_init_f_init_reserve(ulong base)
> > 100 {
> > 101         struct global_data *gd_ptr;
> > 102
> > 103         /*
> > 104          * clear GD entirely and set it up.
> > 105          * Use gd_ptr, as gd may not be properly set yet.
> > 106          */
> > 107
> > 108         gd_ptr = (struct global_data *)base;
> > 109         /* zero the area */
> > 110         memset(gd_ptr, '\0', sizeof(*gd));
> > 111         /* set GD unless architecture did it already */
> > 112 #if !defined(CONFIG_ARM)
> > 113         arch_setup_gd(gd_ptr);
> > 114 #endif
> >
> > gd is always initialized with zeros, no chance for passing infos from
> > SPL to U-Boot...
> >
> > I really thought, that gd_t was intentionally designed for passing data
> > between different U-Boot states, but looking into gd_t definiton in
> > include/asm-generic/global_data.h it is a big ifdef mess and not useable
> > as an "API" between TPL/SPL and U-Boot ...
> >
> > I thought also, that SPL detects for example ramsize and than passes
> > this info to U-Boot ...
> >
> > But Ok, I found "common/init/handoff.c" which seems now the way to go, but:
> >
> > ./common/board_f.c
> >
> >   281 static int setup_spl_handoff(void)
> >   282 {
> >   283 #if CONFIG_IS_ENABLED(HANDOFF)
> >   284         gd->spl_handoff = bloblist_find(BLOBLISTT_SPL_HANDOFF,
> >   285                                         sizeof(struct spl_handoff));
> >   286         debug("Found SPL hand-off info %p\n", gd->spl_handoff);
> >   287 #endif
> >   288
> >   289         return 0;
> >   290 }
> >
> > There is gd->spl_handoff used ... how could this work at least on arm,
> > if gd is set to zeros on init ?
> >
> > Do I miss something obvious?
>
> Sorry for being so stupid, with:
>
> common/board_f.c
>
>   853 #ifdef CONFIG_BLOBLIST
>   854         bloblist_init,
>   855 #endif
>   856         setup_spl_handoff,
>
> and common/bloblist.c
>
> 216 int bloblist_init(void)
> 217 {
> 218         bool expected;
> 219         int ret = -ENOENT;
> 220
> 221         /**
> 222          * Wed expect to find an existing bloblist in the first phase of U-Boot
> 223          * that runs
> 224          */
> 225         expected = !u_boot_first_phase();
> 226         if (expected)
> 227                 ret = bloblist_check(CONFIG_BLOBLIST_ADDR,
> 228                                      CONFIG_BLOBLIST_SIZE);
>
> gd->spl_handoff gets setup through bloblist_find() ...
>
> But beside sandbox there is no current user currently, or?
>
> $ grep -lr BLOBLIST_ADDR .
> ./test/bloblist.c
> ./include/bloblist.h
> ./common/bloblist.c
> ./common/Kconfig
> ./board/sandbox/README.sandbox
> $

Yes that's right, it is not used outside sandbox, although there are
patches to use it on x86.

I think it is a reasonable idea to allow the gd region to pass from
TPL -> SPL -> U-Boot. But we'll need to remove use of
CONFIG_IS_ENABLED(), or put shared things at the beginning of the
structure.

We need the concept of 'am I the first thing to run'. This is
implemented in bloblist as u_boot_first_phase() - see spl.h. If this
is true, we must set up the data structure. If false we must find one
set up by a previous phase and use it. Bloblist handles this, but
perhaps gd could as well?

Also consider the scenario where there is a read-only TPL programmed
in manufacture that never changes, and a read-write SPL +  U-Boot that
can be upgraded in the field. In this case they may eventually end up
being built with different versions of U-Boot. The bloblist structure
is intended to handle this by at least checking that the size matches.

Related, I feel that we should figure out how to use registers to pass
addresses from SPL to U-Boot. On ARM we could use r0 to pass the value
of gd, perhaps.

Regards,
Simon


More information about the U-Boot mailing list