Merge patch series "Clean up bloblist initialization"

Tom Rini <trini@konsulko.com> says:

This series does a few small but important cleanups to how we check for,
and initialize a bloblist. The first thing is that the way things are
done today, our HANDOFF code can only work with a fixed bloblist
location, so express that requirement in Kconfig. Next, we demote the
scary message about "Bloblist at ... not found" to a debug because we
most often see that because the bloblist doesn't (and can't) exist yet.
Finally, we remove bloblist_maybe_init and split this in to an exists
and a real init. This results in practically no growth (between 8 bytes
growth to 12 bytes saved, with some outliers saving much more thanks to
knowing it's impossible to have been passed a bloblist yet). This also
cleans up some of the code around checking for / knowing about a
bloblist existing.

Link: https://lore.kernel.org/r/20260519162225.770071-1-trini@konsulko.com
This commit is contained in:
Tom Rini
2026-06-02 09:30:33 -06:00
10 changed files with 106 additions and 120 deletions
+10 -5
View File
@@ -566,13 +566,18 @@ int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
{
const struct bootdev_ops *ops = bootdev_get_ops(dev);
log_debug("->get_bootflow %s,%x=%p\n", dev->name, iter->part,
ops->get_bootflow);
bootflow_init(bflow, dev, iter->method);
if (!ops->get_bootflow)
return default_get_bootflow(dev, iter, bflow);
return ops->get_bootflow(dev, iter, bflow);
if (ops && ops->get_bootflow) {
log_debug("->get_bootflow %s,%x=%p\n", dev->name, iter->part,
ops->get_bootflow);
return ops->get_bootflow(dev, iter, bflow);
}
log_debug("->get_bootflow %s,%x is unset\n", dev->name, iter->part);
return default_get_bootflow(dev, iter, bflow);
}
int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
+72 -70
View File
@@ -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 (!xferlist_from_boot_arg(&addr))
goto found;
/*
* 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;
/*
* 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;
ret = -ENOENT;
/*
* 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 (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;
/*
* 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;
if (from_addr)
ret = bloblist_check(addr, size);
if (ret)
log_warning("Bloblist at %lx not found (err=%d)\n",
addr, ret);
else
/* Get the real size */
size = gd->bloblist->total_size;
}
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);
}
if (ret)
return log_msg_ret("ini", ret);
gd->flags |= GD_FLG_BLOBLIST_READY;
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;
}
+3 -1
View File
@@ -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);
+1 -1
View File
@@ -220,7 +220,7 @@ source "common/spl/Kconfig.nxp"
config HANDOFF
bool "Pass hand-off information from SPL to U-Boot proper"
depends on BLOBLIST
depends on BLOBLIST_FIXED
help
It is useful to be able to pass information from SPL to U-Boot
proper to preserve state that is known in SPL and is needed in U-Boot.
-4
View File
@@ -37,9 +37,6 @@ static int sata_bootdev_hunt(struct bootdev_hunter *info, bool show)
return 0;
}
struct bootdev_ops sata_bootdev_ops = {
};
static const struct udevice_id sata_bootdev_ids[] = {
{ .compatible = "u-boot,bootdev-sata" },
{ }
@@ -48,7 +45,6 @@ static const struct udevice_id sata_bootdev_ids[] = {
U_BOOT_DRIVER(sata_bootdev) = {
.name = "sata_bootdev",
.id = UCLASS_BOOTDEV,
.ops = &sata_bootdev_ops,
.bind = sata_bootdev_bind,
.of_match = sata_bootdev_ids,
};
-4
View File
@@ -969,9 +969,6 @@ static int ide_bootdev_hunt(struct bootdev_hunter *info, bool show)
return 0;
}
struct bootdev_ops ide_bootdev_ops = {
};
static const struct udevice_id ide_bootdev_ids[] = {
{ .compatible = "u-boot,bootdev-ide" },
{ }
@@ -980,7 +977,6 @@ static const struct udevice_id ide_bootdev_ids[] = {
U_BOOT_DRIVER(ide_bootdev) = {
.name = "ide_bootdev",
.id = UCLASS_BOOTDEV,
.ops = &ide_bootdev_ops,
.bind = ide_bootdev_bind,
.of_match = ide_bootdev_ids,
};
-4
View File
@@ -37,9 +37,6 @@ static int scsi_bootdev_hunt(struct bootdev_hunter *info, bool show)
return 0;
}
struct bootdev_ops scsi_bootdev_ops = {
};
static const struct udevice_id scsi_bootdev_ids[] = {
{ .compatible = "u-boot,bootdev-scsi" },
{ }
@@ -48,7 +45,6 @@ static const struct udevice_id scsi_bootdev_ids[] = {
U_BOOT_DRIVER(scsi_bootdev) = {
.name = "scsi_bootdev",
.id = UCLASS_BOOTDEV,
.ops = &scsi_bootdev_ops,
.bind = scsi_bootdev_bind,
.of_match = scsi_bootdev_ids,
};
-4
View File
@@ -400,9 +400,6 @@ UCLASS_DRIVER(virtio) = {
.per_device_auto = sizeof(struct virtio_dev_priv),
};
struct bootdev_ops virtio_bootdev_ops = {
};
static const struct udevice_id virtio_bootdev_ids[] = {
{ .compatible = "u-boot,bootdev-virtio" },
{ }
@@ -411,7 +408,6 @@ static const struct udevice_id virtio_bootdev_ids[] = {
U_BOOT_DRIVER(virtio_bootdev) = {
.name = "virtio_bootdev",
.id = UCLASS_BOOTDEV,
.ops = &virtio_bootdev_ops,
.bind = virtio_bootdev_bind,
.of_match = virtio_bootdev_ids,
};
+15 -17
View File
@@ -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
+5 -10
View File
@@ -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_phase() > PHASE_TPL)) {
if (bloblist_exists()) {
gd->fdt_blob = bloblist_find(BLOBLISTT_CONTROL_FDT, 0);
if (gd->fdt_blob) {
gd->fdt_src = FDTSRC_BLOBLIST;