Merge "feat(st): use and override default MBedTLS config" into integration
diff --git a/Makefile b/Makefile
index 386a74b..e0b7acc 100644
--- a/Makefile
+++ b/Makefile
@@ -971,6 +971,7 @@
 	ENABLE_FEAT_ECV \
 	ENABLE_FEAT_FGT \
 	ENABLE_FEAT_FGT2 \
+	ENABLE_FEAT_FGWTE3 \
 	ENABLE_FEAT_FPMR \
 	ENABLE_FEAT_HCX \
 	ENABLE_FEAT_LS64_ACCDATA \
@@ -1141,6 +1142,7 @@
 	FEAT_PABANDON \
 	ENABLE_FEAT_FGT \
 	ENABLE_FEAT_FGT2 \
+	ENABLE_FEAT_FGWTE3 \
 	ENABLE_FEAT_FPMR \
 	ENABLE_FEAT_ECV \
 	ENABLE_FEAT_AMUv1p1 \
diff --git a/bl1/aarch32/bl1_context_mgmt.c b/bl1/aarch32/bl1_context_mgmt.c
index 85d35a7..1d7770c 100644
--- a/bl1/aarch32/bl1_context_mgmt.c
+++ b/bl1/aarch32/bl1_context_mgmt.c
@@ -47,7 +47,7 @@
 }
 
 /* Following functions are used for CPU context handling */
-void *cm_get_context(uint32_t security_state)
+void *cm_get_context(size_t security_state)
 {
 	assert(sec_state_is_valid(security_state));
 	return &bl1_cpu_context[security_state];
diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c
index b9a7e5b..98d2ac1 100644
--- a/bl1/aarch64/bl1_context_mgmt.c
+++ b/bl1/aarch64/bl1_context_mgmt.c
@@ -19,7 +19,7 @@
 entry_point_info_t *bl2_ep_info;
 
 
-void *cm_get_context(uint32_t security_state)
+void *cm_get_context(size_t security_state)
 {
 	assert(sec_state_is_valid(security_state));
 	return bl1_cpu_context_ptr[security_state];
diff --git a/bl31/bl31_context_mgmt.c b/bl31/bl31_context_mgmt.c
index 34f69ad..1fe2ddb 100644
--- a/bl31/bl31_context_mgmt.c
+++ b/bl31/bl31_context_mgmt.c
@@ -17,7 +17,7 @@
  * for the calling CPU that was set as the context for the specified security
  * state. NULL is returned if no such structure has been specified.
  ******************************************************************************/
-void *cm_get_context(uint32_t security_state)
+void *cm_get_context(size_t security_state)
 {
 	assert(sec_state_is_valid(security_state));
 
@@ -43,7 +43,7 @@
  * specified.
  ******************************************************************************/
 void *cm_get_context_by_index(unsigned int cpu_idx,
-				unsigned int security_state)
+				size_t security_state)
 {
 	assert(sec_state_is_valid(security_state));
 
diff --git a/bl31/interrupt_mgmt.c b/bl31/interrupt_mgmt.c
index 1a1cbc4..641d66a 100644
--- a/bl31/interrupt_mgmt.c
+++ b/bl31/interrupt_mgmt.c
@@ -78,7 +78,7 @@
  * routing model (expressed through the IRQ and FIQ bits) for a security state
  * which was stored through a call to 'set_routing_model()' earlier.
  ******************************************************************************/
-u_register_t get_scr_el3_from_routing_model(uint32_t security_state)
+u_register_t get_scr_el3_from_routing_model(size_t security_state)
 {
 	u_register_t scr_el3;
 
diff --git a/bl32/sp_min/sp_min_main.c b/bl32/sp_min/sp_min_main.c
index 9add239..57d737d 100644
--- a/bl32/sp_min/sp_min_main.c
+++ b/bl32/sp_min/sp_min_main.c
@@ -67,7 +67,7 @@
  * for the calling CPU that was set as the context for the specified security
  * state. NULL is returned if no such structure has been specified.
  ******************************************************************************/
-void *cm_get_context(uint32_t security_state)
+void *cm_get_context(size_t security_state)
 {
 	assert(security_state == NON_SECURE);
 	return sp_min_cpu_ctx_ptr[plat_my_core_pos()];
@@ -90,7 +90,7 @@
  * specified.
  ******************************************************************************/
 void *cm_get_context_by_index(unsigned int cpu_idx,
-				unsigned int security_state)
+				size_t security_state)
 {
 	assert(security_state == NON_SECURE);
 	return sp_min_cpu_ctx_ptr[cpu_idx];
diff --git a/common/feat_detect.c b/common/feat_detect.c
index fa817d9..d7adae6 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -297,6 +297,12 @@
 			     ID_AA64ISAR2_EL1_MOPS_MASK);
 }
 
+static unsigned int read_feat_fgwte3_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64mmfr4_el1(), ID_AA64MMFR4_EL1_FGWTE3_SHIFT,
+			     ID_AA64MMFR4_EL1_FGWTE3_MASK);
+}
+
 /***********************************************************************************
  * TF-A supports many Arm architectural features starting from arch version
  * (8.0 till 8.7+). These features are mostly enabled through build flags. This
@@ -437,6 +443,8 @@
 	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);
+	check_feature(ENABLE_FEAT_FGWTE3, read_feat_fgwte3_id_field(),
+		      "FGWTE3", 1, 1);
 
 	if (tainted) {
 		panic();
diff --git a/docs/components/ven-el3-service.rst b/docs/components/ven-el3-service.rst
index 8be1b39..3c35948 100644
--- a/docs/components/ven-el3-service.rst
+++ b/docs/components/ven-el3-service.rst
@@ -36,9 +36,13 @@
 +-----------------------------------+ Compliance Suite) SMC | | 1 - 15 are reserved for future expansion. |
 | 0xC7000030 - 0xC700003F (SMC64)   | handler               |                                             |
 +-----------------------------------+-----------------------+---------------------------------------------+
-| 0x87000040 - 0x8700FFFF (SMC32)   | Reserved              | | reserved for future expansion             |
+| 0x87000040 - 0x8700004F (SMC32)   | TPM Start method      | | 0 is in use.                              |
++-----------------------------------+                       | | 1 - 15 are reserved for future expansion. |
+| 0xC7000040 - 0xC700004F (SMC64)   |                       |                                             |
++-----------------------------------+-----------------------+---------------------------------------------+
+| 0x87000050 - 0x8700FFFF (SMC32)   | Reserved              | | reserved for future expansion             |
 +-----------------------------------+                       |                                             |
-| 0xC7000040 - 0xC700FFFF (SMC64)   |                       |                                             |
+| 0xC7000050 - 0xC700FFFF (SMC64)   |                       |                                             |
 +-----------------------------------+-----------------------+---------------------------------------------+
 
 Source definitions for vendor-specific EL3 Monitor Service Calls used by TF-A are located in
@@ -50,6 +54,8 @@
 |                          1 |                          0 | Added Debugfs and PMF services.|
 +----------------------------+----------------------------+--------------------------------+
 |                          1 |                          1 | Added ACS SMC handler services.|
++------------------------------------------------------------------------------------------+
+|                          1 |                          2 | Added TPM Start method.        |
 +----------------------------+----------------------------+--------------------------------+
 
 *Table 1: Showing different versions of Vendor-specific service and changes done with each version*
@@ -84,9 +90,15 @@
 to their ACS EL3 code based on their respective use-cases.
 For more details on System ACS, `System ACS`_.
 
+TPM Start method
+----------------
+
+TPM start method as mentioned in `TCG ACPI specification`_ section 3.3.1.
+
 --------------
 
 *Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.*
 
 .. _System ACS: https://developer.arm.com/Architectures/Architectural%20Compliance%20Suite
 .. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest
+.. _TCG ACPI specification: https://trustedcomputinggroup.org/wp-content/uploads/TCG-ACPI-Specification-Version-1.4-Revision-15_pub.pdf
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index f99840b..8a607ac 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -375,6 +375,23 @@
    This flag can take the values 0 to 2, to align  with the ``ENABLE_FEAT``
    mechanism. Default value is ``0``.
 
+-  ``ENABLE_FEAT_FGWTE3``: Numeric value to enable support for
+   Fine Grained Write Trap EL3 (FEAT_FGWTE3), a feature that allows EL3 to
+   restrict overwriting certain EL3 registers after boot.
+   This lockdown is established by setting individual trap bits for
+   system registers that are not expected to be overwritten after boot.
+   This feature is an optional architectural feature and is available from
+   Armv9.4 onwards. This flag can take values from 0 to 2, aligning with
+   the ``ENABLE_FEAT`` mechanism. The default value is 0.
+
+   .. note::
+      This feature currently traps access to all EL3 registers in
+      ``FGWTE3_EL3``, except for ``MDCR_EL3``, ``MPAM3_EL3``,
+      ``TPIDR_EL3``(when ``CRASH_REPORTING=1``), and
+      ``SCTLR_EL3``(when ``HW_ASSISTED_COHERENCY=0``).
+      If additional traps need to be disabled for specific platforms,
+      please contact the Arm team on `TF-A public mailing list`_.
+
 -  ``ENABLE_FEAT_HCX``: Numeric value to set the bit SCR_EL3.HXEn in EL3 to
    allow access to HCRX_EL2 (extended hypervisor control register) from EL2 as
    well as adding HCRX_EL2 to the EL2 context save/restore operations. Its a
@@ -1567,3 +1584,4 @@
 .. _Firmware Handoff specification: https://github.com/FirmwareHandoff/firmware_handoff/releases/tag/v0.9
 .. _PSA Crypto API specification: https://armmbed.github.io/mbed-crypto/html/
 .. _Platform Initialization specification: https://uefi.org/specs/PI/1.8/index.html
+.. _TF-A public mailing list: https://lists.trustedfirmware.org/mailman3/lists/tf-a.lists.trustedfirmware.org/
diff --git a/drivers/arm/cci/cci.c b/drivers/arm/cci/cci.c
index ae2b9bb..8381c0d 100644
--- a/drivers/arm/cci/cci.c
+++ b/drivers/arm/cci/cci.c
@@ -31,14 +31,14 @@
 static const int *cci_slave_if_map;
 
 #if ENABLE_ASSERTIONS
-static unsigned int max_master_id;
+static size_t max_master_id;
 static int cci_num_slave_ports;
 
 static bool validate_cci_map(const int *map)
 {
 	unsigned int valid_cci_map = 0U;
 	int slave_if_id;
-	unsigned int i;
+	size_t i;
 
 	/* Validate the map */
 	for (i = 0U; i <= max_master_id; i++) {
@@ -109,7 +109,7 @@
 #endif /* ENABLE_ASSERTIONS */
 
 void __init cci_init(uintptr_t base, const int *map,
-				unsigned int num_cci_masters)
+				size_t num_cci_masters)
 {
 	assert(map != NULL);
 	assert(base != 0U);
@@ -130,7 +130,7 @@
 	assert(validate_cci_map(map));
 }
 
-void cci_enable_snoop_dvm_reqs(unsigned int master_id)
+void cci_enable_snoop_dvm_reqs(size_t master_id)
 {
 	int slave_if_id = cci_slave_if_map[master_id];
 
@@ -158,7 +158,7 @@
 	}
 }
 
-void cci_disable_snoop_dvm_reqs(unsigned int master_id)
+void cci_disable_snoop_dvm_reqs(size_t master_id)
 {
 	int slave_if_id = cci_slave_if_map[master_id];
 
diff --git a/drivers/tpm/tpm2_fifo.c b/drivers/tpm/tpm2_fifo.c
index 7c4b9d8..07a0bc0 100644
--- a/drivers/tpm/tpm2_fifo.c
+++ b/drivers/tpm/tpm2_fifo.c
@@ -246,7 +246,7 @@
 
 	err = tpm2_wait_reg_bits(tpm_base_addr + TPM_FIFO_REG_STATUS,
 				TPM_STAT_AVAIL,
-				chip_data->timeout_msec_c,
+				chip_data->timeout_msec_a,
 				status);
 	if (err < 0) {
 		return err;
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 5506cb1..ee18309 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -443,6 +443,13 @@
 #define ID_AA64MMFR3_EL1_TCRX_SHIFT		U(0)
 #define ID_AA64MMFR3_EL1_TCRX_MASK		ULL(0xf)
 
+/* ID_AA64MMFR4_EL1 definitions */
+#define ID_AA64MMFR4_EL1			S3_0_C0_C7_4
+
+#define ID_AA64MMFR4_EL1_FGWTE3_SHIFT		U(16)
+#define ID_AA64MMFR4_EL1_FGWTE3_MASK		ULL(0xf)
+#define FGWTE3_IMPLEMENTED			ULL(0x1)
+
 /* ID_AA64PFR1_EL1 definitions */
 
 #define ID_AA64PFR1_EL1_BT_SHIFT	U(0)
@@ -1622,4 +1629,68 @@
 #define MECIDR_EL2_MECIDWidthm1_MASK	U(0xf)
 #define MECIDR_EL2_MECIDWidthm1_SHIFT	U(0)
 
+/******************************************************************************
+ * FEAT_FGWTE3 - Fine Grained Write Trap
+ ******************************************************************************/
+#define FGWTE3_EL3					S3_6_C1_C1_5
+
+/* FGWTE3_EL3 Defintions */
+#define FGWTE3_EL3_VBAR_EL3_BIT				(U(1) << 21)
+#define FGWTE3_EL3_TTBR0_EL3_BIT			(U(1) << 20)
+#define FGWTE3_EL3_TPIDR_EL3_BIT			(U(1) << 19)
+#define FGWTE3_EL3_TCR_EL3_BIT				(U(1) << 18)
+#define FGWTE3_EL3_SPMROOTCR_EL3_BIT			(U(1) << 17)
+#define FGWTE3_EL3_SCTLR2_EL3_BIT			(U(1) << 16)
+#define FGWTE3_EL3_SCTLR_EL3_BIT			(U(1) << 15)
+#define FGWTE3_EL3_PIR_EL3_BIT				(U(1) << 14)
+#define FGWTE3_EL3_MECID_RL_A_EL3_BIT			(U(1) << 12)
+#define FGWTE3_EL3_MAIR2_EL3_BIT			(U(1) << 10)
+#define FGWTE3_EL3_MAIR_EL3_BIT				(U(1) << 9)
+#define FGWTE3_EL3_GPTBR_EL3_BIT			(U(1) << 8)
+#define FGWTE3_EL3_GPCCR_EL3_BIT			(U(1) << 7)
+#define FGWTE3_EL3_GCSPR_EL3_BIT			(U(1) << 6)
+#define FGWTE3_EL3_GCSCR_EL3_BIT			(U(1) << 5)
+#define FGWTE3_EL3_AMAIR2_EL3_BIT			(U(1) << 4)
+#define FGWTE3_EL3_AMAIR_EL3_BIT			(U(1) << 3)
+#define FGWTE3_EL3_AFSR1_EL3_BIT			(U(1) << 2)
+#define FGWTE3_EL3_AFSR0_EL3_BIT			(U(1) << 1)
+#define FGWTE3_EL3_ACTLR_EL3_BIT			(U(1) << 0)
+
+#define FGWTE3_EL3_EARLY_INIT_VAL			(	\
+		FGWTE3_EL3_VBAR_EL3_BIT 		| 	\
+		FGWTE3_EL3_TTBR0_EL3_BIT 		|	\
+		FGWTE3_EL3_SPMROOTCR_EL3_BIT		|	\
+		FGWTE3_EL3_SCTLR2_EL3_BIT		|	\
+		FGWTE3_EL3_PIR_EL3_BIT			|	\
+		FGWTE3_EL3_MECID_RL_A_EL3_BIT		|	\
+		FGWTE3_EL3_MAIR2_EL3_BIT		|	\
+		FGWTE3_EL3_MAIR_EL3_BIT			|	\
+		FGWTE3_EL3_GPTBR_EL3_BIT		|	\
+		FGWTE3_EL3_GPCCR_EL3_BIT		|	\
+		FGWTE3_EL3_GCSPR_EL3_BIT		|	\
+		FGWTE3_EL3_GCSCR_EL3_BIT		|	\
+		FGWTE3_EL3_AMAIR2_EL3_BIT		|	\
+		FGWTE3_EL3_AMAIR_EL3_BIT		|	\
+		FGWTE3_EL3_AFSR1_EL3_BIT		|	\
+		FGWTE3_EL3_AFSR0_EL3_BIT)
+
+#if HW_ASSISTED_COHERENCY
+#define FGWTE3_EL3_LATE_INIT_SCTLR_EL3_BIT   FGWTE3_EL3_SCTLR_EL3_BIT |
+#else
+#define FGWTE3_EL3_LATE_INIT_SCTLR_EL3_BIT
+#endif
+
+#if !(CRASH_REPORTING)
+#define FGWTE3_EL3_LATE_INIT_TPIDR_EL3_BIT	FGWTE3_EL3_TPIDR_EL3_BIT |
+#else
+#define FGWTE3_EL3_LATE_INIT_TPIDR_EL3_BIT
+#endif
+
+#define FGWTE3_EL3_LATE_INIT_VAL			(	\
+		FGWTE3_EL3_EARLY_INIT_VAL		|	\
+		FGWTE3_EL3_LATE_INIT_SCTLR_EL3_BIT		\
+		FGWTE3_EL3_LATE_INIT_TPIDR_EL3_BIT		\
+		FGWTE3_EL3_TCR_EL3_BIT			|	\
+		FGWTE3_EL3_ACTLR_EL3_BIT)
+
 #endif /* ARCH_H */
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 77355cd..ddb5e23 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -148,6 +148,8 @@
  * +----------------------------+
  * |	FEAT_PAUTH_LR		|
  * +----------------------------+
+ * |    FEAT_FGWTE3             |
+ * +----------------------------+
  */
 
 __attribute__((always_inline))
@@ -271,6 +273,11 @@
 CREATE_FEATURE_FUNCS(feat_fgt2, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
 		     ID_AA64MMFR0_EL1_FGT_MASK, FGT2_IMPLEMENTED, ENABLE_FEAT_FGT2)
 
+/* FEAT_FGWTE3: Fine-grained write traps EL3 */
+CREATE_FEATURE_FUNCS(feat_fgwte3, id_aa64mmfr4_el1, ID_AA64MMFR4_EL1_FGWTE3_SHIFT,
+		     ID_AA64MMFR4_EL1_FGWTE3_MASK, FGWTE3_IMPLEMENTED,
+		     ENABLE_FEAT_FGWTE3)
+
 /* FEAT_ECV: Enhanced Counter Virtualization */
 CREATE_FEATURE_FUNCS(feat_ecv, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV_SHIFT,
 		     ID_AA64MMFR0_EL1_ECV_MASK, 1U, ENABLE_FEAT_ECV)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index a59c531..b0ad93b 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -770,6 +770,11 @@
 /* FEAT_MEC Registers */
 DEFINE_RENAME_SYSREG_READ_FUNC(mecidr_el2, MECIDR_EL2)
 
+DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr4_el1, ID_AA64MMFR4_EL1)
+
+/* FEAT_FGWTE3 Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(fgwte3_el3, FGWTE3_EL3)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)
 
diff --git a/include/bl31/interrupt_mgmt.h b/include/bl31/interrupt_mgmt.h
index e228495..0ca760e 100644
--- a/include/bl31/interrupt_mgmt.h
+++ b/include/bl31/interrupt_mgmt.h
@@ -83,6 +83,7 @@
 #ifndef __ASSEMBLER__
 
 #include <errno.h>
+#include <stddef.h>
 #include <stdint.h>
 
 /*******************************************************************************
@@ -143,7 +144,7 @@
 /*******************************************************************************
  * Function & variable prototypes
  ******************************************************************************/
-u_register_t get_scr_el3_from_routing_model(uint32_t security_state);
+u_register_t get_scr_el3_from_routing_model(size_t security_state);
 int32_t set_routing_model(uint32_t type, uint32_t flags);
 int32_t register_interrupt_type_handler(uint32_t type,
 					interrupt_type_handler_t handler,
diff --git a/include/drivers/arm/cci.h b/include/drivers/arm/cci.h
index 5aea95a..d48b3d6 100644
--- a/include/drivers/arm/cci.h
+++ b/include/drivers/arm/cci.h
@@ -102,6 +102,7 @@
 
 #ifndef __ASSEMBLER__
 
+#include <stddef.h>
 #include <stdint.h>
 
 /* Function declarations */
@@ -116,10 +117,10 @@
  * SLAVE_IF_UNUSED should be used in the map to represent no AMBA 4 master exists
  * for that interface.
  */
-void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters);
+void cci_init(uintptr_t base, const int *map, size_t num_cci_masters);
 
-void cci_enable_snoop_dvm_reqs(unsigned int master_id);
-void cci_disable_snoop_dvm_reqs(unsigned int master_id);
+void cci_enable_snoop_dvm_reqs(size_t master_id);
+void cci_disable_snoop_dvm_reqs(size_t master_id);
 
 #endif /* __ASSEMBLER__ */
 #endif /* CCI_H */
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index f71f33c..80f68f7 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -23,15 +23,15 @@
  ******************************************************************************/
 void cm_init(void);
 void *cm_get_context_by_index(unsigned int cpu_idx,
-			      unsigned int security_state);
+			      size_t security_state);
 void cm_set_context_by_index(unsigned int cpu_idx,
 			     void *context,
 			     unsigned int security_state);
-void *cm_get_context(uint32_t security_state);
+void *cm_get_context(size_t security_state);
 void cm_set_context(void *context, uint32_t security_state);
 void cm_init_my_context(const struct entry_point_info *ep);
 void cm_setup_context(cpu_context_t *ctx, const struct entry_point_info *ep);
-void cm_prepare_el3_exit(uint32_t security_state);
+void cm_prepare_el3_exit(size_t security_state);
 void cm_prepare_el3_exit_ns(void);
 
 #ifdef __aarch64__
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 20a6c39..ba2f8d5 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -217,7 +217,7 @@
  * an access is not out-of-bounds. The function assumes security_state is
  * valid.
  */
-static inline context_pas_t get_cpu_context_index(uint32_t security_state)
+static inline context_pas_t get_cpu_context_index(size_t security_state)
 {
 	if (security_state == SECURE) {
 		return CPU_CONTEXT_SECURE;
diff --git a/include/services/spm_mm_svc.h b/include/services/spm_mm_svc.h
index b4ed1ab..6086c0f 100644
--- a/include/services/spm_mm_svc.h
+++ b/include/services/spm_mm_svc.h
@@ -67,6 +67,13 @@
 #define MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64	U(0xC4000065)
 
 /*
+ * Vendor-specific EL3 range SMC IDs defined for TPM start method for pre-FFA
+ * configuration. These SMCs are converted to MM_COMMUNICATE calls.
+ */
+#define TPM_START_SMC_32			U(0x87000040)
+#define TPM_START_SMC_64			U(0xC7000040)
+
+/*
  * Macros used by MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.
  */
 
@@ -120,6 +127,16 @@
 			uint64_t x2,
 			uint64_t x3);
 
+/* Helper to handle TPM Start SVC call */
+uint64_t spm_mm_tpm_start_handler(uint32_t smc_fid,
+				  uint64_t x1,
+				  uint64_t x2,
+				  uint64_t x3,
+				  uint64_t x4,
+				  void *cookie,
+				  void *handle,
+				  uint64_t flags);
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* SPM_MM_SVC_H */
diff --git a/include/services/ven_el3_svc.h b/include/services/ven_el3_svc.h
index 0336059..ffa7d0e 100644
--- a/include/services/ven_el3_svc.h
+++ b/include/services/ven_el3_svc.h
@@ -21,7 +21,7 @@
 #define VEN_EL3_SVC_VERSION	0x8700ff03
 
 #define VEN_EL3_SVC_VERSION_MAJOR	1
-#define VEN_EL3_SVC_VERSION_MINOR	1
+#define VEN_EL3_SVC_VERSION_MINOR	2
 
 /* DEBUGFS_SMC_32		0x87000010U */
 /* DEBUGFS_SMC_64		0xC7000010U */
@@ -32,4 +32,7 @@
 /* ACS_SMC_HANDLER_32           0x87000030U */
 /* ACS_SMC_HANDLER_64           0xC7000030U */
 
+/* TPM_START_SMC_32		0x87000040U */
+/* TPM_START_SMC_64		0xC7000040U */
+
 #endif /* VEN_EL3_SVC_H */
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 00d9c01..b150cb9 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -175,7 +175,7 @@
  * HYP mode then HYP mode is disabled by configuring all necessary HYP mode
  * registers.
  ******************************************************************************/
-void cm_prepare_el3_exit(uint32_t security_state)
+void cm_prepare_el3_exit(size_t security_state)
 {
 	uint32_t hsctlr, scr;
 	cpu_context_t *ctx = cm_get_context(security_state);
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 50e9565..e188f74 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -619,7 +619,7 @@
  ******************************************************************************/
 void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep)
 {
-	unsigned int security_state;
+	size_t security_state;
 
 	assert(ctx != NULL);
 
@@ -671,6 +671,9 @@
 		sme_init_el3();
 	}
 
+	if (is_feat_fgwte3_supported()) {
+		write_fgwte3_el3(FGWTE3_EL3_EARLY_INIT_VAL);
+	}
 	pmuv3_init_el3();
 }
 
@@ -1097,7 +1100,7 @@
  * EL2 then EL2 is disabled by configuring all necessary EL2 registers.
  * For all entries, the EL1 registers are initialized from the cpu_context
  ******************************************************************************/
-void cm_prepare_el3_exit(uint32_t security_state)
+void cm_prepare_el3_exit(size_t security_state)
 {
 	u_register_t sctlr_el2, scr_el3;
 	cpu_context_t *ctx = cm_get_context(security_state);
@@ -1161,6 +1164,14 @@
 				init_nonsecure_el2_unused(ctx);
 			}
 		}
+
+		if (is_feat_fgwte3_supported()) {
+			/*
+			 * TCR_EL3 and ACTLR_EL3 could be overwritten
+			 * by platforms and hence is locked a bit late.
+			 */
+			write_fgwte3_el3(FGWTE3_EL3_LATE_INIT_VAL);
+		}
 	}
 #if (!CTX_INCLUDE_EL2_REGS)
 	/* Restore EL1 system registers, only when CTX_INCLUDE_EL2_REGS=0 */
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 00b0003..308c6f9 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -331,8 +331,9 @@
 	 * psci_spd_migrate_info() returns.
 	 */
 	rc = psci_spd_migrate_info(&resident_cpu_mpidr);
-	if ((rc != PSCI_TOS_NOT_UP_MIG_CAP) && (rc != PSCI_TOS_UP_MIG_CAP))
+	if ((rc != PSCI_TOS_NOT_UP_MIG_CAP) && (rc != PSCI_TOS_UP_MIG_CAP)) {
 		return (u_register_t)(register_t) PSCI_E_INVALID_PARAMS;
+	}
 
 	return resident_cpu_mpidr;
 }
@@ -343,12 +344,14 @@
 	int rc;
 
 	/* Validate target_cpu */
-	if (!is_valid_mpidr(target_cpu))
+	if (!is_valid_mpidr(target_cpu)) {
 		return PSCI_E_INVALID_PARAMS;
+	}
 
 	/* Validate power_level against PLAT_MAX_PWR_LVL */
-	if (power_level > PLAT_MAX_PWR_LVL)
+	if (power_level > PLAT_MAX_PWR_LVL) {
 		return PSCI_E_INVALID_PARAMS;
+	}
 
 	/*
 	 * Dispatch this call to platform to query power controller, and pass on
diff --git a/lib/psci/psci_mem_protect.c b/lib/psci/psci_mem_protect.c
index 385dcd2..68ad705 100644
--- a/lib/psci/psci_mem_protect.c
+++ b/lib/psci/psci_mem_protect.c
@@ -18,10 +18,12 @@
 	assert(psci_plat_pm_ops->read_mem_protect != NULL);
 	assert(psci_plat_pm_ops->write_mem_protect != NULL);
 
-	if (psci_plat_pm_ops->read_mem_protect(&val) < 0)
+	if (psci_plat_pm_ops->read_mem_protect(&val) < 0) {
 		return (u_register_t) PSCI_E_NOT_SUPPORTED;
-	if (psci_plat_pm_ops->write_mem_protect(enable) < 0)
+	}
+	if (psci_plat_pm_ops->write_mem_protect(enable) < 0) {
 		return (u_register_t) PSCI_E_NOT_SUPPORTED;
+	}
 
 	return (val != 0) ? 1U : 0U;
 }
@@ -32,8 +34,9 @@
 
 	assert(psci_plat_pm_ops->mem_protect_chk != NULL);
 
-	if ((length == 0U) || check_uptr_overflow(base, length - 1U))
+	if ((length == 0U) || check_uptr_overflow(base, length - 1U)) {
 		return (u_register_t) PSCI_E_DENIED;
+	}
 
 	ret = psci_plat_pm_ops->mem_protect_chk(base, length);
 	return (ret < 0) ?
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index a6fd6be..8bcf866 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -437,3 +437,6 @@
 
 # Flag to enable access to Guarded Control Stack (FEAT_GCS).
 ENABLE_FEAT_GCS				?=	0
+
+# Flag to enable Fine Grained Write Traps (FEAT_FGWTE3) for EL3.
+ENABLE_FEAT_FGWTE3			?=	0
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 7f1dfc6..8e16829 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -61,6 +61,7 @@
       ENABLE_FEAT_D128		:= 2
       ENABLE_FEAT_FPMR		:= 2
       ENABLE_FEAT_MOPS		:= 2
+      ENABLE_FEAT_FGWTE3	:= 2
 endif
 
 ENABLE_SYS_REG_TRACE_FOR_NS	:= 2
diff --git a/plat/qti/qcs615/inc/qti_secure_io_cfg.h b/plat/qti/qcs615/inc/qti_secure_io_cfg.h
index a78583e..c386e2b 100644
--- a/plat/qti/qcs615/inc/qti_secure_io_cfg.h
+++ b/plat/qti/qcs615/inc/qti_secure_io_cfg.h
@@ -12,6 +12,7 @@
  * List of peripheral/IO memory areas that are protected from
  * non-secure world but not required to be secure.
  */
+#define EUD_MODE_MANAGER2_EN                 0x088E4000
 #define APPS_SMMU_TBU_PWR_STATUS             0x15002204
 #define APPS_SMMU_CUSTOM_CFG                 0x15002300
 #define APPS_SMMU_STATS_SYNC_INV_TBU_ACK     0x150025DC
@@ -19,6 +20,7 @@
 #define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x15002648
 
 static const uintptr_t qti_secure_io_allowed_regs[] = {
+	EUD_MODE_MANAGER2_EN,
 	APPS_SMMU_TBU_PWR_STATUS,
 	APPS_SMMU_CUSTOM_CFG,
 	APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
diff --git a/plat/qti/sc7180/inc/qti_secure_io_cfg.h b/plat/qti/sc7180/inc/qti_secure_io_cfg.h
index 3de636d..5f07cb5 100644
--- a/plat/qti/sc7180/inc/qti_secure_io_cfg.h
+++ b/plat/qti/sc7180/inc/qti_secure_io_cfg.h
@@ -13,6 +13,7 @@
  * non-secure world but not required to be secure.
  */
 
+#define EUD_MODE_MANAGER2_EN			0x088E2000
 #define APPS_SMMU_TBU_PWR_STATUS		0x15002204
 #define APPS_SMMU_CUSTOM_CFG			0x15002300
 #define APPS_SMMU_STATS_SYNC_INV_TBU_ACK	0x150025DC
@@ -20,6 +21,7 @@
 #define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR	0x15002670
 
 static const uintptr_t qti_secure_io_allowed_regs[] = {
+	EUD_MODE_MANAGER2_EN,
 	APPS_SMMU_TBU_PWR_STATUS,
 	APPS_SMMU_CUSTOM_CFG,
 	APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
diff --git a/plat/qti/sc7280/inc/qti_secure_io_cfg.h b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
index 058c5b5..24a0a34 100644
--- a/plat/qti/sc7280/inc/qti_secure_io_cfg.h
+++ b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
@@ -13,6 +13,7 @@
  * non-secure world but not required to be secure.
  */
 
+#define EUD_MODE_MANAGER2_EN			0x088E2000
 #define APPS_SMMU_TBU_PWR_STATUS		0x15002204
 #define APPS_SMMU_CUSTOM_CFG			0x15002300
 #define APPS_SMMU_STATS_SYNC_INV_TBU_ACK	0x150025DC
@@ -20,6 +21,7 @@
 #define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR	0x15002670
 
 static const uintptr_t qti_secure_io_allowed_regs[] = {
+	EUD_MODE_MANAGER2_EN,
 	APPS_SMMU_TBU_PWR_STATUS,
 	APPS_SMMU_CUSTOM_CFG,
 	APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
diff --git a/services/el3/ven_el3_svc.c b/services/el3/ven_el3_svc.c
index 431bfbf..5117b90 100644
--- a/services/el3/ven_el3_svc.c
+++ b/services/el3/ven_el3_svc.c
@@ -13,6 +13,7 @@
 #if PLAT_ARM_ACS_SMC_HANDLER
 #include <plat/arm/common/plat_acs_smc_handler.h>
 #endif /* PLAT_ARM_ACS_SMC_HANDLER */
+#include <services/spm_mm_svc.h>
 #include <services/ven_el3_svc.h>
 #include <tools_share/uuid.h>
 
@@ -91,6 +92,16 @@
 	case VEN_EL3_SVC_VERSION:
 		SMC_RET2(handle, VEN_EL3_SVC_VERSION_MAJOR, VEN_EL3_SVC_VERSION_MINOR);
 		break;
+#if SPM_MM
+	/*
+	 * Handle TPM start SMC as mentioned in TCG ACPI specification.
+	 */
+	case TPM_START_SMC_32:
+	case TPM_START_SMC_64:
+		return spm_mm_tpm_start_handler(smc_fid, x1, x2, x3, x4, cookie,
+						handle, flags);
+		break;
+#endif
 	default:
 		WARN("Unimplemented vendor-specific EL3 Service call: 0x%x\n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
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 7fe826d..60b34d2 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_main.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_main.c
@@ -21,6 +21,7 @@
 #include <plat/common/platform.h>
 #include <services/spm_mm_partition.h>
 #include <services/spm_mm_svc.h>
+#include <services/ven_el3_svc.h>
 #include <smccc_helpers.h>
 
 #include "spm_common.h"
@@ -31,6 +32,14 @@
  ******************************************************************************/
 static sp_context_t sp_ctx;
 
+/********************************************************************************
+ * TPM service UUID: 17b862a4-1806-4faf-86b3-089a58353861 as mentioned in
+ * https://developer.arm.com/documentation/den0138/latest/
+ *******************************************************************************/
+DEFINE_SVC_UUID2(tpm_service_uuid,
+		 0x17b862a4, 0x1806, 0x4faf, 0x86, 0xb3,
+		 0x08, 0x9a, 0x58, 0x35, 0x38, 0x61);
+
 /*******************************************************************************
  * Set state of a Secure Partition context.
  ******************************************************************************/
@@ -251,6 +260,46 @@
 }
 
 /*******************************************************************************
+ * SPM_MM TPM start handler as mentioned in section 3.3.1 of TCG ACPI
+ * specification version 1.4
+ ******************************************************************************/
+uint64_t spm_mm_tpm_start_handler(uint32_t smc_fid,
+				  uint64_t x1,
+				  uint64_t x2,
+				  uint64_t x3,
+				  uint64_t x4,
+				  void *cookie,
+				  void *handle,
+				  uint64_t flags)
+{
+	mm_communicate_header_t *mm_comm_header = (void *)PLAT_SPM_BUF_BASE;
+	uint32_t spm_mm_smc_fid;
+
+	if (!is_caller_non_secure(flags)) {
+		ERROR("spm_mm TPM START must be requested from normal world only.\n");
+		SMC_RET1(handle, SMC_UNK);
+	}
+
+	switch (smc_fid) {
+	case TPM_START_SMC_32:
+		spm_mm_smc_fid = MM_COMMUNICATE_AARCH32;
+		break;
+	case TPM_START_SMC_64:
+		spm_mm_smc_fid = MM_COMMUNICATE_AARCH64;
+		break;
+	default:
+		ERROR("Unexpected SMC FID\n");
+		SMC_RET1(handle, SMC_UNK);
+		break;
+	}
+
+	memset(mm_comm_header, 0U, sizeof(mm_communicate_header_t));
+	memcpy(&mm_comm_header->header_guid, &tpm_service_uuid, sizeof(struct efi_guid));
+
+	return mm_communicate(spm_mm_smc_fid, x1,  (uint64_t)mm_comm_header, x3, handle);
+}
+
+/*******************************************************************************
  * Secure Partition Manager SMC handler.
  ******************************************************************************/
 uint64_t spm_mm_smc_handler(uint32_t smc_fid,