Merge changes from topic "msm8916-spmin" into integration

* changes:
  docs(msm8916): document new build options
  feat(msm8916): allow selecting which UART to use
  feat(msm8916): add SP_MIN port for AArch32
  refactor(msm8916): detect cold boot in plat_get_my_entrypoint
  feat(msm8916): add Test Secure Payload (TSP) port
  build(msm8916): place bl32 directly after bl31
  refactor(msm8916): separate common platform setup code
diff --git a/bl32/tsp/tsp_ffa_main.c b/bl32/tsp/tsp_ffa_main.c
index 268d329..1c8c68f 100644
--- a/bl32/tsp/tsp_ffa_main.c
+++ b/bl32/tsp/tsp_ffa_main.c
@@ -91,7 +91,7 @@
 	smc_args_t ffa_forward_result;
 	ffa_endpoint_id16_t receiver = arg5;
 
-	ffa_forward_result = ffa_msg_send_direct_req(ffa_endpoint_source(arg1),
+	ffa_forward_result = ffa_msg_send_direct_req(tsp_id,
 						     receiver,
 						     FF_A_ECHO_MESSAGE, arg4,
 						     0, 0, 0);
diff --git a/lib/cpus/aarch64/dsu_helpers.S b/lib/cpus/aarch64/dsu_helpers.S
index b7e028a..a34b9a6 100644
--- a/lib/cpus/aarch64/dsu_helpers.S
+++ b/lib/cpus/aarch64/dsu_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,11 +44,11 @@
 	/* --------------------------------------------------
 	 * Errata Workaround for DSU erratum #798953.
 	 *
-	 * Can clobber only: x0-x17
+	 * Can clobber only: x0-x8
 	 * --------------------------------------------------
 	 */
 func errata_dsu_798953_wa
-	mov	x17, x30
+	mov	x8, x30
 	bl	check_errata_dsu_798953
 	cbz	x0, 1f
 
@@ -58,7 +58,7 @@
 	msr	CLUSTERACTLR_EL1, x0
 	isb
 1:
-	ret	x17
+	ret	x8
 endfunc errata_dsu_798953_wa
 
 	/* -----------------------------------------------------------------------
@@ -72,7 +72,7 @@
 	 * This function is called from both assembly and C environment. So it
 	 * follows AAPCS.
 	 *
-	 * Clobbers: x0-x15
+	 * Clobbers: x0-x4
 	 * -----------------------------------------------------------------------
 	 */
 	.globl	check_errata_dsu_936184
@@ -83,7 +83,7 @@
 	 * Default behaviour respresents SCU is always present with DSU.
 	 * CPUs can override this definition if required.
 	 *
-	 * Can clobber only: x0-x14
+	 * Can clobber only: x0-x3
 	 * --------------------------------------------------------------------
 	 */
 func is_scu_present_in_dsu
@@ -92,7 +92,7 @@
 endfunc is_scu_present_in_dsu
 
 func check_errata_dsu_936184
-	mov	x15, x30
+	mov	x4, x30
 	bl	is_scu_present_in_dsu
 	cmp	x0, xzr
 	/* Default error status */
@@ -116,17 +116,17 @@
 	b.hs	1f
 	mov	x0, #ERRATA_APPLIES
 1:
-	ret	x15
+	ret	x4
 endfunc check_errata_dsu_936184
 
 	/* --------------------------------------------------
 	 * Errata Workaround for DSU erratum #936184.
 	 *
-	 * Can clobber only: x0-x17
+	 * Can clobber only: x0-x8
 	 * --------------------------------------------------
 	 */
 func errata_dsu_936184_wa
-	mov	x17, x30
+	mov	x8, x30
 	bl	check_errata_dsu_936184
 	cbz	x0, 1f
 
@@ -137,7 +137,7 @@
 	msr	CLUSTERACTLR_EL1, x0
 	isb
 1:
-	ret	x17
+	ret	x8
 endfunc errata_dsu_936184_wa
 
 	/* -----------------------------------------------------------------------
@@ -176,11 +176,11 @@
 	/* --------------------------------------------------
 	 * Errata Workaround for DSU erratum #2313941.
 	 *
-	 * Can clobber only: x0-x17
+	 * Can clobber only: x0-x8
 	 * --------------------------------------------------
 	 */
 func errata_dsu_2313941_wa
-	mov	x17, x30
+	mov	x8, x30
 	bl	check_errata_dsu_2313941
 	cbz	x0, 1f
 
@@ -190,6 +190,5 @@
 	msr	CLUSTERACTLR_EL1, x0
 	isb
 1:
-	ret	x17
+	ret	x8
 endfunc errata_dsu_2313941_wa
-
diff --git a/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c
index b9e4f86..72dfa30 100644
--- a/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c
+++ b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c
@@ -27,6 +27,7 @@
 					  void *handle, uint64_t flags)
 {
 	uint64_t ret;
+	uint32_t src_dst;
 
 	/* Determine if we have a 64 or 32 direct request. */
 	if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC32) {
@@ -36,18 +37,22 @@
 	} else {
 		panic(); /* Unknown SMC. */
 	}
+
 	/*
 	 * Handle the incoming request. For testing purposes we echo the
 	 * incoming message.
 	 */
-	INFO("Logical Partition: Received Direct Request from %s world!\n",
-	     secure_origin ? "Secure" : "Normal");
+	INFO("LSP: Received Direct Request from %s world (0x%x)\n",
+	     secure_origin ? "Secure" : "Normal", ffa_endpoint_source(x1));
 
+	/* Populate the source and destination IDs. */
+	src_dst = (uint32_t) LP_PARTITION_ID << FFA_DIRECT_MSG_SOURCE_SHIFT |
+		  ffa_endpoint_source(x1) << FFA_DIRECT_MSG_DESTINATION_SHIFT;
 	/*
 	 * Logical SP's must always send a direct response so we can populate
 	 * our response directly.
 	 */
-	SMC_RET8(handle, ret, 0, 0, x4, 0, 0, 0, 0);
+	SMC_RET8(handle, ret, src_dst, 0, x4, 0, 0, 0, 0);
 }
 
 /* Register logical partition  */
diff --git a/plat/qemu/common/qemu_sdei.c b/plat/qemu/common/qemu_sdei.c
new file mode 100644
index 0000000..820567e
--- /dev/null
+++ b/plat/qemu/common/qemu_sdei.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for ARM platforms */
+
+#include <bl31/ehf.h>
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <services/sdei.h>
+#include <platform_def.h>
+
+/* Private event mappings */
+static sdei_ev_map_t qemu_sdei_private[] = {
+	SDEI_DEFINE_EVENT_0(PLAT_SDEI_SGI_PRIVATE),
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t qemu_sdei_shared[] = {
+};
+
+void plat_sdei_setup(void)
+{
+	INFO("SDEI platform setup\n");
+}
+
+/* Export Arm SDEI events */
+REGISTER_SDEI_MAP(qemu_sdei_private, qemu_sdei_shared);
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index 98b8254..93a3ce8 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -244,8 +244,7 @@
  * interrupts.
  *****************************************************************************/
 #define PLATFORM_G1S_PROPS(grp)						\
-	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,	\
-					   grp, GIC_INTR_CFG_EDGE),	\
+	DESC_G1S_IRQ_SEC_SGI_0(grp)					\
 	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,	\
 					   grp, GIC_INTR_CFG_EDGE),	\
 	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,	\
@@ -261,7 +260,19 @@
 	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,	\
 					   grp, GIC_INTR_CFG_EDGE)
 
-#define PLATFORM_G0_PROPS(grp)
+#if SDEI_SUPPORT
+#define DESC_G0_IRQ_SEC_SGI(grp)					\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
+					   GIC_INTR_CFG_EDGE)
+#define DESC_G1S_IRQ_SEC_SGI_0(grp)
+#else
+#define DESC_G0_IRQ_SEC_SGI(grp)
+#define DESC_G1S_IRQ_SEC_SGI_0(grp)					\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp),	\
+					   GIC_INTR_CFG_EDGE),
+#endif
+
+#define PLATFORM_G0_PROPS(grp)		DESC_G0_IRQ_SEC_SGI(grp)
 
 /*
  * DT related constants
@@ -270,6 +281,14 @@
 #define PLAT_QEMU_DT_MAX_SIZE		0x100000
 
 /*
+ * Platforms macros to support SDEI
+ */
+#define PLAT_PRI_BITS			U(3)
+#define PLAT_SDEI_CRITICAL_PRI		0x60
+#define PLAT_SDEI_NORMAL_PRI		0x70
+#define PLAT_SDEI_SGI_PRIVATE		QEMU_IRQ_SEC_SGI_0
+
+/*
  * System counter
  */
 #define SYS_COUNTER_FREQ_IN_TICKS	((1000 * 1000 * 1000) / 16)
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 3a0e1c0..7a1dccd 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -230,6 +230,10 @@
 				${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c		\
 				${QEMU_GIC_SOURCES}
 
+ifeq (${SDEI_SUPPORT}, 1)
+BL31_SOURCES		+=	plat/qemu/common/qemu_sdei.c
+endif
+
 # Pointer Authentication sources
 ifeq (${ENABLE_PAUTH}, 1)
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c	\
@@ -323,3 +327,7 @@
 ifneq (${BL33},)
 all: qemu_fw.bios qemu_fw.rom
 endif
+
+ifeq (${EL3_EXCEPTION_HANDLING},1)
+BL31_SOURCES		+=	plat/common/aarch64/plat_ehf.c
+endif
diff --git a/services/std_svc/spm/el3_spmc/spmc.h b/services/std_svc/spm/el3_spmc/spmc.h
index 61afee3..13875b9 100644
--- a/services/std_svc/spm/el3_spmc/spmc.h
+++ b/services/std_svc/spm/el3_spmc/spmc.h
@@ -131,6 +131,9 @@
 
 	/* Track the current runtime model of the SP. */
 	enum sp_runtime_model rt_model;
+
+	/* Track the source partition ID to validate a direct response. */
+	uint16_t dir_req_origin_id;
 };
 
 /*
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index 08e7218..ada6f45 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -260,6 +260,65 @@
 }
 
 /*******************************************************************************
+ * Helper function to validate the destination ID of a direct response.
+ ******************************************************************************/
+static bool direct_msg_validate_dst_id(uint16_t dst_id)
+{
+	struct secure_partition_desc *sp;
+
+	/* Check if we're targeting a normal world partition. */
+	if (ffa_is_normal_world_id(dst_id)) {
+		return true;
+	}
+
+	/* Or directed to the SPMC itself.*/
+	if (dst_id == FFA_SPMC_ID) {
+		return true;
+	}
+
+	/* Otherwise ensure the SP exists. */
+	sp = spmc_get_sp_ctx(dst_id);
+	if (sp != NULL) {
+		return true;
+	}
+
+	return false;
+}
+
+/*******************************************************************************
+ * Helper function to validate the response from a Logical Partition.
+ ******************************************************************************/
+static bool direct_msg_validate_lp_resp(uint16_t origin_id, uint16_t lp_id,
+					void *handle)
+{
+	/* Retrieve populated Direct Response Arguments. */
+	uint64_t x1 = SMC_GET_GP(handle, CTX_GPREG_X1);
+	uint64_t x2 = SMC_GET_GP(handle, CTX_GPREG_X2);
+	uint16_t src_id = ffa_endpoint_source(x1);
+	uint16_t dst_id = ffa_endpoint_destination(x1);
+
+	if (src_id != lp_id) {
+		ERROR("Invalid EL3 LP source ID (0x%x).\n", src_id);
+		return false;
+	}
+
+	/*
+	 * Check the destination ID is valid and ensure the LP is responding to
+	 * the original request.
+	 */
+	if ((!direct_msg_validate_dst_id(dst_id)) || (dst_id != origin_id)) {
+		ERROR("Invalid EL3 LP destination ID (0x%x).\n", dst_id);
+		return false;
+	}
+
+	if (!direct_msg_validate_arg2(x2)) {
+		ERROR("Invalid EL3 LP message encoding.\n");
+		return false;
+	}
+	return true;
+}
+
+/*******************************************************************************
  * Handle direct request messages and route to the appropriate destination.
  ******************************************************************************/
 static uint64_t direct_req_smc_handler(uint32_t smc_fid,
@@ -272,6 +331,7 @@
 				       void *handle,
 				       uint64_t flags)
 {
+	uint16_t src_id = ffa_endpoint_source(x1);
 	uint16_t dst_id = ffa_endpoint_destination(x1);
 	struct el3_lp_desc *el3_lp_descs;
 	struct secure_partition_desc *sp;
@@ -283,14 +343,29 @@
 					     FFA_ERROR_INVALID_PARAMETER);
 	}
 
+	/* Validate Sender is either the current SP or from the normal world. */
+	if ((secure_origin && src_id != spmc_get_current_sp_ctx()->sp_id) ||
+		(!secure_origin && !ffa_is_normal_world_id(src_id))) {
+		ERROR("Invalid direct request source ID (0x%x).\n", src_id);
+		return spmc_ffa_error_return(handle,
+					FFA_ERROR_INVALID_PARAMETER);
+	}
+
 	el3_lp_descs = get_el3_lp_array();
 
 	/* Check if the request is destined for a Logical Partition. */
 	for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
 		if (el3_lp_descs[i].sp_id == dst_id) {
-			return el3_lp_descs[i].direct_req(
-					smc_fid, secure_origin, x1, x2, x3, x4,
-					cookie, handle, flags);
+			uint64_t ret = el3_lp_descs[i].direct_req(
+						smc_fid, secure_origin, x1, x2,
+						x3, x4, cookie, handle, flags);
+			if (!direct_msg_validate_lp_resp(src_id, dst_id,
+							 handle)) {
+				panic();
+			}
+
+			/* Message checks out. */
+			return ret;
 		}
 	}
 
@@ -332,6 +407,7 @@
 	 */
 	sp->ec[idx].rt_state = RT_STATE_RUNNING;
 	sp->ec[idx].rt_model = RT_MODEL_DIR_REQ;
+	sp->ec[idx].dir_req_origin_id = src_id;
 	return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
 			       handle, cookie, flags, dst_id);
 }
@@ -370,7 +446,7 @@
 	 * Check that the response is either targeted to the Normal world or the
 	 * SPMC e.g. a PM response.
 	 */
-	if ((dst_id != FFA_SPMC_ID) && ffa_is_secure_world_id(dst_id)) {
+	if (!direct_msg_validate_dst_id(dst_id)) {
 		VERBOSE("Direct response to invalid partition ID (0x%x).\n",
 			dst_id);
 		return spmc_ffa_error_return(handle,
@@ -397,9 +473,18 @@
 		return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
 	}
 
+	if (sp->ec[idx].dir_req_origin_id != dst_id) {
+		WARN("Invalid direct resp partition ID 0x%x != 0x%x on core%u.\n",
+		     dst_id, sp->ec[idx].dir_req_origin_id, idx);
+		return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+	}
+
 	/* Update the state of the SP execution context. */
 	sp->ec[idx].rt_state = RT_STATE_WAITING;
 
+	/* Clear the ongoing direct request ID. */
+	sp->ec[idx].dir_req_origin_id = INV_SP_ID;
+
 	/*
 	 * If the receiver is not the SPMC then forward the response to the
 	 * Normal world.
diff --git a/services/std_svc/spm/el3_spmc/spmc_pm.c b/services/std_svc/spm/el3_spmc/spmc_pm.c
index d25344c..c7e864f 100644
--- a/services/std_svc/spm/el3_spmc/spmc_pm.c
+++ b/services/std_svc/spm/el3_spmc/spmc_pm.c
@@ -83,6 +83,7 @@
 	/* Update the runtime model and state of the partition. */
 	ec->rt_model = RT_MODEL_INIT;
 	ec->rt_state = RT_STATE_RUNNING;
+	ec->dir_req_origin_id = INV_SP_ID;
 
 	INFO("SP (0x%x) init start on core%u.\n", sp->sp_id, linear_id);
 
@@ -132,6 +133,7 @@
 	/* Update the runtime model and state of the partition. */
 	ec->rt_model = RT_MODEL_DIR_REQ;
 	ec->rt_state = RT_STATE_RUNNING;
+	ec->dir_req_origin_id = FFA_SPMC_ID;
 
 	rc = spmc_sp_synchronous_entry(ec);
 	if (rc != 0ULL) {
diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
index 15c7e91..5c3d580 100644
--- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
+++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
@@ -777,16 +777,16 @@
 static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj,
 				uint32_t ffa_version)
 {
-	uint64_t total_page_count;
+	unsigned long long total_page_count;
 	const struct ffa_emad_v1_0 *first_emad;
 	const struct ffa_emad_v1_0 *end_emad;
 	size_t emad_size;
-	uint32_t comp_mrd_offset = 0;
+	uint32_t comp_mrd_offset;
 	size_t header_emad_size;
 	size_t size;
 	size_t count;
 	size_t expected_size;
-	struct ffa_comp_mrd *comp;
+	const struct ffa_comp_mrd *comp;
 
 	if (obj->desc_filled != obj->desc_size) {
 		ERROR("BUG: %s called on incomplete object (%zu != %zu)\n",
@@ -807,9 +807,7 @@
 	comp_mrd_offset = first_emad->comp_mrd_offset;
 
 	/* Loop through the endpoint descriptors, validating each of them. */
-	for (const struct ffa_emad_v1_0 *emad = first_emad;
-	     emad < end_emad;
-	     emad = emad_advance(emad, emad_size)) {
+	for (const struct ffa_emad_v1_0 *emad = first_emad; emad < end_emad;) {
 		ffa_endpoint_id16_t ep_id;
 
 		/*
@@ -836,6 +834,23 @@
 			       __func__, emad->comp_mrd_offset, comp_mrd_offset);
 			return FFA_ERROR_INVALID_PARAMETER;
 		}
+
+		/* Advance to the next endpoint descriptor */
+		emad = emad_advance(emad, emad_size);
+
+		/*
+		 * Ensure neither this emad nor any subsequent emads have
+		 * the same partition ID as the previous emad.
+		 */
+		for (const struct ffa_emad_v1_0 *other_emad = emad;
+		     other_emad < end_emad;
+		     other_emad = emad_advance(other_emad, emad_size)) {
+			if (ep_id == other_emad->mapd.endpoint_id) {
+				WARN("%s: Duplicated endpoint id 0x%x\n",
+				     __func__, emad->mapd.endpoint_id);
+				return FFA_ERROR_INVALID_PARAMETER;
+			}
+		}
 	}
 
 	header_emad_size = (size_t)((const uint8_t *)end_emad -
@@ -869,16 +884,18 @@
 	}
 	size -= comp_mrd_offset;
 
+	/* Check that there is enough space for the composite descriptor. */
 	if (size < sizeof(struct ffa_comp_mrd)) {
 		WARN("%s: invalid object, offset %u, total size %zu, no header space.\n",
 		     __func__, comp_mrd_offset, obj->desc_size);
 		return FFA_ERROR_INVALID_PARAMETER;
 	}
-	size -= sizeof(struct ffa_comp_mrd);
+	size -= sizeof(*comp);
 
 	count = size / sizeof(struct ffa_cons_mrd);
 
-	comp = spmc_shmem_obj_get_comp_mrd(obj, ffa_version);
+	comp = (const struct ffa_comp_mrd *)
+	       ((const uint8_t *)(&obj->desc) + comp_mrd_offset);
 
 	if (comp->address_range_count != count) {
 		WARN("%s: invalid object, desc count %u != %zu\n",
@@ -886,6 +903,7 @@
 		return FFA_ERROR_INVALID_PARAMETER;
 	}
 
+	/* Ensure that the expected and actual sizes are equal. */
 	expected_size = comp_mrd_offset + sizeof(*comp) +
 		count * sizeof(struct ffa_cons_mrd);
 
@@ -897,14 +915,30 @@
 
 	total_page_count = 0;
 
+	/*
+	 * comp->address_range_count is 32-bit, so 'count' must fit in a
+	 * uint32_t at this point.
+	 */
 	for (size_t i = 0; i < count; i++) {
-		total_page_count +=
-			comp->address_range_array[i].page_count;
+		const struct ffa_cons_mrd *mrd = comp->address_range_array + i;
+
+		if (!is_aligned(mrd->address, PAGE_SIZE)) {
+			WARN("%s: invalid object, address in region descriptor "
+			     "%zu not 4K aligned (got 0x%016llx)",
+			     __func__, i, (unsigned long long)mrd->address);
+		}
+
+		/*
+		 * No overflow possible: total_page_count can hold at
+		 * least 2^64 - 1, but will be have at most 2^32 - 1.
+		 * values added to it, each of which cannot exceed 2^32 - 1.
+		 */
+		total_page_count += mrd->page_count;
 	}
+
 	if (comp->total_page_count != total_page_count) {
-		WARN("%s: invalid object, desc total_page_count %u != %" PRIu64 "\n",
-		     __func__, comp->total_page_count,
-		total_page_count);
+		WARN("%s: invalid object, desc total_page_count %u != %llu\n",
+		     __func__, comp->total_page_count, total_page_count);
 		return FFA_ERROR_INVALID_PARAMETER;
 	}
 
@@ -970,11 +1004,8 @@
 			       void *smc_handle)
 {
 	int ret;
-	size_t emad_size;
 	uint32_t handle_low;
 	uint32_t handle_high;
-	struct ffa_emad_v1_0 *emad;
-	struct ffa_emad_v1_0 *other_emad;
 
 	if (mbox->rxtx_page_count == 0U) {
 		WARN("%s: buffer pair not registered.\n", __func__);
@@ -1057,26 +1088,6 @@
 		goto err_bad_desc;
 	}
 
-	/* Ensure partition IDs are not duplicated. */
-	for (size_t i = 0; i < obj->desc.emad_count; i++) {
-		emad = spmc_shmem_obj_get_emad(&obj->desc, i, ffa_version,
-					       &emad_size);
-
-		for (size_t j = i + 1; j < obj->desc.emad_count; j++) {
-			other_emad = spmc_shmem_obj_get_emad(&obj->desc, j,
-							     ffa_version,
-							     &emad_size);
-
-			if (emad->mapd.endpoint_id ==
-				other_emad->mapd.endpoint_id) {
-				WARN("%s: Duplicated endpoint id 0x%x\n",
-				     __func__, emad->mapd.endpoint_id);
-				ret = FFA_ERROR_INVALID_PARAMETER;
-				goto err_bad_desc;
-			}
-		}
-	}
-
 	ret = spmc_shmem_check_state_obj(obj, ffa_version);
 	if (ret) {
 		ERROR("%s: invalid memory region descriptor.\n", __func__);