Merge "fix(spm): silence warning in sp_mk_generator" into integration
diff --git a/.husky/pre-commit.copyright b/.husky/pre-commit.copyright
index a4dfee8..5f838a6 100755
--- a/.husky/pre-commit.copyright
+++ b/.husky/pre-commit.copyright
@@ -17,10 +17,24 @@
 
 exit_code=0
 
+PLATPROV=
+ORG=`echo "$GIT_AUTHOR_EMAIL" | awk -F '[@]' '{ print $2;}'`
+
+case $ORG in
+	amd.com)
+		PLATPROV="Advanced Micro Devices, Inc. All rights reserved."
+		;;
+	*arm.com)
+		PLATPROV="$ARM_RGX"
+		;;
+	*)
+		;;
+esac
+
 function user_warning() {
 	echo -e "Copyright of $RED$FILE$BLANK is out of date/incorrect"
 	echo -e "Updated copyright to"
-	grep -nr "opyright.*$YEAR_RGX.*$ARM_RGX" "$FILE"
+	grep -nr "opyright.*$YEAR_RGX.*$PLATPROV" "$FILE"
 	echo
 }
 
@@ -29,31 +43,45 @@
 	then
 		break
 	fi
-	# Check if correct copyright notice is in file.
-	# To reduce false positives, we assume files with no
-	# copyright notice do not require it.
-	if ! grep "opyright.*$YEAR_NOW.*$ARM_RGX" "$FILE">/dev/null 2>&1
+
+	# Check if copyright header exists for the org
+	if ! grep "opyright.*$YEAR_RGX.*$PLATPROV" "$FILE">/dev/null 2>&1 && [[ $ORG != *arm* ]]
 	then
-		# If it is "from_date - to_date" type of entry - change to_date entry.
-		if grep "opyright.*$YEAR_RGX.*-.*$YEAR_RGX.*$ARM_RGX" "$FILE" >/dev/null 2>&1
-		then
-			exit_code=1
-			sed -i "s/\(opyright.*\)$YEAR_RGX\(.*$ARM_RGX\)/\1$(date +"%Y"), Arm/" $FILE
-			user_warning
-		# If it is single "date" type of entry - add the copyright extension to current year.
-		elif grep "opyright.*$YEAR_RGX.*$ARM_RGX" "$FILE" >/dev/null 2>&1
+		echo -e "Copyright header ""$RED""$PLATPROV""$BLANK"" is missing in ""$YELLOW""$FILE""$BLANK"
+	fi
+
+	# Check if the copyright year is updated for the org  and update it
+	if [ ! -z "$PLATPROV" ]
+	then
+		if ! grep "opyright.*$YEAR_NOW.*$PLATPROV" "$FILE">/dev/null 2>&1
 		then
-			exit_code=1
-			sed -i "s/\(opyright.*$YEAR_RGX\)\(.*$ARM_RGX\)/\1-$(date +"%Y"), Arm/" $FILE
-			user_warning
+			# If it is "from_date - to_date" type of entry - change to_date entry.
+			if grep "opyright.*$YEAR_RGX.*-.*$YEAR_RGX.*$PLATPROV" "$FILE" >/dev/null 2>&1
+			then
+				exit_code=1
+				sed -i "s/\(opyright.*\)$YEAR_RGX\(.*$PLATPROV\)/\1$(date +"%Y")\2/" $FILE
+				user_warning
+			# If it is single "date" type of entry - add the copyright extension to current year.
+			elif grep "opyright.*$YEAR_RGX.*$PLATPROV" "$FILE" >/dev/null 2>&1
+			then
+				exit_code=1
+				sed -i "s/\(opyright.*$YEAR_RGX\)\(.*$PLATPROV\)/\1-$(date +"%Y")\2/" $FILE
+				user_warning
+			fi
+
+			# Even if the year is correct - verify that Arm copyright is formatted correctly.
+			if [[ $ORG == *arm* ]]
+			then
+				if grep "opyright.*\(ARM\|arm\)" "$FILE">/dev/null 2>&1
+				then
+					exit_code=1
+					sed -i "s/\(opyright.*\)\(ARM\|arm\)/\1Arm/" $FILE
+					user_warning
+				fi
+			fi
 		fi
-	# Even if the year is correct - verify that Arm copyright is formatted correctly.
-	elif grep "opyright.*\(ARM\|arm\)" "$FILE">/dev/null 2>&1
-	then
-		exit_code=1
-		sed -i "s/\(opyright.*\)\(ARM\|arm\)/\1Arm/" $FILE
-		user_warning
 	fi
+
 done <<< "$FILES"
 
 if [ $exit_code -eq 1 ]
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
index 4f8c8b7..702bb56 100644
--- a/docs/components/cot-binding.rst
+++ b/docs/components/cot-binding.rst
@@ -67,14 +67,16 @@
         - signing-key
                 Usage:
 
-                This property is used to refer public key node present in
-                parent certificate node and it is required property for all
-                non-root certificates which are authenticated using public-key
-                present in parent certificate.
+                For non-root certificates, this property is used to refer
+                public key node present in parent certificate node and it is
+                required property for all non-root certificates which are
+                authenticated using public-key present in parent certificate.
 
-                This property is not required for root-certificates
-                as root-certificates are validated using root of trust
-                public key provided by platform.
+                This property is not required for all root-certificates. If
+                omitted, the root certificate will be validated using the
+                default platform ROTPK. If instead the root certificate needs
+                validating using a different ROTPK, the signing-key property
+                should provide a reference to the ROTPK node to use.
 
                 Value type: <phandle>
 
@@ -323,10 +325,50 @@
         };
    };
 
+rot_keys node binding definition
+---------------------------------
+
+- rot_keys node
+        Description: Contains root-of-trust keys for the root certificates.
+
+        SUBNODES
+            - Description:
+
+              Root of trust key information present in the root certificates
+              are shown by these nodes.
+
+            - rot key node
+                  Description: Provide ROT key information in the certificate.
+
+                  PROPERTIES
+
+                  - oid
+                     Usage:
+
+                     This property provides the Object ID of ROT key provided
+                     in the certificate.
+
+                     Value type: <string>
+
+Example:
+Below is rot_keys example for CCA platform
+
+.. code:: c
+
+   rot_keys {
+        swd_rot_pk: swd_rot_pk {
+           oid = SWD_ROT_PK_OID;
+        };
+
+        prot_pk: prot_pk {
+           oid = PROT_PK_OID;
+        };
+   };
+
 Future update to chain of trust binding
 ---------------------------------------
 
 This binding document needs to be revisited to generalise some terminologies
 which are currently specific to X.509 certificates for e.g. Object IDs.
 
-*Copyright (c) 2020, Arm Limited. All rights reserved.*
+*Copyright (c) 2020-2024, Arm Limited. All rights reserved.*
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 58b7d99..679de2b 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -142,6 +142,9 @@
    PSA
       Platform Security Architecture
 
+   PSR
+     Platform Security Requirements
+
    PSCI
       Power State Coordination Interface
 
diff --git a/docs/security_advisories/security-advisory-tfv-10.rst b/docs/security_advisories/security-advisory-tfv-10.rst
index 91dba07..f53bae1 100644
--- a/docs/security_advisories/security-advisory-tfv-10.rst
+++ b/docs/security_advisories/security-advisory-tfv-10.rst
@@ -98,7 +98,7 @@
 ``drivers/auth/``) require that the certificate's signature has already been
 validated prior to calling ``get_ext()``, or any function that calls ``get_ext()``.
 Platforms taking their chain of trust from a dynamic configuration file (such as
-``fdts/cot_descriptors.dtsi``) are also safe, as signature verification will
+``fdts/tbbr_cot_descriptors.dtsi``) are also safe, as signature verification will
 always be done prior to any calls to ``get_ext()`` or ``auth_nvctr()`` in this
 case, no matter the order of the properties in the file.  Therefore, it is not
 possible to exploit this vulnerability pre-authentication in upstream TF-A.
diff --git a/docs/threat_model/threat_model.rst b/docs/threat_model/threat_model.rst
index 0da2558..242f818 100644
--- a/docs/threat_model/threat_model.rst
+++ b/docs/threat_model/threat_model.rst
@@ -42,6 +42,8 @@
 - No experimental features are enabled. We do not consider threats that may come
   from them.
 
+- The platform's hardware complies with the `PSR specification`_, defining the
+  bare-minimum security prerequisites for System-on-Chips (SoC).
 
 Data Flow Diagram
 =================
@@ -1101,3 +1103,4 @@
 .. _Secure Development Guidelines: https://trustedfirmware-a.readthedocs.io/en/latest/process/security-hardening.html#secure-development-guidelines
 .. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
 .. _OP-TEE Dispatcher: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/components/spd/optee-dispatcher.rst
+.. _PSR Specification: https://developer.arm.com/documentation/den0106/0100
diff --git a/fdts/cca_cot_descriptors.dtsi b/fdts/cca_cot_descriptors.dtsi
new file mode 100644
index 0000000..d52431b
--- /dev/null
+++ b/fdts/cca_cot_descriptors.dtsi
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tools_share/cca_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <common/nv_cntr_ids.h>
+
+cot {
+	manifests {
+		compatible = "arm, cert-descs";
+
+		cca_content_cert: cca_content_cert {
+			root-certificate;
+			image-id =<CCA_CONTENT_CERT_ID>;
+			antirollback-counter = <&cca_nv_counter>;
+
+			tb_fw_hash: tb_fw_hash {
+				oid = TRUSTED_BOOT_FW_HASH_OID;
+			};
+			tb_fw_config_hash: tb_fw_config_hash {
+				oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+			};
+			hw_config_hash: hw_config_hash {
+				oid = HW_CONFIG_HASH_OID;
+			};
+			fw_config_hash: fw_config_hash {
+				oid = FW_CONFIG_HASH_OID;
+			};
+			soc_fw_hash: soc_fw_hash {
+				oid = SOC_AP_FW_HASH_OID;
+			};
+			soc_fw_config_hash: soc_fw_config_hash {
+				oid = SOC_FW_CONFIG_HASH_OID;
+			};
+			rmm_hash: rmm_hash {
+				oid = RMM_HASH_OID;
+			};
+		};
+
+		core_swd_key_cert: core_swd_key_cert {
+			root-certificate;
+			image-id = <CORE_SWD_KEY_CERT_ID>;
+			signing-key = <&swd_rot_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			core_swd_pk: core_swd_pk {
+				oid = CORE_SWD_PK_OID;
+			};
+		};
+
+		trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+			image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+			parent = <&core_swd_key_cert>;
+			signing-key = <&core_swd_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_hash: tos_fw_hash {
+				oid = TRUSTED_OS_FW_HASH_OID;
+			};
+			tos_fw_config_hash: tos_fw_config_hash {
+				oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		plat_key_cert: plat_key_cert {
+			root-certificate;
+			image-id = <PLAT_KEY_CERT_ID>;
+			signing-key = <&prot_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			plat_pk: plat_pk {
+				oid = PLAT_PK_OID;
+			};
+		};
+
+		non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+			image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+			parent = <&plat_key_cert>;
+			signing-key = <&plat_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_world_bl_hash: nt_world_bl_hash {
+				oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+			};
+			nt_fw_config_hash: nt_fw_config_hash {
+				oid = NON_TRUSTED_FW_CONFIG_HASH_OID;
+			};
+		};
+
+#if defined(SPD_spmd)
+		sip_sp_content_cert: sip_sp_content_cert {
+			image-id = <SIP_SP_CONTENT_CERT_ID>;
+			parent = <&core_swd_key_cert>;
+			signing-key = <&core_swd_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			sp_pkg1_hash: sp_pkg1_hash {
+				oid = SP_PKG1_HASH_OID;
+			};
+			sp_pkg2_hash: sp_pkg2_hash {
+				oid = SP_PKG2_HASH_OID;
+			};
+			sp_pkg3_hash: sp_pkg3_hash {
+				oid = SP_PKG3_HASH_OID;
+			};
+			sp_pkg4_hash: sp_pkg4_hash {
+				oid = SP_PKG4_HASH_OID;
+			};
+		};
+
+		plat_sp_content_cert: plat_sp_content_cert {
+			image-id = <PLAT_SP_CONTENT_CERT_ID>;
+			parent = <&plat_key_cert>;
+			signing-key = <&plat_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			sp_pkg5_hash: sp_pkg5_hash {
+				oid = SP_PKG5_HASH_OID;
+			};
+			sp_pkg6_hash: sp_pkg6_hash {
+				oid = SP_PKG6_HASH_OID;
+			};
+			sp_pkg7_hash: sp_pkg7_hash {
+				oid = SP_PKG7_HASH_OID;
+			};
+			sp_pkg8_hash: sp_pkg8_hash {
+				oid = SP_PKG8_HASH_OID;
+			};
+		};
+#endif
+	};
+
+	images {
+		compatible = "arm, img-descs";
+
+		fw_config {
+			image-id = <FW_CONFIG_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&fw_config_hash>;
+		};
+
+		hw_config {
+			image-id = <HW_CONFIG_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&hw_config_hash>;
+		};
+
+		tb_fw_hash {
+			image-id = <BL2_IMAGE_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&tb_fw_hash>;
+		};
+
+		tb_fw_config {
+			image-id = <TB_FW_CONFIG_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&tb_fw_config_hash>;
+		};
+
+		bl31_image {
+			image-id = <BL31_IMAGE_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&soc_fw_hash>;
+		};
+
+		soc_fw_config {
+			image-id = <SOC_FW_CONFIG_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&soc_fw_config_hash>;
+		};
+
+		rmm_image {
+			image-id = <RMM_IMAGE_ID>;
+			parent = <&cca_content_cert>;
+			hash = <&rmm_hash>;
+		};
+
+		bl32_image {
+			image-id = <BL32_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_hash>;
+		};
+
+		tos_fw_config {
+			image-id = <TOS_FW_CONFIG_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_config_hash>;
+		};
+
+		bl33_image {
+			image-id = <BL33_IMAGE_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_world_bl_hash>;
+		};
+
+		nt_fw_config {
+			image-id = <NT_FW_CONFIG_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_fw_config_hash>;
+		};
+
+#if defined(SPD_spmd)
+		sp_pkg1 {
+			image-id = <SP_PKG1_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg1_hash>;
+		};
+
+		sp_pkg2 {
+			image-id = <SP_PKG2_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg2_hash>;
+		};
+
+		sp_pkg3 {
+			image-id = <SP_PKG3_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg3_hash>;
+		};
+
+		sp_pkg4 {
+			image-id = <SP_PKG4_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg4_hash>;
+		};
+
+		sp_pkg5 {
+			image-id = <SP_PKG5_ID>;
+			parent = <&plat_sp_content_cert>;
+			hash = <&sp_pkg5_hash>;
+		};
+
+		sp_pkg6 {
+			image-id = <SP_PKG6_ID>;
+			parent = <&plat_sp_content_cert>;
+			hash = <&sp_pkg6_hash>;
+		};
+
+		sp_pkg7 {
+			image-id = <SP_PKG7_ID>;
+			parent = <&plat_sp_content_cert>;
+			hash = <&sp_pkg7_hash>;
+		};
+
+		sp_pkg8 {
+			image-id = <SP_PKG8_ID>;
+			parent = <&plat_sp_content_cert>;
+			hash = <&sp_pkg8_hash>;
+		};
+#endif
+	};
+};
+
+non_volatile_counters: non_volatile_counters {
+	compatible = "arm, non-volatile-counter";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cca_nv_counter: cca_nv_counter {
+		id  = <TRUSTED_NV_CTR_ID>;
+		oid = CCA_FW_NVCOUNTER_OID;
+	};
+
+	trusted_nv_counter: trusted_nv_counter {
+		id  = <TRUSTED_NV_CTR_ID>;
+		oid = TRUSTED_FW_NVCOUNTER_OID;
+	};
+
+	non_trusted_nv_counter: non_trusted_nv_counter {
+		id  = <NON_TRUSTED_NV_CTR_ID>;
+		oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+	};
+};
+
+rot_keys {
+	swd_rot_pk: swd_rot_pk {
+		oid = SWD_ROT_PK_OID;
+	};
+
+	prot_pk: prot_pk {
+		oid = PROT_PK_OID;
+	};
+};
diff --git a/fdts/cot_descriptors.dtsi b/fdts/tbbr_cot_descriptors.dtsi
similarity index 99%
rename from fdts/cot_descriptors.dtsi
rename to fdts/tbbr_cot_descriptors.dtsi
index 411bae6..ac39e4e 100644
--- a/fdts/cot_descriptors.dtsi
+++ b/fdts/tbbr_cot_descriptors.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index 9ed6a8b..01dbea9 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,7 +24,7 @@
 
 /* The macros below are used to identify FFA calls from the SMC function ID */
 #define FFA_FNUM_MIN_VALUE	U(0x60)
-#define FFA_FNUM_MAX_VALUE	U(0x8C)
+#define FFA_FNUM_MAX_VALUE	U(0x8E)
 #define is_ffa_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) &&	\
@@ -123,6 +123,10 @@
 /* FF-A v1.2 */
 #define FFA_FNUM_PARTITION_INFO_GET_REGS	U(0x8B)
 #define FFA_FNUM_EL3_INTR_HANDLE		U(0x8C)
+#define FFA_FNUM_MSG_SEND_DIRECT_REQ2		U(0x8D)
+#define FFA_FNUM_MSG_SEND_DIRECT_RESP2		U(0x8E)
+
+#define FFA_FNUM_CONSOLE_LOG			U(0x8A)
 
 /* FFA SMC32 FIDs */
 #define FFA_ERROR		FFA_FID(SMC_32, FFA_FNUM_ERROR)
@@ -171,6 +175,7 @@
 #define FFA_EL3_INTR_HANDLE	FFA_FID(SMC_32, FFA_FNUM_EL3_INTR_HANDLE)
 #define FFA_MEM_PERM_GET	FFA_FID(SMC_32, FFA_FNUM_MEM_PERM_GET)
 #define FFA_MEM_PERM_SET	FFA_FID(SMC_32, FFA_FNUM_MEM_PERM_SET)
+#define FFA_CONSOLE_LOG_SMC32 FFA_FID(SMC_32, FFA_FNUM_CONSOLE_LOG)
 
 /* FFA SMC64 FIDs */
 #define FFA_ERROR_SMC64		FFA_FID(SMC_64, FFA_FNUM_ERROR)
@@ -191,6 +196,11 @@
 	FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET)
 #define FFA_PARTITION_INFO_GET_REGS_SMC64 \
 	FFA_FID(SMC_64, FFA_FNUM_PARTITION_INFO_GET_REGS)
+#define FFA_CONSOLE_LOG_SMC64 FFA_FID(SMC_64, FFA_FNUM_CONSOLE_LOG)
+#define FFA_MSG_SEND_DIRECT_REQ2_SMC64 \
+	FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_REQ2)
+#define FFA_MSG_SEND_DIRECT_RESP2_SMC64	\
+	FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_RESP2)
 
 /*
  * FF-A partition properties values.
diff --git a/lib/fconf/fconf_cot_getter.c b/lib/fconf/fconf_cot_getter.c
index 1033018..b9bc9de 100644
--- a/lib/fconf/fconf_cot_getter.c
+++ b/lib/fconf/fconf_cot_getter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -237,13 +237,17 @@
 	 * verified by signature and images are verified by hash.
 	 */
 	if (type == IMG_CERT) {
-		if (root_certificate) {
-			oid = NULL;
-		} else {
-			rc = get_oid(dtb, node, "signing-key", &oid);
-			if (rc < 0) {
+		rc = get_oid(dtb, node, "signing-key", &oid);
+		if (rc < 0) {
+			/*
+			 * The signing-key property is optional in root
+			 * certificates, mandatory otherwise.
+			 */
+			if (root_certificate) {
+				oid = NULL;
+			} else {
 				ERROR("FCONF: Can't read %s property\n",
-					"signing-key");
+						"signing-key");
 				return rc;
 			}
 		}
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 6ba76db..9eb2177 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, ARM Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -104,7 +104,11 @@
 	};
 
 #if COT_DESC_IN_DTB
-	#include "cot_descriptors.dtsi"
+	#if defined(ARM_COT_cca)
+		#include "cca_cot_descriptors.dtsi"
+	#elif defined(ARM_COT_tbbr)
+		#include "tbbr_cot_descriptors.dtsi"
+	#endif
 #endif
 
 #if MEASURED_BOOT
@@ -117,6 +121,13 @@
 
 #include "../fvp_def.h"
 
+#if defined(ARM_COT_cca)
+/* FVP does not support the CCA NV Counter so use the Trusted one. */
+&cca_nv_counter {
+	reg = <TFW_NVCTR_BASE>;
+};
+#endif
+
 &trusted_nv_counter {
 	reg = <TFW_NVCTR_BASE>;
 };
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index ae0d85d..5084ea9 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -383,7 +383,12 @@
     else ifeq (${COT},dualroot)
         AUTH_SOURCES	+=	drivers/auth/dualroot/cot.c
     else ifeq (${COT},cca)
-        AUTH_SOURCES	+=	drivers/auth/cca/cot.c
+        BL1_SOURCES	+=	drivers/auth/cca/cot.c
+        ifneq (${COT_DESC_IN_DTB},0)
+            BL2_SOURCES	+=	lib/fconf/fconf_cot_getter.c
+        else
+            BL2_SOURCES	+=	drivers/auth/cca/cot.c
+        endif
     else
         $(error Unknown chain of trust ${COT})
     endif
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index 211a7b7..61c0ef2 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -28,6 +28,7 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 #include "socfpga_reset_manager.h"
+#include "socfpga_ros.h"
 #include "socfpga_system_manager.h"
 #include "wdt/watchdog.h"
 
@@ -92,6 +93,7 @@
 void bl2_el3_plat_arch_setup(void)
 {
 
+	unsigned long offset = 0;
 	const mmap_region_t bl_regions[] = {
 		MAP_REGION_FLAT(BL2_BASE, BL2_END - BL2_BASE,
 			MT_MEMORY | MT_RW | MT_SECURE),
@@ -123,14 +125,17 @@
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
 		dw_mmc_init(&params, &mmc_info);
-		socfpga_io_setup(boot_source);
+		socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE);
 		break;
 
 	case BOOT_SOURCE_QSPI:
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
-		socfpga_io_setup(boot_source);
+		if (ros_qspi_get_ssbl_offset(&offset) != ROS_RET_OK) {
+			offset = PLAT_QSPI_DATA_BASE;
+		}
+		socfpga_io_setup(boot_source, offset);
 		break;
 
 	default:
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
index f81480d..6780845 100644
--- a/plat/intel/soc/agilex/platform.mk
+++ b/plat/intel/soc/agilex/platform.mk
@@ -47,6 +47,7 @@
 		plat/intel/soc/agilex/soc/agilex_pinmux.c		\
 		plat/intel/soc/common/bl2_plat_mem_params_desc.c	\
 		plat/intel/soc/common/socfpga_image_load.c		\
+		plat/intel/soc/common/socfpga_ros.c			\
 		plat/intel/soc/common/socfpga_storage.c			\
 		plat/intel/soc/common/soc/socfpga_emac.c		\
 		plat/intel/soc/common/soc/socfpga_firewall.c	\
@@ -77,6 +78,8 @@
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
 
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
 PROGRAMMABLE_RESET_ADDRESS	:= 0
 RESET_TO_BL2			:= 1
 BL2_INV_DCACHE			:= 0
diff --git a/plat/intel/soc/agilex5/bl2_plat_setup.c b/plat/intel/soc/agilex5/bl2_plat_setup.c
index 5c15148..c74d799 100644
--- a/plat/intel/soc/agilex5/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl2_plat_setup.c
@@ -34,6 +34,7 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 #include "socfpga_reset_manager.h"
+#include "socfpga_ros.h"
 #include "wdt/watchdog.h"
 
 
@@ -96,6 +97,7 @@
 void bl2_el3_plat_arch_setup(void)
 {
 	handoff reverse_handoff_ptr;
+	unsigned long offset = 0;
 
 	struct cdns_sdmmc_params params = EMMC_INIT_PARAMS((uintptr_t) &cdns_desc, get_mmc_clk());
 
@@ -109,7 +111,7 @@
 	case BOOT_SOURCE_SDMMC:
 		NOTICE("SDMMC boot\n");
 		sdmmc_init(&reverse_handoff_ptr, &params, &mmc_info);
-		socfpga_io_setup(boot_source);
+		socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE);
 		break;
 
 	case BOOT_SOURCE_QSPI:
@@ -117,13 +119,16 @@
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
-		socfpga_io_setup(boot_source);
+		if (ros_qspi_get_ssbl_offset(&offset) != ROS_RET_OK) {
+			offset = PLAT_QSPI_DATA_BASE;
+		}
+		socfpga_io_setup(boot_source, offset);
 		break;
 
 	case BOOT_SOURCE_NAND:
 		NOTICE("NAND boot\n");
 		nand_init(&reverse_handoff_ptr);
-		socfpga_io_setup(boot_source);
+		socfpga_io_setup(boot_source, PLAT_NAND_DATA_BASE);
 		break;
 
 	default:
diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk
index b42253b..7302164 100644
--- a/plat/intel/soc/agilex5/platform.mk
+++ b/plat/intel/soc/agilex5/platform.mk
@@ -60,6 +60,7 @@
 		plat/intel/soc/agilex5/soc/agilex5_power_manager.c	\
 		plat/intel/soc/common/bl2_plat_mem_params_desc.c	\
 		plat/intel/soc/common/socfpga_image_load.c		\
+		plat/intel/soc/common/socfpga_ros.c			\
 		plat/intel/soc/common/socfpga_storage.c			\
 		plat/intel/soc/common/socfpga_vab.c				\
 		plat/intel/soc/common/soc/socfpga_emac.c		\
@@ -100,6 +101,10 @@
 CTX_INCLUDE_AARCH32_REGS := 0
 ERRATA_A55_1530923 := 1
 
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33	:=	0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
 $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
 
 PROGRAMMABLE_RESET_ADDRESS	:= 0
diff --git a/plat/intel/soc/common/bl2_plat_mem_params_desc.c b/plat/intel/soc/common/bl2_plat_mem_params_desc.c
index 187c53a..a09fb70 100644
--- a/plat/intel/soc/common/bl2_plat_mem_params_desc.c
+++ b/plat/intel/soc/common/bl2_plat_mem_params_desc.c
@@ -88,9 +88,27 @@
 		.image_info.image_base = PLAT_NS_IMAGE_OFFSET,
 		.image_info.image_max_size =
 			0x0 + 0x40000000 - PLAT_NS_IMAGE_OFFSET,
+# if ARM_LINUX_KERNEL_AS_BL33 != 0
+		.next_handoff_image_id = NT_FW_CONFIG_ID,
+	},
+
+	{
+		.image_id = NT_FW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+			VERSION_2, entry_point_info_t,
+			NON_SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+			VERSION_2, image_info_t, 0),
+		.image_info.image_base = ARM_PRELOADED_DTB_BASE,
+		.image_info.image_max_size =
+			0x0 + 0x40000000 - ARM_PRELOADED_DTB_BASE,
 
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	},
+#else
+	.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+# endif
 };
 
 REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h
index 49fc567..1946898 100644
--- a/plat/intel/soc/common/include/platform_def.h
+++ b/plat/intel/soc/common/include/platform_def.h
@@ -44,6 +44,10 @@
 #define PLAT_HANDOFF_OFFSET			0xFFE3F000
 #endif
 
+#define PLAT_QSPI_DATA_BASE			(0x3C00000)
+#define PLAT_NAND_DATA_BASE			(0x0200000)
+#define PLAT_SDMMC_DATA_BASE			(0x0)
+
 /*******************************************************************************
  * Platform binary types for linking
  ******************************************************************************/
diff --git a/plat/intel/soc/common/include/socfpga_private.h b/plat/intel/soc/common/include/socfpga_private.h
index 242dd73..041c282 100644
--- a/plat/intel/soc/common/include/socfpga_private.h
+++ b/plat/intel/soc/common/include/socfpga_private.h
@@ -33,7 +33,7 @@
 
 void enable_nonsecure_access(void);
 
-void socfpga_io_setup(int boot_source);
+void socfpga_io_setup(int boot_source, unsigned long offset);
 
 void socfgpa_configure_mmu_el3(unsigned long total_base,
 			unsigned long total_size,
diff --git a/plat/intel/soc/common/include/socfpga_ros.h b/plat/intel/soc/common/include/socfpga_ros.h
new file mode 100644
index 0000000..10cabd3
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_ros.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_ROS_H
+#define SOCFPGA_ROS_H
+
+#include <arch_helpers.h>
+#include <lib/utils_def.h>
+
+/** status response*/
+#define ROS_RET_OK			(0x00U)
+#define ROS_RET_INVALID			(0x01U)
+#define ROS_RET_NOT_RSU_MODE		(0x02U)
+#define ROS_QSPI_READ_ERROR		(0x03U)
+#define ROS_SPT_BAD_MAGIC_NUM		(0x04U)
+#define ROS_SPT_CRC_ERROR		(0x05U)
+#define ROS_IMAGE_INDEX_ERR		(0x06U)
+#define ROS_IMAGE_PARTNUM_OVFL		(0x07U)
+
+#define ADDR_64(h, l)			(((((unsigned long)(h)) & 0xffffffff) << 32) | \
+						(((unsigned long)(l)) & 0xffffffff))
+
+#define RSU_GET_SPT_RESP_SIZE		(4U)
+
+#define RSU_STATUS_RES_SIZE		(9U)
+
+#define SPT_MAGIC_NUMBER		(0x57713427U)
+#define SPT_VERSION			(0U)
+#define SPT_FLAG_RESERVED		(1U)
+#define SPT_FLAG_READONLY		(2U)
+
+#define SPT_MAX_PARTITIONS		(127U)
+#define SPT_PARTITION_NAME_LENGTH	(16U)
+#define SPT_RSVD_LENGTH			(4U)
+#define SPT_SIZE			(4096U)
+/*BOOT_INFO + FACTORY_IMAGE + SPT0 + SPT1 + CPB0 + CPB1 + FACTORY_IM.SSBL+ *APP* + *APP*.SSBL*/
+#define SPT_MIN_PARTITIONS		(9U)
+
+#define FACTORY_IMAGE			"FACTORY_IMAGE"
+#define FACTORY_SSBL			"FACTORY_IM.SSBL"
+#define SSBL_SUFFIX			".SSBL"
+
+typedef struct {
+	const uint32_t magic_number;
+	const uint32_t version;
+	const uint32_t partitions;
+	uint32_t checksum;
+	const uint32_t __RSVD[SPT_RSVD_LENGTH];
+	struct {
+		const char name[SPT_PARTITION_NAME_LENGTH];
+		const uint64_t offset;
+		const uint32_t length;
+		const uint32_t flags;
+	} partition[SPT_MAX_PARTITIONS];
+} __packed spt_table_t;
+
+uint32_t ros_qspi_get_ssbl_offset(unsigned long *offset);
+
+#endif /* SOCFPGA_ROS_H */
diff --git a/plat/intel/soc/common/socfpga_ros.c b/plat/intel/soc/common/socfpga_ros.c
new file mode 100644
index 0000000..ea37384
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_ros.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2024, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* system header files*/
+#include <assert.h>
+#include <endian.h>
+#include <string.h>
+
+/* CRC function header */
+#include <common/tf_crc32.h>
+
+/* Cadense qspi driver*/
+#include <qspi/cadence_qspi.h>
+
+/* Mailbox driver*/
+#include <socfpga_mailbox.h>
+
+#include <socfpga_ros.h>
+
+static void swap_bits(char *const data, uint32_t len)
+{
+	uint32_t x, y;
+	char tmp;
+
+	for (x = 0U; x < len; x++) {
+		tmp = 0U;
+		for (y = 0U; y < 8; y++) {
+			tmp <<= 1;
+			if (data[x] & 1) {
+				tmp |= 1;
+			}
+			data[x] >>= 1;
+		}
+		data[x] = tmp;
+	}
+}
+
+static uint32_t get_current_image_index(spt_table_t *spt_buf, uint32_t *const img_index)
+{
+	if (spt_buf == NULL || img_index == NULL) {
+		return ROS_RET_INVALID;
+	}
+
+	uint32_t ret;
+	unsigned long current_image;
+	uint32_t rsu_status[RSU_STATUS_RES_SIZE];
+
+	if (spt_buf->partitions < SPT_MIN_PARTITIONS || spt_buf->partitions > SPT_MAX_PARTITIONS) {
+		return ROS_IMAGE_PARTNUM_OVFL;
+	}
+
+	ret = mailbox_rsu_status(rsu_status, RSU_STATUS_RES_SIZE);
+	if (ret != MBOX_RET_OK) {
+		return ROS_RET_NOT_RSU_MODE;
+	}
+
+	current_image = ADDR_64(rsu_status[1], rsu_status[0]);
+	NOTICE("ROS: Current image is at 0x%08lx\n", current_image);
+
+	*img_index = 0U;
+	for (uint32_t index = 0U ; index < spt_buf->partitions; index++) {
+		if (spt_buf->partition[index].offset == current_image) {
+			*img_index = index;
+			break;
+		}
+	}
+
+	if (*img_index == 0U) {
+		return ROS_IMAGE_INDEX_ERR;
+	}
+
+	return ROS_RET_OK;
+}
+
+static uint32_t load_and_check_spt(spt_table_t *spt_ptr, size_t offset)
+{
+
+	if (spt_ptr == NULL || offset == 0U) {
+		return ROS_RET_INVALID;
+	}
+
+	int ret;
+	uint32_t calc_crc;
+	static spt_table_t spt_data;
+
+	ret = cad_qspi_read(spt_ptr, offset, SPT_SIZE);
+	if (ret != 0U) {
+		return ROS_QSPI_READ_ERROR;
+	}
+
+	if (spt_ptr->magic_number != SPT_MAGIC_NUMBER) {
+		return ROS_SPT_BAD_MAGIC_NUM;
+	}
+
+	if (spt_ptr->partitions < SPT_MIN_PARTITIONS || spt_ptr->partitions > SPT_MAX_PARTITIONS) {
+		return ROS_IMAGE_PARTNUM_OVFL;
+	}
+
+	memcpy_s(&spt_data, SPT_SIZE, spt_ptr, SPT_SIZE);
+	spt_data.checksum = 0U;
+	swap_bits((char *)&spt_data, SPT_SIZE);
+
+	calc_crc = tf_crc32(0, (uint8_t *)&spt_data, SPT_SIZE);
+	if (bswap32(spt_ptr->checksum) != calc_crc) {
+		return ROS_SPT_CRC_ERROR;
+	}
+
+	NOTICE("ROS: SPT table at 0x%08lx is verified\n", offset);
+	return ROS_RET_OK;
+}
+
+static uint32_t get_spt(spt_table_t *spt_buf)
+{
+	if (spt_buf == NULL) {
+		return ROS_RET_INVALID;
+	}
+
+	uint32_t ret;
+	uint32_t spt_offset[RSU_GET_SPT_RESP_SIZE];
+
+	/* Get SPT offset from SDM via mailbox commands */
+	ret = mailbox_rsu_get_spt_offset(spt_offset, RSU_GET_SPT_RESP_SIZE);
+	if (ret != MBOX_RET_OK) {
+		WARN("ROS: Not booted in RSU mode\n");
+		return ROS_RET_NOT_RSU_MODE;
+	}
+
+	/* Print the SPT table addresses */
+	VERBOSE("ROS: SPT0 0x%08lx\n", ADDR_64(spt_offset[0], spt_offset[1]));
+	VERBOSE("ROS: SPT1 0x%08lx\n", ADDR_64(spt_offset[2], spt_offset[3]));
+
+	/* Load and validate SPT1*/
+	ret = load_and_check_spt(spt_buf, ADDR_64(spt_offset[2], spt_offset[3]));
+	if (ret != ROS_RET_OK) {
+		/* Load and validate SPT0*/
+		ret = load_and_check_spt(spt_buf, ADDR_64(spt_offset[0], spt_offset[1]));
+		if (ret != ROS_RET_OK) {
+			WARN("Both SPT tables are unusable\n");
+			return ret;
+		}
+	}
+
+	return ROS_RET_OK;
+}
+
+uint32_t ros_qspi_get_ssbl_offset(unsigned long *offset)
+{
+	if (offset == NULL) {
+		return ROS_RET_INVALID;
+	}
+
+	uint32_t ret, img_index;
+	char ssbl_name[SPT_PARTITION_NAME_LENGTH];
+	static spt_table_t spt;
+
+	ret = get_spt(&spt);
+	if (ret != ROS_RET_OK) {
+		return ret;
+	}
+
+	ret = get_current_image_index(&spt, &img_index);
+	if (ret != ROS_RET_OK) {
+		return ret;
+	}
+
+	if (strncmp(spt.partition[img_index].name, FACTORY_IMAGE,
+		SPT_PARTITION_NAME_LENGTH) == 0U) {
+		strlcpy(ssbl_name, FACTORY_SSBL, SPT_PARTITION_NAME_LENGTH);
+	} else {
+		strlcpy(ssbl_name, spt.partition[img_index].name,
+			SPT_PARTITION_NAME_LENGTH);
+		strlcat(ssbl_name, SSBL_SUFFIX, SPT_PARTITION_NAME_LENGTH);
+	}
+
+	for (uint32_t index = 0U; index < spt.partitions; index++) {
+		if (strncmp(spt.partition[index].name, ssbl_name,
+			SPT_PARTITION_NAME_LENGTH) == 0U) {
+			*offset = spt.partition[index].offset;
+			NOTICE("ROS: Corresponding SSBL is at 0x%08lx\n", *offset);
+			return ROS_RET_OK;
+		}
+	}
+
+	return ROS_IMAGE_INDEX_ERR;
+}
diff --git a/plat/intel/soc/common/socfpga_storage.c b/plat/intel/soc/common/socfpga_storage.c
index e80f074..d250d9e 100644
--- a/plat/intel/soc/common/socfpga_storage.c
+++ b/plat/intel/soc/common/socfpga_storage.c
@@ -24,16 +24,13 @@
 
 #include "drivers/sdmmc/sdmmc.h"
 #include "socfpga_private.h"
+#include "socfpga_ros.h"
 
 
 #define PLAT_FIP_BASE		(0)
 #define PLAT_FIP_MAX_SIZE	(0x1000000)
 #define PLAT_MMC_DATA_BASE	(0xffe3c000)
 #define PLAT_MMC_DATA_SIZE	(0x2000)
-#define PLAT_QSPI_DATA_BASE	(0x3C00000)
-#define PLAT_QSPI_DATA_SIZE	(0x1000000)
-#define PLAT_NAND_DATA_BASE	(0x0200000)
-#define PLAT_NAND_DATA_SIZE	(0x1000000)
 
 static const io_dev_connector_t *fip_dev_con;
 static const io_dev_connector_t *boot_dev_con;
@@ -55,6 +52,12 @@
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
 
+# if ARM_LINUX_KERNEL_AS_BL33 != 0
+static const io_uuid_spec_t nt_fw_config_uuid_spec = {
+	.uuid = UUID_NT_FW_CONFIG,
+};
+# endif
+
 uintptr_t a2_lba_offset;
 const char a2[] = {0xa2, 0x0};
 
@@ -101,6 +104,13 @@
 		(uintptr_t) &bl33_uuid_spec,
 		check_fip
 	},
+# if ARM_LINUX_KERNEL_AS_BL33 != 0
+	[NT_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_config_uuid_spec,
+		check_fip
+	},
+# endif
 	[GPT_IMAGE_ID] = {
 		&boot_dev_handle,
 		(uintptr_t) &gpt_block_spec,
@@ -136,9 +146,10 @@
 	return result;
 }
 
-void socfpga_io_setup(int boot_source)
+void socfpga_io_setup(int boot_source, unsigned long offset)
 {
 	int result;
+	fip_spec.offset = offset;
 
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
@@ -152,7 +163,6 @@
 
 	case BOOT_SOURCE_QSPI:
 		register_io_dev = &register_io_dev_memmap;
-		fip_spec.offset = PLAT_QSPI_DATA_BASE;
 		break;
 
 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
@@ -161,7 +171,6 @@
 		nand_dev_spec.ops.init = cdns_nand_init_mtd;
 		nand_dev_spec.ops.read = cdns_nand_read;
 		nand_dev_spec.ops.write = NULL;
-		fip_spec.offset = PLAT_NAND_DATA_BASE;
 		break;
 #endif
 
diff --git a/plat/intel/soc/n5x/platform.mk b/plat/intel/soc/n5x/platform.mk
index 95f076f..29fd0eb 100644
--- a/plat/intel/soc/n5x/platform.mk
+++ b/plat/intel/soc/n5x/platform.mk
@@ -46,6 +46,8 @@
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
 
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
 PROGRAMMABLE_RESET_ADDRESS	:= 0
 RESET_TO_BL2			:= 1
 BL2_INV_DCACHE			:= 0
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
index 73e3216..d140394 100644
--- a/plat/intel/soc/stratix10/bl2_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -122,14 +122,14 @@
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
 		dw_mmc_init(&params, &mmc_info);
-		socfpga_io_setup(boot_source);
+		socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE);
 		break;
 
 	case BOOT_SOURCE_QSPI:
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
-		socfpga_io_setup(boot_source);
+		socfpga_io_setup(boot_source, PLAT_QSPI_DATA_BASE);
 		break;
 
 	default:
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
index 9567c45..afcf514 100644
--- a/plat/intel/soc/stratix10/platform.mk
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -76,6 +76,8 @@
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
 
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
 PROGRAMMABLE_RESET_ADDRESS	:= 0
 RESET_TO_BL2			:= 1
 USE_COHERENT_MEM		:= 1
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index 8c7518d..cd83a98 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -19,9 +19,7 @@
 #include <common/fdt_fixup.h>
 #include <common/fdt_wrappers.h>
 #include <lib/optee_utils.h>
-#if TRANSFER_LIST
 #include <lib/transfer_list.h>
-#endif
 #include <lib/utils.h>
 #include <plat/common/platform.h>
 #if ENABLE_RME
@@ -55,9 +53,7 @@
 
 /* Data structure which holds the extents of the trusted SRAM for BL2 */
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
-#if TRANSFER_LIST
 static struct transfer_list_header *bl2_tl;
-#endif
 
 void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 			       u_register_t arg2, u_register_t arg3)
@@ -122,7 +118,7 @@
 		ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret);
 
 #if TRANSFER_LIST
-	// create a TE
+	/* create a TE */
 	te = transfer_list_add(bl2_tl, TL_TAG_FDT, fdt_totalsize(fdt), fdt);
 	if (!te) {
 		ERROR("Failed to add FDT entry to Transfer List\n");
@@ -321,6 +317,23 @@
 }
 #endif /*defined(SPD_spmd) && SPMD_SPM_AT_SEL2*/
 
+#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
+static int handoff_pageable_part(uint64_t pagable_part)
+{
+#if TRANSFER_LIST
+	struct transfer_list_entry *te;
+
+	te = transfer_list_add(bl2_tl, TL_TAG_OPTEE_PAGABLE_PART,
+			       sizeof(pagable_part), &pagable_part);
+	if (!te) {
+		INFO("Cannot add TE for pageable part\n");
+		return -1;
+	}
+#endif
+	return 0;
+}
+#endif
+
 static int qemu_bl2_handle_post_image_load(unsigned int image_id)
 {
 	int err = 0;
@@ -334,12 +347,24 @@
 #endif
 #if TRANSFER_LIST
 	struct transfer_list_header *ns_tl = NULL;
-	struct transfer_list_entry *te = NULL;
 #endif
 
 	assert(bl_mem_params);
 
 	switch (image_id) {
+#if TRANSFER_LIST
+	case BL31_IMAGE_ID:
+		/*
+		 * arg0 is a bl_params_t reserved for bl31_early_platform_setup2
+		 * we just need arg1 and arg3 for BL31 to update th TL from S
+		 * to NS memory before it exits
+		 */
+		bl_mem_params->ep_info.args.arg1 =
+			TRANSFER_LIST_SIGNATURE |
+			REGISTER_CONVENTION_VERSION_MASK;
+		bl_mem_params->ep_info.args.arg3 = (uintptr_t)bl2_tl;
+		break;
+#endif
 	case BL32_IMAGE_ID:
 #if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
 		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
@@ -354,8 +379,21 @@
 		if (err != 0) {
 			WARN("OPTEE header parse error.\n");
 		}
+
+		/* add TL_TAG_OPTEE_PAGABLE_PART entry to the TL */
+		if (handoff_pageable_part(bl_mem_params->ep_info.args.arg1)) {
+			return -1;
+		}
 #endif
 
+		INFO("Handoff to BL32\n");
+		bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry();
+		if (TRANSFER_LIST &&
+			transfer_list_set_handoff_args(bl2_tl,
+				&bl_mem_params->ep_info))
+			break;
+
+		INFO("Using default arguments\n");
 #if defined(SPMC_OPTEE)
 		/*
 		 * Explicit zeroes to unused registers since they may have
@@ -379,7 +417,6 @@
 		bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE;
 		bl_mem_params->ep_info.args.arg3 = 0;
 #endif
-		bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry();
 		break;
 
 	case BL33_IMAGE_ID:
@@ -406,7 +443,7 @@
 		bl_mem_params->ep_info.args.arg3 = 0U;
 #elif TRANSFER_LIST
 		if (bl2_tl) {
-			// relocate the tl to pre-allocate NS memory
+			/* relocate the tl to pre-allocate NS memory */
 			ns_tl = transfer_list_relocate(bl2_tl,
 					(void *)(uintptr_t)FW_NS_HANDOFF_BASE,
 					bl2_tl->max_size);
@@ -415,37 +452,18 @@
 					(unsigned long)FW_NS_HANDOFF_BASE);
 				return -1;
 			}
-			NOTICE("Transfer list handoff to BL33\n");
-			transfer_list_dump(ns_tl);
-
-			te = transfer_list_find(ns_tl, TL_TAG_FDT);
-
-			bl_mem_params->ep_info.args.arg1 =
-				TRANSFER_LIST_SIGNATURE |
-				REGISTER_CONVENTION_VERSION_MASK;
-			bl_mem_params->ep_info.args.arg3 = (uintptr_t)ns_tl;
+		}
 
-			if (GET_RW(bl_mem_params->ep_info.spsr) == MODE_RW_32) {
-				// aarch32
-				bl_mem_params->ep_info.args.arg0 = 0;
-				bl_mem_params->ep_info.args.arg2 = te ?
-					(uintptr_t)transfer_list_entry_data(te)
-					: 0;
-			} else {
-				// aarch64
-				bl_mem_params->ep_info.args.arg0 = te ?
-					(uintptr_t)transfer_list_entry_data(te)
-					: 0;
-				bl_mem_params->ep_info.args.arg2 = 0;
-			}
-		} else {
-			// Legacy handoff
+		INFO("Handoff to BL33\n");
+		if (!transfer_list_set_handoff_args(ns_tl,
+						    &bl_mem_params->ep_info)) {
+			INFO("Invalid TL, fallback to default arguments\n");
 			bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
 		}
 #else
 		/* BL33 expects to receive the primary CPU MPID (through r0) */
 		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
-#endif // ARM_LINUX_KERNEL_AS_BL33
+#endif /* ARM_LINUX_KERNEL_AS_BL33 */
 
 		break;
 #ifdef SPD_spmd
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
index 894b842..eb88b12 100644
--- a/plat/qemu/common/qemu_bl31_setup.c
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -9,6 +9,7 @@
 #include <common/bl_common.h>
 #include <drivers/arm/pl061_gpio.h>
 #include <lib/gpt_rme/gpt_rme.h>
+#include <lib/transfer_list.h>
 #include <plat/common/platform.h>
 
 #include "qemu_private.h"
@@ -44,6 +45,7 @@
 #if ENABLE_RME
 static entry_point_info_t rmm_image_ep_info;
 #endif
+static struct transfer_list_header *bl31_tl;
 
 /*******************************************************************************
  * Perform any BL3-1 early platform setup.  Here is an opportunity to copy
@@ -100,6 +102,12 @@
 	if (!rmm_image_ep_info.pc)
 		panic();
 #endif
+
+	if (TRANSFER_LIST && arg1 == (TRANSFER_LIST_SIGNATURE |
+				      REGISTER_CONVENTION_VERSION_MASK) &&
+	    transfer_list_check_header((void *)arg3) != TL_OPS_NON) {
+		bl31_tl = (void *)arg3; /* saved TL address from BL2 */
+	}
 }
 
 void bl31_plat_arch_setup(void)
@@ -188,3 +196,18 @@
 	else
 		return NULL;
 }
+
+void bl31_plat_runtime_setup(void)
+{
+	console_switch_state(CONSOLE_FLAG_RUNTIME);
+
+#if TRANSFER_LIST
+	if (bl31_tl) {
+		/*
+		 * update the TL from S to NS memory before jump to BL33
+		 * to reflect all changes in TL done by BL32
+		 */
+		memcpy((void *)FW_NS_HANDOFF_BASE, bl31_tl, bl31_tl->max_size);
+	}
+#endif
+}
diff --git a/plat/st/stm32mp2/aarch64/stm32mp2_helper.S b/plat/st/stm32mp2/aarch64/stm32mp2_helper.S
index 66333ad..0df3e08 100644
--- a/plat/st/stm32mp2/aarch64/stm32mp2_helper.S
+++ b/plat/st/stm32mp2/aarch64/stm32mp2_helper.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 	.globl	platform_mem_init
 	.globl	plat_secondary_cold_boot_setup
 	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_flush
 	.globl	plat_crash_console_putc
@@ -32,9 +33,14 @@
 	 */
 func plat_secondary_cold_boot_setup
 	dsb	sy
+1:
 	wfi
-	/* This shouldn't be reached */
-	b	.
+	/*
+	 * This shouldn't be reached, but when a debugger halts the
+	 * secondary core it causes exit from wfi.
+	 * Put back the core in wfi.
+	 */
+	b	1b
 endfunc plat_secondary_cold_boot_setup
 
 	/* ----------------------------------------------
@@ -50,6 +56,31 @@
 	ret
 endfunc plat_is_my_cpu_primary
 
+	/* -----------------------------------------------------------
+	 *  unsigned int plat_stm32mp_get_core_pos(u_register_t mpidr)
+	 *  Helper function to calculate the core position.
+	 *  With this function: CorePos = (ClusterId * 4) +
+	 *  				  CoreId
+	 * -----------------------------------------------------------
+	 */
+func plat_stm32mp_get_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc plat_stm32mp_get_core_pos
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_stm32mp_get_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_stm32mp_get_core_pos
+endfunc plat_my_core_pos
+
 	/* ---------------------------------------------
 	 * int plat_crash_console_init(void)
 	 *
@@ -65,13 +96,13 @@
 	str	x0, [x1]
 1:
 	ldr	x0, [x1]
-	ands	x2, x0, x2
+	tst	x0, #DEBUG_UART_RST_BIT
 	beq	1b
-	bic	x2, x2, #DEBUG_UART_RST_BIT
-	str	x2, [x1]
+	bic	x0, x0, #DEBUG_UART_RST_BIT
+	str	x0, [x1]
 2:
 	ldr	x0, [x1]
-	ands	x2, x0, x2
+	tst	x0, #DEBUG_UART_RST_BIT
 	bne	2b
 	/* Enable GPIOs for UART TX */
 	mov_imm	x1, (RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index 23efa31..8db732c 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.mk
@@ -28,6 +28,8 @@
 
 CRASH_REPORTING		:= 1
 
+NS_TIMER_SWITCH		:=	0
+
 # Split out RO data into a non-executable section
 SEPARATE_CODE_AND_RODATA :=    1
 
diff --git a/services/spd/opteed/opteed_common.c b/services/spd/opteed/opteed_common.c
index 9aa19c5..8a769fb 100644
--- a/services/spd/opteed/opteed_common.c
+++ b/services/spd/opteed/opteed_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,9 +20,9 @@
  * initialize OPTEE context and entry point info for OPTEE.
  ******************************************************************************/
 void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
-				uint32_t rw, uint64_t pc,
-				uint64_t pageable_part, uint64_t mem_limit,
-				uint64_t dt_addr, optee_context_t *optee_ctx)
+				uint32_t rw, uint64_t pc, uint64_t arg0,
+				uint64_t arg1, uint64_t arg2, uint64_t arg3,
+				optee_context_t *optee_ctx)
 {
 	uint32_t ep_attr;
 
@@ -54,9 +54,10 @@
 							DAIF_IRQ_BIT |
 							DAIF_ABT_BIT);
 	zeromem(&optee_entry_point->args, sizeof(optee_entry_point->args));
-	optee_entry_point->args.arg0 = pageable_part;
-	optee_entry_point->args.arg1 = mem_limit;
-	optee_entry_point->args.arg2 = dt_addr;
+	optee_entry_point->args.arg0 = arg0;
+	optee_entry_point->args.arg1 = arg1;
+	optee_entry_point->args.arg2 = arg2;
+	optee_entry_point->args.arg3 = arg3;
 }
 
 /*******************************************************************************
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index 4d055db..ab9896e 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,6 +27,7 @@
 #include <lib/coreboot.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/optee_utils.h>
+#include <lib/transfer_list.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #if OPTEE_ALLOW_SMC_LOAD
 #include <libfdt.h>
@@ -37,6 +38,10 @@
 #include "opteed_private.h"
 #include "teesmc_opteed.h"
 
+#if OPTEE_ALLOW_SMC_LOAD
+static struct transfer_list_header *bl31_tl;
+#endif
+
 /*******************************************************************************
  * Address of the entrypoint vector table in OPTEE. It is
  * initialised once on the primary core after a cold boot.
@@ -123,9 +128,13 @@
 #else
 	entry_point_info_t *optee_ep_info;
 	uint32_t linear_id;
-	uint64_t opteed_pageable_part;
-	uint64_t opteed_mem_limit;
-	uint64_t dt_addr;
+	uint64_t arg0;
+	uint64_t arg1;
+	uint64_t arg2;
+	uint64_t arg3;
+	struct transfer_list_header *tl = NULL;
+	struct transfer_list_entry *te = NULL;
+	void *dt = NULL;
 
 	linear_id = plat_my_core_pos();
 
@@ -150,17 +159,39 @@
 	if (!optee_ep_info->pc)
 		return 1;
 
-	opteed_rw = optee_ep_info->args.arg0;
-	opteed_pageable_part = optee_ep_info->args.arg1;
-	opteed_mem_limit = optee_ep_info->args.arg2;
-	dt_addr = optee_ep_info->args.arg3;
+	if (TRANSFER_LIST &&
+		optee_ep_info->args.arg1 == (TRANSFER_LIST_SIGNATURE |
+					REGISTER_CONVENTION_VERSION_MASK)) {
+		tl = (void *)optee_ep_info->args.arg3;
+		if (transfer_list_check_header(tl) == TL_OPS_NON) {
+			return 1;
+		}
 
-	opteed_init_optee_ep_state(optee_ep_info,
-				opteed_rw,
-				optee_ep_info->pc,
-				opteed_pageable_part,
-				opteed_mem_limit,
-				dt_addr,
+		opteed_rw = GET_RW(optee_ep_info->spsr);
+		te = transfer_list_find(tl, TL_TAG_FDT);
+		dt = transfer_list_entry_data(te);
+
+		if (opteed_rw == OPTEE_AARCH64) {
+			arg0 = (uint64_t)dt;
+			arg2 = 0;
+		} else {
+			arg2 = (uint64_t)dt;
+			arg0 = 0;
+		}
+
+		arg1 = optee_ep_info->args.arg1;
+		arg3 = optee_ep_info->args.arg3;
+	} else {
+		/* Default handoff arguments */
+		opteed_rw = optee_ep_info->args.arg0;
+		arg0 = optee_ep_info->args.arg1; /* opteed_pageable_part */
+		arg1 = optee_ep_info->args.arg2; /* opteed_mem_limit */
+		arg2 = optee_ep_info->args.arg3; /* dt_addr */
+		arg3 = 0;
+	}
+
+	opteed_init_optee_ep_state(optee_ep_info, opteed_rw, optee_ep_info->pc,
+				arg0, arg1, arg2, arg3,
 				&opteed_sp_context[linear_id]);
 
 	/*
@@ -302,6 +333,26 @@
 	return fdt_finish(fdt_buf);
 }
 
+static int32_t create_smc_tl(const void *fdt, uint32_t fdt_sz)
+{
+#if TRANSFER_LIST
+	bl31_tl = transfer_list_init((void *)(uintptr_t)FW_HANDOFF_BASE,
+				FW_HANDOFF_SIZE);
+	if (!bl31_tl) {
+		ERROR("Failed to initialize Transfer List at 0x%lx\n",
+		(unsigned long)FW_HANDOFF_BASE);
+		return -1;
+	}
+
+	if (!transfer_list_add(bl31_tl, TL_TAG_FDT, fdt_sz, fdt)) {
+		return -1;
+	}
+	return 0;
+#else
+	return -1;
+#endif
+}
+
 /*******************************************************************************
  * This function is responsible for handling the SMC that loads the OP-TEE
  * binary image via a non-secure SMC call. It takes the size and physical
@@ -326,6 +377,10 @@
 	entry_point_info_t optee_ep_info;
 	uint32_t linear_id = plat_my_core_pos();
 	uint64_t dt_addr = 0;
+	uint64_t arg0 = 0;
+	uint64_t arg1 = 0;
+	uint64_t arg2 = 0;
+	uint64_t arg3 = 0;
 
 	mapped_data_pa = page_align(data_pa, DOWN);
 	mapped_data_va = mapped_data_pa;
@@ -394,12 +449,36 @@
 	dt_addr = (uint64_t)fdt_buf;
 	flush_dcache_range(dt_addr, OPTEED_FDT_SIZE);
 
+	if (TRANSFER_LIST &&
+	    !create_smc_tl((void *)dt_addr, OPTEED_FDT_SIZE)) {
+		struct transfer_list_entry *te = NULL;
+		void *dt = NULL;
+
+		te = transfer_list_find(bl31_tl, TL_TAG_FDT);
+		dt = transfer_list_entry_data(te);
+
+		if (opteed_rw == OPTEE_AARCH64) {
+			arg0 = (uint64_t)dt;
+			arg2 = 0;
+		} else {
+			arg2 = (uint64_t)dt;
+			arg0 = 0;
+		}
+		arg1 = TRANSFER_LIST_SIGNATURE |
+			REGISTER_CONVENTION_VERSION_MASK;
+		arg3 = (uint64_t)bl31_tl;
+	} else {
+		/* Default handoff arguments */
+		arg2 = dt_addr;
+	}
+
 	opteed_init_optee_ep_state(&optee_ep_info,
 				   opteed_rw,
 				   image_pa,
-				   0,
-				   0,
-				   dt_addr,
+				   arg0,
+				   arg1,
+				   arg2,
+				   arg3,
 				   &opteed_sp_context[linear_id]);
 	if (opteed_init_with_entry_point(&optee_ep_info) == 0) {
 		rc = -EFAULT;
diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c
index fa724a1..c949823 100644
--- a/services/spd/opteed/opteed_pm.c
+++ b/services/spd/opteed/opteed_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -113,7 +113,7 @@
 
 	opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
 				(uint64_t)&optee_vector_table->cpu_on_entry,
-				0, 0, 0, optee_ctx);
+				0, 0, 0, 0, optee_ctx);
 
 	/* Initialise this cpu's secure context */
 	cm_init_my_context(&optee_on_entrypoint);
diff --git a/services/spd/opteed/opteed_private.h b/services/spd/opteed/opteed_private.h
index c8fbc22..c484516 100644
--- a/services/spd/opteed/opteed_private.h
+++ b/services/spd/opteed/opteed_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -148,11 +148,8 @@
 uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx);
 void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret);
 void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
-				uint32_t rw,
-				uint64_t pc,
-				uint64_t pageable_part,
-				uint64_t mem_limit,
-				uint64_t dt_addr,
+				uint32_t rw, uint64_t pc, uint64_t arg0,
+				uint64_t arg1, uint64_t arg2, uint64_t arg3,
 				optee_context_t *optee_ctx);
 void opteed_cpu_on_finish_handler(u_register_t unused);
 
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index 7978f08..9cfcd87 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2024, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
 #include <errno.h>
+#include <stdio.h>
 
 #include <arch_helpers.h>
 #include <bl31/bl31.h>
@@ -1290,6 +1291,8 @@
 	case FFA_MSG_SEND_DIRECT_RESP_SMC64:
 	case FFA_MEM_RELINQUISH:
 	case FFA_MSG_WAIT:
+	case FFA_CONSOLE_LOG_SMC32:
+	case FFA_CONSOLE_LOG_SMC64:
 
 		if (!secure_origin) {
 			return spmc_ffa_error_return(handle,
@@ -1476,6 +1479,61 @@
 	SMC_RET1(handle, FFA_SUCCESS_SMC32);
 }
 
+static uint64_t spmc_ffa_console_log(uint32_t smc_fid,
+				     bool secure_origin,
+				     uint64_t x1,
+				     uint64_t x2,
+				     uint64_t x3,
+				     uint64_t x4,
+				     void *cookie,
+				     void *handle,
+				     uint64_t flags)
+{
+	char *chars;
+	size_t chars_max;
+	size_t chars_count = x1;
+
+	/* Does not support request from Nwd. */
+	if (!secure_origin) {
+		return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
+	}
+
+	assert(smc_fid == FFA_CONSOLE_LOG_SMC32 || smc_fid == FFA_CONSOLE_LOG_SMC64);
+	if (smc_fid == FFA_CONSOLE_LOG_SMC32) {
+		uint32_t registers[] = {
+			(uint32_t)x2,
+			(uint32_t)x3,
+			(uint32_t)x4,
+			(uint32_t)SMC_GET_GP(handle, CTX_GPREG_X5),
+			(uint32_t)SMC_GET_GP(handle, CTX_GPREG_X6),
+			(uint32_t)SMC_GET_GP(handle, CTX_GPREG_X7),
+		};
+		chars_max = ARRAY_SIZE(registers) * sizeof(uint32_t);
+		chars = (char *)registers;
+	} else {
+		uint64_t registers[] = {
+			x2,
+			x3,
+			x4,
+			SMC_GET_GP(handle, CTX_GPREG_X5),
+			SMC_GET_GP(handle, CTX_GPREG_X6),
+			SMC_GET_GP(handle, CTX_GPREG_X7),
+		};
+		chars_max = ARRAY_SIZE(registers) * sizeof(uint64_t);
+		chars = (char *)registers;
+	}
+
+	if ((chars_count == 0) || (chars_count > chars_max)) {
+		return spmc_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
+	}
+
+	for (size_t i = 0; (i < chars_count) && (chars[i] != '\0'); i++) {
+		putchar(chars[i]);
+	}
+
+	SMC_RET1(handle, FFA_SUCCESS_SMC32);
+}
+
 /*
  * Perform initial validation on the provided secondary entry point.
  * For now ensure it does not lie within the BL31 Image or the SP's
@@ -2365,7 +2423,11 @@
 
 	case FFA_MEM_RECLAIM:
 		return spmc_ffa_mem_reclaim(smc_fid, secure_origin, x1, x2, x3,
-					    x4, cookie, handle, flags);
+						x4, cookie, handle, flags);
+	case FFA_CONSOLE_LOG_SMC32:
+	case FFA_CONSOLE_LOG_SMC64:
+		return spmc_ffa_console_log(smc_fid, secure_origin, x1, x2, x3,
+						x4, cookie, handle, flags);
 
 	case FFA_MEM_PERM_GET:
 		return ffa_mem_perm_get_handler(smc_fid, secure_origin, x1, x2,
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 066571e..5d19868 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -1151,6 +1151,25 @@
 		}
 		break; /* Not reached */
 
+	case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
+		if (!secure_origin) {
+			/* Validate source endpoint is non-secure for non-secure caller. */
+			if (ffa_is_secure_world_id(ffa_endpoint_source(x1))) {
+				return spmd_ffa_error_return(handle,
+						FFA_ERROR_INVALID_PARAMETER);
+			}
+		}
+		/* FFA_MSG_SEND_DIRECT_REQ2 not used for framework messages. */
+		if (secure_origin && spmd_is_spmc_message(x1)) {
+			return spmd_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
+		} else {
+			/* Forward direct message to the other world */
+			return spmd_smc_forward(smc_fid, secure_origin,
+						x1, x2, x3, x4, cookie,
+						handle, flags);
+		}
+		break; /* Not reached */
+
 	case FFA_MSG_SEND_DIRECT_RESP_SMC32:
 	case FFA_MSG_SEND_DIRECT_RESP_SMC64:
 		if (secure_origin && (spmd_is_spmc_message(x1) ||
@@ -1163,7 +1182,12 @@
 						handle, flags);
 		}
 		break; /* Not reached */
-
+	case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
+		/* Forward direct message to the other world */
+		return spmd_smc_forward(smc_fid, secure_origin,
+					x1, x2, x3, x4, cookie,
+					handle, flags);
+		break; /* Not reached */
 	case FFA_RX_RELEASE:
 	case FFA_RXTX_MAP_SMC32:
 	case FFA_RXTX_MAP_SMC64:
@@ -1279,6 +1303,12 @@
 					handle, flags);
 		break; /* Not reached */
 #endif
+	case FFA_CONSOLE_LOG_SMC32:
+	case FFA_CONSOLE_LOG_SMC64:
+		/* This interface must not be forwarded to other worlds. */
+		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
+		break; /* not reached */
+
 	case FFA_EL3_INTR_HANDLE:
 		if (secure_origin) {
 			return spmd_handle_group0_intr_swd(handle);
diff --git a/plat/arm/board/juno/fip/plat_def_uuid_config.c b/tools/fiptool/plat_fiptool/arm/board/juno/plat_def_uuid_config.c
similarity index 100%
rename from plat/arm/board/juno/fip/plat_def_uuid_config.c
rename to tools/fiptool/plat_fiptool/arm/board/juno/plat_def_uuid_config.c
diff --git a/tools/fiptool/plat_fiptool/arm/board/juno/plat_fiptool.mk b/tools/fiptool/plat_fiptool/arm/board/juno/plat_fiptool.mk
index fef2116..5549b0d 100644
--- a/tools/fiptool/plat_fiptool/arm/board/juno/plat_fiptool.mk
+++ b/tools/fiptool/plat_fiptool/arm/board/juno/plat_fiptool.mk
@@ -11,6 +11,6 @@
 ifeq (${ETHOSN_NPU_TZMP1},1)
 HOSTCCFLAGS += -DETHOSN_NPU_TZMP1
 endif
-INCLUDE_PATHS += -I./ -I${PLAT_DIR}fip -I../../include/
-OBJECTS += ${PLAT_DIR}fip/plat_def_uuid_config.o
+INCLUDE_PATHS += -I./ -I../../plat/arm/board/juno/fip -I../../include
+OBJECTS += plat_fiptool/arm/board/juno/plat_def_uuid_config.o
 endif
diff --git a/tools/memory/memory/memmap.py b/tools/memory/memory/memmap.py
index 99149b5..34f5069 100755
--- a/tools/memory/memory/memmap.py
+++ b/tools/memory/memory/memmap.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 #
-# Copyright (c) 2023, Arm Limited. All rights reserved.
+# Copyright (c) 2023-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -99,7 +99,7 @@
 
     if symbols:
         expr = (
-            r"(.*)(TEXT|BSS|RODATA|STACKS|_OPS|PMF|XLAT|GOT|FCONF"
+            r"(.*)(TEXT|BSS|RO|RODATA|STACKS|_OPS|PMF|XLAT|GOT|FCONF|RELA"
             r"|R.M)(.*)(START|UNALIGNED|END)__$"
         )
         printer.print_symbol_table(