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

Tom Rini trini at konsulko.com
Thu May 14 19:42:29 CEST 2026


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)) {
+		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