Add bloblist_get_reg_conv() to get the register values for passing the bloblist on according to the Firmware Handoff spec: the FDT address, the signature and register conventions version, and the transfer list address. It is the counterpart of bloblist_check_reg_conv(), which checks these values when a bloblist is received, and shares its signature calculation.
This allows U-Boot to pass its bloblist to the next stage in registers instead of at a fixed address in memory. Add a test that passes the values from bloblist_get_reg_conv() to bloblist_check_reg_conv(). Signed-off-by: David Lechner <[email protected]> --- common/bloblist.c | 36 +++++++++++++++++++++++++----------- include/bloblist.h | 16 ++++++++++++++++ test/common/bloblist.c | 24 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/common/bloblist.c b/common/bloblist.c index 846c8047f74..4269a49ef99 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -664,22 +664,36 @@ int bloblist_init(void) return 0; } -int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist) +static ulong bloblist_reg_conv_sig(void) { 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))) { - sigval = ((BLOBLIST_MAGIC & ((1ULL << BLOBLIST_REGCONV_SHIFT_64) - 1)) | - ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_64)); - } else { - sigval = ((BLOBLIST_MAGIC & ((1UL << BLOBLIST_REGCONV_SHIFT_32) - 1)) | - ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_32)); - } + (IS_ENABLED(CONFIG_SPL_64BIT) && IS_ENABLED(CONFIG_SPL_BUILD))) + return ((BLOBLIST_MAGIC & ((1ULL << BLOBLIST_REGCONV_SHIFT_64) - 1)) | + ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_64)); + + return ((BLOBLIST_MAGIC & ((1UL << BLOBLIST_REGCONV_SHIFT_32) - 1)) | + ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_32)); +} + +int bloblist_get_reg_conv(ulong *rfdt, ulong *rsig, ulong *xlist) +{ + if (!gd->bloblist) + return -ENOENT; + + *rfdt = (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0); + *rsig = bloblist_reg_conv_sig(); + *xlist = bloblist_get_base(); + + return 0; +} + +int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist) +{ + int ret; - if (rzero || rsig != sigval) + if (rzero || rsig != bloblist_reg_conv_sig()) return -EIO; ret = bloblist_check(xlist, 0); diff --git a/include/bloblist.h b/include/bloblist.h index fcd290eeb16..cdb5764cf55 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -536,6 +536,22 @@ int bloblist_init(void); */ int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist); +/** + * bloblist_get_reg_conv() - Get the register values for passing the bloblist + * according to the Firmware Handoff spec. + * + * This is the counterpart of bloblist_check_reg_conv(). The register that + * must be zero is not returned. Call bloblist_finish() before passing the + * bloblist on. + * + * @rfdt: Returns the FDT base address, or 0 if there is no control FDT in + * the bloblist. + * @rsig: Returns the signature and register conventions version. + * @xlist: Returns the transfer list base address. + * Return: 0 if OK, -ENOENT if there is no bloblist. + */ +int bloblist_get_reg_conv(ulong *rfdt, ulong *rsig, ulong *xlist); + /** * xferlist_from_boot_arg() - Get bloblist from the boot args. * diff --git a/test/common/bloblist.c b/test/common/bloblist.c index 797bde27025..23def33ab6f 100644 --- a/test/common/bloblist.c +++ b/test/common/bloblist.c @@ -605,3 +605,27 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts) return 0; } BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST); + +/* Test that the register values for passing a bloblist pass the check */ +static int bloblist_test_reg_conv(struct unit_test_state *uts) +{ + ulong rfdt, rsig, xlist; + void *fdt; + + clear_bloblist(); + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); + fdt = bloblist_add(BLOBLISTT_CONTROL_FDT, TEST_SIZE, 0); + ut_assertnonnull(fdt); + ut_assertok(bloblist_finish()); + + ut_assertok(bloblist_get_reg_conv(&rfdt, &rsig, &xlist)); + ut_asserteq((ulong)fdt, rfdt); + ut_asserteq(TEST_ADDR, xlist); + ut_assertok(bloblist_check_reg_conv(rfdt, 0, rsig, xlist)); + + ut_asserteq(-EIO, bloblist_check_reg_conv(rfdt, 1, rsig, xlist)); + ut_asserteq(-EIO, bloblist_check_reg_conv(rfdt, 0, rsig + 1, xlist)); + + return 0; +} +BLOBLIST_TEST(bloblist_test_reg_conv, UFT_BLOBLIST); -- 2.53.0
