Merge pull request #1151 from JoelHutton/jh/MISRA-Mandatory

Change sizeof to use type of struct not function
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 0fe82d9..018deb3 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -34,6 +34,9 @@
 	auth_mod_init();
 #endif /* TRUSTED_BOARD_BOOT */
 
+	/* initialize boot source */
+	bl2_plat_preload_setup();
+
 	/* Load the subsequent bootloader images. */
 	next_bl_ep_info = bl2_load_images();
 
diff --git a/common/bl_common.c b/common/bl_common.c
index cad4de9..e4473ed 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -354,7 +354,13 @@
  ******************************************************************************/
 int load_auth_image(unsigned int image_id, image_info_t *image_data)
 {
-	return load_auth_image_internal(image_id, image_data, 0);
+	int err;
+
+	do {
+		err = load_auth_image_internal(image_id, image_data, 0);
+	} while (err != 0 && plat_try_next_boot_source());
+
+	return err;
 }
 
 #else /* LOAD_IMAGE_V2 */
@@ -553,8 +559,14 @@
 		    image_info_t *image_data,
 		    entry_point_info_t *entry_point_info)
 {
-	return load_auth_image_internal(mem_layout, image_id, image_base,
-					image_data, entry_point_info, 0);
+	int err;
+
+	do {
+		err = load_auth_image_internal(mem_layout, image_id, image_base,
+					       image_data, entry_point_info, 0);
+	} while (err != 0 && plat_try_next_boot_source());
+
+	return err;
 }
 
 #endif /* LOAD_IMAGE_V2 */
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 853e390..7cc1970 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -2309,6 +2309,12 @@
 Note that publishing an event on a PE blocks until all the subscribed handlers
 finish executing on the PE.
 
+ARM Trusted Firmware generic code publishes and subscribes to some events
+within. Platform ports are discouraged from subscribing to them. These events
+may be withdrawn, renamed, or have their semantics altered in the future.
+Platforms may however register, publish, and subscribe to platform-specific
+events.
+
 Publish and Subscribe Example
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -2339,22 +2345,6 @@
 
    SUBSCRIBE_TO_EVENT(foo, foo_handler);
 
-Available Events
-~~~~~~~~~~~~~~~~
-
-ARM Trusted Firmware core makes some events available by default. They're listed
-below, along with information as to when they're published, and the arguments
-passed to subscribed handlers.
-
-Other EL3 components that are conditionally compiled in may make their own
-events available, but aren't documented here.
-
--  ``psci_cpu_on_finish``
-
-   - When: Published on a PE after it's finished its power-up sequence.
-
-   - Argument: ``NULL``.
-
 Performance Measurement Framework
 ---------------------------------
 
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 6352bb9..f0a8aaf 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1596,6 +1596,34 @@
 This function isn't needed if either ``PRELOADED_BL33_BASE`` or ``EL3_PAYLOAD_BASE``
 build options are used.
 
+Function : bl2\_plat\_preload\_setup [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+    Argument : void
+    Return   : void
+
+This optional function performs any BL2 platform initialization
+required before image loading, that is not done later in
+bl2\_platform\_setup(). Specifically, if support for multiple
+boot sources is required, it initializes the boot sequence used by
+plat\_try\_next\_boot\_source().
+
+Function : plat\_try\_next\_boot\_source() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+    Argument : void
+    Return   : int
+
+This optional function passes to the next boot source in the redundancy
+sequence.
+
+This function moves the current boot redundancy source to the next
+element in the boot sequence. If there are no more boot sources then it
+must return 0, otherwise it must return 1. The default implementation
+of this always returns 0.
+
 FWU Boot Loader Stage 2 (BL2U)
 ------------------------------
 
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 28483f2..4df7590 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -664,9 +664,10 @@
 
 -  ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options:
 
-   -  ``tsram`` : Trusted SRAM (default option)
+   -  ``tsram`` : Trusted SRAM (default option when TBB is not enabled)
    -  ``tdram`` : Trusted DRAM (if available)
-   -  ``dram`` : Secure region in DRAM (configured by the TrustZone controller)
+   -  ``dram``  : Secure region in DRAM (default option when TBB is enabled,
+                  configured by the TrustZone controller)
 
 -  ``ARM_XLAT_TABLES_LIB_V1``: boolean option to compile the Trusted Firmware
    with version 1 of the translation tables library instead of version 2. It is
@@ -1205,6 +1206,56 @@
     ./build/fvp/release/bl1.bin
     ./build/fvp/release/fip.bin
 
+
+Booting Firmware Update images
+-------------------------------------
+
+When Firmware Update (FWU) is enabled there are at least 2 new images
+that have to be loaded, the Non-Secure FWU ROM (NS-BL1U), and the
+FWU FIP.
+
+Juno
+~~~~
+
+The new images must be programmed in flash memory by adding
+an entry in the ``SITE1/HBI0262x/images.txt`` configuration file
+on the Juno SD card (where ``x`` depends on the revision of the Juno board).
+Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory
+programming" for more information. User should ensure these do not
+overlap with any other entries in the file.
+
+::
+
+	NOR10UPDATE: AUTO                       ;Image Update:NONE/AUTO/FORCE
+	NOR10ADDRESS: 0x00400000                ;Image Flash Address [ns_bl2u_base_address]
+	NOR10FILE: \SOFTWARE\fwu_fip.bin        ;Image File Name
+	NOR10LOAD: 00000000                     ;Image Load Address
+	NOR10ENTRY: 00000000                    ;Image Entry Point
+
+	NOR11UPDATE: AUTO                       ;Image Update:NONE/AUTO/FORCE
+	NOR11ADDRESS: 0x03EB8000                ;Image Flash Address [ns_bl1u_base_address]
+	NOR11FILE: \SOFTWARE\ns_bl1u.bin        ;Image File Name
+	NOR11LOAD: 00000000                     ;Image Load Address
+
+The address ns_bl1u_base_address is the value of NS_BL1U_BASE - 0x8000000.
+In the same way, the address ns_bl2u_base_address is the value of
+NS_BL2U_BASE - 0x8000000.
+
+FVP
+~~~
+
+The additional fip images must be loaded with:
+
+::
+
+    --data cluster0.cpu0="<path_to>/ns_bl1u.bin"@0x0beb8000	[ns_bl1u_base_address]
+    --data cluster0.cpu0="<path_to>/fwu_fip.bin"@0x08400000	[ns_bl2u_base_address]
+
+The address ns_bl1u_base_address is the value of NS_BL1U_BASE.
+In the same way, the address ns_bl2u_base_address is the value of
+NS_BL2U_BASE.
+
+
 EL3 payloads alternative boot flow
 ----------------------------------
 
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index ca2d9fa..96587ac 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config.h
@@ -76,12 +76,13 @@
 #define MBEDTLS_MPI_WINDOW_SIZE              2
 #define MBEDTLS_MPI_MAX_SIZE               256
 
-/* System headers required to build mbed TLS with the current configuration */
-#include <stdlib.h>
-
 /* Memory buffer allocator options */
 #define MBEDTLS_MEMORY_ALIGN_MULTIPLE        8
 
+#ifndef __ASSEMBLY__
+/* System headers required to build mbed TLS with the current configuration */
+#include <stdlib.h>
 #include "mbedtls/check_config.h"
+#endif
 
 #endif /* __MBEDTLS_CONFIG_H__ */
diff --git a/include/lib/el3_runtime/pubsub_events.h b/include/lib/el3_runtime/pubsub_events.h
index 62550f8..9cfedb4 100644
--- a/include/lib/el3_runtime/pubsub_events.h
+++ b/include/lib/el3_runtime/pubsub_events.h
@@ -16,3 +16,21 @@
  * initialization.
  */
 REGISTER_PUBSUB_EVENT(psci_cpu_on_finish);
+
+#ifdef AARCH64
+/*
+ * These events are published by the AArch64 context management framework
+ * after the secure context is restored/saved via
+ * cm_el1_sysregs_context_{restore,save}() API.
+ */
+REGISTER_PUBSUB_EVENT(cm_entering_secure_world);
+REGISTER_PUBSUB_EVENT(cm_exited_secure_world);
+
+/*
+ * These events are published by the AArch64 context management framework
+ * after the normal context is restored/saved via
+ * cm_el1_sysregs_context_{restore,save}() API.
+ */
+REGISTER_PUBSUB_EVENT(cm_entering_normal_world);
+REGISTER_PUBSUB_EVENT(cm_exited_normal_world);
+#endif /* AARCH64 */
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 49ab601..7a4594c 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -53,7 +53,7 @@
  * enable dynamic memory mapping.
  */
 #if defined(IMAGE_BL31) || defined(IMAGE_BL32)
-# define PLAT_ARM_MMAP_ENTRIES		6
+# define PLAT_ARM_MMAP_ENTRIES		7
 # define MAX_XLAT_TABLES		5
 #else
 # define PLAT_ARM_MMAP_ENTRIES		11
@@ -71,7 +71,7 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x1D000
+# define PLAT_ARM_MAX_BL2_SIZE		0x1E000
 #else
 # define PLAT_ARM_MAX_BL2_SIZE		0xF000
 #endif
diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_common.ld.S
new file mode 100644
index 0000000..478b08c
--- /dev/null
+++ b/include/plat/arm/common/arm_common.ld.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __ARM_COMMON_LD_S__
+#define __ARM_COMMON_LD_S__
+
+MEMORY {
+    EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE
+}
+
+SECTIONS
+{
+	. = ARM_EL3_TZC_DRAM1_BASE;
+	ASSERT(. == ALIGN(4096),
+	"ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.")
+	el3_tzc_dram (NOLOAD) : ALIGN(4096) {
+	__EL3_SEC_DRAM_START__ = .;
+	*(arm_el3_tzc_dram)
+	__EL3_SEC_DRAM_UNALIGNED_END__ = .;
+
+	. = NEXT(4096);
+	__EL3_SEC_DRAM_END__ = .;
+	} >EL3_SEC_DRAM
+}
+
+#endif /* __ARM_COMMON_LD_S__ */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index c84fabd..6cab91f 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -77,11 +77,23 @@
 #define ARM_SCP_TZC_DRAM1_END		(ARM_SCP_TZC_DRAM1_BASE +	\
 					 ARM_SCP_TZC_DRAM1_SIZE - 1)
 
+/*
+ * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime
+ * firmware. This region is meant to be NOLOAD and will not be zero
+ * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be
+ * placed here.
+ */
+#define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
+#define ARM_EL3_TZC_DRAM1_SIZE		ULL(0x00200000) /* 2 MB */
+#define ARM_EL3_TZC_DRAM1_END		(ARM_EL3_TZC_DRAM1_BASE +	\
+					ARM_EL3_TZC_DRAM1_SIZE - 1)
+
 #define ARM_AP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
 					 ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE)
 #define ARM_AP_TZC_DRAM1_SIZE		(ARM_TZC_DRAM1_SIZE -		\
-					 ARM_SCP_TZC_DRAM1_SIZE)
+					 (ARM_SCP_TZC_DRAM1_SIZE +	\
+					 ARM_EL3_TZC_DRAM1_SIZE))
 #define ARM_AP_TZC_DRAM1_END		(ARM_AP_TZC_DRAM1_BASE +	\
 					 ARM_AP_TZC_DRAM1_SIZE - 1)
 
@@ -224,6 +236,11 @@
 						MT_MEMORY | MT_RW | MT_SECURE)
 #endif
 
+#define ARM_MAP_EL3_TZC_DRAM		MAP_REGION_FLAT(			\
+						ARM_EL3_TZC_DRAM1_BASE,	\
+						ARM_EL3_TZC_DRAM1_SIZE,	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
 /*
  * The number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 4e589c0..33d951c 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -120,6 +120,7 @@
 int arm_validate_power_state(unsigned int power_state,
 			    psci_power_state_t *req_state);
 int arm_validate_ns_entrypoint(uintptr_t entrypoint);
+void arm_system_pwr_domain_save(void);
 void arm_system_pwr_domain_resume(void);
 void arm_program_trusted_mailbox(uintptr_t address);
 int arm_psci_read_mem_protect(int *val);
@@ -183,6 +184,8 @@
 void plat_arm_gic_redistif_on(void);
 void plat_arm_gic_redistif_off(void);
 void plat_arm_gic_pcpu_init(void);
+void plat_arm_gic_save(void);
+void plat_arm_gic_resume(void);
 void plat_arm_security_setup(void);
 void plat_arm_pwrc_setup(void);
 void plat_arm_interconnect_init(void);
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index f03a399..e2bfa50 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -100,6 +100,8 @@
 void plat_error_handler(int err) __dead2;
 void plat_panic_handler(void) __dead2;
 const char *plat_log_get_prefix(unsigned int log_level);
+void bl2_plat_preload_setup(void);
+int plat_try_next_boot_source(void);
 
 /*******************************************************************************
  * Mandatory BL1 functions
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 21e86de..c8232df 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -13,6 +13,7 @@
 #include <interrupt_mgmt.h>
 #include <platform.h>
 #include <platform_def.h>
+#include <pubsub_events.h>
 #include <smcc_helpers.h>
 #include <string.h>
 #include <utils.h>
@@ -421,9 +422,8 @@
 		}
 	}
 
-	el1_sysregs_context_restore(get_sysregs_ctx(ctx));
-
-	cm_set_next_context(ctx);
+	cm_el1_sysregs_context_restore(security_state);
+	cm_set_next_eret_context(security_state);
 }
 
 /*******************************************************************************
@@ -440,6 +440,13 @@
 
 	el1_sysregs_context_save(get_sysregs_ctx(ctx));
 	el1_sysregs_context_save_post_ops();
+
+#if IMAGE_BL31
+	if (security_state == SECURE)
+		PUBLISH_EVENT(cm_exited_secure_world);
+	else
+		PUBLISH_EVENT(cm_exited_normal_world);
+#endif
 }
 
 void cm_el1_sysregs_context_restore(uint32_t security_state)
@@ -450,6 +457,13 @@
 	assert(ctx);
 
 	el1_sysregs_context_restore(get_sysregs_ctx(ctx));
+
+#if IMAGE_BL31
+	if (security_state == SECURE)
+		PUBLISH_EVENT(cm_entering_secure_world);
+	else
+		PUBLISH_EVENT(cm_entering_normal_world);
+#endif
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 7015ac0..57cc3d5 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -109,6 +109,7 @@
 #ifdef IMAGE_BL31
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
+	ARM_MAP_EL3_TZC_DRAM,
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 	MAP_DEVICE1,
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index dad3a79..faeb1b7 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -9,6 +9,7 @@
 #include <assert.h>
 #include <debug.h>
 #include <errno.h>
+#include <gicv3.h>
 #include <mmio.h>
 #include <plat_arm.h>
 #include <platform.h>
@@ -36,6 +37,9 @@
 	/* State-id - 0x22 */
 	arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
 			ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+	/* State-id - 0x222 */
+	arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
+		ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
 	0,
 };
 #endif
@@ -63,6 +67,18 @@
 	fvp_pwrc_write_pcoffr(mpidr);
 }
 
+/*
+ * Empty implementation of these hooks avoid setting the GICR_WAKER.Sleep bit
+ * on ARM GICv3 implementations on FVP. This is required, because FVP does not
+ * support SYSTEM_SUSPEND and it is `faked` in firmware. Hence, for wake up
+ * from `fake` system suspend the GIC must not be powered off.
+ */
+void arm_gicv3_distif_pre_save(unsigned int proc_num)
+{}
+
+void arm_gicv3_distif_post_restore(unsigned int proc_num)
+{}
+
 static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_state)
 {
 	unsigned long mpidr;
@@ -90,6 +106,10 @@
 		/* Enable coherency if this cluster was off */
 		fvp_interconnect_enable();
 	}
+	/* Perform the common system specific operations */
+	if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+						ARM_LOCAL_STATE_OFF)
+		arm_system_pwr_domain_resume();
 
 	/*
 	 * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
@@ -201,13 +221,18 @@
 	 * register context.
 	 */
 
-	/* Program the power controller to power off this cpu. */
-	fvp_pwrc_write_ppoffr(read_mpidr_el1());
-
 	/* Perform the common cluster specific operations */
 	if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
 					ARM_LOCAL_STATE_OFF)
 		fvp_cluster_pwrdwn_common();
+
+	/* Perform the common system specific operations */
+	if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+						ARM_LOCAL_STATE_OFF)
+		arm_system_pwr_domain_save();
+
+	/* Program the power controller to power off this cpu. */
+	fvp_pwrc_write_ppoffr(read_mpidr_el1());
 }
 
 /*******************************************************************************
@@ -309,7 +334,57 @@
 	return ret;
 }
 
+/*
+ * The FVP doesn't truly support power management at SYSTEM power domain. The
+ * SYSTEM_SUSPEND will be down-graded to the cluster level within the platform
+ * layer. The `fake` SYSTEM_SUSPEND allows us to validate some of the driver
+ * save and restore sequences on FVP.
+ */
+void fvp_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	unsigned int i;
+
+	for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+		req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF;
+}
+
 /*******************************************************************************
+ * Handler to filter PSCI requests.
+ ******************************************************************************/
+/*
+ * The system power domain suspend is only supported only via
+ * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain
+ * will be downgraded to the lower level.
+ */
+static int fvp_validate_power_state(unsigned int power_state,
+			    psci_power_state_t *req_state)
+{
+	int rc;
+	rc = arm_validate_power_state(power_state, req_state);
+
+	/*
+	 * Ensure that the system power domain level is never suspended
+	 * via PSCI CPU SUSPEND API. Currently system suspend is only
+	 * supported via PSCI SYSTEM SUSPEND API.
+	 */
+	req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN;
+	return rc;
+}
+
+/*
+ * Custom `translate_power_state_by_mpidr` handler for FVP. Unlike in the
+ * `fvp_validate_power_state`, we do not downgrade the system power
+ * domain level request in `power_state` as it will be used to query the
+ * PSCI_STAT_COUNT/RESIDENCY at the system power domain level.
+ */
+static int fvp_translate_power_state_by_mpidr(u_register_t mpidr,
+		unsigned int power_state,
+		psci_power_state_t *output_state)
+{
+	return arm_validate_power_state(power_state, output_state);
+}
+
+/*******************************************************************************
  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  * platform layer will take care of registering the handlers with PSCI.
  ******************************************************************************/
@@ -322,9 +397,11 @@
 	.pwr_domain_suspend_finish = fvp_pwr_domain_suspend_finish,
 	.system_off = fvp_system_off,
 	.system_reset = fvp_system_reset,
-	.validate_power_state = arm_validate_power_state,
+	.validate_power_state = fvp_validate_power_state,
 	.validate_ns_entrypoint = arm_validate_ns_entrypoint,
+	.translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr,
 	.get_node_hw_state = fvp_node_hw_state,
+	.get_sys_suspend_power_state = fvp_get_sys_suspend_power_state,
 /*
  * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
  * as that would require mapping in all of NS DRAM into BL31 or BL32.
diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c
index cf1492b..4a007f4 100644
--- a/plat/arm/board/fvp/fvp_topology.c
+++ b/plat/arm/board/fvp/fvp_topology.c
@@ -12,7 +12,7 @@
 #include "drivers/pwrc/fvp_pwrc.h"
 
 /* The FVP power domain tree descriptor */
-unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 1];
+unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2];
 
 
 CASSERT(FVP_CLUSTER_COUNT && FVP_CLUSTER_COUNT <= 256, assert_invalid_fvp_cluster_count);
@@ -23,18 +23,18 @@
  ******************************************************************************/
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	int i;
+	unsigned int i;
 
 	/*
-	 * The FVP power domain tree does not have a single system level power domain
-	 * i.e. a single root node. The first entry in the power domain descriptor
-	 * specifies the number of power domains at the highest power level. For the FVP
-	 * this is the number of cluster power domains.
+	 * The highest level is the system level. The next level is constituted
+	 * by clusters and then cores in clusters.
 	 */
-	fvp_power_domain_tree_desc[0] = FVP_CLUSTER_COUNT;
+	fvp_power_domain_tree_desc[0] = 1;
+	fvp_power_domain_tree_desc[1] = FVP_CLUSTER_COUNT;
 
 	for (i = 0; i < FVP_CLUSTER_COUNT; i++)
-		fvp_power_domain_tree_desc[i + 1] = FVP_MAX_CPUS_PER_CLUSTER;
+		fvp_power_domain_tree_desc[i + 2] = FVP_MAX_CPUS_PER_CLUSTER;
+
 
 	return fvp_power_domain_tree_desc;
 }
diff --git a/plat/arm/board/fvp/include/plat.ld.S b/plat/arm/board/fvp/include/plat.ld.S
new file mode 100644
index 0000000..24c3deb
--- /dev/null
+++ b/plat/arm/board/fvp/include/plat.ld.S
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __PLAT_LD_S__
+#define __PLAT_LD_S__
+
+#include <arm_common.ld.S>
+
+#endif /* __PLAT_LD_S__ */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index e953580..310db7b 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -20,9 +20,9 @@
 	(FVP_CLUSTER_COUNT * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU)
 
 #define PLAT_NUM_PWR_DOMAINS		(FVP_CLUSTER_COUNT + \
-					PLATFORM_CORE_COUNT)
+					PLATFORM_CORE_COUNT) + 1
 
-#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL2
 
 /*
  * Other platform porting definitions are provided by included headers
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 29da12e..1b50296 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -155,5 +155,8 @@
     NEED_BL32 := yes
 endif
 
+# Add support for platform supplied linker script for BL31 build
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
 include plat/arm/board/common/board_common.mk
 include plat/arm/common/arm_common.mk
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 395d1fb..ccc7771 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -12,6 +12,9 @@
 #include <board_css_def.h>
 #include <common_def.h>
 #include <css_def.h>
+#if TRUSTED_BOARD_BOOT
+#include <mbedtls_config.h>
+#endif
 #include <soc_css_def.h>
 #include <tzc400.h>
 #include <v2m_def.h>
@@ -106,7 +109,11 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x19000
+#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
+# define PLAT_ARM_MAX_BL2_SIZE		0x1E000
+#else
+# define PLAT_ARM_MAX_BL2_SIZE		0x1A000
+#endif
 #else
 # define PLAT_ARM_MAX_BL2_SIZE		0xC000
 #endif
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 82f02b1..e1484d7 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -9,7 +9,12 @@
   # DRAM (if available) or the TZC secured area of DRAM.
   # Trusted SRAM is the default.
 
-  ARM_TSP_RAM_LOCATION	:=	tsram
+  ifneq (${TRUSTED_BOARD_BOOT},0)
+    ARM_TSP_RAM_LOCATION	?=	dram
+  else
+    ARM_TSP_RAM_LOCATION	?=	tsram
+  endif
+
   ifeq (${ARM_TSP_RAM_LOCATION}, tsram)
     ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
   else ifeq (${ARM_TSP_RAM_LOCATION}, tdram)
diff --git a/plat/arm/common/arm_gicv2.c b/plat/arm/common/arm_gicv2.c
index aac0248..b081fa8 100644
--- a/plat/arm/common/arm_gicv2.c
+++ b/plat/arm/common/arm_gicv2.c
@@ -92,3 +92,21 @@
 {
 	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)
+{
+	return;
+}
+
+void plat_arm_gic_resume(void)
+{
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+}
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
index cec6a9d..e273b77 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/plat/arm/common/arm_gicv3.c
@@ -32,6 +32,13 @@
 };
 
 /*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory
+ */
+gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
+gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
+
+/*
  * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
  * to core position.
  *
@@ -121,3 +128,58 @@
 {
 	gicv3_rdistif_off(plat_my_core_pos());
 }
+
+/******************************************************************************
+ * ARM common helper to save & restore the GICv3 on resume from system suspend
+ *****************************************************************************/
+void plat_arm_gic_save(void)
+{
+
+	/*
+	 * If an ITS is available, save its context before
+	 * the Redistributor using:
+	 * gicv3_its_save_disable(gits_base, &its_ctx[i])
+	 * Additionnaly, an implementation-defined sequence may
+	 * be required to save the whole ITS state.
+	 */
+
+	/*
+	 * Save the GIC Redistributors and ITS contexts before the
+	 * Distributor context. As we only handle SYSTEM SUSPEND API,
+	 * we only need to save the context of the CPU that is issuing
+	 * the SYSTEM SUSPEND call, i.e. the current CPU.
+	 */
+	gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+
+	/* Save the GIC Distributor context */
+	gicv3_distif_save(&dist_ctx);
+
+	/*
+	 * From here, all the components of the GIC can be safely powered down
+	 * as long as there is an alternate way to handle wakeup interrupt
+	 * sources.
+	 */
+}
+
+void plat_arm_gic_resume(void)
+{
+	/* Restore the GIC Distributor context */
+	gicv3_distif_init_restore(&dist_ctx);
+
+	/*
+	 * Restore the GIC Redistributor and ITS contexts after the
+	 * Distributor context. As we only handle SYSTEM SUSPEND API,
+	 * we only need to restore the context of the CPU that issued
+	 * the SYSTEM SUSPEND call.
+	 */
+	gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+
+	/*
+	 * If an ITS is available, restore its context after
+	 * the Redistributor using:
+	 * gicv3_its_restore(gits_base, &its_ctx[i])
+	 * An implementation-defined sequence may be required to
+	 * restore the whole ITS state. The ITS must also be
+	 * re-enabled after this sequence has been executed.
+	 */
+}
diff --git a/plat/arm/common/arm_gicv3_legacy.c b/plat/arm/common/arm_gicv3_legacy.c
index a014a8e..e19799a 100644
--- a/plat/arm/common/arm_gicv3_legacy.c
+++ b/plat/arm/common/arm_gicv3_legacy.c
@@ -84,3 +84,16 @@
 {
 	return;
 }
+
+/******************************************************************************
+ * ARM common helper to save & restore the GICv3 on resume from system suspend.
+ *****************************************************************************/
+void plat_arm_gic_save(void)
+{
+	return;
+}
+
+void plat_arm_gic_resume(void)
+{
+	arm_gic_setup();
+}
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index cc131a9..5e7e047 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -11,6 +11,7 @@
 #include <console.h>
 #include <errno.h>
 #include <plat_arm.h>
+#include <platform.h>
 #include <platform_def.h>
 #include <psci.h>
 
@@ -140,6 +141,24 @@
 }
 
 /******************************************************************************
+ * Helper function to save the platform state before a system suspend. Save the
+ * state of the system components which are not in the Always ON power domain.
+ *****************************************************************************/
+void arm_system_pwr_domain_save(void)
+{
+	/* Assert system power domain is available on the platform */
+	assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
+
+	plat_arm_gic_save();
+
+	/*
+	 * All the other peripheral which are configured by ARM TF are
+	 * re-initialized on resume from system suspend. Hence we
+	 * don't save their state here.
+	 */
+}
+
+/******************************************************************************
  * Helper function to resume the platform from system suspend. Reinitialize
  * the system components which are not in the Always ON power domain.
  * TODO: Unify the platform setup when waking up from cold boot and system
@@ -153,12 +172,8 @@
 	/* Assert system power domain is available on the platform */
 	assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
 
-	/*
-	 * TODO: On GICv3 systems, figure out whether the core that wakes up
-	 * first from system suspend need to initialize the re-distributor
-	 * interface of all the other suspended cores.
-	 */
-	plat_arm_gic_init();
+	plat_arm_gic_resume();
+
 	plat_arm_security_setup();
 	arm_configure_sys_timer();
 }
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 1d61c57..e19ca67 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -40,7 +40,7 @@
 
 	/* Region 1 set to cover Secure part of DRAM */
 	tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 1,
-			ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END,
+			ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END,
 			TZC_REGION_S_RDWR,
 			0);
 
diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
index 21ca4e8..8e41391 100644
--- a/plat/arm/common/arm_tzc_dmc500.c
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -33,7 +33,7 @@
 
 	/* Region 1 set to cover Secure part of DRAM */
 	tzc_dmc500_configure_region(1, ARM_AP_TZC_DRAM1_BASE,
-		ARM_AP_TZC_DRAM1_END,
+		ARM_EL3_TZC_DRAM1_END,
 		TZC_REGION_S_RDWR,
 		0);
 
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 39c02af..4104dd7 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -74,6 +74,9 @@
 {
 	assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
 
+	/* Enable the gic cpu interface */
+	plat_arm_gic_cpuif_enable();
+
 	/*
 	 * Perform the common cluster specific operations i.e enable coherency
 	 * if this cluster was off.
@@ -95,13 +98,10 @@
 	/* Assert that the system power domain need not be initialized */
 	assert(CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_RUN);
 
-	css_pwr_domain_on_finisher_common(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();
+	css_pwr_domain_on_finisher_common(target_state);
 }
 
 /*******************************************************************************
@@ -144,8 +144,18 @@
 	if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
 		return;
 
+
 	assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
 	css_power_down_common(target_state);
+
+	/* Perform system domain state saving if issuing system suspend */
+	if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
+		arm_system_pwr_domain_save();
+
+		/* Power off the Redistributor after having saved its context */
+		plat_arm_gic_redistif_off();
+	}
+
 	css_scp_suspend(target_state);
 }
 
@@ -165,10 +175,12 @@
 
 	/* Perform system domain restore if woken up from system suspend */
 	if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+		/*
+		 * At this point, the Distributor must be powered on to be ready
+		 * to have its state restored. The Redistributor will be powered
+		 * on as part of gicv3_rdistif_init_restore.
+		 */
 		arm_system_pwr_domain_resume();
-	else
-		/* Enable the gic cpu interface */
-		plat_arm_gic_cpuif_enable();
 
 	css_pwr_domain_on_finisher_common(target_state);
 }
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
index b5f41ff..61d21ab 100644
--- a/plat/common/aarch32/platform_helpers.S
+++ b/plat/common/aarch32/platform_helpers.S
@@ -14,6 +14,8 @@
 	.weak	plat_disable_acp
 	.weak	platform_mem_init
 	.weak	plat_panic_handler
+	.weak	bl2_plat_preload_setup
+	.weak	plat_try_next_boot_source
 
 	/* -----------------------------------------------------
 	 * Placeholder function which should be redefined by
@@ -79,3 +81,23 @@
 func plat_panic_handler
 	b	plat_panic_handler
 endfunc plat_panic_handler
+
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platfrom.
+	 * -----------------------------------------------------
+	 */
+func bl2_plat_preload_setup
+	bx	lr
+endfunc bl2_plat_preload_setup
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platfrom.
+	 * -----------------------------------------------------
+	 */
+func plat_try_next_boot_source
+	mov	r0, #0
+	bx	lr
+endfunc plat_try_next_boot_source
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
index e60db20..797a936 100644
--- a/plat/common/aarch64/platform_helpers.S
+++ b/plat/common/aarch64/platform_helpers.S
@@ -17,6 +17,8 @@
 	.weak	bl1_plat_prepare_exit
 	.weak	plat_error_handler
 	.weak	plat_panic_handler
+	.weak	bl2_plat_preload_setup
+	.weak	plat_try_next_boot_source
 
 #if !ENABLE_PLAT_COMPAT
 	.globl	platform_get_core_pos
@@ -129,3 +131,22 @@
 	wfi
 	b	plat_panic_handler
 endfunc plat_panic_handler
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platfrom.
+	 * -----------------------------------------------------
+	 */
+func bl2_plat_preload_setup
+	ret
+endfunc bl2_plat_preload_setup
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platfrom.
+	 * -----------------------------------------------------
+	 */
+func plat_try_next_boot_source
+	mov	x0, #0
+	ret
+endfunc plat_try_next_boot_source
diff --git a/plat/qemu/qemu_bl31_setup.c b/plat/qemu/qemu_bl31_setup.c
index 5bf4589..f79a885 100644
--- a/plat/qemu/qemu_bl31_setup.c
+++ b/plat/qemu/qemu_bl31_setup.c
@@ -7,6 +7,7 @@
 #include <assert.h>
 #include <bl_common.h>
 #include <console.h>
+#include <gic_common.h>
 #include <gicv2.h>
 #include <platform_def.h>
 #include "qemu_private.h"
@@ -112,22 +113,40 @@
 			      BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
 }
 
-static const unsigned int irq_sec_array[] = {
-	QEMU_IRQ_SEC_SGI_0,
-	QEMU_IRQ_SEC_SGI_1,
-	QEMU_IRQ_SEC_SGI_2,
-	QEMU_IRQ_SEC_SGI_3,
-	QEMU_IRQ_SEC_SGI_4,
-	QEMU_IRQ_SEC_SGI_5,
-	QEMU_IRQ_SEC_SGI_6,
-	QEMU_IRQ_SEC_SGI_7,
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+#define PLATFORM_G1S_PROPS(grp)						\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE),	\
+	INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,	\
+					   grp, GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp)
+
+static const interrupt_prop_t qemu_interrupt_props[] = {
+	PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
+	PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
 };
 
 static const struct gicv2_driver_data plat_gicv2_driver_data = {
 	.gicd_base = GICD_BASE,
 	.gicc_base = GICC_BASE,
-	.g0_interrupt_num = ARRAY_SIZE(irq_sec_array),
-	.g0_interrupt_array = irq_sec_array,
+	.interrupt_props = qemu_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props),
 };
 
 void bl31_platform_setup(void)