[PATCH 3/3] bloblist: Rework bloblist_init and bloblist_maybe_init

Raymond Mao raymondmaoca at gmail.com
Fri May 15 17:05:47 CEST 2026


Hi Tom,

On Thu, May 14, 2026 at 1:55 PM Tom Rini <trini at konsulko.com> wrote:
>
> With bloblist, we need to both see if one already exists as well as
> create one if it does not. However, the current implementation leads to
> odd cases where we attempt to create a bloblist before this is possible
> and have things be overly complicated when we are given one to work
> with.
>
> This reworks things to instead have a bloblist_exists function, which as
> the name implies checks for an existing bloblist. This is used in
> the case of booting, to see if we have one and in turn if we have a
> device tree there as well as in the bloblist_init function to see if we
> need to do anything.
>
> In practical details, we move the logic from bloblist_init that was
> checking for a bloblist to the new bloblist_exists function and then can
> clarify the logic as it is much easier to state when we know we do not
> have one rather than all the ways we might have one. Then we have the
> locations that set gd->bloblist now also set the GD_FLG_BLOBLIST_READY
> flag.
>
> Signed-off-by: Tom Rini <trini at konsulko.com>
> ---
>  common/bloblist.c  | 144 +++++++++++++++++++++++----------------------
>  common/board_f.c   |   4 +-
>  include/bloblist.h |  32 +++++-----
>  lib/fdtdec.c       |  15 ++---
>  4 files changed, 96 insertions(+), 99 deletions(-)
>
> diff --git a/common/bloblist.c b/common/bloblist.c
> index 09afdd1f96b4..51ae9cc50a5f 100644
> --- a/common/bloblist.c
> +++ b/common/bloblist.c
> @@ -448,6 +448,7 @@ int bloblist_new(ulong addr, uint size, uint flags, uint align_log2)
>         hdr->align_log2 = align_log2 ? align_log2 : BLOBLIST_BLOB_ALIGN_LOG2;
>         hdr->chksum = 0;
>         gd->bloblist = hdr;
> +       gd->flags |= GD_FLG_BLOBLIST_READY;
>
>         return 0;
>  }
> @@ -475,6 +476,7 @@ int bloblist_check(ulong addr, uint size)
>                 return log_msg_ret("Bad checksum", -EIO);
>         }
>         gd->bloblist = hdr;
> +       gd->flags |= GD_FLG_BLOBLIST_READY;
>
>         return 0;
>  }
> @@ -576,90 +578,88 @@ int __weak xferlist_from_boot_arg(ulong __always_unused *addr)
>         return -ENOENT;
>  }
>
> -int bloblist_init(void)
> +bool bloblist_exists(void)
>  {
> -       bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED);
> -       int ret = 0;
> -       ulong addr = 0, size;
> +       int ret;
> +       ulong addr = 0;
>
>         /* Check if a valid transfer list passed in */
> -       if (!xferlist_from_boot_arg(&addr)) {
> -               size = bloblist_get_total_size();
> -       } else {
> -               /*
> -                * If U-Boot is not in the first phase, an existing bloblist must
> -                * be at a fixed address.
> -                */
> -               bool from_addr = fixed && !xpl_is_first_phase();
> -
> -               /*
> -                * If Firmware Handoff is mandatory but no transfer list is
> -                * observed, report it as an error.
> -                */
> -               if (IS_ENABLED(CONFIG_BLOBLIST_PASSAGE_MANDATORY))
> -                       return -ENOENT;
> -
> -               ret = -ENOENT;
> -
> -               if (xpl_prev_phase() == PHASE_TPL &&
> -                   !IS_ENABLED(CONFIG_TPL_BLOBLIST))
> -                       from_addr = false;
> -               if (fixed)
> -                       addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
> -                                             CONFIG_BLOBLIST_ADDR);
> -               size = CONFIG_BLOBLIST_SIZE;
> -
> -               if (from_addr)
> -                       ret = bloblist_check(addr, size);
> +       if (!xferlist_from_boot_arg(&addr))
> +               goto found;
>
> -               if (ret)
> -                       log_debug("Bloblist at %lx not found (err=%d)\n",
> -                                 addr, ret);
> -               else
> -                       /* Get the real size */
> -                       size = gd->bloblist->total_size;
> -       }
> +       /*
> +        * If Firmware Handoff is mandatory but no transfer list is
> +        * observed, report it as an error.
> +        */
> +       if (IS_ENABLED(CONFIG_BLOBLIST_PASSAGE_MANDATORY))
> +               return false;
>
> -       if (ret) {
> -               /*
> -                * If we don't have a bloblist from a fixed address, or the one
> -                * in the fixed address is not valid. we must allocate the
> -                * memory for it now.
> -                */
> -               if (CONFIG_IS_ENABLED(BLOBLIST_ALLOC)) {
> -                       void *ptr = memalign(BLOBLIST_ALIGN, size);
> -
> -                       if (!ptr)
> -                               return log_msg_ret("alloc", -ENOMEM);
> -                       addr = map_to_sysmem(ptr);
> -               } else if (!fixed) {
> -                       return log_msg_ret("BLOBLIST_FIXED is not enabled",
> -                                          ret);
> -               }
> -               log_debug("Creating new bloblist size %lx at %lx\n", size,
> -                         addr);
> -               ret = bloblist_new(addr, size, 0, 0);
> -       } else {
> -               log_debug("Found existing bloblist size %lx at %lx\n", size,
> -                         addr);
> -       }
> +       /*
> +        * We have checked for a valid transfer list being passed. At this
> +        * point, if we do not have a fixed address for the bloblist, we cannot
> +        * be provided with one.
> +        */
> +       if (xpl_is_first_phase() || !IS_ENABLED(CONFIG_BLOBLIST_FIXED))
> +               return false;
>
> -       if (ret)
> -               return log_msg_ret("ini", ret);
> -       gd->flags |= GD_FLG_BLOBLIST_READY;
> +       /*
> +        * Check for a valid list as the configured address.
> +        */
> +       addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
> +                             CONFIG_BLOBLIST_ADDR);
> +       ret = bloblist_check(addr, CONFIG_BLOBLIST_SIZE);
> +       if (!ret)
> +               goto found;
> +
> +       log_debug("Bloblist at %lx not found (err=%d)\n", addr, ret);
> +       return false;
>
> +found:
>  #ifdef DEBUG
>         bloblist_show_stats();
>         bloblist_show_list();
>  #endif
> -
> -       return 0;
> +       return true;
>  }
>
> -int bloblist_maybe_init(void)
> +int bloblist_init(void)
>  {
> -       if (CONFIG_IS_ENABLED(BLOBLIST) && !(gd->flags & GD_FLG_BLOBLIST_READY))
> -               return bloblist_init();
> +       int ret;
> +       ulong addr = 0, size = CONFIG_BLOBLIST_SIZE;
> +
> +       if (gd->flags & GD_FLG_BLOBLIST_READY) {
> +               log_debug("Found existing bloblist size %x at %p\n",
> +                         gd->bloblist->total_size, gd->bloblist);
> +               return 0;
> +       }
> +
> +       /*
> +        * If Firmware Handoff is mandatory but no transfer list has been
> +        * observed by fdtdec_setup, report it as an error.
> +        */
> +       if (IS_ENABLED(CONFIG_BLOBLIST_PASSAGE_MANDATORY))
> +               return -ENOENT;
> +
> +       /*
> +        * If we don't have an existing bloblist, we either need
> +        * to allocate one now, or initialize the fixed address
> +        * space as a bloblist.
> +        */
> +       if (CONFIG_IS_ENABLED(BLOBLIST_ALLOC)) {
> +               void *ptr = memalign(BLOBLIST_ALIGN, size);
> +
> +               if (!ptr)
> +                       return log_msg_ret("alloc", -ENOMEM);
> +               addr = map_to_sysmem(ptr);
> +       } else
> +               addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
> +                                     CONFIG_BLOBLIST_ADDR);
> +
> +       log_debug("Creating new bloblist size %lx at %lx\n", size,
> +                 addr);
> +       ret = bloblist_new(addr, size, 0, 0);
> +       if (ret)
> +               return log_msg_ret("ini", ret);
>
>         return 0;
>  }
> @@ -687,7 +687,9 @@ int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist)
>                 return ret;
>
>         if (rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) {
> -               gd->bloblist = NULL;  /* Reset the gd bloblist pointer */
> +               /* Remove this bloblist from gd */
> +               gd->bloblist = NULL;
> +               gd->flags &= ~GD_FLG_BLOBLIST_READY;
>                 return -EIO;
>         }
>
> diff --git a/common/board_f.c b/common/board_f.c
> index ce87c619e680..c39e3b940d3b 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -894,7 +894,9 @@ static void initcall_run_f(void)
>         INITCALL(log_init);
>         INITCALL(initf_bootstage); /* uses its own timer, so does not need DM */
>         INITCALL(event_init);
> -       INITCALL(bloblist_maybe_init);
> +#if CONFIG_IS_ENABLED(BLOBLIST)
> +       INITCALL(bloblist_init);
> +#endif
>         INITCALL(setup_spl_handoff);
>  #if CONFIG_IS_ENABLED(CONSOLE_RECORD_INIT_F)
>         INITCALL(console_record_init);
> diff --git a/include/bloblist.h b/include/bloblist.h
> index e67b2a76358d..4c5787729654 100644
> --- a/include/bloblist.h
> +++ b/include/bloblist.h
> @@ -488,10 +488,24 @@ const char *bloblist_tag_name(enum bloblist_tag_t tag);
>   */
>  int bloblist_reloc(void *to, uint to_size);
>
> +/**
> + * bloblist_exists() - Check for the prior existence of a bloblist
> + *
> + * This will check for a transfer list having been passed via standard
> + * convention. If CONFIG_BLOBLIST_PASSAGE_MANDATORY is selected and one is not
> + * found, we return false.
> + *
> + * If CONFIG_BLOBLIST_FIXED is selected, it uses CONFIG_BLOBLIST_ADDR and
> + * CONFIG_BLOBLIST_SIZE to check for a bloblist.
> + *
> + * Return: true if found, false if not
> + */
> +bool bloblist_exists(void);
> +
>  /**
>   * bloblist_init() - Init the bloblist system with a single bloblist
>   *
> - * This locates and sets up the blocklist for use.
> + * This creates a bloblist for use, if not already found.
>   *
>   * If CONFIG_BLOBLIST_FIXED is selected, it uses CONFIG_BLOBLIST_ADDR and
>   * CONFIG_BLOBLIST_SIZE to set up a bloblist for use by U-Boot.
> @@ -508,22 +522,6 @@ int bloblist_reloc(void *to, uint to_size);
>   */
>  int bloblist_init(void);
>
> -#if CONFIG_IS_ENABLED(BLOBLIST)
> -/**
> - * bloblist_maybe_init() - Init the bloblist system if not already done
> - *
> - * Calls bloblist_init() if the GD_FLG_BLOBLIST_READY flag is not set
> - *
> - * Return: 0 if OK, -ve on error
> - */
> -int bloblist_maybe_init(void);
> -#else
> -static inline int bloblist_maybe_init(void)
> -{
> -       return 0;
> -}
> -#endif /* BLOBLIST */
> -
>  /**
>   * bloblist_check_reg_conv() - Check whether the bloblist is compliant to
>   *                            the register conventions according to the
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index c67b6e8c133e..7fd7f7ff01e5 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -1822,17 +1822,12 @@ int fdtdec_setup(void)
>         int ret = -ENOENT;
>
>         /*
> -        * If allowing a bloblist, check that first. There was discussion about
> -        * adding an OF_BLOBLIST Kconfig, but this was rejected.
> -        *
> -        * The necessary test is whether the previous phase passed a bloblist,
> -        * not whether this phase creates one.
> +        * If allowing a bloblist, check that first. The necessary test is
> +        * whether the previous phase passed a bloblist, not whether this phase
> +        * creates one.
>          */
> -       if (CONFIG_IS_ENABLED(BLOBLIST) &&
> -           (xpl_prev_phase() != PHASE_TPL ||
> -            IS_ENABLED(CONFIG_TPL_BLOBLIST))) {
> -               ret = bloblist_maybe_init();
> -               if (!ret) {
> +       if (CONFIG_IS_ENABLED(BLOBLIST) && (xpl_prev_phase() != PHASE_TPL)) {

I think this change drops the TPL-provided blobs on TPL->SPL boots.
When TPL_BLOBLIST is selected, the next phase starts with
xpl_prev_phase() == PHASE_TPL.
This new guard now skips bloblist_exists(), so gd->flags never gets
GD_FLG_BLOBLIST_READY; the later bloblist_init() in common/spl/spl.c
then creates a fresh bloblist and overwrites the fixed-address list
from TPL.

Regards,
Raymond

> +               if (bloblist_exists()) {
>                         gd->fdt_blob = bloblist_find(BLOBLISTT_CONTROL_FDT, 0);
>                         if (gd->fdt_blob) {
>                                 gd->fdt_src = FDTSRC_BLOBLIST;
> --
> 2.43.0
>


More information about the U-Boot mailing list