PSCI: Introduce PSCI Library argument structure

This patch introduces a `psci_lib_args_t` structure which must be
passed into `psci_setup()` which is then used to initialize the PSCI
library. The `psci_lib_args_t` is a versioned structure so as to enable
compatibility checks during library initialization. Both BL31 and SP_MIN
are modified to use the new structure.

SP_MIN is also modified to add version string and build message as part
of its cold boot log just like the other BLs in Trusted Firmware.

NOTE: Please be aware that this patch modifies the prototype of
`psci_setup()`, which breaks compatibility with EL3 Runtime Firmware
(excluding BL31 and SP_MIN) integrated with the PSCI Library.

Change-Id: Ic3761db0b790760a7ad664d8a437c72ea5edbcd6
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index f95ef41..7b0b675 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -58,13 +58,16 @@
  ******************************************************************************/
 void bl31_lib_init(void)
 {
+	/* Setup the arguments for PSCI Library */
+	DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, bl31_warm_entrypoint);
+
 	cm_init();
 
 	/*
 	 * Initialize the PSCI library here. This also does EL3 architectural
 	 * setup.
 	 */
-	psci_setup((uintptr_t)bl31_warm_entrypoint);
+	psci_setup(&psci_args);
 }
 
 /*******************************************************************************
diff --git a/bl32/sp_min/sp_min_main.c b/bl32/sp_min/sp_min_main.c
index 31cab3d..c1ba8fc 100644
--- a/bl32/sp_min/sp_min_main.c
+++ b/bl32/sp_min/sp_min_main.c
@@ -156,14 +156,20 @@
  *****************************************************************************/
 void sp_min_main(void)
 {
-	/* Perform platform setup in TSP MIN */
+	/* Setup the arguments for PSCI Library */
+	DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, sp_min_warm_entrypoint);
+
+	NOTICE("SP_MIN: %s\n", version_string);
+	NOTICE("SP_MIN: %s\n", build_message);
+
+	/* Perform the SP_MIN platform setup */
 	sp_min_platform_setup();
 
 	/*
 	 * Initialize the PSCI library and perform the remaining generic
 	 * architectural setup from PSCI.
 	 */
-	psci_setup((uintptr_t)sp_min_warm_entrypoint);
+	psci_setup(&psci_args);
 
 	/*
 	 * Initialize the runtime services e.g. psci
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 9fa2a81..12d5036 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -103,6 +103,7 @@
 #define PARAM_BL31		0x03
 #define PARAM_BL_LOAD_INFO	0x04
 #define PARAM_BL_PARAMS		0x05
+#define PARAM_PSCI_LIB_ARGS	0x06
 
 #define IMAGE_ATTRIB_SKIP_LOADING	0x02
 #define IMAGE_ATTRIB_PLAT_SETUP		0x04
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 02cbbf3..34de4c2 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -32,6 +32,7 @@
 #define __PSCI_H__
 
 #include <bakery_lock.h>
+#include <bl_common.h>
 #include <platform_def.h>	/* for PLAT_NUM_PWR_DOMAINS */
 #if ENABLE_PLAT_COMPAT
 #include <psci_compat.h>
@@ -356,10 +357,45 @@
  */
 void psci_entrypoint(void) __deprecated;
 
-/*******************************************************************************
- * Forward declarations
- ******************************************************************************/
-struct entry_point_info;
+/*
+ * Function prototype for the warmboot entrypoint function which will be
+ * programmed in the mailbox by the platform.
+ */
+typedef void (*mailbox_entrypoint_t)(void);
+
+/******************************************************************************
+ * Structure to pass PSCI Library arguments.
+ *****************************************************************************/
+typedef struct psci_lib_args {
+	/* The version information of PSCI Library Interface */
+	param_header_t		h;
+	/* The warm boot entrypoint function */
+	mailbox_entrypoint_t	mailbox_ep;
+} psci_lib_args_t;
+
+/* Helper macro to set the psci_lib_args_t structure at runtime */
+#define SET_PSCI_LIB_ARGS_V1(_p, _entry)	do {			\
+	SET_PARAM_HEAD(_p, PARAM_PSCI_LIB_ARGS, VERSION_1, 0);		\
+	(_p)->mailbox_ep = (_entry);					\
+	} while (0)
+
+/* Helper macro to define the psci_lib_args_t statically */
+#define DEFINE_STATIC_PSCI_LIB_ARGS_V1(_name, _entry)		\
+	static const psci_lib_args_t (_name) = {		\
+		.h.type = (uint8_t)PARAM_PSCI_LIB_ARGS,		\
+		.h.version = (uint8_t)VERSION_1,		\
+		.h.size = (uint16_t)sizeof(_name),		\
+		.h.attr = 0,					\
+		.mailbox_ep = (_entry)				\
+	}
+
+/* Helper macro to verify the pointer to psci_lib_args_t structure */
+#define VERIFY_PSCI_LIB_ARGS_V1(_p)	((_p)			\
+		&& ((_p)->h.type == PARAM_PSCI_LIB_ARGS)	\
+		&& ((_p)->h.version == VERSION_1)		\
+		&& ((_p)->h.size == sizeof(*(_p)))		\
+		&& ((_p)->h.attr == 0)				\
+		&& ((_p)->mailbox_ep))
 
 /******************************************************************************
  * PSCI Library Interfaces
@@ -372,11 +408,11 @@
 			  void *cookie,
 			  void *handle,
 			  u_register_t flags);
-int psci_setup(uintptr_t mailbox_ep);
+int psci_setup(const psci_lib_args_t *lib_args);
 void psci_warmboot_entrypoint(void);
 void psci_register_spd_pm_hook(const spd_pm_ops_t *pm);
 void psci_prepare_next_non_secure_ctx(
-			  struct entry_point_info *next_image_info);
+			  entry_point_info_t *next_image_info);
 
 #endif /*__ASSEMBLY__*/
 
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index 263ab68..cb8b77d 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -206,10 +206,12 @@
  * |   CPU 0   |   CPU 1   |   CPU 2   |   CPU 3  |
  * ------------------------------------------------
  ******************************************************************************/
-int psci_setup(uintptr_t mailbox_ep)
+int psci_setup(const psci_lib_args_t *lib_args)
 {
 	const unsigned char *topology_tree;
 
+	assert(VERIFY_PSCI_LIB_ARGS_V1(lib_args));
+
 	/* Do the Architectural initialization */
 	psci_arch_setup();
 
@@ -234,8 +236,7 @@
 	 */
 	psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL);
 
-	assert(mailbox_ep);
-	plat_setup_psci_ops(mailbox_ep, &psci_plat_pm_ops);
+	plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep, &psci_plat_pm_ops);
 	assert(psci_plat_pm_ops);
 
 	/*