Merge changes from topic "rmm-eac5"
* changes:
feat(rmm-eac5): update RSI_VERSION, RMI_VERSION
feat(rmm) : add api for rec force exit
test(rmm-eac4): add testcase for CPU_ON denied
diff --git a/Makefile b/Makefile
index e104814..58af796 100644
--- a/Makefile
+++ b/Makefile
@@ -169,6 +169,7 @@
$(eval $(call assert_boolean,USE_NVM))
$(eval $(call assert_numeric,BRANCH_PROTECTION))
$(eval $(call assert_boolean,ENABLE_REALM_PAYLOAD_TESTS))
+$(eval $(call assert_boolean,TRANSFER_LIST))
################################################################################
# Process build options
@@ -194,6 +195,7 @@
$(eval $(call add_define,TFTF_DEFINES,PLAT_${PLAT}))
$(eval $(call add_define,TFTF_DEFINES,USE_NVM))
$(eval $(call add_define,TFTF_DEFINES,ENABLE_REALM_PAYLOAD_TESTS))
+$(eval $(call add_define,TFTF_DEFINES,TRANSFER_LIST))
################################################################################
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
new file mode 100644
index 0000000..9ee1f55
--- /dev/null
+++ b/include/lib/transfer_list.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __TRANSFER_LIST_H
+#define __TRANSFER_LIST_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define TRANSFER_LIST_SIGNATURE U(0x006ed0ff)
+#define TRANSFER_LIST_VERSION U(0x0001)
+
+// Init value of maximum alignment required by any TE data in the TL
+// specified as a power of two
+#define TRANSFER_LIST_INIT_MAX_ALIGN U(3)
+
+// alignment required by TE header start address, in bytes
+#define TRANSFER_LIST_GRANULE U(8)
+
+// version of the register convention used.
+// Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
+#define REGISTER_CONVENTION_VERSION_MASK (1 << 24)
+
+#ifndef __ASSEMBLER__
+
+enum transfer_list_tag_id {
+ TL_TAG_EMPTY = 0,
+ TL_TAG_FDT = 1,
+ TL_TAG_HOB_BLOCK = 2,
+ TL_TAG_HOB_LIST = 3,
+ TL_TAG_ACPI_TABLE_AGGREGATE = 4,
+};
+
+enum transfer_list_ops {
+ TL_OPS_NON, // invalid for any operation
+ TL_OPS_ALL, // valid for all operations
+};
+
+struct transfer_list_header {
+ uint32_t signature;
+ uint8_t checksum;
+ uint8_t version;
+ uint8_t hdr_size;
+ uint8_t alignment; // max alignment of TE data
+ uint32_t size; // TL header + all TEs
+ uint32_t max_size;
+ /*
+ * Commented out element used to visualize dynamic part of the
+ * data structure.
+ *
+ * Note that struct transfer_list_entry also is dynamic in size
+ * so the elements can't be indexed directly but instead must be
+ * traversed in order
+ *
+ * struct transfer_list_entry entries[];
+ */
+};
+
+struct transfer_list_entry {
+ uint16_t tag_id;
+ uint8_t reserved0; // place holder
+ uint8_t hdr_size;
+ uint32_t data_size;
+ /*
+ * Commented out element used to visualize dynamic part of the
+ * data structure.
+ *
+ * Note that padding is added at the end of @data to make to reach
+ * a 8-byte boundary.
+ *
+ * uint8_t data[ROUNDUP(data_size, 8)];
+ */
+};
+
+bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
+
+void *transfer_list_entry_data(struct transfer_list_entry *entry);
+
+struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
+ uint16_t tag_id);
+
+enum transfer_list_ops
+transfer_list_check_header(const struct transfer_list_header *tl);
+
+#endif /*__ASSEMBLER__*/
+#endif /*__TRANSFER_LIST_H*/
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
new file mode 100644
index 0000000..c83b0b3
--- /dev/null
+++ b/lib/transfer_list/transfer_list.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <transfer_list.h>
+
+struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
+ uint16_t tag_id)
+{
+ struct transfer_list_entry *te = (void *)tl + tl->hdr_size;
+
+ while (te->tag_id != tag_id) {
+ te += round_up(te->hdr_size + te->data_size, tl->alignment);
+ }
+
+ return te;
+}
+
+void *transfer_list_entry_data(struct transfer_list_entry *entry)
+{
+ return (uint8_t *)entry + entry->hdr_size;
+}
+
+/*******************************************************************************
+ * Verifying the header of a transfer list
+ * Compliant to 2.4.1 of Firmware handoff specification (v0.9)
+ * Return transfer list operation status code
+ ******************************************************************************/
+enum transfer_list_ops
+transfer_list_check_header(const struct transfer_list_header *tl)
+{
+ uint8_t byte_sum = 0U;
+ uint8_t *b = (uint8_t *)tl;
+
+ if (tl == NULL) {
+ return TL_OPS_NON;
+ }
+
+ if (tl->signature != TRANSFER_LIST_SIGNATURE ||
+ tl->size > tl->max_size) {
+ return TL_OPS_NON;
+ }
+
+ for (size_t i = 0; i < tl->size; i++) {
+ byte_sum += b[i];
+ }
+
+ if (byte_sum - tl->checksum == tl->checksum) {
+ return TL_OPS_NON;
+ }
+
+ return TL_OPS_ALL;
+}
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 3605d01..d26ec06 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -51,3 +51,7 @@
# Build RME stack
ENABLE_REALM_PAYLOAD_TESTS := 0
+
+# Use the Firmware Handoff framework to receive configurations from preceding
+# bootloader.
+TRANSFER_LIST := 0
diff --git a/tftf/framework/aarch64/entrypoint.S b/tftf/framework/aarch64/entrypoint.S
index 6aa5645..7937b88 100644
--- a/tftf/framework/aarch64/entrypoint.S
+++ b/tftf/framework/aarch64/entrypoint.S
@@ -18,11 +18,13 @@
*/
func tftf_entrypoint
/* --------------------------------------------------------------------
- * Save arguments x0, x1 from the previous Boot loader
+ * Save arguments x0-x3 from the previous bootloader.
* --------------------------------------------------------------------
*/
mov x20, x0
mov x21, x1
+ mov x22, x2
+ mov x23, x3
bl arch_init
@@ -79,13 +81,15 @@
bl platform_set_stack
/* --------------------------------------------------------------------
- * Save fw_config and hw_config addresses passed in x0, x1 from the
- * previous boot loader
+ * Save the fw_config or transfer list and hw_config addresses passed
+ * in registers x0 to x3 from the previous bootloader.
* --------------------------------------------------------------------
*/
mov x0, x20
mov x1, x21
- bl save_fw_hw_configs
+ mov x2, x22
+ mov x3, x23
+ bl save_handoff_params
/* --------------------------------------------------------------------
* tftf_cold_boot_main() will perform the remaining architectural and
@@ -204,10 +208,22 @@
ret
endfunc arch_init
-/* Set fw_config and hw_config addresses passed in x0, x1 */
-func save_fw_hw_configs
+
+/* ----------------------------------------------------------------------------
+ * Save fw_config or transfer list and hw_config addresses passed in registers
+ * x0 to x3 from the previous bootloader.
+ * ----------------------------------------------------------------------------
+ */
+func save_handoff_params
+#if TRANSFER_LIST
+ adrp x4, ns_tl
+ str x3, [x4, :lo12:ns_tl]
+ str x1, [x4, :lo12:tl_signature]
+ str x0, [x4, :lo12:hw_config_base]
+#else
adrp x2, fw_config_base
str x0, [x2, :lo12:fw_config_base]
str x1, [x2, :lo12:hw_config_base]
+#endif
ret
-endfunc save_fw_hw_configs
+endfunc save_handoff_params
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index ef59502..f57572c 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -65,6 +65,7 @@
lib/smc/${ARCH}/smc.c \
lib/trng/trng.c \
lib/errata_abi/errata_abi.c \
+ lib/transfer_list/transfer_list.c \
lib/trusted_os/trusted_os.c \
lib/utils/mp_printf.c \
lib/utils/uuid.c \
diff --git a/tftf/framework/main.c b/tftf/framework/main.c
index a203bd2..0701e28 100644
--- a/tftf/framework/main.c
+++ b/tftf/framework/main.c
@@ -24,6 +24,9 @@
#include <tftf.h>
#include <tftf_lib.h>
#include <timer.h>
+#if TRANSFER_LIST
+#include <transfer_list.h>
+#endif
#define MIN_RETRY_TO_POWER_ON_LEAD_CPU 10
@@ -44,7 +47,12 @@
static unsigned int test_is_rebooting;
/* Parameters arg0 and arg1 passed from BL31 */
+#if TRANSFER_LIST
+u_register_t ns_tl;
+u_register_t tl_signature;
+#else
u_register_t fw_config_base;
+#endif
u_register_t hw_config_base;
static inline const test_suite_t *current_testsuite(void)
diff --git a/tftf/tests/aarch32_tests_to_skip.txt b/tftf/tests/aarch32_tests_to_skip.txt
index 83e4028..210d465 100644
--- a/tftf/tests/aarch32_tests_to_skip.txt
+++ b/tftf/tests/aarch32_tests_to_skip.txt
@@ -17,3 +17,4 @@
SMMUv3 tests
FF-A Notifications
RMI and SPM tests
+FF-A SMCCC compliance
diff --git a/tftf/tests/misc_tests/test_firmware_handoff.c b/tftf/tests/misc_tests/test_firmware_handoff.c
new file mode 100644
index 0000000..bd565ae
--- /dev/null
+++ b/tftf/tests/misc_tests/test_firmware_handoff.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <transfer_list.h>
+
+extern u_register_t hw_config_base;
+extern u_register_t ns_tl;
+extern u_register_t tl_signature;
+
+#define DTB_PREAMBLE U(0xedfe0dd0)
+
+test_result_t test_handoff_header(void)
+{
+ struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
+
+ assert((uint32_t)tl_signature ==
+ (REGISTER_CONVENTION_VERSION_MASK | TRANSFER_LIST_SIGNATURE));
+
+ if (transfer_list_check_header(tl) == TL_OPS_NON) {
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+test_result_t test_handoff_dtb_payload(void)
+{
+ tftf_testcase_printf("Validating HW_CONFIG from transfer list.\n");
+ struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
+ struct transfer_list_entry *te = (void *)tl + tl->hdr_size;
+ uintptr_t dtb_ptr;
+
+ te = transfer_list_find(tl, TL_TAG_FDT);
+
+ if (te == NULL) {
+ tftf_testcase_printf(
+ "Failed to find HW CONFIG TE in transfer list!");
+ return TEST_RESULT_FAIL;
+ }
+
+ dtb_ptr = (unsigned long)transfer_list_entry_data(te);
+
+ if ((dtb_ptr != hw_config_base) &&
+ (*(uint32_t *)dtb_ptr != DTB_PREAMBLE)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_smccc.c b/tftf/tests/runtime_services/secure_service/test_ffa_smccc.c
new file mode 100644
index 0000000..7a42633
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_smccc.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+
+#include <ffa_endpoints.h>
+#include <ffa_helpers.h>
+#include <ffa_svc.h>
+#include <runtime_services/spm_test_helpers.h>
+#include <spm_common.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <xlat_tables_defs.h>
+
+#define expect_eq(expr, value) \
+ do { \
+ if ((expr) != (value)) { \
+ ERROR("expect failed %s:%u\n", __FILE__, __LINE__); \
+ return TEST_RESULT_FAIL; \
+ } \
+ } while (0);
+
+static const struct ffa_uuid sp_uuids[] = {
+ {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}, {IVY_UUID}
+ };
+
+struct ffa_value8 {
+ u_register_t fid;
+ u_register_t arg1;
+ u_register_t arg2;
+ u_register_t arg3;
+ u_register_t arg4;
+ u_register_t arg5;
+ u_register_t arg6;
+ u_register_t arg7;
+};
+
+/* Declared in test_ffa_smccc_asm.S. */
+uint32_t test_ffa_smc(struct ffa_value8 *);
+uint32_t test_ffa_smc_ext(struct ffa_value *);
+
+/**
+ * FF-A service calls are emitted at the NS physical FF-A instance.
+ * Such services do not return results in registers beyond x7.
+ * Check callee(s) preserves GP registers beyond x7 per SMCCCv1.2.
+ */
+test_result_t test_smccc_callee_preserved(void)
+{
+ struct ffa_value8 args;
+ struct mailbox_buffers mb;
+
+ /*
+ * Permit running the test on configurations running
+ * the S-EL2 SPMC where 4 test partitions are deployed.
+ */
+ CHECK_SPMC_TESTING_SETUP(1, 1, sp_uuids);
+ reset_tftf_mailbox();
+
+ /* Declare RX/TX buffers locally to the test. */
+ CONFIGURE_MAILBOX(mb, PAGE_SIZE);
+
+ memset(&args, 0, sizeof(struct ffa_value8));
+ args.fid = FFA_VERSION;
+ args.arg1 = 0x10001;
+ expect_eq(test_ffa_smc(&args), 0);
+ expect_eq(args.fid, 0x10001);
+ expect_eq(args.arg1, 0);
+ expect_eq(args.arg2, 0);
+ expect_eq(args.arg3, 0);
+ expect_eq(args.arg4, 0);
+ expect_eq(args.arg5, 0);
+ expect_eq(args.arg6, 0);
+ expect_eq(args.arg7, 0);
+
+ memset(&args, 0, sizeof(struct ffa_value8));
+ args.fid = FFA_ID_GET;
+ expect_eq(test_ffa_smc(&args), 0);
+ expect_eq(args.fid, FFA_SUCCESS_SMC32);
+ expect_eq(args.arg1, 0);
+ expect_eq(args.arg2, 0);
+ expect_eq(args.arg3, 0);
+ expect_eq(args.arg4, 0);
+ expect_eq(args.arg5, 0);
+ expect_eq(args.arg6, 0);
+ expect_eq(args.arg7, 0);
+
+ memset(&args, 0, sizeof(struct ffa_value8));
+ args.fid = FFA_RXTX_MAP_SMC64;
+ args.arg1 = (uintptr_t)mb.send;
+ args.arg2 = (uintptr_t)mb.recv;
+ args.arg3 = 1;
+ expect_eq(test_ffa_smc(&args), 0);
+ expect_eq(args.fid, FFA_SUCCESS_SMC32);
+ expect_eq(args.arg1, 0);
+ expect_eq(args.arg2, 0);
+ expect_eq(args.arg3, 0);
+ expect_eq(args.arg4, 0);
+ expect_eq(args.arg5, 0);
+ expect_eq(args.arg6, 0);
+ expect_eq(args.arg7, 0);
+
+ memset(&args, 0, sizeof(struct ffa_value8));
+ args.fid = FFA_PARTITION_INFO_GET;
+ expect_eq(test_ffa_smc(&args), 0);
+ expect_eq(args.fid, FFA_SUCCESS_SMC32);
+ expect_eq(args.arg1, 0);
+ expect_eq(args.arg2, ARRAY_SIZE(sp_uuids));
+ expect_eq(args.arg3, sizeof(struct ffa_partition_info));
+ expect_eq(args.arg4, 0);
+ expect_eq(args.arg5, 0);
+ expect_eq(args.arg6, 0);
+ expect_eq(args.arg7, 0);
+
+ memset(&args, 0, sizeof(struct ffa_value8));
+ args.fid = FFA_RX_RELEASE;
+ expect_eq(test_ffa_smc(&args), 0);
+ expect_eq(args.fid, FFA_SUCCESS_SMC32);
+ expect_eq(args.arg1, 0);
+ expect_eq(args.arg2, 0);
+ expect_eq(args.arg3, 0);
+ expect_eq(args.arg4, 0);
+ expect_eq(args.arg5, 0);
+ expect_eq(args.arg6, 0);
+ expect_eq(args.arg7, 0);
+
+ memset(&args, 0, sizeof(struct ffa_value8));
+ args.fid = FFA_RXTX_UNMAP;
+ expect_eq(test_ffa_smc(&args), 0);
+ expect_eq(args.fid, FFA_SUCCESS_SMC32);
+ expect_eq(args.arg1, 0);
+ expect_eq(args.arg2, 0);
+ expect_eq(args.arg3, 0);
+ expect_eq(args.arg4, 0);
+ expect_eq(args.arg5, 0);
+ expect_eq(args.arg6, 0);
+ expect_eq(args.arg7, 0);
+
+ return TEST_RESULT_SUCCESS;
+}
+
+/**
+ * An FF-A service call is emitted at the NS physical FF-A instance.
+ * The service returns results in x0-x17 registers.
+ * Check callee(s) preserve GP registers beyond x17 per SMCCCv1.2.
+ */
+test_result_t test_smccc_ext_callee_preserved(void)
+{
+ struct ffa_value args_ext;
+
+ CHECK_SPMC_TESTING_SETUP(1, 1, sp_uuids);
+
+ /* Test the SMCCC extended registers range. */
+ memset(&args_ext, 0, sizeof(struct ffa_value));
+ args_ext.fid = FFA_PARTITION_INFO_GET_REGS_SMC64;
+ expect_eq(test_ffa_smc_ext(&args_ext), 0);
+ expect_eq(args_ext.fid, FFA_SUCCESS_SMC64);
+ expect_eq(args_ext.arg1, 0);
+ expect_eq(args_ext.arg2 >> 48, sizeof(struct ffa_partition_info));
+ expect_eq(args_ext.arg2 & 0xffff, ARRAY_SIZE(sp_uuids) - 1);
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_smccc_asm.S b/tftf/tests/runtime_services/secure_service/test_ffa_smccc_asm.S
new file mode 100644
index 0000000..00d82ee
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_smccc_asm.S
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+ .global test_ffa_smc
+ .global test_ffa_smc_ext
+
+ .section .text, "ax"
+
+/**
+ * test_ffa_smc
+ *
+ * x0 - ptr to a struct ffa_value8
+ *
+ * This function is used to test FF-A ABIs on top of SMCCCv1.2 for interfaces
+ * requiring at most 8 input/output registers.
+ * Load 8 GP input registers, move a pattern into x8-x29 and emit an SMC.
+ * On return save 8 output registers to the structure and compare x8-x29
+ * to the known pattern. If a register was altered it indicates an SMCCC
+ * violation and the function returns with a value greater than 0.
+ * The function returns 0 on success.
+ */
+func test_ffa_smc
+ /* Save FP/LR. */
+ stp x29, x30, [sp, #-16]!
+
+ /* Save x19-x28 per AAPCS64. */
+ stp x27, x28, [sp, #-16]!
+ stp x25, x26, [sp, #-16]!
+ stp x23, x24, [sp, #-16]!
+ stp x21, x22, [sp, #-16]!
+ stp x19, x20, [sp, #-16]!
+
+ /*
+ * Store the struct ffa_value pointer to x30.
+ * x30 is preserved by the SMC callee.
+ */
+ mov x30, x0
+
+ /* Load the SMC service input values. */
+ ldp x0, x1, [x30]
+ ldp x2, x3, [x30, #16]
+ ldp x4, x5, [x30, #32]
+ ldp x6, x7, [x30, #48]
+ mov x8, #0xa8
+ add x9, x8, #1
+ add x10, x8, #2
+ add x11, x8, #3
+ add x12, x8, #4
+ add x13, x8, #5
+ add x14, x8, #6
+ add x15, x8, #7
+ add x16, x8, #8
+ add x17, x8, #9
+ add x18, x8, #10
+ add x19, x8, #11
+ add x20, x8, #12
+ add x21, x8, #13
+ add x22, x8, #14
+ add x23, x8, #15
+ add x24, x8, #16
+ add x25, x8, #17
+ add x26, x8, #18
+ add x27, x8, #19
+ add x28, x8, #20
+ add x29, x8, #21
+ smc #0
+
+ /* Store the SMC service return values. */
+ stp x0, x1, [x30]
+ stp x2, x3, [x30, #16]
+ stp x4, x5, [x30, #32]
+ stp x6, x7, [x30, #48]
+
+ /* Check if SMC callee-preserved registers were altered. */
+ mov w0, wzr
+ cmp x8, #0xa8
+ cinc x0, x0, ne
+ cmp x9, #0xa9
+ cinc x0, x0, ne
+ cmp x10, #0xaa
+ cinc x0, x0, ne
+ cmp x11, #0xab
+ cinc x0, x0, ne
+ cmp x12, #0xac
+ cinc x0, x0, ne
+ cmp x13, #0xad
+ cinc x0, x0, ne
+ cmp x14, #0xae
+ cinc x0, x0, ne
+ cmp x15, #0xaf
+ cinc x0, x0, ne
+ cmp x16, #0xb0
+ cinc x0, x0, ne
+ cmp x17, #0xb1
+ cinc x0, x0, ne
+ cmp x18, #0xb2
+ cinc x0, x0, ne
+ cmp x19, #0xb3
+ cinc x0, x0, ne
+ cmp x20, #0xb4
+ cinc x0, x0, ne
+ cmp x21, #0xb5
+ cinc x0, x0, ne
+ cmp x22, #0xb6
+ cinc x0, x0, ne
+ cmp x23, #0xb7
+ cinc x0, x0, ne
+ cmp x24, #0xb8
+ cinc x0, x0, ne
+ cmp x25, #0xb9
+ cinc x0, x0, ne
+ cmp x26, #0xba
+ cinc x0, x0, ne
+ cmp x27, #0xbb
+ cinc x0, x0, ne
+ cmp x28, #0xbc
+ cinc x0, x0, ne
+ cmp x29, #0xbd
+ cinc x0, x0, ne
+
+ /* Restore x19-x28 per AAPCS64. */
+ ldp x19, x20, [sp], #16
+ ldp x21, x22, [sp], #16
+ ldp x23, x24, [sp], #16
+ ldp x25, x26, [sp], #16
+ ldp x27, x28, [sp], #16
+
+ /* Restore FP/LR. */
+ ldp x29, x30, [sp], #16
+ ret
+endfunc test_ffa_smc
+
+/**
+ * test_ffa_smc_ext
+ *
+ * x0 - ptr to a struct ffa_value
+ *
+ * This function is used to test FF-A ABIs on top of SMCCCv1.2 for interfaces
+ * requiring at most 18 input/output registers.
+ * Load 18 GP input registers, move a pattern into x18-x29 and emit an SMC.
+ * On return save 18 output registers to the structure and compare x18-x29
+ * to the known pattern. If a register was altered it indicates an SMCCC
+ * violation and the function returns with a value greater than 0.
+ * The function returns 0 on success.
+ */
+func test_ffa_smc_ext
+ /* Save FP/LR. */
+ stp x29, x30, [sp, #-16]!
+
+ /* Save x19-x28 per AAPCS64. */
+ stp x27, x28, [sp, #-16]!
+ stp x25, x26, [sp, #-16]!
+ stp x23, x24, [sp, #-16]!
+ stp x21, x22, [sp, #-16]!
+ stp x19, x20, [sp, #-16]!
+
+ /*
+ * Store the struct ffa_value_ext pointer to x30.
+ * x30 is preserved by the SMC callee.
+ */
+ mov x30, x0
+
+ /* Load the SMC service input values. */
+ ldp x0, x1, [x30]
+ ldp x2, x3, [x30, #16]
+ ldp x4, x5, [x30, #32]
+ ldp x6, x7, [x30, #48]
+ ldp x8, x9, [x30, #64]
+ ldp x10, x11, [x30, #80]
+ ldp x12, x13, [x30, #96]
+ ldp x14, x15, [x30, #112]
+ ldp x16, x17, [x30, #128]
+ mov x18, #0xb2
+ add x19, x18, #1
+ add x20, x18, #2
+ add x21, x18, #3
+ add x22, x18, #4
+ add x23, x18, #5
+ add x24, x18, #6
+ add x25, x18, #7
+ add x26, x18, #8
+ add x27, x18, #9
+ add x28, x18, #10
+ add x29, x18, #11
+ smc #0
+
+ /* Store the SMC service return values. */
+ stp x0, x1, [x30]
+ stp x2, x3, [x30, #16]
+ stp x4, x5, [x30, #32]
+ stp x6, x7, [x30, #48]
+ stp x8, x9, [x30, #64]
+ stp x10, x11, [x30, #80]
+ stp x12, x13, [x30, #96]
+ stp x14, x15, [x30, #112]
+ stp x16, x17, [x30, #128]
+
+ /* Check if SMC callee-preserved registers were altered. */
+ mov w0, wzr
+ cmp x18, #0xb2
+ cinc x0, x0, ne
+ cmp x19, #0xb3
+ cinc x0, x0, ne
+ cmp x20, #0xb4
+ cinc x0, x0, ne
+ cmp x21, #0xb5
+ cinc x0, x0, ne
+ cmp x22, #0xb6
+ cinc x0, x0, ne
+ cmp x23, #0xb7
+ cinc x0, x0, ne
+ cmp x24, #0xb8
+ cinc x0, x0, ne
+ cmp x25, #0xb9
+ cinc x0, x0, ne
+ cmp x26, #0xba
+ cinc x0, x0, ne
+ cmp x27, #0xbb
+ cinc x0, x0, ne
+ cmp x28, #0xbc
+ cinc x0, x0, ne
+ cmp x29, #0xbd
+ cinc x0, x0, ne
+
+ /* Restore x19-x28 per AAPCS64. */
+ ldp x19, x20, [sp], #16
+ ldp x21, x22, [sp], #16
+ ldp x23, x24, [sp], #16
+ ldp x25, x26, [sp], #16
+ ldp x27, x28, [sp], #16
+
+ /* Restore FP/LR. */
+ ldp x29, x30, [sp], #16
+ ret
+endfunc test_ffa_smc_ext
diff --git a/tftf/tests/tests-firmware-handoff.mk b/tftf/tests/tests-firmware-handoff.mk
new file mode 100644
index 0000000..515188a
--- /dev/null
+++ b/tftf/tests/tests-firmware-handoff.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2023, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq (${TRANSFER_LIST}, 1)
+
+TESTS_SOURCES += $(addprefix tftf/tests/misc_tests/, \
+ test_firmware_handoff.c \
+)
+
+endif
diff --git a/tftf/tests/tests-firmware-handoff.xml b/tftf/tests/tests-firmware-handoff.xml
new file mode 100644
index 0000000..2761626
--- /dev/null
+++ b/tftf/tests/tests-firmware-handoff.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2023, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+ <testsuite name="Firmware Handoff" description="Validate transfer list managed by firmware hanoff framework">
+ <testcase name="Validate transfer list header" function="test_handoff_header" />
+ <testcase name="Validate HW_CONFIG in transfer list" function="test_handoff_dtb_payload" />
+ </testsuite>
+</testsuites>
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index 13f3f86..174e11d 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -36,5 +36,11 @@
host_realm_helper.c \
)
+TESTS_SOURCES += \
+ $(addprefix tftf/tests/runtime_services/secure_service/, \
+ test_ffa_smccc.c \
+ test_ffa_smccc_asm.S \
+ )
+
TESTS_SOURCES += lib/extensions/fpu/fpu.c
endif
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 8ec2812..e47039f 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -42,6 +42,14 @@
function="test_ffa_partition_info_v1_0" />
</testsuite>
+ <testsuite name="FF-A SMCCC compliance"
+ description="SMCCC compliance" >
+ <testcase name="FF-A callee preserves GP register set per SMCCC"
+ function="test_smccc_callee_preserved" />
+ <testcase name="FF-A callee preserves extended GP register set per SMCCC"
+ function="test_smccc_ext_callee_preserved" />
+ </testsuite>
+
<testsuite name="SP exceptions"
description="SP exceptions" >