bloblist: refactor xferlist and bloblist

Refactor the xferlist to remove the relocating when bloblist passed
from the boot args.
Refactor bloblist init to use incoming standard passage by default
if a valid transfer list exists in the boot args.
For bloblist relocation, use the actual total size if it has a smaller
BLOBLIST_SIZE_RELOC.

Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
Suggested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Raymond Mao
2025-02-19 16:02:19 -08:00
committed by Tom Rini
parent 42aebf0f98
commit 6799f09069
4 changed files with 66 additions and 54 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

@@ -492,8 +492,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;
} }
@@ -501,29 +500,30 @@ 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))
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)
@@ -532,6 +532,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) {
/* /*
@@ -556,6 +557,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;
@@ -576,10 +578,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))) {
@@ -590,8 +593,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

@@ -483,19 +483,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 */