aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorTom Rini2024-02-29 09:24:49 -0500
committerTom Rini2024-02-29 09:24:49 -0500
commitea3348ebc215d2a9d6dd14f40fb7e8c86dc45e4a (patch)
tree095062630056cd16bd398e01d896c43b0d089090 /common
parentcfc3e1db499d7d4307559cc911aa914dd131f945 (diff)
parent2b71470628c035ce3ccc76d12e50bdc453bdbc93 (diff)
Merge patch series "Handoff bloblist from previous boot stage"
Raymond Mao <raymond.mao@linaro.org> says: This patch set adds/adapts a few bloblist APIs and implements Arm arch custom function to retrieve the bloblist (aka. Transfer List) from previous loader via boot arguments when BLOBLIST option is enabled and all boot arguments are compliant to the register conventions defined in the Firmware Handoff spec v0.9. If an arch wishes to have different behaviors for loading bloblist from the previous boot stage, it is required to implement the custom function xferlist_from_boot_arg().
Diffstat (limited to 'common')
-rw-r--r--common/bloblist.c85
-rw-r--r--common/board_f.c9
2 files changed, 67 insertions, 27 deletions
diff --git a/common/bloblist.c b/common/bloblist.c
index 2d373910b6d..ad06d7a1795 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -384,7 +384,7 @@ int bloblist_check(ulong addr, uint size)
return log_msg_ret("Bad magic", -ENOENT);
if (hdr->version != BLOBLIST_VERSION)
return log_msg_ret("Bad version", -EPROTONOSUPPORT);
- if (!hdr->total_size || (size && hdr->total_size != size))
+ if (!hdr->total_size || (size && hdr->total_size > size))
return log_msg_ret("Bad total size", -EFBIG);
if (hdr->used_size > hdr->total_size)
return log_msg_ret("Bad used size", -ENOENT);
@@ -472,13 +472,28 @@ void bloblist_show_list(void)
}
}
-void bloblist_reloc(void *to, uint to_size, void *from, uint from_size)
+int bloblist_reloc(void *to, uint to_size)
{
struct bloblist_hdr *hdr;
- memcpy(to, from, from_size);
+ if (to_size < gd->bloblist->total_size)
+ return -ENOSPC;
+
+ memcpy(to, gd->bloblist, gd->bloblist->total_size);
hdr = to;
hdr->total_size = to_size;
+ gd->bloblist = to;
+
+ return 0;
+}
+
+/*
+ * Weak default function for getting bloblist from boot args.
+ */
+int __weak xferlist_from_boot_arg(ulong __always_unused addr,
+ ulong __always_unused size)
+{
+ return -ENOENT;
}
int bloblist_init(void)
@@ -486,32 +501,43 @@ int bloblist_init(void)
bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED);
int ret = -ENOENT;
ulong addr, size;
- bool expected;
-
- /**
- * We don't expect to find an existing bloblist in the first phase of
- * U-Boot that runs. Also we have no way to receive the address of an
- * allocated bloblist from a previous stage, so it must be at a fixed
+ /*
+ * If U-Boot is not in the first phase, an existing bloblist must be
+ * at a fixed address.
+ */
+ bool from_addr = fixed && !u_boot_first_phase();
+ /*
+ * If U-Boot is in the first phase that an arch custom routine should
+ * install the bloblist passed from previous loader to this fixed
* address.
*/
- expected = fixed && !u_boot_first_phase();
+ bool from_boot_arg = fixed && u_boot_first_phase();
+
if (spl_prev_phase() == PHASE_TPL && !IS_ENABLED(CONFIG_TPL_BLOBLIST))
- expected = false;
+ from_addr = false;
if (fixed)
addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
CONFIG_BLOBLIST_ADDR);
size = CONFIG_BLOBLIST_SIZE;
- if (expected) {
+
+ if (from_boot_arg)
+ ret = xferlist_from_boot_arg(addr, size);
+ else if (from_addr)
ret = bloblist_check(addr, size);
- if (ret) {
- log_warning("Expected bloblist at %lx not found (err=%d)\n",
- addr, ret);
- } else {
- /* Get the real size, if it is not what we expected */
- size = gd->bloblist->total_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);
@@ -519,7 +545,8 @@ int bloblist_init(void)
return log_msg_ret("alloc", -ENOMEM);
addr = map_to_sysmem(ptr);
} else if (!fixed) {
- return log_msg_ret("!fixed", ret);
+ return log_msg_ret("BLOBLIST_FIXED is not enabled",
+ ret);
}
log_debug("Creating new bloblist size %lx at %lx\n", size,
addr);
@@ -532,6 +559,11 @@ int bloblist_init(void)
return log_msg_ret("ini", ret);
gd->flags |= GD_FLG_BLOBLIST_READY;
+#ifdef DEBUG
+ bloblist_show_stats();
+ bloblist_show_list();
+#endif
+
return 0;
}
@@ -542,3 +574,14 @@ int bloblist_maybe_init(void)
return 0;
}
+
+int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig)
+{
+ if (rzero || rsig != (BLOBLIST_MAGIC | BLOBLIST_REGCONV_VER) ||
+ rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) {
+ gd->bloblist = NULL; /* Reset the gd bloblist pointer */
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/common/board_f.c b/common/board_f.c
index 442b8349d08..7e313691028 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -706,13 +706,10 @@ static int reloc_bloblist(void)
return 0;
}
if (gd->new_bloblist) {
- int size = CONFIG_BLOBLIST_SIZE;
-
debug("Copying bloblist from %p to %p, size %x\n",
- gd->bloblist, gd->new_bloblist, size);
- bloblist_reloc(gd->new_bloblist, CONFIG_BLOBLIST_SIZE_RELOC,
- gd->bloblist, size);
- gd->bloblist = gd->new_bloblist;
+ gd->bloblist, gd->new_bloblist, gd->bloblist->total_size);
+ return bloblist_reloc(gd->new_bloblist,
+ CONFIG_BLOBLIST_SIZE_RELOC);
}
#endif