fix(xilinx): handle CRC failure in IPI

Currently, if CRC validation fails during IPI communication,
pm_ipi_buff_read() logs error message but don't return error
code to upper layers.

Added CRC failure specific error code which will be returned by
pm_ipi_buff_read() if CRC validation fails.

Signed-off-by: Naman Trivedi Manojbhai <naman.trivedimanojbhai@amd.com>
Change-Id: I33be330f276973471f4ce4115d1e1609ed8fb754
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index a3c3a6f..81f1939 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -136,7 +136,9 @@
 					   uint32_t *value, size_t count)
 {
 	size_t i;
+	enum pm_ret_status ret;
 #if IPI_CRC_CHECK
+	uint32_t *payload_ptr = value;
 	size_t j;
 	uint32_t response_payload[PAYLOAD_ARG_CNT];
 #endif
@@ -155,6 +157,8 @@
 		*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
 		value++;
 	}
+
+	ret = mmio_read_32(buffer_base);
 #if IPI_CRC_CHECK
 	for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
 		response_payload[j] = mmio_read_32(buffer_base +
@@ -165,10 +169,15 @@
 			calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
 		NOTICE("ERROR in CRC response payload value:0x%x\n",
 					response_payload[PAYLOAD_CRC_POS]);
+		ret = PM_RET_ERROR_INVALID_CRC;
+		/* Payload data is invalid as CRC validation failed
+		 * Clear the payload to avoid leakage of data to upper layers
+		 */
+		memset(payload_ptr, 0, count);
 	}
 #endif
 
-	return mmio_read_32(buffer_base);
+	return ret;
 }
 
 /**
diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h
index 2922b5d..dbc801c 100644
--- a/plat/xilinx/versal/pm_service/pm_defs.h
+++ b/plat/xilinx/versal/pm_service/pm_defs.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -115,11 +116,13 @@
 	XPM_SUBSYSID_MAX,
 } XPm_SubsystemId;
 
+/* TODO: move pm_ret_status from device specific location to common location */
 /**
  * @PM_RET_SUCCESS:		success
  * @PM_RET_ERROR_ARGS:		illegal arguments provided (deprecated)
  * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported  (deprecated)
  * @PM_RET_ERROR_NOFEATURE:	feature is not available
+ * @PM_RET_ERROR_INVALID_CRC:	invalid crc in IPI communication
  * @PM_RET_ERROR_INTERNAL:	internal error
  * @PM_RET_ERROR_CONFLICT:	conflict
  * @PM_RET_ERROR_ACCESS:	access rights violation
@@ -134,6 +137,7 @@
 	PM_RET_ERROR_ARGS = 1,
 	PM_RET_ERROR_NOTSUPPORTED = 4,
 	PM_RET_ERROR_NOFEATURE = 19,
+	PM_RET_ERROR_INVALID_CRC = 301,
 	PM_RET_ERROR_INTERNAL = 2000,
 	PM_RET_ERROR_CONFLICT = 2001,
 	PM_RET_ERROR_ACCESS = 2002,
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index 008cfdc..f00ab4b 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -243,11 +243,13 @@
 	PM_OPCHAR_TYPE_LATENCY,
 };
 
+/* TODO: move pm_ret_status from device specific location to common location */
 /**
  * @PM_RET_SUCCESS:		success
  * @PM_RET_ERROR_ARGS:		illegal arguments provided (deprecated)
  * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported  (deprecated)
  * @PM_RET_ERROR_NOT_ENABLED:	feature is not enabled
+ * @PM_RET_ERROR_INVALID_CRC:	invalid crc in IPI communication
  * @PM_RET_ERROR_INTERNAL:	internal error
  * @PM_RET_ERROR_CONFLICT:	conflict
  * @PM_RET_ERROR_ACCESS:	access rights violation
@@ -262,6 +264,7 @@
 	PM_RET_ERROR_ARGS = (1U),
 	PM_RET_ERROR_NOTSUPPORTED = (4U),
 	PM_RET_ERROR_NOT_ENABLED = (29U),
+	PM_RET_ERROR_INVALID_CRC = (301U),
 	PM_RET_ERROR_INTERNAL = (2000U),
 	PM_RET_ERROR_CONFLICT = (2001U),
 	PM_RET_ERROR_ACCESS = (2002U),