feat(intel): support extended random number generation

The random number generation (RNG) mailbox command format
is updated to extends the support to upto 4080 bytes random
number generation. The new RNG format requires an opened
crypto service session.

A separated SMC function ID is introduced for the new RNG
format and it is only supported by Agilex.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Signed-off-by: Boon Khai Ng <boon.khai.ng@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: I3f044a3c01ff7cb50be4705e2c1f982bf6f61432
diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h
index 294d1e5..da982e1 100644
--- a/plat/intel/soc/common/include/socfpga_fcs.h
+++ b/plat/intel/soc/common/include/socfpga_fcs.h
@@ -14,9 +14,12 @@
 #define FCS_SHA384_WORD_SIZE		12U
 
 #define FCS_RANDOM_BYTE_SIZE		(FCS_RANDOM_WORD_SIZE * 4U)
+#define FCS_RANDOM_EXT_MAX_WORD_SIZE	1020U
 #define FCS_PROV_DATA_BYTE_SIZE		(FCS_PROV_DATA_WORD_SIZE * 4U)
 #define FCS_SHA384_BYTE_SIZE		(FCS_SHA384_WORD_SIZE * 4U)
 
+#define FCS_RANDOM_EXT_OFFSET		3
+
 #define FCS_MODE_DECRYPT		0x0
 #define FCS_MODE_ENCRYPT		0x1
 #define FCS_ENCRYPTION_DATA_0		0x10100
@@ -55,7 +58,19 @@
 #define FCS_CS_KEY_RESP_STATUS_MASK	0xFF
 #define FCS_CS_KEY_RESP_STATUS_OFFSET	16U
 
+#define FCS_CS_FIELD_SIZE_MASK		0xFFFF
+#define FCS_CS_FIELD_FLAG_OFFSET	24
+#define FCS_CS_FIELD_FLAG_INIT		BIT(0)
+#define FCS_CS_FIELD_FLAG_UPDATE	BIT(1)
+#define FCS_CS_FIELD_FLAG_FINALIZE	BIT(2)
+
 /* FCS Payload Structure */
+typedef struct fcs_rng_payload_t {
+	uint32_t session_id;
+	uint32_t context_id;
+	uint32_t crypto_header;
+	uint32_t size;
+} fcs_rng_payload;
 
 typedef struct fcs_encrypt_payload_t {
 	uint32_t first_word;
@@ -96,6 +111,8 @@
 
 uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
 				uint32_t *mbox_error);
+int intel_fcs_random_number_gen_ext(uint32_t session_id, uint32_t context_id,
+				uint32_t size, uint32_t *send_id);
 uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
 				uint32_t *send_id);
 uint32_t intel_fcs_get_provision_data(uint32_t *send_id);
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index fb0c661..e790669 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -76,6 +76,7 @@
 
 /* FPGA Crypto Services */
 #define INTEL_SIP_SMC_FCS_RANDOM_NUMBER			0xC200005A
+#define INTEL_SIP_SMC_FCS_RANDOM_NUMBER_EXT		0x4200008F
 #define INTEL_SIP_SMC_FCS_CRYPTION			0x4200005B
 #define INTEL_SIP_SMC_FCS_SEND_CERTIFICATE		0x4200005D
 #define INTEL_SIP_SMC_FCS_GET_PROVISION_DATA		0x4200005E
@@ -96,8 +97,8 @@
 /* ECC DBE */
 #define WARM_RESET_WFI_FLAG				BIT(31)
 #define SYSMGR_ECC_DBE_COLD_RST_MASK			(SYSMGR_ECC_OCRAM_MASK |\
-							SYSMGR_ECC_DDR0_MASK |\
-							SYSMGR_ECC_DDR1_MASK)
+								SYSMGR_ECC_DDR0_MASK |\
+								SYSMGR_ECC_DDR1_MASK)
 
 /* Non-mailbox SMC Call */
 #define INTEL_SIP_SMC_SVC_VERSION			0xC2000200
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
index 821beff..7b3069b 100644
--- a/plat/intel/soc/common/sip/socfpga_sip_fcs.c
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -57,6 +57,45 @@
 	return INTEL_SIP_SMC_STATUS_OK;
 }
 
+int intel_fcs_random_number_gen_ext(uint32_t session_id, uint32_t context_id,
+				uint32_t size, uint32_t *send_id)
+{
+	int status;
+	uint32_t payload_size;
+	uint32_t crypto_header;
+
+	if (size > (FCS_RANDOM_EXT_MAX_WORD_SIZE *
+		MBOX_WORD_BYTE) || size == 0U) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if (!is_size_4_bytes_aligned(size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	crypto_header = (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_FINALIZE) <<
+			FCS_CS_FIELD_FLAG_OFFSET;
+
+	fcs_rng_payload payload = {
+		session_id,
+		context_id,
+		crypto_header,
+		size
+	};
+
+	payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+	status = mailbox_send_cmd_async(send_id, MBOX_FCS_RANDOM_GEN,
+					(uint32_t *) &payload, payload_size,
+					CMD_INDIRECT);
+
+	if (status < 0) {
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
 uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
 					uint32_t *send_id)
 {
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index cdb71bf..24683ea 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -791,6 +791,11 @@
 							&mbox_error);
 		SMC_RET4(handle, status, mbox_error, x1, retval64);
 
+	case INTEL_SIP_SMC_FCS_RANDOM_NUMBER_EXT:
+		status = intel_fcs_random_number_gen_ext(x1, x2, x3,
+							&send_id);
+		SMC_RET1(handle, status);
+
 	case INTEL_SIP_SMC_FCS_SEND_CERTIFICATE:
 		status = intel_fcs_send_cert(x1, x2, &send_id);
 		SMC_RET1(handle, status);