Merge patch series "bloblist: refactor xferlist and bloblist"

Tom Rini <trini@konsulko.com> says:

This small series separates "bloblist" and "standard passage" to allow
for these similar concepts to explore solutions to problems without
introduces breaking changes to the other.

Link: https://lore.kernel.org/r/20250220000223.1044376-1-raymond.mao@linaro.org
This commit is contained in:
Tom Rini 2025-02-19 18:49:47 -06:00
commit c33ccc8725
7 changed files with 87 additions and 65 deletions

View file

@ -8,18 +8,16 @@
#include <bloblist.h> #include <bloblist.h>
#include "xferlist.h" #include "xferlist.h"
int xferlist_from_boot_arg(ulong addr, ulong size) int xferlist_from_boot_arg(ulong *addr)
{ {
int ret; int ret;
ret = bloblist_check(saved_args[3], size);
if (ret)
return ret;
ret = bloblist_check_reg_conv(saved_args[0], saved_args[2], ret = bloblist_check_reg_conv(saved_args[0], saved_args[2],
saved_args[1]); saved_args[1], saved_args[3]);
if (ret) if (ret)
return ret; return ret;
return bloblist_reloc((void *)addr, size); *addr = bloblist_get_base();
return 0;
} }

View file

@ -1066,11 +1066,15 @@ config BLOBLIST_ALLOC
specify a fixed address on systems where this is unknown or can specify a fixed address on systems where this is unknown or can
change at runtime. change at runtime.
config BLOBLIST_PASSAGE config BLOBLIST_PASSAGE_MANDATORY
bool "Use bloblist in-place" bool "Use bloblist in-place mandatorily"
help help
Use a bloblist in the incoming standard passage. The size is detected By default U-Boot will use a bloblist in the incoming standard passage.
automatically so CONFIG_BLOBLIST_SIZE can be 0. 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 endchoice
@ -1086,7 +1090,7 @@ config BLOBLIST_ADDR
config BLOBLIST_SIZE config BLOBLIST_SIZE
hex "Size of bloblist" hex "Size of bloblist"
default 0x0 if BLOBLIST_PASSAGE default 0x0 if BLOBLIST_PASSAGE_MANDATORY
default 0x400 default 0x400
help help
Sets the size of the bloblist in bytes. This must include all Sets the size of the bloblist in bytes. This must include all

View file

@ -505,8 +505,7 @@ int bloblist_reloc(void *to, uint to_size)
/* /*
* Weak default function for getting bloblist from boot args. * Weak default function for getting bloblist from boot args.
*/ */
int __weak xferlist_from_boot_arg(ulong __always_unused addr, int __weak xferlist_from_boot_arg(ulong __always_unused *addr)
ulong __always_unused size)
{ {
return -ENOENT; return -ENOENT;
} }
@ -514,29 +513,37 @@ int __weak xferlist_from_boot_arg(ulong __always_unused addr,
int bloblist_init(void) int bloblist_init(void)
{ {
bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED); bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED);
int ret = -ENOENT; int ret = 0;
ulong addr = 0, size; ulong addr = 0, 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 * If U-Boot is not in the first phase, an existing bloblist must
* at a fixed address. * be at a fixed address.
*/ */
bool from_addr = fixed && !xpl_is_first_phase(); bool from_addr = fixed && !xpl_is_first_phase();
if (xpl_prev_phase() == PHASE_TPL && !IS_ENABLED(CONFIG_TPL_BLOBLIST))
/*
* 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; from_addr = false;
if (fixed) if (fixed)
addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
CONFIG_BLOBLIST_ADDR); CONFIG_BLOBLIST_ADDR);
size = CONFIG_BLOBLIST_SIZE; size = CONFIG_BLOBLIST_SIZE;
if (from_addr)
/*
* 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); ret = bloblist_check(addr, size);
if (ret) if (ret)
@ -545,6 +552,7 @@ int bloblist_init(void)
else else
/* Get the real size */ /* Get the real size */
size = gd->bloblist->total_size; size = gd->bloblist->total_size;
}
if (ret) { if (ret) {
/* /*
@ -569,6 +577,7 @@ int bloblist_init(void)
log_debug("Found existing bloblist size %lx at %lx\n", size, log_debug("Found existing bloblist size %lx at %lx\n", size,
addr); addr);
} }
if (ret) if (ret)
return log_msg_ret("ini", ret); return log_msg_ret("ini", ret);
gd->flags |= GD_FLG_BLOBLIST_READY; gd->flags |= GD_FLG_BLOBLIST_READY;
@ -589,10 +598,11 @@ int bloblist_maybe_init(void)
return 0; 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; u64 version = BLOBLIST_REGCONV_VER;
ulong sigval; ulong sigval;
int ret;
if ((IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_SPL_BUILD)) || if ((IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_SPL_BUILD)) ||
(IS_ENABLED(CONFIG_SPL_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)); ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_32));
} }
if (rzero || rsig != sigval || if (rzero || rsig != sigval)
rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) { 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 */ gd->bloblist = NULL; /* Reset the gd bloblist pointer */
return -EIO; return -EIO;
} }

View file

@ -624,11 +624,14 @@ static int reserve_stacks(void)
static int reserve_bloblist(void) static int reserve_bloblist(void)
{ {
#ifdef CONFIG_BLOBLIST #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 */ /* Align to a 4KB boundary for easier reading of addresses */
gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - size, 0x1000);
CONFIG_BLOBLIST_SIZE_RELOC, 0x1000); gd->boardf->new_bloblist = map_sysmem(gd->start_addr_sp, size);
gd->boardf->new_bloblist = map_sysmem(gd->start_addr_sp,
CONFIG_BLOBLIST_SIZE_RELOC);
#endif #endif
return 0; return 0;
@ -698,11 +701,14 @@ static int reloc_bloblist(void)
return 0; return 0;
} }
if (gd->boardf->new_bloblist) { if (gd->boardf->new_bloblist) {
debug("Copying bloblist from %p to %p, size %x\n", ulong size = bloblist_get_total_size();
gd->bloblist, gd->boardf->new_bloblist,
gd->bloblist->total_size); if (size < CONFIG_BLOBLIST_SIZE_RELOC)
return bloblist_reloc(gd->boardf->new_bloblist, size = CONFIG_BLOBLIST_SIZE_RELOC;
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 #endif

View file

@ -1,5 +1,5 @@
#include <configs/vexpress_fvp_defconfig> #include <configs/vexpress_fvp_defconfig>
CONFIG_BLOBLIST=y CONFIG_BLOBLIST=y
CONFIG_BLOBLIST_PASSAGE=y CONFIG_BLOBLIST_PASSAGE_MANDATORY=y
CONFIG_BLOBLIST_SIZE_RELOC=0x10000 CONFIG_BLOBLIST_SIZE_RELOC=0x10000

View file

@ -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 bloblist, or utilizing a standard passage-provided bloblist with automatic size
detection. detection.
By default, ``vexpress_fvp_bloblist_defconfig`` uses the standard passage method By default, ``vexpress_fvp_bloblist_defconfig`` uses the standard passage method mandatorily
(CONFIG_BLOBLIST_PASSAGE) because TF-A provides a Transfer List in non-secure (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 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 TF-A, contains all necessary data for the handoff process, including DT and ACPI
tables. tables.

View file

@ -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 * If CONFIG_BLOBLIST_ALLOC is selected, it allocates memory for a bloblist of
* size CONFIG_BLOBLIST_SIZE. * size CONFIG_BLOBLIST_SIZE.
* *
* If CONFIG_BLOBLIST_PASSAGE is selected, it uses the bloblist in the incoming * If CONFIG_BLOBLIST_PASSAGE_MANDATORY is selected, bloblist in the incoming
* standard passage. The size is detected automatically so CONFIG_BLOBLIST_SIZE * standard passage is mandatorily required.
* can be 0.
* *
* Sets GD_FLG_BLOBLIST_READY in global_data flags on success * 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. * @rfdt: Register that holds the FDT base address.
* @rzero: Register that must be zero. * @rzero: Register that must be zero.
* @rsig: Register that holds signature and register conventions version. * @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 * Return: 0 if OK, -EIO if the bloblist is not compliant to the register
* conventions. * 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 * xferlist_from_boot_arg() - Get bloblist from the boot args.
* to the specified address.
* *
* @addr: Address for the bloblist * @addr: Address of the bloblist
* @size: Size of space reserved for the bloblist
* Return: 0 if OK, else on error * 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 */ #endif /* __BLOBLIST_H */