Cactus: FFA_PARTITION_INFO_GET test.

Calls FFA_PARTITION_INFO_GET API from secure virtual FFA-A instance.
 * Gets information about primary SP.
 * Gets information about secondary SP.
 * Gets information about all SP running.
 * Attempts to get information about non-existing SP.

Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
Change-Id: Ief4de45b4d7decb1e1dba9bdb0e7e05516062dd2
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 1a49fa8..0692aa9 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -28,6 +28,20 @@
 
 #include <stdint.h>
 
+struct mailbox_buffers {
+	const void *recv;
+	void *send;
+};
+
+struct ffa_partition_info {
+	/** The ID of the VM the information is about */
+	ffa_vm_id_t id;
+	/** The number of execution contexts implemented by the partition */
+	uint16_t exec_context;
+	/** The Partition's properties, e.g. supported messaging methods */
+	uint32_t properties;
+};
+
 /*
  * TODO: In the future this file should be placed in a common folder, and not
  * under tftf. The functions in this file are also used by SPs for SPM tests.
@@ -43,6 +57,8 @@
 					ffa_vm_id_t dest_id, uint32_t message);
 smc_ret_values ffa_error(int32_t error_code);
 smc_ret_values ffa_features(uint32_t feature);
+smc_ret_values ffa_partition_info_get(const uint32_t uuid[4]);
+smc_ret_values ffa_rx_release(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/spm/cactus/cactus_def.h b/spm/cactus/cactus_def.h
index a0adb23..0d3df2e 100644
--- a/spm/cactus/cactus_def.h
+++ b/spm/cactus/cactus_def.h
@@ -28,4 +28,18 @@
 #define CACTUS_TX_BASE			CACTUS_RX_BASE + PAGE_SIZE
 #define CACTUS_RX_TX_SIZE		PAGE_SIZE * 2
 
+/*
+ * RX/TX buffer helpers.
+ */
+#define get_sp_rx_start(sp_id) (CACTUS_RX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE))
+#define get_sp_rx_end(sp_id) (CACTUS_RX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
+#define get_sp_tx_start(sp_id) (CACTUS_TX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE))
+#define get_sp_tx_end(sp_id) (CACTUS_TX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
+
+/*
+ * UUID of secure partition as defined in the respective manifests.
+ */
+#define PRIMARY_UUID {0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb}
+#define SECONDARY_UUID {0xd1582309, 0xf02347b9, 0x827c4464, 0xf5578fc8}
+
 #endif /* CACTUS_DEF_H */
diff --git a/spm/cactus/cactus_ffa_tests.c b/spm/cactus/cactus_ffa_tests.c
index 46813bb..2e6e446 100644
--- a/spm/cactus/cactus_ffa_tests.c
+++ b/spm/cactus/cactus_ffa_tests.c
@@ -6,6 +6,7 @@
 #include <assert.h>
 #include <debug.h>
 #include <errno.h>
+#include <cactus_def.h>
 #include <ffa_helpers.h>
 #include <sp_helpers.h>
 
@@ -13,6 +14,10 @@
 #define FFA_MAJOR 1U
 #define FFA_MINOR 0U
 
+static const uint32_t primary_uuid[4] = PRIMARY_UUID;
+static const uint32_t secondary_uuid[4] = SECONDARY_UUID;
+static const uint32_t null_uuid[4] = {0};
+
 struct feature_test {
 	const char *test_name;
 	unsigned int feature;
@@ -73,7 +78,71 @@
 	announce_test_section_end(test_features);
 }
 
-void ffa_tests(void)
+static void ffa_partition_info_helper(struct mailbox_buffers *mb, const uint32_t uuid[4],
+			       const struct ffa_partition_info *expected,
+			       const uint16_t expected_size)
+{
+	smc_ret_values ret = ffa_partition_info_get(uuid);
+	unsigned int i;
+	expect(ret.ret0, FFA_SUCCESS_SMC32);
+
+	struct ffa_partition_info *info = (struct ffa_partition_info *)(mb->recv);
+	for (i = 0U; i < expected_size; i++) {
+		expect(info[i].id, expected[i].id);
+		expect(info[i].exec_context, expected[i].exec_context);
+		expect(info[i].properties, expected[i].properties);
+	}
+
+	ret = ffa_rx_release();
+	expect(ret.ret0, FFA_SUCCESS_SMC32);
+}
+
+static void ffa_partition_info_wrong_test(void)
+{
+	const char *test_wrong_uuid = "Request wrong UUID";
+	uint32_t uuid[4] = {1};
+
+	announce_test_start(test_wrong_uuid);
+
+	smc_ret_values ret = ffa_partition_info_get(uuid);
+	expect(ret.ret0, FFA_ERROR);
+	expect(ret.ret2, FFA_ERROR_INVALID_PARAMETER);
+
+	announce_test_end(test_wrong_uuid);
+}
+
+static void ffa_partition_info_get_test(struct mailbox_buffers *mb)
+{
+	const char *test_partition_info = "FFA Partition info interface";
+	const char *test_primary = "Get primary partition info";
+	const char *test_secondary = "Get secondary partition info";
+	const char *test_all = "Get all partitions info";
+
+	const struct ffa_partition_info expected_info[] = {
+		{.id = SPM_VM_ID_FIRST, .exec_context = 8, .properties = 0}, /* Primary partition info */
+		{.id = 2, .exec_context = 2, .properties = 0} /* Secondary partition info */
+	};
+
+	announce_test_section_start(test_partition_info);
+
+	announce_test_start(test_secondary);
+	ffa_partition_info_helper(mb, secondary_uuid, &expected_info[1], 1);
+	announce_test_end(test_secondary);
+
+	announce_test_start(test_primary);
+	ffa_partition_info_helper(mb, primary_uuid, &expected_info[0], 1);
+	announce_test_end(test_primary);
+
+	announce_test_start(test_all);
+	ffa_partition_info_helper(mb, null_uuid, expected_info, 2);
+	announce_test_end(test_all);
+
+	ffa_partition_info_wrong_test();
+
+	announce_test_section_end(test_partition_info);
+}
+
+void ffa_tests(struct mailbox_buffers *mb)
 {
 	const char *test_ffa = "FFA Interfaces";
 	const char *test_ffa_version = "FFA Version interface";
@@ -99,6 +168,7 @@
 	announce_test_end(test_ffa_version);
 
 	ffa_features_test();
+	ffa_partition_info_get_test(mb);
 
 	announce_test_section_end(test_ffa);
 }
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 49764ec..31906d5 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -102,12 +102,12 @@
 		(void *)CACTUS_BSS_START, (void *)CACTUS_BSS_END);
 
 	NOTICE("  RX                     : %p - %p\n",
-		(void *)(CACTUS_RX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
-		(void *)(CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)));
+		(void *)get_sp_rx_start(vm_id),
+		(void *)get_sp_rx_end(vm_id));
 
 	NOTICE("  TX                     : %p - %p\n",
-		(void *)(CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
-		(void *)(CACTUS_RX_BASE + (vm_id * CACTUS_RX_TX_SIZE)));
+		(void *)get_sp_tx_start(vm_id),
+		(void *)get_sp_tx_end(vm_id));
 }
 
 static void cactus_plat_configure_mmu(unsigned int vm_id)
@@ -129,13 +129,13 @@
 			CACTUS_BSS_END - CACTUS_BSS_START,
 			MT_RW_DATA);
 
-	mmap_add_region((CACTUS_RX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
-			(CACTUS_RX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
+	mmap_add_region(get_sp_rx_start(vm_id),
+			get_sp_rx_start(vm_id),
 			(CACTUS_RX_TX_SIZE / 2),
 			MT_RO_DATA);
 
-	mmap_add_region((CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
-			(CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
+	mmap_add_region(get_sp_tx_start(vm_id),
+			get_sp_tx_start(vm_id),
 			(CACTUS_RX_TX_SIZE / 2),
 			MT_RW_DATA);
 
@@ -147,6 +147,7 @@
 {
 	assert(IS_IN_EL1() != 0);
 
+	struct mailbox_buffers mb;
 	/* Clear BSS */
 	memset((void *)CACTUS_BSS_START,
 	       0, CACTUS_BSS_END - CACTUS_BSS_START);
@@ -159,6 +160,8 @@
 	}
 
 	ffa_vm_id_t ffa_id = ffa_id_ret.ret2 & 0xffff;
+	mb.send = (void *) get_sp_tx_start(ffa_id);
+	mb.recv = (void *) get_sp_rx_start(ffa_id);
 
 	/* Configure and enable Stage-1 MMU, enable D-Cache */
 	cactus_plat_configure_mmu(ffa_id);
@@ -190,7 +193,7 @@
 	cactus_print_memory_layout(ffa_id);
 
 	/* Invoking Tests */
-	ffa_tests();
+	ffa_tests(&mb);
 
 	/* End up to message loop */
 	message_loop(ffa_id);
diff --git a/spm/cactus/cactus_tests.h b/spm/cactus/cactus_tests.h
index 23586f5..2e13a6f 100644
--- a/spm/cactus/cactus_tests.h
+++ b/spm/cactus/cactus_tests.h
@@ -7,6 +7,8 @@
 #ifndef CACTUS_TESTS_H
 #define CACTUS_TESTS_H
 
+#include <ffa_helpers.h>
+
 /*
  * Test functions
  */
@@ -14,7 +16,7 @@
 /*
  * Test to FFA interfaces.
  */
-void ffa_tests(void);
+void ffa_tests(struct mailbox_buffers *mb);
 
 /*
  * Test other things like the version number returned by SPM.
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index 6e7eca3..c90cac8 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -223,3 +223,27 @@
 
 	return tftf_smc(&args);
 }
+
+/* Get information about VMs or SPs based on UUID */
+smc_ret_values ffa_partition_info_get(const uint32_t uuid[4])
+{
+	smc_args args = {
+		.fid = FFA_PARTITION_INFO_GET,
+		.arg1 = uuid[0],
+		.arg2 = uuid[1],
+		.arg3 = uuid[2],
+		.arg4 = uuid[3]
+	};
+
+	return tftf_smc(&args);
+}
+
+/* Query SPMD that the rx buffer of the partition can be released */
+smc_ret_values ffa_rx_release(void)
+{
+	smc_args args = {
+		.fid = FFA_RX_RELEASE
+	};
+
+	return tftf_smc(&args);
+}