Skip to content

Commit

Permalink
core: kernel: Fix checking register convention r1/x1 value of transfe…
Browse files Browse the repository at this point in the history
…r_list

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]: set to the TL signature (4a0f_b10b->masked value: 0f_b10b)
    R1[31:24]: version of the register convention ==  1
and
In aarch64's x1 value should be
    X1[31:0]: set to the TL signature (4a0f_b10b)
    X1[39:32]: version of the register convention ==  1
    X1[63:40]: MBZ
(See the [2] and [3]).

Therefore, it requires to separate mask and shift value for register
convention version field when checking each r1/x1 value.

This patch fix two 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.

This patch is a breaking change. It works only TF-A is updated.

Link: https://github.com/FirmwareHandoff/firmware_handoff [1]
Link: FirmwareHandoff/firmware_handoff#32 [2]
Link: FirmwareHandoff/firmware_handoff@5aa7aa1 [3]
Fixes: 508e247 ("core: update transfer list header and signature")
Signed-off-by: Levi Yun <[email protected]>
Reviewed-by: Jens Wiklander <[email protected]>
  • Loading branch information
LeviYeoReum authored and jforissier committed Jul 25, 2024
1 parent f40bf1e commit 773d3f8
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
13 changes: 8 additions & 5 deletions core/arch/arm/kernel/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1381,22 +1381,25 @@ void __weak boot_save_args(unsigned long a0, unsigned long a1,
* Transfer List
* a0 - DTB address or 0 (AArch64)
* - must be 0 (AArch32)
* a1 - TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK
* a1 - 1 << 32 | TRANSFER_LIST_SIGNATURE[0:31] (AArch64)
* - 1 << 24 | TRANSFER_LIST_SIGNATURE[0:23] (AArch32)
* a2 - must be 0 (AArch64)
* - DTB address or 0 (AArch32)
* a3 - Transfer list base address
* a4 - Not used
*/

if (IS_ENABLED(CFG_TRANSFER_LIST) &&
a1 == (TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK)) {
if (IS_ENABLED(CFG_ARM64_core)) {
if (IS_ENABLED(CFG_TRANSFER_LIST)) {
if (IS_ENABLED(CFG_ARM64_core) &&
a1 == TL_HANDOFF_X1_VALUE(TL_REG_CONVENTION_VER)) {
boot_save_transfer_list(a2, a3, a0);
boot_arg_fdt = a0;
} else {
} else if (IS_ENABLED(CFG_ARM32_core) &&
a1 == TL_HANDOFF_R1_VALUE(TL_REG_CONVENTION_VER)) {
boot_save_transfer_list(a0, a3, a2);
boot_arg_fdt = a2;
}

return;
}

Expand Down
17 changes: 16 additions & 1 deletion core/include/kernel/transfer_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,22 @@
* Version of the register convention used.
* Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
*/
#define REG_CONVENTION_VER_MASK BIT(24)
#define TL_REG_CONVENTION_VER_SHIFT_64 UL(32)
#define TL_REG_CONVENTION_VER_SHIFT_32 UL(24)
#define TL_REG_CONVENTION_VER_MASK UL(0xff)
#define TL_REG_CONVENTION_VER UL(1)

#define TL_HANDOFF_X1_VALUE(__version) \
((TRANSFER_LIST_SIGNATURE & \
((BIT64(TL_REG_CONVENTION_VER_SHIFT_64)) - 1)) | \
(((__version) & TL_REG_CONVENTION_VER_MASK) << \
TL_REG_CONVENTION_VER_SHIFT_64))

#define TL_HANDOFF_R1_VALUE(__version) \
((TRANSFER_LIST_SIGNATURE & \
((BIT32(TL_REG_CONVENTION_VER_SHIFT_32)) - 1)) | \
(((__version) & TL_REG_CONVENTION_VER_MASK) << \
TL_REG_CONVENTION_VER_SHIFT_32))

#define TL_FLAGS_HAS_CHECKSUM BIT(0)

Expand Down

0 comments on commit 773d3f8

Please sign in to comment.