feat(runtime/rmi): implement RMI_PDEV_AUX_COUNT

Implement RMI handler to get the number of auxiliary granules
required for a PDEV from PDEV flags.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I30bb4acfe9454b959a1eabce6c7c234e9245dd38
diff --git a/app/common/framework/src/fake_host/app.c b/app/common/framework/src/fake_host/app.c
index c1e6520..065198f 100644
--- a/app/common/framework/src/fake_host/app.c
+++ b/app/common/framework/src/fake_host/app.c
@@ -329,6 +329,12 @@
 	return app_data->app_heap;
 }
 
+size_t app_get_required_granule_count(unsigned long app_id)
+{
+	(void)app_id;
+	return 0U;
+}
+
 /* Used by the Mbed TLS library in case EL3 token signing is active when
  * emulating EL3 signing.
  */
diff --git a/app/common/framework/src/no_app_support/app.c b/app/common/framework/src/no_app_support/app.c
index c72ab2c..34ae176 100644
--- a/app/common/framework/src/no_app_support/app.c
+++ b/app/common/framework/src/no_app_support/app.c
@@ -75,3 +75,9 @@
 
 	return 0;
 }
+
+size_t app_get_required_granule_count(unsigned long app_id)
+{
+	(void)app_id;
+	return 0U;
+}
diff --git a/runtime/core/handler.c b/runtime/core/handler.c
index 54c1aef..2684d89 100644
--- a/runtime/core/handler.c
+++ b/runtime/core/handler.c
@@ -139,7 +139,7 @@
 	HANDLER(DATA_CREATE,		5, 0, smc_data_create,		 false, false),
 	HANDLER(DATA_CREATE_UNKNOWN,	3, 0, smc_data_create_unknown,	 false, false),
 	HANDLER(DATA_DESTROY,		2, 2, smc_data_destroy,		 false, true),
-	HANDLER(PDEV_AUX_COUNT,		0, 0, NULL,			 true, true),
+	HANDLER(PDEV_AUX_COUNT,		1, 1, smc_pdev_aux_count,	 true, true),
 	HANDLER(REALM_ACTIVATE,		1, 0, smc_realm_activate,	 true,  true),
 	HANDLER(REALM_CREATE,		2, 0, smc_realm_create,		 true,  true),
 	HANDLER(REALM_DESTROY,		1, 0, smc_realm_destroy,	 true,  true),
diff --git a/runtime/include/smc-handler.h b/runtime/include/smc-handler.h
index 33557d4..222c5bf 100644
--- a/runtime/include/smc-handler.h
+++ b/runtime/include/smc-handler.h
@@ -109,6 +109,8 @@
 unsigned long smc_pdev_create(unsigned long pdev_ptr,
 			      unsigned long pdev_params_ptr);
 
+void smc_pdev_aux_count(unsigned long flags, struct smc_result *res);
+
 void smc_pdev_get_state(unsigned long pdev_ptr, struct smc_result *res);
 
 unsigned long smc_pdev_destroy(unsigned long pdev_ptr);
diff --git a/runtime/rmi/pdev.c b/runtime/rmi/pdev.c
index 12d3380..6284e7e 100644
--- a/runtime/rmi/pdev.c
+++ b/runtime/rmi/pdev.c
@@ -72,6 +72,48 @@
 	return 0;
 }
 
+static unsigned long pdev_get_aux_count_from_flags(unsigned long pdev_flags)
+{
+	unsigned long aux_count;
+
+	(void)pdev_flags;
+
+	/*
+	 * The current implementation requires that RMI_PDEV_SPDM_TRUE
+	 * is set in the flags.
+	 */
+	assert(EXTRACT(RMI_PDEV_FLAGS_SPDM, pdev_flags) == RMI_PDEV_SPDM_TRUE);
+
+	/*
+	 * Currently, the number of pages required to instantiate an app is
+	 * hardcoded in the app header. In this implementation, aux_count
+	 * does not depend on the flags set in pdev_flags. The worst case
+	 * (i.e., the most granules) is assumed.
+	 */
+	aux_count = app_get_required_granule_count(RMM_DEV_ASSIGN_APP_ID);
+	assert(aux_count <= PDEV_PARAM_AUX_GRANULES_MAX);
+
+	return aux_count;
+}
+
+/*
+ * smc_pdev_aux_count
+ *
+ * Get number of auxiliary Granules required for a PDEV.
+ *
+ * flags	- PDEV flags
+ * res		- SMC result
+ */
+void smc_pdev_aux_count(unsigned long flags, struct smc_result *res)
+{
+	if (is_rmi_feat_da_enabled()) {
+		res->x[0] = RMI_SUCCESS;
+		res->x[1] = pdev_get_aux_count_from_flags(flags);
+	} else {
+		res->x[0] = SMC_NOT_SUPPORTED;
+	}
+}
+
 /*
  * smc_pdev_create
  *
@@ -86,6 +128,7 @@
 	struct pdev *pd;
 	struct rmi_pdev_params pdev_params; /* this consumes 4k of stack */
 	struct granule *pdev_aux_granules[PDEV_PARAM_AUX_GRANULES_MAX];
+	unsigned long num_aux_req;
 	bool ns_access_ok;
 	void *aux_mapped_addr;
 	struct dev_assign_params dparams;
@@ -131,10 +174,19 @@
 		return RMI_ERROR_NOT_SUPPORTED;
 	}
 
-	/* Validate PDEV parameters that are not specific to a device class. */
+	/* Validate PDEV parameters num_aux */
+	num_aux_req = pdev_get_aux_count_from_flags(pdev_params.flags);
 	/* coverity[uninit_use:SUPPRESS] */
-	if ((pdev_params.num_aux > PDEV_PARAM_AUX_GRANULES_MAX) ||
-	    (pdev_params.ncoh_num_addr_range > PDEV_PARAM_NCOH_ADDR_RANGE_MAX)) {
+	if ((pdev_params.num_aux == 0U) ||
+	    (pdev_params.num_aux != num_aux_req)) {
+		ERROR("ERROR: PDEV need %ld aux granules, host allocated %ld.\n",
+		      num_aux_req, pdev_params.num_aux);
+		return RMI_ERROR_INPUT;
+	}
+
+	/* Validate PDEV parameters ncoh_num_addr_range. */
+	/* coverity[uninit_use:SUPPRESS] */
+	if (pdev_params.ncoh_num_addr_range > PDEV_PARAM_NCOH_ADDR_RANGE_MAX) {
 		return RMI_ERROR_INPUT;
 	}