Merge "fix(cm): don't access a field that doesn't exist" into integration
diff --git a/Makefile b/Makefile
index 4f6afaf..6d5a0c3 100644
--- a/Makefile
+++ b/Makefile
@@ -764,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
 ################################################################################
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 5944b91..a9f89fc 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -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>
@@ -145,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/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/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 2a42269..e5f7b30 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -1288,11 +1288,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/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_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..df3460f 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,8 @@
         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
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/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_log.h b/include/drivers/measured_boot/event_log/event_log.h
index 18abadf..50e4721 100644
--- a/include/drivers/measured_boot/event_log/event_log.h
+++ b/include/drivers/measured_boot/event_log/event_log.h
@@ -7,12 +7,11 @@
 #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 "tcg.h"
 
 /*
  * Set Event Log debug level to one of:
@@ -33,7 +32,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 +64,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/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index ae2e96f..4a856a7 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>
@@ -358,6 +359,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);
@@ -367,6 +371,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/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 1bbea7a..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>
@@ -183,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_suspend.c b/lib/psci/psci_suspend.c
index a7b53cb..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>
@@ -198,13 +199,17 @@
 		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
@@ -280,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.
@@ -320,6 +330,11 @@
 	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);
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/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 965698b..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
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 27a2b72..98242e6 100644
--- a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
@@ -29,6 +29,7 @@
 ENABLE_FEAT_FGT				:=	1
 ENABLE_FEAT_MTE2			:=	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..7e2d9cc 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
  */
@@ -25,8 +25,20 @@
 
 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 = PLAT_ARM_EVENT_LOG_MAX_SIZE;
+	int rc;
+
+	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)
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_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..9a51eb7 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
  */
@@ -20,5 +20,7 @@
 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/platform.mk b/plat/arm/board/fvp/platform.mk
index 280aa39..beb6d5d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -130,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")
@@ -174,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
 
@@ -343,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/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/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/platform.mk b/plat/arm/board/tc/platform.mk
index cf42243..bbccce6 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
@@ -115,13 +116,6 @@
 	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
-
 TC_BASE	=	plat/arm/board/tc
 
 PLAT_INCLUDES		+=	-I${TC_BASE}/include/ \
@@ -195,7 +189,6 @@
 
 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/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index fa35bb2..82f96ba 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -257,7 +257,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,
@@ -394,10 +396,6 @@
 	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();
-
 #if RESET_TO_BL31
 	/*
 	 * Do initial security configuration to allow DRAM/device access
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/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index cc4ae59..6b15b73 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -207,8 +207,11 @@
 	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,
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index df3488b..4f45579 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
  */
@@ -14,6 +14,7 @@
 #include <drivers/arm/pl011.h>
 #include <drivers/console.h>
 #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
@@ -57,7 +58,13 @@
  ******************************************************************************/
 void tsp_platform_setup(void)
 {
-	plat_arm_gic_driver_init();
+	/*
+	 * 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
 }
 
 /*******************************************************************************
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/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/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/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/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/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__);