SPMD: Add support for SPCI_ID_GET

This patch introduces the `SPCI_ID_GET` interface which will return the
ID of the calling SPCI component. Returns 0 for requests from the
non-secure world and the spmc component ID as specified in the manifest
for secure world requests.

Change-Id: Id61725f8195106f9a30d61b9d99ed1d7da8c1163
diff --git a/include/services/spm_core_manifest.h b/include/services/spm_core_manifest.h
index 8dfb696..cddd263 100644
--- a/include/services/spm_core_manifest.h
+++ b/include/services/spm_core_manifest.h
@@ -49,6 +49,11 @@
 	 */
 	uint32_t binary_size;
 
+	/*
+	 * ID of the SPMC (mandatory).
+	 */
+	uint16_t spmc_id;
+
 } spmc_manifest_sect_attribute_t;
 
 #endif /* SPMC_MANIFEST_H */
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 602b465..5906745 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -4,6 +4,7 @@
 	compatible = "arm,spmc_rd";
 
 	attribute {
+		spmc_id = <0x8000>;
 		maj_ver = <0x0>;
 		min_ver = <0x9>;
 		runtime_el = <0x1>;
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index ea06d5b..f63674b 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -45,6 +45,12 @@
 		return -ENOENT;
 	}
 
+	rc = fdtw_read_cells(fdt, node, "spmc_id", 1, &attr->spmc_id);
+	if (rc) {
+		ERROR("Missing SPMC ID in manifest.\n");
+		return -ENOENT;
+	}
+
 	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
 	if (rc)
 		NOTICE("Execution state not specified in SPM core manifest.\n");
@@ -63,6 +69,7 @@
 
 	VERBOSE("SPM core manifest attribute section:\n");
 	VERBOSE("  version: %x.%x\n", attr->major_version, attr->minor_version);
+	VERBOSE("  spmc id: %x\n", attr->spmc_id);
 	VERBOSE("  runtime_el: 0x%x\n", attr->runtime_el);
 	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
 	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 251c05d..ad88536 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -208,6 +208,16 @@
 
 	INFO("SPM core run time EL%x.\n", spmc_attrs.runtime_el);
 
+	/* Validate the SPMC ID, Ensure high bit is set */
+	if (!(spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) &
+                SPMC_SECURE_ID_MASK) {
+		WARN("Invalid ID (0x%x) for SPMC.\n",
+		     spmc_attrs.spmc_id);
+		goto error;
+	}
+
+	INFO("SPMC ID %x.\n", spmc_attrs.spmc_id);
+
 	/* Validate the SPM core execution state */
 	if ((spmc_attrs.exec_state != MODE_RW_64) &&
 	    (spmc_attrs.exec_state != MODE_RW_32)) {
@@ -392,6 +402,29 @@
 				 SMC_GET_GP(handle, CTX_GPREG_X6),
 				 SMC_GET_GP(handle, CTX_GPREG_X7));
 		}
+		case SPCI_ID_GET:
+			/*
+			 * Returns the ID of the calling SPCI component.
+			*/
+			if (in_sstate == NON_SECURE) {
+				SMC_RET8(handle, SPCI_SUCCESS,
+				         SPCI_TARGET_INFO_MBZ,
+						 SPCI_NS_ENDPOINT_ID,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ);
+			} else {
+				SMC_RET8(handle, SPCI_SUCCESS,
+				         SPCI_TARGET_INFO_MBZ,
+						 spmc_attrs.spmc_id,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ,
+						 SPCI_PARAM_MBZ);
+			}
 
 	case SPCI_RX_RELEASE:
 	case SPCI_RXTX_MAP_SMC32:
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
index eb9a5c5..4420597 100644
--- a/services/std_svc/spmd/spmd_private.h
+++ b/services/std_svc/spmd/spmd_private.h
@@ -81,6 +81,15 @@
 /* SPMC entry point information */
 extern entry_point_info_t *spmc_ep_info;
 
+/*
+ * Reserve ID for NS physical SPCI Endpoint.
+ */
+#define SPCI_NS_ENDPOINT_ID U(0)
+
+/* Mask and shift to check valid secure SPCI Endpoint ID. */
+#define SPMC_SECURE_ID_MASK     0x1
+#define SPMC_SECURE_ID_SHIFT    15
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* SPMD_PRIVATE_H */