Merge "fix(xilinx): resolve misra rule 8.4 violations" into integration
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..6a89eeb
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,199 @@
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignArrayOfStructures: None
+AlignConsecutiveMacros: None
+AlignConsecutiveAssignments: None
+AlignConsecutiveBitFields: None
+AlignConsecutiveDeclarations: None
+AlignEscapedNewlines: Left
+AlignOperands:   Align
+AlignTrailingComments: false
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortEnumsOnASingleLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+AttributeMacros:
+  - __capability
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+  AfterCaseLabel:  false
+  AfterClass:      false
+  AfterControlStatement: Never
+  AfterEnum:       false
+  AfterFunction:   true
+  AfterNamespace:  true
+  AfterObjCDeclaration: false
+  AfterStruct:     false
+  AfterUnion:      false
+  AfterExternBlock: false
+  BeforeCatch:     false
+  BeforeElse:      false
+  BeforeLambdaBody: false
+  BeforeWhile:     false
+  IndentBraces:    false
+  SplitEmptyFunction: true
+  SplitEmptyRecord: true
+  SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeConceptDeclarations: true
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+QualifierAlignment: Leave
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DeriveLineEnding: true
+DerivePointerAlignment: false
+DisableFormat:   false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+ExperimentalAutoDetectBinPacking: false
+PackConstructorInitializers: BinPack
+BasedOnStyle:    ''
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+AllowAllConstructorInitializersOnNextLine: true
+FixNamespaceComments: false
+ForEachMacros:
+  - fdt_for_each_compatible_node
+  - fdt_for_each_property_offset
+  - fdt_for_each_subnode
+  - for_each_err_record_info
+  - for_each_subscriber
+IfMacros:
+  - KJ_IF_MAYBE
+IncludeBlocks:   Regroup
+IncludeCategories:
+  - Regex:           '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stdckdint|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>$'
+    Priority:        0
+    SortPriority:    0
+    CaseSensitive:   false
+  - Regex:           '^<lib/(compiler-rt|libfdt|mbedtls|zlib)/.+>$'
+    Priority:        1
+    SortPriority:    0
+    CaseSensitive:   false
+  - Regex:           '^<(platform(_def)?\.h)|(plat[_/].+)>$'
+    Priority:        2
+    SortPriority:    0
+    CaseSensitive:   false
+  - Regex:           '^<.+>$'
+    Priority:        3
+    SortPriority:    0
+    CaseSensitive:   false
+  - Regex:           '^".+"$'
+    Priority:        4
+    SortPriority:    0
+    CaseSensitive:   false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseLabels: false
+IndentCaseBlocks: false
+IndentGotoLabels: false
+IndentPPDirectives: None
+IndentExternBlock: AfterExternBlock
+IndentRequires:  false
+IndentWidth:     8
+IndentWrappedFunctionNames: false
+InsertTrailingCommas: None
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+LambdaBodyIndentation: Signature
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 8
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 10
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakString: 10
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+PenaltyIndentedWhitespace: 0
+PointerAlignment: Right
+PPIndentWidth:   -1
+ReferenceAlignment: Pointer
+ReflowComments:  false
+RemoveBracesLLVM: false
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SortIncludes:    CaseInsensitive
+SortJavaStaticImport: Before
+SortUsingDeclarations: false
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatementsExceptControlMacros
+SpaceBeforeParensOptions:
+  AfterControlStatements: true
+  AfterForeachMacros: false
+  AfterFunctionDefinitionName: false
+  AfterFunctionDeclarationName: false
+  AfterIfMacros:   false
+  AfterOverloadedOperator: false
+  BeforeNonEmptyParentheses: false
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  Never
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInLineCommentPrefix:
+  Minimum:         1
+  Maximum:         -1
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+BitFieldColonSpacing: Both
+Standard:        c++03
+StatementAttributeLikeMacros:
+  - Q_EMIT
+StatementMacros:
+  - Q_UNUSED
+  - QT_REQUIRE_VERSION
+TabWidth:        8
+UseCRLF:         false
+UseTab:          Always
+WhitespaceSensitiveMacros:
+  - STRINGIZE
+  - PP_STRINGIZE
+  - BOOST_PP_STRINGIZE
+  - NS_SWIFT_NAME
+  - CF_SWIFT_NAME
+...
diff --git a/Makefile b/Makefile
index aae3452..150aa30 100644
--- a/Makefile
+++ b/Makefile
@@ -148,7 +148,7 @@
 		TF_CFLAGS_aarch64	:=	-target aarch64-arm-none-eabi
 	else
 		TF_CFLAGS_aarch32	=	$(target32-directive)
-		TF_CFLAGS_aarch64	:=	-target aarch64-elf
+		TF_CFLAGS_aarch64	:=	-target aarch64-unknown-none-elf
 	endif
 
 else ifeq ($($(ARCH)-cc-id),gnu-gcc)
@@ -492,6 +492,12 @@
 include ${PLAT_MAKEFILE_FULL}
 
 ################################################################################
+# Setup arch_features based on ARM_ARCH_MAJOR, ARM_ARCH_MINOR provided from
+# platform.
+################################################################################
+
+include ${MAKE_HELPERS_DIRECTORY}arch_features.mk
+################################################################################
 # Process BRANCH_PROTECTION value and set
 # Pointer Authentication and Branch Target Identification flags
 ################################################################################
@@ -517,30 +523,29 @@
 	# Turn on branch target identification mechanism
 	BP_OPTION := bti
 	ENABLE_BTI := 1
+else ifeq (${BRANCH_PROTECTION},5)
+	# Turn on branch target identification mechanism
+	BP_OPTION := standard
+	ENABLE_BTI := 2
+	ENABLE_PAUTH := 2
 else
         $(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION})
 endif #(BRANCH_PROTECTION)
 
-ifeq ($(ENABLE_PAUTH),1)
-	CTX_INCLUDE_PAUTH_REGS := 1
+ifneq ($(ENABLE_PAUTH),0)
+	CTX_INCLUDE_PAUTH_REGS	:= ${ENABLE_PAUTH}
 endif
 ifneq (${BP_OPTION},none)
 	TF_CFLAGS_aarch64	+=	-mbranch-protection=${BP_OPTION}
 endif #(BP_OPTION)
 
 # Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
+ifneq (${ENABLE_PAUTH},0)
 # arm/common/aarch64/arm_pauth.c contains a sample platform hook to complete the
 # Pauth support. As it's not secure, it must be reimplemented for real platforms
-	BL_COMMON_SOURCES	+=	lib/extensions/pauth/pauth_helpers.S
+	BL_COMMON_SOURCES	+=	lib/extensions/pauth/pauth.c
 endif
 
-################################################################################
-# Setup arch_features based on ARM_ARCH_MAJOR, ARM_ARCH_MINOR provided from
-# platform.
-################################################################################
-include ${MAKE_HELPERS_DIRECTORY}arch_features.mk
-
 ####################################################
 # Enable required options for Memory Stack Tagging.
 ####################################################
@@ -647,7 +652,7 @@
 ################################################################################
 include ${MAKE_HELPERS_DIRECTORY}march.mk
 
-TF_CFLAGS   +=	$(march-directive)
+TF_CFLAGS	+=	$(march-directive)
 ASFLAGS		+=	$(march-directive)
 
 # This internal flag is common option which is set to 1 for scenarios
@@ -759,6 +764,10 @@
 include lib/libc/libc.mk
 endif
 
+ifneq (${USE_GIC_DRIVER},0)
+include drivers/arm/gic/gic.mk
+endif
+
 ################################################################################
 # Check incompatible options and dependencies
 ################################################################################
@@ -917,18 +926,46 @@
 # If pointer authentication is used in the firmware, make sure that all the
 # registers associated to it are also saved and restored.
 # Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1.
-ifeq ($(ENABLE_PAUTH),1)
+ifneq ($(ENABLE_PAUTH),0)
 	ifeq ($(CTX_INCLUDE_PAUTH_REGS),0)
-                $(error Pointer Authentication requires CTX_INCLUDE_PAUTH_REGS=1)
+                $(error Pointer Authentication requires CTX_INCLUDE_PAUTH_REGS to be enabled)
 	endif
 endif #(ENABLE_PAUTH)
 
-ifeq ($(CTX_INCLUDE_PAUTH_REGS),1)
+ifneq ($(CTX_INCLUDE_PAUTH_REGS),0)
 	ifneq (${ARCH},aarch64)
                 $(error CTX_INCLUDE_PAUTH_REGS requires AArch64)
 	endif
 endif #(CTX_INCLUDE_PAUTH_REGS)
 
+# Check ENABLE_FEAT_PAUTH_LR
+ifneq (${ENABLE_FEAT_PAUTH_LR},0)
+
+# Make sure PAUTH is enabled
+ifeq (${ENABLE_PAUTH},0)
+	$(error Error: PAUTH_LR cannot be used without PAUTH (see BRANCH_PROTECTION))
+endif
+
+# Make sure SCTLR2 is enabled
+ifeq (${ENABLE_FEAT_SCTLR2},0)
+	$(error Error: PAUTH_LR cannot be used without ENABLE_FEAT_SCTLR2)
+endif
+
+# FEAT_PAUTH_LR is only supported in aarch64 state
+ifneq (${ARCH},aarch64)
+	$(error ENABLE_FEAT_PAUTH_LR requires AArch64)
+endif
+
+# Currently, FEAT_PAUTH_LR is only supported by arm/clang compilers
+# TODO implement for GCC when support is added
+ifeq ($($(ARCH)-cc-id),arm-clang)
+	arch-features	:= $(arch-features)+pauth-lr
+else
+	$(error Error: ENABLE_FEAT_PAUTH_LR not supported for GCC compiler)
+endif
+
+endif # ${ENABLE_FEAT_PAUTH_LR}
+
 ifeq ($(FEATURE_DETECTION),1)
         $(info FEATURE_DETECTION is an experimental feature)
 endif #(FEATURE_DETECTION)
@@ -975,7 +1012,7 @@
 	endif
 
 	# FEAT_RNG_TRAP is not supported in AArch32
-	ifeq (${ENABLE_FEAT_RNG_TRAP},1)
+	ifneq (${ENABLE_FEAT_RNG_TRAP},0)
                 $(error "ENABLE_FEAT_RNG_TRAP cannot be used with ARCH=aarch32")
 	endif
 
@@ -1239,6 +1276,7 @@
 	DISCRETE_TPM \
 	DICE_PROTECTION_ENVIRONMENT \
 	RMMD_ENABLE_EL3_TOKEN_SIGN \
+	RMMD_ENABLE_IDE_KEY_PROG \
 	DRTM_SUPPORT \
 	NS_TIMER_SWITCH \
 	OVERRIDE_LIBC \
@@ -1314,6 +1352,7 @@
 	ENABLE_TRBE_FOR_NS \
 	ENABLE_BTI \
 	ENABLE_PAUTH \
+	ENABLE_FEAT_PAUTH_LR \
 	ENABLE_FEAT_AMU \
 	ENABLE_FEAT_AMUv1p1 \
 	ENABLE_FEAT_CSV2_2 \
@@ -1400,11 +1439,13 @@
 	ENABLE_FEAT_DEBUGV8P9 \
 	ENABLE_FEAT_MPAM \
 	ENABLE_PAUTH \
+	ENABLE_FEAT_PAUTH_LR \
 	ENABLE_PIE \
 	ENABLE_PMF \
 	ENABLE_PSCI_STAT \
 	ENABLE_RME \
 	RMMD_ENABLE_EL3_TOKEN_SIGN \
+	RMMD_ENABLE_IDE_KEY_PROG \
 	ENABLE_RUNTIME_INSTRUMENTATION \
 	ENABLE_SME_FOR_NS \
 	ENABLE_SME2_FOR_NS \
diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S
index eaaf59a..3e3e002 100644
--- a/bl1/aarch64/bl1_exceptions.S
+++ b/bl1/aarch64/bl1_exceptions.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -224,15 +224,6 @@
 	 */
 	bl	prepare_el3_entry
 
-#if ENABLE_PAUTH
-	/* -----------------------------------------------------
-	 * Load and program stored APIAKey firmware key.
-	 * Re-enable pointer authentication in EL3, as it was
-	 * disabled before jumping to the next boot image.
-	 * -----------------------------------------------------
-	 */
-	bl	pauth_load_bl1_apiakey_enable
-#endif
 	/* -----------------------------------------------------
 	 * Populate the parameters for the SMC handler. We
 	 * already have x0-x4 in place. x5 will point to a
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index 2b3a827..db14ec6 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -52,14 +52,6 @@
 
 	/* Perform late platform-specific setup */
 	bl1_plat_arch_setup();
-
-#if CTX_INCLUDE_PAUTH_REGS
-	/*
-	 * Assert that the ARMv8.3-PAuth registers are present or an access
-	 * fault will be triggered when they are being saved or restored.
-	 */
-	assert(is_armv8_3_pauth_present());
-#endif /* CTX_INCLUDE_PAUTH_REGS */
 }
 
 /*******************************************************************************
@@ -127,12 +119,6 @@
 	/* Perform platform setup in BL1. */
 	bl1_platform_setup();
 
-#if ENABLE_PAUTH
-	/* Store APIAKey_EL1 key */
-	bl1_apiakey[0] = read_apiakeylo_el1();
-	bl1_apiakey[1] = read_apiakeyhi_el1();
-#endif /* ENABLE_PAUTH */
-
 	/* Get the image id of next image to load and run. */
 	image_id = bl1_plat_get_next_image_id();
 
diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S
index a021e42..756c16d 100644
--- a/bl2/aarch64/bl2_entrypoint.S
+++ b/bl2/aarch64/bl2_entrypoint.S
@@ -48,6 +48,10 @@
 	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el1
 	orr	x0, x0, x1
+#if ENABLE_BTI
+	/* Enable PAC branch type compatibility */
+	bic     x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT)
+#endif
 	bic	x0, x0, #SCTLR_DSSBS_BIT
 	msr	sctlr_el1, x0
 	isb
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index f12c1a5..dbe9453 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,14 +50,6 @@
 
 	/* Perform late platform-specific setup */
 	bl2_el3_plat_arch_setup();
-
-#if CTX_INCLUDE_PAUTH_REGS
-	/*
-	 * Assert that the ARMv8.3-PAuth registers are present or an access
-	 * fault will be triggered when they are being saved or restored.
-	 */
-	assert(is_armv8_3_pauth_present());
-#endif /* CTX_INCLUDE_PAUTH_REGS */
 }
 #else /* RESET_TO_BL2 */
 
@@ -75,14 +67,6 @@
 
 	/* Perform late platform-specific setup */
 	bl2_plat_arch_setup();
-
-#if CTX_INCLUDE_PAUTH_REGS
-	/*
-	 * Assert that the ARMv8.3-PAuth registers are present or an access
-	 * fault will be triggered when they are being saved or restored.
-	 */
-	assert(is_armv8_3_pauth_present());
-#endif /* CTX_INCLUDE_PAUTH_REGS */
 }
 #endif /* RESET_TO_BL2 */
 
@@ -136,12 +120,12 @@
 	disable_mmu_icache_secure();
 #endif /* !__aarch64__ */
 
-#if ENABLE_PAUTH
 	/*
 	 * Disable pointer authentication before running next boot image
 	 */
-	pauth_disable_el1();
-#endif /* ENABLE_PAUTH */
+	if (is_feat_pauth_supported()) {
+		pauth_disable_el1();
+	}
 
 #if ENABLE_RUNTIME_INSTRUMENTATION
 	PMF_CAPTURE_TIMESTAMP(bl_svc, BL2_EXIT, PMF_CACHE_MAINT);
@@ -164,12 +148,12 @@
 #endif
 	console_flush();
 
-#if ENABLE_PAUTH
 	/*
 	 * Disable pointer authentication before running next boot image
 	 */
-	pauth_disable_el3();
-#endif /* ENABLE_PAUTH */
+	if (is_feat_pauth_supported()) {
+		pauth_disable_el3();
+	}
 
 	bl2_run_next_image(next_bl_ep_info);
 #endif /* BL2_RUNS_AT_EL3 */
diff --git a/bl2u/aarch64/bl2u_entrypoint.S b/bl2u/aarch64/bl2u_entrypoint.S
index 15978b6..8fc34b3 100644
--- a/bl2u/aarch64/bl2u_entrypoint.S
+++ b/bl2u/aarch64/bl2u_entrypoint.S
@@ -45,6 +45,10 @@
 	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el1
 	orr	x0, x0, x1
+#if ENABLE_BTI
+	/* Enable PAC branch type compatibility */
+	bic     x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT)
+#endif
 	bic	x0, x0, #SCTLR_DSSBS_BIT
 	msr	sctlr_el1, x0
 	isb
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index b5bf575..7b61692 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -397,8 +397,26 @@
 	ldr	x4, [x0, #REGSZ * 7]
 
 #if ENABLE_PAUTH
+#if ENABLE_PAUTH == 2
+	/* Skip if not present in hardware */
+	is_feat_pauth_present_asm x0, x1
+	beq	1f
+#endif
+	/*
+	 * The assembler must see support for xpaci. So turn the compiler
+	 * extension on. GCC prior to 10 doesn't understand the PAuth extension
+	 * but it does understand armv8.3-a in general. Avoid using 8.3 if
+	 * the compiler understands "pauth" so we don't downgrade a higher
+	 * -march that was specified on the commandline.
+	 */
+#if __GNUC__ < 10
+	.arch armv8.3-a
+#else
+	.arch_extension pauth
+#endif
 	/* Demangle address */
 	xpaci	x4
+1:
 #endif
 	bl	asm_print_hex
 	bl	asm_print_newline
diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S
index fce17e1..3f1b3ea 100644
--- a/bl31/aarch64/ea_delegate.S
+++ b/bl31/aarch64/ea_delegate.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -46,11 +46,6 @@
 	 */
 	bl	prepare_el3_entry
 
-#if ENABLE_PAUTH
-	/* Load and program APIAKey firmware key */
-	bl	pauth_load_bl31_apiakey
-#endif
-
 	/* Setup exception class and syndrome arguments for platform handler */
 	mov	x0, #ERROR_EA_SYNC
 	mrs	x1, esr_el3
@@ -78,11 +73,6 @@
 	 */
 	bl	prepare_el3_entry
 
-#if ENABLE_PAUTH
-	/* Load and program APIAKey firmware key */
-	bl	pauth_load_bl31_apiakey
-#endif
-
 	/* Setup exception class and syndrome arguments for platform handler */
 	mov	x0, #ERROR_EA_ASYNC
 	mrs	x1, esr_el3
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 7423805..6537aa7 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -340,11 +340,6 @@
 	 */
 	bl	prepare_el3_entry
 
-#if ENABLE_PAUTH
-	/* Load and program APIAKey firmware key */
-	bl	pauth_load_bl31_apiakey
-#endif
-
 	/*
 	 * Populate the parameters for the SMC handler.
 	 * We already have x0-x4 in place. x5 will point to a cookie (not used
@@ -536,11 +531,6 @@
 	 */
 	bl	prepare_el3_entry
 
-#if ENABLE_PAUTH
-	/* Load and program APIAKey firmware key */
-	bl	pauth_load_bl31_apiakey
-#endif
-
 	/* Save the EL3 system registers needed to return from this exception */
 	mrs	x0, spsr_el3
 	mrs	x1, elr_el3
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 0cd0c79..a9f89fc 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +17,7 @@
 #include <common/debug.h>
 #include <common/feat_detect.h>
 #include <common/runtime_svc.h>
+#include <drivers/arm/gic.h>
 #include <drivers/console.h>
 #include <lib/bootmarker_capture.h>
 #include <lib/el3_runtime/context_debug.h>
@@ -104,14 +105,6 @@
 	/* Perform late platform-specific setup */
 	bl31_plat_arch_setup();
 
-#if CTX_INCLUDE_PAUTH_REGS
-	/*
-	 * Assert that the ARMv8.3-PAuth registers are present or an access
-	 * fault will be triggered when they are being saved or restored.
-	 */
-	assert(is_armv8_3_pauth_present());
-#endif /* CTX_INCLUDE_PAUTH_REGS */
-
 	/* Prints context_memory allocated for all the security states */
 	report_ctx_memory_usage();
 }
@@ -153,6 +146,18 @@
 	/* Perform platform setup in BL31 */
 	bl31_platform_setup();
 
+#if USE_GIC_DRIVER
+	/*
+	 * Initialize the GIC driver as well as per-cpu and global interfaces.
+	 * Platform has had an opportunity to initialise specifics.
+	 */
+	unsigned int core_pos = plat_my_core_pos();
+
+	gic_init(core_pos);
+	gic_pcpu_init(core_pos);
+	gic_cpuif_enable(core_pos);
+#endif /* USE_GIC_DRIVER */
+
 	/* Initialise helper libraries */
 	bl31_lib_init();
 
diff --git a/bl31/bl31_traps.c b/bl31/bl31_traps.c
index 984fdaa..114a57d 100644
--- a/bl31/bl31_traps.c
+++ b/bl31/bl31_traps.c
@@ -90,19 +90,17 @@
  * Explicitly create all bits of SPSR to get PSTATE at exception return.
  *
  * The code is based on "Aarch64.exceptions.takeexception" described in
- * DDI0602 revision 2023-06.
- * "https://developer.arm.com/documentation/ddi0602/2023-06/Shared-Pseudocode/
+ * DDI0602 revision 2025-03.
+ * "https://developer.arm.com/documentation/ddi0597/2025-03/Shared-Pseudocode/
  * aarch64-exceptions-takeexception"
  *
- * NOTE: This piece of code must be reviewed every release to ensure that
- * we keep up with new ARCH features which introduces a new SPSR bit.
+ * NOTE: This piece of code must be reviewed every release against the latest
+ * takeexception sequence to ensure that we keep up with new arch features that
+ * affect the PSTATE.
  *
- * TF-A 2.12 release review
- * The latest version available is 2024-09, which has two extra features which
- * impacts generation of SPSR, since these features are not implemented in TF-A
- * at the time of release, just log the feature names here to be taken up when
- * feature support is introduced.
- *  - FEAT_PAuth_LR (2023 extension)
+ * TF-A 2.13 release review
+ *
+ * Review of version 2025-03 indicates we are missing support for one feature.
  *  - FEAT_UINJ (2024 extension)
  */
 u_register_t create_spsr(u_register_t old_spsr, unsigned int target_el)
@@ -204,6 +202,12 @@
 		new_spsr |= (gcscr & GCSCR_EXLOCK_EN_BIT) ? SPSR_EXLOCK_BIT_AARCH64 : 0;
 	}
 
+	/* If FEAT_PAUTH_LR present then zero the PACM bit. */
+	new_spsr |= old_spsr & SPSR_PACM_BIT_AARCH64;
+	if (is_feat_pauth_lr_present()) {
+		new_spsr &= ~SPSR_PACM_BIT_AARCH64;
+	}
+
 	return new_spsr;
 }
 
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
index e5ea88c..4ea2f5b 100644
--- a/bl32/tsp/aarch64/tsp_entrypoint.S
+++ b/bl32/tsp/aarch64/tsp_entrypoint.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -51,6 +51,15 @@
 	.endm
 
 func tsp_entrypoint _align=3
+	/*---------------------------------------------
+	 * Save arguments x0 - x3 from BL1 for future
+	 * use.
+	 * ---------------------------------------------
+	 */
+	mov	x20, x0
+	mov	x21, x1
+	mov	x22, x2
+	mov	x23, x3
 
 #if ENABLE_PIE
 		/*
@@ -94,6 +103,10 @@
 	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el1
 	orr	x0, x0, x1
+#if ENABLE_BTI
+	/* Enable PAC branch type compatibility */
+	bic     x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT)
+#endif
 	bic	x0, x0, #SCTLR_DSSBS_BIT
 	msr	sctlr_el1, x0
 	isb
@@ -169,6 +182,16 @@
 	bl	update_stack_protector_canary
 #endif
 
+	/*---------------------------------------------
+	 * Save arguments x0 - x3 from prio stage for
+	 * future use.
+	 * ---------------------------------------------
+	 */
+	mov	x0, x20
+	mov	x1, x21
+	mov	x2, x22
+	mov	x3, x23
+
 	/* ---------------------------------------------
 	 * Perform TSP setup
 	 * ---------------------------------------------
diff --git a/bl32/tsp/tsp_common.c b/bl32/tsp/tsp_common.c
index 3a6c9d9..144349a 100644
--- a/bl32/tsp/tsp_common.c
+++ b/bl32/tsp/tsp_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -64,24 +64,17 @@
 /*******************************************************************************
  * Setup function for TSP.
  ******************************************************************************/
-void tsp_setup(void)
+void tsp_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
+	       u_register_t arg3)
 {
 	/* Enable early console if EARLY_CONSOLE flag is enabled */
 	plat_setup_early_console();
 
 	/* Perform early platform-specific setup. */
-	tsp_early_platform_setup();
+	tsp_early_platform_setup(arg0, arg1, arg2, arg3);
 
 	/* Perform late platform-specific setup. */
 	tsp_plat_arch_setup();
-
-#if ENABLE_PAUTH
-	/*
-	 * Assert that the ARMv8.3-PAuth registers are present or an access
-	 * fault will be triggered when they are being saved or restored.
-	 */
-	assert(is_armv8_3_pauth_present());
-#endif /* ENABLE_PAUTH */
 }
 
 /*******************************************************************************
@@ -104,7 +97,7 @@
 	tsp_stats[linear_id].eret_count++;
 
 	INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets requests\n", read_mpidr(),
 	     tsp_stats[linear_id].smc_count,
 	     tsp_stats[linear_id].eret_count);
 
@@ -132,7 +125,7 @@
 	tsp_stats[linear_id].eret_count++;
 
 	INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets requests\n", read_mpidr(),
 	     tsp_stats[linear_id].smc_count,
 	     tsp_stats[linear_id].eret_count);
 
diff --git a/bl32/tsp/tsp_interrupt.c b/bl32/tsp/tsp_interrupt.c
index a847b6c..9d86e3e 100644
--- a/bl32/tsp/tsp_interrupt.c
+++ b/bl32/tsp/tsp_interrupt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,8 +37,8 @@
 
 	VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%" PRIx64 "\n",
 		read_mpidr(), elr_el3);
-	VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
-		" %d sync s-el1 interrupt returns\n",
+	VERBOSE("TSP: cpu 0x%lx: %u sync s-el1 interrupt requests,"
+		" %u sync s-el1 interrupt returns\n",
 		read_mpidr(),
 		tsp_stats[linear_id].sync_sel1_intr_count,
 		tsp_stats[linear_id].sync_sel1_intr_ret_count);
@@ -54,7 +54,7 @@
 	uint32_t linear_id = plat_my_core_pos();
 
 	tsp_stats[linear_id].preempt_intr_count++;
-	VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n",
+	VERBOSE("TSP: cpu 0x%lx: %u preempt interrupt requests\n",
 		read_mpidr(), tsp_stats[linear_id].preempt_intr_count);
 	return TSP_PREEMPTED;
 }
@@ -107,9 +107,9 @@
 
 	/* Update the statistics and print some messages */
 	tsp_stats[linear_id].sel1_intr_count++;
-	VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n",
+	VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %u\n",
 	       read_mpidr(), id);
-	VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
+	VERBOSE("TSP: cpu 0x%lx: %u S-EL1 requests\n",
 	     read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
 	return 0;
 }
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index 8c6b2ed..1b7116a 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -47,7 +47,7 @@
 	tsp_stats[linear_id].eret_count++;
 	tsp_stats[linear_id].cpu_on_count++;
 
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu on requests\n",
 	     read_mpidr(),
 	     tsp_stats[linear_id].smc_count,
 	     tsp_stats[linear_id].eret_count,
@@ -75,7 +75,7 @@
 	tsp_stats[linear_id].cpu_on_count++;
 
 	INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu on requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -112,7 +112,7 @@
 	tsp_stats[linear_id].cpu_off_count++;
 
 	INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu off requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -150,7 +150,7 @@
 	tsp_stats[linear_id].eret_count++;
 	tsp_stats[linear_id].cpu_suspend_count++;
 
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu suspend requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -184,9 +184,9 @@
 	tsp_stats[linear_id].eret_count++;
 	tsp_stats[linear_id].cpu_resume_count++;
 
-	INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n",
+	INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRIu64 "\n",
 	     read_mpidr(), max_off_pwrlvl);
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu resume requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -224,7 +224,7 @@
 	INFO("TSP: cpu 0x%lx received %s smc 0x%" PRIx64 "\n", read_mpidr(),
 		((func >> 31) & 1) == 1 ? "fast" : "yielding",
 		func);
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets\n", read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count);
 
diff --git a/changelog.yaml b/changelog.yaml
index 6e7f179..93eeb73 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -205,13 +205,6 @@
             deprecated:
               - plat/tc
 
-            subsections:
-              - title: TC0
-                scope: tc0
-
-                deprecated:
-                  - plat/tc0
-
           - title: Corstone-1000
             scope: corstone-1000
 
@@ -1403,6 +1396,9 @@
     scope: tools
 
     subsections:
+      - title: Clang-Format
+        scope: clang-format
+
       - title: Dependabot
         scope: dependabot
 
diff --git a/common/backtrace/backtrace.c b/common/backtrace/backtrace.c
index f994ae5..479c4fd 100644
--- a/common/backtrace/backtrace.c
+++ b/common/backtrace/backtrace.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/console.h>
@@ -41,15 +42,14 @@
 {
 	uintptr_t ret = address;
 
-#if ENABLE_PAUTH
 	/*
 	 * When pointer authentication is enabled, the LR value saved on the
 	 * stack contains a PAC. It must be stripped to retrieve the return
 	 * address.
 	 */
-
-	xpaci(ret);
-#endif
+	if (is_feat_pauth_supported()) {
+		ret = xpaci(address);
+	}
 
 	return ret;
 }
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 821ccb8..2d80b42 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -66,7 +66,7 @@
 static void read_feat_pauth(void)
 {
 #if (ENABLE_PAUTH == FEAT_STATE_ALWAYS) || (CTX_INCLUDE_PAUTH_REGS == FEAT_STATE_ALWAYS)
-	feat_detect_panic(is_armv8_3_pauth_present(), "PAUTH");
+	feat_detect_panic(is_feat_pauth_present(), "PAUTH");
 #endif
 }
 
@@ -330,7 +330,7 @@
 	 * revisions so that we catch them as they come along
 	 */
 	check_feature(FEAT_STATE_ALWAYS, read_feat_pmuv3_id_field(),
-		      "PMUv3", 1, ID_AA64DFR0_PMUVER_PMUV3P8);
+		      "PMUv3", 1, ID_AA64DFR0_PMUVER_PMUV3P9);
 
 	/* v8.1 features */
 	check_feature(ENABLE_FEAT_PAN, read_feat_pan_id_field(), "PAN", 1, 3);
@@ -429,6 +429,7 @@
 	/* v9.4 features */
 	check_feature(ENABLE_FEAT_GCS, read_feat_gcs_id_field(), "GCS", 1, 1);
 	check_feature(ENABLE_RME, read_feat_rme_id_field(), "RME", 1, 1);
+	check_feature(ENABLE_FEAT_PAUTH_LR, is_feat_pauth_lr_present(), "PAUTH_LR", 1, 1);
 
 	if (tainted) {
 		panic();
diff --git a/docs/about/lts.rst b/docs/about/lts.rst
index 5aa32a2..593f9dc 100644
--- a/docs/about/lts.rst
+++ b/docs/about/lts.rst
@@ -283,8 +283,9 @@
    cherry-pick -x sha1-hash``.
 #. Some of the patches of this list may not be taken, mainly due to false
    positive. If in doubt, that can be discussed either in the “tf-a-lts” channel
-   on Discord or during the LTS weekly meeting. There could also be patches to
-   be taken in tf-a-ci-scripts or tf-a-tests.
+   on Discord or during the LTS weekly meeting.
+#. Some dependency patches, not listed in the CSV file, may have to be taken, to ease the
+   application of the LTS patches. This can also be discussed with the other LTS maintainers.
 #. Push the stack of changes: ``git push origin
    HEAD:refs/for/lts-v2.x%topic=for-lts-v2.x.y+1``. You might need the
    ``--no-verify`` option: ``git push origin --no-verify
@@ -298,6 +299,13 @@
    present, Gerrit will automatically merge the patch. LTS maintainers will then
    trigger a Jenkins job that will take care of the release (tag, mail, and
    readthedocs update).
+#. Some features may also require updates in other repositories (tf-a-ci-scripts,
+   tf-a-job-configs or tf-a-tests...). For tf-a-job-configs, there are no LTS branches, but
+   dedicated scripts for each LTS version which have to be updated manually. This is the case
+   for e.g. MbedTLS updates. For tf-a-ci-scripts and tf-a-tests, there are LTS branches and patches
+   will be cherry-picked from master branch to the LTS branch the same way it is done for TF-A.
+   There is no automation for those repositories. So the patches will have to be merged manually,
+   and for tf-a-ci-scripts and tf-a-tests, tags will also have to be set manually.
 
 Execution Plan
 **************
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 9e6f613..f1ce15a 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -226,10 +226,10 @@
 ^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Michal Simek <michal.simek@amd.com>
 :|G|: `michalsimek`_
-:|M|: Amit Nagal <amit.nagal@amd.com>
-:|G|: `amit-nagal`_
 :|M|: Akshay Belsare <akshay.belsare@amd.com>
 :|G|: `Akshay-Belsare`_
+:|M|: Maheedhar Sai Bollapalli <maheedharsai.bollapalli@amd.com>
+:|G|: `maheedhar-bollapalli`_
 :|F|: drivers/arm/dcc/
 :|F|: include/drivers/arm/dcc.h
 
@@ -592,10 +592,10 @@
 
 Arm Total Compute platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:|M|: Vishnu Banavath <vishnu.banavath@arm.com>
-:|G|: `vishnu-banavath`_
-:|M|: Rupinderjit Singh <rupinderjit.singh@arm.com>
-:|G|: `rupsin01`_
+:|M|: Artem Kopotev <artem.kopotev@arm.com>
+:|G|: `artkopotev`_
+:|M|: Oleksandr Tarhunakov <Oleksandr.Tarhunakov@arm.com>
+:|G|: `o-tarhunakov`_
 :|F|: plat/arm/board/tc
 
 Arm Automotive RD platform port
@@ -912,15 +912,17 @@
 :|F|: docs/plat/socionext-uniphier.rst
 :|F|: plat/socionext/uniphier/
 
-Xilinx platform port
-^^^^^^^^^^^^^^^^^^^^
+AMD-Xilinx platform port
+^^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Michal Simek <michal.simek@amd.com>
 :|G|: `michalsimek`_
-:|M|: Amit Nagal <amit.nagal@amd.com>
-:|G|: `amit-nagal`_
 :|M|: Akshay Belsare <akshay.belsare@amd.com>
 :|G|: `Akshay-Belsare`_
+:|M|: Maheedhar Sai Bollapalli <maheedharsai.bollapalli@amd.com>
+:|G|: `maheedhar-bollapalli`_
+:|F|: docs/plat/amd\*
 :|F|: docs/plat/xilinx\*
+:|F|: plat/amd/
 :|F|: plat/xilinx/
 
 
@@ -1035,7 +1037,6 @@
 .. _abdellatif-elkhlifi: https://github.com/abdellatif-elkhlifi
 .. _Akshay-Belsare: https://github.com/Akshay-Belsare
 .. _AlexeiFedorov: https://github.com/AlexeiFedorov
-.. _amit-nagal: https://github.com/amit-nagal
 .. _andersdellien-arm: https://github.com/andersdellien-arm
 .. _Andre-ARM: https://github.com/Andre-ARM
 .. _Anson-Huang: https://github.com/Anson-Huang
@@ -1085,6 +1086,7 @@
 .. _leon-chen-mtk: https://github.com/leon-chen-mtk
 .. _linyidi: https://github.com/linyidi
 .. _madhukar-Arm: https://github.com/madhukar-Arm
+.. _maheedhar-bollapalli: https://github.com/maheedhar-bollapalli
 .. _manish-pandey-arm: https://github.com/manish-pandey-arm
 .. _ManishVB-Arm: https://github.com/ManishVB-Arm
 .. _marcbonnici: https://github.com/marcbonnici
@@ -1113,7 +1115,7 @@
 .. _remi-triplefault: https://github.com/repk
 .. _rockchip-linux: https://github.com/rockchip-linux
 .. _rohit-arm: https://github.com/rohit-arm
-.. _rupsin01: https://github.com/rupsin01
+.. _o-tarhunakov: https://github.com/o-tarhunakov
 .. _rutigl: https://github.com/rutigl
 .. _sandrine-bailleux-arm: https://github.com/sandrine-bailleux-arm
 .. _shawnguo2: https://github.com/shawnguo2
@@ -1128,11 +1130,11 @@
 .. _TravMurav: https://github.com/TravMurav
 .. _uarif1: https://github.com/uarif1
 .. _vijayenthiran-arm: https://github.com/vijayenthiran-arm
-.. _vishnu-banavath: https://github.com/vishnu-banavath
+.. _artkopotev: https://github.com/artkopotev
 .. _vwadekar: https://github.com/vwadekar
 .. _Yann-lms: https://github.com/Yann-lms
 .. _sjaypee208: https://github.com/sjaypee208
 
 --------------
 
-*Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index dc2b2fd..0edd314 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -74,6 +74,8 @@
 +-----------------+---------------------------+------------------------------+
 | v2.13           | 4th week of May '25       | 2nd week of May '25          |
 +-----------------+---------------------------+------------------------------+
+| v2.14           | 4th week of Nov '25       | 2nd week of Nov '25          |
++-----------------+---------------------------+------------------------------+
 
 Removal of Deprecated Interfaces
 --------------------------------
diff --git a/docs/components/context-management-library.rst b/docs/components/context-management-library.rst
index 8cb1ace..cef6fba 100644
--- a/docs/components/context-management-library.rst
+++ b/docs/components/context-management-library.rst
@@ -106,7 +106,6 @@
 	#define FEAT_STATE_DISABLED     	0
 	#define FEAT_STATE_ENABLED      	1
 	#define FEAT_STATE_CHECK        	2
-	#define FEAT_STATE_CHECK_ASYMMETRIC	3
 
 A pattern is established for feature enablement behavior.
 Each feature must support the 3 possible values with rigid semantics.
@@ -120,15 +119,15 @@
 - **FEAT_STATE_CHECK** - same as ``FEAT_STATE_ALWAYS`` except that the feature's
   existence will be checked at runtime. Default on dynamic platforms (example: FVP).
 
-- **FEAT_STATE_CHECK_ASYMMETRIC** - same as ``FEAT_STATE_CHECK`` except that the feature's
-  existence is asymmetric across cores, which requires the feature existence is checked
-  during warmboot path also. Note that only limited number of features can be asymmetric.
-
  .. note::
-   Only limited number of features can be ``FEAT_STATE_CHECK_ASYMMETRIC`` this is due to
-   the fact that Operating systems are designed for SMP systems.
-   There are no clear guidelines what kind of mismatch is allowed but following pointers
-   can help making a decision
+
+   In general, it is assumed that all cores will support the same set of
+   architectural features (features will be symmetrical). However, there are
+   cases where this is impractical to achieve. Only some features can be
+   mismatched among cores and this is the exception rather than the rule. This
+   is due to the fact that Operating systems are designed for SMP systems. There
+   are no clear guidelines what kind of mismatch is allowed but following
+   pointers can help in making a decision:
 
     - All mandatory features must be symmetric.
     - Any feature that impacts the generation of page tables must be symmetric.
@@ -136,8 +135,9 @@
     - Features related with profiling, debug and trace could be asymmetric
     - Migration of vCPU/tasks between CPUs should not cause an error
 
-    Whenever there is asymmetric feature support is added for a feature TF-A need to add
-    feature specific code in context management code.
+   TF-A caters for mismatched features, however, this is not regularly tested
+   for all features and may not work as expected, even without considering OS
+   support.
 
  .. note::
    ``FEAT_RAS`` is an exception here, as it impacts the execution of EL3 and
@@ -345,9 +345,9 @@
 
 |Context Init WarmBoot|
 
-The primary CPU initializes the Non-Secure context for the secondary CPU while
-restoring re-entry information for the Non-Secure world.
-It initialises via ``cm_init_context_by_index(target_idx, ep )``.
+The primary CPU writes the entrypoint for the secondary CPU. When the secondary
+wakes up it initialises its own context via ``cm_init_my_context( ep )`` using
+the provided entrypoint.
 
 ``psci_warmboot_entrypoint()`` is the warm boot entrypoint procedure.
 During the warm bootup process, secondary CPUs have their secure context
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index 2b6382b..34290f8 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -29,8 +29,13 @@
 
 - uuid [mandatory]
    - value type: <prop-encoded-array>
-   - An array consisting of 4 <u32> values, identifying the UUID of the service
-     implemented by this partition. The UUID format is described in RFC 4122.
+   - An array of comma separated tuples each consisting of 4 <u32> values,
+     identifying the UUID of the services implemented by this partition.
+     The UUID format is described in RFC 4122.
+   - These 4 <u32> values are packed similar to the UUID register mapping
+     specified in section '5.3 Unique Identification format', SMC Calling
+     Convention, DEN0028, v1.6 G BET0
+     (https://developer.arm.com/documentation/den0028/latest/).
 
 - id
    - value type: <u32>
diff --git a/docs/components/rmm-el3-comms-spec.rst b/docs/components/rmm-el3-comms-spec.rst
index 2693e58..6a07271 100644
--- a/docs/components/rmm-el3-comms-spec.rst
+++ b/docs/components/rmm-el3-comms-spec.rst
@@ -52,7 +52,7 @@
   - ``RES0``: Bit 31 of the version number is reserved 0 as to maintain
     consistency with the versioning schemes used in other parts of RMM.
 
-This document specifies the 0.5 version of Boot Interface ABI and RMM-EL3
+This document specifies the 0.6 version of Boot Interface ABI and RMM-EL3
 services specification and the 0.5 version of the Boot Manifest.
 
 .. _rmm_el3_boot_interface:
@@ -719,6 +719,263 @@
    ``E_RMM_OK``,No errors detected
 
 
+RMM_IDE_KEY_PROG command
+=========================
+
+Set the key/IV info at Root port for an IDE stream as part of Device Assignment flow. This
+command is available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and how this will be invoked by RMM.
+
+The key is 256 bits and IV is 96 bits. The caller needs
+to call this SMC to program this key to the Rx, Tx ports and for each sub-stream
+corresponding to a single keyset.
+
+FID
+---
+
+``0xC40001B7``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KEY_PROG
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+   "Keyset[12]:
+   Dir[11]:
+   Substream[10:8]:
+   StreamID[7:0]",x3,[63:0],UInt64,IDE selective stream informationKey set: can be 0 or 1unused bits MBZ.
+   KeqQW0,x4,[63:0],UInt64,Quad word of key [63:0]
+   KeqQW1,x5,[63:0],UInt64,Quad word of key [127:64]
+   KeqQW2,x6,[63:0],UInt64,Quad word of key [191:128]
+   KeqQW3,x7,[63:0],UInt64,Quad word of key [255:192]
+   IFVQW0,x8,[63:0],UInt64,Quad word of IV [63:0]
+   IFVQW1,x9,[63:0],UInt64,Quad word of IV [95:64]
+   request_id,x10,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+   cookie,x11,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KEY_PROG
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   Result,x0,[63:0],Error Code,Command return status
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KEY_PROG
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,The Key programming is successful.
+   ``E_RMM_FAULT``,The Key programming is not successful.
+   ``E_RMM_INVAL``,The Key programming arguments are incorrect.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,Returned only for non-blocking mode. IDE-KM interface is busy or request is full. Retry required.
+   ``E_RMM_INPROGRESS``,Returned only for non-blocking mode. The caller must issue RMM_IDE_KM_PULL_RESPONSE SMC to pull the response.
+
+
+RMM_IDE_KEY_SET_GO command
+==========================
+
+Activate the IDE stream at Root Port once the keys have been programmed as part of
+Device Assignment flow. This command is available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and info on how this will be invoked by RMM.
+
+The caller(RMM) needs to ensure the EL3_IDE_KEY_PROG() call had succeeded prior to this call.
+
+FID
+---
+
+``0xC40001B8``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KEY_SET_GO
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+   "Keyset[12]:
+   Dir[11]:
+   Substream[10:8]:
+   StreamID[7:0]",x3,[63:0],UInt64,IDE selective stream information. Key set can be 0 or 1. Unused bits MBZ.
+   request_id,x4,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+   cookie,x5,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KEY_SET_GO
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   Result,x0,[63:0],Error Code,Command return status
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KEY_SET_GO
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,The Key set go is successful.
+   ``E_RMM_FAULT``,The Key set go is not successful.
+   ``E_RMM_INVAL``,Incorrect arguments.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,Returned only for non-blocking mode. IDE-KM interface is busy or request is full. Retry required.
+   ``E_RMM_INPROGRESS``,Returned only for non-blocking mode. The caller must issue RMM_IDE_KM_PULL_RESPONSE SMC to pull the response.
+
+
+RMM_IDE_KEY_SET_STOP command
+============================
+
+Deactivate the IDE stream at Root Port as part of Device Assignment flow. This command is
+available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and info on how this will be invoked by RMM.
+
+This SMC is used to tear down an IDE Stream.
+
+FID
+---
+
+``0xC40001B9``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KEY_SET_STOP
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+   "Keyset[12]:
+   Dir[11]:
+   Substream[10:8]:
+   StreamID[7:0]",x3,[63:0],UInt64,IDE selective stream information. Key set can be 0 or 1. Unused bits MBZ.
+   request_id,x4,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+   cookie,x5,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KEY_SET_STOP
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   Result,x0,[63:0],Error Code,Command return status
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KEY_SET_STOP
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,The Key set stop is successful.
+   ``E_RMM_FAULT``,The Key set stop is not successful.
+   ``E_RMM_INVAL``,Incorrect arguments.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,Returned only for non-blocking mode. IDE-KM interface is busy or request is full. Retry required.
+   ``E_RMM_INPROGRESS``,Returned only for non-blocking mode. The caller must issue RMM_IDE_KM_PULL_RESPONSE SMC to pull the response.
+
+
+RMM_IDE_KM_PULL_RESPONSE command
+================================
+
+Retrieve the response from Root Port to a previous non-blocking IDE-KM SMC request as part of
+Device Assignment flow. This command is available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and info on how this will be invoked by RMM.
+
+The response from this call could correspond to any of the last pending requests and the
+RMM needs to identify the request and populate the response. For blocking calls, this SMC
+always returns E_RMM_UNK.
+
+FID
+---
+
+``0xC40001BA``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KM_PULL_RESPONSE
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KM_PULL_RESPONSE
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   Result,x0,[63:0],Error Code,Command return status
+   Result,x1,[63:0],Error Code,Retrieved response corresponding to previous IDE_KM requests.
+   Result,x2,[63:0],value,passthrough from requested SMC
+   Result,x3,[63:0],value,passthrough from requested SMC
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KM_PULL_RESPONSE(x0)
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,Response is retrieved successfully.
+   ``E_RMM_INVAL``,Arguments to pull response SMC is not correct.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,IDE-KM response queue is empty and no response is available.
+
+.. csv-table:: Failure conditions for RMM_IDE_KM_PULL_RESPONSE(x1)
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,The previous request was successful.
+   ``E_RMM_FAULT``,The previous request was not successful.
+   ``E_RMM_INVAL``,Arguments to previous request were incorrect.
+   ``E_RMM_UNK``,Previous request returned unknown error.
+
 RMM-EL3 world switch register save restore convention
 _____________________________________________________
 
diff --git a/docs/design_documents/measured_boot.rst b/docs/design_documents/measured_boot.rst
index 1f76770..a9d2fa9 100644
--- a/docs/design_documents/measured_boot.rst
+++ b/docs/design_documents/measured_boot.rst
@@ -231,9 +231,9 @@
    - Public key data size is passed as the third argument to this function.
    - This function must return 0 on success, a signed integer error code
      otherwise.
-   - In TC2 platform, this function is used to calculate the hash of the given
-     key and forward this hash to |RSE| alongside the measurement of the image
-     which the key signs.
+   - In Total Compute platform, this function is used to calculate the hash
+     of the given key and forward this hash to |RSE| alongside the measurement
+     of the image which the key signs.
 
 --------------
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index b5814bb..32daf1e 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -113,12 +113,16 @@
 -  ``BRANCH_PROTECTION``: Numeric value to enable ARMv8.3 Pointer Authentication
    and ARMv8.5 Branch Target Identification support for TF-A BL images themselves.
    If enabled, it is needed to use a compiler that supports the option
-   ``-mbranch-protection``. Selects the branch protection features to use:
--  0: Default value turns off all types of branch protection
+   ``-mbranch-protection``. The value of the ``-march`` (via ``ARM_ARCH_MINOR``
+   and ``ARM_ARCH_MAJOR``) option will control which instructions will be
+   emitted (HINT space or not). Selects the branch protection features to use:
+-  0: Default value turns off all types of branch protection (FEAT_STATE_DISABLED)
 -  1: Enables all types of branch protection features
 -  2: Return address signing to its standard level
 -  3: Extend the signing to include leaf functions
 -  4: Turn on branch target identification mechanism
+-  5: Enables all types of branch protection features, only if present in
+   hardware (FEAT_STATE_CHECK).
 
    The table below summarizes ``BRANCH_PROTECTION`` values, GCC compilation options
    and resulting PAuth/BTI features.
@@ -136,6 +140,8 @@
    +-------+--------------+-------+-----+
    |   4   |     bti      |   N   |  Y  |
    +-------+--------------+-------+-----+
+   |   5   |   dynamic    |   Y   |  Y  |
+   +-------+--------------+-------+-----+
 
    This option defaults to 0.
    Note that Pointer Authentication is enabled for Non-secure world
@@ -198,11 +204,13 @@
 -  ``CTX_INCLUDE_PAUTH_REGS``: Numeric value to enable the Pointer
    Authentication for Secure world. This will cause the ARMv8.3-PAuth registers
    to be included when saving and restoring the CPU context as part of world
-   switch. This flag can take values 0 to 2, to align with ``ENABLE_FEAT``
-   mechanism. Default value is 0.
+   switch. Automatically enabled when ``BRANCH_PROTECTION`` is enabled. This flag
+   can take values 0 to 2, to align with ``ENABLE_FEAT`` mechanism. Default value
+   is 0.
 
    Note that Pointer Authentication is enabled for Non-secure world irrespective
-   of the value of this flag if the CPU supports it.
+   of the value of this flag if the CPU supports it. Alternatively, when
+   ``BRANCH_PROTECTION`` is enabled, this flag is superseded.
 
 -  ``CTX_INCLUDE_SVE_REGS``: Boolean option that, when set to 1, will cause the
    SVE registers to be included when saving and restoring the CPU context. Note
@@ -397,6 +405,12 @@
    flag can take values 0 to 2, to align  with the ``ENABLE_FEAT``
    mechanism. Default value is ``0``.
 
+-  ``ENABLE_FEAT_PAUTH_LR``: Numeric value to enable the ``FEAT_PAUTH_LR``
+   extension. ``FEAT_PAUTH_LR`` is an optional feature available from Arm v9.4
+   onwards. This feature requires PAUTH to be enabled via the
+   ``BRANCH_PROTECTION`` flag. This flag can take the values 0 to 2, to align
+   with the ``ENABLE_FEAT`` mechanism. Default value is ``0``.
+
 -  ``ENABLE_FEAT_RNG``: Numeric value to enable the ``FEAT_RNG`` extension.
    ``FEAT_RNG`` is an optional feature available on Arm v8.5 onwards. This
    flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
@@ -1280,11 +1294,37 @@
   This option should only be enabled on a need basis if there is a use case for
   reading characters from the console.
 
-GICv3 driver options
+GIC driver options
 --------------------
 
-GICv3 driver files are included using directive:
+The generic GIC driver can be included with the ``USE_GIC_DRIVER`` option. It is
+a numeric option that can take the following values:
 
+ - ``0``: generic GIC driver not enabled. Any support is entirely in platform
+   code. Strongly discouraged for GIC based interrupt controllers.
+
+ - ``1``: enable the use of the generic GIC driver but do not include any files
+   or function definitions. It is then the platform's responsibility to provide
+   these. This is useful if the platform either has a custom GIC implementation
+   or an alternative interrupt controller design. Use of this option is strongly
+   discouraged for standard GIC implementations.
+
+ - ``2``: use the GICv2 driver
+
+ - ``3``: use the GICv3 driver. See the next section on how to further configure
+   it. Use this option for GICv4 implementations.
+
+ For GIC driver versions other than ``1``, deciding when to save and restore GIC
+ context on a power domain state transition, as well as any GIC actions outside
+ of the PSCI library's visibility are the platform's responsibility. The driver
+ provides implementations of all necessary subroutines, they only need to be
+ called as appropriate.
+
+GICv3 driver options
+~~~~~~~~~~~~~~~~~~~~
+
+``USE_GIC_DRIVER=3`` is the preferred way of including GICv3 driver files. The
+old (deprecated) way of included them is using the directive:
 ``include drivers/arm/gic/v3/gicv3.mk``
 
 The driver can be configured with the following options set in the platform
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index a043991..da7a2c3 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -27,7 +27,7 @@
         Program          Min supported version
 ======================== =====================
 Arm Compiler             6.23
-Arm GNU Compiler         13.3
+Arm GNU Compiler         14.2
 Clang/LLVM               18.1.8
 Device Tree Compiler     1.6.1
 GNU make                 3.81
@@ -51,7 +51,7 @@
 AArch64 builds, the respective targets required are ``arm-none-eabi`` and
 ``aarch64-none-elf``.
 
-Testing has been performed with version 13.3.Rel1 (gcc 13.3) of the Arm
+Testing has been performed with version 14.2.Rel1 (GCC 14.2) of the Arm
 GNU compiler, which can be installed from the `Arm Developer website`_.
 
 In addition, a native compiler is required to build supporting tools.
diff --git a/docs/plat/arm/tc/index.rst b/docs/plat/arm/tc/index.rst
index 467738c..d57b48e 100644
--- a/docs/plat/arm/tc/index.rst
+++ b/docs/plat/arm/tc/index.rst
@@ -17,12 +17,8 @@
 the Total Compute platform number. The platforms support the CPU variants
 listed as below:
 
--  TC0 has support for Cortex A510, Cortex A710 and Cortex X2. (Note TC0 is now deprecated)
--  TC1 has support for Cortex A510, Cortex A715 and Cortex X3. (Note TC1 is now deprecated)
--  TC2 has support for Cortex A520, Cortex A720 and Cortex x4. (Note TC2 is now deprecated)
 -  TC3 has support for Cortex A520, Cortex A725 and Cortex x925.
 
-
 Boot Sequence
 -------------
 
@@ -59,6 +55,6 @@
 
 --------------
 
-*Copyright (c) 2020-2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2020-2025, Arm Limited. All rights reserved.*
 
 .. _Arm Toolchain: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index d0d6889..a30f55d 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -72,7 +72,7 @@
 +----------------+----------------+--------------------+--------------------+
 |    Platform    |     Vendor     | Deprecated version |  Deleted version   |
 +================+================+====================+====================+
-|      TC2       |      Arm       |        2.12        |         TBD        |
+|      TC2       |      Arm       |        2.12        |         2.13       |
 |                |                |                    |                    |
 +----------------+----------------+--------------------+--------------------+
 |     fvp_r      |      Arm       |        2.13        |         2.13       |
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 327c67b..7e40e47 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2460,6 +2460,163 @@
 The function returns E_RMM_OK on success, RMM_E_INVAL if arguments are invalid and
 E_RMM_UNK if the SMC is not implemented or if interface version is < 0.4.
 
+Function : plat_rmmd_el3_ide_key_program() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t, struct rp_ide_key_info_t *, uint64_t, uint64_t
+    Return   : int
+
+This function sets the key/IV info for an IDE stream at the Root port. The key is 256 bits
+and IV is 96 bits. The caller calls this SMC to program this key to the Rx and Tx ports
+and for each substream corresponding to a single keyset. The platform should validate
+the arguments `Ecam address` and `Rootport ID` before acting on it. The arguments `request ID`
+and `cookie` are to be ignored for blocking mode and are pass-through to the response for
+non-blocking mode.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - The IDE stream info associated with a physical device, this parameter packs the
+    the keyset, direction, substream and stream ID info.
+
+    arg3 - Structure with key and IV info.
+
+    arg4 - The request ID, is used in non-blocking mode only and can be ignored in blocking mode.
+
+    arg5 - The cookie variable, is used in non-blocking mode only and can be ignored in blocking
+    mode.
+
+The function returns E_RMM_OK on success, E_RMM_INVAL if arguments are invalid, E_RMM_FAULT
+if the key programming is unsuccesful, E_RMM_UNK for an unknown error, E_RMM_AGAIN returned
+only for non-blocking mode if the IDE-KM interface is busy or the request queue is full.
+E_RMM_INPROGRESS returned if the request is queued successfully and used only in non-blocking
+mode.
+
+Function : plat_rmmd_el3_ide_key_set_go() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
+    Return   : int
+
+This function activates the IDE stream at the Root Port once all the keys have been
+programmed. The platform should validate the arguments `Ecam address` and `Rootport ID`
+before acting on it. The arguments `request ID` and `cookie` are to be ignored for blocking
+mode and are pass-through to the response for non-blocking mode.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - The IDE stream info associated with a physical device, this parameter packs the
+    the keyset, direction, substream and stream ID info.
+
+    arg3 - The request ID, is used in non-blocking mode only and can be ignored in blocking mode.
+
+    arg4 - The cookie variable, is used in non-blocking mode only and can be ignored in blocking
+    mode.
+
+The function returns E_RMM_OK on success, E_RMM_INVAL if arguments are invalid, E_RMM_FAULT
+if the key programming is unsuccesful, E_RMM_UNK for an unknown error, E_RMM_AGAIN returned
+only for non-blocking mode if the IDE-KM interface is busy or the request queue is full.
+E_RMM_INPROGRESS returned if the request is queued successfully and used only in non-blocking
+mode.
+
+Function : plat_rmmd_el3_ide_key_set_stop() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
+    Return   : int
+
+This function stops the IDE stream and is used to tear down the IDE stream at Root Port.
+The platform should validate the arguments `Ecam address` and `Rootport ID` before acting
+on it. The arguments `request ID` and `cookie` are to be ignored for blocking
+mode and are pass-through to the response for non-blocking mode.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - The IDE stream info associated with a physical device, this parameter packs the
+    the keyset, direction, substream and stream ID info.
+
+    arg3 - The request ID, is used in non-blocking mode only and can be ignored in blocking mode.
+
+    arg4 - The cookie variable, is used in non-blocking mode only and can be ignored in blocking
+    mode.
+
+The function returns E_RMM_OK on success, E_RMM_INVAL if arguments are invalid, E_RMM_FAULT
+if the key programming is unsuccesful, E_RMM_UNK for an unknown error, E_RMM_AGAIN returned
+only for non-blocking mode if the IDE-KM interface is busy or the request queue is full.
+E_RMM_INPROGRESS returned if the request is queued successfully and used only in non-blocking
+mode.
+
+Function : plat_rmmd_el3_ide_km_pull_response() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t *, uint64_t *, uint64_t *
+    Return   : int
+
+This function retrieves a reponse for any of the prior non-blocking IDE-KM requests. The
+caller has to identify the request and populate the accurate response. For blocking calls,
+this function always returns E_RMM_UNK.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - Retrieved response corresponding to the previous IDE_KM request.
+
+    arg3 - returns the passthrough request ID of the retrieved response.
+
+    arg4 - returns the passthrough cookie of the retrieved response.
+
+The function returns E_RMM_OK if response is retrieved successfully, E_RMM_INVAL if arguments
+to this function are invalid, E_RMM_UNK if response retrieval failed for an unknown error or
+IDE-KM interface is having blocking semantics, E_RMM_AGAIN if the response queue is empty.
+
+The `arg2` return parameter can return the following values:
+E_RMM_OK - The previous request was successful.
+E_RMM_FAULT - The previous request was not successful.
+E_RMM_INVAL - Arguments to previous request were incorrect.
+E_RMM_UNK - Previous request returned Unknown error.
+
 Function : bl31_plat_enable_mmu [optional]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index b310ff4..74d9fad 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -309,10 +309,11 @@
 	 */
 	mmio_write_64(PLAT_ARM_TRUSTED_MAILBOX_BASE, 0U);
 
+	unsigned int core_pos = plat_my_core_pos();
 	/*
 	 * Send powerdown request to online secondary core(s)
 	 */
-	ret = psci_stop_other_cores(plat_my_core_pos(), 0, css_raise_pwr_down_interrupt);
+	ret = psci_stop_other_cores(core_pos, 0, css_raise_pwr_down_interrupt);
 	if (ret != PSCI_E_SUCCESS) {
 		ERROR("Failed to powerdown secondary core(s)\n");
 	}
@@ -321,8 +322,8 @@
 	 * Disable GIC CPU interface to prevent pending interrupt from waking
 	 * up the AP from WFI.
 	 */
-	plat_arm_gic_cpuif_disable();
-	plat_arm_gic_redistif_off();
+	gic_cpuif_disable(core_pos);
+	gic_pcpu_off(core_pos);
 
 	/*
 	 * Issue SCMI command. First issue a graceful
diff --git a/drivers/arm/css/scp/css_pm_scpi.c b/drivers/arm/css/scp/css_pm_scpi.c
index 02be070..781b216 100644
--- a/drivers/arm/css/scp/css_pm_scpi.c
+++ b/drivers/arm/css/scp/css_pm_scpi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -121,12 +121,6 @@
 {
 	uint32_t response;
 
-	/*
-	 * Disable GIC CPU interface to prevent pending interrupt
-	 * from waking up the AP from WFI.
-	 */
-	plat_arm_gic_cpuif_disable();
-
 	/* Send the power down request to the SCP */
 	response = scpi_sys_power_state(scpi_system_shutdown);
 
@@ -143,12 +137,6 @@
 {
 	uint32_t response;
 
-	/*
-	 * Disable GIC CPU interface to prevent pending interrupt
-	 * from waking up the AP from WFI.
-	 */
-	plat_arm_gic_cpuif_disable();
-
 	/* Send the system reset request to the SCP */
 	response = scpi_sys_power_state(scpi_system_reboot);
 
diff --git a/drivers/arm/gic/gic.mk b/drivers/arm/gic/gic.mk
new file mode 100644
index 0000000..ad30984
--- /dev/null
+++ b/drivers/arm/gic/gic.mk
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+GIC_REVISIONS_ := 1 2 3
+ifeq ($(filter $(USE_GIC_DRIVER),$(GIC_REVISIONS_)),)
+$(error USE_GIC_DRIVER can only be one of $(GIC_REVISIONS_))
+endif
+
+ifeq (${USE_GIC_DRIVER},2)
+include drivers/arm/gic/v2/gicv2.mk
+GIC_SOURCES	:=	${GICV2_SOURCES}			\
+			drivers/arm/gic/v2/gicv2_base.c	\
+			plat/common/plat_gicv2.c
+else ifeq (${USE_GIC_DRIVER},3)
+include drivers/arm/gic/v3/gicv3.mk
+GIC_SOURCES	:=	${GICV3_SOURCES}			\
+			drivers/arm/gic/v3/gicv3_base.c	\
+			plat/common/plat_gicv3.c
+endif
+
+ifeq ($(ARCH),aarch64)
+BL31_SOURCES	+=	${GIC_SOURCES}
+else
+BL32_SOURCES	+=	${GIC_SOURCES}
+endif
+
+$(eval $(call add_defines,\
+	USE_GIC_DRIVER \
+))
diff --git a/plat/arm/common/arm_gicv2.c b/drivers/arm/gic/v2/gicv2_base.c
similarity index 74%
copy from plat/arm/common/arm_gicv2.c
copy to drivers/arm/gic/v2/gicv2_base.c
index 80a845f..317375f 100644
--- a/plat/arm/common/arm_gicv2.c
+++ b/drivers/arm/gic/v2/gicv2_base.c
@@ -1,24 +1,19 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <platform_def.h>
 
+#include <drivers/arm/gic.h>
 #include <drivers/arm/gicv2.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
-/******************************************************************************
- * The following functions are defined as weak to allow a platform to override
- * the way the GICv2 driver is initialised and used.
- *****************************************************************************/
-#pragma weak plat_arm_gic_driver_init
-#pragma weak plat_arm_gic_init
-#pragma weak plat_arm_gic_cpuif_enable
-#pragma weak plat_arm_gic_cpuif_disable
-#pragma weak plat_arm_gic_pcpu_init
+#if USE_GIC_DRIVER != 2
+#error "This file should only be used with GENERIC_GIC_DRIVER=2"
+#endif
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
@@ -43,23 +38,16 @@
 /******************************************************************************
  * ARM common helper to initialize the GICv2 only driver.
  *****************************************************************************/
-void plat_arm_gic_driver_init(void)
+void __init gic_init(unsigned int cpu_idx)
 {
 	gicv2_driver_init(&arm_gic_data);
-}
-
-void plat_arm_gic_init(void)
-{
 	gicv2_distif_init();
-	gicv2_pcpu_distif_init();
-	gicv2_set_pe_target_mask(plat_my_core_pos());
-	gicv2_cpuif_enable();
 }
 
 /******************************************************************************
  * ARM common helper to enable the GICv2 CPU interface
  *****************************************************************************/
-void plat_arm_gic_cpuif_enable(void)
+void gic_cpuif_enable(unsigned int cpu_idx)
 {
 	gicv2_cpuif_enable();
 }
@@ -67,7 +55,7 @@
 /******************************************************************************
  * ARM common helper to disable the GICv2 CPU interface
  *****************************************************************************/
-void plat_arm_gic_cpuif_disable(void)
+void gic_cpuif_disable(unsigned int cpu_idx)
 {
 	gicv2_cpuif_disable();
 }
@@ -75,7 +63,7 @@
 /******************************************************************************
  * ARM common helper to initialize the per cpu distributor interface in GICv2
  *****************************************************************************/
-void plat_arm_gic_pcpu_init(void)
+void gic_pcpu_init(unsigned int cpu_idx)
 {
 	gicv2_pcpu_distif_init();
 	gicv2_set_pe_target_mask(plat_my_core_pos());
@@ -85,29 +73,23 @@
  * Stubs for Redistributor power management. Although GICv2 doesn't have
  * Redistributor interface, these are provided for the sake of uniform GIC API
  *****************************************************************************/
-void plat_arm_gic_redistif_on(void)
+void gic_pcpu_off(unsigned int cpu_idx)
 {
 	return;
 }
 
-void plat_arm_gic_redistif_off(void)
-{
-	return;
-}
-
-
 /******************************************************************************
  * ARM common helper to save & restore the GICv3 on resume from system suspend.
  * The normal world currently takes care of saving and restoring the GICv2
  * registers due to legacy reasons. Hence we just initialize the Distributor
  * on resume from system suspend.
  *****************************************************************************/
-void plat_arm_gic_save(void)
+void gic_save(void)
 {
 	return;
 }
 
-void plat_arm_gic_resume(void)
+void gic_resume(void)
 {
 	gicv2_distif_init();
 	gicv2_pcpu_distif_init();
diff --git a/plat/arm/common/arm_gicv3.c b/drivers/arm/gic/v3/gicv3_base.c
similarity index 76%
copy from plat/arm/common/arm_gicv3.c
copy to drivers/arm/gic/v3/gicv3_base.c
index 5becbcd..3c97b01 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/drivers/arm/gic/v3/gicv3_base.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,25 +9,18 @@
 
 #include <common/debug.h>
 #include <common/interrupt_props.h>
+#include <drivers/arm/gic.h>
 #include <drivers/arm/gicv3.h>
 #include <lib/utils.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
-/******************************************************************************
- * The following functions are defined as weak to allow a platform to override
- * the way the GICv3 driver is initialised and used.
- *****************************************************************************/
-#pragma weak plat_arm_gic_driver_init
-#pragma weak plat_arm_gic_init
-#pragma weak plat_arm_gic_cpuif_enable
-#pragma weak plat_arm_gic_cpuif_disable
-#pragma weak plat_arm_gic_pcpu_init
-#pragma weak plat_arm_gic_redistif_on
-#pragma weak plat_arm_gic_redistif_off
+#if USE_GIC_DRIVER != 3
+#error "This file should only be used with GENERIC_GIC_DRIVER=3"
+#endif
 
 /* The GICv3 driver only needs to be initialized in EL3 */
-static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
 
 /* Default GICR base address to be used for GICR probe. */
 static const uintptr_t gicr_base_addrs[2] = {
@@ -79,7 +72,7 @@
 	return plat_arm_calc_core_pos(mpidr);
 }
 
-static const gicv3_driver_data_t arm_gic_data __unused = {
+gicv3_driver_data_t gic_data __unused = {
 	.gicd_base = PLAT_ARM_GICD_BASE,
 	.gicr_base = 0U,
 	.interrupt_props = arm_interrupt_props,
@@ -101,49 +94,29 @@
 	gicr_frames = plat_gicr_frames;
 }
 
-void __init plat_arm_gic_driver_init(void)
-{
-	/*
-	 * The GICv3 driver is initialized in EL3 and does not need
-	 * to be initialized again in SEL1. This is because the S-EL1
-	 * can use GIC system registers to manage interrupts and does
-	 * not need GIC interface base addresses to be configured.
-	 */
-#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
-	(defined(__aarch64__) && defined(IMAGE_BL31))
-	gicv3_driver_init(&arm_gic_data);
-
-	if (gicv3_rdistif_probe(gicr_base_addrs[0]) == -1) {
-		ERROR("No GICR base frame found for Primary CPU\n");
-		panic();
-	}
-#endif
-}
-
 /******************************************************************************
  * ARM common helper to initialize the GIC. Only invoked by BL31
  *****************************************************************************/
-void __init plat_arm_gic_init(void)
+void __init gic_init(unsigned int cpu_idx)
 {
+	gicv3_driver_init(&gic_data);
 	gicv3_distif_init();
-	gicv3_rdistif_init(plat_my_core_pos());
-	gicv3_cpuif_enable(plat_my_core_pos());
 }
 
 /******************************************************************************
  * ARM common helper to enable the GIC CPU interface
  *****************************************************************************/
-void plat_arm_gic_cpuif_enable(void)
+void gic_cpuif_enable(unsigned int cpu_idx)
 {
-	gicv3_cpuif_enable(plat_my_core_pos());
+	gicv3_cpuif_enable(cpu_idx);
 }
 
 /******************************************************************************
  * ARM common helper to disable the GIC CPU interface
  *****************************************************************************/
-void plat_arm_gic_cpuif_disable(void)
+void gic_cpuif_disable(unsigned int cpu_idx)
 {
-	gicv3_cpuif_disable(plat_my_core_pos());
+	gicv3_cpuif_disable(cpu_idx);
 }
 
 /******************************************************************************
@@ -151,7 +124,7 @@
  * corresponding per-cpu redistributor frame as well as initialize the
  * corresponding interface in GICv3.
  *****************************************************************************/
-void plat_arm_gic_pcpu_init(void)
+void gic_pcpu_init(unsigned int cpu_idx)
 {
 	int result;
 	const uintptr_t *plat_gicr_frames = gicr_frames;
@@ -170,26 +143,22 @@
 		ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
 		panic();
 	}
-	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_rdistif_init(cpu_idx);
 }
 
 /******************************************************************************
  * ARM common helpers to power GIC redistributor interface
  *****************************************************************************/
-void plat_arm_gic_redistif_on(void)
+void gic_pcpu_off(unsigned int cpu_idx)
 {
-	gicv3_rdistif_on(plat_my_core_pos());
-}
-
-void plat_arm_gic_redistif_off(void)
-{
-	gicv3_rdistif_off(plat_my_core_pos());
+	gicv3_rdistif_off(cpu_idx);
 }
 
 /******************************************************************************
- * ARM common helper to save & restore the GICv3 on resume from system suspend
+ * Common helper to save & restore the GICv3 on resume from system suspend. It
+ * is the platform's responsibility to call these.
  *****************************************************************************/
-void plat_arm_gic_save(void)
+void gic_save(void)
 {
 	gicv3_redist_ctx_t * const rdist_context =
 			(gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
@@ -222,7 +191,7 @@
 	 */
 }
 
-void plat_arm_gic_resume(void)
+void gic_resume(void)
 {
 	const gicv3_redist_ctx_t *rdist_context =
 			(gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
diff --git a/drivers/measured_boot/event_log/event_handoff.c b/drivers/measured_boot/event_log/event_handoff.c
new file mode 100644
index 0000000..238ea27
--- /dev/null
+++ b/drivers/measured_boot/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/drivers/measured_boot/event_log/event_log.c b/drivers/measured_boot/event_log/event_log.c
index 6f2898d..761ff29 100644
--- a/drivers/measured_boot/event_log/event_log.c
+++ b/drivers/measured_boot/event_log/event_log.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,12 +7,9 @@
 #include <assert.h>
 #include <errno.h>
 #include <string.h>
-#include <arch_helpers.h>
 
-#include <common/bl_common.h>
-#include <common/debug.h>
-#include <drivers/auth/crypto_mod.h>
-#include <drivers/measured_boot/event_log/event_log.h>
+#include "crypto_mod.h"
+#include "event_log.h"
 
 #if TPM_ALG_ID == TPM_ALG_SHA512
 #define	CRYPTO_MD_ID	CRYPTO_MD_SHA512
@@ -75,34 +72,25 @@
 	}
 };
 
-/*
- * Record a measurement as a TCG_PCR_EVENT2 event
- *
- * @param[in] hash		Pointer to hash data of TCG_DIGEST_SIZE bytes
- * @param[in] event_type	Type of Event, Various Event Types are
- * 				mentioned in tcg.h header
- * @param[in] metadata_ptr	Pointer to event_log_metadata_t structure
- *
- * There must be room for storing this new event into the event log buffer.
- */
-void event_log_record(const uint8_t *hash, uint32_t event_type,
+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;
 
-	assert(hash != NULL);
-	assert(metadata_ptr != NULL);
 	/* event_log_buf_init() must have been called prior to this. */
-	assert(log_ptr != NULL);
+	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 */
-	assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) <
-	       log_end);
+	if (((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) > log_end) {
+		return -ENOMEM;
+	}
 
 	/*
 	 * As per TCG specifications, firmware components that are measured
@@ -145,38 +133,42 @@
 	/* End of event data */
 	log_ptr = (uint8_t *)((uintptr_t)ptr +
 			offsetof(event2_data_t, event) + name_len);
+
+	return 0;
 }
 
-void event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+int event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish)
 {
-	assert(event_log_start != NULL);
-	assert(event_log_finish > event_log_start);
+	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;
 }
 
-/*
- * Initialise Event Log global variables, used during the recording
- * of various payload measurements into the Event Log buffer
- *
- * @param[in] event_log_start		Base address of Event Log buffer
- * @param[in] event_log_finish		End address of Event Log buffer,
- * 					it is a first byte past end of the
- * 					buffer
- */
-void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+int event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish)
 {
-	event_log_buf_init(event_log_start, event_log_finish);
+	return event_log_buf_init(event_log_start, event_log_finish);
 }
 
-void event_log_write_specid_event(void)
+int event_log_write_specid_event(void)
 {
-	void *ptr = log_ptr;
+	void *ptr;
 
 	/* event_log_buf_init() must have been called prior to this. */
-	assert(log_ptr != NULL);
-	assert(((uintptr_t)log_ptr + ID_EVENT_SIZE) < log_end);
+	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
@@ -199,21 +191,26 @@
 	((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;
 }
 
-/*
- * Initialises Event Log by writing Specification ID and
- * Startup Locality events
- */
-void event_log_write_header(void)
+int event_log_write_header(void)
 {
 	const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
 	void *ptr;
+	int rc;
 
-	event_log_write_specid_event();
+	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;
-	assert(((uintptr_t)log_ptr + LOC_EVENT_SIZE) < log_end);
 
 	/*
 	 * The Startup Locality event should be placed in the log before
@@ -250,6 +247,8 @@
 	 */
 	((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,
@@ -260,18 +259,6 @@
 				    (void *)data_base, data_size, hash_data);
 }
 
-/*
- * Calculate and write hash of image, configuration data, etc.
- * to Event Log.
- *
- * @param[in] data_base		Address of data
- * @param[in] data_size		Size of data
- * @param[in] data_id		Data ID
- * @param[in] metadata_ptr	Event Log metadata
- * @return:
- *	0 = success
- *    < 0 = error
- */
 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)
@@ -279,14 +266,18 @@
 	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
 	int rc;
 
-	assert(metadata_ptr != NULL);
+	if (metadata_ptr == NULL) {
+		return -EINVAL;
+	}
 
 	/* Get the metadata associated with this image. */
-	while ((metadata_ptr->id != EVLOG_INVALID_ID) &&
-		(metadata_ptr->id != data_id)) {
+	while (metadata_ptr->id != data_id) {
+		if (metadata_ptr->id == EVLOG_INVALID_ID) {
+			return -EINVAL;
+		}
+
 		metadata_ptr++;
 	}
-	assert(metadata_ptr->id != EVLOG_INVALID_ID);
 
 	/* Measure the payload with algorithm selected by EventLog driver */
 	rc = event_log_measure(data_base, data_size, hash_data);
@@ -294,18 +285,14 @@
 		return rc;
 	}
 
-	event_log_record(hash_data, EV_POST_CODE, metadata_ptr);
+	rc = event_log_record(hash_data, EV_POST_CODE, metadata_ptr);
+	if (rc != 0) {
+		return rc;
+	}
 
 	return 0;
 }
 
-/*
- * Get current Event Log buffer size i.e. used space of Event Log buffer
- *
- * @param[in]  event_log_start		Base Pointer to Event Log buffer
- *
- * @return: current Size of Event Log buffer
- */
 size_t event_log_get_cur_size(uint8_t *event_log_start)
 {
 	assert(event_log_start != NULL);
diff --git a/drivers/measured_boot/event_log/event_log.mk b/drivers/measured_boot/event_log/event_log.mk
index 9e0d6c4..09c15da 100644
--- a/drivers/measured_boot/event_log/event_log.mk
+++ b/drivers/measured_boot/event_log/event_log.mk
@@ -4,6 +4,8 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+EVENT_LOG_SRC_DIR	:= drivers/measured_boot/event_log/
+
 # Default log level to dump the event log (LOG_LEVEL_INFO)
 EVENT_LOG_LEVEL         ?= 40
 
@@ -40,7 +42,13 @@
         EVENT_LOG_LEVEL \
 )))
 
-EVENT_LOG_SRC_DIR	:= drivers/measured_boot/event_log/
+INCLUDES		+= -Iinclude/drivers/measured_boot/event_log \
+				-Iinclude/drivers/auth
 
 EVENT_LOG_SOURCES	:= ${EVENT_LOG_SRC_DIR}event_log.c		\
 			   ${EVENT_LOG_SRC_DIR}event_print.c
+
+
+ifeq (${TRANSFER_LIST}, 1)
+EVENT_LOG_SOURCES	+= ${EVENT_LOG_SRC_DIR}/event_handoff.c
+endif
diff --git a/drivers/measured_boot/event_log/event_print.c b/drivers/measured_boot/event_log/event_print.c
index 1390427..234a694 100644
--- a/drivers/measured_boot/event_log/event_print.c
+++ b/drivers/measured_boot/event_log/event_print.c
@@ -4,21 +4,28 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
 #include <string.h>
 
 #include <common/debug.h>
-#include <drivers/measured_boot/event_log/event_log.h>
+#include "event_log.h"
 
-#if LOG_LEVEL >= EVENT_LOG_LEVEL
-
-/*
- * Print TCG_EfiSpecIDEventStruct
+/**
+ * Print a TCG_EfiSpecIDEventStruct entry from the event log.
  *
- * @param[in/out] log_addr	Pointer to Event Log
- * @param[in/out] log_size	Pointer to Event Log size
+ * 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 void event_log_print_id_event(uint8_t **log_addr, size_t *log_size)
+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;
@@ -27,12 +34,11 @@
 	id_event_algorithm_size_t *alg_ptr;
 	uint32_t event_size, number_of_algorithms;
 	size_t digest_len;
-#if ENABLE_ASSERTIONS
 	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
-	bool valid = true;
-#endif
 
-	assert(*log_size >= sizeof(id_event_headers_t));
+	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
@@ -40,10 +46,14 @@
 	 */
 	LOG_EVENT("TCG_EfiSpecIDEvent:\n");
 	LOG_EVENT("  PCRIndex           : %u\n", event->header.pcr_index);
-	assert(event->header.pcr_index == (uint32_t)PCR_0);
+	if (event->header.pcr_index != (uint32_t)PCR_0) {
+		return -EINVAL;
+	}
 
 	LOG_EVENT("  EventType          : %u\n", event->header.event_type);
-	assert(event->header.event_type == EV_NO_ACTION);
+	if (event->header.event_type != EV_NO_ACTION) {
+		return -EINVAL;
+	}
 
 	LOG_EVENT("  Digest             :");
 	for (i = 0U; i < sizeof(event->header.digest); ++i) {
@@ -54,18 +64,12 @@
 			(void)printf("\n");
 			LOG_EVENT("\t\t      :");
 		}
-#if ENABLE_ASSERTIONS
-		if (val != 0U) {
-			valid = false;
-		}
-#endif
 	}
+
 	if ((i & U(0xF)) != 0U) {
 		(void)printf("\n");
 	}
 
-	assert(valid);
-
 	/* EventSize */
 	event_size = event->header.event_size;
 	LOG_EVENT("  EventSize          : %u\n", event_size);
@@ -90,7 +94,9 @@
 
 	/* Size of DigestSizes[] */
 	digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
-	assert(((uintptr_t)alg_ptr + digest_len) <= (uintptr_t)end_ptr);
+	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) {
@@ -110,7 +116,7 @@
 		default:
 			(void)printf("?\n");
 			ERROR("Algorithm 0x%x not found\n", algorithm_id);
-			assert(false);
+			return -ENOENT;
 		}
 
 		LOG_EVENT("       DigestSize    : %u\n",
@@ -119,17 +125,24 @@
 
 	/* Address of VendorInfoSize */
 	info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len);
-	assert((uintptr_t)info_size_ptr <= (uintptr_t)end_ptr);
+	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 */
-	assert(((uintptr_t)info_size_ptr + info_size) <= (uintptr_t)end_ptr);
+	if (((uintptr_t)info_size_ptr + info_size) > (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
 
 	/* Check EventSize */
-	assert(event_size == (sizeof(id_event_struct_t) +
-				digest_len + info_size));
+	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) {
@@ -140,24 +153,33 @@
 
 	*log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
 	*log_addr = info_size_ptr;
+
+	return 0;
 }
 
-/*
- * Print TCG_PCR_EVENT2
+/**
+ * Print a TCG_PCR_EVENT2 entry from the event log.
  *
- * @param[in/out] log_addr	Pointer to Event Log
- * @param[in/out] log_size	Pointer to Event Log size
+ * 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 void event_log_print_pcr_event2(uint8_t **log_addr, size_t *log_size)
+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;
-#if ENABLE_ASSERTIONS
 	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
-#endif
 
-	assert(*log_size >= sizeof(event2_header_t));
+	if (*log_size < sizeof(event2_header_t)) {
+		return -EINVAL;
+	}
 
 	LOG_EVENT("PCR_Event2:\n");
 	LOG_EVENT("  PCRIndex           : %u\n",
@@ -166,16 +188,25 @@
 			((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);
-	assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U));
+	if ((uintptr_t)ptr > (uintptr_t)end_ptr) {
+		return -EFAULT;
+	}
 
 	for (unsigned int i = 0U; i < count; ++i) {
 		/* Check AlgorithmId address */
-		assert(((uintptr_t)ptr +
-			offsetof(tpmt_ha, digest)) <= (uintptr_t)end_ptr);
+		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) {
@@ -193,14 +224,16 @@
 			break;
 		default:
 			(void)printf("?\n");
-			ERROR("Algorithm 0x%x not found\n",
+			printf("Algorithm 0x%x not found\n",
 				((tpmt_ha *)ptr)->algorithm_id);
-			panic();
+			return -ENOENT;
 		}
 
 		/* End of Digest[] */
 		ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
-		assert(((uintptr_t)ptr + sha_size) <= (uintptr_t)end_ptr);
+		if (((uintptr_t)ptr + sha_size) > (uintptr_t)end_ptr) {
+			return -EFAULT;
+		}
 
 		/* Total size of all digests */
 		digests_size += sha_size;
@@ -218,7 +251,10 @@
 	}
 
 	/* TCG_PCR_EVENT2.EventSize */
-	assert(((uintptr_t)ptr + offsetof(event2_data_t, event)) <= (uintptr_t)end_ptr);
+	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);
@@ -227,7 +263,9 @@
 	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
 
 	/* End of TCG_PCR_EVENT2.Event[EventSize] */
-	assert(((uintptr_t)ptr + event_size) <= (uintptr_t)end_ptr);
+	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)) {
@@ -241,25 +279,30 @@
 
 	*log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
 	*log_addr = (uint8_t *)ptr + event_size;
-}
-#endif	/* LOG_LEVEL >= EVENT_LOG_LEVEL */
 
-/*
- * Print Event Log
- *
- * @param[in]	log_addr	Pointer to Event Log
- * @param[in]	log_size	Event Log size
- */
-void event_log_dump(uint8_t *log_addr, size_t log_size)
+	return 0;
+}
+
+int event_log_dump(uint8_t *log_addr, size_t log_size)
 {
-#if LOG_LEVEL >= EVENT_LOG_LEVEL
-	assert(log_addr != NULL);
+	int rc;
+
+	if (log_addr == NULL) {
+		return -EINVAL;
+	}
 
 	/* Print TCG_EfiSpecIDEvent */
-	event_log_print_id_event(&log_addr, &log_size);
+	rc = event_log_print_id_event(&log_addr, &log_size);
+
+	if (rc < 0) {
+		return rc;
+	}
 
 	while (log_size != 0U) {
-		event_log_print_pcr_event2(&log_addr, &log_size);
+		rc = event_log_print_pcr_event2(&log_addr, &log_size);
+		if (rc < 0) {
+			return rc;
+		}
 	}
-#endif
+	return 0;
 }
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index 92182a0..ac9d99a 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -19,7 +19,7 @@
 #define S32CC_DDR_PLL_VCO_FREQ		(1600U * MHZ)
 #define S32CC_DDR_PLL_PHI0_FREQ		(800U * MHZ)
 #define S32CC_PERIPH_DFS_PHI3_FREQ	(800U * MHZ)
-#define S32CC_USDHC_FREQ		(400U * MHZ)
+#define S32CC_USDHC_FREQ		(200U * MHZ)
 
 static int setup_fxosc(void)
 {
diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c
index 387469c..564d29d 100644
--- a/drivers/partition/partition.c
+++ b/drivers/partition/partition.c
@@ -75,11 +75,6 @@
 
 	memcpy(&tmp, mbr_sector + MBR_PRIMARY_ENTRY_OFFSET, sizeof(tmp));
 
-	if (tmp.first_lba != 1) {
-		VERBOSE("MBR header may have an invalid first LBA\n");
-		return -EINVAL;
-	}
-
 	if ((tmp.sector_nums == 0) || (tmp.sector_nums == UINT32_MAX)) {
 		VERBOSE("MBR header entry has an invalid number of sectors\n");
 		return -EINVAL;
@@ -421,6 +416,11 @@
 		goto out;
 	}
 	if (mbr_entry.type == PARTITION_TYPE_GPT) {
+		if (mbr_entry.first_lba != 1U) {
+			VERBOSE("MBR header may have an invalid first LBA\n");
+			return -EINVAL;
+		}
+
 		result = load_primary_gpt(image_handle, mbr_entry.first_lba);
 		if (result != 0) {
 			io_close(image_handle);
diff --git a/fdts/stm32mp151a-prtt1a.dts b/fdts/stm32mp151a-prtt1a.dts
index 9742dcb..d1a8268 100644
--- a/fdts/stm32mp151a-prtt1a.dts
+++ b/fdts/stm32mp151a-prtt1a.dts
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright (C) 2023, Protonic Holland - All Rights Reserved
- * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2024-2025, STMicroelectronics - All Rights Reserved
  * Author: David Jander <david@protonic.nl>
  */
 /dts-v1/;
@@ -71,29 +71,9 @@
 		CLK_MPU_PLL1P
 		CLK_AXI_PLL2P
 		CLK_MCU_PLL3P
-		CLK_PLL12_HSE
-		CLK_PLL3_HSE
-		CLK_PLL4_HSE
 		CLK_RTC_LSI
 		CLK_MCO1_DISABLED
 		CLK_MCO2_DISABLED
-	>;
-
-	st,clkdiv = <
-		1 /*MPU*/
-		0 /*AXI*/
-		0 /*MCU*/
-		1 /*APB1*/
-		1 /*APB2*/
-		1 /*APB3*/
-		1 /*APB4*/
-		2 /*APB5*/
-		23 /*RTC*/
-		0 /*MCO1*/
-		0 /*MCO2*/
-	>;
-
-	st,pkcs = <
 		CLK_CKPER_HSE
 		CLK_FMC_ACLK
 		CLK_QSPI_ACLK
@@ -131,35 +111,76 @@
 		CLK_LPTIM45_LSI
 	>;
 
-	/* VCO = 1300.0 MHz => P = 650 (CPU) */
-	pll1: st,pll@0 {
-		compatible = "st,stm32mp1-pll";
-		reg = <0>;
-		cfg = <2 80 0 0 0 PQR(1,0,0)>;
-		frac = <0x800>;
+	st,clkdiv = <
+		DIV(DIV_MPU, 1)
+		DIV(DIV_AXI, 0)
+		DIV(DIV_MCU, 0)
+		DIV(DIV_APB1, 1)
+		DIV(DIV_APB2, 1)
+		DIV(DIV_APB3, 1)
+		DIV(DIV_APB4, 1)
+		DIV(DIV_APB5, 2)
+		DIV(DIV_RTC, 23)
+		DIV(DIV_MCO1, 0)
+		DIV(DIV_MCO2, 0)
+	>;
+
+	st,pll_vco {
+		pll2_vco_1066Mhz: pll2-vco-1066Mhz {
+			src = <CLK_PLL12_HSE>;
+			divmn = <2 65>;
+			frac = <0x1400>;
+		};
+
+		pll3_vco_417Mhz: pll3-vco-417Mhz {
+			src = <CLK_PLL3_HSE>;
+			divmn = <1 33>;
+			frac = <0x1a04>;
+		};
+
+		pll4_vco_480Mhz: pll4-vco-480Mhz {
+			src = <CLK_PLL4_HSE>;
+			divmn = <1 39>;
+		};
 	};
 
 	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
 	pll2: st,pll@1 {
 		compatible = "st,stm32mp1-pll";
 		reg = <1>;
-		cfg = <2 65 1 0 0 PQR(1,1,1)>;
-		frac = <0x1400>;
+
+		st,pll = <&pll2_cfg1>;
+
+		pll2_cfg1: pll2_cfg1 {
+			st,pll_vco = <&pll2_vco_1066Mhz>;
+			st,pll_div_pqr = <1 0 0>;
+		};
 	};
 
 	/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
 	pll3: st,pll@2 {
 		compatible = "st,stm32mp1-pll";
 		reg = <2>;
-		cfg = <1 33 1 16 36 PQR(1,1,1)>;
-		frac = <0x1a04>;
+
+		st,pll = <&pll3_cfg1>;
+
+		pll3_cfg1: pll3_cfg1 {
+			st,pll_vco = <&pll3_vco_417Mhz>;
+			st,pll_div_pqr = <1 16 36>;
+		};
 	};
 
 	/* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */
 	pll4: st,pll@3 {
 		compatible = "st,stm32mp1-pll";
 		reg = <3>;
-		cfg = <1 39 3 11 4 PQR(1,1,1)>;
+
+		st,pll = <&pll4_cfg1>;
+
+		pll4_cfg1: pll4_cfg1 {
+			st,pll_vco = <&pll4_vco_480Mhz>;
+			st,pll_div_pqr = <3 11 4>;
+		};
 	};
 };
 
diff --git a/fdts/stm32mp153c-lxa-fairytux2-fw-config.dts b/fdts/stm32mp153c-lxa-fairytux2-fw-config.dts
new file mode 100644
index 0000000..9ee09e9
--- /dev/null
+++ b/fdts/stm32mp153c-lxa-fairytux2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp153c-lxa-fairytux2.dts b/fdts/stm32mp153c-lxa-fairytux2.dts
new file mode 100644
index 0000000..0729ae3
--- /dev/null
+++ b/fdts/stm32mp153c-lxa-fairytux2.dts
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */
+/*
+ * Copyright (C) 2020 STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2021 Rouven Czerwinski, Pengutronix
+ * Copyright (C) 2024 Leonard Goehrs, Pengutronix
+ */
+
+/dts-v1/;
+
+#include "stm32mp153.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
+#include "stm32mp15xx-osd32.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+
+/ {
+	model = "Linux Automation GmbH FairyTux 2";
+	compatible = "lxa,stm32mp153c-fairytux-2", "oct,stm32mp15xx-osd32", "st,stm32mp153";
+
+	aliases {
+		mmc1 = &sdmmc2;
+		serial0 = &uart4;
+	};
+
+	chosen {
+		stdout-path = &uart4;
+	};
+
+	led-controller-0 {
+		compatible = "gpio-leds";
+
+		led-0 {
+			label = "fairytux:green:status";
+			gpios = <&gpioa 13 1>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	reg_3v3: regulator_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		vin-supply = <&v3v3>;
+	};
+};
+
+&pinctrl {
+	fairytux_sdmmc2_d47_pins_b: fairytux-sdmmc2-d47-1 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, AF9)>,  /* SDMMC2_D4 */
+				 <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+				 <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */
+				 <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+};
+
+/* VCO = 624 MHz => P = 208, Q = 48, R = 104 */
+&pll3 {
+	st,pll = <&pll3_cfg2>;
+
+	pll3_cfg2: pll3-cfg2 {
+		st,pll_vco = <&pll3_vco_624Mhz>;
+		st,pll_div_pqr = <2 12 5>;
+	};
+};
+
+/* VCO = 750.0 MHz => P = 125, Q = 75, R = 62.5 */
+&pll4 {
+	st,pll = <&pll4_cfg2>;
+
+	pll4_cfg2: pll4-cfg2 {
+		st,pll_vco = <&pll4_vco_750Mhz>;
+		st,pll_div_pqr = <5 9 11>;
+	};
+};
+
+&rcc {
+	/* change parent clocks */
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_MCU_PLL3P
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_DISABLED
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_PLL4P
+		CLK_SDMMC12_PLL3R
+		CLK_DSI_DSIPLL
+		CLK_STGEN_HSE
+		CLK_USBPHY_HSE
+		CLK_SPI2S1_PLL3Q
+		CLK_SPI2S23_PLL3Q
+		CLK_SPI45_HSI
+		CLK_SPI6_HSI
+		CLK_I2C46_HSI
+		CLK_SDMMC3_DISABLED
+		CLK_USBO_USBPHY
+		CLK_ADC_CKPER
+		CLK_CEC_DISABLED
+		CLK_I2C12_HSI
+		CLK_I2C35_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+		CLK_UART35_HSI
+		CLK_UART6_HSI
+		CLK_UART78_HSI
+		CLK_SPDIF_DISABLED
+		CLK_FDCAN_PLL3Q
+		CLK_SAI1_DISABLED
+		CLK_SAI2_DISABLED
+		CLK_SAI3_DISABLED
+		CLK_SAI4_DISABLED
+		CLK_RNG1_LSI
+		CLK_RNG2_LSI
+		CLK_LPTIM1_PCLK1
+		CLK_LPTIM23_PCLK3
+		CLK_LPTIM45_LSE
+	>;
+
+	st,pll_vco {
+		pll3_vco_624Mhz: pll3-vco-624Mhz {
+			src = <CLK_PLL3_HSE>;
+			divmn = <1 51>;
+		};
+
+		pll4_vco_750Mhz: pll4-vco-750Mhz {
+			src = <CLK_PLL4_HSE>;
+			divmn = <3 124>;
+		};
+	};
+};
+
+&sdmmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc2_b4_pins_a &fairytux_sdmmc2_d47_pins_b>;
+	bus-width = <8>;
+	mmc-ddr-3_3v;
+	no-1-8-v;
+	no-sd;
+	no-sdio;
+	non-removable;
+	st,neg-edge;
+	vmmc-supply = <&reg_3v3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_a>;
+	status = "okay";
+};
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
deleted file mode 100644
index fa16dcd..0000000
--- a/fdts/tc2.dts
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-/dts-v1/;
-
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <platform_def.h>
-
-#if TARGET_FLAVOUR_FVP
-#define LIT_CAPACITY			406
-#define MID_CAPACITY			912
-#else /* TARGET_FLAVOUR_FPGA */
-#define LIT_CAPACITY			280
-#define MID_CAPACITY			775
-/* this is an area optimized configuration of the big core */
-#define BIG2_CAPACITY			930
-#endif /* TARGET_FLAVOUR_FPGA */
-#define BIG_CAPACITY			1024
-
-#define MHU_TX_ADDR			45000000 /* hex */
-#define MHU_TX_COMPAT			"arm,mhuv2-tx","arm,primecell"
-#define MHU_TX_INT_NAME			"mhu_tx"
-
-#define MHU_RX_ADDR			45010000 /* hex */
-#define MHU_RX_COMPAT			"arm,mhuv2-rx","arm,primecell"
-#define MHU_OFFSET			0x1000
-#define MHU_MBOX_CELLS			2
-#define MHU_RX_INT_NUM			317
-#define MHU_RX_INT_NAME			"mhu_rx"
-
-#define LIT_CPU_PMU_COMPATIBLE		"arm,cortex-a520-pmu"
-#define MID_CPU_PMU_COMPATIBLE		"arm,cortex-a720-pmu"
-#define BIG_CPU_PMU_COMPATIBLE		"arm,cortex-x4-pmu"
-
-#define DSU_MPAM_ADDR			0x1 0x00010000 /* 0x1_0001_0000 */
-
-#define DPU_ADDR			2cc00000
-#define DPU_IRQ				69
-
-#define ETHERNET_ADDR			18000000
-#define ETHERNET_INT			109
-
-#define SYS_REGS_ADDR			1c010000
-
-#define MMC_ADDR			1c050000
-#define MMC_INT_0			107
-#define MMC_INT_1			108
-
-#define RTC_ADDR			1c170000
-#define RTC_INT				100
-
-#define KMI_0_ADDR			1c060000
-#define KMI_0_INT			197
-#define KMI_1_ADDR			1c070000
-#define KMI_1_INT			103
-
-#define VIRTIO_BLOCK_ADDR		1c130000
-#define VIRTIO_BLOCK_INT		204
-
-#include "tc-common.dtsi"
-#if TARGET_FLAVOUR_FVP
-#include "tc-fvp.dtsi"
-#else
-#include "tc-fpga.dtsi"
-#endif /* TARGET_FLAVOUR_FVP */
-#include "tc-base.dtsi"
-
-/ {
-	cpus {
-#if TARGET_FLAVOUR_FPGA
-		cpu-map {
-			cluster0 {
-				core8 {
-					cpu = <&CPU8>;
-				};
-				core9 {
-					cpu = <&CPU9>;
-				};
-				core10 {
-					cpu = <&CPU10>;
-				};
-				core11 {
-					cpu = <&CPU11>;
-				};
-				core12 {
-					cpu = <&CPU12>;
-				};
-				core13 {
-					cpu = <&CPU13>;
-				};
-			};
-		};
-#endif
-
-		CPU2:cpu@200 {
-			clocks = <&scmi_dvfs 0>;
-			capacity-dmips-mhz = <LIT_CAPACITY>;
-		};
-
-		CPU3:cpu@300 {
-			clocks = <&scmi_dvfs 0>;
-			capacity-dmips-mhz = <LIT_CAPACITY>;
-		};
-
-		CPU6:cpu@600 {
-			clocks = <&scmi_dvfs 1>;
-			capacity-dmips-mhz = <MID_CAPACITY>;
-		};
-
-		CPU7:cpu@700 {
-			clocks = <&scmi_dvfs 1>;
-			capacity-dmips-mhz = <MID_CAPACITY>;
-		};
-
-#if TARGET_FLAVOUR_FPGA
-		CPU8:cpu@800 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x800>;
-			enable-method = "psci";
-			clocks = <&scmi_dvfs 1>;
-			capacity-dmips-mhz = <MID_CAPACITY>;
-		};
-
-		CPU9:cpu@900 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x900>;
-			enable-method = "psci";
-			clocks = <&scmi_dvfs 2>;
-			capacity-dmips-mhz = <BIG2_CAPACITY>;
-		};
-
-		CPU10:cpu@A00 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0xA00>;
-			enable-method = "psci";
-			clocks = <&scmi_dvfs 2>;
-			capacity-dmips-mhz = <BIG2_CAPACITY>;
-		};
-
-		CPU11:cpu@B00 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0xB00>;
-			enable-method = "psci";
-			clocks = <&scmi_dvfs 2>;
-			capacity-dmips-mhz = <BIG2_CAPACITY>;
-		};
-
-		CPU12:cpu@C00 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0xC00>;
-			enable-method = "psci";
-			clocks = <&scmi_dvfs 3>;
-			capacity-dmips-mhz = <BIG_CAPACITY>;
-		};
-
-		CPU13:cpu@D00 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0xD00>;
-			enable-method = "psci";
-			clocks = <&scmi_dvfs 3>;
-			capacity-dmips-mhz = <BIG_CAPACITY>;
-		};
-#endif
-	};
-
-#if TARGET_FLAVOUR_FPGA
-	ete8 {
-		compatible = "arm,embedded-trace-extension";
-		cpu = <&CPU8>;
-	};
-
-	ete9 {
-		compatible = "arm,embedded-trace-extension";
-		cpu = <&CPU9>;
-	};
-
-	ete10 {
-		compatible = "arm,embedded-trace-extension";
-		cpu = <&CPU10>;
-	};
-
-	ete11 {
-		compatible = "arm,embedded-trace-extension";
-		cpu = <&CPU11>;
-	};
-
-	ete12 {
-		compatible = "arm,embedded-trace-extension";
-		cpu = <&CPU12>;
-	};
-
-	ete13 {
-		compatible = "arm,embedded-trace-extension";
-		cpu = <&CPU13>;
-	};
-#endif /* TARGET_FLAVOUR_FPGA */
-
-	cmn-pmu {
-		compatible = "arm,ci-700";
-		reg = <0x0 0x50000000 0x0 0x10000000>;
-		interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH 0>;
-	};
-
-	mbox_db_rx: mhu@MHU_RX_ADDR {
-		arm,mhuv2-protocols = <0 1>;
-	};
-
-	mbox_db_tx: mhu@MHU_TX_ADDR {
-		arm,mhuv2-protocols = <0 1>;
-	};
-
-	firmware {
-		/*
-		 * TC2 does not have a P2A channel, but wiring one was needed to make Linux work
-		 * (by chance). At the time the SCMI driver did not support bidirectional
-		 * mailboxes so as a workaround, the A2P channel was wired for TX communication
-		 * and the synchronous replies would be read asyncrhonously as if coming from
-		 * the P2A channel, while being the actual A2P channel.
-		 *
-		 * This will not work with kernels > 5.15, but keep it around to keep TC2
-		 * working with its target kernel. Newer kernels will still work, but SCMI
-		 * won't as they check that the two regions are distinct.
-		 */
-		scmi {
-			mboxes = <&mbox_db_tx 0 0 &mbox_db_rx 0 0>;
-			shmem = <&cpu_scp_scmi_a2p &cpu_scp_scmi_a2p>;
-		};
-	};
-
-	gic: interrupt-controller@GIC_CTRL_ADDR {
-		ppi-partitions {
-			ppi_partition_little: interrupt-partition-0 {
-				affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>;
-			};
-
-#if TARGET_FLAVOUR_FVP
-			ppi_partition_mid: interrupt-partition-1 {
-				affinity = <&CPU4>, <&CPU5>, <&CPU6>;
-			};
-
-			ppi_partition_big: interrupt-partition-2 {
-				affinity = <&CPU7>;
-			};
-#elif TARGET_FLAVOUR_FPGA
-			ppi_partition_mid: interrupt-partition-1 {
-				affinity = <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>, <&CPU8>;
-			};
-
-			ppi_partition_big: interrupt-partition-2 {
-				affinity = <&CPU9>, <&CPU10>, <&CPU11>, <&CPU12>, <&CPU13>;
-			};
-#endif
-		};
-	};
-
-	spe-pmu-big {
-		status = "okay";
-	};
-
-	smmu_700: iommu@3f000000 {
-		status = "okay";
-	};
-
-	dp0: display@DPU_ADDR {
-#if TC_SCMI_PD_CTRL_EN
-		power-domains = <&scmi_devpd (PLAT_MAX_CPUS_PER_CLUSTER + 2)>;
-#endif
-		iommus = <&smmu_700 0x100>;
-	};
-
-	gpu: gpu@2d000000 {
-		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>,
-			     <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>,
-			     <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
-		interrupt-names = "JOB", "MMU", "GPU";
-		iommus = <&smmu_700 0x200>;
-	};
-};
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index 243ac15..47a2659 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -204,5 +204,9 @@
 static inline bool is_feat_ls64_accdata_present(void) { return false; }
 __attribute__((always_inline))
 static inline bool is_feat_mops_supported(void) { return false; }
+__attribute__((always_inline))
+static inline bool is_feat_bti_supported(void) { return false; }
+__attribute__((always_inline))
+static inline bool is_feat_pauth_supported(void) { return false; }
 
 #endif /* ARCH_FEATURES_H */
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 3707520..77660b7 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -251,7 +251,7 @@
 #define ID_AA64DFR0_PMUVER_SHIFT	U(8)
 #define ID_AA64DFR0_PMUVER_MASK		U(0xf)
 #define ID_AA64DFR0_PMUVER_PMUV3	U(1)
-#define ID_AA64DFR0_PMUVER_PMUV3P8	U(8)
+#define ID_AA64DFR0_PMUVER_PMUV3P9	U(9)
 #define ID_AA64DFR0_PMUVER_IMP_DEF	U(0xf)
 
 /* ID_AA64DFR0_EL1.SEBEP definitions */
@@ -606,6 +606,11 @@
 #define SCTLR_EPAN_BIT		(ULL(1) << 57)
 #define SCTLR_RESET_VAL		SCTLR_EL3_RES1
 
+#define SCTLR2_EnPACM_BIT	(ULL(1) << 7)
+
+/* SCTLR2 currently has no RES1 fields so reset to 0 */
+#define SCTLR2_RESET_VAL	ULL(0)
+
 /* CPACR_EL1 definitions */
 #define CPACR_EL1_FPEN(x)	((x) << 20)
 #define CPACR_EL1_FP_TRAP_EL0	UL(0x1)
@@ -696,6 +701,7 @@
 #define MDCR_NSPBE_BIT		(ULL(1) << 11)
 #define MDCR_TDOSA_BIT		(ULL(1) << 10)
 #define MDCR_TDA_BIT		(ULL(1) << 9)
+#define MDCR_EnPM2_BIT		(ULL(1) << 7)
 #define MDCR_TPM_BIT		(ULL(1) << 6)
 #define MDCR_RLTE_BIT		(ULL(1) << 0)
 #define MDCR_EL3_RESET_VAL	MDCR_MTPME_BIT
@@ -855,6 +861,7 @@
 #define SPSR_PPEND_BIT		BIT(33)
 #define SPSR_EXLOCK_BIT_AARCH64	BIT_64(34)
 #define SPSR_NZCV		(SPSR_V_BIT | SPSR_C_BIT | SPSR_Z_BIT | SPSR_N_BIT)
+#define SPSR_PACM_BIT_AARCH64	BIT_64(35)
 
 #define DISABLE_ALL_EXCEPTIONS \
 		(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT)
@@ -1531,6 +1538,7 @@
 /*******************************************************************************
  * FEAT_SCTLR2 - Extension to SCTLR_ELx Registers
  ******************************************************************************/
+#define SCTLR2_EL3		S3_6_C1_C0_3
 #define SCTLR2_EL2		S3_4_C1_C0_3
 #define SCTLR2_EL1		S3_0_C1_C0_3
 
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 43ff2cc..757ce06 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -146,6 +146,8 @@
  * +----------------------------+
  * |	FEAT_MOPS		|
  * +----------------------------+
+ * |	FEAT_PAUTH_LR		|
+ * +----------------------------+
  */
 
 __attribute__((always_inline))
@@ -176,9 +178,9 @@
 			((ID_AA64ISAR2_GPA3_MASK << ID_AA64ISAR2_GPA3_SHIFT) |
 			(ID_AA64ISAR2_APA3_MASK << ID_AA64ISAR2_APA3_SHIFT)), 1U)
 
-/* PAUTH */
+/* FEAT_PAUTH: Pointer Authentication */
 __attribute__((always_inline))
-static inline bool is_armv8_3_pauth_present(void)
+static inline bool is_feat_pauth_present(void)
 {
 	uint64_t mask_id_aa64isar1 =
 		(ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) |
@@ -193,14 +195,45 @@
 	return ((read_id_aa64isar1_el1() & mask_id_aa64isar1) != 0U ||
 		is_feat_pacqarma3_present());
 }
+CREATE_FEATURE_SUPPORTED(feat_pauth, is_feat_pauth_present, ENABLE_PAUTH)
+CREATE_FEATURE_SUPPORTED(ctx_pauth, is_feat_pauth_present, CTX_INCLUDE_PAUTH_REGS)
+
+/*
+ * FEAT_PAUTH_LR
+ * This feature has a non-standard discovery method so define this function
+ * manually then call use the CREATE_FEATURE_SUPPORTED macro with it. This
+ * feature is enabled with ENABLE_PAUTH when present.
+ */
+__attribute__((always_inline))
+static inline bool is_feat_pauth_lr_present(void)
+{
+	/*
+	 * FEAT_PAUTH_LR support is indicated by up to 3 fields, if one or more
+	 * of these is 0b0110 then the feature is present.
+	 *   1) id_aa64isr1_el1.api
+	 *   2) id_aa64isr1_el1.apa
+	 *   3) id_aa64isr2_el1.apa3
+	 */
+	if (ISOLATE_FIELD(read_id_aa64isar1_el1(), ID_AA64ISAR1_API_SHIFT, ID_AA64ISAR1_API_MASK) == 0b0110) {
+		return true;
+	}
+	if (ISOLATE_FIELD(read_id_aa64isar1_el1(), ID_AA64ISAR1_APA_SHIFT, ID_AA64ISAR1_APA_MASK) == 0b0110) {
+		return true;
+	}
+	if (ISOLATE_FIELD(read_id_aa64isar2_el1(), ID_AA64ISAR2_APA3_SHIFT, ID_AA64ISAR2_APA3_MASK) == 0b0110) {
+		return true;
+	}
+	return false;
+}
+CREATE_FEATURE_SUPPORTED(feat_pauth_lr, is_feat_pauth_lr_present, ENABLE_FEAT_PAUTH_LR)
 
 /* FEAT_TTST: Small translation tables */
 CREATE_FEATURE_PRESENT(feat_ttst, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_ST_SHIFT,
 			ID_AA64MMFR2_EL1_ST_MASK, 1U)
 
 /* FEAT_BTI: Branch target identification */
-CREATE_FEATURE_PRESENT(feat_bti, id_aa64pfr1_el1, ID_AA64PFR1_EL1_BT_SHIFT,
-			ID_AA64PFR1_EL1_BT_MASK, BTI_IMPLEMENTED)
+CREATE_FEATURE_FUNCS(feat_bti, id_aa64pfr1_el1, ID_AA64PFR1_EL1_BT_SHIFT,
+			ID_AA64PFR1_EL1_BT_MASK, BTI_IMPLEMENTED, ENABLE_BTI)
 
 /* FEAT_MTE2: Memory tagging extension */
 CREATE_FEATURE_FUNCS(feat_mte2, id_aa64pfr1_el1, ID_AA64PFR1_EL1_MTE_SHIFT,
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 569182a..c885424 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -238,7 +238,14 @@
 /*******************************************************************************
  * Strip Pointer Authentication Code
  ******************************************************************************/
-DEFINE_SYSOP_PARAM_FUNC(xpaci)
+static inline u_register_t xpaci(u_register_t arg)
+{
+	__asm__ (".arch armv8.3-a\n"
+		 "xpaci %0\n"
+		 : "+r" (arg));
+
+	return arg;
+}
 
 void flush_dcache_range(uintptr_t addr, size_t size);
 void flush_dcache_to_popa_range(uintptr_t addr, size_t size);
@@ -725,6 +732,7 @@
 /* FEAT_SCTLR2 Registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el1, SCTLR2_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el2, SCTLR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el3, SCTLR2_EL3)
 
 /* FEAT_LS64_ACCDATA Registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(accdata_el1, ACCDATA_EL1)
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index dce07d9..8f1651d 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -230,7 +230,7 @@
 	 */
 	.macro	read reg:req
 #if ENABLE_BTI
-	bti	j
+	BTI	j
 #endif
 	mrs	x0, \reg
 	ret
@@ -241,7 +241,7 @@
 	 */
 	.macro	write reg:req
 #if ENABLE_BTI
-	bti	j
+	BTI	j
 #endif
 	msr	\reg, x1
 	ret
@@ -329,7 +329,7 @@
 	.endm
 
 	/*
-	* is_feat_sysreg128_present_asm - Set flags and reg if FEAT_SYSREG128
+	* is_feat_XYZ_present_asm - Set flags and reg if FEAT_XYZ
 	* is enabled at runtime.
 	*
 	* Arguments:
@@ -342,6 +342,20 @@
 	ands	\reg, \reg, #(ID_AA64ISAR2_SYSREG128_MASK << ID_AA64ISAR2_SYSREG128_SHIFT)
 	.endm
 
+	.macro is_feat_pauth_present_asm reg:req, clobber:req
+	mrs	\reg, ID_AA64ISAR1_EL1
+	mov_imm	\clobber, ((ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) \
+			 | (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) \
+			 | (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) \
+			 | (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT))
+	tst	\reg, \clobber
+	.endm
+
+	.macro is_feat_sctlr2_present_asm reg:req
+	mrs	\reg, ID_AA64MMFR3_EL1
+	ands	\reg, \reg, #(ID_AA64MMFR3_EL1_SCTLR2_MASK << ID_AA64MMFR3_EL1_SCTLR2_SHIFT)
+	.endm
+
 .macro call_reset_handler
 #if !(defined(IMAGE_BL2) && ENABLE_RME)
 	/* ---------------------------------------------------------------------
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 2f2aeaf..fce0f2c 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -32,14 +32,29 @@
 	 *  load or store one or more registers have an alignment check that the
 	 *  address being accessed is aligned to the size of the data element(s)
 	 *  being accessed.
+	 *
+	 * SCTLR_EL3.BT: PAuth instructions are compatible with bti jc
 	 * ---------------------------------------------------------------------
 	 */
-	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
+	mov_imm	x1, (SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el3
+#if ENABLE_BTI
+	bic	x0, x0, #SCTLR_BT_BIT
+#endif
 	orr	x0, x0, x1
 	msr	sctlr_el3, x0
 	isb
 
+#if ENABLE_FEAT_SCTLR2
+#if ENABLE_FEAT_SCTLR2 > 1
+	is_feat_sctlr2_present_asm x1
+	beq	feat_sctlr2_not_supported\@
+#endif
+	mov	x1, #SCTLR2_RESET_VAL
+	msr	SCTLR2_EL3, x1
+feat_sctlr2_not_supported\@:
+#endif
+
 #ifdef IMAGE_BL31
 	/* ---------------------------------------------------------------------
 	 * Initialise the per-cpu cache pointer to the CPU.
diff --git a/include/bl32/tsp/platform_tsp.h b/include/bl32/tsp/platform_tsp.h
index fe8a2c9..81a1a40 100644
--- a/include/bl32/tsp/platform_tsp.h
+++ b/include/bl32/tsp/platform_tsp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +10,8 @@
 /*******************************************************************************
  * Mandatory TSP functions (only if platform contains a TSP)
  ******************************************************************************/
-void tsp_early_platform_setup(void);
+void tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3);
 void tsp_plat_arch_setup(void);
 void tsp_platform_setup(void);
 
diff --git a/include/bl32/tsp/tsp.h b/include/bl32/tsp/tsp.h
index a63abf1..bc152e5 100644
--- a/include/bl32/tsp/tsp.h
+++ b/include/bl32/tsp/tsp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -106,7 +106,8 @@
 	tsp_vector_isn_t abort_yield_smc_entry;
 } tsp_vectors_t;
 
-void tsp_setup(void);
+void tsp_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
+	       u_register_t arg3);
 
 #endif /* __ASSEMBLER__ */
 
diff --git a/include/common/asm_macros_common.S b/include/common/asm_macros_common.S
index fd0ea81..9172b55 100644
--- a/include/common/asm_macros_common.S
+++ b/include/common/asm_macros_common.S
@@ -7,6 +7,20 @@
 #define ASM_MACROS_COMMON_S
 
 	/*
+	 * Provide a wrapper for the "bti" instructions using the more
+	 * compatible "hint" encoding, otherwise older toolchains would reject
+	 * this when not compiled for a BTI capable machine (-march=armv8.5-a).
+	 */
+	.macro	BTI _targets
+	.ifc	\_targets, j
+	hint	#36
+	.endif
+	.ifc	\_targets, jc
+	hint	#38
+	.endif
+	.endm
+
+	/*
 	 * This macro is used to create a function label and place the
 	 * code into a separate text section based on the function name
 	 * to enable elimination of unused code during linking. It also adds
@@ -42,7 +56,7 @@
 	/* When Branch Target Identification is enabled, insert "bti jc"
 	 * instruction to enable indirect calls and branches
 	 */
-	 bti	jc
+	BTI	jc
 #endif
 	.endm
 
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 2f065ec..db4bb9a 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -199,8 +199,6 @@
 void setup_page_tables(const struct mmap_region *bl_regions,
 			   const struct mmap_region *plat_regions);
 
-void bl_handle_pauth(void);
-
 #endif /*__ASSEMBLER__*/
 
 #endif /* BL_COMMON_H */
diff --git a/include/common/feat_detect.h b/include/common/feat_detect.h
index b85e1ce..18e6c42 100644
--- a/include/common/feat_detect.h
+++ b/include/common/feat_detect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,5 @@
 #define FEAT_STATE_DISABLED		0
 #define FEAT_STATE_ALWAYS		1
 #define FEAT_STATE_CHECK		2
-#define FEAT_STATE_CHECK_ASYMMETRIC	3
 
 #endif /* FEAT_DETECT_H */
diff --git a/include/drivers/arm/gic.h b/include/drivers/arm/gic.h
new file mode 100644
index 0000000..e98737a
--- /dev/null
+++ b/include/drivers/arm/gic.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef GIC_H
+#define GIC_H
+/* the function names conflict with some platform implementations. */
+#if USE_GIC_DRIVER
+void gic_init(unsigned int cpu_idx);
+void gic_cpuif_enable(unsigned int cpu_idx);
+void gic_cpuif_disable(unsigned int cpu_idx);
+void gic_pcpu_off(unsigned int cpu_idx);
+void gic_pcpu_init(unsigned int cpu_idx);
+void gic_save(void);
+void gic_resume(void);
+#endif
+#endif /* GIC_H */
diff --git a/include/drivers/measured_boot/event_log/event_handoff.h b/include/drivers/measured_boot/event_log/event_handoff.h
new file mode 100644
index 0000000..e969d1f
--- /dev/null
+++ b/include/drivers/measured_boot/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/drivers/measured_boot/event_log/event_log.h b/include/drivers/measured_boot/event_log/event_log.h
index 18abadf..b5adfdc 100644
--- a/include/drivers/measured_boot/event_log/event_log.h
+++ b/include/drivers/measured_boot/event_log/event_log.h
@@ -7,12 +7,12 @@
 #ifndef EVENT_LOG_H
 #define EVENT_LOG_H
 
+#include <stddef.h>
 #include <stdint.h>
 
-#include <common/debug.h>
-#include <common/tbbr/tbbr_img_def.h>
 #include <drivers/auth/crypto_mod.h>
-#include <drivers/measured_boot/event_log/tcg.h>
+#include "event_handoff.h"
+#include "tcg.h"
 
 /*
  * Set Event Log debug level to one of:
@@ -33,7 +33,7 @@
 #elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
 #define	LOG_EVENT	VERBOSE
 #else
-#error "Not supported EVENT_LOG_LEVEL"
+#define LOG_EVENT printf
 #endif
 
 /* Number of hashing algorithms supported */
@@ -65,18 +65,130 @@
 			sizeof(event2_data_t))
 
 /* Functions' declarations */
-void event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish);
-void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish);
-void event_log_write_specid_event(void);
-void event_log_write_header(void);
-void event_log_dump(uint8_t *log_addr, size_t log_size);
-int event_log_measure(uintptr_t data_base, uint32_t data_size,
-		      unsigned char hash_data[CRYPTO_MD_MAX_SIZE]);
-void event_log_record(const uint8_t *hash, uint32_t event_type,
-		      const event_log_metadata_t *metadata_ptr);
+
+/**
+ * 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/drivers/mmc.h b/include/drivers/mmc.h
index e94693d..454a85a 100644
--- a/include/drivers/mmc.h
+++ b/include/drivers/mmc.h
@@ -19,29 +19,29 @@
 
 #define MMC_ACMD(_x)			U(_x)
 
-#define OCR_POWERUP			BIT(31)
-#define OCR_HCS				BIT(30)
-#define OCR_BYTE_MODE			(U(0) << 29)
-#define OCR_SECTOR_MODE			(U(2) << 29)
-#define OCR_ACCESS_MODE_MASK		(U(3) << 29)
-#define OCR_3_5_3_6			BIT(23)
-#define OCR_3_4_3_5			BIT(22)
-#define OCR_3_3_3_4			BIT(21)
-#define OCR_3_2_3_3			BIT(20)
-#define OCR_3_1_3_2			BIT(19)
-#define OCR_3_0_3_1			BIT(18)
-#define OCR_2_9_3_0			BIT(17)
-#define OCR_2_8_2_9			BIT(16)
-#define OCR_2_7_2_8			BIT(15)
-#define OCR_VDD_MIN_2V7			GENMASK(23, 15)
-#define OCR_VDD_MIN_2V0			GENMASK(14, 8)
-#define OCR_VDD_MIN_1V7			BIT(7)
+#define OCR_POWERUP			BIT_32(31U)
+#define OCR_HCS				BIT_32(30U)
+#define OCR_BYTE_MODE			(U(0) << 29U)
+#define OCR_SECTOR_MODE			(U(2) << 29U)
+#define OCR_ACCESS_MODE_MASK		(U(3) << 29U)
+#define OCR_3_5_3_6			BIT_32(23U)
+#define OCR_3_4_3_5			BIT_32(22U)
+#define OCR_3_3_3_4			BIT_32(21U)
+#define OCR_3_2_3_3			BIT_32(20U)
+#define OCR_3_1_3_2			BIT_32(19U)
+#define OCR_3_0_3_1			BIT_32(18U)
+#define OCR_2_9_3_0			BIT_32(17U)
+#define OCR_2_8_2_9			BIT_32(16U)
+#define OCR_2_7_2_8			BIT_32(15U)
+#define OCR_VDD_MIN_2V7			GENMASK_32(23U, 15U)
+#define OCR_VDD_MIN_2V0			GENMASK_32(14U, 8U)
+#define OCR_VDD_MIN_1V7			BIT_32(7U)
 
-#define MMC_RSP_48			BIT(0)
-#define MMC_RSP_136			BIT(1)		/* 136 bit response */
-#define MMC_RSP_CRC			BIT(2)		/* expect valid crc */
-#define MMC_RSP_CMD_IDX			BIT(3)		/* response contains cmd idx */
-#define MMC_RSP_BUSY			BIT(4)		/* device may be busy */
+#define MMC_RSP_48			BIT_32(0U)
+#define MMC_RSP_136			BIT_32(1U)		/* 136 bit response */
+#define MMC_RSP_CRC			BIT_32(2U)		/* expect valid crc */
+#define MMC_RSP_CMD_IDX			BIT_32(3U)		/* response contains cmd idx */
+#define MMC_RSP_BUSY			BIT_32(4U)		/* device may be busy */
 
 /* JEDEC 4.51 chapter 6.12 */
 #define MMC_RESPONSE_R1			(MMC_RSP_48 | MMC_RSP_CMD_IDX | MMC_RSP_CRC)
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index c43beb6..402e07f 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -50,22 +50,6 @@
 	 *	Numeric value expected to read from CPU's MIDR
 	 * _resetfunc:
 	 *	Reset function for the CPU.
-	 * _extra1:
-	 *	This is a placeholder for future per CPU operations.  Currently,
-	 *	some CPUs use this entry to set a test function to determine if
-	 *	the workaround for CVE-2017-5715 needs to be applied or not.
-	 * _extra2:
-	 *	This is a placeholder for future per CPU operations. Currently
-	 *	some CPUs use this entry to set a function to disable the
-	 *	workaround for CVE-2018-3639.
-	 * _extra3:
-	 *	This is a placeholder for future per CPU operations. Currently,
-	 *	some CPUs use this entry to set a test function to determine if
-	 *	the workaround for CVE-2022-23960 needs to be applied or not.
-	 * _extra4:
-	 *	This is a placeholder for future per CPU operations. Currently,
-	 *	some CPUs use this entry to set a test function to determine if
-	 *	the workaround for CVE-2024-7881 needs to be applied or not.
 	 * _e_handler:
 	 *	This is a placeholder for future per CPU exception handlers.
 	 * _power_down_ops:
@@ -78,7 +62,6 @@
 	 *	used to handle power down at subsequent levels
 	 */
 	.macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \
-		_extra1:req, _extra2:req, _extra3:req, _extra4:req, \
 		_e_handler:req, _power_down_ops:vararg
 	.section .cpu_ops, "a"
 	.align 3
@@ -87,10 +70,6 @@
 #if defined(IMAGE_AT_EL3)
 	.quad \_resetfunc
 #endif
-	.quad \_extra1
-	.quad \_extra2
-	.quad \_extra3
-	.quad \_extra4
 	.quad \_e_handler
 #ifdef IMAGE_BL31
 	/* Insert list of functions */
@@ -153,28 +132,13 @@
 
 	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
 		_power_down_ops:vararg
-		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, 0, \
-			\_power_down_ops
+		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, \_power_down_ops
 	.endm
 
 	.macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \
 		_e_handler:req, _power_down_ops:vararg
 		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
-			0, 0, 0, 0, \_e_handler, \_power_down_ops
-	.endm
-
-	.macro declare_cpu_ops_wa _name:req, _midr:req, \
-		_resetfunc:req, _extra1:req, _extra2:req, \
-		_extra3:req, _power_down_ops:vararg
-		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
-			\_extra1, \_extra2, \_extra3, 0, 0, \_power_down_ops
-	.endm
-
-	.macro declare_cpu_ops_wa_4 _name:req, _midr:req, \
-		_resetfunc:req, _extra1:req, _extra2:req, \
-		_extra3:req, _extra4:req, _power_down_ops:vararg
-		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
-			\_extra1, \_extra2, \_extra3, \_extra4, 0, \_power_down_ops
+			\_e_handler, \_power_down_ops
 	.endm
 
 	/*
@@ -240,7 +204,7 @@
  *	Default value is 0.
  */
 .macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _split_wa=0
-#if REPORT_ERRATA || ERRATA_ABI_SUPPORT
+#if INCLUDE_ERRATA_LIST
 	.pushsection .rodata.errata_entries
 		.align	3
 		.ifndef \_cpu\()_errata_list_start
@@ -550,7 +514,7 @@
 	.align \_align
 	\_name:
 #if ENABLE_BTI
-	bti	jc
+	BTI	jc
 #endif
 .endm
 
diff --git a/include/lib/cpus/cpu_ops.h b/include/lib/cpus/cpu_ops.h
index 0b08919..5ba78cf 100644
--- a/include/lib/cpus/cpu_ops.h
+++ b/include/lib/cpus/cpu_ops.h
@@ -22,14 +22,6 @@
 /* The number of CPU operations allowed */
 #define CPU_MAX_PWR_DWN_OPS		2
 
-#if __aarch64__
-#define CPU_NO_EXTRA1_FUNC		0
-#define CPU_NO_EXTRA2_FUNC		0
-#define CPU_NO_EXTRA3_FUNC		0
-#define CPU_NO_EXTRA4_FUNC		0
-#endif /* __aarch64__ */
-
-
 /*
  * Define the sizes of the fields in the cpu_ops structure. Word size is set per
  * Aarch so keep these definitions the same and each can include whatever it
@@ -41,10 +33,6 @@
 #else
 #define CPU_RESET_FUNC_SIZE	0
 #endif /* IMAGE_AT_EL3 */
-#define CPU_EXTRA1_FUNC_SIZE	CPU_WORD_SIZE
-#define CPU_EXTRA2_FUNC_SIZE	CPU_WORD_SIZE
-#define CPU_EXTRA3_FUNC_SIZE	CPU_WORD_SIZE
-#define CPU_EXTRA4_FUNC_SIZE	CPU_WORD_SIZE
 #define CPU_E_HANDLER_FUNC_SIZE CPU_WORD_SIZE
 /* The power down core and cluster is needed only in BL31 and BL32 */
 #if defined(IMAGE_BL31) || defined(IMAGE_BL32)
@@ -86,11 +74,7 @@
 #define CPU_MIDR		0
 #define CPU_RESET_FUNC		CPU_MIDR + CPU_MIDR_SIZE
 #if __aarch64__
-#define CPU_EXTRA1_FUNC		CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
-#define CPU_EXTRA2_FUNC		CPU_EXTRA1_FUNC + CPU_EXTRA1_FUNC_SIZE
-#define CPU_EXTRA3_FUNC		CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE
-#define CPU_EXTRA4_FUNC		CPU_EXTRA3_FUNC + CPU_EXTRA3_FUNC_SIZE
-#define CPU_E_HANDLER_FUNC	CPU_EXTRA4_FUNC + CPU_EXTRA4_FUNC_SIZE
+#define CPU_E_HANDLER_FUNC	CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
 #define CPU_PWR_DWN_OPS		CPU_E_HANDLER_FUNC + CPU_E_HANDLER_FUNC_SIZE
 #else
 #define CPU_PWR_DWN_OPS		CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
@@ -117,10 +101,6 @@
 	void (*reset_func)(void);
 #endif /* IMAGE_AT_EL3 */
 #if __aarch64__
-	void (*extra1_func)(void);
-	void (*extra2_func)(void);
-	void (*extra3_func)(void);
-	void (*extra4_func)(void);
 	void (*e_handler_func)(long es);
 #endif /* __aarch64__ */
 #if (defined(IMAGE_BL31) || defined(IMAGE_BL32)) && CPU_MAX_PWR_DWN_OPS
diff --git a/include/lib/cpus/errata.h b/include/lib/cpus/errata.h
index 8e28d46..235e2b9 100644
--- a/include/lib/cpus/errata.h
+++ b/include/lib/cpus/errata.h
@@ -27,6 +27,18 @@
 #define ERRATA_APPLIES		1
 #define ERRATA_MISSING		2
 
+/* Errata ID for smc workarounds */
+#define ARCH_WORKAROUND_2		2
+#define ARCH_WORKAROUND_3		3
+
+#define INCLUDE_ERRATA_LIST	(		\
+	REPORT_ERRATA			|	\
+	ERRATA_ABI_SUPPORT		|	\
+	WORKAROUND_CVE_2017_5715	|	\
+	WORKAROUND_CVE_2018_3639	|	\
+	WORKAROUND_CVE_2022_23960	|	\
+	WORKAROUND_CVE_2024_7881)
+
 #ifndef __ASSEMBLER__
 #include <lib/cassert.h>
 
@@ -67,10 +79,11 @@
 }
 #endif
 
-
 bool check_if_trbe_disable_affected_core(void);
 int check_wa_cve_2024_7881(void);
 bool errata_ich_vmcr_el2_applies(void);
+struct erratum_entry *find_erratum_entry(uint32_t errata_id);
+int check_erratum_applies(uint32_t cve, int errata_id);
 
 #else
 
@@ -83,8 +96,6 @@
  * unlikely event that this does happen, prepending the CVE id with a 0 should
  * resolve the conflict
  */
-#define ERRATUM(id)		0, id
-#define CVE(year, id)		year, id
 #define NO_ISB			1
 #define NO_ASSERT		0
 #define NO_APPLY_AT_RESET	0
@@ -97,6 +108,9 @@
 
 #endif /* __ASSEMBLER__ */
 
+#define ERRATUM(id)		0, id
+#define CVE(year, id)		year, id
+
 /* Macro to get CPU revision code for checking errata version compatibility. */
 #define CPU_REV(r, p)		((r << 4) | p)
 
diff --git a/include/lib/cpus/wa_cve_2017_5715.h b/include/lib/cpus/wa_cve_2017_5715.h
deleted file mode 100644
index 2ad56e1..0000000
--- a/include/lib/cpus/wa_cve_2017_5715.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef WA_CVE_2017_5715_H
-#define WA_CVE_2017_5715_H
-
-int check_wa_cve_2017_5715(void);
-
-#endif /* WA_CVE_2017_5715_H */
diff --git a/include/lib/cpus/wa_cve_2018_3639.h b/include/lib/cpus/wa_cve_2018_3639.h
deleted file mode 100644
index 5a7c9bf..0000000
--- a/include/lib/cpus/wa_cve_2018_3639.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef WA_CVE_2018_3639_H
-#define WA_CVE_2018_3639_H
-
-void *wa_cve_2018_3639_get_disable_ptr(void);
-
-#endif /* WA_CVE_2018_3639_H */
diff --git a/include/lib/cpus/wa_cve_2022_23960.h b/include/lib/cpus/wa_cve_2022_23960.h
deleted file mode 100644
index 50c0f76..0000000
--- a/include/lib/cpus/wa_cve_2022_23960.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef WA_CVE_2022_23960_H
-#define WA_CVE_2022_23960_H
-
-int check_smccc_arch_wa3_applies(void);
-
-#endif /* WA_CVE_2022_23960_H */
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index a48ed96..72a8ea2 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -34,17 +34,11 @@
 void cm_prepare_el3_exit(uint32_t security_state);
 void cm_prepare_el3_exit_ns(void);
 
-#if !IMAGE_BL1
-void cm_init_context_by_index(unsigned int cpu_idx,
-			      const struct entry_point_info *ep);
-#endif /* !IMAGE_BL1 */
-
 #ifdef __aarch64__
 #if IMAGE_BL31
 void cm_manage_extensions_el3(unsigned int my_idx);
 void manage_extensions_nonsecure_per_world(void);
 void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx);
-void cm_handle_asymmetric_features(void);
 #endif
 
 #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
@@ -97,7 +91,6 @@
 void cm_set_next_context(void *context);
 static inline void cm_manage_extensions_el3(unsigned int cpu_idx) {}
 static inline void manage_extensions_nonsecure_per_world(void) {}
-static inline void cm_handle_asymmetric_features(void) {}
 #endif /* __aarch64__ */
 
 #endif /* CONTEXT_MGMT_H */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index e417f45..3dc156a 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -23,10 +23,10 @@
 /* Size of cpu_context array */
 #define CPU_DATA_CONTEXT_NUM		3
 /* Offset of cpu_ops_ptr, size 8 bytes */
-#define CPU_DATA_CPU_OPS_PTR		0x18
+#define CPU_DATA_CPU_OPS_PTR		0x20
 #else /* ENABLE_RME */
 #define CPU_DATA_CONTEXT_NUM		2
-#define CPU_DATA_CPU_OPS_PTR		0x10
+#define CPU_DATA_CPU_OPS_PTR		0x18
 #endif /* ENABLE_RME */
 
 #if ENABLE_PAUTH
@@ -47,8 +47,9 @@
 #if CRASH_REPORTING
 #error "Crash reporting is not supported in AArch32"
 #endif
-#define CPU_DATA_CPU_OPS_PTR		0x0
-#define CPU_DATA_CRASH_BUF_OFFSET	(0x4 + PSCI_CPU_DATA_SIZE)
+#define WARMBOOT_EP_INFO		0x0
+#define CPU_DATA_CPU_OPS_PTR		0x4
+#define CPU_DATA_CRASH_BUF_OFFSET	(CPU_DATA_CPU_OPS_PTR + PSCI_CPU_DATA_SIZE)
 
 #endif	/* __aarch64__ */
 
@@ -79,7 +80,12 @@
 #if ENABLE_RUNTIME_INSTRUMENTATION
 /* Temporary space to store PMF timestamps from assembly code */
 #define CPU_DATA_PMF_TS_COUNT		1
+#if __aarch64__
 #define CPU_DATA_PMF_TS0_OFFSET		CPU_DATA_EHF_DATA_BUF_END
+#else
+/* alignment */
+#define CPU_DATA_PMF_TS0_OFFSET		(CPU_DATA_EHF_DATA_BUF_END + 8)
+#endif
 #define CPU_DATA_PMF_TS0_IDX		0
 #endif
 
@@ -131,6 +137,7 @@
 #ifdef __aarch64__
 	void *cpu_context[CPU_DATA_CONTEXT_NUM];
 #endif /* __aarch64__ */
+	entry_point_info_t *warmboot_ep_info;
 	uintptr_t cpu_ops_ptr;
 	struct psci_cpu_data psci_svc_cpu_data;
 #if ENABLE_PAUTH
diff --git a/include/lib/extensions/pauth.h b/include/lib/extensions/pauth.h
index dbc2226..db47b80 100644
--- a/include/lib/extensions/pauth.h
+++ b/include/lib/extensions/pauth.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,12 +7,34 @@
 #ifndef PAUTH_H
 #define PAUTH_H
 
-/*******************************************************************************
- * ARMv8.3-PAuth support functions
- ******************************************************************************/
+#if ENABLE_PAUTH
+/* Platform hook to generate the APIAKey */
+uint128_t plat_init_apkey(void);
 
-/* Disable ARMv8.3 pointer authentication in EL1/EL3 */
+void pauth_init(void);
+void pauth_enable_el1(void);
+void pauth_enable_el3(void);
+void pauth_enable_el2(void);
 void pauth_disable_el1(void);
 void pauth_disable_el3(void);
-
+#else
+static inline void pauth_init(void)
+{
+}
+static inline void pauth_enable_el1(void)
+{
+}
+static inline void pauth_enable_el3(void)
+{
+}
+static inline void pauth_enable_el2(void)
+{
+}
+static inline void pauth_disable_el1(void)
+{
+}
+static inline void pauth_disable_el3(void)
+{
+}
+#endif
 #endif /* PAUTH_H */
diff --git a/include/lib/libc/cdefs.h b/include/lib/libc/cdefs.h
index 5febe9d..3bd4a70 100644
--- a/include/lib/libc/cdefs.h
+++ b/include/lib/libc/cdefs.h
@@ -17,6 +17,7 @@
 #define __section(x)	__attribute__((__section__(x)))
 #define __fallthrough	__attribute__((__fallthrough__))
 #define __noinline	__attribute__((__noinline__))
+#define __no_pauth	__attribute__((target("branch-protection=none")))
 #if RECLAIM_INIT_CODE
 /*
  * Add each function to a section that is unique so the functions can still
diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h
index bba9816..098fded 100644
--- a/include/lib/libc/string.h
+++ b/include/lib/libc/string.h
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 /*
- * Portions copyright (c) 2018-2020, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * Portions copyright (c) 2023, Intel Corporation. All rights reserved.
  * All rights reserved.
  */
@@ -14,19 +14,26 @@
 
 #include <stddef.h>
 
-void *memcpy(void *dst, const void *src, size_t len);
+/*
+ * When conditions are right, the compiler may have a baked-in call that can be
+ * inlined and that will be much more optimal than our generic implementation.
+ * When it doesn't, it will emit a call to the original function for which we
+ * provide an implementation.
+ */
+#define memcpy  __builtin_memcpy
+#define memset  __builtin_memset
+#define memcmp  __builtin_memcmp
+#define memchr  __builtin_memchr
+#define strcmp  __builtin_strcmp
+#define strncmp __builtin_strncmp
+#define strchr  __builtin_strchr
+#define strlen  __builtin_strlen
+#define strrchr __builtin_strrchr
+
 int memcpy_s(void *dst, size_t dsize, void *src, size_t ssize);
 void *memmove(void *dst, const void *src, size_t len);
-int memcmp(const void *s1, const void *s2, size_t len);
-int strcmp(const char *s1, const char *s2);
-int strncmp(const char *s1, const char *s2, size_t n);
-void *memchr(const void *src, int c, size_t len);
 void *memrchr(const void *src, int c, size_t len);
-char *strchr(const char *s, int c);
-void *memset(void *dst, int val, size_t count);
-size_t strlen(const char *s);
 size_t strnlen(const char *s, size_t maxlen);
-char *strrchr(const char *p, int ch);
 size_t strlcpy(char * dst, const char * src, size_t dsize);
 size_t strlcat(char * dst, const char * src, size_t dsize);
 char *strtok_r(char *s, const char *delim, char **last);
diff --git a/include/lib/libc/string_private.h b/include/lib/libc/string_private.h
new file mode 100644
index 0000000..da85fae
--- /dev/null
+++ b/include/lib/libc/string_private.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STRING_PRIVATE_H
+#define STRING_PRIVATE_H
+
+/* Do not include outside of the libc. Use string.h instead. */
+
+#include <stddef.h>
+
+int memcmp(const void *s1, const void *s2, size_t len);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, size_t n);
+void *memchr(const void *src, int c, size_t len);
+char *strchr(const char *s, int c);
+void *memset(void *dst, int val, size_t count);
+size_t strlen(const char *s);
+char *strrchr(const char *p, int ch);
+
+#endif /* STRING_PRIVATE_H */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 6d8a06a..098506a 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -61,6 +61,9 @@
 #define HI(addr)			(addr >> 32)
 #define LO(addr)			(addr & 0xffffffff)
 
+#define HI_64(addr)			(addr >> 64)
+#define LO_64(addr)			(addr & 0xffffffffffffffff)
+
 /*
  * This variant of div_round_up can be used in macro definition but should not
  * be used in C code as the `div` parameter is evaluated twice.
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 5434a9a..f540fa5 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -62,10 +62,8 @@
 #define OSH			(U(0x2) << 6)
 #define ISH			(U(0x3) << 6)
 
-#ifdef __aarch64__
 /* Guarded Page bit */
 #define GP			(ULL(1) << 50)
-#endif
 
 #define TABLE_ADDR_MASK		ULL(0x0000FFFFFFFFF000)
 
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 396bd14..aed85f5 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -10,6 +10,7 @@
 #include <stdint.h>
 
 #include <common/desc_image_load.h>
+#include <drivers/arm/gic.h>
 #include <drivers/arm/tzc_common.h>
 #include <lib/bakery_lock.h>
 #include <lib/cassert.h>
@@ -147,6 +148,14 @@
 
 #endif /* defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) */
 
+#ifdef __aarch64__
+#define TL_TAG_EXEC_EP_INFO	TL_TAG_EXEC_EP_INFO64
+#define TL_TAG_SRAM_LAYOUT	TL_TAG_SRAM_LAYOUT64
+#else
+#define TL_TAG_EXEC_EP_INFO	TL_TAG_EXEC_EP_INFO32
+#define TL_TAG_SRAM_LAYOUT	TL_TAG_SRAM_LAYOUT32
+#endif
+
 #if ARM_RECOM_STATE_ID_ENC
 /*
  * Macros used to parse state information from State-ID if it is using the
@@ -291,7 +300,8 @@
 void arm_transfer_list_get_heap_info(void **heap_addr, size_t *heap_size);
 
 /* TSP utility functions */
-void arm_tsp_early_platform_setup(void);
+void arm_tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+				  u_register_t arg2, u_register_t arg3);
 
 /* SP_MIN utility functions */
 void arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
@@ -350,6 +360,9 @@
  * Mandatory functions required in ARM standard platforms
  */
 unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr);
+
+/* should not be used, but keep for compatibility */
+#if USE_GIC_DRIVER == 0
 void plat_arm_gic_driver_init(void);
 void plat_arm_gic_init(void);
 void plat_arm_gic_cpuif_enable(void);
@@ -359,6 +372,7 @@
 void plat_arm_gic_pcpu_init(void);
 void plat_arm_gic_save(void);
 void plat_arm_gic_resume(void);
+#endif
 void plat_arm_security_setup(void);
 void plat_arm_pwrc_setup(void);
 void plat_arm_interconnect_init(void);
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index e10770c..b9985a3 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -399,6 +399,24 @@
 size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared);
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest);
 int plat_rmmd_mecid_key_update(uint16_t mecid);
+
+/* The following 4 functions are to be implemented if
+ * RMMD_ENABLE_IDE_KEY_PROG=1.
+ * The following functions are expected to return E_RMM_* error codes.
+ */
+int plat_rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t root_port_id,
+				  uint64_t ide_stream_info,
+				  rp_ide_key_info_t *ide_key_info_ptr,
+				  uint64_t request_id, uint64_t cookie);
+int plat_rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t root_port_id,
+				 uint64_t ide_stream_info, uint64_t request_id,
+				 uint64_t cookie);
+int plat_rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t ide_stream_info, uint64_t request_id,
+				   uint64_t cookie);
+int plat_rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t *req_resp, uint64_t *request_id,
+				   uint64_t *cookie);
 #endif /* ENABLE_RME */
 
 /*******************************************************************************
diff --git a/include/services/arm_arch_svc.h b/include/services/arm_arch_svc.h
index 699a8d7..10ac2f1 100644
--- a/include/services/arm_arch_svc.h
+++ b/include/services/arm_arch_svc.h
@@ -95,6 +95,12 @@
 #define SCR_FEAT_AMUv1p1 (0)
 #endif
 
+#if ENABLE_FEAT_TWED
+#define SCR_FEAT_TWED SCR_TWEDEn_BIT
+#else
+#define SCR_FEAT_TWED (0)
+#endif
+
 #if ENABLE_FEAT_ECV
 #define SCR_FEAT_ECV SCR_ECVEN_BIT
 #else
@@ -119,7 +125,7 @@
 #define SCR_FEAT_CSV2_2 (0)
 #endif
 
-#if ENABLE_FEAT_RAS
+#if !RAS_TRAP_NS_ERR_REC_ACCESS
 #define SCR_FEAT_RAS SCR_TERR_BIT
 #else
 #define SCR_FEAT_RAS (0)
@@ -182,6 +188,7 @@
 	SCR_FEAT_HCX		|						\
 	SCR_FEAT_LS64_ACCDATA	|						\
 	SCR_FEAT_AMUv1p1	|						\
+	SCR_FEAT_TWED		|						\
 	SCR_FEAT_ECV		|						\
 	SCR_FEAT_FGT		|						\
 	SCR_FEAT_MTE2		|						\
@@ -289,6 +296,7 @@
 	MDCR_FEAT_SPE		|						\
 	MDCR_TDOSA_BIT		|						\
 	MDCR_TDA_BIT		|						\
+	MDCR_EnPM2_BIT		|						\
 	MDCR_TPM_BIT		| /* FEAT_PMUv3 */				\
 	MDCR_PLAT_FEATS)
 #define MDCR_EL3_FLIPPED (							\
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
index 8bf9319..9b99e92 100644
--- a/include/services/rmmd_svc.h
+++ b/include/services/rmmd_svc.h
@@ -92,6 +92,8 @@
 #define E_RMM_NOMEM			-4
 #define E_RMM_INVAL			-5
 #define E_RMM_AGAIN			-6
+#define E_RMM_FAULT			-7
+#define E_RMM_IN_PROGRESS		-8
 
 /* Return error codes from RMI SMCs */
 #define RMI_SUCCESS			0
@@ -179,6 +181,83 @@
 /* Identifier for the hash algorithm used for attestation signing */
 #define EL3_TOKEN_SIGN_HASH_ALG_SHA384		U(1)
 
+/* Starting RMM-EL3 interface version 0.6 */
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ *     arg3 - IDE selective stream info
+ *     arg4 - Quad word of key[63:0]
+ *     arg5 - Quad word of key[127:64]
+ *     arg6 - Quad word of key[191:128]
+ *     arg7 - Quad word of key[255:192]
+ *     arg8 - Quad word of IV [63:0]
+ *     arg9 - Quad word of IV [95:64]
+ *     arg10 - request_id
+ *     arg11 - cookie
+ * The return arguments are:
+ *     ret0 - Status/Error
+ */
+#define RMM_IDE_KEY_PROG			SMC64_RMMD_EL3_FID(U(7))
+
+/*******************************************************************************
+ * Structure to hold el3_ide_key info
+ ******************************************************************************/
+#ifndef __ASSEMBLER__
+typedef struct rp_ide_key_info {
+	uint64_t keyqw0;
+	uint64_t keyqw1;
+	uint64_t keyqw2;
+	uint64_t keyqw3;
+	uint64_t ifvqw0;
+	uint64_t ifvqw1;
+} rp_ide_key_info_t;
+#endif /* __ASSEMBLER__ */
+
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ *     arg3 - IDE selective stream info
+ *     arg4 - request_id
+ *     arg5 - cookie
+ * The return arguments are:
+ *     ret0 - Status/Error
+ */
+#define RMM_IDE_KEY_SET_GO			SMC64_RMMD_EL3_FID(U(8))
+
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ *     arg3 - IDE selective stream info
+ *     arg4 - request_id
+ *     arg5 - cookie
+ * The return arguments are:
+ *     ret0 - Status/Error
+ */
+#define RMM_IDE_KEY_SET_STOP			SMC64_RMMD_EL3_FID(U(9))
+
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ * The return arguments are:
+ *     ret0 - Status/Error
+ *     ret1 - Retrieved response corresponding to the previous request.
+ *     ret2 - request_id
+ *     ret3 - cookie
+ */
+#define RMM_IDE_KM_PULL_RESPONSE		SMC64_RMMD_EL3_FID(U(10))
+
 /*
  * RMM_BOOT_COMPLETE originates on RMM when the boot finishes (either cold
  * or warm boot). This is handled by the RMM-EL3 interface SMC handler.
@@ -200,7 +279,7 @@
  * Increase this when a bug is fixed, or a feature is added without
  * breaking compatibility.
  */
-#define RMM_EL3_IFC_VERSION_MINOR	(U(5))
+#define RMM_EL3_IFC_VERSION_MINOR	(U(6))
 
 #define RMM_EL3_INTERFACE_VERSION				\
 	(((RMM_EL3_IFC_VERSION_MAJOR << 16) & 0x7FFFF) |	\
diff --git a/include/services/trp/platform_trp.h b/include/services/trp/platform_trp.h
index 756e9db..67dfff1 100644
--- a/include/services/trp/platform_trp.h
+++ b/include/services/trp/platform_trp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,4 +16,8 @@
  ******************************************************************************/
 void trp_early_platform_setup(struct rmm_manifest *manifest);
 
+#if RMMD_ENABLE_IDE_KEY_PROG
+uint64_t trp_get_test_rootport(uint64_t *ecam, uint64_t *rootport);
+#endif /* RMMD_ENABLE_IDE_KEY_PROG */
+
 #endif /* PLATFORM_TRP_H */
diff --git a/include/services/trp/trp_helpers.h b/include/services/trp/trp_helpers.h
index 83ec740..2f36720 100644
--- a/include/services/trp/trp_helpers.h
+++ b/include/services/trp/trp_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,7 +17,11 @@
 #define TRP_ARG5		0x28
 #define TRP_ARG6		0x30
 #define TRP_ARG7		0x38
-#define TRP_ARGS_END		0x40
+#define TRP_ARG8		0x40
+#define TRP_ARG9		0x48
+#define TRP_ARG10		0x50
+#define TRP_ARG11		0x58
+#define TRP_ARGS_END		0x60
 
 #ifndef __ASSEMBLER__
 
@@ -35,7 +39,11 @@
 			 uint64_t arg4,
 			 uint64_t arg5,
 			 uint64_t arg6,
-			 uint64_t arg7);
+			 uint64_t arg7,
+			 uint64_t arg8,
+			 uint64_t arg9,
+			 uint64_t arg10,
+			 uint64_t arg11);
 
 __dead2 void trp_boot_abort(uint64_t err);
 
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index ff9a4e6..cc46c53 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -215,7 +215,7 @@
 
 	.macro	dcsw_loop _op
 #if ENABLE_BTI
-	bti	j
+	BTI	j
 #endif
 loop2_\_op:
 	lsl	w7, w6, w2		// w7 = aligned max set number
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index 6ec6742..258817f 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -128,6 +128,15 @@
 
 check_erratum_ls cortex_a510, ERRATUM(2288014), CPU_REV(1, 0)
 
+workaround_reset_start cortex_a510, ERRATUM(2313941), ERRATA_DSU_2313941
+	errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_a510, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_a510, ERRATUM(2313941)
+	check_errata_dsu_2313941_impl
+	ret
+check_erratum_custom_end cortex_a510, ERRATUM(2313941)
+
 workaround_reset_start cortex_a510, ERRATUM(2347730), ERRATA_A510_2347730
 	/*
 	 * Set CPUACTLR_EL1[17] to 1'b1, which disables
@@ -169,15 +178,6 @@
 
 check_erratum_ls cortex_a510, ERRATUM(2684597), CPU_REV(1, 2)
 
-workaround_reset_start cortex_a510, ERRATUM(2313941), ERRATA_DSU_2313941
-	errata_dsu_2313941_wa_impl
-workaround_reset_end cortex_a510, ERRATUM(2313941)
-
-check_erratum_custom_start cortex_a510, ERRATUM(2313941)
-	check_errata_dsu_2313941_impl
-	ret
-check_erratum_custom_end cortex_a510, ERRATUM(2313941)
-
 .global check_erratum_cortex_a510_2971420
 add_erratum_entry cortex_a510, ERRATUM(2971420), ERRATA_A510_2971420
 check_erratum_range cortex_a510, ERRATUM(2971420), CPU_REV(0, 1), CPU_REV(1, 3)
diff --git a/lib/cpus/aarch64/cortex_a55.S b/lib/cpus/aarch64/cortex_a55.S
index cf91431..f5921a2 100644
--- a/lib/cpus/aarch64/cortex_a55.S
+++ b/lib/cpus/aarch64/cortex_a55.S
@@ -22,24 +22,6 @@
 
 cpu_reset_prologue cortex_a55
 
-workaround_reset_start cortex_a55, ERRATUM(798953), ERRATA_DSU_798953
-	errata_dsu_798953_wa_impl
-workaround_reset_end cortex_a55, ERRATUM(798953)
-
-check_erratum_custom_start cortex_a55, ERRATUM(798953)
-	check_errata_dsu_798953_impl
-	ret
-check_erratum_custom_end cortex_a55, ERRATUM(798953)
-
-workaround_reset_start cortex_a55, ERRATUM(936184), ERRATA_DSU_936184
-	errata_dsu_936184_wa_impl
-workaround_reset_end cortex_a55, ERRATUM(936184)
-
-check_erratum_custom_start cortex_a55, ERRATUM(936184)
-	check_errata_dsu_936184_impl
-	ret
-check_erratum_custom_end cortex_a55, ERRATUM(936184)
-
 workaround_reset_start cortex_a55, ERRATUM(768277), ERRATA_A55_768277
 	sysreg_bit_set CORTEX_A55_CPUACTLR_EL1, CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE
 workaround_reset_end cortex_a55, ERRATUM(768277)
@@ -71,6 +53,15 @@
 
 check_erratum_ls cortex_a55, ERRATUM(798797), CPU_REV(0, 0)
 
+workaround_reset_start cortex_a55, ERRATUM(798953), ERRATA_DSU_798953
+	errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a55, ERRATUM(798953)
+
+check_erratum_custom_start cortex_a55, ERRATUM(798953)
+	check_errata_dsu_798953_impl
+	ret
+check_erratum_custom_end cortex_a55, ERRATUM(798953)
+
 workaround_reset_start cortex_a55, ERRATUM(846532), ERRATA_A55_846532
 	sysreg_bit_set CORTEX_A55_CPUACTLR_EL1, CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE
 workaround_reset_end cortex_a55, ERRATUM(846532)
@@ -83,6 +74,15 @@
 
 check_erratum_ls cortex_a55, ERRATUM(903758), CPU_REV(0, 1)
 
+workaround_reset_start cortex_a55, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a55, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a55, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a55, ERRATUM(936184)
+
 workaround_reset_start cortex_a55, ERRATUM(1221012), ERRATA_A55_1221012
 	mov	x0, #0x0020
 	movk	x0, #0x0850, lsl #16
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index adacc5c..553f6f9 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -65,15 +65,20 @@
 	ret
 endfunc cortex_a57_disable_ext_debug
 
+/* Erratum entry and check function for SMCCC_ARCH_WORKAROUND_3 */
+add_erratum_entry cortex_a57, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
+
+check_erratum_chosen cortex_a57, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
+
 /*
  * Disable the over-read from the LDNP/STNP instruction. The SDEN doesn't
- * provide and erratum number, so assign it an obvious 1
+ * provide and erratum number, so assign it an obvious 99999
  */
-workaround_reset_start cortex_a57, ERRATUM(1), A57_DISABLE_NON_TEMPORAL_HINT
+workaround_reset_start cortex_a57, ERRATUM(99999), A57_DISABLE_NON_TEMPORAL_HINT
 	sysreg_bit_set CORTEX_A57_CPUACTLR_EL1, CORTEX_A57_CPUACTLR_EL1_DIS_OVERREAD
-workaround_reset_end cortex_a57, ERRATUM(1)
+workaround_reset_end cortex_a57, ERRATUM(99999)
 
-check_erratum_ls cortex_a57, ERRATUM(1), CPU_REV(1, 2)
+check_erratum_ls cortex_a57, ERRATUM(99999), CPU_REV(1, 2)
 
 workaround_reset_start cortex_a57, ERRATUM(806969), ERRATA_A57_806969
 	sysreg_bit_set CORTEX_A57_CPUACTLR_EL1, CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA
@@ -187,11 +192,6 @@
 	sysreg_bit_set CORTEX_A57_ECTLR_EL1, CORTEX_A57_ECTLR_SMP_BIT
 cpu_reset_func_end cortex_a57
 
-func check_smccc_arch_workaround_3
-	mov	x0, #ERRATA_APPLIES
-	ret
-endfunc check_smccc_arch_workaround_3
-
 	/* ----------------------------------------------------
 	 * The CPU Ops core power down function for Cortex-A57.
 	 * ----------------------------------------------------
@@ -307,10 +307,7 @@
 	ret
 endfunc cortex_a57_cpu_reg_dump
 
-declare_cpu_ops_wa cortex_a57, CORTEX_A57_MIDR, \
+declare_cpu_ops cortex_a57, CORTEX_A57_MIDR, \
 	cortex_a57_reset_func, \
-	check_erratum_cortex_a57_5715, \
-	CPU_NO_EXTRA2_FUNC, \
-	check_smccc_arch_workaround_3, \
 	cortex_a57_core_pwr_dwn, \
 	cortex_a57_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index fee28ee..23b27ab 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -76,14 +76,17 @@
 	ret
 endfunc cortex_a72_disable_ext_debug
 
-func check_smccc_arch_workaround_3
+check_erratum_custom_start cortex_a72, ERRATUM(ARCH_WORKAROUND_3)
 	cpu_check_csv2	x0, 1f
 	mov	x0, #ERRATA_APPLIES
 	ret
 1:
 	mov	x0, #ERRATA_NOT_APPLIES
 	ret
-endfunc check_smccc_arch_workaround_3
+check_erratum_custom_end cortex_a72, ERRATUM(ARCH_WORKAROUND_3)
+
+/* Erratum entry and check function for SMCCC_ARCH_WORKAROUND_3 */
+add_erratum_entry cortex_a72, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
 
 workaround_reset_start cortex_a72, ERRATUM(859971), ERRATA_A72_859971
 	sysreg_bit_set CORTEX_A72_CPUACTLR_EL1, CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH
@@ -294,10 +297,7 @@
 	ret
 endfunc cortex_a72_cpu_reg_dump
 
-declare_cpu_ops_wa cortex_a72, CORTEX_A72_MIDR, \
+declare_cpu_ops cortex_a72, CORTEX_A72_MIDR, \
 	cortex_a72_reset_func, \
-	check_erratum_cortex_a72_5715, \
-	CPU_NO_EXTRA2_FUNC, \
-	check_smccc_arch_workaround_3, \
 	cortex_a72_core_pwr_dwn, \
 	cortex_a72_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index d1fc6d4..9cc6fdb 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -33,10 +33,10 @@
 	ret
 endfunc cortex_a73_disable_smp
 
-func check_smccc_arch_workaround_3
-	mov	x0, #ERRATA_APPLIES
-	ret
-endfunc check_smccc_arch_workaround_3
+/* Erratum entry and check function for SMCCC_ARCH_WORKAROUND_3 */
+add_erratum_entry cortex_a73, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
+
+check_erratum_chosen cortex_a73, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
 
 workaround_reset_start cortex_a73, ERRATUM(852427), ERRATA_A73_852427
 	sysreg_bit_set CORTEX_A73_DIAGNOSTIC_REGISTER, BIT(12)
@@ -200,10 +200,7 @@
 	ret
 endfunc cortex_a73_cpu_reg_dump
 
-declare_cpu_ops_wa cortex_a73, CORTEX_A73_MIDR, \
+declare_cpu_ops cortex_a73, CORTEX_A73_MIDR, \
 	cortex_a73_reset_func, \
-	check_erratum_cortex_a73_5715, \
-	CPU_NO_EXTRA2_FUNC, \
-	check_smccc_arch_workaround_3, \
 	cortex_a73_core_pwr_dwn, \
 	cortex_a73_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 13599ca..ef9c067 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -20,6 +20,11 @@
 
 cpu_reset_prologue cortex_a75
 
+/* Erratum entry and check function for SMCCC_ARCH_WORKAROUND_3 */
+add_erratum_entry cortex_a75, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
+
+check_erratum_chosen cortex_a75, ERRATUM(ARCH_WORKAROUND_3), WORKAROUND_CVE_2022_23960
+
 workaround_reset_start cortex_a75, ERRATUM(764081), ERRATA_A75_764081
 	sysreg_bit_set sctlr_el3, SCTLR_IESB_BIT
 workaround_reset_end cortex_a75, ERRATUM(764081)
@@ -131,11 +136,6 @@
 #endif
 cpu_reset_func_end cortex_a75
 
-func check_smccc_arch_workaround_3
-	mov	x0, #ERRATA_APPLIES
-	ret
-endfunc check_smccc_arch_workaround_3
-
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -170,9 +170,6 @@
 	ret
 endfunc cortex_a75_cpu_reg_dump
 
-declare_cpu_ops_wa cortex_a75, CORTEX_A75_MIDR, \
+declare_cpu_ops cortex_a75, CORTEX_A75_MIDR, \
 	cortex_a75_reset_func, \
-	check_erratum_cortex_a75_5715, \
-	CPU_NO_EXTRA2_FUNC, \
-	check_smccc_arch_workaround_3, \
 	cortex_a75_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 822ef05..ca5ccf7 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -301,6 +301,29 @@
 endfunc apply_cve_2018_3639_sync_wa
 #endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */
 
+/* Erratum entry and check function for SMCCC_ARCH_WORKAROUND_2*/
+add_erratum_entry cortex_a76, ERRATUM(ARCH_WORKAROUND_2), WORKAROUND_CVE_2018_3639
+
+check_erratum_chosen cortex_a76, ERRATUM(ARCH_WORKAROUND_2), WORKAROUND_CVE_2018_3639
+
+workaround_reset_start cortex_a76, ERRATUM(798953), ERRATA_DSU_798953
+	errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a76, ERRATUM(798953)
+
+check_erratum_custom_start cortex_a76, ERRATUM(798953)
+	check_errata_dsu_798953_impl
+	ret
+check_erratum_custom_end cortex_a76, ERRATUM(798953)
+
+workaround_reset_start cortex_a76, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a76, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a76, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a76, ERRATUM(936184)
+
 workaround_reset_start cortex_a76, ERRATUM(1073348), ERRATA_A76_1073348
 	sysreg_bit_set CORTEX_A76_CPUACTLR_EL1 ,CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION
 workaround_reset_end cortex_a76, ERRATUM(1073348)
@@ -314,6 +337,24 @@
 
 check_erratum_ls cortex_a76, ERRATUM(1130799), CPU_REV(2, 0)
 
+/* --------------------------------------------------------------
+ * Errata Workaround for Cortex A76 Errata #1165522.
+ * This applies only to revisions <= r3p0 of Cortex A76.
+ * Due to the nature of the errata it is applied unconditionally
+ * when built in, report it as applicable in this case
+ * --------------------------------------------------------------
+ */
+check_erratum_custom_start cortex_a76, ERRATUM(1165522)
+#if ERRATA_A76_1165522
+	mov	x0, #ERRATA_APPLIES
+#else
+	cpu_rev_var_ls	CPU_REV(3, 0)
+#endif
+	ret
+check_erratum_custom_end cortex_a76, ERRATUM(1165522)
+
+add_erratum_entry cortex_a76, ERRATUM(1165522), ERRATA_A76_1165522
+
 workaround_reset_start cortex_a76, ERRATUM(1220197), ERRATA_A76_1220197
 	sysreg_bit_set CORTEX_A76_CPUECTLR_EL1, CORTEX_A76_CPUECTLR_EL1_WS_THR_L2
 workaround_reset_end cortex_a76, ERRATUM(1220197)
@@ -353,6 +394,8 @@
 	ret
 check_erratum_custom_end cortex_a76, ERRATUM(1286807)
 
+add_erratum_entry cortex_a76, ERRATUM(1286807), ERRATA_A76_1286807
+
 workaround_reset_start cortex_a76, ERRATUM(1791580), ERRATA_A76_1791580
 	sysreg_bit_set CORTEX_A76_CPUACTLR2_EL1, CORTEX_A76_CPUACTLR2_EL1_BIT_2
 workaround_reset_end cortex_a76, ERRATUM(1791580)
@@ -411,45 +454,11 @@
 	ret
 endfunc cortex_a76_disable_wa_cve_2018_3639
 
-/* --------------------------------------------------------------
- * Errata Workaround for Cortex A76 Errata #1165522.
- * This applies only to revisions <= r3p0 of Cortex A76.
- * Due to the nature of the errata it is applied unconditionally
- * when built in, report it as applicable in this case
- * --------------------------------------------------------------
- */
-check_erratum_custom_start cortex_a76, ERRATUM(1165522)
-#if ERRATA_A76_1165522
-	mov	x0, #ERRATA_APPLIES
-#else
-	cpu_rev_var_ls	CPU_REV(3, 0)
-#endif
-	ret
-check_erratum_custom_end cortex_a76, ERRATUM(1165522)
-
 check_erratum_chosen cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
 /* erratum has no workaround in the cpu. Generic code must take care */
 add_erratum_entry cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
-workaround_reset_start cortex_a76, ERRATUM(798953), ERRATA_DSU_798953
-	errata_dsu_798953_wa_impl
-workaround_reset_end cortex_a76, ERRATUM(798953)
-
-check_erratum_custom_start cortex_a76, ERRATUM(798953)
-	check_errata_dsu_798953_impl
-	ret
-check_erratum_custom_end cortex_a76, ERRATUM(798953)
-
-workaround_reset_start cortex_a76, ERRATUM(936184), ERRATA_DSU_936184
-	errata_dsu_936184_wa_impl
-workaround_reset_end cortex_a76, ERRATUM(936184)
-
-check_erratum_custom_start cortex_a76, ERRATUM(936184)
-	check_errata_dsu_936184_impl
-	ret
-check_erratum_custom_end cortex_a76, ERRATUM(936184)
-
 cpu_reset_func_start cortex_a76
 
 #if WORKAROUND_CVE_2018_3639
@@ -531,9 +540,6 @@
 	ret
 endfunc cortex_a76_cpu_reg_dump
 
-declare_cpu_ops_wa cortex_a76, CORTEX_A76_MIDR, \
+declare_cpu_ops cortex_a76, CORTEX_A76_MIDR, \
 	cortex_a76_reset_func, \
-	CPU_NO_EXTRA1_FUNC, \
-	cortex_a76_disable_wa_cve_2018_3639, \
-	CPU_NO_EXTRA3_FUNC, \
 	cortex_a76_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index c4872fe..158ee0e 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -167,10 +167,6 @@
 	ret
 endfunc cortex_x3_cpu_reg_dump
 
-declare_cpu_ops_wa_4 cortex_x3, CORTEX_X3_MIDR, \
+declare_cpu_ops cortex_x3, CORTEX_X3_MIDR, \
 	cortex_x3_reset_func, \
-	CPU_NO_EXTRA1_FUNC, \
-	CPU_NO_EXTRA2_FUNC, \
-	CPU_NO_EXTRA3_FUNC, \
-	check_erratum_cortex_x3_7881, \
 	cortex_x3_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index fbbe925..1d0c377 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -169,10 +169,6 @@
 	ret
 endfunc cortex_x4_cpu_reg_dump
 
-declare_cpu_ops_wa_4 cortex_x4, CORTEX_X4_MIDR, \
+declare_cpu_ops cortex_x4, CORTEX_X4_MIDR, \
 	cortex_x4_reset_func, \
-	CPU_NO_EXTRA1_FUNC, \
-	CPU_NO_EXTRA2_FUNC, \
-	CPU_NO_EXTRA3_FUNC, \
-	check_erratum_cortex_x4_7881, \
 	cortex_x4_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_x925.S b/lib/cpus/aarch64/cortex_x925.S
index 093d91d..0663b21 100644
--- a/lib/cpus/aarch64/cortex_x925.S
+++ b/lib/cpus/aarch64/cortex_x925.S
@@ -99,10 +99,6 @@
 	ret
 endfunc cortex_x925_cpu_reg_dump
 
-declare_cpu_ops_wa_4 cortex_x925, CORTEX_X925_MIDR, \
+declare_cpu_ops cortex_x925, CORTEX_X925_MIDR, \
 	cortex_x925_reset_func, \
-	CPU_NO_EXTRA1_FUNC, \
-	CPU_NO_EXTRA2_FUNC, \
-	CPU_NO_EXTRA3_FUNC, \
-	check_erratum_cortex_x925_7881, \
 	cortex_x925_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index e608422..105da5c 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -188,143 +188,3 @@
 	get_rev_var x0, x1
 	ret
 endfunc cpu_get_rev_var
-
-/*
- * int check_wa_cve_2017_5715(void);
- *
- * This function returns:
- *  - ERRATA_APPLIES when firmware mitigation is required.
- *  - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required.
- *  - ERRATA_MISSING when firmware mitigation would be required but
- *    is not compiled in.
- *
- * NOTE: Must be called only after cpu_ops have been initialized
- *       in per-CPU data.
- */
-	.globl	check_wa_cve_2017_5715
-func check_wa_cve_2017_5715
-	mrs	x0, tpidr_el3
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_DATA_CPU_OPS_PTR]
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_EXTRA1_FUNC]
-	/*
-	 * If the reserved function pointer is NULL, this CPU
-	 * is unaffected by CVE-2017-5715 so bail out.
-	 */
-	cmp	x0, #CPU_NO_EXTRA1_FUNC
-	beq	1f
-	br	x0
-1:
-	mov	x0, #ERRATA_NOT_APPLIES
-	ret
-endfunc check_wa_cve_2017_5715
-
-/*
- * int check_wa_cve_2024_7881(void);
- *
- * This function returns:
- *  - ERRATA_APPLIES when firmware mitigation is required.
- *  - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required.
- *  - ERRATA_MISSING when firmware mitigation would be required but
- *    is not compiled in.
- *
- * NOTE: Must be called only after cpu_ops have been initialized
- *       in per-CPU data.
- */
-.globl	check_wa_cve_2024_7881
-func check_wa_cve_2024_7881
-	mrs	x0, tpidr_el3
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_DATA_CPU_OPS_PTR]
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_EXTRA4_FUNC]
-	/*
-	 * If the reserved function pointer is NULL, this CPU
-	 * is unaffected by CVE-2024-7881 so bail out.
-	 */
-	cmp	x0, #CPU_NO_EXTRA4_FUNC
-	beq	1f
-	br	x0
-1:
-	mov	x0, #ERRATA_NOT_APPLIES
-	ret
-endfunc check_wa_cve_2024_7881
-
-/*
- * void *wa_cve_2018_3639_get_disable_ptr(void);
- *
- * Returns a function pointer which is used to disable mitigation
- * for CVE-2018-3639.
- * The function pointer is only returned on cores that employ
- * dynamic mitigation.  If the core uses static mitigation or is
- * unaffected by CVE-2018-3639 this function returns NULL.
- *
- * NOTE: Must be called only after cpu_ops have been initialized
- *       in per-CPU data.
- */
-	.globl	wa_cve_2018_3639_get_disable_ptr
-func wa_cve_2018_3639_get_disable_ptr
-	mrs	x0, tpidr_el3
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_DATA_CPU_OPS_PTR]
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_EXTRA2_FUNC]
-	ret
-endfunc wa_cve_2018_3639_get_disable_ptr
-
-/*
- * int check_smccc_arch_wa3_applies(void);
- *
- * This function checks whether SMCCC_ARCH_WORKAROUND_3 is enabled to mitigate
- * CVE-2022-23960 for this CPU. It returns:
- *  - ERRATA_APPLIES when SMCCC_ARCH_WORKAROUND_3 can be invoked to mitigate
- *    the CVE.
- *  - ERRATA_NOT_APPLIES when SMCCC_ARCH_WORKAROUND_3 should not be invoked to
- *    mitigate the CVE.
- *
- * NOTE: Must be called only after cpu_ops have been initialized
- *       in per-CPU data.
- */
-	.globl	check_smccc_arch_wa3_applies
-func check_smccc_arch_wa3_applies
-	mrs	x0, tpidr_el3
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_DATA_CPU_OPS_PTR]
-#if ENABLE_ASSERTIONS
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-	ldr	x0, [x0, #CPU_EXTRA3_FUNC]
-	/*
-	 * If the reserved function pointer is NULL, this CPU
-	 * is unaffected by CVE-2022-23960 so bail out.
-	 */
-	cmp	x0, #CPU_NO_EXTRA3_FUNC
-	beq	1f
-	br	x0
-1:
-	mov	x0, #ERRATA_NOT_APPLIES
-	ret
-endfunc check_smccc_arch_wa3_applies
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index 64158e7..22cd3ba 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -319,11 +319,8 @@
 
 /* macro to declare cpu_ops for Denver SKUs */
 .macro	denver_cpu_ops_wa midr
-	declare_cpu_ops_wa denver, \midr, \
+	declare_cpu_ops denver, \midr, \
 		denver_reset_func, \
-		check_erratum_denver_5715, \
-		CPU_NO_EXTRA2_FUNC, \
-		CPU_NO_EXTRA3_FUNC, \
 		denver_core_pwr_dwn, \
 		denver_cluster_pwr_dwn
 .endm
diff --git a/lib/cpus/aarch64/neoverse_v2.S b/lib/cpus/aarch64/neoverse_v2.S
index ce84942..9526b80 100644
--- a/lib/cpus/aarch64/neoverse_v2.S
+++ b/lib/cpus/aarch64/neoverse_v2.S
@@ -148,10 +148,6 @@
 	ret
 endfunc neoverse_v2_cpu_reg_dump
 
-declare_cpu_ops_wa_4 neoverse_v2, NEOVERSE_V2_MIDR, \
+declare_cpu_ops neoverse_v2, NEOVERSE_V2_MIDR, \
 	neoverse_v2_reset_func, \
-	CPU_NO_EXTRA1_FUNC, \
-	CPU_NO_EXTRA2_FUNC, \
-	CPU_NO_EXTRA3_FUNC, \
-	check_erratum_neoverse_v2_7881, \
 	neoverse_v2_core_pwr_dwn
diff --git a/lib/cpus/aarch64/neoverse_v3.S b/lib/cpus/aarch64/neoverse_v3.S
index 2ead062..ca108e7 100644
--- a/lib/cpus/aarch64/neoverse_v3.S
+++ b/lib/cpus/aarch64/neoverse_v3.S
@@ -124,10 +124,6 @@
 	neoverse_v3_reset_func, \
 	neoverse_v3_core_pwr_dwn
 
-declare_cpu_ops_wa_4 neoverse_v3, NEOVERSE_V3_MIDR, \
+declare_cpu_ops neoverse_v3, NEOVERSE_V3_MIDR, \
 	neoverse_v3_reset_func, \
-	CPU_NO_EXTRA1_FUNC, \
-	CPU_NO_EXTRA2_FUNC, \
-	CPU_NO_EXTRA3_FUNC, \
-	check_erratum_neoverse_v3_7881, \
 	neoverse_v3_core_pwr_dwn
diff --git a/lib/cpus/errata_common.c b/lib/cpus/errata_common.c
index 0530647..a1e6d60 100644
--- a/lib/cpus/errata_common.c
+++ b/lib/cpus/errata_common.c
@@ -6,6 +6,8 @@
 
 /* Runtime C routines for errata workarounds and common routines */
 
+#include <assert.h>
+
 #include <arch.h>
 #include <arch_helpers.h>
 #include <cortex_a75.h>
@@ -26,6 +28,31 @@
 #include <neoverse_n3.h>
 #include <neoverse_v3.h>
 
+struct erratum_entry *find_erratum_entry(uint32_t errata_id)
+{
+	struct cpu_ops *cpu_ops;
+	struct erratum_entry *entry, *end;
+
+	cpu_ops = get_cpu_ops_ptr();
+	assert(cpu_ops != NULL);
+
+	entry = cpu_ops->errata_list_start;
+	assert(entry != NULL);
+
+	end = cpu_ops->errata_list_end;
+	assert(end != NULL);
+
+	end--; /* point to the last erratum entry of the queried cpu */
+
+	while ((entry <= end)) {
+		if (entry->id == errata_id) {
+			return entry;
+		}
+		entry += 1;
+	}
+	return NULL;
+}
+
 bool check_if_trbe_disable_affected_core(void)
 {
 	switch (EXTRACT_PARTNUM(read_midr())) {
@@ -151,3 +178,21 @@
 
 	return false;
 }
+
+int check_erratum_applies(uint32_t cve, int errata_id)
+{
+	struct erratum_entry *entry;
+	long rev_var;
+
+	rev_var = cpu_get_rev_var();
+
+	entry = find_erratum_entry(errata_id);
+
+	if (entry == NULL) {
+		return ERRATA_NOT_APPLIES;
+	}
+
+	assert(entry->cve == cve);
+
+	return entry->check_func(rev_var);
+}
diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c
index 03d18ec..ab68467 100644
--- a/lib/cpus/errata_report.c
+++ b/lib/cpus/errata_report.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -63,9 +63,6 @@
 #else /* !REPORT_ERRATA */
 /*
  * New errata status message printer
- * The order checking function is hidden behind the FEATURE_DETECTION flag to
- * save space. This functionality is only useful on development and platform
- * bringup builds, when FEATURE_DETECTION should be used anyway
  */
 void generic_errata_report(void)
 {
@@ -73,11 +70,6 @@
 	struct erratum_entry *entry = cpu_ops->errata_list_start;
 	struct erratum_entry *end = cpu_ops->errata_list_end;
 	long rev_var = cpu_get_rev_var();
-#if FEATURE_DETECTION
-	uint32_t last_erratum_id = 0;
-	uint16_t last_cve_yr = 0;
-	bool check_cve = false;
-#endif /* FEATURE_DETECTION */
 
 	for (; entry != end; entry += 1) {
 		uint64_t status = entry->check_func(rev_var);
@@ -94,24 +86,6 @@
 		}
 
 		print_status(status, cpu_ops->cpu_str, entry->cve, entry->id);
-
-#if FEATURE_DETECTION
-		if (entry->cve) {
-			if (last_cve_yr > entry->cve ||
-			   (last_cve_yr == entry->cve && last_erratum_id >= entry->id)) {
-				WARN("CVE %u_%u was out of order!\n",
-				      entry->cve, entry->id);
-			}
-			check_cve = true;
-			last_cve_yr = entry->cve;
-		} else {
-			if (last_erratum_id >= entry->id || check_cve) {
-				WARN("Erratum %u was out of order!\n",
-				      entry->id);
-			}
-		}
-		last_erratum_id = entry->id;
-#endif /* FEATURE_DETECTION */
 	}
 }
 
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 132888c..00d9c01 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -155,21 +155,6 @@
 #endif /*  IMAGE_BL32 */
 }
 
-#if !IMAGE_BL1
-/*******************************************************************************
- * The following function initializes the cpu_context for a CPU specified by
- * its `cpu_idx` for first use, and sets the initial entrypoint state as
- * specified by the entry_point_info structure.
- ******************************************************************************/
-void cm_init_context_by_index(unsigned int cpu_idx,
-			      const entry_point_info_t *ep)
-{
-	cpu_context_t *ctx;
-	ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr));
-	cm_setup_context(ctx, ep);
-}
-#endif /* !IMAGE_BL1 */
-
 /*******************************************************************************
  * The following function initializes the cpu_context for the current CPU
  * for first use, and sets the initial entrypoint state as specified by the
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 243a372..7929901 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -343,11 +343,11 @@
 	.endm /* restore_mpam3_el3 */
 
 /* ------------------------------------------------------------------
- * The following macro is used to save and restore all the general
- * purpose and ARMv8.3-PAuth (if enabled) registers.
- * It also checks if the Secure Cycle Counter (PMCCNTR_EL0)
- * is disabled in EL3/Secure (ARMv8.5-PMU), wherein PMCCNTR_EL0
- * needs not to be saved/restored during world switch.
+ * The following macro is used to save all the general purpose
+ * registers and swap the FEAT_PAUTH keys with BL31's keys in
+ * cpu_data. It also checks if the Secure Cycle Counter (PMCCNTR_EL0)
+ * is disabled in EL3/Secure (ARMv8.5-PMU), wherein PMCCNTR_EL0 needs
+ * not to be saved/restored during world switch.
  *
  * Ideally we would only save and restore the callee saved registers
  * when a world switch occurs but that type of implementation is more
@@ -379,6 +379,11 @@
 	mrs	x9, pmcr_el0
 	str	x9, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0]
 #if CTX_INCLUDE_PAUTH_REGS
+#if CTX_INCLUDE_PAUTH_REGS == 2
+	/* Skip if not present in hardware */
+	is_feat_pauth_present_asm x9, x10
+	beq	no_pauth_\@
+#endif
 	/* ----------------------------------------------------------
  	 * Save the ARMv8.3-PAuth keys as they are not banked
  	 * by exception level
@@ -402,6 +407,25 @@
 	stp	x24, x25, [x19, #CTX_PACDAKEY_LO]
 	stp	x26, x27, [x19, #CTX_PACDBKEY_LO]
 	stp	x28, x29, [x19, #CTX_PACGAKEY_LO]
+#if ENABLE_PAUTH
+#if IMAGE_BL31
+	/* tpidr_el3 contains the address of the cpu_data structure */
+	mrs	x9, tpidr_el3
+	/* Load APIAKey from cpu_data */
+	ldp	x10, x11, [x9, #CPU_DATA_APIAKEY_OFFSET]
+#endif /* IMAGE_BL31 */
+
+#if IMAGE_BL1
+	/* BL1 does not use cpu_data and has dedicated storage */
+	adr_l	x9, bl1_apiakey
+	ldp	x10, x11, [x9]
+#endif /* IMAGE_BL1 */
+
+	/* Program instruction key A */
+	msr	APIAKeyLo_EL1, x10
+	msr	APIAKeyHi_EL1, x11
+no_pauth_\@:
+#endif /* ENABLE_PAUTH */
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 	.endm /* save_gp_pmcr_pauth_regs */
 
@@ -442,6 +466,11 @@
  */
 func restore_gp_pmcr_pauth_regs
 #if CTX_INCLUDE_PAUTH_REGS
+#if CTX_INCLUDE_PAUTH_REGS == 2
+	/* Skip if not present in hardware */
+	is_feat_pauth_present_asm x0, x1
+	beq	no_pauth
+#endif
  	/* Restore the ARMv8.3 PAuth keys */
 	add	x10, sp, #CTX_PAUTH_REGS_OFFSET
 
@@ -461,6 +490,7 @@
 	msr	APDBKeyHi_EL1, x7
 	msr	APGAKeyLo_EL1, x8
 	msr	APGAKeyHi_EL1, x9
+no_pauth:
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 
 	/* PMUv3 is presumed to be always present */
diff --git a/lib/el3_runtime/aarch64/context_debug.c b/lib/el3_runtime/aarch64/context_debug.c
index b37bcb7..1addb45 100644
--- a/lib/el3_runtime/aarch64/context_debug.c
+++ b/lib/el3_runtime/aarch64/context_debug.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <string.h>
 
+#include <arch_features.h>
 #include <common/debug.h>
 #include <context.h>
 #include <lib/el3_runtime/context_mgmt.h>
@@ -65,11 +66,11 @@
 #else
 	size_t el1_total = 0U;
 #endif /* CTX_INCLUDE_EL2_REGS */
-
-#if CTX_INCLUDE_PAUTH_REGS
 	size_t pauth_total = 0U;
-	PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
-#endif
+
+	if (is_ctx_pauth_supported()) {
+		PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+	}
 
 	PRINT_MEM_USAGE_SEPARATOR();
 
@@ -80,9 +81,9 @@
 	printf("|    EL1    ");
 #endif /* CTX_INCLUDE_EL2_REGS */
 
-#if CTX_INCLUDE_PAUTH_REGS
-	printf("|   PAUTH   ");
-#endif
+	if (is_ctx_pauth_supported()) {
+		printf("|   PAUTH   ");
+	}
 
 	printf("|   Other   |   Total   |\n");
 
@@ -97,10 +98,9 @@
 		size_t el1_size = 0U;
 #endif /* CTX_INCLUDE_EL2_REGS */
 
-#if CTX_INCLUDE_PAUTH_REGS
-		size_t pauth_size = 0U;
-		PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
-#endif
+		if (is_ctx_pauth_supported()) {
+			PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+		}
 
 		PRINT_MEM_USAGE_SEPARATOR();
 
@@ -125,10 +125,12 @@
 #endif /* CTX_INCLUDE_EL2_REGS */
 
 #if CTX_INCLUDE_PAUTH_REGS
-		pauth_size = sizeof(ctx->pauth_ctx);
-		size_other -= pauth_size;
-		pauth_total += pauth_size;
-		printf("| %8luB ", pauth_size);
+		if (is_ctx_pauth_supported()) {
+			size_t pauth_size = sizeof(ctx->pauth_ctx);
+			size_other -= pauth_size;
+			pauth_total += pauth_size;
+			printf("| %8luB ", pauth_size);
+		}
 #endif
 		printf("| %8luB | %8luB |\n", size_other, core_total);
 
@@ -138,15 +140,15 @@
 		total += core_total;
 	}
 
-#if CTX_INCLUDE_PAUTH_REGS
-	PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
-#endif
+	if (is_ctx_pauth_supported()) {
+		PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+	}
 
 	PRINT_MEM_USAGE_SEPARATOR();
 
-#if CTX_INCLUDE_PAUTH_REGS
-	PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
-#endif
+	if (is_ctx_pauth_supported()) {
+		PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+	}
 
 	PRINT_MEM_USAGE_SEPARATOR();
 
@@ -158,15 +160,15 @@
 	printf("| %8luB ", el1_total);
 #endif /* CTX_INCLUDE_EL2_REGS */
 
-#if CTX_INCLUDE_PAUTH_REGS
-	printf("| %8luB ", pauth_total);
-#endif
+	if (is_ctx_pauth_supported()) {
+		printf("| %8luB ", pauth_total);
+	}
 
 	printf("| %8luB | %8luB |\n", other_total, total);
 
-#if CTX_INCLUDE_PAUTH_REGS
-	PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
-#endif
+	if (is_ctx_pauth_supported()) {
+		PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+	}
 	PRINT_MEM_USAGE_SEPARATOR();
 	printf("\n");
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 021d538..d04e02f 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -30,6 +30,7 @@
 #include <lib/extensions/fgt2.h>
 #include <lib/extensions/fpmr.h>
 #include <lib/extensions/mpam.h>
+#include <lib/extensions/pauth.h>
 #include <lib/extensions/pmuv3.h>
 #include <lib/extensions/sme.h>
 #include <lib/extensions/spe.h>
@@ -227,17 +228,15 @@
 		scr_el3 |= SCR_ATA_BIT;
 	}
 
-#if !CTX_INCLUDE_PAUTH_REGS
 	/*
-	 * Pointer Authentication feature, if present, is always enabled by default
-	 * for Non secure lower exception levels. We do not have an explicit
-	 * flag to set it.
+	 * Pointer Authentication feature, if present, is always enabled by
+	 * default for Non secure lower exception levels. We do not have an
+	 * explicit flag to set it. To prevent the leakage between the worlds
+	 * during world switch, we enable it only for the non-secure world.
+	 *
 	 * CTX_INCLUDE_PAUTH_REGS flag, is explicitly used to enable for lower
 	 * exception levels of secure and realm worlds.
 	 *
-	 * To prevent the leakage between the worlds during world switch,
-	 * we enable it only for the non-secure world.
-	 *
 	 * If the Secure/realm world wants to use pointer authentication,
 	 * CTX_INCLUDE_PAUTH_REGS must be explicitly set to 1, in which case
 	 * it will be enabled globally for all the contexts.
@@ -248,10 +247,9 @@
 	 * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
 	 *  than EL3
 	 */
-	if (is_armv8_3_pauth_present()) {
+	if (!is_ctx_pauth_supported()) {
 		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
 	}
-#endif /* CTX_INCLUDE_PAUTH_REGS */
 
 #if HANDLE_EA_EL3_FIRST_NS
 	/* SCR_EL3.EA: Route External Abort and SError Interrupt to EL3. */
@@ -468,7 +466,6 @@
 	scr_el3 |= SCR_FIEN_BIT;
 #endif
 
-#if CTX_INCLUDE_PAUTH_REGS
 	/*
 	 * Enable Pointer Authentication globally for all the worlds.
 	 *
@@ -478,17 +475,9 @@
 	 * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
 	 *  than EL3
 	 */
-	if (is_armv8_3_pauth_present()) {
+	if (is_ctx_pauth_supported()) {
 		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
 	}
-#endif /* CTX_INCLUDE_PAUTH_REGS */
-
-	/*
-	 * SCR_EL3.TCR2EN: Enable access to TCR2_ELx for AArch64 if present.
-	 */
-	if (is_feat_tcr2_supported() && (GET_RW(ep->spsr) == MODE_RW_64)) {
-		scr_el3 |= SCR_TCR2EN_BIT;
-	}
 
 	/*
 	 * SCR_EL3.PIEN: Enable permission indirection and overlay
@@ -591,6 +580,10 @@
 		trf_enable(ctx);
 	}
 
+	if (is_feat_tcr2_supported()) {
+		tcr2_enable(ctx);
+	}
+
 	pmuv3_enable(ctx);
 #endif /* IMAGE_BL31 */
 
@@ -839,8 +832,10 @@
 		spe_enable(ctx);
 	}
 
-	if (is_feat_trbe_supported()) {
-		trbe_enable(ctx);
+	if (!check_if_trbe_disable_affected_core()) {
+		if (is_feat_trbe_supported()) {
+			trbe_enable(ctx);
+		}
 	}
 
 	if (is_feat_brbe_supported()) {
@@ -849,20 +844,6 @@
 #endif /* IMAGE_BL31 */
 }
 
-/* TODO: move to lib/extensions/pauth when it has been ported to FEAT_STATE */
-static __unused void enable_pauth_el2(void)
-{
-	u_register_t hcr_el2 = read_hcr_el2();
-	/*
-	 * For Armv8.3 pointer authentication feature, disable traps to EL2 when
-	 *  accessing key registers or using pointer authentication instructions
-	 *  from lower ELs.
-	 */
-	hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT);
-
-	write_hcr_el2(hcr_el2);
-}
-
 #if INIT_UNUSED_NS_EL2
 /*******************************************************************************
  * Enable architecture extensions in-place at EL2 on first entry to Non-secure
@@ -909,9 +890,9 @@
 		write_hcrx_el2(read_hcrx_el2() | HCRX_EL2_MSCEn_BIT);
 	}
 
-#if ENABLE_PAUTH
-	enable_pauth_el2();
-#endif /* ENABLE_PAUTH */
+	if (is_feat_pauth_supported()) {
+		pauth_enable_el2();
+	}
 #endif /* IMAGE_BL31 */
 }
 #endif /* INIT_UNUSED_NS_EL2 */
@@ -955,21 +936,6 @@
 #endif /* IMAGE_BL31 */
 }
 
-#if !IMAGE_BL1
-/*******************************************************************************
- * The following function initializes the cpu_context for a CPU specified by
- * its `cpu_idx` for first use, and sets the initial entrypoint state as
- * specified by the entry_point_info structure.
- ******************************************************************************/
-void cm_init_context_by_index(unsigned int cpu_idx,
-			      const entry_point_info_t *ep)
-{
-	cpu_context_t *ctx;
-	ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr));
-	cm_setup_context(ctx, ep);
-}
-#endif /* !IMAGE_BL1 */
-
 /*******************************************************************************
  * The following function initializes the cpu_context for the current CPU
  * for first use, and sets the initial entrypoint state as specified by the
@@ -1647,52 +1613,6 @@
 }
 #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
 
-#if IMAGE_BL31
-/*********************************************************************************
-* This function allows Architecture features asymmetry among cores.
-* TF-A assumes that all the cores in the platform has architecture feature parity
-* and hence the context is setup on different core (e.g. primary sets up the
-* context for secondary cores).This assumption may not be true for systems where
-* cores are not conforming to same Arch version or there is CPU Erratum which
-* requires certain feature to be be disabled only on a given core.
-*
-* This function is called on secondary cores to override any disparity in context
-* setup by primary, this would be called during warmboot path.
-*********************************************************************************/
-void cm_handle_asymmetric_features(void)
-{
-	cpu_context_t *ctx __maybe_unused = cm_get_context(NON_SECURE);
-
-	assert(ctx != NULL);
-
-#if ENABLE_SPE_FOR_NS == FEAT_STATE_CHECK_ASYMMETRIC
-	if (is_feat_spe_supported()) {
-		spe_enable(ctx);
-	} else {
-		spe_disable(ctx);
-	}
-#endif
-
-	if (check_if_trbe_disable_affected_core()) {
-		if (is_feat_trbe_supported()) {
-			trbe_disable(ctx);
-		}
-	}
-
-#if ENABLE_FEAT_TCR2 == FEAT_STATE_CHECK_ASYMMETRIC
-	el3_state_t *el3_state = get_el3state_ctx(ctx);
-	u_register_t spsr = read_ctx_reg(el3_state, CTX_SPSR_EL3);
-
-	if (is_feat_tcr2_supported() && (GET_RW(spsr) == MODE_RW_64)) {
-		tcr2_enable(ctx);
-	} else {
-		tcr2_disable(ctx);
-	}
-#endif
-
-}
-#endif
-
 /*******************************************************************************
  * This function is used to exit to Non-secure world. If CTX_INCLUDE_EL2_REGS
  * is enabled, it restores EL1 and EL2 sysreg contexts instead of directly
@@ -1701,18 +1621,6 @@
  ******************************************************************************/
 void cm_prepare_el3_exit_ns(void)
 {
-#if IMAGE_BL31
-	/*
-	 * Check and handle Architecture feature asymmetry among cores.
-	 *
-	 * In warmboot path secondary cores context is initialized on core which
-	 * did CPU_ON SMC call, if there is feature asymmetry in these cores handle
-	 * it in this function call.
-	 * For Symmetric cores this is an empty function.
-	 */
-	cm_handle_asymmetric_features();
-#endif
-
 #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
 #if ENABLE_ASSERTIONS
 	cpu_context_t *ctx = cm_get_context(NON_SECURE);
diff --git a/lib/extensions/pauth/pauth.c b/lib/extensions/pauth/pauth.c
new file mode 100644
index 0000000..fbbcaa2
--- /dev/null
+++ b/lib/extensions/pauth/pauth.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/el3_runtime/cpu_data.h>
+#include <lib/extensions/pauth.h>
+
+extern uint64_t bl1_apiakey[2];
+
+void __no_pauth pauth_init_enable_el3(void)
+{
+	if (is_feat_pauth_supported()) {
+		pauth_init();
+		pauth_enable_el3();
+	}
+}
+
+void __no_pauth pauth_init_enable_el1(void)
+{
+	if (is_feat_pauth_supported()) {
+		pauth_init();
+		pauth_enable_el1();
+	}
+}
+
+void pauth_init(void)
+{
+	uint128_t keys = plat_init_apkey();
+	uint64_t key_lo = LO_64(keys);
+	uint64_t key_hi = HI_64(keys);
+
+	/* Program instruction key A used by the Trusted Firmware */
+	write_apiakeylo_el1(key_lo);
+	write_apiakeyhi_el1(key_hi);
+
+#if IMAGE_BL31
+	set_cpu_data(apiakey[0], key_lo);
+	set_cpu_data(apiakey[1], key_hi);
+
+	/*
+	 * In the warmboot entrypoint, cpu_data may have been written before
+	 * data caching was enabled. Flush the caches so nothing stale is read.
+	 */
+#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
+	flush_cpu_data(apiakey);
+#endif
+#elif IMAGE_BL1
+	bl1_apiakey[0] = key_lo;
+	bl1_apiakey[1] = key_hi;
+#endif
+}
+
+/*
+ * Begin checking function calls at the current EL. This function must not have
+ * PAuth guards because the signing will be a NOP and attempting to authenticate
+ * will fail. Includes an ISB to avoid accidental failures.
+ */
+void __no_pauth pauth_enable_el3(void)
+{
+	write_sctlr_el3(read_sctlr_el3() | SCTLR_EnIA_BIT);
+
+	if (is_feat_pauth_lr_supported()) {
+		write_sctlr2_el3(read_sctlr2_el3() | SCTLR2_EnPACM_BIT);
+	}
+
+	isb();
+}
+
+void __no_pauth pauth_enable_el1(void)
+{
+	write_sctlr_el1(read_sctlr_el1() | SCTLR_EnIA_BIT);
+
+	if (is_feat_pauth_lr_supported()) {
+		write_sctlr2_el1(read_sctlr2_el1() | SCTLR2_EnPACM_BIT);
+	}
+
+	isb();
+}
+
+void pauth_enable_el2(void)
+{
+	u_register_t hcr_el2 = read_hcr_el2();
+	/*
+	 * For Armv8.3 pointer authentication feature, disable traps to EL2 when
+	 * accessing key registers or using pointer authentication instructions
+	 * from lower ELs.
+	 */
+	hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT);
+
+	write_hcr_el2(hcr_el2);
+}
+
+void __no_pauth pauth_disable_el1(void)
+{
+	write_sctlr_el1(read_sctlr_el1() & ~SCTLR_EnIA_BIT);
+	isb(); /* usually called by caller, here it's for compatibility */
+}
+
+void __no_pauth pauth_disable_el3(void)
+{
+	write_sctlr_el3(read_sctlr_el3() & ~SCTLR_EnIA_BIT);
+	isb(); /* usually called by caller, here it's for compatibility */
+}
diff --git a/lib/extensions/pauth/pauth_helpers.S b/lib/extensions/pauth/pauth_helpers.S
deleted file mode 100644
index fb5fa97..0000000
--- a/lib/extensions/pauth/pauth_helpers.S
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <asm_macros.S>
-#include <lib/el3_runtime/cpu_data.h>
-
-	.global	pauth_init_enable_el1
-	.global	pauth_disable_el1
-	.global	pauth_init_enable_el3
-	.global	pauth_disable_el3
-	.globl	pauth_load_bl31_apiakey
-	.globl	pauth_load_bl1_apiakey_enable
-
-/* -------------------------------------------------------------
- * Program APIAKey_EL1 and enable pointer authentication in EL1
- * -------------------------------------------------------------
- */
-func pauth_init_enable_el1
-	stp	x29, x30, [sp, #-16]!
-
-	/* Initialize platform key */
-	bl	plat_init_apkey
-
-	/* Program instruction key A used by the Trusted Firmware */
-	msr	APIAKeyLo_EL1, x0
-	msr	APIAKeyHi_EL1, x1
-
-	/* Enable pointer authentication */
-	mrs	x0, sctlr_el1
-	orr	x0, x0, #SCTLR_EnIA_BIT
-
-#if ENABLE_BTI
-	 /* Enable PAC branch type compatibility */
-	bic	x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT)
-#endif
-	msr	sctlr_el1, x0
-	isb
-
-	ldp	x29, x30, [sp], #16
-	ret
-endfunc pauth_init_enable_el1
-
-/* -------------------------------------------------------------
- * Disable pointer authentication in EL1
- * -------------------------------------------------------------
- */
-func pauth_disable_el1
-	mrs	x0, sctlr_el1
-	bic	x0, x0, #SCTLR_EnIA_BIT
-	msr	sctlr_el1, x0
-	isb
-	ret
-endfunc pauth_disable_el1
-
-/* -------------------------------------------------------------
- * Program APIAKey_EL1 and enable pointer authentication in EL3
- * -------------------------------------------------------------
- */
-func pauth_init_enable_el3
-	stp	x29, x30, [sp, #-16]!
-
-	/* Initialize platform key */
-	bl	plat_init_apkey
-
-	/* Program instruction key A used by the Trusted Firmware */
-	msr	APIAKeyLo_EL1, x0
-	msr	APIAKeyHi_EL1, x1
-
-	/* Enable pointer authentication */
-	mrs	x0, sctlr_el3
-	orr	x0, x0, #SCTLR_EnIA_BIT
-
-#if ENABLE_BTI
-	 /* Enable PAC branch type compatibility */
-	bic	x0, x0, #SCTLR_BT_BIT
-#endif
-	msr	sctlr_el3, x0
-	isb
-
-	ldp	x29, x30, [sp], #16
-	ret
-endfunc pauth_init_enable_el3
-
-/* -------------------------------------------------------------
- * Disable pointer authentication in EL3
- * -------------------------------------------------------------
- */
-func pauth_disable_el3
-	mrs	x0, sctlr_el3
-	bic	x0, x0, #SCTLR_EnIA_BIT
-	msr	sctlr_el3, x0
-	isb
-	ret
-endfunc pauth_disable_el3
-
-/* -------------------------------------------------------------
- * The following functions strictly follow the AArch64 PCS
- * to use x9-x17 (temporary caller-saved registers) to load
- * the APIAKey_EL1 and enable pointer authentication.
- * -------------------------------------------------------------
- */
-func pauth_load_bl31_apiakey
-	/* tpidr_el3 contains the address of cpu_data structure */
-	mrs	x9, tpidr_el3
-
-	/* Load apiakey from cpu_data */
-	ldp	x10, x11, [x9, #CPU_DATA_APIAKEY_OFFSET]
-
-	/* Program instruction key A */
-	msr	APIAKeyLo_EL1, x10
-	msr	APIAKeyHi_EL1, x11
-	isb
-	ret
-endfunc pauth_load_bl31_apiakey
-
-func pauth_load_bl1_apiakey_enable
-	/* Load instruction key A used by the Trusted Firmware */
-	adrp	x9, bl1_apiakey
-	add	x9, x9, :lo12:bl1_apiakey
-	ldp	x10, x11, [x9]
-
-	/* Program instruction key A */
-	msr	APIAKeyLo_EL1, x10
-	msr	APIAKeyHi_EL1, x11
-
-	/* Enable pointer authentication */
-	mrs	x9, sctlr_el3
-	orr	x9, x9, #SCTLR_EnIA_BIT
-
-#if ENABLE_BTI
-	 /* Enable PAC branch type compatibility */
-	bic	x9, x9, #SCTLR_BT_BIT
-#endif
-	msr	sctlr_el3, x9
-	isb
-	ret
-endfunc pauth_load_bl1_apiakey_enable
diff --git a/lib/extensions/pmuv3/aarch64/pmuv3.c b/lib/extensions/pmuv3/aarch64/pmuv3.c
index 61d1258..b47b664 100644
--- a/lib/extensions/pmuv3/aarch64/pmuv3.c
+++ b/lib/extensions/pmuv3/aarch64/pmuv3.c
@@ -78,11 +78,14 @@
 	 *   1  |  1   |    enabled   | disabled only for counters 0 to
 	 *                              MDCR_EL2.HPMN - 1. Enabled for the rest
 	 *
+	 * MDCR_EL3.EnPM2: Set to one so that various PMUv3p9 related system
+	 * register accesses do not trap to EL3.
+	 *
 	 * MDCR_EL3.TPM: Set to zero so that EL0, EL1, and EL2 System register
 	 *  accesses to all Performance Monitors registers do not trap to EL3.
 	 */
-	mdcr_el3_val = (mdcr_el3_val | MDCR_SCCD_BIT | MDCR_MCCD_BIT) &
-		  ~(MDCR_MPMX_BIT | MDCR_SPME_BIT | MDCR_TPM_BIT);
+	mdcr_el3_val |= MDCR_SCCD_BIT | MDCR_MCCD_BIT | MDCR_EnPM2_BIT;
+	mdcr_el3_val &=	~(MDCR_MPMX_BIT | MDCR_SPME_BIT | MDCR_TPM_BIT);
 	mdcr_el3_val = mtpmu_disable_el3(mdcr_el3_val);
 
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
diff --git a/lib/libc/memchr.c b/lib/libc/memchr.c
index 66d7ba1..e009a5f 100644
--- a/lib/libc/memchr.c
+++ b/lib/libc/memchr.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 void *memchr(const void *src, int c, size_t len)
 {
diff --git a/lib/libc/memcmp.c b/lib/libc/memcmp.c
index db2701b..1458208 100644
--- a/lib/libc/memcmp.c
+++ b/lib/libc/memcmp.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 int memcmp(const void *s1, const void *s2, size_t len)
 {
diff --git a/lib/libc/memcpy.c b/lib/libc/memcpy.c
index af9ed45..ca31de5 100644
--- a/lib/libc/memcpy.c
+++ b/lib/libc/memcpy.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 void *memcpy(void *dst, const void *src, size_t len)
 {
diff --git a/lib/libc/memcpy_s.c b/lib/libc/memcpy_s.c
index 26953bf..ee87637 100644
--- a/lib/libc/memcpy_s.c
+++ b/lib/libc/memcpy_s.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2023, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -53,12 +53,7 @@
 		}
 	}
 
-	/*
-	 * Start copy process when there is no error
-	 */
-	while (ssize--) {
-		d[ssize] = s[ssize];
-	}
+	(void)memcpy(dst, src, ssize);
 
 	return 0;
 }
diff --git a/lib/libc/memmove.c b/lib/libc/memmove.c
index 5c2b661..6451e4e 100644
--- a/lib/libc/memmove.c
+++ b/lib/libc/memmove.c
@@ -16,7 +16,7 @@
 	 * that issue is probably moot as such usage is probably undefined
 	 * behaviour and a bug anyway.
 	 */
-	if ((size_t)dst - (size_t)src >= len) {
+	if (((size_t)dst - (size_t)src) >= len) {
 		/* destination not in source data, so can safely use memcpy */
 		return memcpy(dst, src, len);
 	} else {
diff --git a/lib/libc/memset.c b/lib/libc/memset.c
index c5bac8d..2513221 100644
--- a/lib/libc/memset.c
+++ b/lib/libc/memset.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 #include <stdint.h>
 
 void *memset(void *dst, int val, size_t count)
diff --git a/lib/libc/printf.c b/lib/libc/printf.c
index a856345..2a4b9db 100644
--- a/lib/libc/printf.c
+++ b/lib/libc/printf.c
@@ -44,19 +44,19 @@
 	unsigned int rem;
 
 	/* num_buf is only large enough for radix >= 10 */
-	if (radix < 10) {
+	if (radix < 10U) {
 		assert(0);
 		return 0;
 	}
 
 	do {
-		rem = unum % radix;
-		if (rem < 0xa) {
+		rem = (uint32_t)(unum % radix);
+		if (rem < 0xaU) {
 			num_buf[i] = '0' + rem;
 		} else if (uppercase) {
-			num_buf[i] = 'A' + (rem - 0xa);
+			num_buf[i] = 'A' + (rem - 0xaU);
 		} else {
-			num_buf[i] = 'a' + (rem - 0xa);
+			num_buf[i] = 'a' + (rem - 0xaU);
 		}
 		i++;
 		unum /= radix;
@@ -64,14 +64,14 @@
 
 	if (padn > 0) {
 		while (i < padn) {
-			(void)putchar(padc);
+			(void)putchar((int32_t)padc);
 			count++;
 			padn--;
 		}
 	}
 
 	while (--i >= 0) {
-		(void)putchar(num_buf[i]);
+		(void)putchar((int32_t)num_buf[i]);
 		count++;
 	}
 
@@ -122,13 +122,13 @@
 loop:
 			switch (*fmt) {
 			case '%':
-				(void)putchar('%');
+				(void)putchar((int32_t)'%');
 				break;
 			case 'i': /* Fall through to next one */
 			case 'd':
 				num = get_num_va_args(args, l_count);
 				if (num < 0) {
-					(void)putchar('-');
+					(void)putchar((int32_t)'-');
 					unum = (unsigned long long int)-num;
 					padn--;
 				} else
diff --git a/lib/libc/strchr.c b/lib/libc/strchr.c
index 1cd03ca..b3bebe4 100644
--- a/lib/libc/strchr.c
+++ b/lib/libc/strchr.c
@@ -30,12 +30,12 @@
  */
 
 /*
- * Portions copyright (c) 2018, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * All rights reserved.
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 char *
 strchr(const char *p, int ch)
diff --git a/lib/libc/strcmp.c b/lib/libc/strcmp.c
index 290db4c..5afd0e9 100644
--- a/lib/libc/strcmp.c
+++ b/lib/libc/strcmp.c
@@ -33,11 +33,11 @@
  */
 
 /*
- * Portions copyright (c) 2018, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * All rights reserved.
  */
 
-#include <string.h>
+#include <string_private.h>
 
 /*
  * Compare strings.
diff --git a/lib/libc/strlen.c b/lib/libc/strlen.c
index e4b79d9..cc1d1df 100644
--- a/lib/libc/strlen.c
+++ b/lib/libc/strlen.c
@@ -1,10 +1,10 @@
 /*
- * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <string.h>
+#include <string_private.h>
 
 size_t strlen(const char *s)
 {
diff --git a/lib/libc/strncmp.c b/lib/libc/strncmp.c
index f0bbadc..828e0c5 100644
--- a/lib/libc/strncmp.c
+++ b/lib/libc/strncmp.c
@@ -30,11 +30,11 @@
  */
 
 /*
- * Portions copyright (c) 2018, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * All rights reserved.
  */
 
-#include <string.h>
+#include <string_private.h>
 
 int
 strncmp(const char *s1, const char *s2, size_t n)
diff --git a/lib/libc/strrchr.c b/lib/libc/strrchr.c
index cd435ff..98f76c6 100644
--- a/lib/libc/strrchr.c
+++ b/lib/libc/strrchr.c
@@ -30,7 +30,7 @@
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 char *
 strrchr(const char *p, int ch)
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 17ecab8..1c634e3 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1032,6 +1032,13 @@
 	}
 
 	/*
+	 * Caches and (importantly) coherency are on so we can rely on seeing
+	 * whatever the primary gave us without explicit cache maintenance
+	 */
+	entry_point_info_t *ep = get_cpu_data(warmboot_ep_info);
+	cm_init_my_context(ep);
+
+	/*
 	 * Generic management: Now we just need to retrieve the
 	 * information that we had stashed away during the cpu_on
 	 * call to set this cpu on its way.
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 34668ea..f126f49 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -28,15 +28,17 @@
 
 {
 	int rc;
-	entry_point_info_t ep;
+	entry_point_info_t *ep;
+	unsigned int target_idx = (unsigned int)plat_core_pos_by_mpidr(target_cpu);
 
 	/* Validate the target CPU */
 	if (!is_valid_mpidr(target_cpu)) {
 		return PSCI_E_INVALID_PARAMS;
 	}
 
-	/* Validate the entry point and get the entry_point_info */
-	rc = psci_validate_entry_point(&ep, entrypoint, context_id);
+	ep = get_cpu_data_by_index(target_idx, warmboot_ep_info);
+	/* Validate the lower EL entry point and put it in the entry_point_info */
+	rc = psci_validate_entry_point(ep, entrypoint, context_id);
 	if (rc != PSCI_E_SUCCESS) {
 		return rc;
 	}
@@ -45,7 +47,7 @@
 	 * To turn this cpu on, specify which power
 	 * levels need to be turned on
 	 */
-	return psci_cpu_on_start(target_cpu, &ep);
+	return psci_cpu_on_start(target_cpu, ep);
 }
 
 unsigned int psci_version(void)
@@ -59,7 +61,6 @@
 {
 	int rc;
 	unsigned int target_pwrlvl, is_power_down_state;
-	entry_point_info_t ep;
 	psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
 	plat_local_state_t cpu_pd_state;
 	unsigned int cpu_idx = plat_my_core_pos();
@@ -173,7 +174,9 @@
 	 * point and program entry information.
 	 */
 	if (is_power_down_state != 0U) {
-		rc = psci_validate_entry_point(&ep, entrypoint, context_id);
+		entry_point_info_t *ep = get_cpu_data_by_index(cpu_idx, warmboot_ep_info);
+
+		rc = psci_validate_entry_point(ep, entrypoint, context_id);
 		if (rc != PSCI_E_SUCCESS) {
 			return rc;
 		}
@@ -186,7 +189,6 @@
 	 * arrival of an interrupt
 	 */
 	rc = psci_cpu_suspend_start(cpu_idx,
-				    &ep,
 				    target_pwrlvl,
 				    &state_info,
 				    is_power_down_state);
@@ -199,8 +201,8 @@
 {
 	int rc;
 	psci_power_state_t state_info;
-	entry_point_info_t ep;
 	unsigned int cpu_idx = plat_my_core_pos();
+	entry_point_info_t *ep = get_cpu_data_by_index(cpu_idx, warmboot_ep_info);
 
 	/* Check if the current CPU is the last ON CPU in the system */
 	if (!psci_is_last_on_cpu(cpu_idx)) {
@@ -208,7 +210,7 @@
 	}
 
 	/* Validate the entry point and get the entry_point_info */
-	rc = psci_validate_entry_point(&ep, entrypoint, context_id);
+	rc = psci_validate_entry_point(ep, entrypoint, context_id);
 	if (rc != PSCI_E_SUCCESS) {
 		return rc;
 	}
@@ -235,7 +237,6 @@
 	 * arrival of an interrupt
 	 */
 	rc = psci_cpu_suspend_start(cpu_idx,
-				    &ep,
 				    PLAT_MAX_PWR_LVL,
 				    &state_info,
 				    PSTATE_TYPE_POWERDOWN);
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index 932a039..2485601 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -11,6 +11,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/arm/gic.h>
 #include <lib/pmf/pmf.h>
 #include <lib/runtime_instr.h>
 #include <plat/common/platform.h>
@@ -117,6 +118,13 @@
 	 */
 	psci_pwrdown_cpu_start(psci_find_max_off_lvl(&state_info));
 
+#if USE_GIC_DRIVER
+	/* turn the GIC off before we hand off to the platform */
+	gic_cpuif_disable(idx);
+	/* we don't want any wakeups until explicitly turned on */
+	gic_pcpu_off(idx);
+#endif /* USE_GIC_DRIVER */
+
 	/*
 	 * Plat. management: Perform platform specific actions to turn this
 	 * cpu off e.g. exit cpu coherency, program the power controller etc.
diff --git a/lib/psci/psci_on.c b/lib/psci/psci_on.c
index 3eacb9c..4ae07e1 100644
--- a/lib/psci/psci_on.c
+++ b/lib/psci/psci_on.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
+#include <drivers/arm/gic.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/el3_runtime/pubsub_events.h>
 #include <plat/common/platform.h>
@@ -141,10 +142,7 @@
 	rc = psci_plat_pm_ops->pwr_domain_on(target_cpu);
 	assert((rc == PSCI_E_SUCCESS) || (rc == PSCI_E_INTERN_FAIL));
 
-	if (rc == PSCI_E_SUCCESS) {
-		/* Store the re-entry information for the non-secure world. */
-		cm_init_context_by_index(target_idx, ep);
-	} else {
+	if (rc != PSCI_E_SUCCESS) {
 		/* Restore the state on error. */
 		psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_OFF);
 		flush_cpu_data_by_index(target_idx,
@@ -186,6 +184,13 @@
 	if (psci_plat_pm_ops->pwr_domain_on_finish_late != NULL) {
 		psci_plat_pm_ops->pwr_domain_on_finish_late(state_info);
 	}
+
+#if USE_GIC_DRIVER
+	/* GIC init after platform has had a say with MMU on */
+	gic_pcpu_init(cpu_idx);
+	gic_cpuif_enable(cpu_idx);
+#endif /* USE_GIC_DRIVER */
+
 	/*
 	 * All the platform specific actions for turning this cpu
 	 * on have completed. Perform enough arch.initialization
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 49b19c9..f3f5a5c 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -344,7 +344,6 @@
 
 /* Private exported functions from psci_suspend.c */
 int psci_cpu_suspend_start(unsigned int idx,
-			   const entry_point_info_t *ep,
 			   unsigned int end_pwrlvl,
 			   psci_power_state_t *state_info,
 			   unsigned int is_power_down_state);
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index 3604549..0863a82 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,6 +30,7 @@
  * of relying on platform defined constants.
  ******************************************************************************/
 static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT];
+static entry_point_info_t warmboot_ep_info[PLATFORM_CORE_COUNT];
 
 /******************************************************************************
  * Define the psci capability variable.
@@ -114,6 +115,13 @@
 	}
 }
 
+static void __init populate_cpu_data(void)
+{
+	for (unsigned int idx = 0; idx < psci_plat_core_count; idx++) {
+		set_cpu_data_by_index(idx, warmboot_ep_info, &warmboot_ep_info[idx]);
+	}
+}
+
 /*******************************************************************************
  * Core routine to populate the power domain tree. The tree descriptor passed by
  * the platform is populated breadth-first and the first entry in the map
@@ -218,6 +226,9 @@
 	/* Update the CPU limits for each node in psci_non_cpu_pd_nodes */
 	psci_update_pwrlvl_limits();
 
+	/* Initialise the warmboot entrypoints */
+	populate_cpu_data();
+
 	/* Populate the mpidr field of cpu node for this CPU */
 	psci_cpu_pd_nodes[cpu_idx].mpidr =
 		read_mpidr() & MPIDR_AFFINITY_MASK;
@@ -308,11 +319,6 @@
 	/* Having initialized cpu_ops, we can now print errata status */
 	print_errata_status();
 
-#if ENABLE_PAUTH
-	/* Store APIAKey_EL1 key */
-	set_cpu_data(apiakey[0], read_apiakeylo_el1());
-	set_cpu_data(apiakey[1], read_apiakeyhi_el1());
-#endif /* ENABLE_PAUTH */
 }
 
 /******************************************************************************
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index f690e49..73b9a67 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -12,6 +12,7 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <context.h>
+#include <drivers/arm/gic.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/el3_runtime/cpu_data.h>
 #include <lib/el3_runtime/pubsub_events.h>
@@ -45,7 +46,6 @@
 static void psci_suspend_to_pwrdown_start(unsigned int idx,
 					  unsigned int end_pwrlvl,
 					  unsigned int max_off_lvl,
-					  const entry_point_info_t *ep,
 					  const psci_power_state_t *state_info)
 {
 	PUBLISH_EVENT_ARG(psci_suspend_pwrdown_start, &idx);
@@ -85,12 +85,6 @@
 	if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early != NULL)
 		psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info);
 #endif
-
-	/*
-	 * Store the re-entry information for the non-secure world.
-	 */
-	cm_init_my_context(ep);
-
 	/*
 	 * Arch. management. Initiate power down sequence.
 	 */
@@ -116,7 +110,6 @@
  * not possible to undo any of the actions taken beyond that point.
  ******************************************************************************/
 int psci_cpu_suspend_start(unsigned int idx,
-			   const entry_point_info_t *ep,
 			   unsigned int end_pwrlvl,
 			   psci_power_state_t *state_info,
 			   unsigned int is_power_down_state)
@@ -124,10 +117,6 @@
 	int rc = PSCI_E_SUCCESS;
 	unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
 	unsigned int max_off_lvl = 0;
-#if FEAT_PABANDON
-	cpu_context_t *ctx = cm_get_context(NON_SECURE);
-	cpu_context_t old_ctx;
-#endif
 
 	/*
 	 * This function must only be called on platforms where the
@@ -205,35 +194,22 @@
 #if !CTX_INCLUDE_EL2_REGS
 		cm_el1_sysregs_context_save(NON_SECURE);
 #endif
-		/*
-		 * when the core wakes it expects its context to already be in
-		 * place so we must overwrite it before powerdown. But if
-		 * powerdown never happens we want the old context. Save it in
-		 * case we wake up. EL2/El1 will not be touched by PSCI so don't
-		 * copy */
-		memcpy(&ctx->gpregs_ctx, &old_ctx.gpregs_ctx, sizeof(gp_regs_t));
-		memcpy(&ctx->el3state_ctx, &old_ctx.el3state_ctx, sizeof(el3_state_t));
-#if DYNAMIC_WORKAROUND_CVE_2018_3639
-		memcpy(&ctx->cve_2018_3639_ctx, &old_ctx.cve_2018_3639_ctx, sizeof(cve_2018_3639_t));
-#endif
-#if ERRATA_SPECULATIVE_AT
-		memcpy(&ctx->errata_speculative_at_ctx, &old_ctx.errata_speculative_at_ctx, sizeof(errata_speculative_at_t));
-#endif
-#if CTX_INCLUDE_PAUTH_REGS
-		memcpy(&ctx->pauth_ctx, &old_ctx.pauth_ctx, sizeof(pauth_t));
-#endif
 #endif
 		max_off_lvl = psci_find_max_off_lvl(state_info);
-		psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, ep, state_info);
+		psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, state_info);
 	}
 
+#if USE_GIC_DRIVER
+	/* turn the GIC off before we hand off to the platform */
+	gic_cpuif_disable(idx);
+#endif /* USE_GIC_DRIVER */
+
 	/*
 	 * Plat. management: Allow the platform to perform the
 	 * necessary actions to turn off this cpu e.g. set the
 	 * platform defined mailbox with the psci entrypoint,
 	 * program the power controller etc.
 	 */
-
 	psci_plat_pm_ops->pwr_domain_suspend(state_info);
 
 #if ENABLE_PSCI_STAT
@@ -301,18 +277,6 @@
 #if FEAT_PABANDON
 		psci_cpu_suspend_to_powerdown_finish(idx, max_off_lvl, state_info);
 
-		/* we overwrote context ourselves, put it back */
-		memcpy(&ctx->gpregs_ctx, &old_ctx.gpregs_ctx, sizeof(gp_regs_t));
-		memcpy(&ctx->el3state_ctx, &old_ctx.el3state_ctx, sizeof(el3_state_t));
-#if DYNAMIC_WORKAROUND_CVE_2018_3639
-		memcpy(&ctx->cve_2018_3639_ctx, &old_ctx.cve_2018_3639_ctx, sizeof(cve_2018_3639_t));
-#endif
-#if ERRATA_SPECULATIVE_AT
-		memcpy(&ctx->errata_speculative_at_ctx, &old_ctx.errata_speculative_at_ctx, sizeof(errata_speculative_at_t));
-#endif
-#if CTX_INCLUDE_PAUTH_REGS
-		memcpy(&ctx->pauth_ctx, &old_ctx.pauth_ctx, sizeof(pauth_t));
-#endif
 #if !CTX_INCLUDE_EL2_REGS
 		cm_el1_sysregs_context_restore(NON_SECURE);
 #endif
@@ -321,6 +285,11 @@
 		psci_cpu_suspend_to_standby_finish(end_pwrlvl, state_info);
 	}
 
+#if USE_GIC_DRIVER
+	/* Turn GIC on after platform has had a chance to do state management */
+	gic_cpuif_enable(idx);
+#endif /* USE_GIC_DRIVER */
+
 	/*
 	 * Set the requested and target state of this CPU and all the higher
 	 * power domain levels for this CPU to run.
@@ -361,16 +330,15 @@
 	psci_do_pwrup_cache_maintenance();
 #endif
 
+#if USE_GIC_DRIVER
+	/* GIC on after platform has had its say and MMU is on */
+	gic_cpuif_enable(cpu_idx);
+#endif /* USE_GIC_DRIVER */
+
 	/* Re-init the cntfrq_el0 register */
 	counter_freq = plat_get_syscnt_freq2();
 	write_cntfrq_el0(counter_freq);
 
-#if ENABLE_PAUTH
-	/* Store APIAKey_EL1 key */
-	set_cpu_data(apiakey[0], read_apiakeylo_el1());
-	set_cpu_data(apiakey[1], read_apiakeyhi_el1());
-#endif /* ENABLE_PAUTH */
-
 	/*
 	 * Call the cpu suspend finish handler registered by the Secure Payload
 	 * Dispatcher to let it do any bookeeping. If the handler encounters an
diff --git a/lib/psci/psci_system_off.c b/lib/psci/psci_system_off.c
index 1dcaa23..19f2476 100644
--- a/lib/psci/psci_system_off.c
+++ b/lib/psci/psci_system_off.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/arm/gic.h>
 #include <drivers/console.h>
 #include <plat/common/platform.h>
 
@@ -27,6 +28,11 @@
 
 	console_flush();
 
+#if USE_GIC_DRIVER
+	/* turn the GIC off before we hand off to the platform */
+	gic_cpuif_disable(plat_my_core_pos());
+#endif /* USE_GIC_DRIVER */
+
 	/* Call the platform specific hook */
 	psci_plat_pm_ops->system_off();
 
@@ -46,6 +52,11 @@
 
 	console_flush();
 
+#if USE_GIC_DRIVER
+	/* turn the GIC off before we hand off to the platform */
+	gic_cpuif_disable(plat_my_core_pos());
+#endif /* USE_GIC_DRIVER */
+
 	/* Call the platform specific hook */
 	psci_plat_pm_ops->system_reset();
 
@@ -80,6 +91,11 @@
 	}
 	console_flush();
 
+#if USE_GIC_DRIVER
+	/* turn the GIC off before we hand off to the platform */
+	gic_cpuif_disable(plat_my_core_pos());
+#endif /* USE_GIC_DRIVER */
+
 	u_register_t ret =
 		(u_register_t) psci_plat_pm_ops->system_reset2((int) is_vendor, reset_type, cookie);
 	if (ret != PSCI_E_SUCCESS)
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index bd7f017..76aba50 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -210,17 +210,14 @@
 				desc |= LOWER_ATTRS(ISH);
 			}
 
-			/* Check if Branch Target Identification is enabled */
-#if ENABLE_BTI
 			/* Set GP bit for block and page code entries
 			 * if BTI mechanism is implemented.
 			 */
-			if (is_feat_bti_present() &&
+			if (is_feat_bti_supported() &&
 			   ((attr & (MT_TYPE_MASK | MT_RW |
 				MT_EXECUTE_NEVER)) == MT_CODE)) {
 				desc |= GP;
 			}
-#endif
 		} else {
 			assert(mem_type == MT_NON_CACHEABLE);
 			desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index 56bfb64..1561a59 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -160,6 +160,11 @@
 # direct setting. Use BRANCH_PROTECTION to enable PAUTH.
 ENABLE_PAUTH			?=	0
 
+# FEAT_PAUTH_LR is an optional architectural feature, so this flag must be set
+# manually in addition to the BRANCH_PROTECTION flag which is used for other
+# branch protection and pointer authentication features.
+ENABLE_FEAT_PAUTH_LR		?=	0
+
 # Include pointer authentication (ARMv8.3-PAuth) registers in cpu context. This
 # must be set to 1 if the platform wants to use this feature in the Secure
 # world. It is not necessary for use in the Non-secure world.
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 906e5d7..f438a9d 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -156,6 +156,9 @@
 # default, they are for Secure EL1.
 GICV2_G0_FOR_EL3		:= 0
 
+# Generic implementation of a GICvX driver
+USE_GIC_DRIVER			:= 0
+
 # Route NS External Aborts to EL3. Disabled by default; External Aborts are handled
 # by lower ELs.
 HANDLE_EA_EL3_FIRST_NS		:= 0
@@ -432,3 +435,8 @@
 
 # Enable RMMD to forward attestation requests from RMM to EL3.
 RMMD_ENABLE_EL3_TOKEN_SIGN	:= 0
+
+# Enable RMMD to program and manage IDE Keys at the PCIe Root Port(RP).
+# This flag is temporary and it is expected once the interface is
+# finalized, this flag will be removed.
+RMMD_ENABLE_IDE_KEY_PROG	:= 0
diff --git a/plat/amd/versal2/include/plat_ipi.h b/plat/amd/versal2/include/plat_ipi.h
index 503ec1f..c110fb8 100644
--- a/plat/amd/versal2/include/plat_ipi.h
+++ b/plat/amd/versal2/include/plat_ipi.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #define PLAT_IPI_H
 
 #include <stdint.h>
+#include <lib/utils_def.h>
 
 #include <ipi.h>
 
@@ -24,7 +25,15 @@
 #define IPI_ID_3	5U
 #define IPI_ID_4	6U
 #define IPI_ID_5	7U
-#define IPI_ID_MAX	8U
+#define IPI_ID_PMC_NOBUF	8U
+#define IPI_ID_6_NOBUF_95	9U
+#define IPI_ID_1_NOBUF	10U
+#define IPI_ID_2_NOBUF	11U
+#define IPI_ID_3_NOBUF	12U
+#define IPI_ID_4_NOBUF	13U
+#define IPI_ID_5_NOBUF	14U
+#define IPI_ID_6_NOBUF_101	15U
+#define IPI_ID_MAX	16U
 
 /*********************************************************************
  * IPI message buffers
@@ -56,17 +65,34 @@
  * IPI registers and bitfields
  ******************************************************************************/
 #define IPI0_REG_BASE		(0xEB330000U)
-#define IPI0_TRIG_BIT		(1 << 2)
-#define PMC_IPI_TRIG_BIT	(1 << 1)
+#define IPI0_TRIG_BIT		BIT_32(2)
+#define PMC_IPI_TRIG_BIT	BIT_32(1)
 #define IPI1_REG_BASE		(0xEB340000U)
-#define IPI1_TRIG_BIT		(1 << 3)
+#define IPI1_TRIG_BIT		BIT_32(3)
 #define IPI2_REG_BASE		(0xEB350000U)
-#define IPI2_TRIG_BIT		(1 << 4)
+#define IPI2_TRIG_BIT		BIT_32(4)
 #define IPI3_REG_BASE		(0xEB360000U)
-#define IPI3_TRIG_BIT		(1 << 5)
+#define IPI3_TRIG_BIT		BIT_32(5)
 #define IPI4_REG_BASE		(0xEB370000U)
-#define IPI4_TRIG_BIT		(1 << 6)
+#define IPI4_TRIG_BIT		BIT_32(6)
 #define IPI5_REG_BASE		(0xEB380000U)
-#define IPI5_TRIG_BIT		(1 << 7)
+#define IPI5_TRIG_BIT		BIT_32(7)
+
+#define PMC_NOBUF_REG_BASE	(0xEB390000U)
+#define PMC_NOBUF_TRIG_BIT	BIT_32(8)
+#define IPI6_NOBUF_95_REG_BASE	(0xEB3A0000U)
+#define IPI6_NOBUF_95_TRIG_BIT	BIT_32(9)
+#define IPI1_NOBUF_REG_BASE	(0xEB3B0000U)
+#define IPI1_NOBUF_TRIG_BIT	BIT_32(10)
+#define IPI2_NOBUF_REG_BASE	(0xEB3B1000U)
+#define IPI2_NOBUF_TRIG_BIT	BIT_32(11)
+#define IPI3_NOBUF_REG_BASE	(0xEB3B2000U)
+#define IPI3_NOBUF_TRIG_BIT	BIT_32(12)
+#define IPI4_NOBUF_REG_BASE	(0xEB3B3000U)
+#define IPI4_NOBUF_TRIG_BIT	BIT_32(13)
+#define IPI5_NOBUF_REG_BASE	(0xEB3B4000U)
+#define IPI5_NOBUF_TRIG_BIT	BIT_32(14)
+#define IPI6_NOBUF_101_REG_BASE	(0xEB3B5000U)
+#define IPI6_NOBUF_101_TRIG_BIT	BIT_32(15)
 
 #endif /* PLAT_IPI_H */
diff --git a/plat/amd/versal2/plat_psci_pm.c b/plat/amd/versal2/plat_psci_pm.c
index 50614d5..3cc6b95 100644
--- a/plat/amd/versal2/plat_psci_pm.c
+++ b/plat/amd/versal2/plat_psci_pm.c
@@ -110,7 +110,7 @@
 	 * Send the system reset request to the firmware if power down request
 	 * is not received from firmware.
 	 */
-	if (pwrdwn_req_received == true) {
+	if (pwrdwn_req_received == false) {
 		/*
 		 * TODO: shutdown scope for this reset needs be revised once
 		 * we have a clearer understanding of the overall reset scoping
diff --git a/plat/amd/versal2/soc_ipi.c b/plat/amd/versal2/soc_ipi.c
index 85d1bcd..24ff969 100644
--- a/plat/amd/versal2/soc_ipi.c
+++ b/plat/amd/versal2/soc_ipi.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,6 @@
  * SoC IPI agent registers access management
  */
 
-#include <lib/utils_def.h>
 #include <plat_ipi.h>
 
 /* versal2 ipi configuration table */
@@ -62,6 +61,62 @@
 		.ipi_reg_base = IPI5_REG_BASE,
 		.secure_only = 0,
 	},
+
+	/* PMC_NOBUF IPI */
+	[IPI_ID_PMC_NOBUF] = {
+		.ipi_bit_mask = PMC_NOBUF_TRIG_BIT,
+		.ipi_reg_base = PMC_NOBUF_REG_BASE,
+		.secure_only = IPI_SECURE_MASK,
+	},
+
+	/* IPI6 IPI */
+	[IPI_ID_6_NOBUF_95] = {
+		.ipi_bit_mask = IPI6_NOBUF_95_TRIG_BIT,
+		.ipi_reg_base = IPI6_NOBUF_95_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI1 NO BUF IPI */
+	[IPI_ID_1_NOBUF] = {
+		.ipi_bit_mask = IPI1_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI1_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI2 NO BUF IPI */
+	[IPI_ID_2_NOBUF] = {
+		.ipi_bit_mask = IPI2_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI2_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI3 NO BUF IPI */
+	[IPI_ID_3_NOBUF] = {
+		.ipi_bit_mask = IPI3_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI3_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI4 NO BUF IPI */
+	[IPI_ID_4_NOBUF] = {
+		.ipi_bit_mask = IPI4_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI4_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI5 NO BUF IPI */
+	[IPI_ID_5_NOBUF] = {
+		.ipi_bit_mask = IPI5_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI5_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI6 NO BUF IPI */
+	[IPI_ID_6_NOBUF_101] = {
+		.ipi_bit_mask = IPI6_NOBUF_101_TRIG_BIT,
+		.ipi_reg_base = IPI6_NOBUF_101_REG_BASE,
+		.secure_only = 0,
+	},
 };
 
 /**
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index 6d60cbe..32e089d 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -19,12 +19,7 @@
 
 DYN_CFG_SOURCES		+=	${FDT_WRAPPERS_SOURCES}
 
-# Include GICv2 driver files
-include drivers/arm/gic/v2/gicv2.mk
-
-A5DS_GIC_SOURCES	:=	${GICV2_SOURCES}			\
-				plat/common/plat_gicv2.c		\
-				plat/arm/common/arm_gicv2.c
+USE_GIC_DRIVER		:=	2
 
 A5DS_SECURITY_SOURCES	:=	plat/arm/board/a5ds/a5ds_security.c
 
diff --git a/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
index 4b0c97d..c3ce916 100644
--- a/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
+++ b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, ARM Limited. All rights reserved.
+# Copyright (c) 2019-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -18,5 +18,4 @@
 			plat/common/aarch32/platform_mp_stack.S		\
 			plat/common/plat_psci_common.c			\
 			${A5DS_CPU_LIBS}				\
-			${A5DS_GIC_SOURCES}				\
 			${A5DS_SECURITY_SOURCES}
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
index 12b1e8c..98242e6 100644
--- a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
@@ -28,7 +28,8 @@
 ENABLE_FEAT_ECV				:=	1
 ENABLE_FEAT_FGT				:=	1
 ENABLE_FEAT_MTE2			:=	1
-ENABLE_MPAM_FOR_LOWER_ELS		:=	1
+ENABLE_FEAT_MPAM			:=	1
+USE_GIC_DRIVER				:=	3
 GIC_ENABLE_V4_EXTN			:=	1
 GICV3_SUPPORT_GIC600			:=	1
 HW_ASSISTED_COHERENCY			:=	1
@@ -40,11 +41,6 @@
 
 RD1AE_CPU_SOURCES	:=	lib/cpus/aarch64/neoverse_v3.S
 
-include drivers/arm/gic/v3/gicv3.mk
-RD1AE_GIC_SOURCES	:=	${GICV3_SOURCES}	\
-				plat/common/plat_gicv3.c	\
-				plat/arm/common/arm_gicv3.c
-
 PLAT_BL_COMMON_SOURCES	+=	${RD1AE_BASE}/rd1ae_plat.c	\
 				${RD1AE_BASE}/include/rd1ae_helpers.S
 
@@ -56,7 +52,6 @@
 			drivers/arm/sbsa/sbsa.c
 
 BL31_SOURCES	+=	${RD1AE_CPU_SOURCES}	\
-			${RD1AE_GIC_SOURCES}	\
 			${RD1AE_BASE}/rd1ae_bl31_setup.c	\
 			${RD1AE_BASE}/rd1ae_topology.c	\
 			drivers/cfi/v2m/v2m_flash.c	\
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
index 5264187..ac80887 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -65,7 +65,6 @@
 void corstone1000_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
 	(void)target_state;
-	plat_arm_gic_init();
 }
 #endif
 
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
index dfde5aa..65be9c1 100644
--- a/plat/arm/board/corstone1000/platform.mk
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021-2024 Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2025 Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -43,13 +43,7 @@
 endif
 endif
 
-# Include GICv2 driver files
-include drivers/arm/gic/v2/gicv2.mk
-
-CORSTONE1000_GIC_SOURCES	:=	${GICV2_SOURCES}			\
-				plat/common/plat_gicv2.c		\
-				plat/arm/common/arm_gicv2.c
-
+USE_GIC_DRIVER			:=	2
 
 BL2_SOURCES		+=	plat/arm/board/corstone1000/common/corstone1000_security.c		\
 				plat/arm/board/corstone1000/common/corstone1000_err.c		\
@@ -70,8 +64,7 @@
 			plat/arm/board/corstone1000/common/corstone1000_plat.c		\
 			plat/arm/board/corstone1000/common/corstone1000_pm.c		\
 			plat/arm/board/corstone1000/common/corstone1000_bl31_setup.c	\
-			${CORSTONE1000_CPU_LIBS}					\
-			${CORSTONE1000_GIC_SOURCES}
+			${CORSTONE1000_CPU_LIBS}
 
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 	ifneq (${ENABLE_STACK_PROTECTOR},none)
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index d6d3bef..b76ef20 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -29,12 +29,7 @@
     $(error Variable AARCH32_SP has to be set for AArch32)
 endif
 
-# Include GICv2 driver files
-include drivers/arm/gic/v2/gicv2.mk
-
-CORSTONE700_GIC_SOURCES	:=	${GICV2_SOURCES}			\
-				plat/common/plat_gicv2.c		\
-				plat/arm/common/arm_gicv2.c
+USE_GIC_DRIVER		:=	2
 
 # BL1/BL2 Image not a part of the capsule Image for Corstone700
 override NEED_BL1	:=	no
diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
index 75dc0f1..3e282cd 100644
--- a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -12,8 +12,7 @@
 			plat/arm/board/corstone700/common/corstone700_security.c	\
 			plat/arm/board/corstone700/common/corstone700_plat.c		\
 			plat/arm/board/corstone700/common/corstone700_pm.c		\
-			plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c	\
-			${CORSTONE700_GIC_SOURCES}
+			plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c
 
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 	ifneq (${ENABLE_STACK_PROTECTOR},none)
diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
index f14dbff..d6b6863 100644
--- a/plat/arm/board/fvp/fvp_bl1_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,11 +8,16 @@
 
 #include <drivers/measured_boot/event_log/event_log.h>
 #include <drivers/measured_boot/metadata.h>
-#include <plat/arm/common/plat_arm.h>
 #include <tools_share/zero_oid.h>
 
+#include <plat/arm/common/plat_arm.h>
+
 /* Event Log data */
+#if TRANSFER_LIST
+static uint8_t *event_log;
+#else
 static uint8_t event_log[PLAT_ARM_EVENT_LOG_MAX_SIZE];
+#endif
 
 /* FVP table with platform specific image IDs, names and PCRs */
 const event_log_metadata_t fvp_event_log_metadata[] = {
@@ -20,29 +25,60 @@
 	{ TB_FW_CONFIG_ID, MBOOT_TB_FW_CONFIG_STRING, PCR_0 },
 	{ BL2_IMAGE_ID, MBOOT_BL2_IMAGE_STRING, PCR_0 },
 
-	{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+	{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
 };
 
 void bl1_plat_mboot_init(void)
 {
-	event_log_init(event_log, event_log + sizeof(event_log));
-	event_log_write_header();
+	size_t event_log_max_size;
+	int rc;
+
+#if TRANSFER_LIST
+	event_log = transfer_list_event_log_extend(
+		secure_tl, PLAT_ARM_EVENT_LOG_MAX_SIZE,
+		&event_log_max_size);
+	assert(event_log != NULL);
+#else
+	event_log_max_size = sizeof(event_log);
+#endif
+
+	rc = event_log_init(event_log, event_log + event_log_max_size);
+	if (rc < 0) {
+		ERROR("Failed to initialize event log (%d).\n", rc);
+		panic();
+	}
+
+	rc = event_log_write_header();
+	if (rc < 0) {
+		ERROR("Failed to write event log header (%d).\n", rc);
+		panic();
+	}
 }
 
 void bl1_plat_mboot_finish(void)
 {
-	size_t event_log_cur_size;
+	size_t event_log_cur_size = event_log_get_cur_size(event_log);
 
-	event_log_cur_size = event_log_get_cur_size(event_log);
-	int rc = arm_set_tb_fw_info((uintptr_t)event_log,
-				    event_log_cur_size,
-				    PLAT_ARM_EVENT_LOG_MAX_SIZE);
-	if (rc != 0) {
-		/*
-		 * It is a fatal error because on FVP platform, BL2 software
-		 * assumes that a valid Event Log buffer exist and it will use
-		 * same Event Log buffer to append image measurements.
-		 */
-		panic();
+#if TRANSFER_LIST
+	uint8_t *rc = transfer_list_event_log_finish(
+		secure_tl, (uintptr_t)event_log + event_log_cur_size);
+
+	if (rc != NULL) {
+		return;
 	}
+#else
+	int rc = arm_set_tb_fw_info((uintptr_t)event_log, event_log_cur_size,
+				PLAT_ARM_EVENT_LOG_MAX_SIZE);
+	if (rc == 0) {
+		return;
+	}
+#endif
+
+	/*
+	 * Panic if we fail to set up the event log for the next stage. This is a fatal
+	 * error because, on the FVP platform, BL2 software assumes that a valid
+	 * Event Log buffer exists and will use the same Event Log buffer to append image
+	 * measurements.
+	 */
+	panic();
 }
diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
index 28aef92..1fae0cf 100644
--- a/plat/arm/board/fvp/fvp_bl2_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,7 +19,7 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/common_def.h>
 
-#if defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd)
+#if !TRANSFER_LIST && (defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd))
 CASSERT(ARM_EVENT_LOG_DRAM1_SIZE >= PLAT_ARM_EVENT_LOG_MAX_SIZE, \
 	assert_res_eventlog_mem_insufficient);
 #endif /* defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd) */
@@ -61,10 +61,17 @@
 {
 	uint8_t *event_log_start;
 	uint8_t *event_log_finish;
-	size_t bl1_event_log_size;
-	size_t event_log_max_size;
-	int rc;
+	size_t bl1_event_log_size __unused;
+	size_t event_log_max_size __unused;
+	int rc __unused;
 
+#if TRANSFER_LIST
+	event_log_start = transfer_list_event_log_extend(
+		secure_tl, PLAT_ARM_EVENT_LOG_MAX_SIZE, &event_log_max_size);
+	event_log_finish = event_log_start + event_log_max_size;
+
+	event_log_base = (uintptr_t)event_log_start;
+#else
 	rc = arm_get_tb_fw_info(&event_log_base, &bl1_event_log_size,
 				&event_log_max_size);
 	if (rc != 0) {
@@ -82,10 +89,11 @@
 	 * BL1 and BL2 share the same Event Log buffer and that BL2 will
 	 * append its measurements after BL1's
 	 */
-	event_log_start = (uint8_t *)((uintptr_t)event_log_base +
-				      bl1_event_log_size);
-	event_log_finish = (uint8_t *)((uintptr_t)event_log_base +
-				       event_log_max_size);
+	event_log_start =
+		(uint8_t *)((uintptr_t)event_log_base + bl1_event_log_size);
+	event_log_finish =
+		(uint8_t *)((uintptr_t)event_log_base + event_log_max_size);
+#endif
 
 	event_log_init((uint8_t *)event_log_start, event_log_finish);
 }
@@ -160,7 +168,7 @@
 	int rc;
 
 	/* Event Log address in Non-Secure memory */
-	uintptr_t ns_log_addr;
+	uintptr_t ns_log_addr __unused;
 
 	/* Event Log filled size */
 	size_t event_log_cur_size;
@@ -172,6 +180,15 @@
 
 	event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
 
+#if TRANSFER_LIST
+	/*
+	 * Re-size the event log for the next stage and update the size to include
+	 * the entire event log (i.e., not just what this stage has added.)
+	 */
+	event_log_base = (uintptr_t)transfer_list_event_log_finish(
+		secure_tl, (uintptr_t)event_log_base + event_log_cur_size);
+	event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
+#else
 #if defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd)
 	/* Copy Event Log to TZC secured DRAM memory */
 	(void)memcpy((void *)ARM_EVENT_LOG_DRAM1_BASE,
@@ -217,6 +234,7 @@
 		panic();
 	}
 #endif /* defined(SPD_tspd) || defined(SPD_spmd) */
+#endif /* TRANSFER_LIST */
 
 	event_log_dump((uint8_t *)event_log_base, event_log_cur_size);
 }
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index aa7b875..d75abb4 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -91,6 +91,16 @@
 	}
 }
 
+void __init bl31_platform_setup(void)
+{
+	arm_bl31_platform_setup();
+
+#if USE_GIC_DRIVER == 3
+	fvp_pcpu_init();
+	fvp_gic_driver_pre_init();
+#endif
+}
+
 #if !TRANSFER_LIST
 void __init bl31_plat_arch_setup(void)
 {
diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c
index e780f21..4167229 100644
--- a/plat/arm/board/fvp/fvp_gicv3.c
+++ b/plat/arm/board/fvp/fvp_gicv3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,51 +21,15 @@
 static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false};
 #endif /* FVP_GICR_REGION_PROTECTION */
 
-/* The GICv3 driver only needs to be initialized in EL3 */
-static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT];
-
 /* Default GICR base address to be used for GICR probe. */
-static uint64_t fvp_gicr_base_addrs[2] = { 0U };
+static uintptr_t __unused fvp_gicr_base_addrs[2] = { 0U };
 
-/* List of zero terminated GICR frame addresses which CPUs will probe */
-static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs;
-
-#if  !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \
-	(defined(__aarch64__) && defined(IMAGE_BL31))))
-static const interrupt_prop_t fvp_interrupt_props[] = {
+static const interrupt_prop_t __unused fvp_interrupt_props[] = {
 	PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
 	PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
 };
-#endif
 
-/*
- * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
- * to core position.
- *
- * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
- * values read from GICR_TYPER don't have an MT field. To reuse the same
- * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
- * that read from GICR_TYPER.
- *
- * Assumptions:
- *
- *   - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
- *   - No CPUs implemented in the system use affinity level 3.
- */
-static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr)
-{
-	u_register_t temp_mpidr = mpidr;
-
-	temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
-	return plat_arm_calc_core_pos(temp_mpidr);
-}
-
-
-static gicv3_driver_data_t fvp_gic_data = {
-	.rdistif_num = PLATFORM_CORE_COUNT,
-	.rdistif_base_addrs = fvp_rdistif_base_addrs,
-	.mpidr_to_core_pos = fvp_gicv3_mpidr_hash
-};
+extern gicv3_driver_data_t gic_data;
 
 /******************************************************************************
  * This function gets called per core to make its redistributor frame rw
@@ -97,78 +61,41 @@
 #endif /* FVP_GICR_REGION_PROTECTION */
 }
 
-void plat_arm_gic_driver_init(void)
+void fvp_pcpu_init(void)
 {
 	fvp_gicv3_make_rdistrif_rw();
+}
+
+void fvp_gic_driver_pre_init(void)
+{
+/* FCONF won't be used in these cases, so we couldn't do this */
+#if !(BL2_AT_EL3 || RESET_TO_BL31 || RESET_TO_SP_MIN || RESET_TO_BL2)
 	/*
 	 * Get GICD and GICR base addressed through FCONF APIs.
 	 * FCONF is not supported in BL32 for FVP.
 	 */
 #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
 	(defined(__aarch64__) && defined(IMAGE_BL31))
-	fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
+	gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
 							       gicv3_config,
 							       gicd_base);
 	fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config,
 						    gicr_base);
 #if SEC_INT_DESC_IN_FCONF
-	fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
+	gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
 					sec_intr_prop, descriptor);
-	fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
+	gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
 					sec_intr_prop, count);
 #else
-	fvp_gic_data.interrupt_props = fvp_interrupt_props;
-	fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+	gic_data.interrupt_props = fvp_interrupt_props;
+	gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
 #endif
 #else
-	fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE;
+	gic_data.gicd_base = PLAT_ARM_GICD_BASE;
 	fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE;
-	fvp_gic_data.interrupt_props = fvp_interrupt_props;
-	fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+	gic_data.interrupt_props = fvp_interrupt_props;
+	gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
 #endif
-
-	/*
-	 * The GICv3 driver is initialized in EL3 and does not need
-	 * to be initialized again in SEL1. This is because the S-EL1
-	 * can use GIC system registers to manage interrupts and does
-	 * not need GIC interface base addresses to be configured.
-	 */
-
-#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
-	(defined(__aarch64__) && defined(IMAGE_BL31))
-	gicv3_driver_init(&fvp_gic_data);
-	if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) {
-		ERROR("No GICR base frame found for Primary CPU\n");
-		panic();
-	}
-#endif
-}
-
-/******************************************************************************
- * Function to iterate over all GICR frames and discover the corresponding
- * per-cpu redistributor frame as well as initialize the corresponding
- * interface in GICv3.
- *****************************************************************************/
-void plat_arm_gic_pcpu_init(void)
-{
-	int result;
-	const uint64_t *plat_gicr_frames = fvp_gicr_frames;
-
-	fvp_gicv3_make_rdistrif_rw();
-
-	do {
-		result = gicv3_rdistif_probe(*plat_gicr_frames);
-
-		/* If the probe is successful, no need to proceed further */
-		if (result == 0)
-			break;
-
-		plat_gicr_frames++;
-	} while (*plat_gicr_frames != 0U);
-
-	if (result == -1) {
-		ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
-		panic();
-	}
-	gicv3_rdistif_init(plat_my_core_pos());
+	plat_arm_override_gicr_frames(fvp_gicr_base_addrs);
+#endif /* !(BL2_AT_EL3 || RESET_TO_BL31 || RESET_TO_SP_MIN || RESET_TO_BL2) */
 }
diff --git a/plat/arm/board/fvp/fvp_ide_keymgmt.c b/plat/arm/board/fvp/fvp_ide_keymgmt.c
new file mode 100644
index 0000000..ff05351
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_ide_keymgmt.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <plat/common/platform.h>
+
+int plat_rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t root_port_id,
+				  uint64_t ide_stream_info,
+				  rp_ide_key_info_t *ide_key_info_ptr, uint64_t request_id,
+				  uint64_t cookie)
+{
+	/* placeholder to add further implementation */
+
+	return 0;
+
+}
+
+int plat_rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t root_port_id,
+				 uint64_t ide_stream_info, uint64_t request_id,
+				 uint64_t cookie)
+{
+	/* placeholder to add further implementation */
+
+	return 0;
+
+}
+
+int plat_rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t ide_stream_info, uint64_t request_id,
+				   uint64_t cookie)
+{
+	/* placeholder to add further implementation */
+
+	return 0;
+}
+
+int plat_rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t *req_resp, uint64_t *request,
+				   uint64_t *cookie)
+{
+	/* placeholder to add further implementation */
+	return E_RMM_UNK;
+}
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 2a0bb93..fb72105 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -180,12 +180,6 @@
 	 * by the cluster specific operations if applicable.
 	 */
 
-	/* Prevent interrupts from spuriously waking up this cpu */
-	plat_arm_gic_cpuif_disable();
-
-	/* Turn redistributor off */
-	plat_arm_gic_redistif_off();
-
 	/* Program the power controller to power off this cpu. */
 	fvp_pwrc_write_ppoffr(read_mpidr_el1());
 
@@ -220,9 +214,6 @@
 	/* Program the power controller to enable wakeup interrupts. */
 	fvp_pwrc_set_wen(mpidr);
 
-	/* Prevent interrupts from spuriously waking up this cpu */
-	plat_arm_gic_cpuif_disable();
-
 	/*
 	 * The Redistributor is not powered off as it can potentially prevent
 	 * wake up events reaching the CPUIF and/or might lead to losing
@@ -253,7 +244,6 @@
 static void fvp_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
 	fvp_power_domain_on_finish_common(target_state);
-
 }
 
 /*******************************************************************************
@@ -263,11 +253,9 @@
  ******************************************************************************/
 static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
 {
-	/* Program GIC per-cpu distributor or re-distributor interface */
-	plat_arm_gic_pcpu_init();
-
-	/* Enable GIC CPU interface */
-	plat_arm_gic_cpuif_enable();
+#if USE_GIC_DRIVER == 3
+	fvp_pcpu_init();
+#endif
 }
 
 /*******************************************************************************
@@ -287,9 +275,6 @@
 		return;
 
 	fvp_power_domain_on_finish_common(target_state);
-
-	/* Enable GIC CPU interface */
-	plat_arm_gic_cpuif_enable();
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/fvp/fvp_private.h b/plat/arm/board/fvp/fvp_private.h
index 3590370..7e53a65 100644
--- a/plat/arm/board/fvp/fvp_private.h
+++ b/plat/arm/board/fvp/fvp_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,6 +19,7 @@
 void fvp_interconnect_enable(void);
 void fvp_interconnect_disable(void);
 void fvp_timer_init(void);
-void tsp_early_platform_setup(void);
+void fvp_pcpu_init(void);
+void fvp_gic_driver_pre_init(void);
 
 #endif /* FVP_PRIVATE_H */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index f5be8f2..68ff0fe 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -206,7 +206,7 @@
 #  define PLAT_ARM_MMAP_ENTRIES		12
 #  define MAX_XLAT_TABLES		6
 # else
-#  define PLAT_ARM_MMAP_ENTRIES		11
+#  define PLAT_ARM_MMAP_ENTRIES		12
 #  define MAX_XLAT_TABLES		5
 # endif /* (IMAGE_BL2 && ENABLE_RME) */
 #else
@@ -307,9 +307,15 @@
  * calculated using the current SP_MIN PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
+#if TRANSFER_LIST
+# define PLAT_ARM_MAX_BL32_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
+					 ARM_SHARED_RAM_SIZE - \
+					 PLAT_ARM_FW_HANDOFF_SIZE)
+#else
 # define PLAT_ARM_MAX_BL32_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
 					 ARM_SHARED_RAM_SIZE - \
 					 ARM_FW_CONFIGS_SIZE)
+#endif /* TRANSFER_LIST */
 #endif /* RESET_TO_SP_MIN */
 #endif
 
@@ -508,8 +514,12 @@
 /* Account for additional measurements of secure partitions and SPM. */
 #define	PLAT_ARM_EVENT_LOG_MAX_SIZE		UL(0x800)
 #else
+#if defined(IMAGE_BL1) && TRANSFER_LIST
+#define PLAT_ARM_EVENT_LOG_MAX_SIZE		UL(0x200)
+#else
 #define	PLAT_ARM_EVENT_LOG_MAX_SIZE		UL(0x400)
 #endif
+#endif
 
 /*
  * Maximum size of Event Log buffer used for DRTM
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 8c114e7..8e8870c 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -95,6 +95,7 @@
 
 ifeq (${ENABLE_RME},1)
     ENABLE_FEAT_MEC		:= 2
+    RMMD_ENABLE_IDE_KEY_PROG	:= 1
 endif
 
 # The FVP platform depends on this macro to build with correct GIC driver.
@@ -129,36 +130,21 @@
 
 # Choose the GIC sources depending upon the how the FVP will be invoked
 ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
+USE_GIC_DRIVER			:=	3
 
 # The GIC model (GIC-600 or GIC-500) will be detected at runtime
 GICV3_SUPPORT_GIC600		:=	1
 GICV3_OVERRIDE_DISTIF_PWR_OPS	:=	1
 
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-FVP_GIC_SOURCES		:=	${GICV3_SOURCES}			\
-				plat/common/plat_gicv3.c		\
-				plat/arm/common/arm_gicv3.c
-
-	ifeq ($(filter 1,${RESET_TO_BL2} \
-		${RESET_TO_BL31} ${RESET_TO_SP_MIN}),)
-		FVP_GIC_SOURCES += plat/arm/board/fvp/fvp_gicv3.c
-	endif
+FVP_SECURITY_SOURCES += plat/arm/board/fvp/fvp_gicv3.c
 
 else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
+USE_GIC_DRIVER		:=	2
 
 # No GICv4 extension
 GIC_ENABLE_V4_EXTN	:=	0
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
 
-# Include GICv2 driver files
-include drivers/arm/gic/v2/gicv2.mk
-
-FVP_GIC_SOURCES		:=	${GICV2_SOURCES}			\
-				plat/common/plat_gicv2.c		\
-				plat/arm/common/arm_gicv2.c
-
 FVP_DT_PREFIX		:=	fvp-base-gicv2-psci
 else
 $(error "Incorrect GIC driver chosen on FVP port")
@@ -173,7 +159,7 @@
 $(error "Incorrect CCN driver chosen on FVP port")
 endif
 
-FVP_SECURITY_SOURCES	:=	drivers/arm/tzc/tzc400.c		\
+FVP_SECURITY_SOURCES	+=	drivers/arm/tzc/tzc400.c		\
 				plat/arm/board/fvp/fvp_security.c	\
 				plat/arm/common/arm_tzc400.c
 
@@ -302,10 +288,11 @@
 
 BL31_SOURCES		+=	plat/arm/board/fvp/fvp_plat_attest_token.c	\
 				plat/arm/board/fvp/fvp_realm_attest_key.c	\
-				plat/arm/board/fvp/fvp_el3_token_sign.c
+				plat/arm/board/fvp/fvp_el3_token_sign.c		\
+				plat/arm/board/fvp/fvp_ide_keymgmt.c
 endif
 
-ifeq (${ENABLE_FEAT_RNG_TRAP},1)
+ifneq (${ENABLE_FEAT_RNG_TRAP},0)
 BL31_SOURCES		+=	plat/arm/board/fvp/fvp_sync_traps.c
 endif
 
@@ -341,7 +328,6 @@
 				plat/arm/board/fvp/fvp_cpu_pwr.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c	\
 				${FVP_CPU_LIBS}					\
-				${FVP_GIC_SOURCES}				\
 				${FVP_INTERCONNECT_SOURCES}			\
 				${FVP_SECURITY_SOURCES}
 
diff --git a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
index 76ca5b5..8c193fa 100644
--- a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
+++ b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
@@ -14,16 +14,34 @@
 
 #include "../fvp_private.h"
 
+static uintptr_t hw_config __unused;
+
 void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
 			u_register_t arg2, u_register_t arg3)
 {
 	const struct dyn_cfg_dtb_info_t *tos_fw_config_info __unused;
+	struct transfer_list_header *tl __unused;
 
 	/* Initialize the console to provide early debug support */
 	arm_console_boot_init();
 
-#if !RESET_TO_SP_MIN && !RESET_TO_BL2
+#if TRANSFER_LIST
+	/*
+	 * Register usage at function entry:
+	 *   r0 - Reserved (must be zero)
+	 *   r1 - Register convention and TL signature
+	 *   r2 - Pointer to the FDT located within the TL
+	 *   r3 - Base address of the TL
+	 *
+	 * Initialize TL pointer from r3 and validate that the FDT pointer (arg2)
+	 * lies within the bounds of the Transfer List memory region.
+	 */
+	tl = (struct transfer_list_header *)arg3;
 
+	assert(arg2 > (uintptr_t)tl && arg2 < (uintptr_t)tl + tl->size);
+	hw_config = (uintptr_t)arg2;
+#else
+#if !RESET_TO_SP_MIN && !RESET_TO_BL2
 	INFO("SP_MIN FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
 	/* Fill the properties struct with the info from the config dtb */
 	fconf_populate("FW_CONFIG", arg1);
@@ -33,6 +51,7 @@
 		arg1 = tos_fw_config_info->config_addr;
 	}
 #endif /* !RESET_TO_SP_MIN && !RESET_TO_BL2 */
+#endif /* TRANSFER_LIST */
 
 	arm_sp_min_early_platform_setup(arg0, arg1, arg2, arg3);
 
@@ -75,7 +94,10 @@
 	 * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support
 	 * gets deprecated.
 	 */
-#if !RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1
+#if TRANSFER_LIST
+	INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", (void *)hw_config);
+	fconf_populate("HW_CONFIG", hw_config);
+#elif !RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1
 	hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
 	assert(hw_config_info != NULL);
 	assert(hw_config_info->config_addr != 0UL);
@@ -118,5 +140,6 @@
 		      rc);
 		panic();
 	}
-#endif /*!RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1*/
+
+#endif /* TRANSFER_LIST */
 }
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
index 4ddba6f..0328864 100644
--- a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -17,7 +17,7 @@
 				plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c	\
 				plat/arm/common/arm_nor_psci_mem_protect.c	\
 				${FVP_CPU_LIBS}					\
-				${FVP_GIC_SOURCES}				\
+				${GIC_SOURCES}					\
 				${FVP_INTERCONNECT_SOURCES}			\
 				${FVP_SECURITY_SOURCES}
 
diff --git a/plat/arm/board/fvp/trp/test_ide_km_interface.c b/plat/arm/board/fvp/trp/test_ide_km_interface.c
new file mode 100644
index 0000000..2a1f0e2
--- /dev/null
+++ b/plat/arm/board/fvp/trp/test_ide_km_interface.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+#include <services/trp/platform_trp.h>
+
+#include <platform_def.h>
+
+/*
+ * Helper function for ecam address and root port ID
+ *
+ */
+uint64_t trp_get_test_rootport(uint64_t *ecam_address, uint64_t *rp_id)
+{
+
+	*ecam_address = 0xE001C000;
+	*rp_id = 0x001C0001;
+
+	return 0;
+}
+
diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk
index a450541..3c1b96b 100644
--- a/plat/arm/board/fvp/trp/trp-fvp.mk
+++ b/plat/arm/board/fvp/trp/trp-fvp.mk
@@ -6,7 +6,8 @@
 
 # TRP source files specific to FVP platform
 
-RMM_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S
+RMM_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S	\
+				plat/arm/board/fvp/trp/test_ide_km_interface.c
 
 include plat/arm/common/trp/arm_trp.mk
 
diff --git a/plat/arm/board/fvp/tsp/fvp_tsp_setup.c b/plat/arm/board/fvp/tsp/fvp_tsp_setup.c
index 3c8a963..53a84c6 100644
--- a/plat/arm/board/fvp/tsp/fvp_tsp_setup.c
+++ b/plat/arm/board/fvp/tsp/fvp_tsp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,9 +8,10 @@
 
 #include "../fvp_private.h"
 
-void tsp_early_platform_setup(void)
+void tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3)
 {
-	arm_tsp_early_platform_setup();
+	arm_tsp_early_platform_setup(arg0, arg1, arg2, arg3);
 
 	/* Initialize the platform config for future decision making */
 	fvp_config_setup();
diff --git a/plat/arm/board/fvp/tsp/tsp-fvp.mk b/plat/arm/board/fvp/tsp/tsp-fvp.mk
index ab3f225..8557ec1 100644
--- a/plat/arm/board/fvp/tsp/tsp-fvp.mk
+++ b/plat/arm/board/fvp/tsp/tsp-fvp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,6 @@
 				plat/arm/board/fvp/aarch64/fvp_helpers.S	\
 				plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/tsp/fvp_tsp_setup.c		\
-				${FVP_GIC_SOURCES}
+				${GIC_SOURCES}
 
 include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 79cf356..b1fcd52 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -12,12 +12,7 @@
 BL2_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
 endif
 
-# Include GICv2 driver files
-include drivers/arm/gic/v2/gicv2.mk
-
-FVP_VE_GIC_SOURCES	:=	${GICV2_SOURCES}		\
-				plat/common/plat_gicv2.c	\
-				plat/arm/common/arm_gicv2.c
+USE_GIC_DRIVER		:=	2
 
 FVP_VE_SECURITY_SOURCES	:=	plat/arm/board/fvp_ve/fvp_ve_security.c
 
diff --git a/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk
index 4ca810d..db1a616 100644
--- a/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk
+++ b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -18,5 +18,4 @@
 				plat/common/aarch32/platform_mp_stack.S		\
 				plat/common/plat_psci_common.c			\
 				${FVP_VE_CPU_LIBS}				\
-				${FVP_VE_GIC_SOURCES}				\
 				${FVP_VE_SECURITY_SOURCES}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 9530498..38ba0ed 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -1,17 +1,12 @@
 #
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 include common/fdt_wrappers.mk
 
-# Include GICv2 driver files
-include drivers/arm/gic/v2/gicv2.mk
-
-JUNO_GIC_SOURCES	:=	${GICV2_SOURCES}			\
-				plat/common/plat_gicv2.c		\
-				plat/arm/common/arm_gicv2.c
+USE_GIC_DRIVER		:=	2
 
 JUNO_INTERCONNECT_SOURCES	:=	drivers/arm/cci/cci.c		\
 					plat/arm/common/arm_cci.c
@@ -99,7 +94,6 @@
 				plat/arm/board/juno/juno_pm.c		\
 				plat/arm/board/juno/juno_topology.c	\
 				plat/arm/common/arm_nor_psci_mem_protect.c \
-				${JUNO_GIC_SOURCES}			\
 				${JUNO_INTERCONNECT_SOURCES}		\
 				${JUNO_SECURITY_SOURCES}
 
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index b3471c1..45a93c8 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -14,7 +14,7 @@
 			plat/arm/board/juno/juno_topology.c	\
 			plat/arm/common/arm_nor_psci_mem_protect.c	\
 			plat/arm/soc/common/soc_css_security.c	\
-			${JUNO_GIC_SOURCES}			\
+			${GIC_SOURCES}				\
 			${JUNO_INTERCONNECT_SOURCES}		\
 			${JUNO_SECURITY_SOURCES}
 
diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk
index be75c4d..c7debf1 100644
--- a/plat/arm/board/juno/tsp/tsp-juno.mk
+++ b/plat/arm/board/juno/tsp/tsp-juno.mk
@@ -1,12 +1,12 @@
 #
-# Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 BL32_SOURCES		+=	plat/arm/board/juno/juno_topology.c	\
 				plat/arm/css/common/css_topology.c	\
-				${JUNO_GIC_SOURCES}			\
+				${GIC_SOURCES}				\
 				${JUNO_SECURITY_SOURCES}
 
 include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/board/morello/morello_pm.c b/plat/arm/board/morello/morello_pm.c
index fa7bd1d..30791cc 100644
--- a/plat/arm/board/morello/morello_pm.c
+++ b/plat/arm/board/morello/morello_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,5 +19,4 @@
 void morello_pwr_domain_off(const psci_power_state_t *target_state)
 {
 	css_pwr_domain_off(target_state);
-	plat_arm_gic_redistif_off();
 }
diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk
index 8211c26..7653583 100644
--- a/plat/arm/board/morello/platform.mk
+++ b/plat/arm/board/morello/platform.mk
@@ -18,15 +18,9 @@
 MORELLO_CPU_SOURCES	:=	lib/cpus/aarch64/rainier.S
 
 # GIC-600 configuration
+USE_GIC_DRIVER		:=	3
 GICV3_SUPPORT_GIC600	:=	1
 
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-MORELLO_GIC_SOURCES	:=	${GICV3_SOURCES}			\
-				plat/common/plat_gicv3.c		\
-				plat/arm/common/arm_gicv3.c		\
-
 PLAT_BL_COMMON_SOURCES	:=	${MORELLO_BASE}/morello_plat.c		\
 				${MORELLO_BASE}/aarch64/morello_helper.S
 
@@ -47,7 +41,6 @@
 
 BL31_SOURCES		:=	${MORELLO_CPU_SOURCES}			\
 				${INTERCONNECT_SOURCES}			\
-				${MORELLO_GIC_SOURCES}			\
 				${MORELLO_BASE}/morello_bl31_setup.c	\
 				${MORELLO_BASE}/morello_pm.c		\
 				${MORELLO_BASE}/morello_topology.c	\
diff --git a/plat/arm/board/n1sdp/n1sdp_pm.c b/plat/arm/board/n1sdp/n1sdp_pm.c
index 8d45354..d89fb05 100644
--- a/plat/arm/board/n1sdp/n1sdp_pm.c
+++ b/plat/arm/board/n1sdp/n1sdp_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,5 +19,4 @@
 void n1sdp_pwr_domain_off(const psci_power_state_t *target_state)
 {
 	css_pwr_domain_off(target_state);
-	plat_arm_gic_redistif_off();
 }
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index f937ee7..218081c 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -19,16 +19,10 @@
 ARM_ARCH_MINOR := 2
 
 # GIC-600 configuration
+USE_GIC_DRIVER			:=	3
 GICV3_SUPPORT_GIC600		:=	1
 GICV3_IMPL_GIC600_MULTICHIP	:=	1
 
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-N1SDP_GIC_SOURCES	:=	${GICV3_SOURCES}			\
-				plat/common/plat_gicv3.c		\
-				plat/arm/common/arm_gicv3.c		\
-
 PLAT_BL_COMMON_SOURCES	:=	${N1SDP_BASE}/n1sdp_plat.c	        \
 				${N1SDP_BASE}/aarch64/n1sdp_helper.S
 
@@ -49,7 +43,6 @@
 
 BL31_SOURCES		:=	${N1SDP_CPU_SOURCES}			\
 				${INTERCONNECT_SOURCES}			\
-				${N1SDP_GIC_SOURCES}			\
 				${N1SDP_BASE}/n1sdp_bl31_setup.c	\
 				${N1SDP_BASE}/n1sdp_pm.c		\
 				${N1SDP_BASE}/n1sdp_topology.c	        \
diff --git a/plat/arm/board/neoverse_rd/common/nrd-common.mk b/plat/arm/board/neoverse_rd/common/nrd-common.mk
index a09f369..acc5a47 100644
--- a/plat/arm/board/neoverse_rd/common/nrd-common.mk
+++ b/plat/arm/board/neoverse_rd/common/nrd-common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -30,15 +30,9 @@
 PLAT_INCLUDES		+=	-I${NRD_COMMON_BASE}/include
 
 # GIC-600 configuration
+USE_GIC_DRIVER		:=	3
 GICV3_SUPPORT_GIC600	:=	1
 
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
-				plat/common/plat_gicv3.c	\
-				plat/arm/common/arm_gicv3.c
-
 PLAT_BL_COMMON_SOURCES	+=	${NRD_COMMON_BASE}/arch/aarch64/nrd_helper.S
 
 BL1_SOURCES		+=	${INTERCONNECT_SOURCES}			\
@@ -49,7 +43,6 @@
 				drivers/arm/css/sds/sds.c
 
 BL31_SOURCES		+=	${INTERCONNECT_SOURCES}			\
-				${ENT_GIC_SOURCES}			\
 				${NRD_COMMON_BASE}/nrd_bl31_setup.c	\
 				${NRD_COMMON_BASE}/nrd_topology.c	\
 				drivers/delay_timer/generic_delay_timer.c
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 0216000..76bae38 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -258,11 +258,7 @@
 #define TC_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
 						V2M_FLASH0_SIZE,	\
 						MT_DEVICE | MT_RO | MT_SECURE)
-#if TARGET_PLATFORM == 2
-#define PLAT_ARM_NSTIMER_FRAME_ID	U(0)
-#else
 #define PLAT_ARM_NSTIMER_FRAME_ID	U(1)
-#endif
 
 #define PLAT_ARM_TRUSTED_ROM_BASE	0x0
 
@@ -276,10 +272,7 @@
 #define PLAT_ARM_NSRAM_SIZE		0x00008000	/* 64KB */
 #endif /* TARGET_FLAVOUR_FPGA */
 
-#if TARGET_PLATFORM <= 2
-#define PLAT_ARM_DRAM2_BASE		ULL(0x8080000000)
-#define PLAT_ARM_DRAM2_SIZE             ULL(0x180000000)
-#elif TARGET_PLATFORM >= 3
+#if TARGET_PLATFORM >= 3
 
 #if TC_FPGA_FS_IMG_IN_RAM
 /* 10GB reserved for system+userdata+vendor images */
@@ -348,28 +341,19 @@
 					 CSS_SCMI_PAYLOAD_SIZE_MAX)
 
 #define PLAT_ARM_CLUSTER_COUNT		U(1)
-#if TARGET_FLAVOUR_FPGA && TARGET_PLATFORM == 2
-#define PLAT_MAX_CPUS_PER_CLUSTER	U(14)
-#else /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM == 2 */
 #define PLAT_MAX_CPUS_PER_CLUSTER	U(8)
-#endif /* TARGET_FLAVOUR_FPGA && TARGET_PLATFORM == 2 */
 #define PLAT_MAX_PE_PER_CPU		U(1)
 
 #define PLATFORM_CORE_COUNT		(PLAT_MAX_CPUS_PER_CLUSTER * PLAT_ARM_CLUSTER_COUNT)
 
 /* Message Handling Unit (MHU) base addresses */
-#if TARGET_PLATFORM <= 2
-	#define PLAT_CSS_MHU_BASE		UL(0x45400000)
-#elif TARGET_PLATFORM >= 3
+#if TARGET_PLATFORM >= 3
 	#define PLAT_CSS_MHU_BASE		UL(0x46000000)
 #endif /* TARGET_PLATFORM >= 3 */
 #define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* AP<->RSS MHUs */
-#if TARGET_PLATFORM <= 2
-#define PLAT_RSE_AP_SND_MHU_BASE	UL(0x2A840000)
-#define PLAT_RSE_AP_RCV_MHU_BASE	UL(0x2A850000)
-#elif TARGET_PLATFORM == 3
+#if TARGET_PLATFORM == 3
 #define PLAT_RSE_AP_SND_MHU_BASE	UL(0x49000000)
 #define PLAT_RSE_AP_RCV_MHU_BASE	UL(0x49100000)
 #elif TARGET_PLATFORM == 4
@@ -403,36 +387,6 @@
  */
 #define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x30000
 
-#if TARGET_PLATFORM <= 2
-/* TZC Related Constants */
-#define PLAT_ARM_TZC_BASE		UL(0x25000000)
-#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
-
-#define TZC400_OFFSET			UL(0x1000000)
-#define TZC400_COUNT			4
-
-#define TZC400_BASE(n)			(PLAT_ARM_TZC_BASE + \
-					 (n * TZC400_OFFSET))
-
-#define TZC_NSAID_DEFAULT		U(0)
-
-#define PLAT_ARM_TZC_NS_DEV_ACCESS	\
-		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT))
-
-/*
- * The first region below, TC_TZC_DRAM1_BASE (0xf9000000) to
- * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 112 MB of DRAM as
- * secure. The second and third regions gives non secure access to rest of DRAM.
- */
-#define TC_TZC_REGIONS_DEF	\
-	{TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END,	\
-		TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS},	\
-	{TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS,	\
-		PLAT_ARM_TZC_NS_DEV_ACCESS},	\
-	{PLAT_ARM_DRAM2_BASE, PLAT_ARM_DRAM2_END,	\
-		ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}
-#endif
-
 /* virtual address used by dynamic mem_protect for chunk_base */
 #define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xc0000000)
 
@@ -468,13 +422,11 @@
 #undef  ARM_CONSOLE_BAUDRATE
 #define ARM_CONSOLE_BAUDRATE		38400
 
-#if TARGET_PLATFORM <= 2
-#define TC_UARTCLK			5000000
-#elif TARGET_PLATFORM == 3
+#if TARGET_PLATFORM == 3
 #define TC_UARTCLK			3750000
 #elif TARGET_PLATFORM == 4
 #define TC_UARTCLK			4000000
-#endif /* TARGET_PLATFORM <=2 */
+#endif /* TARGET_PLATFORM == 3 */
 
 
 #if TARGET_FLAVOUR_FVP
diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
index cc2f760..9a8172a 100644
--- a/plat/arm/board/tc/include/tc_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -74,10 +74,6 @@
 	ret
 endfunc enable_dsu_pmu_el1_access
 
-func TC_HANDLER(2)
-	ret
-endfunc TC_HANDLER(2)
-
 func TC_HANDLER(3)
 	mov	x9, lr
 	bl	mark_extllc_presence
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index a056bc2..b29f0d6 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -15,6 +15,7 @@
 CSS_USE_SCMI_SDS_DRIVER		:=	1
 HW_ASSISTED_COHERENCY		:=	1
 USE_COHERENT_MEM		:=	0
+USE_GIC_DRIVER			:=	3
 GIC_ENABLE_V4_EXTN		:=      1
 GICV3_SUPPORT_GIC600		:=	1
 override NEED_BL2U		:=	no
@@ -35,8 +36,8 @@
 ENABLE_AMU_AUXILIARY_COUNTERS	:=	1
 ENABLE_MPMM			:=	1
 ENABLE_FEAT_MTE2		:=	2
-ENABLE_SPE_FOR_NS		:=	3
-ENABLE_FEAT_TCR2		:=	3
+ENABLE_SPE_FOR_NS		:=	2
+ENABLE_FEAT_TCR2		:=	2
 
 ifneq ($(filter ${TARGET_PLATFORM}, 3),)
 ENABLE_FEAT_RNG_TRAP		:=	0
@@ -66,15 +67,10 @@
 endif
 endif
 
-ifneq ($(shell expr $(TARGET_PLATFORM) \<= 1), 0)
+ifneq ($(shell expr $(TARGET_PLATFORM) \<= 2), 0)
         $(error Platform ${PLAT}$(TARGET_PLATFORM) is no longer available.)
 endif
 
-ifneq ($(shell expr $(TARGET_PLATFORM) = 2), 0)
-        $(warning Platform ${PLAT}$(TARGET_PLATFORM) is deprecated. \
-          Some of the features might not work as expected)
-endif
-
 ifeq ($(shell expr $(TARGET_PLATFORM) \<= 4), 0)
         $(error TARGET_PLATFORM must be less than or equal to 4)
 endif
@@ -108,42 +104,13 @@
 # Save DSU PMU registers on cluster off and restore them on cluster on
 PRESERVE_DSU_PMU_REGS		:= 1
 
-# Specify MHU type based on platform
-ifneq ($(filter ${TARGET_PLATFORM}, 2),)
-	PLAT_MHU		:= MHUv2
-else
-	PLAT_MHU		:= MHUv3
-endif
-
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
-				plat/common/plat_gicv3.c	\
-				plat/arm/common/arm_gicv3.c
+PLAT_MHU		:= MHUv3
 
 TC_BASE	=	plat/arm/board/tc
 
 PLAT_INCLUDES		+=	-I${TC_BASE}/include/ \
 				-I${TC_BASE}/fdts/
 
-# CPU libraries for TARGET_PLATFORM=1
-ifeq (${TARGET_PLATFORM}, 1)
-TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_a510.S \
-			lib/cpus/aarch64/cortex_a715.S \
-			lib/cpus/aarch64/cortex_x3.S
-endif
-
-# CPU libraries for TARGET_PLATFORM=2
-ifeq (${TARGET_PLATFORM}, 2)
-ERRATA_A520_2938996	:=	1
-ERRATA_X4_2726228	:=	1
-
-TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_a520.S \
-			lib/cpus/aarch64/cortex_a720.S \
-			lib/cpus/aarch64/cortex_x4.S
-endif
-
 # CPU libraries for TARGET_PLATFORM=3
 ifeq (${TARGET_PLATFORM}, 3)
 ERRATA_A520_2938996	:=	1
@@ -189,13 +156,8 @@
 				drivers/arm/tzc/tzc400.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
-ifeq ($(shell test $(TARGET_PLATFORM) -le 2; echo $$?),0)
-BL2_SOURCES		+=	plat/arm/common/arm_tzc400.c
-endif
-
 BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
 				${TC_CPU_SOURCES}	\
-				${ENT_GIC_SOURCES}			\
 				${TC_BASE}/tc_bl31_setup.c	\
 				${TC_BASE}/tc_topology.c	\
 				lib/fconf/fconf.c			\
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index a358390..7f2014b 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -54,15 +54,6 @@
 }
 #endif /* PLATFORM_TEST_TFM_TESTSUITE */
 
-#if TARGET_PLATFORM <= 2
-static scmi_channel_plat_info_t tc_scmi_plat_info = {
-	.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
-	.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
-	.db_preserve_mask = 0xfffffffe,
-	.db_modify_mask = 0x1,
-	.ring_doorbell = &mhuv2_ring_doorbell,
-};
-#elif TARGET_PLATFORM >= 3
 static scmi_channel_plat_info_t tc_scmi_plat_info = {
 	.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
 	.db_reg_addr = PLAT_CSS_MHU_BASE + MHU_V3_SENDER_REG_SET(0),
@@ -70,7 +61,6 @@
 	.db_modify_mask = 0x1,
 	.ring_doorbell = &mhu_ring_doorbell,
 };
-#endif
 
 /* the bottom 3 AMU group 1 counters */
 #define MPMM_GEARS ((1 << 0) | (1 << 1) | (1 << 2))
diff --git a/plat/arm/board/tc/tc_security.c b/plat/arm/board/tc/tc_security.c
index 7c7a1a1..804a35b 100644
--- a/plat/arm/board/tc/tc_security.c
+++ b/plat/arm/board/tc/tc_security.c
@@ -7,21 +7,8 @@
 #include <plat/arm/common/plat_arm.h>
 #include <platform_def.h>
 
-#if (TARGET_PLATFORM <= 2)
-static const arm_tzc_regions_info_t tzc_regions[] = {
-	TC_TZC_REGIONS_DEF,
-	{}
-};
-#endif
-
 /* Initialize the secure environment */
 void plat_arm_security_setup(void)
 {
-#if (TARGET_PLATFORM <= 2)
-	unsigned int i;
 
-	for (i = 0U; i < TZC400_COUNT; i++) {
-		arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
-	}
-#endif
 }
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 75d6a53..06a919c 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -289,18 +289,17 @@
 	return  is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
 }
 
-// Use the default implementation of this function when Firmware Handoff is
-// disabled to avoid duplicating its logic.
 #if TRANSFER_LIST
 int bl1_plat_handle_post_image_load(unsigned int image_id)
 {
-	image_desc_t *image_desc __unused;
-
-	assert(image_id == BL2_IMAGE_ID);
 	struct transfer_list_entry *te;
 
+	if (image_id != BL2_IMAGE_ID) {
+		return 0;
+	}
+
 	/* Convey this information to BL2 via its TL. */
-	te = transfer_list_add(secure_tl, TL_TAG_SRAM_LAYOUT64,
+	te = transfer_list_add(secure_tl, TL_TAG_SRAM_LAYOUT,
 			       sizeof(meminfo_t), NULL);
 	assert(te != NULL);
 
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 6418628..522017f 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -78,7 +78,7 @@
 #if TRANSFER_LIST
 	secure_tl = (struct transfer_list_header *)arg3;
 
-	te = transfer_list_find(secure_tl, TL_TAG_SRAM_LAYOUT64);
+	te = transfer_list_find(secure_tl, TL_TAG_SRAM_LAYOUT);
 	assert(te != NULL);
 
 	bl2_tzram_layout = *(meminfo_t *)transfer_list_entry_data(te);
@@ -320,6 +320,13 @@
 void arm_bl2_setup_next_ep_info(bl_mem_params_node_t *next_param_node)
 {
 	entry_point_info_t *ep __unused;
+
+	/*
+	 * Information might have been added to the TL before this (i.e. event log)
+	 * make sure the checksum is up to date.
+	 */
+	transfer_list_update_checksum(secure_tl);
+
 	ep = transfer_list_set_handoff_args(secure_tl,
 					    &next_param_node->ep_info);
 	assert(ep != NULL);
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index fa35bb2..f196269 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -133,7 +133,12 @@
 	}
 #endif
 	else {
+#if TRANSFER_LIST && !RESET_TO_BL31
+		next_image_info = transfer_list_set_handoff_args(
+			secure_tl, &bl32_image_ep_info);
+#else
 		next_image_info = &bl32_image_ep_info;
+#endif
 	}
 
 	/*
@@ -257,7 +262,9 @@
 	 * to verify platform parameters from BL2 to BL31.
 	 * In release builds, it's not used.
 	 */
+#if DEBUG
 	assert(((uintptr_t)arg3) == ARM_BL31_PLAT_PARAM_VAL);
+#endif
 
 	/*
 	 * Check params passed from BL2 should not be NULL,
@@ -392,11 +399,17 @@
 	te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
 			       transfer_list_entry_data(te));
 	assert(te != NULL);
-#endif /* TRANSFER_LIST && !RESET_TO_BL31 */
 
-	/* Initialize the GIC driver, cpu and distributor interfaces */
-	plat_arm_gic_driver_init();
-	plat_arm_gic_init();
+	te = transfer_list_find(secure_tl, TL_TAG_TPM_EVLOG);
+	if (te != NULL) {
+		te = transfer_list_add(ns_tl, TL_TAG_TPM_EVLOG, te->data_size,
+				  transfer_list_entry_data(te));
+		if (te == NULL) {
+			ERROR("Failed to load event log in Non-Secure transfer list\n");
+			panic();
+		}
+	}
+#endif /* TRANSFER_LIST && !RESET_TO_BL31 */
 
 #if RESET_TO_BL31
 	/*
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 9659e73..418a9d8 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -356,7 +356,7 @@
 endif
 
 # Pointer Authentication sources
-ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3 5))
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c
 endif
 
@@ -456,6 +456,9 @@
     ifeq (${MEASURED_BOOT},1)
          BL1_SOURCES		+= 	${EVENT_LOG_SOURCES}
          BL2_SOURCES		+= 	${EVENT_LOG_SOURCES}
+         ifeq (${SPD_tspd},1)
+             BL32_SOURCES		+= 	${EVENT_LOG_SOURCES}
+         endif
     endif
 
     ifeq (${DRTM_SUPPORT},1)
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 3e6c9f2..e8d15f7 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -148,7 +148,7 @@
 	/* Assert system power domain is available on the platform */
 	assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
 
-	plat_arm_gic_save();
+	gic_save();
 
 	/*
 	 * Unregister console now so that it is not registered for a second
@@ -177,7 +177,7 @@
 	/* Assert system power domain is available on the platform */
 	assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
 
-	plat_arm_gic_resume();
+	gic_resume();
 
 	plat_arm_security_setup();
 	arm_configure_sys_timer();
diff --git a/plat/arm/common/arm_transfer_list.c b/plat/arm/common/arm_transfer_list.c
index 6847591..5a480b6 100644
--- a/plat/arm/common/arm_transfer_list.c
+++ b/plat/arm/common/arm_transfer_list.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -71,9 +71,8 @@
 					struct transfer_list_header *tl)
 {
 	uint32_t next_exe_img_id;
-	entry_point_info_t *ep;
+	entry_point_info_t *ep __unused;
 	struct transfer_list_entry *te;
-
 	assert(next_param_node != NULL);
 
 	while ((next_exe_img_id = next_param_node->next_handoff_image_id) !=
@@ -83,14 +82,16 @@
 				next_exe_img_id)];
 		assert(next_param_node != NULL);
 
-		te = transfer_list_add(tl, TL_TAG_EXEC_EP_INFO64,
+		te = transfer_list_add(tl, TL_TAG_EXEC_EP_INFO,
 				       sizeof(entry_point_info_t),
 				       &next_param_node->ep_info);
 		assert(te != NULL);
 
 		ep = transfer_list_entry_data(te);
+		assert(ep != NULL);
 
-		if ((next_exe_img_id == BL32_IMAGE_ID) && SPMC_AT_EL3) {
+#if SPMC_AT_EL3
+		if (next_exe_img_id == BL32_IMAGE_ID) {
 			/*
 			 * Populate the BL32 image base, size and max limit in
 			 * the entry point information, since there is no
@@ -106,6 +107,7 @@
 				next_param_node->image_info.image_base +
 				next_param_node->image_info.image_max_size;
 		}
+#endif /* SPMC_AT_EL3 */
 
 		next_exe_img_id = next_param_node->next_handoff_image_id;
 	}
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 78fc88e..6b15b73 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -16,6 +16,9 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
+struct transfer_list_header *secure_tl;
+struct transfer_list_header *ns_tl __unused;
+
 static entry_point_info_t bl33_image_ep_info;
 
 /* Weak definitions may be overridden in specific ARM standard platform */
@@ -28,13 +31,25 @@
 					BL32_END - BL32_BASE,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
+#define MAP_EL3_FW_HANDOFF                            \
+	MAP_REGION_FLAT(PLAT_ARM_EL3_FW_HANDOFF_BASE, \
+			PLAT_ARM_FW_HANDOFF_SIZE, MT_MEMORY | MT_RW | EL3_PAS)
+
+#define MAP_FW_NS_HANDOFF                                             \
+	MAP_REGION_FLAT(FW_NS_HANDOFF_BASE, PLAT_ARM_FW_HANDOFF_SIZE, \
+			MT_MEMORY | MT_RW | MT_NS)
+
 /*
  * Check that BL32_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
  * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
  */
 #if !RESET_TO_SP_MIN
+#if TRANSFER_LIST
+CASSERT(BL32_BASE >= PLAT_ARM_EL3_FW_HANDOFF_LIMIT, assert_bl32_base_overflows);
+#else
 CASSERT(BL32_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
 #endif
+#endif
 
 /*******************************************************************************
  * Return a pointer to the 'entry_point_info' structure of the next image for the
@@ -64,9 +79,22 @@
 void arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
 			u_register_t arg2, u_register_t arg3)
 {
+	struct transfer_list_entry *te __unused;
+
 	/* Initialize the console to provide early debug support */
 	arm_console_boot_init();
 
+#if TRANSFER_LIST
+	secure_tl = (struct transfer_list_header *)arg3;
+
+	te = transfer_list_find(secure_tl, TL_TAG_EXEC_EP_INFO32);
+	assert(te != NULL);
+
+	bl33_image_ep_info =
+		*(struct entry_point_info *)transfer_list_entry_data(te);
+	return;
+#endif /* TRANSFER_LIST */
+
 #if RESET_TO_SP_MIN
 	/* Populate entry point information for BL33 */
 	SET_PARAM_HEAD(&bl33_image_ep_info,
@@ -81,7 +109,7 @@
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
-# if ARM_LINUX_KERNEL_AS_BL33
+#if ARM_LINUX_KERNEL_AS_BL33
 	/*
 	 * According to the file ``Documentation/arm/Booting`` of the Linux
 	 * kernel tree, Linux expects:
@@ -176,9 +204,35 @@
  ******************************************************************************/
 void sp_min_platform_setup(void)
 {
+	struct transfer_list_entry *te __unused;
+
 	/* Initialize the GIC driver, cpu and distributor interfaces */
-	plat_arm_gic_driver_init();
-	plat_arm_gic_init();
+	unsigned int core_pos = plat_my_core_pos();
+
+	gic_init(core_pos);
+	gic_pcpu_init(core_pos);
+	gic_cpuif_enable(core_pos);
+
+#if TRANSFER_LIST
+	ns_tl = transfer_list_ensure((void *)FW_NS_HANDOFF_BASE,
+				       PLAT_ARM_FW_HANDOFF_SIZE);
+	if (ns_tl == NULL) {
+		ERROR("Non-secure transfer list initialisation failed!\n");
+		panic();
+	}
+
+	te = transfer_list_find(secure_tl, TL_TAG_FDT);
+	if (te != NULL) {
+		te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
+				  (void *)transfer_list_entry_data(te));
+		if (te == NULL) {
+			ERROR("Failed to relocate device tree into non-secure memory.\n");
+			panic();
+		}
+	}
+
+	transfer_list_set_handoff_args(ns_tl, &bl33_image_ep_info);
+#endif
 
 	/*
 	 * Do initial security configuration to allow DRAM/device access
@@ -223,6 +277,10 @@
 #if USE_COHERENT_MEM
 		ARM_MAP_BL_COHERENT_RAM,
 #endif
+#if TRANSFER_LIST
+		MAP_EL3_FW_HANDOFF,
+		MAP_FW_NS_HANDOFF,
+#endif
 		{0}
 	};
 
diff --git a/plat/arm/common/tsp/arm_tsp.mk b/plat/arm/common/tsp/arm_tsp.mk
index 4ad77c6..d7592df 100644
--- a/plat/arm/common/tsp/arm_tsp.mk
+++ b/plat/arm/common/tsp/arm_tsp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,3 +8,10 @@
 BL32_SOURCES		+=	plat/arm/common/arm_topology.c			\
 				plat/arm/common/tsp/arm_tsp_setup.c		\
 				plat/common/aarch64/platform_mp_stack.S
+
+ifeq (${TRANSFER_LIST},1)
+BL32_SOURCES	+=	$(TRANSFER_LIST_SOURCES)
+ifeq (${MEASURED_BOOT},1)
+BL32_SOURCES	+=	$(EVENT_LOG_SOURCES)
+endif
+endif
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index df3488b..d018dee 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +13,11 @@
 #include <common/debug.h>
 #include <drivers/arm/pl011.h>
 #include <drivers/console.h>
+#if TRANSFER_LIST && MEASURED_BOOT
+#include <drivers/measured_boot/event_log/event_log.h>
+#endif
 #include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak tsp_early_platform_setup
@@ -25,13 +29,32 @@
 					BL32_END - BL32_BASE,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
+#define MAP_FW_HANDOFF		MAP_REGION_FLAT(			\
+					PLAT_ARM_EL3_FW_HANDOFF_BASE,	\
+					PLAT_ARM_FW_HANDOFF_SIZE,	\
+					MT_MEMORY | MT_RO | MT_SECURE)
+
+struct transfer_list_header *secure_tl __unused;
+
 /*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
 static console_t arm_tsp_runtime_console;
 
-void arm_tsp_early_platform_setup(void)
+void arm_tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3)
 {
+#if TRANSFER_LIST
+	secure_tl = (struct transfer_list_header *)arg3;
+	assert(secure_tl != NULL);
+
+	if (transfer_list_check_header(secure_tl) == TL_OPS_NON) {
+		ERROR("Invalid transfer list received");
+		transfer_list_dump(secure_tl);
+		panic();
+	}
+#endif
+
 	/*
 	 * Initialize a different console than already in use to display
 	 * messages from TSP
@@ -40,16 +63,18 @@
 					PLAT_ARM_TSP_UART_CLK_IN_HZ,
 					ARM_CONSOLE_BAUDRATE,
 					&arm_tsp_runtime_console);
-	if (rc == 0)
+	if (rc == 0) {
 		panic();
+	}
 
 	console_set_scope(&arm_tsp_runtime_console,
 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 }
 
-void tsp_early_platform_setup(void)
+void tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3)
 {
-	arm_tsp_early_platform_setup();
+	arm_tsp_early_platform_setup(arg0, arg1, arg2, arg3);
 }
 
 /*******************************************************************************
@@ -57,7 +82,26 @@
  ******************************************************************************/
 void tsp_platform_setup(void)
 {
-	plat_arm_gic_driver_init();
+	struct transfer_list_entry *te __unused;
+
+	/*
+	 * On GICv2 the driver must be initialised before calling the plat_ic_*
+	 * functions as they need the data structures. Higher versions don't.
+	 */
+#if USE_GIC_DRIVER == 2
+	gic_init(plat_my_core_pos());
+#endif
+
+#if TRANSFER_LIST && MEASURED_BOOT
+	te = transfer_list_find(secure_tl, TL_TAG_TPM_EVLOG);
+	assert(te != NULL);
+
+	/*
+	 * Note the actual log is offset 4-bytes from the start of entry data, the
+	 * first bytes are reserved.
+	 */
+	event_log_dump(transfer_list_entry_data(te) + U(4), te->data_size - U(4));
+#endif
 }
 
 /*******************************************************************************
@@ -74,6 +118,9 @@
 	const mmap_region_t bl_regions[] = {
 		MAP_BL_TSP_TOTAL,
 		ARM_MAP_BL_RO,
+#if TRANSFER_LIST
+		MAP_FW_HANDOFF,
+#endif
 		{0}
 	};
 
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index f8bc542..18882d3 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -114,12 +114,6 @@
  ******************************************************************************/
 void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
 {
-	/* Program the gic per-cpu distributor or re-distributor interface */
-	plat_arm_gic_pcpu_init();
-
-	/* Enable the gic cpu interface */
-	plat_arm_gic_cpuif_enable();
-
 	/* Setup the CPU power down request interrupt for secondary core(s) */
 	css_setup_cpu_pwr_down_intr();
 }
@@ -132,9 +126,6 @@
  ******************************************************************************/
 static void css_power_down_common(const psci_power_state_t *target_state)
 {
-	/* Prevent interrupts from spuriously waking up this cpu */
-	plat_arm_gic_cpuif_disable();
-
 	/* Cluster is to be turned off, so disable coherency */
 	if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
 #if PRESERVE_DSU_PMU_REGS
@@ -152,8 +143,6 @@
 {
 	assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
 	css_power_down_common(target_state);
-	/* ask the GIC not to wake us up */
-	plat_arm_gic_redistif_off();
 	css_scp_off(target_state);
 }
 
@@ -179,7 +168,7 @@
 		arm_system_pwr_domain_save();
 
 		/* Power off the Redistributor after having saved its context */
-		plat_arm_gic_redistif_off();
+		gic_pcpu_off(plat_my_core_pos());
 	}
 
 	css_scp_suspend(target_state);
@@ -209,9 +198,6 @@
 		arm_system_pwr_domain_resume();
 
 	css_pwr_domain_on_finisher_common(target_state);
-
-	/* Enable the gic cpu interface */
-	plat_arm_gic_cpuif_enable();
 }
 
 /*******************************************************************************
@@ -352,6 +338,8 @@
 int css_reboot_interrupt_handler(uint32_t intr_raw, uint32_t flags,
 		void *handle, void *cookie)
 {
+	unsigned int core_pos = plat_my_core_pos();
+
 	assert(intr_raw == CSS_CPU_PWR_DOWN_REQ_INTR);
 
 	/* Deactivate warm reboot SGI */
@@ -361,8 +349,8 @@
 	 * Disable GIC CPU interface to prevent pending interrupt from waking
 	 * up the AP from WFI.
 	 */
-	plat_arm_gic_cpuif_disable();
-	plat_arm_gic_redistif_off();
+	gic_cpuif_disable(core_pos);
+	gic_pcpu_off(core_pos);
 
 	psci_pwrdown_cpu_start(PLAT_MAX_PWR_LVL);
 
diff --git a/plat/arm/common/arm_gicv2.c b/plat/common/plat_gicv2_base.c
similarity index 97%
rename from plat/arm/common/arm_gicv2.c
rename to plat/common/plat_gicv2_base.c
index 80a845f..7fe41c2 100644
--- a/plat/arm/common/arm_gicv2.c
+++ b/plat/common/plat_gicv2_base.c
@@ -1,14 +1,13 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <platform_def.h>
-
 #include <drivers/arm/gicv2.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <platform_def.h>
 
 /******************************************************************************
  * The following functions are defined as weak to allow a platform to override
diff --git a/plat/arm/common/arm_gicv3.c b/plat/common/plat_gicv3_base.c
similarity index 97%
rename from plat/arm/common/arm_gicv3.c
rename to plat/common/plat_gicv3_base.c
index 5becbcd..df05b89 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/plat/common/plat_gicv3_base.c
@@ -1,11 +1,10 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
-#include <platform_def.h>
 
 #include <common/debug.h>
 #include <common/interrupt_props.h>
@@ -13,6 +12,7 @@
 #include <lib/utils.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <platform_def.h>
 
 /******************************************************************************
  * The following functions are defined as weak to allow a platform to override
@@ -79,7 +79,7 @@
 	return plat_arm_calc_core_pos(mpidr);
 }
 
-static const gicv3_driver_data_t arm_gic_data __unused = {
+gicv3_driver_data_t arm_gic_data __unused = {
 	.gicd_base = PLAT_ARM_GICD_BASE,
 	.gicr_base = 0U,
 	.interrupt_props = arm_interrupt_props,
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index 98b99d1..c848cae 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -149,6 +149,7 @@
 ERRATA_A53_835769	:=	1
 ERRATA_A53_843419	:=	1
 ERRATA_A53_855873	:=	1
+ERRATA_A53_1530924	:=	1
 
 IMX_DRAM_RETENTION	?=	1
 $(eval $(call assert_boolean,IMX_DRAM_RETENTION))
diff --git a/plat/mediatek/build_helpers/options.mk b/plat/mediatek/build_helpers/options.mk
index 75cc80a..c55f50e 100644
--- a/plat/mediatek/build_helpers/options.mk
+++ b/plat/mediatek/build_helpers/options.mk
@@ -1,27 +1,30 @@
 #
-# Copyright (c) 2022-2023, MediaTek Inc. All rights reserved.
+# Copyright (c) 2022-2025, MediaTek Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # call add_defined_option to evaluate MTK defined value
-$(eval $(call add_defined_option,MTK_SIP_KERNEL_BOOT_ENABLE))
-$(eval $(call add_defined_option,PLAT_EXTRA_RODATA_INCLUDES))
-$(eval $(call add_defined_option,MTK_EXTRA_LINKERFILE))
-$(eval $(call add_defined_option,MTK_BL31_AS_BL2))
-$(eval $(call add_defined_option,MTK_BL33_IS_64BIT))
-$(eval $(call add_defined_option,PLAT_XLAT_TABLES_DYNAMIC))
-$(eval $(call add_defined_option,MTK_ADAPTED))
-$(eval $(call add_defined_option,MTK_PUBEVENT_ENABLE))
-$(eval $(call add_defined_option,MTK_SOC))
-$(eval $(call add_defined_option,UART_CLOCK))
-$(eval $(call add_defined_option,UART_BAUDRATE))
-$(eval $(call add_defined_option,CONFIG_MTK_MCUSYS))
-$(eval $(call add_defined_option,CONFIG_MTK_PM_SUPPORT))
-$(eval $(call add_defined_option,CONFIG_MTK_CPU_PM_SUPPORT))
-$(eval $(call add_defined_option,CONFIG_MTK_SMP_EN))
-$(eval $(call add_defined_option,CONFIG_MTK_CPU_SUSPEND_EN))
-$(eval $(call add_defined_option,CONFIG_MTK_PM_ARCH))
-$(eval $(call add_defined_option,CONFIG_MTK_CPU_PM_ARCH))
-$(eval $(call add_defined_option,CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND))
-$(eval $(call add_defined_option,CONFIG_MTK_MTCMOS))
+DEFINED_OPTIONS := \
+	CONFIG_MTK_CPU_PM_ARCH \
+	CONFIG_MTK_CPU_PM_SUPPORT \
+	CONFIG_MTK_CPU_SUSPEND_EN \
+	CONFIG_MTK_MCUSYS \
+	CONFIG_MTK_MTCMOS \
+	CONFIG_MTK_PM_ARCH \
+	CONFIG_MTK_PM_SUPPORT \
+	CONFIG_MTK_SMP_EN \
+	CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND \
+	MTK_ADAPTED \
+	MTK_BL31_AS_BL2 \
+	MTK_BL33_IS_64BIT \
+	MTK_EXTRA_LINKERFILE \
+	MTK_PUBEVENT_ENABLE \
+	MTK_SIP_KERNEL_BOOT_ENABLE \
+	MTK_SOC \
+	PLAT_EXTRA_RODATA_INCLUDES \
+	PLAT_XLAT_TABLES_DYNAMIC \
+	UART_BAUDRATE \
+	UART_CLOCK
+
+$(foreach opt, $(DEFINED_OPTIONS),$(eval $(call add_defined_option,$(opt))))
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c
index 632af52..70168d1 100644
--- a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c
@@ -22,7 +22,15 @@
 	uint32_t count = 0;
 
 	while ((mmio_read_32(reg) & mask) != expect) {
-		if (count > retry_times) {
+		/*
+		 * If retry_times == HW_SEM_NO_WAIT, it is just for checking if the hardware
+		 * semaphore can be locked or not. The purpose is for SMMU to check NPU power
+		 * status. Hence, just returning -EBUSY is okay. There is no need to show any
+		 * ERROR message here.
+		 */
+		if (retry_times == HW_SEM_NO_WAIT) {
+			return -EBUSY;
+		} else if (count > retry_times) {
 			ERROR("%s: timed out, reg = %x, mask = %x, expect = %x\n",
 			       __func__, reg, mask, expect);
 			return -EBUSY;
@@ -116,14 +124,14 @@
 {
 	return apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_CTRL,
 					APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_STA,
-					APU_HW_SEM_SYS_APMCU, HW_SEM_GET, 0, 0);
+					APU_HW_SEM_SYS_APMCU, HW_SEM_GET, HW_SEM_NO_WAIT, 0);
 }
 
 int rv_iommu_hw_sem_unlock(void)
 {
 	return apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_CTRL,
 					APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_STA,
-					APU_HW_SEM_SYS_APMCU, HW_SEM_PUT, 0, 0);
+					APU_HW_SEM_SYS_APMCU, HW_SEM_PUT, HW_SEM_NO_WAIT, 0);
 }
 
 int apu_hw_sema_ctl(uint32_t sem_addr, uint8_t usr_bit, uint8_t ctl, uint32_t timeout,
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h
index b5a48e2..17f5500 100644
--- a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h
@@ -27,6 +27,7 @@
 		    uint8_t bypass);
 
 #define HW_SEM_TIMEOUT	(300) /* 300 us */
+#define HW_SEM_NO_WAIT	(0)   /* no wait */
 
 /* APU MBOX */
 #define MBOX_WKUP_CFG		(0x80)
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c
index 563e6b5..a1c903e 100644
--- a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c
+++ b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c
@@ -7,12 +7,11 @@
 #include <stdint.h>
 #include <stdio.h>
 
-#include <drivers/cirq.h>
-
 #include <platform_def.h>
 
 #include <lib/pm/mtk_pm.h>
 #include <lpm_v2/mt_lp_rm.h>
+#include <mt_cirq.h>
 #include "mt_cpu_pm.h"
 #include "mt_lp_irqremain.h"
 
diff --git a/plat/mediatek/drivers/smmu/smmu.c b/plat/mediatek/drivers/smmu/smmu.c
index 4d31071..a3d83ec 100644
--- a/plat/mediatek/drivers/smmu/smmu.c
+++ b/plat/mediatek/drivers/smmu/smmu.c
@@ -255,9 +255,6 @@
 		break;
 	}
 
-	if (ret)
-		ERROR(TAG "%s, smmu_%u cmd:%u fail:%u\n", __func__, smmu_id, cmd_id, ret);
-
 	return ret;
 }
 /* Register MTK SMMU service */
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index 4d5a100..a41c205 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -21,7 +21,7 @@
 
 PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/xlat_tables_common.c		\
 				lib/xlat_tables/aarch64/xlat_tables.c		\
-				plat/arm/common/arm_gicv2.c			\
+				plat/common/plat_gicv2_base.c			\
 				plat/common/plat_gicv2.c			\
 				plat/common/aarch64/crash_console_helpers.S
 
diff --git a/plat/mediatek/mt8189/include/platform_def.h b/plat/mediatek/mt8189/include/platform_def.h
index 66bec16..e61aaa2 100644
--- a/plat/mediatek/mt8189/include/platform_def.h
+++ b/plat/mediatek/mt8189/include/platform_def.h
@@ -45,6 +45,15 @@
 #define UART_BAUDRATE	(115200)
 
 /*******************************************************************************
+ * CIRQ related constants
+ ******************************************************************************/
+#define SYS_CIRQ_BASE		(IO_PHYS + 204000)
+#define MD_WDT_IRQ_BIT_ID	(519)
+#define CIRQ_REG_NUM		(19)
+#define CIRQ_SPI_START		(128)
+#define CIRQ_IRQ_NUM		(598)
+
+/*******************************************************************************
  * System counter frequency related constants
  ******************************************************************************/
 #define SYS_COUNTER_FREQ_IN_HZ	(13000000)
@@ -81,6 +90,18 @@
 #define BL31_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
 
 /*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE		(MT_GIC_BASE)
+#define MT_GIC_RDIST_BASE	(MT_GIC_BASE + 0x40000)
+#define DEV_IRQ_ID		300
+
+#define PLAT_MTK_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(DEV_IRQ_ID, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_LEVEL)
+
+/*******************************************************************************
  * Platform specific page table and MMU setup constants
  ******************************************************************************/
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
diff --git a/plat/mediatek/mt8189/platform.mk b/plat/mediatek/mt8189/platform.mk
index 31a5ed5..7e40146 100644
--- a/plat/mediatek/mt8189/platform.mk
+++ b/plat/mediatek/mt8189/platform.mk
@@ -27,6 +27,8 @@
 MODULES-y += $(MTK_PLAT)/lib/mtk_init
 MODULES-y += $(MTK_PLAT)/lib/pm
 MODULES-y += $(MTK_PLAT)/topology
+MODULES-y += $(MTK_PLAT)/drivers/cirq
+MODULES-y += $(MTK_PLAT)/drivers/gic600
 MODULES-y += $(MTK_PLAT)/drivers/mcusys
 MODULES-y += $(MTK_PLAT)/drivers/timer
 
diff --git a/plat/mediatek/mt8196/plat_config.mk b/plat/mediatek/mt8196/plat_config.mk
index 84a25e9..7412756 100644
--- a/plat/mediatek/mt8196/plat_config.mk
+++ b/plat/mediatek/mt8196/plat_config.mk
@@ -50,6 +50,7 @@
 CPU_PWR_TOPOLOGY := group_4_3_1
 CPU_PM_CORE_ARCH64_ONLY := y
 CPU_PM_DOMAIN_CORE_ONLY := n
+CPU_PM_IRQ_REMAIN_ENABLE := y
 CPU_PM_SUSPEND_NOTIFY := y
 CONFIG_MTK_SPM_SUPPORT := y
 CONFIG_MTK_SPM_COMMON_SUPPORT := y
diff --git a/plat/mediatek/topology/armv9/topology.c b/plat/mediatek/topology/armv9/topology.c
deleted file mode 100644
index d6ecc83..0000000
--- a/plat/mediatek/topology/armv9/topology.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2024, Mediatek Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <lib/psci/psci.h>
-#include <platform_def.h>
-
-#pragma weak plat_get_power_domain_tree_desc
-
-static const unsigned char mtk_power_domain_tree_desc[] = {
-	/* Number of root nodes */
-	PLATFORM_SYSTEM_COUNT,
-	/* Number of children for the root node */
-	PLATFORM_CLUSTER_COUNT,
-	/* Number of children for the first cluster node */
-	PLATFORM_CLUSTER0_CORE_COUNT
-};
-
-/*******************************************************************************
- * This function returns the default topology tree information.
- ******************************************************************************/
-const unsigned char *plat_get_power_domain_tree_desc(void)
-{
-	return mtk_power_domain_tree_desc;
-}
diff --git a/plat/nuvoton/npcm845x/platform.mk b/plat/nuvoton/npcm845x/platform.mk
index d73756c..a69336a 100644
--- a/plat/nuvoton/npcm845x/platform.mk
+++ b/plat/nuvoton/npcm845x/platform.mk
@@ -201,7 +201,7 @@
 PLAT_BL_COMMON_SOURCES	:=	drivers/delay_timer/delay_timer.c \
 		drivers/delay_timer/generic_delay_timer.c \
 		plat/common/plat_gicv2.c \
-		plat/arm/common/arm_gicv2.c \
+		plat/common/plat_gicv2_base.c \
 		plat/nuvoton/common/plat_nuvoton_gic.c \
 		${NPCM850_GIC_SOURCES} \
 		plat/nuvoton/npcm845x/npcm845x_common.c \
diff --git a/plat/nxp/s32/s32g274ardb2/plat_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
index 7121900..a7dda0d 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_helpers.S
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -113,14 +113,12 @@
 /* void platform_mem_init(void); */
 func platform_mem_init
 	mov	x10, x30
-	mov	x0, #BL31_BASE
-	mov	x1, #(BL31_LIMIT & 0xFFFFU)
-	movk	x1, #(BL31_LIMIT >> 16), lsl #16
+	mov_imm	x0, BL31_BASE
+	mov_imm	x1, BL31_LIMIT
 	sub	x1, x1, x0
 	bl	zeromem
-	mov	x0, #BL33_BASE
-	mov	x1, #(BL33_LIMIT & 0xFFFFU)
-	movk	x1, #(BL33_LIMIT >> 16), lsl #16
+	mov_imm	x0, BL33_BASE
+	mov_imm	x1, BL33_LIMIT
 	sub	x1, x1, x0
 	bl	zeromem
 	mov	x30, x10
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index da981e5..751511c 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -148,7 +148,7 @@
 endif
 
 # Pointer Authentication sources
-ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3 5))
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c
 endif
 
diff --git a/plat/qti/common/src/aarch64/qti_kryo4_gold.S b/plat/qti/common/src/aarch64/qti_kryo4_gold.S
index 49b7cf0..61eb755 100644
--- a/plat/qti/common/src/aarch64/qti_kryo4_gold.S
+++ b/plat/qti/common/src/aarch64/qti_kryo4_gold.S
@@ -59,9 +59,7 @@
 	ret
 endfunc qti_kryo4_gold_cpu_reg_dump
 
-declare_cpu_ops_wa	qti_kryo4_gold, QTI_KRYO4_GOLD_MIDR,	\
+declare_cpu_ops	qti_kryo4_gold, QTI_KRYO4_GOLD_MIDR,	\
 		qti_kryo4_gold_reset_func,		\
-		CPU_NO_EXTRA1_FUNC,		\
-		cortex_a76_disable_wa_cve_2018_3639,	\
 		cortex_a76_core_pwr_dwn,	\
 		qti_kryo4_gold_cluster_pwr_dwn
diff --git a/plat/qti/msm8916/tsp/msm8916_tsp_setup.c b/plat/qti/msm8916/tsp/msm8916_tsp_setup.c
index 218af57..88d3c93 100644
--- a/plat/qti/msm8916/tsp/msm8916_tsp_setup.c
+++ b/plat/qti/msm8916/tsp/msm8916_tsp_setup.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2023, Stephan Gerhold <stephan@gerhold.net>
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +11,8 @@
 #include "../msm8916_setup.h"
 #include <platform_def.h>
 
-void tsp_early_platform_setup(void)
+void tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3)
 {
 	msm8916_early_platform_setup();
 }
diff --git a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
index 4bbb259..31583b5 100644
--- a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
+++ b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,7 +15,8 @@
 
 static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
 
-void tsp_early_platform_setup(void)
+void tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3)
 {
 	uniphier_soc = uniphier_get_soc_id();
 	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
diff --git a/plat/xilinx/common/tsp/tsp_plat_setup.c b/plat/xilinx/common/tsp/tsp_plat_setup.c
index 21c29c3..5df4b6e 100644
--- a/plat/xilinx/common/tsp/tsp_plat_setup.c
+++ b/plat/xilinx/common/tsp/tsp_plat_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2023, Advanced Micro Devices. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -17,7 +17,8 @@
 /*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
-void tsp_early_platform_setup(void)
+void tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
+			      u_register_t arg2, u_register_t arg3)
 {
 	/*
 	 * Register a different console than already in use to display
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index eb926ee..6ec8649 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -116,12 +116,14 @@
 }
 
 /**
- * versal_net_system_reset() - This function sends the reset request to firmware
- *                             for the system to reset. This function does not
- *                             return.
+ * versal_net_system_reset_scope() - Sends the reset request to firmware for
+ * the system to reset.
+ * @scope : scope of reset which could be SYSTEM/SUBSYSTEM/PS-ONLY
  *
+ * Return:
+ *     Does not return if system resets, none if there is a failure.
  */
-static void __dead2 versal_net_system_reset(void)
+static void __dead2 versal_net_system_reset_scope(uint32_t scope)
 {
 	uint32_t ret, timeout = 10000U;
 
@@ -133,7 +135,7 @@
 	 */
 	if (!pwrdwn_req_received) {
 		(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
-					 pm_get_shutdown_scope(), SECURE_FLAG);
+					 scope, SECURE_FLAG);
 
 		/*
 		 * Wait for system shutdown request completed and idle callback
@@ -155,6 +157,54 @@
 }
 
 /**
+ * versal_net_system_reset() - This function sends the reset request to firmware
+ * for the system to reset in response to SYSTEM_RESET call
+ *
+ * Return:
+ *     Does not return if system resets, none if there is a failure.
+ */
+static void __dead2 versal_net_system_reset(void)
+{
+	/*
+	 * Any platform-specific actions for handling a cold reset
+	 * should be performed here before invoking
+	 * versal_net_system_reset_scope.
+	 */
+	versal_net_system_reset_scope(XPM_SHUTDOWN_SUBTYPE_RST_SUBSYSTEM);
+}
+
+/**
+ * versal_net_system_reset2() - Handles warm / vendor-specific system reset
+ * in response to SYSTEM_RESET2 call.
+ * @is_vendor: Flag indicating if this is a vendor-specific reset
+ * @reset_type: Type of reset requested
+ * @cookie: Additional reset data
+ *
+ * This function initiates a controlled system reset by requesting it
+ * through the PM firmware.
+ *
+ * Return:
+ *	Does not return if system resets, PSCI_E_INTERN_FAIL
+ *	if there is a failure.
+ */
+static int versal_net_system_reset2(int is_vendor, int reset_type, u_register_t cookie)
+{
+	if (is_vendor == 0 && reset_type == PSCI_RESET2_SYSTEM_WARM_RESET) {
+		/*
+		 * Any platform-specific actions for handling a warm reset
+		 * should be performed here before invoking
+		 * versal_net_system_reset_scope.
+		 */
+		versal_net_system_reset_scope(XPM_SHUTDOWN_SUBTYPE_RST_SUBSYSTEM);
+	} else {
+		/* Vendor specific reset */
+		versal_net_system_reset_scope(pm_get_shutdown_scope());
+	}
+
+	return PSCI_E_INTERN_FAIL;
+}
+
+/**
  * versal_net_pwr_domain_suspend() - This function sends request to PMC to suspend
  *                                   core.
  * @target_state: Targeted state.
@@ -315,6 +365,7 @@
 	.pwr_domain_suspend_finish      = versal_net_pwr_domain_suspend_finish,
 	.system_off                     = versal_net_system_off,
 	.system_reset                   = versal_net_system_reset,
+	.system_reset2                  = versal_net_system_reset2,
 	.validate_ns_entrypoint		= versal_net_validate_ns_entrypoint,
 	.validate_power_state           = versal_net_validate_power_state,
 	.get_sys_suspend_power_state    = versal_net_get_sys_suspend_power_state,
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
index 25caab4..eda3e36 100644
--- a/plat/xilinx/versal_net/platform.mk
+++ b/plat/xilinx/versal_net/platform.mk
@@ -141,7 +141,7 @@
 				${PLAT_PATH}/bl31_versal_net_setup.c		\
 				common/fdt_fixup.c				\
 				common/fdt_wrappers.c				\
-				plat/arm/common/arm_gicv3.c 			\
+				plat/common/plat_gicv3_base.c			\
 				${LIBFDT_SRCS}					\
 				${PLAT_PATH}/sip_svc_setup.c			\
 				${XLAT_TABLES_LIB_SRCS}
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 5a86658..27e5427 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -101,7 +101,7 @@
 				drivers/cadence/uart/aarch64/cdns_console.S	\
 				plat/arm/common/arm_cci.c			\
 				plat/arm/common/arm_common.c			\
-				plat/arm/common/arm_gicv2.c			\
+				plat/common/plat_gicv2_base.c			\
 				plat/common/plat_gicv2.c			\
 				plat/xilinx/common/ipi.c			\
 				plat/xilinx/zynqmp/zynqmp_ipi.c			\
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 46333af..6051de8 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -7,9 +7,6 @@
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <lib/cpus/errata.h>
-#include <lib/cpus/wa_cve_2017_5715.h>
-#include <lib/cpus/wa_cve_2018_3639.h>
-#include <lib/cpus/wa_cve_2022_23960.h>
 #include <lib/smccc.h>
 #include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
@@ -35,8 +32,11 @@
 	/* Workaround checks are currently only implemented for aarch64 */
 #if WORKAROUND_CVE_2017_5715
 	case SMCCC_ARCH_WORKAROUND_1:
-		if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)
+		if (check_erratum_applies(CVE(2017, 5715))
+			== ERRATA_NOT_APPLIES) {
 			return 1;
+		}
+
 		return 0; /* ERRATA_APPLIES || ERRATA_MISSING */
 #endif
 
@@ -66,8 +66,10 @@
 		 * or permanently mitigated, report the latter as not
 		 * needing dynamic mitigation.
 		 */
-		if (wa_cve_2018_3639_get_disable_ptr() == NULL)
+		if (check_erratum_applies(ERRATUM(ARCH_WORKAROUND_2))
+			== ERRATA_NOT_APPLIES)
 			return 1;
+
 		/*
 		 * If we get here, this CPU requires dynamic mitigation
 		 * so report it as such.
@@ -87,10 +89,13 @@
 		 * CVE-2017-5715 since this SMC can be used instead of
 		 * SMCCC_ARCH_WORKAROUND_1.
 		 */
-		if ((check_smccc_arch_wa3_applies() == ERRATA_NOT_APPLIES) &&
-		    (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)) {
+		if ((check_erratum_applies(ERRATUM(ARCH_WORKAROUND_3))
+			== ERRATA_NOT_APPLIES) &&
+		    (check_erratum_applies(CVE(2017, 5715))
+			== ERRATA_NOT_APPLIES)) {
 			return 1;
 		}
+
 		return 0; /* ERRATA_APPLIES || ERRATA_MISSING */
 #endif
 
@@ -101,7 +106,7 @@
 
 #if WORKAROUND_CVE_2024_7881
 	case SMCCC_ARCH_WORKAROUND_4:
-		if (check_wa_cve_2024_7881() != ERRATA_APPLIES) {
+		if (check_erratum_applies(CVE(2024, 7881)) != ERRATA_APPLIES) {
 			return SMC_ARCH_CALL_NOT_SUPPORTED;
 		}
 		return 0;
diff --git a/services/spd/tlkd/tlkd.mk b/services/spd/tlkd/tlkd.mk
index fc8840d..6d71632 100644
--- a/services/spd/tlkd/tlkd.mk
+++ b/services/spd/tlkd/tlkd.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2024-2025, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,9 +8,11 @@
 SPD_INCLUDES		:=	-Iinclude/bl32/payloads
 endif
 
-ifeq (${ENABLE_FEAT_D128}, 0)
+ifneq (${ENABLE_FEAT_D128}, 0)
+        $(error spd=tlkd will not work with ENABLE_FEAT_D128 enabled.)
+endif
+
 SPD_SOURCES		:=	services/spd/tlkd/tlkd_common.c		\
 				services/spd/tlkd/tlkd_helpers.S	\
 				services/spd/tlkd/tlkd_main.c		\
 				services/spd/tlkd/tlkd_pm.c
-endif
\ No newline at end of file
diff --git a/services/std_svc/drtm/drtm_measurements.c b/services/std_svc/drtm/drtm_measurements.c
index d4f2b57..7214e23 100644
--- a/services/std_svc/drtm/drtm_measurements.c
+++ b/services/std_svc/drtm/drtm_measurements.c
@@ -56,7 +56,10 @@
 	}
 
 	/* Record the mesasurement in the EventLog buffer */
-	event_log_record(hash_data, event_type, &metadata);
+	rc = event_log_record(hash_data, event_type, &metadata);
+	if (rc != 0) {
+		return rc;
+	}
 
 	return 0;
 }
diff --git a/services/std_svc/errata_abi/cpu_errata_info.h b/services/std_svc/errata_abi/cpu_errata_info.h
index d688431..d685eef 100644
--- a/services/std_svc/errata_abi/cpu_errata_info.h
+++ b/services/std_svc/errata_abi/cpu_errata_info.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -48,5 +48,5 @@
 	struct   em_cpu cpu_errata_list[MAX_PLAT_CPU_ERRATA_ENTRIES];
 };
 
-int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag);
+int32_t verify_errata_implemented(uint32_t errata_id);
 #endif /* ERRATA_CPUSPEC_H */
diff --git a/services/std_svc/errata_abi/errata_abi_main.c b/services/std_svc/errata_abi/errata_abi_main.c
index a945637..74a1586 100644
--- a/services/std_svc/errata_abi/errata_abi_main.c
+++ b/services/std_svc/errata_abi/errata_abi_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -166,50 +166,33 @@
 #endif
 
 /* Function to check if the errata exists for the specific CPU and rxpx */
-int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag)
+int32_t verify_errata_implemented(uint32_t errata_id)
 {
-	int32_t ret_val;
-	struct cpu_ops *cpu_ops;
-	struct erratum_entry *entry, *end;
+	struct erratum_entry *entry;
 	long rev_var;
 
-	ret_val = EM_UNKNOWN_ERRATUM;
 	rev_var = cpu_get_rev_var();
 
 #if ERRATA_NON_ARM_INTERCONNECT
-	ret_val = non_arm_interconnect_errata(errata_id, rev_var);
+	int32_t ret_val = non_arm_interconnect_errata(errata_id, rev_var);
 	if (ret_val != EM_UNKNOWN_ERRATUM) {
 		return ret_val;
 	}
 #endif
+	entry = find_erratum_entry(errata_id);
+	if (entry == NULL)
+		return EM_UNKNOWN_ERRATUM;
 
-	cpu_ops = get_cpu_ops_ptr();
-	assert(cpu_ops != NULL);
-
-	entry = cpu_ops->errata_list_start;
-	assert(entry != NULL);
-
-	end = cpu_ops->errata_list_end;
-	assert(end != NULL);
-
-	end--; /* point to the last erratum entry of the queried cpu */
-
-	while ((entry <= end) && (ret_val == EM_UNKNOWN_ERRATUM)) {
-		if (entry->id == errata_id) {
-			if (entry->check_func(rev_var)) {
-				if (entry->chosen & WA_ENABLED_MASK)
-					if (entry->chosen & SPLIT_WA_MASK)
-						return EM_AFFECTED;
-					else
-						return EM_HIGHER_EL_MITIGATION;
-				else
-					return EM_AFFECTED;
-			}
-			return EM_NOT_AFFECTED;
-		}
-		entry += 1;
+	if (entry->check_func(rev_var)) {
+		if (entry->chosen & WA_ENABLED_MASK)
+			if (entry->chosen & SPLIT_WA_MASK)
+				return EM_AFFECTED;
+			else
+				return EM_HIGHER_EL_MITIGATION;
+		else
+			return EM_AFFECTED;
 	}
-	return ret_val;
+	return EM_NOT_AFFECTED;
 }
 
 /* Predicate indicating that a function id is part of EM_ABI */
@@ -271,7 +254,7 @@
 		if (((uint32_t)x2 != 0) && (validate_spsr_mode())) {
 			SMC_RET1(handle, EM_INVALID_PARAMETERS);
 		}
-		ret_id = verify_errata_implemented((uint32_t)x1, (uint32_t)x2);
+		ret_id = verify_errata_implemented((uint32_t)x1);
 		SMC_RET1(handle, ret_id);
 		break; /* unreachable */
 	default:
diff --git a/services/std_svc/rmmd/rmmd.mk b/services/std_svc/rmmd/rmmd.mk
index eae5031..67955ff 100644
--- a/services/std_svc/rmmd/rmmd.mk
+++ b/services/std_svc/rmmd/rmmd.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021-2024, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2025, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -16,7 +16,8 @@
 RMMD_SOURCES	+=	$(addprefix services/std_svc/rmmd/,	\
 			${ARCH}/rmmd_helpers.S			\
 			rmmd_main.c				\
-			rmmd_attest.c)
+			rmmd_attest.c				\
+			rmmd_keymgmt.c)
 
 # Let the top-level Makefile know that we intend to include RMM image
 NEED_RMM	:=	yes
diff --git a/services/std_svc/rmmd/rmmd_keymgmt.c b/services/std_svc/rmmd/rmmd_keymgmt.c
new file mode 100644
index 0000000..2414b35
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_keymgmt.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "rmmd_private.h"
+#include <common/debug.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+#include <services/rmmd_svc.h>
+#include <smccc_helpers.h>
+
+#define DIR_BIT_SHIFT		0xB
+#define KEYSET_BIT_SHIFT	0xC
+#define STREAM_ID_MASK		0xFF
+#define SUBSTREAM_MASK		0x7
+#define SUBSTREAM_SHIFT		0x8
+#define MAX_STREAM_ID		32U
+#define MAX_SUBSTREAM		3U
+
+bool extract_ide_stream_info(uint64_t ide_stream_info)
+{
+	uint8_t keyset, dir;
+	uint8_t stream_id, substream;
+
+	/* Extract keyset, dir, substream and stream ID */
+	keyset = (ide_stream_info >> KEYSET_BIT_SHIFT) & 0x1;
+	dir = (ide_stream_info >> DIR_BIT_SHIFT) & 0x1;
+	stream_id = ide_stream_info & STREAM_ID_MASK;
+	substream = (ide_stream_info >> SUBSTREAM_SHIFT) & SUBSTREAM_MASK;
+
+	if ((stream_id >= MAX_STREAM_ID) || (substream >= MAX_SUBSTREAM)) {
+		ERROR("invalid input: stream_id = %x, substream = %x\n", stream_id, substream);
+		return false;
+	}
+
+	VERBOSE("keyset = %d, dir = %d, stream_id = %d and substream = %d\n", keyset, dir,
+		 stream_id, substream);
+
+	return true;
+}
+
+int rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t rp_id,
+			     uint64_t ide_stream_info, rp_ide_key_info_t *ide_key_info_ptr,
+			     uint64_t request_id, uint64_t cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KEY_PROG: ecam address = 0x%lx and rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	if (!extract_ide_stream_info(ide_stream_info)) {
+		err = E_RMM_INVAL;
+		goto exit_fn;
+	}
+
+	err = plat_rmmd_el3_ide_key_program(ecam_address, rp_id, ide_stream_info,
+					    ide_key_info_ptr, request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+exit_fn:
+	return err;
+}
+
+int rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t rp_id,
+			    uint64_t ide_stream_info, uint64_t request_id,
+			    uint64_t cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KEY_SET_GO: ecam address = 0x%lx and rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	if (!extract_ide_stream_info(ide_stream_info)) {
+		err = E_RMM_INVAL;
+		goto exit_fn;
+	}
+
+	err = plat_rmmd_el3_ide_key_set_go(ecam_address, rp_id, ide_stream_info,
+					   request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+exit_fn:
+	return err;
+}
+
+int rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t rp_id,
+			      uint64_t ide_stream_info, uint64_t request_id,
+			      uint64_t cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KEY_SET_STOP: ecam address = 0x%lx and rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	if (!extract_ide_stream_info(ide_stream_info)) {
+		err = E_RMM_INVAL;
+		goto exit_fn;
+	}
+
+	err = plat_rmmd_el3_ide_key_set_stop(ecam_address, rp_id, ide_stream_info,
+					     request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+exit_fn:
+	return err;
+}
+
+int rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t rp_id,
+				  uint64_t *req_resp, uint64_t *request_id,
+				  uint64_t *cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KM_PULL: ecam address = 0x%lx, rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	err = plat_rmmd_el3_ide_km_pull_response(ecam_address, rp_id, req_resp, request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+	return err;
+}
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 19c8373..35582dc 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -561,6 +561,37 @@
 	case RMM_EL3_TOKEN_SIGN:
 		return rmmd_el3_token_sign(handle, x1, x2, x3, x4);
 #endif
+
+#if RMMD_ENABLE_IDE_KEY_PROG
+	case RMM_IDE_KEY_PROG:
+	{
+		rp_ide_key_info_t ide_key_info;
+
+		ide_key_info.keyqw0 = x4;
+		ide_key_info.keyqw1 = SMC_GET_GP(handle, CTX_GPREG_X5);
+		ide_key_info.keyqw2 = SMC_GET_GP(handle, CTX_GPREG_X6);
+		ide_key_info.keyqw3 = SMC_GET_GP(handle, CTX_GPREG_X7);
+		ide_key_info.ifvqw0 = SMC_GET_GP(handle, CTX_GPREG_X8);
+		ide_key_info.ifvqw1 = SMC_GET_GP(handle, CTX_GPREG_X9);
+		uint64_t x10 = SMC_GET_GP(handle, CTX_GPREG_X10);
+		uint64_t x11 = SMC_GET_GP(handle, CTX_GPREG_X11);
+
+		ret = rmmd_el3_ide_key_program(x1, x2, x3, &ide_key_info, x10, x11);
+		SMC_RET1(handle, ret);
+	}
+	case RMM_IDE_KEY_SET_GO:
+		ret = rmmd_el3_ide_key_set_go(x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5));
+		SMC_RET1(handle, ret);
+	case RMM_IDE_KEY_SET_STOP:
+		ret = rmmd_el3_ide_key_set_stop(x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5));
+		SMC_RET1(handle, ret);
+	case RMM_IDE_KM_PULL_RESPONSE: {
+		uint64_t req_resp = 0, req_id = 0, cookie_var = 0;
+
+		ret = rmmd_el3_ide_km_pull_response(x1, x2, &req_resp, &req_id, &cookie_var);
+		SMC_RET4(handle, ret, req_resp, req_id, cookie_var);
+	}
+#endif /* RMMD_ENABLE_IDE_KEY_PROG */
 	case RMM_BOOT_COMPLETE:
 		VERBOSE("RMMD: running rmmd_rmm_sync_exit\n");
 		rmmd_rmm_sync_exit(x1);
diff --git a/services/std_svc/rmmd/rmmd_private.h b/services/std_svc/rmmd/rmmd_private.h
index 0ce104d..1fbcd31 100644
--- a/services/std_svc/rmmd/rmmd_private.h
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #define RMMD_PRIVATE_H
 
 #include <context.h>
+#include <services/rmmd_svc.h>
 
 /*******************************************************************************
  * Constants that allow assembler code to preserve callee-saved registers of the
@@ -54,6 +55,17 @@
 uint64_t rmmd_el3_token_sign(void *handle, uint64_t x1, uint64_t x2,
 				    uint64_t x3, uint64_t x4);
 
+/* Functions implementing IDE KM programming */
+int rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t rp_id,
+			     uint64_t ide_stream_info, rp_ide_key_info_t *ide_key_info_ptr,
+			     uint64_t request_id, uint64_t cookie);
+int rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t rp_id, uint64_t ide_stream_info,
+			    uint64_t request_id, uint64_t cookie);
+int rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t rp_id, uint64_t ide_stream_info,
+			      uint64_t request_id, uint64_t cookie);
+int rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t rp_id, uint64_t *req_resp,
+				  uint64_t *request_id, uint64_t *cookie_ptr);
+
 /* Assembly helpers */
 uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);
 void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret);
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
index 3e1d8c9..a2fd6a0 100644
--- a/services/std_svc/rmmd/trp/trp_entry.S
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,8 @@
 	 * ---------------------------------------------
 	 */
 	.macro restore_args_call_smc
+	ldp	x10, x11, [x0, #TRP_ARG10]
+	ldp	x8, x9, [x0, #TRP_ARG8]
 	ldp	x6, x7, [x0, #TRP_ARG6]
 	ldp	x4, x5, [x0, #TRP_ARG4]
 	ldp	x2, x3, [x0, #TRP_ARG2]
diff --git a/services/std_svc/rmmd/trp/trp_helpers.c b/services/std_svc/rmmd/trp/trp_helpers.c
index 159f3a5..0607864 100644
--- a/services/std_svc/rmmd/trp/trp_helpers.c
+++ b/services/std_svc/rmmd/trp/trp_helpers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,7 +25,11 @@
 			uint64_t arg4,
 			uint64_t arg5,
 			uint64_t arg6,
-			uint64_t arg7)
+			uint64_t arg7,
+			uint64_t arg8,
+			uint64_t arg9,
+			uint64_t arg10,
+			uint64_t arg11)
 {
 	uint32_t linear_id;
 	trp_args_t *pcpu_smc_args;
@@ -44,6 +48,10 @@
 	write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5);
 	write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6);
 	write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7);
+	write_trp_arg(pcpu_smc_args, TRP_ARG8, arg8);
+	write_trp_arg(pcpu_smc_args, TRP_ARG9, arg9);
+	write_trp_arg(pcpu_smc_args, TRP_ARG10, arg10);
+	write_trp_arg(pcpu_smc_args, TRP_ARG11, arg11);
 
 	return pcpu_smc_args;
 }
@@ -53,6 +61,6 @@
  */
 __dead2 void trp_boot_abort(uint64_t err)
 {
-	(void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0));
+	(void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
 	panic();
 }
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
index b75483c..a82966e 100644
--- a/services/std_svc/rmmd/trp/trp_main.c
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,27 @@
 
 #include <platform_def.h>
 
+#define RMI_ERROR_REALM			2U
+#define RMI_ERROR_NOT_SUPPORTED		6U
+
+#define DIR_BIT_SHIFT			0x8
+#define KEYSET_SHIFT			0xC
+#define	STREAM_ID_MASK			0xFF
+#define STREAM_ID_SHIFT			0x0
+#define SUBSTREAM_MASK			0x7
+#define SUBSTREAM_SHIFT			0x8
+
+#define KEY_SET				0x0
+#define	DIR_VAL				0x0
+#define	SUBSTREAM_VAL			0x1
+#define	STREAM_ID			0x1
+
+#define ENCODE_STREAM_INFO(key, dir, substream, stream_id)			\
+		(((key & 0x1) << KEYSET_SHIFT) |				\
+		((dir & 0x1) << DIR_BIT_SHIFT) |				\
+		((substream && SUBSTREAM_MASK) << SUBSTREAM_SHIFT) |		\
+		((stream_id && STREAM_ID_MASK) << STREAM_ID_SHIFT))
+
 /* Parameters received from the previous image */
 static unsigned int trp_boot_abi_version;
 static uintptr_t trp_shared_region_start;
@@ -129,7 +150,7 @@
 {
 	VERBOSE("Delegating granule 0x%llx\n", x1);
 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
-						0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
 
 	if (smc_ret->x[0] != 0ULL) {
 		ERROR("Granule transition from NON-SECURE type to REALM type "
@@ -145,7 +166,7 @@
 {
 	VERBOSE("Undelegating granule 0x%llx\n", x1);
 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
-						0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
 
 	if (smc_ret->x[0] != 0ULL) {
 		ERROR("Granule transition from REALM type to NON-SECURE type "
@@ -154,6 +175,62 @@
 }
 
 /*******************************************************************************
+ * Test the IDE Key management interface
+ ******************************************************************************/
+static void trp_ide_keymgmt_interface_fn(unsigned long long x1, unsigned long long x2,
+					struct trp_smc_result *smc_ret)
+{
+	uint64_t ecam_address = 0U, rp_id = 0U, ide_stream_info;
+	uint64_t keyqw0, keyqw1, keyqw2, keyqw3;
+	uint64_t ifvqw0, ifvqw1;
+	int return_value;
+
+#if RMMD_ENABLE_IDE_KEY_PROG
+	trp_get_test_rootport(&ecam_address, &rp_id);
+#endif /* RMMD_ENABLE_IDE_KEY_PROG */
+	/*
+	 * Dummy values for testing:
+	 * Key set = 0x0
+	 * Dir = 0x0
+	 * Substream = 0x1
+	 * Stream ID = 0x1
+	 */
+	ide_stream_info  = ENCODE_STREAM_INFO(KEY_SET, DIR_VAL, SUBSTREAM_VAL, STREAM_ID);
+
+	/* Dummy key and IV values for testing */
+	keyqw0 = 0xA1B2C3D4E5F60708;
+	keyqw1 = 0x1122334455667788;
+	keyqw2 = 0xDEADBEEFCAFEBABE;
+	keyqw3 = 0x1234567890ABCDEF;
+	ifvqw0 = 0xABCDEF0123456789;
+	ifvqw1 = 0x9876543210FEDCBA;
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_PROG, ecam_address, rp_id,
+				ide_stream_info, keyqw0, keyqw1, keyqw2, keyqw3, ifvqw0,
+				ifvqw1, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_PROG = %d\n", return_value);
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_GO, ecam_address, rp_id,
+				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_SET_GO = %d\n", return_value);
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_STOP, ecam_address, rp_id,
+				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KM_PULL_RESPONSE, ecam_address, rp_id,
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
+
+	smc_ret->x[0] = RMI_ERROR_NOT_SUPPORTED;
+
+}
+
+/*******************************************************************************
  * Main RMI SMC handler function
  ******************************************************************************/
 void trp_rmi_handler(unsigned long fid,
@@ -179,6 +256,9 @@
 	case RMI_RMM_GRANULE_UNDELEGATE:
 		trp_asc_mark_nonsecure(x1, smc_ret);
 		break;
+	case RMI_RMM_PDEV_CREATE:
+		trp_ide_keymgmt_interface_fn(x1, x2, smc_ret);
+		break;
 	default:
 		ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
 		smc_ret->x[0] = SMC_UNK;
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
index d8c6960..16edc5e 100644
--- a/services/std_svc/rmmd/trp/trp_private.h
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -28,6 +28,7 @@
 #define RMI_RMM_REQ_VERSION		SMC64_RMI_FID(U(0))
 #define RMI_RMM_GRANULE_DELEGATE	SMC64_RMI_FID(U(1))
 #define RMI_RMM_GRANULE_UNDELEGATE	SMC64_RMI_FID(U(2))
+#define RMI_RMM_PDEV_CREATE		SMC64_RMI_FID(U(0x26))
 
 /* Definitions for RMI VERSION */
 #define RMI_ABI_VERSION_MAJOR		U(0x0)
diff --git a/services/std_svc/sdei/sdei_event.c b/services/std_svc/sdei/sdei_event.c
index e0c7971..cc8f557 100644
--- a/services/std_svc/sdei/sdei_event.c
+++ b/services/std_svc/sdei/sdei_event.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,14 +19,14 @@
  * Both shared and private maps are stored in single-dimensional array. Private
  * event entries are kept for each PE forming a 2D array.
  */
-sdei_entry_t *get_event_entry(sdei_ev_map_t *map)
+sdei_entry_t *get_event_entry(const sdei_ev_map_t *map)
 {
 	const sdei_mapping_t *mapping;
 	sdei_entry_t *cpu_priv_base;
 	unsigned int base_idx;
 	long int idx;
 
-	if (is_event_private(map)) {
+	if ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U) {
 		/*
 		 * For a private map, find the index of the mapping in the
 		 * array.
@@ -52,6 +52,39 @@
 }
 
 /*
+ * Retrieve the SDEI entry for the given mapping and target PE.
+ *
+ * on success : Returns a pointer to the SDEI entry
+ *
+ * On error, returns NULL
+ *
+ * Both shared and private maps are stored in single-dimensional array. Private
+ * event entries are kept for each PE forming a 2D array.
+ */
+sdei_entry_t *get_event_entry_target_pe(long int mapsub, unsigned int nm, uint64_t target_pe)
+{
+	sdei_entry_t *cpu_priv_base;
+	unsigned int base_idx;
+	long int idx;
+
+	/*
+	 * For a private map, find the index of the mapping in the
+	 * array.
+	 */
+	idx = mapsub;
+
+	/* Base of private mappings for this CPU */
+	base_idx = (unsigned int) plat_core_pos_by_mpidr(target_pe);
+	base_idx *= nm;
+	cpu_priv_base = &sdei_private_event_table[base_idx];
+	/*
+	 * Return the address of the entry at the same index in the
+	 * per-CPU event entry.
+	 */
+	return &cpu_priv_base[idx];
+}
+
+/*
  * Find event mapping for a given interrupt number: On success, returns pointer
  * to the event mapping. On error, returns NULL.
  */
diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c
index c58adba..4854b2e 100644
--- a/services/std_svc/sdei/sdei_intr_mgmt.c
+++ b/services/std_svc/sdei/sdei_intr_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,7 +29,8 @@
 #define MAX_EVENT_NESTING	2U
 
 /* Per-CPU SDEI state access macro */
-#define sdei_get_this_pe_state()	(&cpu_state[plat_my_core_pos()])
+#define sdei_get_this_pe_state()		(&cpu_state[plat_my_core_pos()])
+#define sdei_get_target_pe_state(_pe)	(&cpu_state[plat_core_pos_by_mpidr(_pe)])
 
 /* Structure to store information about an outstanding dispatch */
 typedef struct sdei_dispatch_context {
@@ -58,6 +59,13 @@
 /* SDEI states for all cores in the system */
 static sdei_cpu_state_t cpu_state[PLATFORM_CORE_COUNT];
 
+bool sdei_is_target_pe_masked(uint64_t target_pe)
+{
+	const sdei_cpu_state_t *state = sdei_get_target_pe_state(target_pe);
+
+	return state->pe_masked;
+}
+
 int64_t sdei_pe_mask(void)
 {
 	int64_t ret = 0;
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 01cc131..bbc9f73 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -910,25 +910,54 @@
 /* Send a signal to another SDEI client PE */
 static int sdei_signal(int ev_num, uint64_t target_pe)
 {
+	unsigned int i;
 	sdei_ev_map_t *map;
+	sdei_ev_map_t *map_priv;
+	sdei_entry_t *se;
 
 	/* Only event 0 can be signalled */
-	if (ev_num != SDEI_EVENT_0)
+	if (ev_num != SDEI_EVENT_0) {
 		return SDEI_EINVAL;
+	}
 
 	/* Find mapping for event 0 */
 	map = find_event_map(SDEI_EVENT_0);
-	if (map == NULL)
+	if (map == NULL) {
 		return SDEI_EINVAL;
+	}
 
 	/* The event must be signalable */
-	if (!is_event_signalable(map))
+	if (!is_event_signalable(map)) {
 		return SDEI_EINVAL;
+	}
 
 	/* Validate target */
-	if (!is_valid_mpidr(target_pe))
+	if (!is_valid_mpidr(target_pe)) {
 		return SDEI_EINVAL;
+	}
 
+	/* The event must be unmasked */
+	if (sdei_is_target_pe_masked(target_pe)) {
+		return SDEI_EINVAL;
+	}
+
+	/* The event must be registered and enabled */
+	if (is_event_private(map)) {
+		map_priv = SDEI_PRIVATE_MAPPING()->map;
+		for (i = 0; i < SDEI_PRIVATE_MAPPING()->num_maps; i++) {
+			if (map_priv->ev_num == SDEI_EVENT_0) {
+				se = get_event_entry_target_pe((long int) i,
+				(unsigned int) SDEI_PRIVATE_MAPPING()->num_maps, target_pe);
+				if (!(GET_EV_STATE((se), REGISTERED))) {
+					return SDEI_EINVAL;
+				}
+				if (!(GET_EV_STATE((se), ENABLED))) {
+					return SDEI_EINVAL;
+				}
+			}
+			map_priv++;
+		}
+	}
 	/* Raise SGI. Platform will validate target_pe */
 	plat_ic_raise_el3_sgi((int) map->intr, (u_register_t) target_pe);
 
diff --git a/services/std_svc/sdei/sdei_private.h b/services/std_svc/sdei/sdei_private.h
index 44a7301..d48db46 100644
--- a/services/std_svc/sdei/sdei_private.h
+++ b/services/std_svc/sdei/sdei_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -232,13 +232,15 @@
 
 sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared);
 sdei_ev_map_t *find_event_map(int ev_num);
-sdei_entry_t *get_event_entry(sdei_ev_map_t *map);
+sdei_entry_t *get_event_entry(const sdei_ev_map_t *map);
+sdei_entry_t *get_event_entry_target_pe(long int mapsub, unsigned int nm, uint64_t target_pe);
 
 int64_t sdei_event_context(void *handle, unsigned int param);
 int sdei_event_complete(bool resume, uint64_t pc);
 
-void sdei_pe_unmask(void);
+bool sdei_is_target_pe_masked(uint64_t target_pe);
 int64_t sdei_pe_mask(void);
+void sdei_pe_unmask(void);
 
 int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle,
 		void *cookie);
diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
index 5263c04..323f7f7 100644
--- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
+++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
@@ -679,6 +679,18 @@
 		return 0;
 }
 
+static bool compatible_version(uint32_t ffa_version, uint16_t major,
+			       uint16_t minor)
+{
+	bool bit31_set = ffa_version & FFA_VERSION_BIT31_MASK;
+	uint16_t majv = (ffa_version >> FFA_VERSION_MAJOR_SHIFT) &
+			FFA_VERSION_MAJOR_MASK;
+	uint16_t minv = (ffa_version >> FFA_VERSION_MINOR_SHIFT) &
+			FFA_VERSION_MINOR_MASK;
+
+	return !bit31_set && majv == major && minv >= minor;
+}
+
 static int
 spmc_validate_mtd_start(struct ffa_mtd *desc, uint32_t ffa_version,
 			size_t fragment_length, size_t total_length)
@@ -691,7 +703,7 @@
 	/* Determine the appropriate minimum descriptor size. */
 	if (ffa_version == MAKE_FFA_VERSION(1, 0)) {
 		min_desc_size = sizeof(struct ffa_mtd_v1_0);
-	} else if (ffa_version == MAKE_FFA_VERSION(1, 1)) {
+	} else if (compatible_version(ffa_version, 1, 1)) {
 		min_desc_size = sizeof(struct ffa_mtd);
 	} else {
 		return FFA_ERROR_INVALID_PARAMETER;
@@ -1212,7 +1224,7 @@
 
 	if (ffa_version == MAKE_FFA_VERSION(1, 0)) {
 		min_desc_size = sizeof(struct ffa_mtd_v1_0);
-	} else if (ffa_version == MAKE_FFA_VERSION(1, 1)) {
+	} else if (compatible_version(ffa_version, 1, 1)) {
 		min_desc_size = sizeof(struct ffa_mtd);
 	} else {
 		WARN("%s: bad FF-A version.\n", __func__);
diff --git a/services/std_svc/spm/spm_mm/spm_mm_main.c b/services/std_svc/spm/spm_mm/spm_mm_main.c
index 34e2c00..7fe826d 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_main.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -34,53 +34,19 @@
 /*******************************************************************************
  * Set state of a Secure Partition context.
  ******************************************************************************/
-void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
+static void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
 {
-	spin_lock(&(sp_ptr->state_lock));
 	sp_ptr->state = state;
 	spin_unlock(&(sp_ptr->state_lock));
 }
 
 /*******************************************************************************
- * Wait until the state of a Secure Partition is the specified one and change it
- * to the desired state.
+ * Change the state of a Secure Partition to the one specified.
  ******************************************************************************/
-void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
+static void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
 {
-	int success = 0;
-
-	while (success == 0) {
-		spin_lock(&(sp_ptr->state_lock));
-
-		if (sp_ptr->state == from) {
-			sp_ptr->state = to;
-
-			success = 1;
-		}
-
-		spin_unlock(&(sp_ptr->state_lock));
-	}
-}
-
-/*******************************************************************************
- * Check if the state of a Secure Partition is the specified one and, if so,
- * change it to the desired state. Returns 0 on success, -1 on error.
- ******************************************************************************/
-int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
-{
-	int ret = -1;
-
 	spin_lock(&(sp_ptr->state_lock));
-
-	if (sp_ptr->state == from) {
-		sp_ptr->state = to;
-
-		ret = 0;
-	}
-
-	spin_unlock(&(sp_ptr->state_lock));
-
-	return ret;
+	sp_ptr->state = to;
 }
 
 /*******************************************************************************