Merge "docs(fuzz): Adding fuzzing documentation"
diff --git a/Makefile b/Makefile
index 4936ff7..3ebf566 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
 #
-# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # TFTF Version
 VERSION_MAJOR		:= 2
-VERSION_MINOR		:= 12
+VERSION_MINOR		:= 13
 
 MAKE_HELPERS_DIRECTORY := make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
@@ -171,6 +171,7 @@
 $(eval $(call assert_boolean,ENABLE_REALM_PAYLOAD_TESTS))
 $(eval $(call assert_boolean,TRANSFER_LIST))
 $(eval $(call assert_boolean,SPMC_AT_EL3))
+$(eval $(call assert_boolean,CACTUS_PWR_MGMT_SUPPORT))
 
 ################################################################################
 # Process build options
@@ -199,6 +200,7 @@
 $(eval $(call add_define,TFTF_DEFINES,TRANSFER_LIST))
 $(eval $(call add_define,TFTF_DEFINES,PLAT_AMU_GROUP1_COUNTERS_MASK))
 $(eval $(call add_define,TFTF_DEFINES,SPMC_AT_EL3))
+$(eval $(call add_define,TFTF_DEFINES,CACTUS_PWR_MGMT_SUPPORT))
 
 ################################################################################
 
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 0f22ded..964b13c 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -7,6 +7,148 @@
 Tests are not guaranteed to be compatible. This also means that a version
 upgrade on the TF-A-Tests side might not necessarily introduce any new feature.
 
+Version 2.13
+------------
+
+New features
+^^^^^^^^^^^^
+
+More features and tests are introduced in this release to enhance validation and
+support in the following areas:
+
+- Realm Management Extension
+- FF-A and SPM Testing
+- Fuzzing Framework
+- System Functionality Tests (e.g., PointerAuth, RAS registers, SMCCC feature
+  availability, FPMR access)
+- Firmware Handoff
+- Platform Enhancements
+
+Realm Management Extension
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    - Added and updated tests for `FEAT_MPAM` on Realms.
+    - Added AUX RTT support for planes.
+    - Added MbedTLS as a submodule.
+    - Added PCIe helpers.
+    - Added support for planes shared buffer.
+    - Added support for RSI Planes ABI.
+    - Added support for s2poe/pie for planes.
+    - Added test for multi REC planes.
+    - Added test for RSI_PLANE_REG_READ/WRITE command.
+    - Added test for validating RTT calls.
+    - Added test case to enter all planes.
+    - Added tests for realm attestation.
+    - Allocated memory for multiple planes.
+    - Called `RMI_PDEV` ABIs from host realm management.
+    - Enhanced Realm memory exception tests for planes.
+    - Extended RIPAS tests for planes.
+    - Fixed `rmi_realm_params` structure not being zeroed upon realm creation.
+    - Fixed bug in `RMI_RTT_SET_S2AP` command helper.
+    - Fixed multi REC PMU tests.
+    - Fixed PMU save/restore registers.
+    - Fixed position of `RTT_S2AP_INDIRECT` bit in `RmiFeatureRegister0`.
+    - Fixed Realm PMU tests.
+    - Fixed Realm tests marking all memory as RAM.
+    - Fixed the LPA2 flag setting for BRBE test.
+    - Handled permission fault for planes.
+    - Made PCIe tests default for testing.
+    - Undelegated PDEV granules upon DA ABI failure so later tests do not fail.
+    - Validated NS EL1/EL2 context is preserved by RMM.
+
+TFTF
+^^^^
+
+- SPM/FF-A Testing:
+
+    - Added a second instance of the Cactus S-EL1 partition to validate HOB generation.
+    - Added support for PPI timer interrupts.
+    - Added v1.2 fields to RXTX header.
+    - Fixed indirect messaging tests by adding ME handling.
+    - Introduced an enum type for FF-A errors.
+    - Refilled TX buffer after undelegation.
+    - Skipped CPU cycle allocation for SP vCPU to reach message loop.
+    - Skipped enabling/disabling SRI physical interrupts in TFTF.
+    - Specify the secure partition package for an SP
+
+- New Tests
+
+    - Fuzzing Enhancements
+
+        - Added fuzzing for vendor EL3 SMCCC calls.
+        - Enabled capability for randomized fuzzing inputs.
+        - Fixed single-feature testing behaviour.
+        - Introduced support for all SDEI calls, and the FF-A interface.
+
+    - Functionality Tests
+
+        - Added RAS system registers access test.
+        - Added test for `SMCCC_ARCH_WORKAROUND_4`.
+        - Added test for ARMv8.3 PointerAuth instructions.
+        - Added test for FPMR register access.
+        - Added tests for `SMCCC_ARCH_FEATURE_AVAILABILITY`.
+        - Added two new features and fixed TRNDR handling in availability tests
+        - Check SCTLR2, THE and D128 sysregs read/writes work as expected.
+        - Denied prohibited ABIs during `CPU_OFF` PSCI message handling.
+        - Evaluated EL3–RMM IDE KM interface in TRP.
+        - Validated `psci_is_last_cpu_to_idle_at_pwrlvl`.
+        - Verified save/restore logic for `BRBCR_EL1`.
+
+    - Firmware Handoff
+
+        - Added AArch32 handoff tests.
+        - Imported Measured Boot drivers from TF-A to support event log testing.
+        - Added tests for validating an event log received from a Transfer List.
+
+- Platforms:
+
+    - Versal NET
+
+        - Provided fix to prevent continuous interrupts by properly cleaning up
+          TTC timer in cancel routine.
+
+    - Versal
+
+        - Added platform specific function to return custom entry address.
+        - Updated Versal-2 test skip list.
+        - Updated Versal-2 TFTF and UART base address.
+
+    - Neoverse-RD
+
+        - Added TFTF support for RD-V3 platform.
+        - Deprecated and remove NRD1, RD-N1-Edge, RD-V1, SGI-575 platform
+          variants.
+
+- Miscellaneous
+
+    - Added `bdf` macro.
+    - Added `xpaci` instruction to exception report.
+    - Added build flag to control support for CPU_OFF PSCI message.
+    - Added Cortex-X925 and updated Cortex-X4 to Errata ABI.
+    - Added HOB definitions to TFTF.
+    - Added MbedTLS support and updated version to v3.6.3.
+    - Added new interface to get an invalid entrypoint address.
+    - Added register definitions needed for SMCCC_ARCH_FEATURE_AVAILABILITY
+    - Added split workaround check in Errata ABI test.
+    - Added support for SMC calls with no ret vals in x8.
+    - Updated ARM GCC toolchain requirements to 14.2.Rel1.
+    - Updated Cortex-A710 errata list.
+
+Cactus (Secure-EL1 FF-A test partition)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    - Added boot-time prints for Cactus-StMM HOB list.
+    - Added support for receiving PSCI messages through direct request framework message.
+    - Added mapping for boot information regions.
+    - Moved StMM to Cactus tertiary.
+
+Issues resolved since last release
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    - Applied fix to synchronize SME context before it is used.
+    - Fixed reporting of BRBE support with later revisions.
+    - Fixed compile error in `test_irq_spurious_gicv2.c`.
+
 Version 2.12
 ------------
 
@@ -1996,7 +2138,7 @@
 
 --------------
 
-*Copyright (c) 2018-2022, Arm Limited. All rights reserved.*
+*Copyright (c) 2018-2025, Arm Limited. All rights reserved.*
 
 .. _Arm Neoverse Reference Design N1 Edge (RD-N1-Edge): https://developer.arm.com/products/system-design/reference-design/neoverse-reference-design
 .. _Arm SGI-575: https://developer.arm.com/products/system-design/fixed-virtual-platforms
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 08343e3..3f62958 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -155,6 +155,14 @@
 - ``SPMC_AT_EL3``: This flag is required to match the feature set of Cactus SP that
    are implemented in TF-A EL3 SPMC. Default value is 0.
 
+-  ``CACTUS_PWR_MGMT_SUPPORT``: If a Cactus SP subscribes to receiving power
+   management framework message through its partition manifest, this flag
+   controls whether the SP supports handling the aforementioned message. This
+   option can take either 0 (unsupported) or 1 (supported). Default value is 1.
+
+   Note that a value of 0 is particularly useful in stress testing of power
+   management handling by the SPMC.
+
 Realm payload specific Build Options
 ------------------------------------
 
diff --git a/docs/getting_started/requirements.rst b/docs/getting_started/requirements.rst
index 14e4458..3c27b9d 100644
--- a/docs/getting_started/requirements.rst
+++ b/docs/getting_started/requirements.rst
@@ -25,7 +25,7 @@
 ======================== =====================
         Name             Version
 ======================== =====================
-Mbed TLS                 3.6.2
+Mbed TLS                 3.6.3
 ======================== =====================
 
 Toolchain
@@ -40,7 +40,7 @@
 Note that at least Python 3.8 is required.
 
 Download and install the GNU cross-toolchain from Arm. The TF-A Tests have
-been tested with version 13.3.Rel1 (gcc 13.3):
+been tested with version 14.2.Rel1 (GCC 14.2):
 
 -  `GCC cross-toolchain`_
 
@@ -53,4 +53,4 @@
 
 --------------
 
-*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
diff --git a/ext/mbedtls b/ext/mbedtls
index 107ea89..22098d4 160000
--- a/ext/mbedtls
+++ b/ext/mbedtls
@@ -1 +1 @@
-Subproject commit 107ea89daaefb9867ea9121002fbbdf926780e98
+Subproject commit 22098d41c6620ce07cf8a0134d37302355e1e5ef
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
index 2a144ba..1bc6672 100644
--- a/include/common/firmware_image_package.h
+++ b/include/common/firmware_image_package.h
@@ -16,6 +16,8 @@
 /* ToC Entry UUIDs */
 #define UUID_FIRMWARE_UPDATE_SCP_BL2U \
 	{{0x65, 0x92, 0x27, 0x03}, {0x2f, 0x74}, {0xe6, 0x44}, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} }
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \
+	{{0x5f, 0xf9, 0xec, 0x0b}, {0x4d, 0x22}, {0x3e, 0x4d}, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} }
 #define UUID_FIRMWARE_UPDATE_BL2U \
 	{{0x60, 0xb3, 0xeb, 0x37}, {0xc1, 0xe5}, {0xea, 0x41}, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} }
 #define UUID_FIRMWARE_UPDATE_NS_BL2U \
diff --git a/include/common/sha_common_macros.h b/include/common/sha_common_macros.h
new file mode 100644
index 0000000..d690e08
--- /dev/null
+++ b/include/common/sha_common_macros.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SHA_COMMON_MACROS_H
+#define SHA_COMMON_MACROS_H
+
+#define MD5_DIGEST_SIZE                 16U
+#define SHA1_DIGEST_SIZE                20U
+#define SHA224_DIGEST_SIZE              28U
+#define SHA256_DIGEST_SIZE              32U
+#define SHA384_DIGEST_SIZE              48U
+#define SHA512_224_DIGEST_SIZE          28U
+#define SHA512_256_DIGEST_SIZE          32U
+#define SHA512_DIGEST_SIZE              64U
+
+#endif /* SHA_COMMON_MACROS_H */
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index 8ca4cdf..1ab35ba 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -279,6 +279,14 @@
 		}                                                               \
 	} while (false)
 
+#define SKIP_TEST_IF_RAS_NOT_SUPPORTED()                                     \
+	do {                                                                 \
+		if(!is_feat_ras_present()){                                  \
+			tftf_testcase_printf("ARMv8.2-RAS not supported\n"); \
+			return TEST_RESULT_SKIPPED;                          \
+		}                                                            \
+	} while (false)
+
 #ifdef __aarch64__
 #define SKIP_TEST_IF_PA_SIZE_LESS_THAN(n)					\
 	do {									\
diff --git a/include/configs/tftf_mbedtls_config.h b/include/configs/tftf_mbedtls_config.h
index 77e7ba9..9ad0b71 100644
--- a/include/configs/tftf_mbedtls_config.h
+++ b/include/configs/tftf_mbedtls_config.h
@@ -21,8 +21,8 @@
 /* For snprintf function declaration */
 #include <stdio.h>
 
-/* This file is compatible with release 3.6.2 */
-#define MBEDTLS_CONFIG_VERSION         0x03060200
+/* This file is compatible with release 3.6.3 */
+#define MBEDTLS_CONFIG_VERSION         0x03060300
 
 /* Configuration file to build mbed TLS with the required features for TFTF */
 #define MBEDTLS_PLATFORM_MEMORY
diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h
new file mode 100644
index 0000000..bec19da
--- /dev/null
+++ b/include/drivers/auth/crypto_mod.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CRYPTO_MOD_H
+#define CRYPTO_MOD_H
+
+#define	CRYPTO_AUTH_VERIFY_ONLY			1
+#define	CRYPTO_HASH_CALC_ONLY			2
+#define	CRYPTO_AUTH_VERIFY_AND_HASH_CALC	3
+
+/* Return values */
+enum crypto_ret_value {
+	CRYPTO_SUCCESS = 0,
+	CRYPTO_ERR_INIT,
+	CRYPTO_ERR_HASH,
+	CRYPTO_ERR_SIGNATURE,
+	CRYPTO_ERR_DECRYPTION,
+	CRYPTO_ERR_UNKNOWN
+};
+
+#define CRYPTO_MAX_IV_SIZE		16U
+#define CRYPTO_MAX_TAG_SIZE		16U
+
+/* Decryption algorithm */
+enum crypto_dec_algo {
+	CRYPTO_GCM_DECRYPT = 0
+};
+
+/* Message digest algorithm */
+enum crypto_md_algo {
+	CRYPTO_MD_SHA256,
+	CRYPTO_MD_SHA384,
+	CRYPTO_MD_SHA512,
+};
+
+/* Maximum size as per the known stronger hash algorithm i.e.SHA512 */
+#define CRYPTO_MD_MAX_SIZE		64U
+
+/*
+ * Cryptographic library descriptor
+ */
+typedef struct crypto_lib_desc_s {
+	const char *name;
+
+	/* Initialize library. This function is not expected to fail. All errors
+	 * must be handled inside the function, asserting or panicking in case of
+	 * a non-recoverable error */
+	void (*init)(void);
+
+	/* Verify a digital signature. Return one of the
+	 * 'enum crypto_ret_value' options */
+	int (*verify_signature)(void *data_ptr, unsigned int data_len,
+				void *sig_ptr, unsigned int sig_len,
+				void *sig_alg, unsigned int sig_alg_len,
+				void *pk_ptr, unsigned int pk_len);
+
+	/* Verify a hash. Return one of the 'enum crypto_ret_value' options */
+	int (*verify_hash)(void *data_ptr, unsigned int data_len,
+			   void *digest_info_ptr, unsigned int digest_info_len);
+
+	/* Calculate a hash. Return hash value */
+	int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr,
+			 unsigned int data_len,
+			 unsigned char output[CRYPTO_MD_MAX_SIZE]);
+
+	/* Convert Public key (optional) */
+	int (*convert_pk)(void *full_pk_ptr, unsigned int full_pk_len,
+			  void **hashed_pk_ptr, unsigned int *hashed_pk_len);
+
+	/*
+	 * Authenticated decryption. Return one of the
+	 * 'enum crypto_ret_value' options.
+	 */
+	int (*auth_decrypt)(enum crypto_dec_algo dec_algo, void *data_ptr,
+			    size_t len, const void *key, unsigned int key_len,
+			    unsigned int key_flags, const void *iv,
+			    unsigned int iv_len, const void *tag,
+			    unsigned int tag_len);
+} crypto_lib_desc_t;
+
+/* Public functions */
+#if CRYPTO_SUPPORT
+void crypto_mod_init(void);
+#else
+static inline void crypto_mod_init(void)
+{
+}
+#endif /* CRYPTO_SUPPORT */
+
+#if (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY) || \
+    (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC)
+int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
+				void *sig_ptr, unsigned int sig_len,
+				void *sig_alg_ptr, unsigned int sig_alg_len,
+				void *pk_ptr, unsigned int pk_len);
+int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
+			   void *digest_info_ptr, unsigned int digest_info_len);
+#endif /* (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY) || \
+	  (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC) */
+
+int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
+			    size_t len, const void *key, unsigned int key_len,
+			    unsigned int key_flags, const void *iv,
+			    unsigned int iv_len, const void *tag,
+			    unsigned int tag_len);
+
+#if (CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY) || \
+    (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC)
+int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
+			 unsigned int data_len,
+			 unsigned char output[CRYPTO_MD_MAX_SIZE]);
+#endif /* (CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY) || \
+	  (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC) */
+
+int crypto_mod_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+			  void **hashed_pk_ptr, unsigned int *hashed_pk_len);
+
+/* Macro to register a cryptographic library */
+#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
+			    _calc_hash, _auth_decrypt, _convert_pk) \
+	const crypto_lib_desc_t crypto_lib_desc = { \
+		.name = _name, \
+		.init = _init, \
+		.verify_signature = _verify_signature, \
+		.verify_hash = _verify_hash, \
+		.calc_hash = _calc_hash, \
+		.auth_decrypt = _auth_decrypt, \
+		.convert_pk = _convert_pk \
+	}
+
+extern const crypto_lib_desc_t crypto_lib_desc;
+
+#endif /* CRYPTO_MOD_H */
diff --git a/include/drivers/measured_boot/event_log/tcg.h b/include/drivers/measured_boot/event_log/tcg.h
new file mode 100644
index 0000000..653f9c2
--- /dev/null
+++ b/include/drivers/measured_boot/event_log/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+#include <common/sha_common_macros.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03	"Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE	"StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2   2
+#define TCG_SPEC_VERSION_MINOR_TPM2   0
+#define TCG_SPEC_ERRATA_TPM2          2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT				U(0x00000000)
+#define EV_POST_CODE				U(0x00000001)
+#define	EV_UNUSED				U(0x00000002)
+#define EV_NO_ACTION				U(0x00000003)
+#define EV_SEPARATOR				U(0x00000004)
+#define EV_ACTION				U(0x00000005)
+#define	EV_EVENT_TAG				U(0x00000006)
+#define EV_S_CRTM_CONTENTS			U(0x00000007)
+#define EV_S_CRTM_VERSION			U(0x00000008)
+#define EV_CPU_MICROCODE			U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS		U(0x0000000A)
+#define EV_TABLE_OF_DEVICES			U(0x0000000B)
+#define EV_COMPACT_HASH				U(0x0000000C)
+#define	EV_IPL					U(0x0000000D)
+#define	EV_IPL_PARTITION_DATA			U(0x0000000E)
+#define EV_NONHOST_CODE				U(0x0000000F)
+#define EV_NONHOST_CONFIG			U(0x00000010)
+#define EV_NONHOST_INFO				U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS		U(0x00000012)
+#define	EV_EFI_EVENT_BASE			U(0x80000000)
+#define	EV_EFI_VARIABLE_DRIVER_CONFIG		U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT			U(0x80000002)
+#define	EV_EFI_BOOT_SERVICES_APPLICATION	U(0x80000003)
+#define	EV_EFI_BOOT_SERVICES_DRIVER		U(0x80000004)
+#define	EV_EFI_RUNTIME_SERVICES_DRIVER		U(0x80000005)
+#define	EV_EFI_GPT_EVENT			U(0x80000006)
+#define	EV_EFI_ACTION				U(0x80000007)
+#define	EV_EFI_PLATFORM_FIRMWARE_BLOB		U(0x80000008)
+#define	EV_EFI_HANDOFF_TABLES			U(0x80000009)
+#define	EV_EFI_HCRTM_EVENT			U(0x80000010)
+#define	EV_EFI_VARIABLE_AUTHORITY		U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256		0x000B
+#define TPM_ALG_SHA384		0x000C
+#define TPM_ALG_SHA512		0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT   0
+#define PLATFORM_CLASS_SERVER   1
+
+enum {
+	/*
+	 * SRTM, BIOS, Host Platform Extensions, Embedded
+	 * Option ROMs and PI Drivers
+	 */
+	PCR_0 = 0,
+	/* Host Platform Configuration */
+	PCR_1,
+	/* UEFI driver and application Code */
+	PCR_2,
+	/* UEFI driver and application Configuration and Data */
+	PCR_3,
+	/* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+	PCR_4,
+	/*
+	 * Boot Manager Code Configuration and Data (for use
+	 * by the Boot Manager Code) and GPT/Partition Table
+	 */
+	PCR_5,
+	/* Host Platform Manufacturer Specific */
+	PCR_6,
+	/* Secure Boot Policy */
+	PCR_7,
+	/* 8-15: Defined for use by the Static OS */
+	PCR_8,
+	/* Debug */
+	PCR_16 = 16,
+
+	/* D-CRTM-measurements by DRTM implementation */
+	PCR_17 = 17,
+	/* DCE measurements by DRTM implementation */
+	PCR_18 = 18
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+	/* PCRIndex:
+	 * The PCR Index to which this event is extended
+	 */
+	uint32_t	pcr_index;
+
+	/* EventType:
+	 * SHALL be an EV_NO_ACTION event
+	 */
+	uint32_t	event_type;
+
+	/* SHALL be 20 Bytes of 0x00 */
+	uint8_t		digest[SHA1_DIGEST_SIZE];
+
+	/* The size of the event */
+	uint32_t	event_size;
+
+	/* SHALL be a TCG_EfiSpecIdEvent */
+	uint8_t		event[];	/* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/* Algorithm ID (hashAlg) of the Hash used by BIOS */
+	uint16_t	algorithm_id;
+
+	/* The size of the digest produced by the implemented Hash algorithm */
+	uint16_t	digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "Spec ID Event03".
+	 * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+	 * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+	 */
+	uint8_t		signature[16];
+
+	/*
+	 * The value for the Platform Class.
+	 * The enumeration is defined in the TCG ACPI Specification Client
+	 * Common Header.
+	 */
+	uint32_t	platform_class;
+
+	/*
+	 * The PC Client Platform Profile Specification minor version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+	 */
+	uint8_t		spec_version_minor;
+
+	/*
+	 * The PC Client Platform Profile Specification major version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_version_major;
+
+	/*
+	 * The PC Client Platform Profile Specification errata version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_errata;
+
+	/*
+	 * Specifies the size of the UINTN fields used in various data
+	 * structures used in this specification.
+	 * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+	 */
+	uint8_t		uintn_size;
+
+	/*
+	 * The number of Hash algorithms in the digestSizes field.
+	 * This field MUST be set to a value of 0x01 or greater.
+	 */
+	uint32_t	number_of_algorithms;
+
+	/*
+	 * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+	 * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+	 * structure, the first of which is a Hash algorithmID and the second
+	 * is the size of the respective digest.
+	 */
+	id_event_algorithm_size_t    digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+	/*
+	 * Size in bytes of the VendorInfo field.
+	 * Maximum value MUST be FFh bytes.
+	 */
+	uint8_t		vendor_info_size;
+
+	/*
+	 * Provided for use by Platform Firmware implementer. The value might
+	 * be used, for example, to provide more detailed information about the
+	 * specific BIOS such as BIOS revision numbers, etc. The values within
+	 * this field are not standardized and are implementer-specific.
+	 * Platform-specific or -unique information MUST NOT be provided in
+	 * this field.
+	 *
+	 */
+	uint8_t		vendor_info[];	/* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+	id_event_struct_header_t	struct_header;
+	id_event_struct_data_t		struct_data;
+} id_event_struct_t;
+
+typedef struct {
+	tcg_pcr_event_t			header;
+	id_event_struct_header_t	struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+	/* Selector of the hash contained in the digest that implies
+	 * the size of the digest
+	 */
+	uint16_t	algorithm_id;	/* AlgorithmId */
+
+	/* Digest, depends on AlgorithmId */
+	uint8_t		digest[];	/* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+	/* The number of digests in the list */
+	uint32_t	count;			/* Count */
+
+	/* The list of tagged digests, as sent to the TPM as part of a
+	 * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+	 */
+	tpmt_ha		digests[];		/* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+	 /* The PCR Index to which this event was extended */
+	uint32_t		pcr_index;	/* PCRIndex */
+
+	/* Type of event */
+	uint32_t		event_type;	/* EventType */
+
+	/* Digests:
+	 * A counted list of tagged digests, which contain the digest of
+	 * the event data (or external data) for all active PCR banks
+	 */
+	tpml_digest_values	digests;	/* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+	/* The size of the event data */
+	uint32_t		event_size;	/* EventSize */
+
+	/* The data of the event */
+	uint8_t			event[];	/* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "StartupLocality" SHALL be
+	 * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+	 * 0x61 0x6C 0x69 0x74 0x79 0x00}
+	 */
+	uint8_t		signature[16];
+
+	/* The Locality Indicator which sent the TPM2_Startup command */
+	uint8_t		startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 09835b5..d9009dd 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -273,6 +273,7 @@
 #define ID_AA64DFR0_PMUVER_SHIFT		U(8)
 #define ID_AA64DFR0_PMUVER_MASK			ULL(0xf)
 #define ID_AA64DFR0_PMUVER_NOT_SUPPORTED	ULL(0)
+#define ID_AA64DFR0_PMUVER_V3P9_SUPPORTED	ULL(9)
 
 /* ID_AA64DFR0_EL1.TraceVer definitions */
 #define ID_AA64DFR0_TRACEVER_SHIFT		U(4)
@@ -285,6 +286,10 @@
 
 /* ID_AA64ISAR0_EL1 definitions */
 #define ID_AA64ISAR0_EL1			S3_0_C0_C6_0
+#define ID_AA64ISAR0_RNDR_MASK			ULL(0xf)
+#define ID_AA64ISAR0_RNDR_SHIFT			U(60)
+#define ID_AA64ISAR0_RNDR_WIDTH			U(4)
+#define ID_AA64ISAR0_RNDR_SUPPORTED		ULL(0x1)
 #define ID_AA64ISAR0_TLB_MASK			ULL(0xf)
 #define ID_AA64ISAR0_TLB_SHIFT			U(56)
 #define ID_AA64ISAR0_TLB_WIDTH			U(4)
@@ -408,6 +413,10 @@
 #define ID_AA64MMFR1_EL1_PAN_SUPPORTED		ULL(0x1)
 #define ID_AA64MMFR1_EL1_PAN2_SUPPORTED		ULL(0x2)
 #define ID_AA64MMFR1_EL1_PAN3_SUPPORTED		ULL(0x3)
+#define ID_AA64MMFR1_EL1_TWED_SHIFT		U(32)
+#define ID_AA64MMFR1_EL1_TWED_MASK		ULL(0xf)
+#define ID_AA64MMFR1_EL1_TWED_WIDTH		U(4)
+#define ID_AA64MMFR1_EL1_TWED_SUPPORTED		ULL(0x1)
 #define ID_AA64MMFR1_EL1_HCX_SHIFT		U(40)
 #define ID_AA64MMFR1_EL1_HCX_MASK		ULL(0xf)
 #define ID_AA64MMFR1_EL1_HCX_SUPPORTED		ULL(0x1)
@@ -1335,6 +1344,7 @@
  * Definitions for system register interface to MPAM
  ******************************************************************************/
 #define MPAMIDR_EL1		S3_0_C10_C4_4
+#define MPAMSM_EL1		S3_0_C10_C5_3
 #define MPAM2_EL2		S3_4_C10_C5_0
 #define MPAMHCR_EL2		S3_4_C10_C4_0
 #define MPAM3_EL3		S3_6_C10_C5_0
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index cee8dd2..3b4fffc 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -230,6 +230,13 @@
 		ID_AA64ISAR2_WFXT_MASK) == ID_AA64ISAR2_WFXT_SUPPORTED);
 }
 
+static inline bool is_feat_rng_present(void)
+{
+	return (((read_id_aa64isar0_el1() >> ID_AA64ISAR0_RNDR_SHIFT) &
+			ID_AA64ISAR0_RNDR_MASK)
+			>= ID_AA64ISAR0_RNDR_SUPPORTED);
+}
+
 static inline bool is_feat_rng_trap_present(void)
 {
 	return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT) &
@@ -273,6 +280,12 @@
 		ID_AA64DFR0_PMUVER_MASK) != ID_AA64DFR0_PMUVER_NOT_SUPPORTED);
 }
 
+static inline bool is_feat_pmuv3p9_present(void)
+{
+	return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMUVER_SHIFT) &
+		ID_AA64DFR0_PMUVER_MASK) >= ID_AA64DFR0_PMUVER_V3P9_SUPPORTED);
+}
+
 static inline bool get_feat_hpmn0_supported(void)
 {
 	return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_HPMN0_SHIFT) &
@@ -477,6 +490,12 @@
 	return amu_get_version() >= ID_AA64PFR0_AMU_V1P1;
 }
 
+static inline bool is_feat_twed_present(void)
+{
+	return EXTRACT(ID_AA64MMFR1_EL1_TWED, read_id_aa64mmfr1_el1())
+		>= ID_AA64MMFR1_EL1_TWED_SUPPORTED;
+}
+
 static inline bool is_feat_trbe_present(void)
 {
 	return EXTRACT(ID_AA64DFR0_TRACEBUFFER, read_id_aa64dfr0_el1())
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 42e104c..ed705bf 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -525,6 +525,7 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2)
 DEFINE_RENAME_SYSREG_WRITE_FUNC(mpamidr_el1, MPAMIDR_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(mpamsm_el1, MPAMSM_EL1)
 DEFINE_RENAME_SYSREG_WRITE_FUNC(mpam0_el1, MPAM0_EL1)
 DEFINE_RENAME_SYSREG_WRITE_FUNC(mpam1_el1, MPAM1_EL1)
 
diff --git a/include/lib/event_log/event_handoff.h b/include/lib/event_log/event_handoff.h
new file mode 100644
index 0000000..e969d1f
--- /dev/null
+++ b/include/lib/event_log/event_handoff.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef HANDOFF_H
+#define HANDOFF_H
+
+#include <stdint.h>
+
+#include <lib/transfer_list.h>
+
+/**
+ * Initializes or extends the TPM event log in the transfer list.
+ *
+ * If an event log entry exists, attempts to resize it. Otherwise, adds a new entry.
+ * Copies old data if needed. Updates free to reflect available space.
+ *
+ * @param tl         Pointer to the transfer list header.
+ * @param req_size   Requested size (bytes)
+ * @param free       Available size (bytes)
+ * @return           Pointer to writable space in the log, or NULL on failure.
+ */
+uint8_t *transfer_list_event_log_extend(struct transfer_list_header *tl,
+					size_t req_size, size_t *free);
+
+/**
+ * Finalizes the event log after writing is complete.
+ *
+ * Resizes the event log to match actual data written, updates checksum,
+ * and flushes cache for the next stage.
+ *
+ * @param tl         Pointer to the transfer list header.
+ * @param cursor     End offset of written log data.
+ * @return           Pointer to finalized log data (past reserved bytes), or NULL.
+ */
+uint8_t *transfer_list_event_log_finish(struct transfer_list_header *tl,
+					uintptr_t cursor);
+
+#define EVENT_LOG_RESERVED_BYTES U(4)
+
+#endif /* HANDOFF_H */
diff --git a/include/lib/event_log/event_log.h b/include/lib/event_log/event_log.h
new file mode 100644
index 0000000..b5adfdc
--- /dev/null
+++ b/include/lib/event_log/event_log.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_H
+#define EVENT_LOG_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <drivers/auth/crypto_mod.h>
+#include "event_handoff.h"
+#include "tcg.h"
+
+/*
+ * Set Event Log debug level to one of:
+ *
+ * LOG_LEVEL_ERROR
+ * LOG_LEVEL_INFO
+ * LOG_LEVEL_WARNING
+ * LOG_LEVEL_VERBOSE
+ */
+#if EVENT_LOG_LEVEL   == LOG_LEVEL_ERROR
+#define	LOG_EVENT	ERROR
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
+#define	LOG_EVENT	NOTICE
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
+#define	LOG_EVENT	WARN
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
+#define	LOG_EVENT	INFO
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
+#define	LOG_EVENT	VERBOSE
+#else
+#define LOG_EVENT printf
+#endif
+
+/* Number of hashing algorithms supported */
+#define HASH_ALG_COUNT		1U
+
+#define EVLOG_INVALID_ID	UINT32_MAX
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+typedef struct {
+	unsigned int id;
+	const char *name;
+	unsigned int pcr;
+} event_log_metadata_t;
+
+#define	ID_EVENT_SIZE	(sizeof(id_event_headers_t) + \
+			(sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
+			sizeof(id_event_struct_data_t))
+
+#define	LOC_EVENT_SIZE	(sizeof(event2_header_t) + \
+			sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+			sizeof(event2_data_t) + \
+			sizeof(startup_locality_event_t))
+
+#define	LOG_MIN_SIZE	(ID_EVENT_SIZE + LOC_EVENT_SIZE)
+
+#define EVENT2_HDR_SIZE	(sizeof(event2_header_t) + \
+			sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+			sizeof(event2_data_t))
+
+/* Functions' declarations */
+
+/**
+ * Initialize the Event Log buffer.
+ *
+ * Sets global pointers to manage the Event Log memory region,
+ * allowing subsequent log operations to write into the buffer.
+ *
+ * @param[in] event_log_start  Pointer to the start of the Event Log buffer.
+ * @param[in] event_log_finish Pointer to the end of the buffer
+ *                             (i.e., one byte past the last valid address).
+ *
+ * @return 0 on success, or -EINVAL if the input range is invalid.
+ */
+int event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish);
+
+/**
+ * Dump the contents of the Event Log.
+ *
+ * Outputs the raw contents of the Event Log buffer, typically
+ * for debugging or audit purposes.
+ *
+ * @param[in] log_addr Pointer to the start of the Event Log buffer.
+ * @param[in] log_size Size of the Event Log buffer in bytes.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_dump(uint8_t *log_addr, size_t log_size);
+
+/**
+ * Initialize the Event Log subsystem.
+ *
+ * Wrapper around `event_log_buf_init()` to configure the memory range
+ * for the Event Log buffer.
+ *
+ * @param[in] event_log_start  Pointer to the start of the Event Log buffer.
+ * @param[in] event_log_finish Pointer to the end of the buffer
+ *                             (i.e., one byte past the last valid address).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish);
+
+/**
+ * Measure input data and log its hash to the Event Log.
+ *
+ * Computes the cryptographic hash of the specified data and records it
+ * in the Event Log as a TCG_PCR_EVENT2 structure using event type EV_POST_CODE.
+ * Useful for firmware or image attestation.
+ *
+ * @param[in] data_base     Pointer to the base of the data to be measured.
+ * @param[in] data_size     Size of the data in bytes.
+ * @param[in] data_id       Identifier used to match against metadata.
+ * @param[in] metadata_ptr  Pointer to an array of event_log_metadata_t.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
+				 uint32_t data_id,
+				 const event_log_metadata_t *metadata_ptr);
+
+/**
+ * Measure the input data and return its hash.
+ *
+ * Computes the cryptographic hash of the specified memory region using
+ * the default hashing algorithm configured in the Event Log subsystem.
+ *
+ * @param[in]  data_base  Pointer to the base of the data to be measured.
+ * @param[in]  data_size  Size of the data in bytes.
+ * @param[out] hash_data  Buffer to hold the resulting hash output
+ *                        (must be at least CRYPTO_MD_MAX_SIZE bytes).
+ *
+ * @return 0 on success, or an error code on failure.
+ */
+int event_log_measure(uintptr_t data_base, uint32_t data_size,
+		      unsigned char hash_data[CRYPTO_MD_MAX_SIZE]);
+
+/**
+ * Record a measurement event in the Event Log.
+ *
+ * Writes a TCG_PCR_EVENT2 structure to the Event Log using the
+ * provided hash and metadata. This function assumes the buffer
+ * has enough space and that `event_log_buf_init()` has been called.
+ *
+ * @param[in] hash         Pointer to the digest (TCG_DIGEST_SIZE bytes).
+ * @param[in] event_type   Type of the event, as defined in tcg.h.
+ * @param[in] metadata_ptr Pointer to an event_log_metadata_t structure
+ *                         providing event-specific context (e.g., PCR index, name).
+ *
+ * @return 0 on success, or -ENOMEM if the buffer has insufficient space.
+ */
+int event_log_record(const uint8_t *hash, uint32_t event_type,
+		     const event_log_metadata_t *metadata_ptr);
+
+/**
+ * Initialize the Event Log with mandatory header events.
+ *
+ * Writes the Specification ID (SpecID) and Startup Locality events
+ * as required by the TCG PC Client Platform Firmware Profile.
+ * These must be the first entries in the Event Log.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_write_header(void);
+
+/**
+ * Write the SpecID event to the Event Log.
+ *
+ * Records the TCG_EfiSpecIDEventStruct to declare the structure
+ * and supported algorithms of the Event Log format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_write_specid_event(void);
+
+/**
+ * Get the current size of the Event Log.
+ *
+ * Calculates how many bytes of the Event Log buffer have been used,
+ * based on the current log pointer and the start of the buffer.
+ *
+ * @param[in] event_log_start Pointer to the start of the Event Log buffer.
+ *
+ * @return The number of bytes currently used in the Event Log.
+ */
+size_t event_log_get_cur_size(uint8_t *event_log_start);
+
+#endif /* EVENT_LOG_H */
diff --git a/include/lib/event_log/tcg.h b/include/lib/event_log/tcg.h
new file mode 100644
index 0000000..653f9c2
--- /dev/null
+++ b/include/lib/event_log/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+#include <common/sha_common_macros.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03	"Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE	"StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2   2
+#define TCG_SPEC_VERSION_MINOR_TPM2   0
+#define TCG_SPEC_ERRATA_TPM2          2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT				U(0x00000000)
+#define EV_POST_CODE				U(0x00000001)
+#define	EV_UNUSED				U(0x00000002)
+#define EV_NO_ACTION				U(0x00000003)
+#define EV_SEPARATOR				U(0x00000004)
+#define EV_ACTION				U(0x00000005)
+#define	EV_EVENT_TAG				U(0x00000006)
+#define EV_S_CRTM_CONTENTS			U(0x00000007)
+#define EV_S_CRTM_VERSION			U(0x00000008)
+#define EV_CPU_MICROCODE			U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS		U(0x0000000A)
+#define EV_TABLE_OF_DEVICES			U(0x0000000B)
+#define EV_COMPACT_HASH				U(0x0000000C)
+#define	EV_IPL					U(0x0000000D)
+#define	EV_IPL_PARTITION_DATA			U(0x0000000E)
+#define EV_NONHOST_CODE				U(0x0000000F)
+#define EV_NONHOST_CONFIG			U(0x00000010)
+#define EV_NONHOST_INFO				U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS		U(0x00000012)
+#define	EV_EFI_EVENT_BASE			U(0x80000000)
+#define	EV_EFI_VARIABLE_DRIVER_CONFIG		U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT			U(0x80000002)
+#define	EV_EFI_BOOT_SERVICES_APPLICATION	U(0x80000003)
+#define	EV_EFI_BOOT_SERVICES_DRIVER		U(0x80000004)
+#define	EV_EFI_RUNTIME_SERVICES_DRIVER		U(0x80000005)
+#define	EV_EFI_GPT_EVENT			U(0x80000006)
+#define	EV_EFI_ACTION				U(0x80000007)
+#define	EV_EFI_PLATFORM_FIRMWARE_BLOB		U(0x80000008)
+#define	EV_EFI_HANDOFF_TABLES			U(0x80000009)
+#define	EV_EFI_HCRTM_EVENT			U(0x80000010)
+#define	EV_EFI_VARIABLE_AUTHORITY		U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256		0x000B
+#define TPM_ALG_SHA384		0x000C
+#define TPM_ALG_SHA512		0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT   0
+#define PLATFORM_CLASS_SERVER   1
+
+enum {
+	/*
+	 * SRTM, BIOS, Host Platform Extensions, Embedded
+	 * Option ROMs and PI Drivers
+	 */
+	PCR_0 = 0,
+	/* Host Platform Configuration */
+	PCR_1,
+	/* UEFI driver and application Code */
+	PCR_2,
+	/* UEFI driver and application Configuration and Data */
+	PCR_3,
+	/* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+	PCR_4,
+	/*
+	 * Boot Manager Code Configuration and Data (for use
+	 * by the Boot Manager Code) and GPT/Partition Table
+	 */
+	PCR_5,
+	/* Host Platform Manufacturer Specific */
+	PCR_6,
+	/* Secure Boot Policy */
+	PCR_7,
+	/* 8-15: Defined for use by the Static OS */
+	PCR_8,
+	/* Debug */
+	PCR_16 = 16,
+
+	/* D-CRTM-measurements by DRTM implementation */
+	PCR_17 = 17,
+	/* DCE measurements by DRTM implementation */
+	PCR_18 = 18
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+	/* PCRIndex:
+	 * The PCR Index to which this event is extended
+	 */
+	uint32_t	pcr_index;
+
+	/* EventType:
+	 * SHALL be an EV_NO_ACTION event
+	 */
+	uint32_t	event_type;
+
+	/* SHALL be 20 Bytes of 0x00 */
+	uint8_t		digest[SHA1_DIGEST_SIZE];
+
+	/* The size of the event */
+	uint32_t	event_size;
+
+	/* SHALL be a TCG_EfiSpecIdEvent */
+	uint8_t		event[];	/* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/* Algorithm ID (hashAlg) of the Hash used by BIOS */
+	uint16_t	algorithm_id;
+
+	/* The size of the digest produced by the implemented Hash algorithm */
+	uint16_t	digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "Spec ID Event03".
+	 * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+	 * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+	 */
+	uint8_t		signature[16];
+
+	/*
+	 * The value for the Platform Class.
+	 * The enumeration is defined in the TCG ACPI Specification Client
+	 * Common Header.
+	 */
+	uint32_t	platform_class;
+
+	/*
+	 * The PC Client Platform Profile Specification minor version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+	 */
+	uint8_t		spec_version_minor;
+
+	/*
+	 * The PC Client Platform Profile Specification major version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_version_major;
+
+	/*
+	 * The PC Client Platform Profile Specification errata version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_errata;
+
+	/*
+	 * Specifies the size of the UINTN fields used in various data
+	 * structures used in this specification.
+	 * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+	 */
+	uint8_t		uintn_size;
+
+	/*
+	 * The number of Hash algorithms in the digestSizes field.
+	 * This field MUST be set to a value of 0x01 or greater.
+	 */
+	uint32_t	number_of_algorithms;
+
+	/*
+	 * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+	 * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+	 * structure, the first of which is a Hash algorithmID and the second
+	 * is the size of the respective digest.
+	 */
+	id_event_algorithm_size_t    digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+	/*
+	 * Size in bytes of the VendorInfo field.
+	 * Maximum value MUST be FFh bytes.
+	 */
+	uint8_t		vendor_info_size;
+
+	/*
+	 * Provided for use by Platform Firmware implementer. The value might
+	 * be used, for example, to provide more detailed information about the
+	 * specific BIOS such as BIOS revision numbers, etc. The values within
+	 * this field are not standardized and are implementer-specific.
+	 * Platform-specific or -unique information MUST NOT be provided in
+	 * this field.
+	 *
+	 */
+	uint8_t		vendor_info[];	/* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+	id_event_struct_header_t	struct_header;
+	id_event_struct_data_t		struct_data;
+} id_event_struct_t;
+
+typedef struct {
+	tcg_pcr_event_t			header;
+	id_event_struct_header_t	struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+	/* Selector of the hash contained in the digest that implies
+	 * the size of the digest
+	 */
+	uint16_t	algorithm_id;	/* AlgorithmId */
+
+	/* Digest, depends on AlgorithmId */
+	uint8_t		digest[];	/* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+	/* The number of digests in the list */
+	uint32_t	count;			/* Count */
+
+	/* The list of tagged digests, as sent to the TPM as part of a
+	 * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+	 */
+	tpmt_ha		digests[];		/* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+	 /* The PCR Index to which this event was extended */
+	uint32_t		pcr_index;	/* PCRIndex */
+
+	/* Type of event */
+	uint32_t		event_type;	/* EventType */
+
+	/* Digests:
+	 * A counted list of tagged digests, which contain the digest of
+	 * the event data (or external data) for all active PCR banks
+	 */
+	tpml_digest_values	digests;	/* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+	/* The size of the event data */
+	uint32_t		event_size;	/* EventSize */
+
+	/* The data of the event */
+	uint8_t			event[];	/* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "StartupLocality" SHALL be
+	 * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+	 * 0x61 0x6C 0x69 0x74 0x79 0x00}
+	 */
+	uint8_t		signature[16];
+
+	/* The Locality Indicator which sent the TPM2_Startup command */
+	uint8_t		startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index f1e4181..eee2b82 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -48,6 +48,7 @@
 	TL_TAG_HOB_BLOCK = 2,
 	TL_TAG_HOB_LIST = 3,
 	TL_TAG_ACPI_TABLE_AGGREGATE = 4,
+	TL_TAG_TPM_EVLOG = 5,
 };
 
 enum transfer_list_ops {
@@ -91,6 +92,10 @@
 	 */
 };
 
+struct transfer_list_entry *
+transfer_list_next(struct transfer_list_header *tl,
+		   struct transfer_list_entry *last);
+
 bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
 
 void *transfer_list_entry_data(struct transfer_list_entry *entry);
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 0013d19..0128277 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -184,4 +184,44 @@
 #define CONCAT(x, y)	x##y
 #define CONC(x, y)	CONCAT(x, y)
 
+/* add operation together with checking whether the operation overflowed
+ * The result is '*res',
+ * return 0 on success and 1 on overflow
+ */
+#define add_overflow(a, b, res) __builtin_add_overflow((a), (b), (res))
+
+/*
+ * Round up a value to align with a given size and
+ * check whether overflow happens.
+ * The rounduped value is '*res',
+ * return 0 on success and 1 on overflow
+ */
+#define round_up_overflow(v, size, res)                                     \
+	(__extension__({                                                    \
+		typeof(res) __res = res;                                    \
+		typeof(*(__res)) __roundup_tmp = 0;                         \
+		typeof(v) __roundup_mask = (typeof(v))(size) - 1;           \
+                                                                            \
+		add_overflow((v), __roundup_mask, &__roundup_tmp) ?         \
+			1 :                                                 \
+			(void)(*(__res) = __roundup_tmp & ~__roundup_mask), \
+			0;                                                  \
+	}))
+
+/*
+ * Add a with b, then round up the result to align with a given size and
+ * check whether overflow happens.
+ * The rounduped value is '*res',
+ * return 0 on success and 1 on overflow
+ */
+#define add_with_round_up_overflow(a, b, size, res)               \
+	(__extension__({                                          \
+		typeof(a) __a = (a);                              \
+		typeof(__a) __add_res = 0;                        \
+                                                                  \
+		add_overflow((__a), (b), &__add_res)	    ? 1 : \
+		round_up_overflow(__add_res, (size), (res)) ? 1 : \
+							      0;  \
+	}))
+
 #endif /* UTILS_DEF_H */
diff --git a/include/runtime_services/cactus_message_loop.h b/include/runtime_services/cactus_message_loop.h
index 4d963ac..a13f42f 100644
--- a/include/runtime_services/cactus_message_loop.h
+++ b/include/runtime_services/cactus_message_loop.h
@@ -42,3 +42,5 @@
 
 bool cactus_handle_cmd(struct ffa_value *cmd_args, struct ffa_value *ret,
 		       struct mailbox_buffers *mb);
+
+struct ffa_value cactus_handle_framework_msg(struct ffa_value args);
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 0a63e96..67fd393 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -349,6 +349,33 @@
 	return (args.arg2 >> 48) & 0xFFFFU;
 }
 
+/**
+ * FF-A Framework message helpers
+ */
+#define FFA_FRAMEWORK_MSG_BIT (1U << 31)
+
+#define FFA_FRAMEWORK_MSG_MASK 0xFFU
+
+#define FFA_FRAMEWORK_MSG_PSCI_REQ 0U
+#define FFA_FRAMEWORK_MSG_PSCI_RESP 2U
+
+static inline uint32_t ffa_framework_msg_flags(struct ffa_value args)
+{
+	return (uint32_t)args.arg2;
+}
+
+static inline bool ffa_is_framework_msg(struct ffa_value args)
+{
+	return (ffa_func_id(args) == FFA_MSG_SEND_DIRECT_REQ_SMC32 ||
+		ffa_func_id(args) == FFA_MSG_SEND_DIRECT_REQ_SMC64) &&
+		((ffa_framework_msg_flags(args) & FFA_FRAMEWORK_MSG_BIT) != 0);
+}
+
+static inline uint32_t ffa_get_framework_msg(struct ffa_value args)
+{
+	return ffa_framework_msg_flags(args) & FFA_FRAMEWORK_MSG_MASK;
+}
+
 typedef uint64_t ffa_notification_bitmap_t;
 
 /**
@@ -933,7 +960,12 @@
 					    uint32_t arg1, uint32_t arg2,
 					    uint32_t arg3, uint32_t arg4);
 
+struct ffa_value ffa_framework_msg_send_direct_resp(ffa_id_t source_id,
+					    ffa_id_t dest_id, uint32_t msg,
+					    uint32_t status_code);
+
 struct ffa_value ffa_run(uint32_t dest_id, uint32_t vcpu_id);
+struct ffa_value ffa_yield(void);
 struct ffa_value ffa_version(uint32_t input_version);
 struct ffa_value ffa_id_get(void);
 struct ffa_value ffa_spm_id_get(void);
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index ddf4559..4c82507 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -15,18 +15,22 @@
  * FFA error codes.
  * Don't forget to update `ffa_error_name` if you add a new one.
  */
-#define FFA_ERROR_NOT_SUPPORTED		-1
-#define FFA_ERROR_INVALID_PARAMETER	-2
-#define FFA_ERROR_NO_MEMORY		-3
-#define FFA_ERROR_BUSY			-4
-#define FFA_ERROR_INTERRUPTED		-5
-#define FFA_ERROR_DENIED		-6
-#define FFA_ERROR_RETRY			-7
-#define FFA_ERROR_ABORTED		-8
-#define FFA_ERROR_NO_DATA		-9
+/* clang-format off */
+enum ffa_error {
+	FFA_ERROR_NOT_SUPPORTED 	= -1,
+	FFA_ERROR_INVALID_PARAMETER 	= -2,
+	FFA_ERROR_NO_MEMORY 		= -3,
+	FFA_ERROR_BUSY 			= -4,
+	FFA_ERROR_INTERRUPTED 		= -5,
+	FFA_ERROR_DENIED 		= -6,
+	FFA_ERROR_RETRY 		= -7,
+	FFA_ERROR_ABORTED 		= -8,
+	FFA_ERROR_NO_DATA 		= -9,
+};
+/* clang-format on */
 
 /* Return the name of the error code. */
-static inline const char *ffa_error_name(int32_t error)
+static inline const char *ffa_error_name(enum ffa_error error)
 {
 	switch (error) {
 	case FFA_ERROR_NOT_SUPPORTED:
@@ -47,9 +51,8 @@
 		return "FFA_ERROR_ABORTED";
 	case FFA_ERROR_NO_DATA:
 		return "FFA_ERROR_NO_DATA";
-	default:
-		return "UNKNOWN";
 	}
+	return "UNKNOWN";
 }
 
 /* The macros below are used to identify FFA calls from the SMC function ID */
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
index 771a125..4a87ede 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -583,7 +583,7 @@
 #define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_SHIFT	45UL
 #define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_WIDTH	4UL
 
-#define RMI_FEATURE_REGISTER_0_RTT_S2AP_INDIRECT	BIT(50)
+#define RMI_FEATURE_REGISTER_0_RTT_S2AP_INDIRECT	BIT(49)
 
 /* Possible values for RmiPlaneRttFeature */
 #define RMI_PLANE_RTT_AUX				0UL
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index fa755b9..33ee54e 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -106,10 +106,10 @@
 
 bool check_spmc_execution_level(void);
 
-unsigned int get_ffa_feature_test_target(
-		const struct ffa_features_test **test_target);
+size_t get_ffa_feature_test_target(
+	const struct ffa_features_test **test_target);
 bool ffa_features_test_targets(const struct ffa_features_test *targets,
-			       uint32_t test_target_size);
+			       size_t test_target_size);
 
 /**
  * Helper to conduct a memory retrieve. This is to be called by the receiver
diff --git a/include/runtime_services/spm_test_helpers.h b/include/runtime_services/spm_test_helpers.h
index 14b2fb5..93675ce 100644
--- a/include/runtime_services/spm_test_helpers.h
+++ b/include/runtime_services/spm_test_helpers.h
@@ -15,14 +15,16 @@
 #define SKIP_TEST_IF_FFA_VERSION_LESS_THAN(major, minor)			\
 	do {									\
 		struct ffa_value ret = ffa_version(FFA_VERSION_COMPILED);	\
-		enum ffa_version version = ret.fid;				\
+		enum ffa_version version;					\
 										\
-		if (version == FFA_ERROR_NOT_SUPPORTED) {			\
+		if (ret.fid == FFA_ERROR_NOT_SUPPORTED) {			\
 			tftf_testcase_printf("FFA_VERSION not supported.\n");	\
 			return TEST_RESULT_SKIPPED;				\
 		}								\
 										\
-		if (!ffa_version_is_valid(version)) {			\
+		version = ret.fid;						\
+										\
+		if (!ffa_version_is_valid(version)) {				\
 			tftf_testcase_printf("FFA_VERSION bad response: %x\n",	\
 					version);				\
 			return TEST_RESULT_FAIL;				\
diff --git a/include/runtime_services/ven_el3_svc.h b/include/runtime_services/ven_el3_svc.h
index 3a61ecd..04f501e 100644
--- a/include/runtime_services/ven_el3_svc.h
+++ b/include/runtime_services/ven_el3_svc.h
@@ -19,6 +19,6 @@
 #define VEN_EL3_SVC_VERSION	0x8700ff03
 
 #define VEN_EL3_SVC_VERSION_MAJOR	1
-#define VEN_EL3_SVC_VERSION_MINOR	0
+#define VEN_EL3_SVC_VERSION_MINOR	1
 
 #endif /* VEN_EL3_SVC_H */
diff --git a/lib/event_log/event_handoff.c b/lib/event_log/event_handoff.c
new file mode 100644
index 0000000..238ea27
--- /dev/null
+++ b/lib/event_log/event_handoff.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/event_log/event_handoff.h>
+
+#include <platform_def.h>
+
+static uint8_t *get_log_ptr(struct transfer_list_entry *te, size_t offset)
+{
+	uint8_t *base_ptr = transfer_list_entry_data(te);
+
+	if (base_ptr == NULL) {
+		return NULL;
+	}
+
+	return base_ptr + offset;
+}
+
+uint8_t *transfer_list_event_log_extend(struct transfer_list_header *tl,
+					size_t req_size, size_t *free)
+{
+	struct transfer_list_entry *existing_entry;
+	struct transfer_list_entry *new_entry;
+	uint8_t *old_data;
+	size_t existing_offset;
+	size_t old_size;
+
+	if (tl == NULL || free == NULL || req_size == 0) {
+		ERROR("Invalid arguments to event log extend.\n");
+		return NULL;
+	}
+
+	existing_entry = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+	existing_offset = EVENT_LOG_RESERVED_BYTES;
+
+	if (existing_entry != NULL) {
+		existing_offset = existing_entry->data_size;
+
+		if (transfer_list_set_data_size(tl, existing_entry,
+						req_size + existing_offset)) {
+			VERBOSE("TPM event log entry resized: new space %zu bytes at offset %zu\n",
+				req_size, existing_offset);
+
+			*free = existing_entry->data_size - existing_offset;
+
+			return get_log_ptr(existing_entry, existing_offset);
+		}
+	}
+
+	/* Add new entry (resize failed or no existing entry) */
+	new_entry = transfer_list_add(tl, TL_TAG_TPM_EVLOG,
+				      req_size + existing_offset, NULL);
+
+	if (new_entry == NULL) {
+		ERROR("Failed to add TPM event log entry to transfer list.\n");
+		return NULL;
+	}
+
+	VERBOSE("New TPM event log entry added at %p\n",
+		transfer_list_entry_data(new_entry));
+
+	if (existing_entry != NULL) {
+		old_data = transfer_list_entry_data(existing_entry);
+		old_size = existing_offset;
+
+		VERBOSE("Copying existing event log (%zu bytes) to new entry at %p\n",
+			old_size, transfer_list_entry_data(new_entry));
+
+		memmove(transfer_list_entry_data(new_entry), old_data,
+			old_size);
+
+		transfer_list_rem(tl, existing_entry);
+	}
+
+	*free = new_entry->data_size - existing_offset;
+
+	return get_log_ptr(new_entry, existing_offset);
+}
+
+uint8_t *transfer_list_event_log_finish(struct transfer_list_header *tl,
+					uintptr_t cursor)
+{
+	uintptr_t entry_data_base;
+	size_t final_log_size;
+	struct transfer_list_entry *entry;
+
+	entry = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+	entry_data_base = (uintptr_t)transfer_list_entry_data(entry);
+
+	if (cursor < entry_data_base ||
+	    cursor >= entry_data_base + entry->data_size) {
+		ERROR("Invalid cursor: outside event log bounds.\n");
+		return NULL;
+	}
+
+	final_log_size = cursor - entry_data_base;
+
+	if (!transfer_list_set_data_size(tl, entry, final_log_size)) {
+		ERROR("Unable to resize event log TE.\n");
+		return NULL;
+	}
+
+	transfer_list_update_checksum(tl);
+
+	VERBOSE("TPM event log finalized: trimmed to %zu bytes",
+		final_log_size - EVENT_LOG_RESERVED_BYTES);
+
+	/* Ensure changes are visible to the next stage. */
+	flush_dcache_range((uintptr_t)tl, tl->size);
+
+	return get_log_ptr(entry, EVENT_LOG_RESERVED_BYTES);
+}
diff --git a/lib/event_log/event_log.c b/lib/event_log/event_log.c
new file mode 100644
index 0000000..761ff29
--- /dev/null
+++ b/lib/event_log/event_log.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "crypto_mod.h"
+#include "event_log.h"
+
+#if TPM_ALG_ID == TPM_ALG_SHA512
+#define	CRYPTO_MD_ID	CRYPTO_MD_SHA512
+#elif TPM_ALG_ID == TPM_ALG_SHA384
+#define	CRYPTO_MD_ID	CRYPTO_MD_SHA384
+#elif TPM_ALG_ID == TPM_ALG_SHA256
+#define	CRYPTO_MD_ID	CRYPTO_MD_SHA256
+#else
+#  error Invalid TPM algorithm.
+#endif /* TPM_ALG_ID */
+
+/* Running Event Log Pointer */
+static uint8_t *log_ptr;
+
+/* Pointer to the first byte past end of the Event Log buffer */
+static uintptr_t log_end;
+
+/* TCG_EfiSpecIdEvent */
+static const id_event_headers_t id_event_header = {
+	.header = {
+		.pcr_index = PCR_0,
+		.event_type = EV_NO_ACTION,
+		.digest = {0},
+		.event_size = (uint32_t)(sizeof(id_event_struct_t) +
+				(sizeof(id_event_algorithm_size_t) *
+				HASH_ALG_COUNT))
+	},
+
+	.struct_header = {
+		.signature = TCG_ID_EVENT_SIGNATURE_03,
+		.platform_class = PLATFORM_CLASS_CLIENT,
+		.spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
+		.spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
+		.spec_errata = TCG_SPEC_ERRATA_TPM2,
+		.uintn_size = (uint8_t)(sizeof(unsigned int) /
+					sizeof(uint32_t)),
+		.number_of_algorithms = HASH_ALG_COUNT
+	}
+};
+
+static const event2_header_t locality_event_header = {
+	/*
+	 * All EV_NO_ACTION events SHALL set
+	 * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
+	 */
+	.pcr_index = PCR_0,
+
+	/*
+	 * All EV_NO_ACTION events SHALL set
+	 * TCG_PCR_EVENT2.eventType = 03h
+	 */
+	.event_type = EV_NO_ACTION,
+
+	/*
+	 * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all
+	 * 0x00's for each allocated Hash algorithm
+	 */
+	.digests = {
+		.count = HASH_ALG_COUNT
+	}
+};
+
+int event_log_record(const uint8_t *hash, uint32_t event_type,
+		      const event_log_metadata_t *metadata_ptr)
+{
+	void *ptr = log_ptr;
+	uint32_t name_len = 0U;
+
+	/* event_log_buf_init() must have been called prior to this. */
+	if (hash == NULL || metadata_ptr == NULL || log_ptr == NULL) {
+		return -EINVAL;
+	}
+
+	if (metadata_ptr->name != NULL) {
+		name_len = (uint32_t)strlen(metadata_ptr->name) + 1U;
+	}
+
+	/* Check for space in Event Log buffer */
+	if (((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) > log_end) {
+		return -ENOMEM;
+	}
+
+	/*
+	 * As per TCG specifications, firmware components that are measured
+	 * into PCR[0] must be logged in the event log using the event type
+	 * EV_POST_CODE.
+	 */
+	/* TCG_PCR_EVENT2.PCRIndex */
+	((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr;
+
+	/* TCG_PCR_EVENT2.EventType */
+	((event2_header_t *)ptr)->event_type = event_type;
+
+	/* TCG_PCR_EVENT2.Digests.Count */
+	ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
+	((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
+
+	/* TCG_PCR_EVENT2.Digests[] */
+	ptr = (uint8_t *)((uintptr_t)ptr +
+			offsetof(tpml_digest_values, digests));
+
+	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+	/* TCG_PCR_EVENT2.Digests[].Digest[] */
+	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
+
+	/* Copy digest */
+	(void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
+
+	/* TCG_PCR_EVENT2.EventSize */
+	ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE);
+	((event2_data_t *)ptr)->event_size = name_len;
+
+	/* Copy event data to TCG_PCR_EVENT2.Event */
+	if (metadata_ptr->name != NULL) {
+		(void)memcpy((void *)(((event2_data_t *)ptr)->event),
+				(const void *)metadata_ptr->name, name_len);
+	}
+
+	/* End of event data */
+	log_ptr = (uint8_t *)((uintptr_t)ptr +
+			offsetof(event2_data_t, event) + name_len);
+
+	return 0;
+}
+
+int event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+{
+	if (event_log_start == NULL || event_log_finish == NULL ||
+	    event_log_start > event_log_finish) {
+		return -EINVAL;
+	}
+
+	log_ptr = event_log_start;
+	log_end = (uintptr_t)event_log_finish;
+
+	return 0;
+}
+
+int event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+{
+	return event_log_buf_init(event_log_start, event_log_finish);
+}
+
+int event_log_write_specid_event(void)
+{
+	void *ptr;
+
+	/* event_log_buf_init() must have been called prior to this. */
+	if (log_ptr == NULL) {
+		return -EFAULT;
+	}
+
+	if (((uintptr_t)log_ptr + ID_EVENT_SIZE) > log_end) {
+		return -ENOMEM;
+	}
+
+	ptr = log_ptr;
+
+	/*
+	 * Add Specification ID Event first
+	 *
+	 * Copy TCG_EfiSpecIDEventStruct structure header
+	 */
+	(void)memcpy(ptr, (const void *)&id_event_header,
+			sizeof(id_event_header));
+	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header));
+
+	/* TCG_EfiSpecIdEventAlgorithmSize structure */
+	((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
+	((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
+	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t));
+
+	/*
+	 * TCG_EfiSpecIDEventStruct.vendorInfoSize
+	 * No vendor data
+	 */
+	((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
+	log_ptr = (uint8_t *)((uintptr_t)ptr +
+			offsetof(id_event_struct_data_t, vendor_info));
+
+	return 0;
+}
+
+int event_log_write_header(void)
+{
+	const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
+	void *ptr;
+	int rc;
+
+	rc = event_log_write_specid_event();
+	if (rc < 0) {
+		return rc;
+	}
+
+	if (((uintptr_t)log_ptr + LOC_EVENT_SIZE) > log_end) {
+		return -ENOMEM;
+	}
+
+	ptr = log_ptr;
+
+	/*
+	 * The Startup Locality event should be placed in the log before
+	 * any event which extends PCR[0].
+	 *
+	 * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+	 */
+
+	/* Copy Startup Locality Event Header */
+	(void)memcpy(ptr, (const void *)&locality_event_header,
+			sizeof(locality_event_header));
+	ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header));
+
+	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+	/* TCG_PCR_EVENT2.Digests[].Digest[] */
+	(void)memset(&((tpmt_ha *)ptr)->digest, 0, TCG_DIGEST_SIZE);
+	ptr = (uint8_t *)((uintptr_t)ptr +
+			offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE);
+
+	/* TCG_PCR_EVENT2.EventSize */
+	((event2_data_t *)ptr)->event_size =
+		(uint32_t)sizeof(startup_locality_event_t);
+	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
+
+	/* TCG_EfiStartupLocalityEvent.Signature */
+	(void)memcpy(ptr, (const void *)locality_signature,
+		sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
+
+	/*
+	 * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
+	 * the platform's boot firmware
+	 */
+	((startup_locality_event_t *)ptr)->startup_locality = 0U;
+	log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t));
+
+	return 0;
+}
+
+int event_log_measure(uintptr_t data_base, uint32_t data_size,
+		      unsigned char hash_data[CRYPTO_MD_MAX_SIZE])
+{
+	/* Calculate hash */
+	return crypto_mod_calc_hash(CRYPTO_MD_ID,
+				    (void *)data_base, data_size, hash_data);
+}
+
+int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
+				 uint32_t data_id,
+				 const event_log_metadata_t *metadata_ptr)
+{
+	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
+	int rc;
+
+	if (metadata_ptr == NULL) {
+		return -EINVAL;
+	}
+
+	/* Get the metadata associated with this image. */
+	while (metadata_ptr->id != data_id) {
+		if (metadata_ptr->id == EVLOG_INVALID_ID) {
+			return -EINVAL;
+		}
+
+		metadata_ptr++;
+	}
+
+	/* Measure the payload with algorithm selected by EventLog driver */
+	rc = event_log_measure(data_base, data_size, hash_data);
+	if (rc != 0) {
+		return rc;
+	}
+
+	rc = event_log_record(hash_data, EV_POST_CODE, metadata_ptr);
+	if (rc != 0) {
+		return rc;
+	}
+
+	return 0;
+}
+
+size_t event_log_get_cur_size(uint8_t *event_log_start)
+{
+	assert(event_log_start != NULL);
+	assert(log_ptr >= event_log_start);
+
+	return (size_t)((uintptr_t)log_ptr - (uintptr_t)event_log_start);
+}
diff --git a/lib/event_log/event_log.mk b/lib/event_log/event_log.mk
new file mode 100644
index 0000000..df55c62
--- /dev/null
+++ b/lib/event_log/event_log.mk
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Path to library sources
+EVENT_LOG_SRC_DIR	:= lib/event_log/
+
+# Default log level to dump the event log (LOG_LEVEL_INFO)
+EVENT_LOG_LEVEL		?= 40
+
+EVENT_LOG_SOURCES	:=	${EVENT_LOG_SRC_DIR}event_print.c
+
+INCLUDES		+=	-Iinclude/lib/event_log \
+				-Iinclude/drivers/auth
+
+ifdef CRYPTO_SUPPORT
+# Measured Boot hash algorithm.
+# SHA-256 (or stronger) is required for all devices that are TPM 2.0 compliant.
+ifdef TPM_HASH_ALG
+    $(warning "TPM_HASH_ALG is deprecated. Please use MBOOT_EL_HASH_ALG instead.")
+    MBOOT_EL_HASH_ALG		:=	${TPM_HASH_ALG}
+else
+    MBOOT_EL_HASH_ALG		:=	sha256
+endif
+
+ifeq (${MBOOT_EL_HASH_ALG}, sha512)
+    TPM_ALG_ID			:=	TPM_ALG_SHA512
+    TCG_DIGEST_SIZE		:=	64U
+else ifeq (${MBOOT_EL_HASH_ALG}, sha384)
+    TPM_ALG_ID			:=	TPM_ALG_SHA384
+    TCG_DIGEST_SIZE		:=	48U
+else
+    TPM_ALG_ID			:=	TPM_ALG_SHA256
+    TCG_DIGEST_SIZE		:=	32U
+endif #MBOOT_EL_HASH_ALG
+
+# Set definitions for event log library.
+$(eval $(call add_define,TFTF_DEFINES,TPM_ALG_ID))
+$(eval $(call add_define,TFTF_DEFINES,EVENT_LOG_LEVEL))
+$(eval $(call add_define,TFTF_DEFINES,TCG_DIGEST_SIZE))
+
+EVENT_LOG_SOURCES	:=	${EVENT_LOG_SRC_DIR}event_log.c
+
+INCLUDES		+=	-Iinclude/lib/event_log \
+				-Iinclude/drivers/auth
+
+ifeq (${TRANSFER_LIST}, 1)
+EVENT_LOG_SOURCES	+= ${EVENT_LOG_SRC_DIR}/event_handoff.c
+INCLUDES		+=	-Iinclude/lib
+endif
+
+endif
diff --git a/lib/event_log/event_print.c b/lib/event_log/event_print.c
new file mode 100644
index 0000000..234a694
--- /dev/null
+++ b/lib/event_log/event_print.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include "event_log.h"
+
+/**
+ * Print a TCG_EfiSpecIDEventStruct entry from the event log.
+ *
+ * This function extracts and prints a TCG_EfiSpecIDEventStruct
+ * entry from the event log for debugging or auditing purposes.
+ *
+ * @param[in,out] log_addr  Pointer to the current position in the Event Log.
+ *                          Updated to the next entry after processing.
+ * @param[in,out] log_size  Pointer to the remaining Event Log size.
+ *                          Updated to reflect the remaining bytes.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+static int event_log_print_id_event(uint8_t **log_addr, size_t *log_size)
+{
+	unsigned int i;
+	uint8_t info_size, *info_size_ptr;
+	void *ptr = *log_addr;
+	id_event_headers_t *event = (id_event_headers_t *)ptr;
+	id_event_algorithm_size_t *alg_ptr;
+	uint32_t event_size, number_of_algorithms;
+	size_t digest_len;
+	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
+
+	if (*log_size < sizeof(id_event_headers_t)) {
+		return -EINVAL;
+	}
+
+	/* The fields of the event log header are defined to be PCRIndex of 0,
+	 * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
+	 * Event content defined as TCG_EfiSpecIDEventStruct.
+	 */
+	LOG_EVENT("TCG_EfiSpecIDEvent:\n");
+	LOG_EVENT("  PCRIndex           : %u\n", event->header.pcr_index);
+	if (event->header.pcr_index != (uint32_t)PCR_0) {
+		return -EINVAL;
+	}
+
+	LOG_EVENT("  EventType          : %u\n", event->header.event_type);
+	if (event->header.event_type != EV_NO_ACTION) {
+		return -EINVAL;
+	}
+
+	LOG_EVENT("  Digest             :");
+	for (i = 0U; i < sizeof(event->header.digest); ++i) {
+		uint8_t val = event->header.digest[i];
+
+		(void)printf(" %02x", val);
+		if ((i & U(0xF)) == 0U) {
+			(void)printf("\n");
+			LOG_EVENT("\t\t      :");
+		}
+	}
+
+	if ((i & U(0xF)) != 0U) {
+		(void)printf("\n");
+	}
+
+	/* EventSize */
+	event_size = event->header.event_size;
+	LOG_EVENT("  EventSize          : %u\n", event_size);
+
+	LOG_EVENT("  Signature          : %s\n",
+			event->struct_header.signature);
+	LOG_EVENT("  PlatformClass      : %u\n",
+			event->struct_header.platform_class);
+	LOG_EVENT("  SpecVersion        : %u.%u.%u\n",
+			event->struct_header.spec_version_major,
+			event->struct_header.spec_version_minor,
+			event->struct_header.spec_errata);
+	LOG_EVENT("  UintnSize          : %u\n",
+			event->struct_header.uintn_size);
+
+	/* NumberOfAlgorithms */
+	number_of_algorithms = event->struct_header.number_of_algorithms;
+	LOG_EVENT("  NumberOfAlgorithms : %u\n", number_of_algorithms);
+
+	/* Address of DigestSizes[] */
+	alg_ptr = event->struct_header.digest_size;
+
+	/* Size of DigestSizes[] */
+	digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
+	if (digest_len > (uintptr_t)end_ptr - (uintptr_t)alg_ptr) {
+		return -EFAULT;
+	}
+
+	LOG_EVENT("  DigestSizes        :\n");
+	for (i = 0U; i < number_of_algorithms; ++i) {
+		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
+		uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+
+		switch (algorithm_id) {
+		case TPM_ALG_SHA256:
+			(void)printf("256\n");
+			break;
+		case TPM_ALG_SHA384:
+			(void)printf("384\n");
+			break;
+		case TPM_ALG_SHA512:
+			(void)printf("512\n");
+			break;
+		default:
+			(void)printf("?\n");
+			ERROR("Algorithm 0x%x not found\n", algorithm_id);
+			return -ENOENT;
+		}
+
+		LOG_EVENT("       DigestSize    : %u\n",
+					alg_ptr[i].digest_size);
+	}
+
+	/* Address of VendorInfoSize */
+	info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len);
+	if ((uintptr_t)info_size_ptr > (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
+
+	info_size = *info_size_ptr++;
+	LOG_EVENT("  VendorInfoSize     : %u\n", info_size);
+
+	/* Check VendorInfo end address */
+	if (((uintptr_t)info_size_ptr + info_size) > (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
+
+	/* Check EventSize */
+	if (event_size !=
+	    (sizeof(id_event_struct_t) + digest_len + info_size)) {
+		return -EFAULT;
+	}
+
+	if (info_size != 0U) {
+		LOG_EVENT("  VendorInfo         :");
+		for (i = 0U; i < info_size; ++i) {
+			(void)printf(" %02x", *info_size_ptr++);
+		}
+		(void)printf("\n");
+	}
+
+	*log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
+	*log_addr = info_size_ptr;
+
+	return 0;
+}
+
+/**
+ * Print a TCG_PCR_EVENT2 entry from the event log.
+ *
+ * This function extracts and prints a TCG_PCR_EVENT2 structure
+ * from the event log for debugging or auditing purposes.
+ *
+ * @param[in,out] log_addr  Pointer to the current position in the Event Log.
+ *                          Updated to the next entry after processing.
+ * @param[in,out] log_size  Pointer to the remaining Event Log size.
+ *                          Updated to reflect the remaining bytes.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+static int event_log_print_pcr_event2(uint8_t **log_addr, size_t *log_size)
+{
+	uint32_t event_size, count;
+	size_t sha_size, digests_size = 0U;
+	void *ptr = *log_addr;
+	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
+
+	if (*log_size < sizeof(event2_header_t)) {
+		return -EINVAL;
+	}
+
+	LOG_EVENT("PCR_Event2:\n");
+	LOG_EVENT("  PCRIndex           : %u\n",
+			((event2_header_t *)ptr)->pcr_index);
+	LOG_EVENT("  EventType          : %u\n",
+			((event2_header_t *)ptr)->event_type);
+
+	count = ((event2_header_t *)ptr)->digests.count;
+	if (count < 1U) {
+		LOG_EVENT("Invalid Digests Count      : %u\n", count);
+		return -EINVAL;
+	}
+
+	LOG_EVENT("  Digests Count      : %u\n", count);
+
+	/* Address of TCG_PCR_EVENT2.Digests[] */
+	ptr = (uint8_t *)ptr + sizeof(event2_header_t);
+	if ((uintptr_t)ptr > (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
+
+	for (unsigned int i = 0U; i < count; ++i) {
+		/* Check AlgorithmId address */
+		if (((uintptr_t)ptr + offsetof(tpmt_ha, digest)) >
+		    (uintptr_t)end_ptr) {
+			return -EFAULT;
+		}
+
+		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
+		switch (((tpmt_ha *)ptr)->algorithm_id) {
+		case TPM_ALG_SHA256:
+			sha_size = SHA256_DIGEST_SIZE;
+			(void)printf("256\n");
+			break;
+		case TPM_ALG_SHA384:
+			sha_size = SHA384_DIGEST_SIZE;
+			(void)printf("384\n");
+			break;
+		case TPM_ALG_SHA512:
+			sha_size = SHA512_DIGEST_SIZE;
+			(void)printf("512\n");
+			break;
+		default:
+			(void)printf("?\n");
+			printf("Algorithm 0x%x not found\n",
+				((tpmt_ha *)ptr)->algorithm_id);
+			return -ENOENT;
+		}
+
+		/* End of Digest[] */
+		ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
+		if (((uintptr_t)ptr + sha_size) > (uintptr_t)end_ptr) {
+			return -EFAULT;
+		}
+
+		/* Total size of all digests */
+		digests_size += sha_size;
+
+		LOG_EVENT("       Digest        :");
+		for (unsigned int j = 0U; j < sha_size; ++j) {
+			(void)printf(" %02x", *(uint8_t *)ptr++);
+			if ((j & U(0xF)) == U(0xF)) {
+				(void)printf("\n");
+				if (j < (sha_size - 1U)) {
+					LOG_EVENT("\t\t      :");
+				}
+			}
+		}
+	}
+
+	/* TCG_PCR_EVENT2.EventSize */
+	if (((uintptr_t)ptr + offsetof(event2_data_t, event)) >
+	    (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
+
+	event_size = ((event2_data_t *)ptr)->event_size;
+	LOG_EVENT("  EventSize          : %u\n", event_size);
+
+	/* Address of TCG_PCR_EVENT2.Event[EventSize] */
+	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
+
+	/* End of TCG_PCR_EVENT2.Event[EventSize] */
+	if (((uintptr_t)ptr + event_size) > (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
+
+	if ((event_size == sizeof(startup_locality_event_t)) &&
+	     (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
+		LOG_EVENT("  Signature          : %s\n",
+			((startup_locality_event_t *)ptr)->signature);
+		LOG_EVENT("  StartupLocality    : %u\n",
+			((startup_locality_event_t *)ptr)->startup_locality);
+	} else {
+		LOG_EVENT("  Event              : %s\n", (uint8_t *)ptr);
+	}
+
+	*log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
+	*log_addr = (uint8_t *)ptr + event_size;
+
+	return 0;
+}
+
+int event_log_dump(uint8_t *log_addr, size_t log_size)
+{
+	int rc;
+
+	if (log_addr == NULL) {
+		return -EINVAL;
+	}
+
+	/* Print TCG_EfiSpecIDEvent */
+	rc = event_log_print_id_event(&log_addr, &log_size);
+
+	if (rc < 0) {
+		return rc;
+	}
+
+	while (log_size != 0U) {
+		rc = event_log_print_pcr_event2(&log_addr, &log_size);
+		if (rc < 0) {
+			return rc;
+		}
+	}
+	return 0;
+}
diff --git a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
index c643475..770a1bd 100644
--- a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
+++ b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
@@ -130,6 +130,9 @@
 	msr	ttbr0_el2, x3
 	msr	tcr_el2, x4
 	msr	vbar_el2, x5
+
+	/* make sure whatever just got turned on is in effect */
+	isb
         /*
 	 * Check if the processor supports SME
 	 */
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index c83b0b3..13ff6ff 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -8,13 +8,63 @@
 
 #include <transfer_list.h>
 
+/*******************************************************************************
+ * Search for an existing transfer entry with the specified tag id from a
+ * transfer list
+ * Return pointer to the found transfer entry or NULL on error
+ ******************************************************************************/
 struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
 					       uint16_t tag_id)
 {
-	struct transfer_list_entry *te = (void *)tl + tl->hdr_size;
+	struct transfer_list_entry *te = NULL;
 
-	while (te->tag_id != tag_id) {
-		te += round_up(te->hdr_size + te->data_size, tl->alignment);
+	do {
+		te = transfer_list_next(tl, te);
+	} while (te && (te->tag_id != tag_id));
+
+	return te;
+}
+
+/*******************************************************************************
+ * Enumerate the next transfer entry
+ * Return pointer to the next transfer entry or NULL on error
+ ******************************************************************************/
+struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl,
+					       struct transfer_list_entry *last)
+{
+	struct transfer_list_entry *te = NULL;
+	uintptr_t tl_ev = 0;
+	uintptr_t va = 0;
+	uintptr_t ev = 0;
+	size_t sz = 0;
+
+	if (!tl) {
+		return NULL;
+	}
+
+	tl_ev = (uintptr_t)tl + tl->size;
+
+	if (last) {
+		va = (uintptr_t)last;
+		/* check if the total size overflow */
+		if (add_overflow(last->hdr_size, last->data_size, &sz)) {
+			return NULL;
+		}
+		/* roundup to the next entry */
+		if (add_with_round_up_overflow(va, sz, TRANSFER_LIST_GRANULE,
+					       &va)) {
+			return NULL;
+		}
+	} else {
+		va = (uintptr_t)tl + tl->hdr_size;
+	}
+
+	te = (struct transfer_list_entry *)va;
+
+	if (va + sizeof(*te) > tl_ev || te->hdr_size < sizeof(*te) ||
+	    add_overflow(te->hdr_size, te->data_size, &sz) ||
+	    add_overflow(va, sz, &ev) || ev > tl_ev) {
+		return NULL;
 	}
 
 	return te;
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 3a7f8bf..337c6a6 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -59,3 +59,10 @@
 # This flag is required to match the feature set of Cactus SP that are
 # implemented in TF-A EL3 SPMC.
 SPMC_AT_EL3		:= 0
+
+# If a Cactus SP subscribes to receiving power management framework message
+# through its partition manifest, this flag controls whether the SP supports
+# handling the aforementioned message. This option can take either 0
+# (unsupported) or 1 (supported). Default value is 1. Note that a value of 0 is
+# particularly useful in stress testing of power management handling by the SPMC.
+CACTUS_PWR_MGMT_SUPPORT	:= 1
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index 61392a7..89a8cde 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2024-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,7 +12,7 @@
 #define PLATFORM_LINKER_FORMAT			"elf64-littleaarch64"
 #define PLATFORM_LINKER_ARCH			aarch64
 
-#define TFTF_BASE				U(0x8000000)
+#define TFTF_BASE				U(0x40000000)
 
 #define CACHE_WRITEBACK_GRANULE			U(0x40)
 
@@ -77,13 +77,14 @@
 
 /* ARM PL011 UART */
 #define PL011_UART0_BASE			U(0xf1920000)
+#define PL011_UART1_BASE			U(0xf1930000)
 #define PL011_BAUDRATE				U(115200)
 #define PL011_UART_CLK_IN_HZ			U(100000000)
 
-#define PLAT_ARM_UART_BASE                      PL011_UART0_BASE
+#define PLAT_ARM_UART_BASE                      PL011_UART1_BASE
 #define PLAT_ARM_UART_SIZE                      U(0x1000)
 
-#define CRASH_CONSOLE_BASE			PL011_UART0_BASE
+#define CRASH_CONSOLE_BASE			PL011_UART1_BASE
 #define CRASH_CONSOLE_SIZE			PLAT_ARM_UART_SIZE
 
 /*******************************************************************************
diff --git a/plat/amd/versal2/tests_to_skip.txt b/plat/amd/versal2/tests_to_skip.txt
index 2c286ec..3179879 100644
--- a/plat/amd/versal2/tests_to_skip.txt
+++ b/plat/amd/versal2/tests_to_skip.txt
@@ -33,6 +33,7 @@
 SIMD,SVE Registers context/Check that SIMD registers context is preserved
 FF-A Interrupt
 FF-A Notifications
+FF-A Group0 interrupts/FF-A Group0 normal world
 
 #TESTS: AMD-Xilinx tests
 AMD-Xilinx tests
@@ -47,10 +48,12 @@
 PSCI CPU Suspend/CPU suspend to standby at level 2
 PSCI CPU Suspend in OSI mode/CPU suspend to powerdown at level 0 in OSI mode
 PSCI CPU Suspend in OSI mode/CPU suspend to powerdown at level 1 in OSI mode
+CPU Hotplug/Invalid entry point
 PSCI System Suspend Validation/System suspend multiple times
 PSCI System Suspend Validation/system suspend from all cores
 PSCI System Suspend Validation/Validate suspend to RAM functionality
 PSCI System Suspend Validation/Validate PSCI System Suspend API
+PSCI System Suspend Validation/Suspend system with cores in suspend
 
 #PSCI
 PSCI Features
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_def1.h
deleted file mode 100644
index 2668c62..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_def1.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the CSS specific memory and interrupt map
- * definitions for the first generation platforms based on the A75, N1 and V1
- * CPUs. There are minor differences in the memory map of these platforms and
- * those differences are not in the scope of this file.
- */
-
-#ifndef NRD_CSS_DEF1_H
-#define NRD_CSS_DEF1_H
-
-/*******************************************************************************
- * CSS memory map related defines
- ******************************************************************************/
-
-/* Sub-system Peripherals */
-#define NRD_CSS_PERIPH0_BASE		UL(0x2A000000)
-#define NRD_CSS_PERIPH0_SIZE		UL(0x26000000)
-
-/* Peripherals and PCIe expansion area */
-#define NRD_CSS_PERIPH1_BASE		UL(0x60000000)
-#define NRD_CSS_PERIPH1_SIZE		UL(0x20000000)
-
-/* DRAM base address and size */
-#define NRD_CSS_DRAM1_BASE		UL(0x80000000)
-#define NRD_CSS_DRAM1_SIZE		UL(0x80000000)
-
-/* AP Non-Secure UART related constants */
-#define NRD_CSS_NSEC_UART_BASE		UL(0x2A400000)
-
-/* Base address of trusted watchdog */
-#define NRD_CSS_TWDOG_BASE		UL(0x2A480000)
-
-/* Base address of non-trusted watchdog */
-#define NRD_CSS_WDOG_BASE		UL(0x1C0F0000)
-
-/* Memory mapped Generic timer interfaces */
-#define NRD_CSS_NSEC_CNT_BASE1			UL(0x2A830000)
-
-#endif /* NRD_CSS_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_fw_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_fw_def1.h
deleted file mode 100644
index 55356e6..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_fw_def1.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the CSS firmware specific definitions for
- * the first generation platforms based on the A75, N1 and V1 CPUs.
- */
-
-#ifndef NRD1_CSS_FW_DEF1_H
-#define NRD1_CSS_FW_DEF1_H
-
-#include "nrd_css_def1.h"
-
-/*******************************************************************************
- * Console config
- ******************************************************************************/
-
-#define NRD_CSS_NSEC_CLK_IN_HZ		UL(7372800)
-
-#endif /* NRD_CSS_FW_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_plat_arm_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_plat_arm_def1.h
deleted file mode 100644
index 6a5085f..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_plat_arm_def1.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the platform port definitions for the
- * first generation platforms based on the A75, N1 and V1 CPUs.
- */
-
-#ifndef NRD_PLAT_ARM_DEF1_H
-#define NRD_PLAT_ARM_DEF1_H
-
-#ifndef __ASSEMBLER__
-#include <lib/mmio.h>
-#endif /* __ASSEMBLER__ */
-
-#include <lib/utils_def.h>
-#include "nrd_css_fw_def1.h"
-#include "nrd_ros_def1.h"
-
-/*******************************************************************************
- * Linker related definitions
- ******************************************************************************/
-
-/* Platform binary types for linking */
-#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
-#define PLATFORM_LINKER_ARCH		aarch64
-
-/*******************************************************************************
- * Stack size
- ******************************************************************************/
-
-/* Size of cacheable stacks */
-#define PLATFORM_STACK_SIZE		U(0x1400) /* 5120 bytes */
-
-/* Size of coherent stacks */
-#define PCPU_DV_MEM_STACK_SIZE		U(0x600) /* 1536 bytes */
-
-/*******************************************************************************
- * Core count
- ******************************************************************************/
-
-#define PLATFORM_CORE_COUNT		(PLAT_ARM_CLUSTER_COUNT * \
-						NRD_MAX_CPUS_PER_CLUSTER)
-#define PLATFORM_NUM_AFFS		(PLAT_ARM_CLUSTER_COUNT + \
-						PLATFORM_CORE_COUNT)
-
-/*******************************************************************************
- * Power related definitions
- ******************************************************************************/
-
-#define PLATFORM_MAX_AFFLVL		MPIDR_AFFLVL1
-
-#define PLAT_MAX_PWR_LEVEL		PLATFORM_MAX_AFFLVL
-#define PLAT_MAX_PWR_STATES_PER_LVL	U(2)
-
-/* Local state bit width for each level in the state-ID field of power state */
-#define PLAT_LOCAL_PSTATE_WIDTH		U(4)
-
-/*******************************************************************************
- * XLAT definitions
- ******************************************************************************/
-
-/* Platform specific page table and MMU setup constants */
-#define MAX_XLAT_TABLES			U(6)
-#define MAX_MMAP_REGIONS		U(16)
-
-/*******************************************************************************
- * I/O definitions
- ******************************************************************************/
-
-/* I/O Storage NOR flash device */
-#define MAX_IO_DEVICES			U(1)
-#define MAX_IO_HANDLES			U(1)
-
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-
-/* Non-Secure Software Generated Interupts IDs */
-#define IRQ_NS_SGI_0			U(0)
-#define IRQ_NS_SGI_7			U(7)
-
-/* Maximum SPI */
-#define PLAT_MAX_SPI_OFFSET_ID	U(64)
-
-/*******************************************************************************
- * Timer related config
- ******************************************************************************/
-
-/* Per-CPU Hypervisor Timer Interrupt ID */
-#define IRQ_PCPU_HP_TIMER		U(26)
-
-/* Memory mapped Generic timer interfaces */
-#define SYS_CNT_BASE1			NRD_CSS_NSEC_CNT_BASE1
-
-/* AP_REFCLK Generic Timer, Non-secure. */
-#define IRQ_CNTPSIRQ1			U(92)
-
-/* Times(in ms) used by test code for completion of different events */
-#define PLAT_SUSPEND_ENTRY_TIME		U(15)
-#define PLAT_SUSPEND_ENTRY_EXIT_TIME	U(30)
-
-/*******************************************************************************
- * Console config
- ******************************************************************************/
-
-#define PLAT_ARM_UART_BASE		NRD_CSS_NSEC_UART_BASE
-#define PLAT_ARM_UART_CLK_IN_HZ		NRD_CSS_NSEC_CLK_IN_HZ
-
-/*******************************************************************************
- * DRAM config
- ******************************************************************************/
-
-/* TF-A reserves DRAM space 0xFF000000- 0xFFFFFFFF for TZC */
-#define DRAM_BASE			NRD_CSS_DRAM1_BASE
-#define DRAM_SIZE			(NRD_CSS_DRAM1_SIZE - 0x1000000)
-
-/*******************************************************************************
- * Cache related config
- ******************************************************************************/
-
-#define CACHE_WRITEBACK_SHIFT		U(6)
-#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
-
-/*******************************************************************************
- * Run-time address of the TFTF image.
- * It has to match the location where the Trusted Firmware-A loads the BL33
- * image.
- ******************************************************************************/
-
-#define TFTF_BASE			UL(0xE0000000)
-
-/*******************************************************************************
- * TFTF NVM configs
- ******************************************************************************/
-
-#define TFTF_NVM_OFFSET			U(0x0)
-#define TFTF_NVM_SIZE			UL(0x08000000)	/* 128 MB */
-
-/*******************************************************************************
- * Watchdog related config
- ******************************************************************************/
-
-/* Base address of trusted watchdog (SP805) */
-#define SP805_TWDOG_BASE		NRD_CSS_TWDOG_BASE
-
-/* Base address of non-trusted watchdog (SP805) */
-#define SP805_WDOG_BASE		NRD_CSS_WDOG_BASE
-
-/* Trusted watchdog (SP805) Interrupt ID */
-#define IRQ_TWDOG_INTID			U(86)
-
-/*******************************************************************************
- * Flash related config
- ******************************************************************************/
-
-/* Base address and size of external NVM flash */
-#define FLASH_BASE			NRD_ROS_FLASH_BASE
-#define FLASH_SIZE			NRD_ROS_FLASH_SIZE
-#define NOR_FLASH_BLOCK_SIZE		UL(0x40000)     /* 256KB */
-
-#endif /* NRD_PLAT_ARM_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_ros_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_ros_def1.h
deleted file mode 100644
index 3c1764b..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_ros_def1.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the RoS specific definitions for the first
- * generation platforms based on the A75, N1 and V1 CPUs. RoS (Rest Of System)
- * is used to refer to the part of the reference design platform that excludes
- * CSS.
- */
-
-#ifndef NRD_ROS_DEF1_H
-#define NRD_ROS_DEF1_H
-
-/*******************************************************************************
- * ROS configs
- ******************************************************************************/
-
-/* Base address and size of external NVM flash */
-#define NRD_ROS_FLASH_BASE			UL(0x08000000)  /* 128MB */
-#define NRD_ROS_FLASH_SIZE			UL(0x04000000)  /* 64MB */
-
-#endif /* NRD_ROS_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/include/platform_def.h b/plat/arm/neoverse_rd/platform/rdn1edge/include/platform_def.h
deleted file mode 100644
index 544e7b8..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/include/platform_def.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
-
-#include <nrd1/nrd_plat_arm_def1.h>
-
-#define PLAT_ARM_CLUSTER_COUNT		U(2)
-#define NRD_MAX_CPUS_PER_CLUSTER	U(4)
-#define NRD_MAX_PE_PER_CPU		U(1)
-
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE		UL(0x30000000)
-#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
-#define PLAT_ARM_GICR_BASE		UL(0x300C0000)
-
-/* Platform specific page table and MMU setup constants */
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
-
-#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/platform.mk b/plat/arm/neoverse_rd/platform/rdn1edge/platform.mk
deleted file mode 100644
index 9f92efd..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/platform.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include plat/arm/neoverse_rd/common/nrd_common.mk
-
-PLAT_INCLUDES		+=	-Iplat/arm/neoverse_rd/platform/rdn1edge/include/
-
-PLAT_SOURCES		+=	plat/arm/neoverse_rd/platform/rdn1edge/topology.c
-
-PLAT_TESTS_SKIP_LIST	:=	plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt
-
-ifdef NRD_PLATFORM_VARIANT
-$(error "NRD_PLATFORM_VARIANT should not be set for RD-N1-Edge, \
-    currently set to ${NRD_PLATFORM_VARIANT}.")
-endif
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt
deleted file mode 100644
index 6341809..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS-initiated mode is not supported on RD-N1Edge
-PSCI CPU Suspend in OSI mode
-
-# System suspend is not supported as there are no wakeup sources in RD-N1Edge FVP
-PSCI STAT/Stats test cases after system suspend
-PSCI System Suspend Validation
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/topology.c b/plat/arm/neoverse_rd/platform/rdn1edge/topology.c
deleted file mode 100644
index cb79ba6..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/topology.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <plat_topology.h>
-#include <tftf_lib.h>
-
-static const struct {
-	unsigned int cluster_id;
-	unsigned int cpu_id;
-} plat_cores[] = {
-	/* Cluster0: 4 cores*/
-	{ 0, 0 },
-	{ 0, 1 },
-	{ 0, 2 },
-	{ 0, 3 },
-	/* Cluster1: 4 cores */
-	{ 1, 0 },
-	{ 1, 1 },
-	{ 1, 2 },
-	{ 1, 3 },
-};
-
-/*
- * The power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr().
- */
-const unsigned char plat_pd_tree_desc[] = {
-	/* Number of root nodes */
-	PLAT_ARM_CLUSTER_COUNT,
-	/* Number of children for the 1st node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 2nd node */
-	NRD_MAX_CPUS_PER_CLUSTER
-};
-
-const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
-{
-	return plat_pd_tree_desc;
-}
-
-uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
-{
-	unsigned int mpid;
-
-	assert(core_pos < PLATFORM_CORE_COUNT);
-
-	mpid = make_mpid(
-			plat_cores[core_pos].cluster_id,
-			plat_cores[core_pos].cpu_id);
-
-	return mpid;
-}
diff --git a/plat/arm/neoverse_rd/platform/rdv1/include/platform_def.h b/plat/arm/neoverse_rd/platform/rdv1/include/platform_def.h
deleted file mode 100644
index de94ac9..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/include/platform_def.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
-
-#include <nrd1/nrd_plat_arm_def1.h>
-
-#define PLAT_ARM_CLUSTER_COUNT		U(16)
-#define NRD_MAX_CPUS_PER_CLUSTER	U(1)
-#define NRD_MAX_PE_PER_CPU		U(1)
-
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE		UL(0x30000000)
-#define PLAT_ARM_GICR_BASE		UL(0x30140000)
-#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
-
-/* Platform specific page table and MMU setup constants */
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 42)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 42)
-
-#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/neoverse_rd/platform/rdv1/platform.mk b/plat/arm/neoverse_rd/platform/rdv1/platform.mk
deleted file mode 100644
index cfb8543..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/platform.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include plat/arm/neoverse_rd/common/nrd_common.mk
-
-PLAT_INCLUDES		+=	-Iplat/arm/neoverse_rd/platform/rdv1/include/
-
-PLAT_SOURCES		+=	plat/arm/neoverse_rd/platform/rdv1/topology.c
-
-PLAT_TESTS_SKIP_LIST	:=	plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt
-
-ifdef NRD_PLATFORM_VARIANT
-$(error "NRD_PLATFORM_VARIANT should not be set for RD-V1, \
-    currently set to ${NRD_PLATFORM_VARIANT}.")
-endif
diff --git a/plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt
deleted file mode 100644
index d62b9dd..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS-initiated mode is not supported on RD-V1
-PSCI CPU Suspend in OSI mode
-
-# System suspend is not supported as there are no wakeup sources in RD-V1 FVP
-PSCI STAT/Stats test cases after system suspend
-PSCI System Suspend Validation
-
-# The following tests hang during the test execution
-Timer framework Validation/Stress test the timer framework
-PSCI Affinity Info/Affinity info level0 powerdown
-PSCI CPU Suspend/CPU suspend to powerdown at level 0
-PSCI CPU Suspend/CPU suspend to powerdown at level 1
-
-# The following tests are not supported on RD-V1
-CPU extensions/Use trace buffer control Registers
-CPU extensions/Use trace filter control Registers
diff --git a/plat/arm/neoverse_rd/platform/rdv1/topology.c b/plat/arm/neoverse_rd/platform/rdv1/topology.c
deleted file mode 100644
index 882bffb..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/topology.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <plat_topology.h>
-#include <tftf_lib.h>
-
-static const struct {
-	unsigned int cluster_id;
-	unsigned int cpu_id;
-} plat_cores[] = {
-	/* Cluster0: 1 core */
-	{ 0, 0 },
-	/* Cluster1: 1 core */
-	{ 1, 0 },
-	/* Cluster2: 1 core */
-	{ 2, 0 },
-	/* Cluster3: 1 core */
-	{ 3, 0 },
-	/* Cluster4: 1 core */
-	{ 4, 0 },
-	/* Cluster5: 1 core */
-	{ 5, 0 },
-	/* Cluster6: 1 core */
-	{ 6, 0 },
-	/* Cluster7: 1 core */
-	{ 7, 0 },
-	/* Cluster8: 1 core */
-	{ 8, 0 },
-	/* Cluster9: 1 core */
-	{ 9, 0 },
-	/* Cluster10: 1 core */
-	{ 10, 0 },
-	/* Cluster11: 1 core */
-	{ 11, 0 },
-	/* Cluster12: 1 core */
-	{ 12, 0 },
-	/* Cluster13: 1 core */
-	{ 13, 0 },
-	/* Cluster14: 1 core */
-	{ 14, 0 },
-	/* Cluster15: 1 core */
-	{ 15, 0 },
-};
-
-/*
- * The power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr().
- */
-const unsigned char plat_pd_tree_desc[] = {
-	/* Number of root nodes */
-	PLAT_ARM_CLUSTER_COUNT,
-	/* Number of children for the 1st node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 2nd node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 3rd node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 4th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 5th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 6th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 7th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 8th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 9th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 10th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 11th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 12th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 13th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 14th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 15th node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 16th node */
-	NRD_MAX_CPUS_PER_CLUSTER
-};
-
-const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
-{
-	return plat_pd_tree_desc;
-}
-
-uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
-{
-	unsigned int mpid;
-
-	assert(core_pos < PLATFORM_CORE_COUNT);
-
-	mpid = make_mpid(plat_cores[core_pos].cluster_id,
-				plat_cores[core_pos].cpu_id);
-
-	return (uint64_t)mpid;
-}
diff --git a/plat/arm/neoverse_rd/platform/sgi575/include/platform_def.h b/plat/arm/neoverse_rd/platform/sgi575/include/platform_def.h
deleted file mode 100644
index e8a4606..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/include/platform_def.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
-
-#include <nrd1/nrd_plat_arm_def1.h>
-
-#define PLAT_ARM_CLUSTER_COUNT		U(2)
-#define NRD_MAX_CPUS_PER_CLUSTER	U(4)
-#define NRD_MAX_PE_PER_CPU		U(1)
-
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE		UL(0x30000000)
-#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
-#define PLAT_ARM_GICR_BASE		UL(0x300C0000)
-
-/* Platform specific page table and MMU setup constants */
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
-
-#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/neoverse_rd/platform/sgi575/platform.mk b/plat/arm/neoverse_rd/platform/sgi575/platform.mk
deleted file mode 100644
index 5e81be5..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/platform.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include plat/arm/neoverse_rd/common/nrd_common.mk
-
-PLAT_INCLUDES		+=	-Iplat/arm/neoverse_rd/platform/sgi575/include/
-
-PLAT_SOURCES		+=	plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c
-
-PLAT_TESTS_SKIP_LIST	:=	plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt
-
-ifdef NRD_PLATFORM_VARIANT
-$(error "NRD_PLATFORM_VARIANT should not be set for SGI-575, \
-    currently set to ${NRD_PLATFORM_VARIANT}.")
-endif
diff --git a/plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c b/plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c
deleted file mode 100644
index f38c197..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <plat_topology.h>
-#include <tftf_lib.h>
-
-static const struct {
-	unsigned int cluster_id;
-	unsigned int cpu_id;
-} sgi575_cores[] = {
-	/* Cluster0: 4 cores*/
-	{ 0, 0 },
-	{ 0, 1 },
-	{ 0, 2 },
-	{ 0, 3 },
-	/* Cluster1: 4 cores */
-	{ 1, 0 },
-	{ 1, 1 },
-	{ 1, 2 },
-	{ 1, 3 },
-};
-
-/*
- * The power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr().
- */
-const unsigned char sgi575_pd_tree_desc[] = {
-	/* Number of root nodes */
-	PLAT_ARM_CLUSTER_COUNT,
-	/* Number of children for the 1st node */
-	NRD_MAX_CPUS_PER_CLUSTER,
-	/* Number of children for the 2nd node */
-	NRD_MAX_CPUS_PER_CLUSTER
-};
-
-const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
-{
-	return sgi575_pd_tree_desc;
-}
-
-uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
-{
-	unsigned int mpid;
-
-	assert(core_pos < PLATFORM_CORE_COUNT);
-
-	mpid = make_mpid(
-			sgi575_cores[core_pos].cluster_id,
-			sgi575_cores[core_pos].cpu_id);
-
-	return mpid;
-}
diff --git a/plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt
deleted file mode 100644
index 8817946..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS-initiated mode is not supported on SGI-575
-PSCI CPU Suspend in OSI mode
-
-# System suspend is not supported as there are no wakeup sources in SGI-575 FVP
-PSCI STAT/Stats test cases after system suspend
-PSCI System Suspend Validation
diff --git a/plat/xilinx/common/timer/timers.c b/plat/xilinx/common/timer/timers.c
index f53cd84..da8467b 100644
--- a/plat/xilinx/common/timer/timers.c
+++ b/plat/xilinx/common/timer/timers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,6 +26,7 @@
 #define TTC_IER_OFFSET			U(0x60) /* Interrupt Enable Reg, RW */
 
 #define TTC_CNT_CNTRL_DISABLE_MASK	BIT(0)
+#define TTC_ISR_INTERVAL_BIT		BIT_32(0)
 
 #define TTC_CLK_SEL_MASK		GENMASK(1, 0)
 
@@ -68,12 +69,22 @@
 
 static int cancel_timer(void)
 {
+	uint32_t status;
+	uint32_t reg;
+
+	status = timer_read_32(TTC_ISR_OFFSET);
+	if (status & TTC_ISR_INTERVAL_BIT) {
+		VERBOSE("Timer Interval Interrupt Event! %x\n", status);
+	} else {
+		INFO("Its not a Timer Interval Interrupt Event %d\n", status);
+	}
 	/* Disable Interrupt */
 	timer_write_32(TTC_IER_OFFSET, 0);
 
 	/* Disable Counter */
-	timer_write_32(TTC_CLK_CNTRL_OFFSET, !CLK_CNTRL_PRESCALE_EN);
-	timer_write_32(TTC_CNT_CNTRL_OFFSET, !CLK_CNTRL_PRESCALE_EN);
+	reg = timer_read_32(TTC_CNT_CNTRL_OFFSET);
+	reg |= TTC_CNT_CNTRL_DISABLE_MASK;
+	timer_write_32(TTC_CNT_CNTRL_OFFSET, reg);
 
 	return RET_SUCCESS;
 }
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
index 92a7ba0..12c5910 100644
--- a/plat/xilinx/versal_net/include/platform_def.h
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -99,7 +99,7 @@
 #define IRQ_NS_SGI_7				7
 
 /* Per-CPU Hypervisor Timer Interrupt ID */
-#define IRQ_PCPU_HP_TIMER			U(29)
+#define IRQ_PCPU_HP_TIMER			U(26)
 /* Datasheet: TIME00 event*/
 #define IRQ_CNTPSIRQ1				U(29)
 
diff --git a/realm/realm_mpam.c b/realm/realm_mpam.c
index 913e451..e38d045 100644
--- a/realm/realm_mpam.c
+++ b/realm/realm_mpam.c
@@ -7,16 +7,27 @@
 #include <arch_helpers.h>
 #include <sync.h>
 #include <realm_helpers.h>
+#include <utils_def.h>
 
 /* Check if Realm gets undefined abort when it access MPAM registers */
 bool test_realm_mpam_undef_abort(void)
 {
+	void (*write_reg[])(u_register_t) = {write_mpam0_el1,
+					     write_mpam1_el1,
+					     write_mpamsm_el1,
+					     write_mpamidr_el1};
+	unsigned int n_access = ARRAY_SIZE(write_reg);
+
 	realm_reset_undef_abort_count();
 
 	/* Install exception handler to catch undefined abort */
 	register_custom_sync_exception_handler(realm_sync_exception_handler);
-	write_mpam0_el1(0UL);
+
+	for (unsigned int i = 0U; i < n_access; i++) {
+		write_reg[i](0UL);
+	}
+
 	unregister_custom_sync_exception_handler();
 
-	return (realm_get_undef_abort_count() != 0UL);
+	return (realm_get_undef_abort_count() == (unsigned long)n_access);
 }
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 58de955..70687f1 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -243,7 +243,7 @@
 		} else {
 			realm_printf("rsi_ipa_state_get failed top=0x%lx",
 					"new_top=0x%lx ripas=%u ret=0x%lx\n",
-					ripas);
+					top, new_top, ripas, ret);
 			return false;
 		}
 	}
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index 7d39221..34565f0 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -100,6 +100,7 @@
 $(eval $(call add_define,CACTUS_DEFINES,PLAT_${PLAT}))
 $(eval $(call add_define,CACTUS_DEFINES,PLAT_XLAT_TABLES_DYNAMIC))
 $(eval $(call add_define,CACTUS_DEFINES,SPMC_AT_EL3))
+$(eval $(call add_define,CACTUS_DEFINES,CACTUS_PWR_MGMT_SUPPORT))
 
 $(CACTUS_DTB) : $(BUILD_PLAT)/cactus $(BUILD_PLAT)/cactus/cactus.elf
 $(CACTUS_DTB) : $(CACTUS_DTS)
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 8554709..4a28862 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -102,6 +102,11 @@
 			continue;
 		}
 
+		if (ffa_is_framework_msg(ffa_ret)) {
+			ffa_ret = cactus_handle_framework_msg(ffa_ret);
+			continue;
+		}
+
 		destination = ffa_dir_msg_dest(ffa_ret);
 		if (destination != vm_id) {
 			ERROR("%s(%u) invalid vm id 0x%x\n",
diff --git a/spm/cactus/cactus_tests/cactus_message_loop.c b/spm/cactus/cactus_tests/cactus_message_loop.c
index c0abf2b..aba3124 100644
--- a/spm/cactus/cactus_tests/cactus_message_loop.c
+++ b/spm/cactus/cactus_tests/cactus_message_loop.c
@@ -11,7 +11,9 @@
 #include <ffa_helpers.h>
 #include <events.h>
 #include <platform.h>
+#include <sp_helpers.h>
 #include <spm_helpers.h>
+#include <psci.h>
 
 /**
  * Counter of the number of handled requests, for each CPU. The number of
@@ -99,3 +101,87 @@
 				 CACTUS_ERROR_UNHANDLED);
 	return true;
 }
+
+struct ffa_value cactus_handle_framework_msg(struct ffa_value args)
+{
+	ffa_id_t source_id = ffa_dir_msg_source(args);
+	ffa_id_t destination_id = ffa_dir_msg_dest(args);
+	uint32_t status_code;
+
+#if CACTUS_PWR_MGMT_SUPPORT == 1
+	uint32_t framework_msg = ffa_get_framework_msg(args);
+	uint32_t psci_function = args.arg3;
+	struct ffa_value ret;
+
+	/*
+	 * As of now, Cactus supports receiving only PSCI power management
+	 * request as framework message.
+	 */
+	if (framework_msg != FFA_FRAMEWORK_MSG_PSCI_REQ) {
+		ERROR("Unsupported framework message received by SP:%x\n",
+					destination_id);
+		status_code = PSCI_E_DENIED;
+		goto out;
+	}
+
+	/* Cactus only supports receiving CPU_OFF PSCI function as message. */
+	if (psci_function != SMC_PSCI_CPU_OFF) {
+		ERROR("Unsupported PSCI function(%x) received by SP:%x through "
+			"framework message\n", psci_function, destination_id);
+		status_code = PSCI_E_DENIED;
+		goto out;
+	}
+
+	/* Only SPMC can send the PSCI framework message. */
+	if (source_id != SPMC_ID) {
+		ERROR("Framework message source illegal %x\n", source_id);
+		status_code = PSCI_E_DENIED;
+		goto out;
+	}
+
+	status_code = PSCI_E_SUCCESS;
+
+	/*
+	 * FF-A spec states that SPs are prohibited from invoking Direct
+	 * request, FFA_RUN and FFA_YIELD interfaces while handling power
+	 * management framework message. Make the Cactus SP intentionally
+	 * invoke prohibited interfaces and attest that SPMC should deny such
+	 * invocations.
+	 */
+	ret = cactus_success_resp(destination_id, source_id, status_code);
+
+	/* Non-framework direct response must be denied. */
+	EXPECT(ffa_func_id(ret), FFA_ERROR);
+	EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+	ret = cactus_echo_send_cmd(destination_id, SP_ID(4), 0x9999);
+
+	/* Direct request message must be denied. */
+	EXPECT(ffa_func_id(ret), FFA_ERROR);
+	EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+	ret = ffa_run(SP_ID(4), 0);
+
+	/* FFA_RUN invocation must be denied. */
+	EXPECT(ffa_func_id(ret), FFA_ERROR);
+	EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+	ret = ffa_yield();
+
+	/* FFA_YIELD invocation must be denied. */
+	EXPECT(ffa_func_id(ret), FFA_ERROR);
+	EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+	/*
+	 * Return successful status for PSCI power management request through
+	 * direct response Framework message.
+	 */
+	VERBOSE("PSCI power management request handled successfully by SP:%x\n",
+							destination_id);
+out:
+#else
+	status_code = PSCI_E_DENIED;
+#endif
+	return ffa_framework_msg_send_direct_resp(destination_id, source_id,
+				FFA_FRAMEWORK_MSG_PSCI_RESP, status_code);
+}
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
index 0f6c23d..a8130c6 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
@@ -30,6 +30,7 @@
 	messaging-method = <3>; /* Direct messaging only */
 	ns-interrupts-action = <2>; /* Non secure interrupts are signaled. */
 	notification-support; /* Support receipt of notifications. */
+	power-management-messages = <1>; /* Support CPU_OFF power management message. */
 
 	rx_tx-info {
 		compatible = "arm,ffa-manifest-rx_tx-buffer";
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 4d95069..03a7d17 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -30,6 +30,7 @@
 	messaging-method = <7>; /* Indirect Messaging and direct messaging. */
 	ns-interrupts-action = <1>; /* Managed exit is supported */
 	notification-support; /* Support receipt of notifications. */
+	power-management-messages = <1>; /* Support CPU_OFF power management message. */
 
 	/* Boot protocol */
 	gp-register-num = <0>;
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index e7dd720..94576d1 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -83,9 +83,7 @@
 {
 	const struct ffa_features_test *func_id_targets;
 	/* Get common features between tftf and cactus. */
-	unsigned int test_target_size =
-		get_ffa_feature_test_target(&func_id_targets);
-	/* Specific to SPs. */
+	size_t test_target_size = get_ffa_feature_test_target(&func_id_targets);
 	struct ffa_features_test feature_id_targets[] = {
 		{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_SUCCESS_SMC32, 0,
 			FFA_VERSION_1_1},
diff --git a/tftf/framework/aarch32/entrypoint.S b/tftf/framework/aarch32/entrypoint.S
index eaa0788..3e40ab9 100644
--- a/tftf/framework/aarch32/entrypoint.S
+++ b/tftf/framework/aarch32/entrypoint.S
@@ -16,6 +16,12 @@
  * ----------------------------------------------------------------------------
  */
 func tftf_entrypoint
+#if TRANSFER_LIST
+	mov	r4, r0
+	mov	r5, r1
+	mov	r6, r2
+	mov	r7, r3
+#endif
 	bl	arch_init
 
 	/* --------------------------------------------------------------------
@@ -53,6 +59,19 @@
 	bl	zeromem
 
 	/* --------------------------------------------------------------------
+	 * Save transfer list and hw_config addresses passed in registers r0 to
+	 * r3 from the previous bootloader.
+	 * --------------------------------------------------------------------
+	 */
+#if TRANSFER_LIST
+	mov	r0, r4
+	mov	r1, r5
+	mov	r2, r6
+	mov	r3, r7
+	bl	save_handoff_params
+#endif
+
+	/* --------------------------------------------------------------------
 	 * Give ourselves a small coherent stack to ease the pain of
 	 * initializing the MMU
 	 * --------------------------------------------------------------------
@@ -172,3 +191,18 @@
 	/* Primary core MPID already saved */
 	b	panic
 endfunc save_primary_mpid
+
+/* ----------------------------------------------------------------------------
+ * Save transfer list and hw_config addresses passed in registers r0 to r3 from
+ * the previous bootloader.
+ * ----------------------------------------------------------------------------
+ */
+func save_handoff_params
+	ldr	r4, =ns_tl
+	str	r3, [r4]
+	ldr	r4, =tl_signature
+	str	r1, [r4]
+	ldr	r4, =hw_config_base
+	str	r2, [r4]
+	bx	lr
+endfunc save_handoff_params
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index d5d3300..098f2b8 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -55,6 +55,7 @@
 	lib/${ARCH}/misc_helpers.S					\
 	lib/delay/delay.c						\
 	lib/events/events.c						\
+	${EVENT_LOG_SOURCES}						\
 	lib/extensions/amu/${ARCH}/amu.c				\
 	lib/extensions/amu/${ARCH}/amu_helpers.S			\
 	lib/exceptions/irq.c						\
diff --git a/tftf/tests/extensions/pauth/test_pauth.c b/tftf/tests/extensions/pauth/test_pauth.c
index ada2f1d..f964266 100644
--- a/tftf/tests/extensions/pauth/test_pauth.c
+++ b/tftf/tests/extensions/pauth/test_pauth.c
@@ -58,13 +58,10 @@
 	SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();
 
 #if ARM_ARCH_AT_LEAST(8, 3)
+	u_register_t reg = 42;
+
 	/* Pointer authentication instructions */
-	__asm__ volatile (
-		"paciasp\n"
-		"autiasp\n"
-		"paciasp\n"
-		"xpaclri"
-	);
+	__asm__ volatile ("pacdza %0\n" : "+r"(reg));
 	return TEST_RESULT_SUCCESS;
 #else
 	tftf_testcase_printf("Pointer Authentication instructions "
diff --git a/tftf/tests/extensions/ras/test_ras.c b/tftf/tests/extensions/ras/test_ras.c
new file mode 100644
index 0000000..cd27f16
--- /dev/null
+++ b/tftf/tests/extensions/ras/test_ras.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <tftf.h>
+
+/*
+ * FEAT_RAS introduces EL1 system registers to query error records, those
+ * CPU specific parts of the RAS extension can be accessed independently of
+ * any FFH/KFH handling setup or any system specific RAS implementation.
+ * Reading these registers will trap to EL3 and crash when EL3 has not
+ * allowed access, which is controlled by the SCR_EL3.TERR bit.
+ */
+
+test_result_t test_ras_reg_access(void)
+{
+	SKIP_TEST_IF_AARCH32();
+
+#ifdef __aarch64__
+	SKIP_TEST_IF_RAS_NOT_SUPPORTED();
+
+	read_erridr_el1();
+
+	return TEST_RESULT_SUCCESS;
+#endif
+}
diff --git a/tftf/tests/misc_tests/test_firmware_handoff.c b/tftf/tests/misc_tests/test_firmware_handoff.c
index 00cebd3..026f057 100644
--- a/tftf/tests/misc_tests/test_firmware_handoff.c
+++ b/tftf/tests/misc_tests/test_firmware_handoff.c
@@ -6,10 +6,13 @@
 
 #include <assert.h>
 
+#include <drivers/measured_boot/event_log/tcg.h>
 #include <test_helpers.h>
 #include <tftf_lib.h>
 #include <transfer_list.h>
 
+#include "event_log.h"
+
 extern u_register_t hw_config_base;
 extern u_register_t ns_tl;
 extern u_register_t tl_signature;
@@ -20,8 +23,15 @@
 {
 	struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
 
-	assert(tl_signature ==
-		TRANSFER_LIST_HANDOFF_X1_VALUE(TRANSFER_LIST_VERSION));
+#if __aarch64__
+	uint64_t signature = TRANSFER_LIST_HANDOFF_X1_VALUE(TRANSFER_LIST_VERSION);
+#else
+	uint32_t signature = TRANSFER_LIST_HANDOFF_R1_VALUE(TRANSFER_LIST_VERSION);
+#endif /* __aarch64__ */
+
+	if (signature != tl_signature) {
+		return TEST_RESULT_FAIL;
+	}
 
 	if (transfer_list_check_header(tl) == TL_OPS_NON) {
 		return TEST_RESULT_FAIL;
@@ -54,3 +64,31 @@
 
 	return TEST_RESULT_SUCCESS;
 }
+
+test_result_t test_handoff_event_payload(void)
+{
+
+	struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
+	struct transfer_list_entry *te;
+	uint8_t *log_addr;
+	size_t log_size;
+
+	tftf_testcase_printf(
+		"Validate that a TPM event log can be successfully dumped when "
+		"present in the transfer list.");
+
+	te = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+	if (te == NULL) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* 4-bytes are reserved in TE data section. */
+	log_addr = (uint8_t *)transfer_list_entry_data(te) + U(4);
+	log_size = te->data_size - U(4);
+
+	if (event_log_dump(log_addr, log_size) != 0) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/neg_scenario_tests/test_fwu_image_size.c b/tftf/tests/neg_scenario_tests/test_fwu_image_size.c
new file mode 100644
index 0000000..0bf4d29
--- /dev/null
+++ b/tftf/tests/neg_scenario_tests/test_fwu_image_size.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <firmware_image_package.h>
+#include <fwu_nvm.h>
+#include <image_loader.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <smccc.h>
+#include <status.h>
+#include <tftf_lib.h>
+#include <uuid.h>
+#include <uuid_utils.h>
+
+/*
+ * @TEST_AIM@ validate FWU IMAGE SIZE invalid scenario
+ * TEST SUCCESS if FWU FIP IMAGE SIZE is found invalid and Fails to Proceed
+ * TEST FAIL in case FWU process is able to reboot
+ */
+
+static fip_toc_entry_t *
+find_fiptoc_entry_t(const int fip_base, const uuid_t *uuid)
+{
+	fip_toc_entry_t *current_file =
+		(fip_toc_entry_t *) (fip_base + sizeof(fip_toc_header_t));
+
+	while (!is_uuid_null(&(current_file->uuid))) {
+		if (uuid_equal(&(current_file->uuid), uuid))
+			return current_file;
+
+		current_file += 1;
+	};
+	return NULL;
+}
+
+test_result_t test_fwu_image_size(void)
+{
+	STATUS status;
+	int fip_base = PLAT_ARM_FIP_BASE;
+	int fwu_fip_base = PLAT_ARM_FWU_FIP_BASE;
+
+	const uuid_t bl2	= UUID_TRUSTED_BOOT_FIRMWARE_BL2;
+	const uuid_t bl2u	= UUID_FIRMWARE_UPDATE_BL2U;
+
+	fip_toc_entry_t *bl2_entry;
+	fip_toc_entry_t *bl2u_entry;
+
+	uintptr_t bl2_entry_address, bl2u_entry_address;
+
+	int corrupt_size = 0xFFFF;
+	int offset;
+
+	smc_args args = { SMC_PSCI_SYSTEM_RESET };
+	smc_ret_values ret = {0};
+
+	/* retrieve bl2 and bl2u */
+	bl2_entry = find_fiptoc_entry_t(fip_base, &bl2);
+	bl2_entry_address = (uintptr_t)bl2_entry;
+
+	bl2u_entry = find_fiptoc_entry_t(fwu_fip_base, &bl2u);
+	bl2u_entry_address = (intptr_t)bl2u_entry;
+
+	/* Reboot has not occurred yet */
+	tftf_testcase_printf("not rebooted yet\n");
+
+	/* Corrupt FWU_FIP_SIZE */
+	tftf_testcase_printf("bl2_entry_address value is (%lx)\n", bl2_entry_address);
+
+	/*
+	 * corrupt bl2 in fip
+	 * corrupt toc entry size field of bl2u
+	 */
+
+	/* corrupt bl2 image */
+	offset = bl2_entry_address + sizeof(uuid_t) + sizeof(uint64_t) - FLASH_BASE;
+	status = fwu_nvm_write(offset, &corrupt_size, sizeof(uint64_t));
+
+	if (status != STATUS_SUCCESS) {
+		tftf_testcase_printf("staus not success error %d\n", status);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* corrupt toc bl2u entry */
+	offset = bl2u_entry_address + sizeof(uuid_t) + sizeof(uint64_t) - FLASH_BASE;
+	status = fwu_nvm_write(offset, &corrupt_size, sizeof(uint64_t));
+
+	if (status != STATUS_SUCCESS) {
+		tftf_testcase_printf("status not success error %d\n", status);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Notify that we are rebooting now. */
+	tftf_notify_reboot();
+
+	/* Request PSCI system reset. */
+	ret = tftf_smc(&args);
+
+	/* The PSCI SYSTEM_RESET call is not supposed to return */
+	tftf_testcase_printf("System didn't reboot properly (%d)\n",
+						(unsigned int)ret.ret0);
+
+	return TEST_RESULT_FAIL;
+}
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
index 1418ca1..7c7f91b 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
@@ -79,12 +79,13 @@
 	CHECK_BIT_SET(is_feat_tcr2_supported,			SCR_TCR2EN_BIT);
 	CHECK_BIT_SET(is_feat_the_supported,			SCR_RCWMASKEn_BIT);
 	CHECK_BIT_SET(is_feat_sme_supported,			SCR_ENTP2_BIT);
-	CHECK_BIT_SET(is_feat_rng_trap_present,			SCR_TRNDR_BIT);
+	CHECK_BIT_SET(is_feat_rng_present,			SCR_TRNDR_BIT);
 	CHECK_BIT_SET(is_feat_gcs_present,			SCR_GCSEn_BIT);
 	CHECK_BIT_SET(get_feat_hcx_support,			SCR_HXEn_BIT);
 	CHECK_BIT_SET(is_feat_ls64_accdata_present,		SCR_ADEn_BIT);
 	CHECK_BIT_SET(is_feat_ls64_accdata_present,		SCR_EnAS0_BIT);
 	CHECK_BIT_SET(is_feat_amuv1p1_present,			SCR_AMVOFFEN_BIT);
+	CHECK_BIT_SET(is_feat_twed_present,			SCR_TWEDEn_BIT);
 	CHECK_BIT_SET(get_armv8_6_ecv_support,			SCR_ECVEN_BIT);
 	CHECK_BIT_SET(is_armv8_6_fgt_present,			SCR_FGTEN_BIT);
 	CHECK_BIT_SET(is_feat_mte2_present,			SCR_ATA_BIT);
@@ -108,6 +109,7 @@
 	CHECK_BIT_SET(is_feat_trbe_present,			MDCR_NSTB(1));
 	CHECK_BIT_SET(get_armv8_4_trf_support,			MDCR_TTRF_BIT);
 	CHECK_BIT_SET(is_feat_spe_supported,			MDCR_NSPB(1));
+	CHECK_BIT_SET(is_feat_pmuv3p9_present,			MDCR_EnPM2_BIT);
 	CHECK_BIT_SET(is_feat_doublelock_present,		MDCR_TDOSA_BIT);
 	CHECK_BIT_SET(always_present,				MDCR_TDA_BIT);
 	CHECK_BIT_SET(get_feat_pmuv3_supported,			MDCR_TPM_BIT);
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
index c43c374..572bc2a 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
@@ -378,6 +378,10 @@
 
 	/* Allocate granule for PDEV and delegate */
 	tdi->pdev = page_alloc(PAGE_SIZE);
+	if (tdi->pdev == NULL) {
+		return -1;
+	}
+
 	memset(tdi->pdev, 0, GRANULE_SIZE);
 	ret = host_rmi_granule_delegate((u_register_t)tdi->pdev);
 	if (ret != RMI_SUCCESS) {
@@ -393,48 +397,67 @@
 	ret = host_rmi_pdev_aux_count(tdi->pdev_flags, &count);
 	if (ret != RMI_SUCCESS) {
 		ERROR("host_rmi_pdev_aux_count() failed 0x%lx\n", ret);
-		return -1;
+		goto err_undelegate_pdev;
 	}
 	tdi->pdev_aux_num = count;
 
 	/* Allocate aux granules for PDEV and delegate */
 	INFO("PDEV create requires %u aux pages\n", tdi->pdev_aux_num);
 	for (i = 0; i < tdi->pdev_aux_num; i++) {
-		tdi->pdev_aux[i] = page_alloc(PAGE_SIZE);
-		ret = host_rmi_granule_delegate((u_register_t)tdi->pdev_aux[i]);
+		void *pdev_aux = page_alloc(PAGE_SIZE);
+
+		if (pdev_aux == NULL) {
+			goto err_undelegate_pdev_aux;
+		}
+
+		ret = host_rmi_granule_delegate((u_register_t)pdev_aux);
 		if (ret != RMI_SUCCESS) {
 			ERROR("Aux granule delegate failed 0x%lx\n", ret);
-			return -1;
+			goto err_undelegate_pdev_aux;
 		}
+
+		tdi->pdev_aux[i] = pdev_aux;
 	}
 
 	/* Allocate dev_comm_data and send/recv buffer for Dev communication */
 	tdi->dev_comm_data = (struct rmi_dev_comm_data *)page_alloc(PAGE_SIZE);
+	if (tdi->dev_comm_data == NULL) {
+		goto err_undelegate_pdev_aux;
+	}
+
 	memset(tdi->dev_comm_data, 0, sizeof(struct rmi_dev_comm_data));
+
 	tdi->dev_comm_data->enter.req_addr = (unsigned long)
 		page_alloc(PAGE_SIZE);
+	if (tdi->dev_comm_data->enter.req_addr == 0UL) {
+		goto err_undelegate_pdev_aux;
+	}
+
 	tdi->dev_comm_data->enter.resp_addr = (unsigned long)
 		page_alloc(PAGE_SIZE);
+	if (tdi->dev_comm_data->enter.resp_addr == 0UL) {
+		goto err_undelegate_pdev_aux;
+	}
 
 	/* Allocate buffer to cache device certificate */
 	tdi->cert_slot_id = 0;
 	tdi->cert_chain = (uint8_t *)page_alloc(HOST_PDEV_CERT_LEN_MAX);
 	tdi->cert_chain_len = 0;
 	if (tdi->cert_chain == NULL) {
-		return -1;
+		goto err_undelegate_pdev_aux;
 	}
 
 	/* Allocate buffer to store extracted public key */
 	tdi->public_key = (void *)page_alloc(PAGE_SIZE);
 	if (tdi->public_key == NULL) {
-		return -1;
+		goto err_undelegate_pdev_aux;
 	}
 	tdi->public_key_len = PAGE_SIZE;
 
 	/* Allocate buffer to store public key metadata */
 	tdi->public_key_metadata = (void *)page_alloc(PAGE_SIZE);
 	if (tdi->public_key_metadata == NULL) {
-		return -1;
+		goto err_undelegate_pdev_aux;
 	}
 	tdi->public_key_metadata_len = PAGE_SIZE;
 
@@ -442,13 +465,27 @@
 	tdi->meas = (uint8_t *)page_alloc(HOST_PDEV_MEAS_LEN_MAX);
 	tdi->meas_len = 0;
 	if (tdi->meas == NULL) {
-		return -1;
+		goto err_undelegate_pdev_aux;
 	}
 
 	/* Set algorithm to use for device digests */
 	tdi->pdev_hash_algo = RMI_HASH_SHA_512;
 
 	return 0;
+
+err_undelegate_pdev_aux:
+	/* Undelegate all the delegated pages */
+	for (int i = 0; i < tdi->pdev_aux_num; i++) {
+		if (tdi->pdev_aux[i]) {
+			host_rmi_granule_undelegate((u_register_t)
+						    tdi->pdev_aux[i]);
+		}
+	}
+
+err_undelegate_pdev:
+	host_rmi_granule_undelegate((u_register_t)tdi->pdev);
+
+	return -1;
 }
 
 /*
@@ -578,3 +615,41 @@
 
 	return TEST_RESULT_SUCCESS;
 }
+
+
+/*
+ * This function invokes PDEV_CREATE on TRP and tries to test
+ * the EL3 RMM-EL3 IDE KM interface. Will be skipped on TF-RMM.
+ */
+test_result_t host_realm_test_root_port_key_management(void)
+{
+	struct host_tdi *tdi;
+	int ret;
+
+	if (host_rmi_version(RMI_ABI_VERSION_VAL) != 0U) {
+		tftf_testcase_printf("RMM is not TRP\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* Initialize Host NS heap memory */
+	ret = page_pool_init((u_register_t)PAGE_POOL_BASE,
+				(u_register_t)PAGE_POOL_MAX_SIZE);
+	if (ret != HEAP_INIT_SUCCESS) {
+		ERROR("Failed to init heap pool %d\n", ret);
+		return TEST_RESULT_FAIL;
+	}
+
+	tdi = &g_tdi;
+
+	/*
+	 * Call rmi_pdev_create with invalid pdev, expect an error
+	 * to be returned from TRP.
+	 */
+	ret = host_tdi_pdev_create(tdi);
+	if (ret != 0) {
+		return TEST_RESULT_SUCCESS;
+	}
+
+	ERROR("RMI_PDEV_CREATE did not return error as expected\n");
+	return TEST_RESULT_FAIL;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c
index 9f6246b..3816422 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c
@@ -30,6 +30,11 @@
 	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 	SKIP_TEST_IF_BRBE_NOT_SUPPORTED();
 
+	if (is_feat_52b_on_4k_2_supported()) {
+		feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+		sl = RTT_MIN_LEVEL_LPA2;
+	}
+
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
 						feature_flag, feature_flag1, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
index 023ec1c..1c2f58e 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
@@ -147,9 +147,16 @@
 	sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
 
 	/*
-	 * Pass a sve_vq that is greater than the value supported by RMM
-	 * and check whether creating Realm fails
+	 * TODO: The TFTF framework packs the sve_vl to feature flag for which the max value
+	 * is 15 and then unpacks it to rmi_realm_params. Hence the value is clipped to 4 bits
+	 * and hence it is not possible for test to send a value higher than this. Refactor
+	 * this part of TFTF and then remove this limitation.
 	 */
+	if (sve_vq == SVE_VQ_ARCH_MAX) {
+		INFO("RMI supports arch max SVE VL %u, skipping\n", (sve_vq + 1));
+		return TEST_RESULT_SKIPPED;
+	}
+
 	rc = host_create_sve_realm_payload(&realm, true, (sve_vq + 1));
 	if (rc == TEST_RESULT_SUCCESS) {
 		ERROR("Error: Realm created with invalid SVE VL %u\n", (sve_vq + 1));
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index 51dc94b..2478d4f 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -2724,7 +2724,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 3L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
@@ -2732,7 +2732,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_UNASSIGNED
 			|| (rtt.ripas != RMI_EMPTY)) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -2743,7 +2743,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 2L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
@@ -2751,7 +2751,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 1L || rtt.state != RMI_UNASSIGNED
 			|| (rtt.ripas != RMI_EMPTY)) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -2762,7 +2762,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 1L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
@@ -2770,7 +2770,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 0L || rtt.state != RMI_UNASSIGNED
 			|| (rtt.ripas != RMI_EMPTY)) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -2900,7 +2900,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 3L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
@@ -2908,7 +2908,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_UNASSIGNED
 			|| (rtt.ripas != RMI_RAM)) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -2919,7 +2919,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 2L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
@@ -2927,7 +2927,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 1L || rtt.state != RMI_UNASSIGNED
 			|| (rtt.ripas != RMI_RAM)) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -2938,7 +2938,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 1L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
@@ -2946,7 +2946,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 0L || rtt.state != RMI_UNASSIGNED
 			|| (rtt.ripas != RMI_RAM)) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -3066,14 +3066,14 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, ns_ipa, 2L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto destroy_realm;
 	}
 
 	/* Walk should terminate at L1 */
 	ret = host_rmi_rtt_readentry(realm.rd, ns_ipa, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 1L || rtt.state != RMI_ASSIGNED) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto destroy_realm;
@@ -3160,7 +3160,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 3U);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto undelegate_destroy;
 	}
 
@@ -3168,7 +3168,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_ASSIGNED ||
 			rtt.ripas != RMI_EMPTY) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 				" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr);
 		goto undelegate_destroy;
@@ -3276,7 +3276,7 @@
 	/* RTT Fold */
 	ret = host_realm_fold_rtt(realm.rd, base, 3L);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+		ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
 		goto undelegate_destroy;
 	}
 
@@ -3284,7 +3284,7 @@
 	ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
 	if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_ASSIGNED ||
 			rtt.ripas != RMI_RAM) {
-		ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+		ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
 			" rtt.walk_level=0x%lx rtt.out_addr=0x%llx ripas=0x%lx\n",
 				ret, rtt.state, rtt.walk_level, rtt.out_addr, rtt.ripas);
 		goto undelegate_destroy;
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index e0388db..3dc7036 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -142,6 +142,29 @@
 	return ffa_service_call(&args);
 }
 
+struct ffa_value ffa_framework_msg_send_direct_resp(ffa_id_t source_id,
+					    ffa_id_t dest_id, uint32_t msg,
+					    uint32_t status_code)
+{
+	struct ffa_value args = {
+		.fid = FFA_MSG_SEND_DIRECT_RESP_SMC32,
+		.arg1 = ((uint32_t)(source_id << 16)) | (dest_id),
+		.arg2 = ((uint32_t)(1 << 31)) | (msg & 0xFF),
+		.arg3 = status_code,
+	};
+
+	return ffa_service_call(&args);
+}
+
+struct ffa_value ffa_yield(void)
+{
+	struct ffa_value args = {
+		.fid = FFA_MSG_YIELD,
+	};
+
+	return ffa_service_call(&args);
+}
+
 void ffa_memory_region_init_header(struct ffa_memory_region *memory_region,
 				   ffa_id_t sender,
 				   ffa_memory_attributes_t attributes,
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 4405c50..029113f 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -210,15 +210,11 @@
  *
  * Returns number of elements in the *test_target.
  */
-unsigned int get_ffa_feature_test_target(
-	const struct ffa_features_test **test_target)
+size_t get_ffa_feature_test_target(const struct ffa_features_test **test_target)
 {
-	if (test_target != NULL) {
-		*test_target = ffa_feature_test_target;
-	}
-
-	return sizeof(ffa_feature_test_target) /
-	       sizeof(struct ffa_features_test);
+	assert(test_target != NULL);
+	*test_target = ffa_feature_test_target;
+	return ARRAY_SIZE(ffa_feature_test_target);
 }
 
 /**
@@ -226,7 +222,7 @@
  * FFA_FEATURES calls.
  */
 bool ffa_features_test_targets(const struct ffa_features_test *targets,
-			       uint32_t test_target_size)
+			       size_t test_target_size)
 {
 	bool ret = true;
 
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
index 5effe53..1586fe6 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
@@ -98,8 +98,7 @@
 			FFA_VERSION_1_1},
 		{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_ERROR},
 	};
-	unsigned int test_target_size =
-		get_ffa_feature_test_target(&func_ids_target);
+	size_t test_target_size = get_ffa_feature_test_target(&func_ids_target);
 
 	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
 
diff --git a/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c b/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
index 98c567d..178516c 100644
--- a/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
+++ b/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
@@ -303,7 +303,7 @@
 		{2008768, 0x00, 0x20, 0x00},
 		{2017096, 0x00, 0x20, 0x00},
 		{2055002, 0x10, 0x20, 0x00},
-		{2058056, 0x00, 0x10, 0x00},
+		{2058056, 0x00, 0x21, 0x00},
 		{2081180, 0x00, 0x20, 0x00},
 		{2083908, 0x20, 0x20, 0x00},
 		{2136059, 0x00, 0x20, 0x00},
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 9358c49..37e41de 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -19,6 +19,7 @@
 	extensions/mte/test_mte.c					\
 	extensions/pauth/test_pauth.c					\
 	extensions/pmuv3/test_pmuv3.c					\
+	extensions/ras/test_ras.c					\
 	extensions/sctlr2/test_sctlr2.c					\
 	extensions/sme/test_sme.c					\
 	extensions/sme/test_sme2.c					\
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 632e231..dd60bc1 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -19,6 +19,7 @@
     <testcase name="Check for Pointer Authentication key leakage from EL3" function="test_pauth_leakage" />
     <testcase name="Check for Pointer Authentication key leakage from TSP" function="test_pauth_leakage_tsp" />
     <testcase name="Access MPAM registers" function="test_mpam_reg_access" />
+    <testcase name="Access RAS registers" function="test_ras_reg_access" />
     <testcase name="Use MTE Instructions" function="test_mte_instructions" />
     <testcase name="Check for MTE register leakage" function="test_mte_leakage" />
     <testcase name="Use FGT Registers" function="test_fgt_enabled" />
diff --git a/tftf/tests/tests-firmware-handoff.mk b/tftf/tests/tests-firmware-handoff.mk
index 515188a..65dfc4b 100644
--- a/tftf/tests/tests-firmware-handoff.mk
+++ b/tftf/tests/tests-firmware-handoff.mk
@@ -6,8 +6,12 @@
 
 ifeq (${TRANSFER_LIST}, 1)
 
+include lib/event_log/event_log.mk
+
 TESTS_SOURCES	+=	$(addprefix tftf/tests/misc_tests/,		\
 	test_firmware_handoff.c						\
 )
 
+TESTS_SOURCES	+=	${EVENT_LOG_SOURCES}
+
 endif
diff --git a/tftf/tests/tests-firmware-handoff.xml b/tftf/tests/tests-firmware-handoff.xml
index 4b4b2a4..9b456cc 100644
--- a/tftf/tests/tests-firmware-handoff.xml
+++ b/tftf/tests/tests-firmware-handoff.xml
@@ -10,5 +10,6 @@
   <testsuite name="Firmware Handoff" description="Validate transfer list managed by firmware handoff framework">
      <testcase name="Validate transfer list header" function="test_handoff_header" />
      <testcase name="Validate HW_CONFIG in transfer list" function="test_handoff_dtb_payload" />
+     <testcase name="Validate event log in transfer list" function="test_handoff_event_payload" />
   </testsuite>
 </testsuites>
diff --git a/tftf/tests/tests-neg_scenario.mk b/tftf/tests/tests-neg_scenario.mk
new file mode 100644
index 0000000..38093e6
--- /dev/null
+++ b/tftf/tests/tests-neg_scenario.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=	$(addprefix tftf/tests/neg_scenario_tests/,	\
+				test_fwu_image_size.c \
+)
+
+TESTS_SOURCES	+=	plat/common/fwu_nvm_accessors.c \
+				plat/common/image_loader.c \
+				plat/arm/common/arm_fwu_io_storage.c
diff --git a/tftf/tests/tests-neg_scenario.xml b/tftf/tests/tests-neg_scenario.xml
new file mode 100644
index 0000000..bfec31c
--- /dev/null
+++ b/tftf/tests/tests-neg_scenario.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2025, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+  <testsuite name="neg scenario test" description="Validate firmware update failure in a scenario where BL2 is corrupted, triggering a firmware update that fails due to a BL2U size corruption.">
+     <testcase name="FWU imageSize Failure" function="test_fwu_image_size" />
+  </testsuite>
+
+</testsuites>
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 875c793..b9e83fe 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -158,5 +158,8 @@
 	  <!-- Test case related to FEAT_BRBE -->
 	  <testcase name="Test if BRBE realted registers are preserved "
 	  function="host_realm_test_brbe_save_restore" />
+	 <!-- Test case for EL3-RMM IDE KM Interface -->
+	  <testcase name="Test for Root Port Key management interface"
+	  function="host_realm_test_root_port_key_management" />
   </testsuite>
 </testsuites>