fix(intel): update encryption and decryption command logic

This change is to re-align HPS cryption logic with
underlying Secure Device Manager's (SDM) mailbox API.

Signed-off-by: Abdul Halim, Muhammad Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: I8fc90982d3cddceaf401c1a112ff8e20861bf4c5
diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h
index d3b7141..a3efd80 100644
--- a/plat/intel/soc/common/include/socfpga_fcs.h
+++ b/plat/intel/soc/common/include/socfpga_fcs.h
@@ -17,17 +17,30 @@
 #define FCS_PROV_DATA_BYTE_SIZE		(FCS_PROV_DATA_WORD_SIZE * 4U)
 #define FCS_SHA384_BYTE_SIZE		(FCS_SHA384_WORD_SIZE * 4U)
 
-#define FCS_CRYPTION_DATA_0		0x10100
+#define FCS_MODE_DECRYPT		0x0
+#define FCS_MODE_ENCRYPT		0x1
+#define FCS_ENCRYPTION_DATA_0		0x10100
+#define FCS_DECRYPTION_DATA_0		0x10102
+#define FCS_OWNER_ID_OFFSET		0xC
 
 /* FCS Payload Structure */
 
-typedef struct fcs_crypt_payload_t {
+typedef struct fcs_encrypt_payload_t {
 	uint32_t first_word;
 	uint32_t src_addr;
 	uint32_t src_size;
 	uint32_t dst_addr;
 	uint32_t dst_size;
-} fcs_crypt_payload;
+} fcs_encrypt_payload;
+
+typedef struct fcs_decrypt_payload_t {
+	uint32_t first_word;
+	uint32_t owner_id[2];
+	uint32_t src_addr;
+	uint32_t src_size;
+	uint32_t dst_addr;
+	uint32_t dst_size;
+} fcs_decrypt_payload;
 
 /* Functions Definitions */
 
@@ -36,9 +49,13 @@
 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_cryption(uint32_t mode, uint32_t src_addr,
-			uint32_t src_size, uint32_t dst_addr,
-			uint32_t dst_size, uint32_t *send_id);
+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);
+
+uint32_t intel_fcs_decryption(uint32_t src_addr, uint32_t src_size,
+				uint32_t dst_addr, uint32_t dst_size,
+				uint32_t *send_id);
 
 uint32_t intel_fcs_get_rom_patch_sha384(uint64_t addr, uint64_t *ret_size,
 				uint32_t *mbox_error);
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index ca6f1f8..fcd5450 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -71,7 +71,8 @@
 /* Mailbox Command */
 #define INTEL_SIP_SMC_GET_USERCODE			0xC200003D
 
-/* SiP Definitions */
+/* FPGA Crypto Services */
+#define INTEL_SIP_SMC_FCS_CRYPTION			0x4200005B
 
 /* ECC DBE */
 #define WARM_RESET_WFI_FLAG				BIT(31)
@@ -103,7 +104,7 @@
 };
 
 /* Function Definitions */
-
+bool is_size_4_bytes_aligned(uint32_t size);
 bool is_address_in_ddr_range(uint64_t addr, uint64_t size);
 
 /* ECC DBE */
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
index 85551a4..a174e5f 100644
--- a/plat/intel/soc/common/sip/socfpga_sip_fcs.c
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -11,7 +11,7 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_sip_svc.h"
 
-static bool is_size_4_bytes_aligned(uint32_t size)
+bool is_size_4_bytes_aligned(uint32_t size)
 {
 	if ((size % MBOX_WORD_BYTE) != 0U) {
 		return false;
@@ -95,37 +95,70 @@
 	return INTEL_SIP_SMC_STATUS_OK;
 }
 
-uint32_t intel_fcs_cryption(uint32_t mode, uint32_t src_addr,
-		uint32_t src_size, uint32_t dst_addr,
-		uint32_t dst_size, uint32_t *send_id)
+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)
 {
 	int status;
-	uint32_t cmd;
+	uint32_t load_size;
 
-	fcs_crypt_payload payload = {
-		FCS_CRYPTION_DATA_0,
+	fcs_encrypt_payload payload = {
+		FCS_ENCRYPTION_DATA_0,
 		src_addr,
 		src_size,
 		dst_addr,
 		dst_size };
+	load_size = sizeof(payload) / MBOX_WORD_BYTE;
 
 	if (!is_address_in_ddr_range(src_addr, src_size) ||
 		!is_address_in_ddr_range(dst_addr, dst_size)) {
 		return INTEL_SIP_SMC_STATUS_REJECTED;
 	}
 
-	if (!is_size_4_bytes_aligned(sizeof(fcs_crypt_payload))) {
+	if (!is_size_4_bytes_aligned(src_size)) {
 		return INTEL_SIP_SMC_STATUS_REJECTED;
 	}
 
-	if (mode != 0U) {
-		cmd = MBOX_FCS_ENCRYPT_REQ;
-	} else {
-		cmd = MBOX_FCS_DECRYPT_REQ;
+	status = mailbox_send_cmd_async(send_id, MBOX_FCS_ENCRYPT_REQ,
+				(uint32_t *) &payload, load_size,
+				CMD_INDIRECT);
+	inv_dcache_range(dst_addr, dst_size);
+
+	if (status < 0) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_decryption(uint32_t src_addr, uint32_t src_size,
+		uint32_t dst_addr, uint32_t dst_size, uint32_t *send_id)
+{
+	int status;
+	uint32_t load_size;
+	uintptr_t id_offset;
+
+	id_offset = src_addr + FCS_OWNER_ID_OFFSET;
+	fcs_decrypt_payload payload = {
+		FCS_DECRYPTION_DATA_0,
+		{mmio_read_32(id_offset),
+		mmio_read_32(id_offset + MBOX_WORD_BYTE)},
+		src_addr,
+		src_size,
+		dst_addr,
+		dst_size };
+	load_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+	if (!is_address_in_ddr_range(src_addr, src_size) ||
+		!is_address_in_ddr_range(dst_addr, dst_size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if (!is_size_4_bytes_aligned(src_size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
 	}
 
-	status = mailbox_send_cmd_async(send_id, cmd, (uint32_t *) &payload,
-				sizeof(fcs_crypt_payload) / MBOX_WORD_BYTE,
+	status = mailbox_send_cmd_async(send_id, MBOX_FCS_DECRYPT_REQ,
+				(uint32_t *) &payload, load_size,
 				CMD_INDIRECT);
 	inv_dcache_range(dst_addr, dst_size);
 
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 79444cf..a80208f 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -711,6 +711,19 @@
 		status = intel_smc_get_usercode(&retval);
 		SMC_RET2(handle, status, retval);
 
+	case INTEL_SIP_SMC_FCS_CRYPTION:
+		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+
+		if (x1 == FCS_MODE_DECRYPT) {
+			status = intel_fcs_decryption(x2, x3, x4, x5, &send_id);
+		} else if (x1 == FCS_MODE_ENCRYPT) {
+			status = intel_fcs_encryption(x2, x3, x4, x5, &send_id);
+		} else {
+			status = INTEL_SIP_SMC_STATUS_REJECTED;
+		}
+
+		SMC_RET3(handle, status, x4, x5);
+
 	case INTEL_SIP_SMC_HPS_SET_BRIDGES:
 		status = intel_hps_set_bridges(x1, x2);
 		SMC_RET1(handle, status);