According to recently firmware handsoff spec [1]'s "Register usage at handoff boundary", Transfer List's signature value was changed from 0x40_b10b (3 bytes) to 4a0f_b10b (4 bytes).
As updating of TL's signature, register value of x1/r1 should be: In aarch32's r1 value should be R1[23:0]: TL signature (4a0f_b10b->masked range value: 0f_b10b) R1[31:24]: version of the register convention == 1 and In aarch64's x1 value should be X1[31:0]: TL signature (4a0f_b10b) X1[39:32]: version of the register convention == 1 X1[63:40]: MBZ (See the [2] and [3]). Also, according to architecture, the convention is slight different: In aarch32: R0: MBZ R1: see above R2: Compatibility location for passing a platform description devicetree R3: tl_base_pa In aarch64: X0: Compatibility location for passing a platform description devicetree X1: see above X2: MBZ X3: tl_base_pa This patch fix problems: 1. breaking X1 value with updated specification in aarch64 - change of length of signature field. 2. previous error value set in R1 in arm32. - length of signature should be 24, but it uses 32bit signature. 3. according to architecture, check register convetion differently. [1] https://github.com/FirmwareHandoff/firmware_handoff [2] https://github.com/FirmwareHandoff/firmware_handoff/issues/32 [3] https://github.com/FirmwareHandoff/firmware_handoff/commit/5aa7aa1d3a1db75213e458d392b751f0707de027 Signed-off-by: Levi Yun <yeoreum....@arm.com> --- arch/arm/lib/xferlist.c | 8 +++++--- common/bloblist.c | 11 ++++++++++- include/bloblist.h | 5 ++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/arm/lib/xferlist.c b/arch/arm/lib/xferlist.c index f9c5d88bd4..a6349293bd 100644 --- a/arch/arm/lib/xferlist.c +++ b/arch/arm/lib/xferlist.c @@ -12,12 +12,14 @@ int xferlist_from_boot_arg(ulong addr, ulong size) { int ret; - ret = bloblist_check(saved_args[3], size); + if (IS_ENABLED(CONFIG_64BIT)) + ret = bloblist_check_reg_conv(saved_args[0], saved_args[2], saved_args[1]); + else + ret = bloblist_check_reg_conv(saved_args[2], saved_args[0], saved_args[1]); if (ret) return ret; - ret = bloblist_check_reg_conv(saved_args[0], saved_args[2], - saved_args[1]); + ret = bloblist_check(saved_args[3], size); if (ret) return ret; diff --git a/common/bloblist.c b/common/bloblist.c index 11d6422b69..2008ab4d25 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -576,7 +576,16 @@ int bloblist_maybe_init(void) int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig) { - if (rzero || rsig != (BLOBLIST_MAGIC | BLOBLIST_REGCONV_VER) || + ulong version = BLOBLIST_REGCONV_VER; + ulong sigval; + + sigval = (IS_ENABLED(CONFIG_64BIT)) ? + ((BLOBLIST_MAGIC & ((1UL << BLOBLIST_REGCONV_SHIFT_64) - 1)) | + ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_64)) : + ((BLOBLIST_MAGIC & ((1UL << BLOBLIST_REGCONV_SHIFT_32) - 1)) | + ((version & BLOBLIST_REGCONV_MASK) << BLOBLIST_REGCONV_SHIFT_32)); + + if (rzero || rsig != sigval || rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) { gd->bloblist = NULL; /* Reset the gd bloblist pointer */ return -EIO; diff --git a/include/bloblist.h b/include/bloblist.h index 7fbdd622bc..f4849f22a0 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -83,7 +83,10 @@ enum { * Register convention version should be placed into a higher byte * https://github.com/FirmwareHandoff/firmware_handoff/issues/32 */ - BLOBLIST_REGCONV_VER = 1 << 24, + BLOBLIST_REGCONV_SHIFT_64 = 32, + BLOBLIST_REGCONV_SHIFT_32 = 24, + BLOBLIST_REGCONV_MASK = 0xff, + BLOBLIST_REGCONV_VER = 1, BLOBLIST_BLOB_ALIGN_LOG2 = 3, BLOBLIST_BLOB_ALIGN = 1 << BLOBLIST_BLOB_ALIGN_LOG2, -- LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}