feat(intel): single certificate feature enablement

Extend the functionality of FPGA Crypto Service
(FCS) to support FPGA single certificate feature
so that the counter value can be updated with
only one preauthorized certificate

Signed-off-by: Boon Khai Ng <boon.khai.ng@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: Ibde87e4ee46367cf7f27f7bb0172838ab8766340
diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h
index d5125df..1df1639 100644
--- a/plat/intel/soc/common/include/socfpga_fcs.h
+++ b/plat/intel/soc/common/include/socfpga_fcs.h
@@ -28,6 +28,17 @@
 #define PSGSIGMA_UNKNOWN_SESSION	0xFFFFFFFF
 
 #define	RESERVED_AS_ZERO		0x0
+/* FCS Single cert */
+
+#define FCS_BIG_CNTR_SEL		0x1
+
+#define FCS_SVN_CNTR_0_SEL		0x2
+#define FCS_SVN_CNTR_1_SEL		0x3
+#define FCS_SVN_CNTR_2_SEL		0x4
+#define FCS_SVN_CNTR_3_SEL		0x5
+
+#define FCS_BIG_CNTR_VAL_MAX		495U
+#define FCS_SVN_CNTR_VAL_MAX		64U
 
 /* FCS Payload Structure */
 
@@ -54,6 +65,10 @@
 	uint32_t session_id;
 } psgsigma_teardown_msg;
 
+typedef struct fcs_cntr_set_preauth_payload_t {
+	uint32_t first_word;
+	uint32_t counter_value;
+} fcs_cntr_set_preauth_payload;
 
 /* Functions Definitions */
 
@@ -62,6 +77,10 @@
 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);
+uint32_t intel_fcs_cntr_set_preauth(uint8_t counter_type,
+				int32_t counter_value,
+				uint32_t test_bit,
+				uint32_t *mbox_error);
 uint32_t intel_fcs_encryption(uint32_t src_addr, uint32_t src_size,
 				uint32_t dst_addr, uint32_t dst_size,
 				uint32_t *send_id);
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index eafe241..64024b8 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -16,7 +16,7 @@
 #define MBOX_MAX_JOB_ID			0xFU
 #define MBOX_MAX_IND_JOB_ID		(MBOX_MAX_JOB_ID - 1U)
 #define MBOX_JOB_ID			MBOX_MAX_JOB_ID
-
+#define MBOX_TEST_BIT			BIT(31)
 
 /* Mailbox Shared Memory Register Map */
 #define MBOX_CIN			0x00
@@ -71,6 +71,7 @@
 
 /* FCS Command */
 #define MBOX_FCS_GET_PROVISION			0x7B
+#define MBOX_FCS_CNTR_SET_PREAUTH		0x7C
 #define MBOX_FCS_ENCRYPT_REQ			0x7E
 #define MBOX_FCS_DECRYPT_REQ			0x7F
 #define MBOX_FCS_RANDOM_GEN			0x80
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 26db14b..53aece3 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -73,6 +73,7 @@
 
 /* FPGA Crypto Services */
 #define INTEL_SIP_SMC_FCS_CRYPTION			0x4200005B
+#define INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH			0xC200005F
 #define INTEL_SIP_SMC_FCS_PSGSIGMA_TEARDOWN			0xC2000064
 #define INTEL_SIP_SMC_FCS_CHIP_ID				0xC2000065
 #define INTEL_SIP_SMC_FCS_ATTESTATION_SUBKEY			0xC2000066
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
index 4b06fa6..26da55e 100644
--- a/plat/intel/soc/common/sip/socfpga_sip_fcs.c
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -95,6 +95,53 @@
 	return INTEL_SIP_SMC_STATUS_OK;
 }
 
+uint32_t intel_fcs_cntr_set_preauth(uint8_t counter_type, int32_t counter_value,
+					uint32_t test_bit, uint32_t *mbox_error)
+{
+	int status;
+	uint32_t first_word;
+	uint32_t payload_size;
+
+	if ((test_bit != MBOX_TEST_BIT) &&
+		(test_bit != 0)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if ((counter_type < FCS_BIG_CNTR_SEL) ||
+		(counter_type > FCS_SVN_CNTR_3_SEL)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if ((counter_type == FCS_BIG_CNTR_SEL) &&
+		(counter_value > FCS_BIG_CNTR_VAL_MAX)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if ((counter_type >= FCS_SVN_CNTR_0_SEL) &&
+		(counter_type <= FCS_SVN_CNTR_3_SEL) &&
+		(counter_value > FCS_SVN_CNTR_VAL_MAX)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	first_word = test_bit | counter_type;
+	fcs_cntr_set_preauth_payload payload = {
+		first_word,
+		counter_value
+	};
+
+	payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+	status =  mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_CNTR_SET_PREAUTH,
+				  (uint32_t *) &payload, payload_size,
+				  CMD_CASUAL, NULL, NULL);
+
+	if (status < 0) {
+		*mbox_error = -status;
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
 uint32_t intel_fcs_encryption(uint32_t src_addr, uint32_t src_size,
 		uint32_t dst_addr, uint32_t dst_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 851bc94..294040b 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -724,6 +724,11 @@
 
 		SMC_RET3(handle, status, x4, x5);
 
+	case INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH:
+		status = intel_fcs_cntr_set_preauth(x1, x2, x3,
+							&mbox_error);
+		SMC_RET2(handle, status, mbox_error);
+
 	case INTEL_SIP_SMC_HPS_SET_BRIDGES:
 		status = intel_hps_set_bridges(x1, x2);
 		SMC_RET1(handle, status);