summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/lib/xferlist.c12
-rw-r--r--common/Kconfig14
-rw-r--r--common/bloblist.c80
-rw-r--r--common/board_f.c24
-rw-r--r--configs/vexpress_fvp_bloblist_defconfig2
-rw-r--r--doc/board/armltd/vexpress64.rst4
-rw-r--r--include/bloblist.h16
7 files changed, 87 insertions, 65 deletions
diff --git a/arch/arm/lib/xferlist.c b/arch/arm/lib/xferlist.c
index f9c5d88bd47..6425936d354 100644
--- a/arch/arm/lib/xferlist.c
+++ b/arch/arm/lib/xferlist.c
@@ -8,18 +8,16 @@
#include <bloblist.h>
#include "xferlist.h"
-int xferlist_from_boot_arg(ulong addr, ulong size)
+int xferlist_from_boot_arg(ulong *addr)
{
int ret;
- ret = bloblist_check(saved_args[3], size);
- if (ret)
- return ret;
-
ret = bloblist_check_reg_conv(saved_args[0], saved_args[2],
- saved_args[1]);
+ saved_args[1], saved_args[3]);
if (ret)
return ret;
- return bloblist_reloc((void *)addr, size);
+ *addr = bloblist_get_base();
+
+ return 0;
}
diff --git a/common/Kconfig b/common/Kconfig
index 7b2db46ef06..1d6de8badf7 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1066,11 +1066,15 @@ config BLOBLIST_ALLOC
specify a fixed address on systems where this is unknown or can
change at runtime.
-config BLOBLIST_PASSAGE
- bool "Use bloblist in-place"
+config BLOBLIST_PASSAGE_MANDATORY
+ bool "Use bloblist in-place mandatorily"
help
- Use a bloblist in the incoming standard passage. The size is detected
- automatically so CONFIG_BLOBLIST_SIZE can be 0.
+ By default U-Boot will use a bloblist in the incoming standard passage.
+ This option controls whether U-Boot tries to load a static bloblist or
+ allocate one if a valid incoming bloblist does not exist.
+ Select this option to mark incoming standard passage as mandatory and
+ U-Boot will report an error when a valid incoming bloblist does not
+ exist.
endchoice
@@ -1086,7 +1090,7 @@ config BLOBLIST_ADDR
config BLOBLIST_SIZE
hex "Size of bloblist"
- default 0x0 if BLOBLIST_PASSAGE
+ default 0x0 if BLOBLIST_PASSAGE_MANDATORY
default 0x400
help
Sets the size of the bloblist in bytes. This must include all
diff --git a/common/bloblist.c b/common/bloblist.c
index 31ba0311090..6e4f020d7c4 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -505,8 +505,7 @@ int bloblist_reloc(void *to, uint to_size)
/*
* Weak default function for getting bloblist from boot args.
*/
-int __weak xferlist_from_boot_arg(ulong __always_unused addr,
- ulong __always_unused size)
+int __weak xferlist_from_boot_arg(ulong __always_unused *addr)
{
return -ENOENT;
}
@@ -514,37 +513,46 @@ int __weak xferlist_from_boot_arg(ulong __always_unused addr,
int bloblist_init(void)
{
bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED);
- int ret = -ENOENT;
+ int ret = 0;
ulong addr = 0, size;
- /*
- * 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 (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 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 the current boot stage is the first phase of U-Boot, then an
- * architecture-specific routine should be used to handle the bloblist
- * passed from the previous boot loader
- */
- if (xpl_is_first_phase() && !IS_ENABLED(CONFIG_BLOBLIST_ALLOC))
- ret = xferlist_from_boot_arg(addr, size);
- else if (from_addr)
- ret = bloblist_check(addr, 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 -ENOENT;
- if (ret)
- log_warning("Bloblist at %lx not found (err=%d)\n",
- addr, ret);
- else
- /* Get the real size */
- size = gd->bloblist->total_size;
+ 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 (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) {
/*
@@ -569,6 +577,7 @@ int bloblist_init(void)
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;
@@ -589,10 +598,11 @@ int bloblist_maybe_init(void)
return 0;
}
-int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig)
+int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist)
{
u64 version = BLOBLIST_REGCONV_VER;
ulong sigval;
+ int ret;
if ((IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_SPL_BUILD)) ||
(IS_ENABLED(CONFIG_SPL_64BIT) && IS_ENABLED(CONFIG_SPL_BUILD))) {
@@ -603,8 +613,14 @@ int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig)
((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_32));
}
- if (rzero || rsig != sigval ||
- rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) {
+ if (rzero || rsig != sigval)
+ return -EIO;
+
+ ret = bloblist_check(xlist, 0);
+ if (ret)
+ return ret;
+
+ if (rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) {
gd->bloblist = NULL; /* Reset the gd bloblist pointer */
return -EIO;
}
diff --git a/common/board_f.c b/common/board_f.c
index 6c5c3bfab48..2912320054f 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -624,11 +624,14 @@ static int reserve_stacks(void)
static int reserve_bloblist(void)
{
#ifdef CONFIG_BLOBLIST
+ ulong size = bloblist_get_total_size();
+
+ if (size < CONFIG_BLOBLIST_SIZE_RELOC)
+ size = CONFIG_BLOBLIST_SIZE_RELOC;
+
/* Align to a 4KB boundary for easier reading of addresses */
- gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp -
- CONFIG_BLOBLIST_SIZE_RELOC, 0x1000);
- gd->boardf->new_bloblist = map_sysmem(gd->start_addr_sp,
- CONFIG_BLOBLIST_SIZE_RELOC);
+ gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - size, 0x1000);
+ gd->boardf->new_bloblist = map_sysmem(gd->start_addr_sp, size);
#endif
return 0;
@@ -698,11 +701,14 @@ static int reloc_bloblist(void)
return 0;
}
if (gd->boardf->new_bloblist) {
- debug("Copying bloblist from %p to %p, size %x\n",
- gd->bloblist, gd->boardf->new_bloblist,
- gd->bloblist->total_size);
- return bloblist_reloc(gd->boardf->new_bloblist,
- CONFIG_BLOBLIST_SIZE_RELOC);
+ ulong size = bloblist_get_total_size();
+
+ if (size < CONFIG_BLOBLIST_SIZE_RELOC)
+ size = CONFIG_BLOBLIST_SIZE_RELOC;
+
+ debug("Copying bloblist from %p to %p, size %lx\n",
+ gd->bloblist, gd->boardf->new_bloblist, size);
+ return bloblist_reloc(gd->boardf->new_bloblist, size);
}
#endif
diff --git a/configs/vexpress_fvp_bloblist_defconfig b/configs/vexpress_fvp_bloblist_defconfig
index dcc87db8723..4d52b96202b 100644
--- a/configs/vexpress_fvp_bloblist_defconfig
+++ b/configs/vexpress_fvp_bloblist_defconfig
@@ -1,5 +1,5 @@
#include <configs/vexpress_fvp_defconfig>
CONFIG_BLOBLIST=y
-CONFIG_BLOBLIST_PASSAGE=y
+CONFIG_BLOBLIST_PASSAGE_MANDATORY=y
CONFIG_BLOBLIST_SIZE_RELOC=0x10000
diff --git a/doc/board/armltd/vexpress64.rst b/doc/board/armltd/vexpress64.rst
index 4dadadb53dc..a732fac899d 100644
--- a/doc/board/armltd/vexpress64.rst
+++ b/doc/board/armltd/vexpress64.rst
@@ -53,8 +53,8 @@ predefined bloblist at a specified address, dynamically allocating memory for a
bloblist, or utilizing a standard passage-provided bloblist with automatic size
detection.
-By default, ``vexpress_fvp_bloblist_defconfig`` uses the standard passage method
-(CONFIG_BLOBLIST_PASSAGE) because TF-A provides a Transfer List in non-secure
+By default, ``vexpress_fvp_bloblist_defconfig`` uses the standard passage method mandatorily
+(CONFIG_BLOBLIST_PASSAGE_MANDATORY) because TF-A provides a Transfer List in non-secure
memory that U-Boot can utilise. This Bloblist, which is referred to as a Transfer List in
TF-A, contains all necessary data for the handoff process, including DT and ACPI
tables.
diff --git a/include/bloblist.h b/include/bloblist.h
index 98aacf52733..f32faf78560 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -467,9 +467,8 @@ int bloblist_reloc(void *to, uint to_size);
* If CONFIG_BLOBLIST_ALLOC is selected, it allocates memory for a bloblist of
* size CONFIG_BLOBLIST_SIZE.
*
- * If CONFIG_BLOBLIST_PASSAGE is selected, it uses the bloblist in the incoming
- * standard passage. The size is detected automatically so CONFIG_BLOBLIST_SIZE
- * can be 0.
+ * If CONFIG_BLOBLIST_PASSAGE_MANDATORY is selected, bloblist in the incoming
+ * standard passage is mandatorily required.
*
* Sets GD_FLG_BLOBLIST_READY in global_data flags on success
*
@@ -501,19 +500,18 @@ static inline int bloblist_maybe_init(void)
* @rfdt: Register that holds the FDT base address.
* @rzero: Register that must be zero.
* @rsig: Register that holds signature and register conventions version.
+ * @xlist: Register that holds the transfer list.
* Return: 0 if OK, -EIO if the bloblist is not compliant to the register
* conventions.
*/
-int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig);
+int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist);
/**
- * xferlist_from_boot_arg() - Get bloblist from the boot args and relocate it
- * to the specified address.
+ * xferlist_from_boot_arg() - Get bloblist from the boot args.
*
- * @addr: Address for the bloblist
- * @size: Size of space reserved for the bloblist
+ * @addr: Address of the bloblist
* Return: 0 if OK, else on error
*/
-int xferlist_from_boot_arg(ulong addr, ulong size);
+int xferlist_from_boot_arg(ulong *addr);
#endif /* __BLOBLIST_H */