feat(ff-a): partition information via registers

This patch enables basic support for getting partition information via
the ffa_partition_info_get_regs abi. This interface can be used to query
partition information in the absence of rx/tx buffer or when using
memory is inconvenient (such as early boot loaders etc). The patch adds
the required calls, a few helper functions and enables the use of x8-x17
as return values, that is required for this abi to work.

Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
Change-Id: I70ed78e809a5bf77d77a49e5bc122c1989303ebb
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 8ce6ed3..a7cdcb5 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -22,7 +22,7 @@
 typedef uint8_t ffa_memory_receiver_flags_t;
 
 struct ffa_uuid {
-	const uint32_t uuid[4];
+	uint32_t uuid[4];
 };
 
 /** Length in bytes of the name in boot information descriptor. */
@@ -188,6 +188,16 @@
 	u_register_t arg5;
 	u_register_t arg6;
 	u_register_t arg7;
+	u_register_t arg8;
+	u_register_t arg9;
+	u_register_t arg10;
+	u_register_t arg11;
+	u_register_t arg12;
+	u_register_t arg13;
+	u_register_t arg14;
+	u_register_t arg15;
+	u_register_t arg16;
+	u_register_t arg17;
 };
 
 /* Function to make an SMC or SVC service call depending on the exception
@@ -237,6 +247,47 @@
 	return (uint32_t)val.arg2;
 }
 
+static inline uint16_t ffa_partition_info_regs_get_last_idx(
+	struct ffa_value args)
+{
+	return args.arg2 & 0xFFFF;
+}
+
+static inline uint16_t ffa_partition_info_regs_get_curr_idx(
+	struct ffa_value args)
+{
+	return (args.arg2 >> 16) & 0xFFFF;
+}
+
+static inline uint16_t ffa_partition_info_regs_get_tag(struct ffa_value args)
+{
+	return (args.arg2 >> 32) & 0xFFFF;
+}
+
+static inline uint16_t ffa_partition_info_regs_get_desc_size(
+	struct ffa_value args)
+{
+	return (args.arg2 >> 48);
+}
+
+static inline uint32_t ffa_partition_info_regs_partition_count(
+		struct ffa_value args)
+{
+	return ffa_partition_info_regs_get_last_idx(args) + 1;
+}
+
+static inline uint32_t ffa_partition_info_regs_entry_count(
+		struct ffa_value args, uint16_t start_idx)
+{
+	return (ffa_partition_info_regs_get_curr_idx(args) - start_idx + 1);
+}
+
+static inline uint16_t ffa_partition_info_regs_entry_size(
+		struct ffa_value args)
+{
+	return (args.arg2 >> 48) & 0xFFFFU;
+}
+
 typedef uint64_t ffa_notification_bitmap_t;
 
 #define FFA_NOTIFICATION(ID)		(UINT64_C(1) << ID)
@@ -703,7 +754,9 @@
 struct ffa_value ffa_notification_info_get(void);
 
 struct ffa_value ffa_console_log(const char* message, size_t char_count);
-
+struct ffa_value ffa_partition_info_get_regs(const struct ffa_uuid uuid,
+					     const uint16_t start_index,
+					     const uint16_t tag);
 #endif /* __ASSEMBLY__ */
 
 #endif /* FFA_HELPERS_H */
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index 6236ae3..bf535ea 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -100,6 +100,7 @@
 #define FFA_FNUM_SPM_ID_GET			U(0x85)
 #define FFA_FNUM_MSG_SEND2			U(0x86)
 #define FFA_FNUM_SECONDARY_EP_REGISTER		U(0x87)
+#define FFA_FNUM_PARTITION_INFO_GET_REGS	U(0x8B)
 
 /* Implementation defined function numbers */
 #define FFA_FNUM_CONSOLE_LOG			U(0x8A)
@@ -165,6 +166,8 @@
 	FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET)
 
 #define FFA_FEATURES_MEM_RETRIEVE_REQ_NS_SUPPORT (UINT32_C(1) << 1)
+#define FFA_PARTITION_INFO_GET_REGS_SMC64 \
+	FFA_FID(SMC_64, FFA_FNUM_PARTITION_INFO_GET_REGS)
 
 /* Implementation defined SMC64 FIDs */
 #define FFA_CONSOLE_LOG_SMC64	FFA_FID(SMC_64, FFA_FNUM_CONSOLE_LOG)
diff --git a/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S b/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S
index 0e35a38..93355cc 100644
--- a/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S
+++ b/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S
@@ -8,13 +8,18 @@
 
 	.macro service_call _conduit
 	/*
-	 * Save the address of the ffa_value structure on the stack.
-	 *
-	 * Although x0 contains an 8-byte value, we are allocating 16 bytes
+	 * Use a callee saved register to point to ffa_value structure after
+	 * returning from the conduit.
+	 * Although x19 contains an 8-byte value, we are allocating 16 bytes
 	 * on the stack to respect the 16-byte stack-alignment.
 	 */
-	str	x0, [sp, #-16]!
+	str	x19, [sp, #-16]!
 
+	/*
+	 * Save pointed to ffa_value structure into x19, which is a callee saved
+	 * register.
+	 */
+	mov	x19, x0
 	/* Load the argument values into the appropriate registers. */
 	ldp	x6, x7, [x0, #48]
 	ldp	x4, x5, [x0, #32]
@@ -24,20 +29,19 @@
 	\_conduit	#0
 
 	/*
-	 * Pop the ffa_value structure address from the stack into a
-	 * caller-saved register.
+	 * The return values are stored in x0-x17, put them in the ffa_value
+	 * return structure. x19 points to the ffa_value structure.
 	 */
-	ldr	x9, [sp], #16
-
-	/*
-	 * The return values are stored in x0-x7, put them in the ffa_value
-	 * return structure.
-	 */
-	stp	x0, x1, [x9, #0]
-	stp	x2, x3, [x9, #16]
-	stp	x4, x5, [x9, #32]
-	stp	x6, x7, [x9, #48]
-
+	stp	x0, x1, [x19, #0]
+	stp	x2, x3, [x19, #16]
+	stp	x4, x5, [x19, #32]
+	stp	x6, x7, [x19, #48]
+	stp	x8, x9, [x19, #64]
+	stp	x10, x11, [x19, #80]
+	stp	x12, x13, [x19, #96]
+	stp	x14, x15, [x19, #112]
+	stp	x16, x17, [x19, #128]
+	ldr	x19, [sp], #16
 	.endm
 
 .globl ffa_svc
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index 55221da..9547c07 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -382,6 +382,25 @@
 	return ffa_service_call(&args);
 }
 
+/* Get information about VMs or SPs based on UUID, using registers. */
+struct ffa_value ffa_partition_info_get_regs(const struct ffa_uuid uuid,
+					     const uint16_t start_index,
+					     const uint16_t tag)
+{
+	uint64_t arg1 = (uint64_t)uuid.uuid[1] << 32 | uuid.uuid[0];
+	uint64_t arg2 = (uint64_t)uuid.uuid[3] << 32 | uuid.uuid[2];
+	uint64_t arg3 = start_index | (uint64_t)tag << 16;
+
+	struct ffa_value args = {
+		.fid = FFA_PARTITION_INFO_GET_REGS_SMC64,
+		.arg1 = arg1,
+		.arg2 = arg2,
+		.arg3 = arg3,
+	};
+
+	return ffa_service_call(&args);
+}
+
 /* Get information about VMs or SPs based on UUID */
 struct ffa_value ffa_partition_info_get(const struct ffa_uuid uuid)
 {