Trusted Firmware-A Tests, version 2.0

This is the first public version of the tests for the Trusted
Firmware-A project. Please see the documentation provided in the
source tree for more details.

Change-Id: I6f3452046a1351ac94a71b3525c30a4ca8db7867
Signed-off-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: amobal01 <amol.balasokamble@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Co-authored-by: Asha R <asha.r@arm.com>
Co-authored-by: Chandni Cherukuri <chandni.cherukuri@arm.com>
Co-authored-by: David Cunado <david.cunado@arm.com>
Co-authored-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Co-authored-by: dp-arm <dimitris.papastamos@arm.com>
Co-authored-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Co-authored-by: Jonathan Wright <jonathan.wright@arm.com>
Co-authored-by: Kévin Petit <kevin.petit@arm.com>
Co-authored-by: Roberto Vargas <roberto.vargas@arm.com>
Co-authored-by: Sathees Balya <sathees.balya@arm.com>
Co-authored-by: Shawon Roy <Shawon.Roy@arm.com>
Co-authored-by: Soby Mathew <soby.mathew@arm.com>
Co-authored-by: Thomas Abraham <thomas.abraham@arm.com>
Co-authored-by: Vikram Kanigiri <vikram.kanigiri@arm.com>
Co-authored-by: Yatharth Kochar <yatharth.kochar@arm.com>
diff --git a/plat/arm/board/fvp/aarch32/plat_helpers.S b/plat/arm/board/fvp/aarch32/plat_helpers.S
new file mode 100644
index 0000000..2dcc6e9
--- /dev/null
+++ b/plat/arm/board/fvp/aarch32/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include "../fvp_def.h"
+
+	.globl	platform_get_core_pos
+
+/*----------------------------------------------------------------------
+ * unsigned int platform_get_core_pos(unsigned long mpid)
+ *
+ * Function to calculate the core position on FVP.
+ *
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
+ * (CPUId * FVP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func platform_get_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation
+	 */
+	tst	r0, #MPIDR_MT_MASK
+	mov	r3, r0
+	lsleq	r3, r0, #MPIDR_AFFINITY_BITS
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	r3, #FVP_MAX_CPUS_PER_CLUSTER
+	mla	r1, r2, r3, r1
+	mov	r3, #FVP_MAX_PE_PER_CPU
+	mla	r0, r1, r3, r0
+
+	bx	lr
+endfunc platform_get_core_pos
diff --git a/plat/arm/board/fvp/aarch64/plat_helpers.S b/plat/arm/board/fvp/aarch64/plat_helpers.S
new file mode 100644
index 0000000..bc9f60d
--- /dev/null
+++ b/plat/arm/board/fvp/aarch64/plat_helpers.S
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include "../fvp_def.h"
+
+	.globl	platform_get_core_pos
+
+/*----------------------------------------------------------------------
+ * unsigned int platform_get_core_pos(unsigned long mpid)
+ *
+ * Function to calculate the core position on FVP.
+ *
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
+ * (CPUId * FVP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func platform_get_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation.
+	 */
+	tst	x0, #MPIDR_MT_MASK
+	lsl	x3, x0, #MPIDR_AFFINITY_BITS
+	csel	x3, x3, x0, eq
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x3, #FVP_MAX_CPUS_PER_CLUSTER
+	madd	x1, x2, x3, x1
+	mov	x3, #FVP_MAX_PE_PER_CPU
+	madd	x0, x1, x3, x0
+	ret
+endfunc platform_get_core_pos
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
new file mode 100644
index 0000000..a47287f
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*******************************************************************************
+ * FVP specific definitions. Used only by FVP specific code.
+ ******************************************************************************/
+
+#ifndef __FVP_DEF_H__
+#define __FVP_DEF_H__
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Cluster Topology definitions
+ ******************************************************************************/
+#define FVP_MAX_CPUS_PER_CLUSTER	4
+/* Currently the highest cluster count on the FVP is 4 (Quad cluster) */
+#define FVP_CLUSTER_COUNT		4
+/* Currently multi-threaded CPUs only have a single thread */
+#define FVP_MAX_PE_PER_CPU		1
+
+/*******************************************************************************
+ * FVP memory map related constants
+ ******************************************************************************/
+
+#define DEVICE0_BASE		0x1a000000
+#define DEVICE0_SIZE		0x12200000
+
+#define DEVICE1_BASE		0x2f000000
+#define DEVICE1_SIZE		0x400000
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+/* Base FVP compatible GIC memory map */
+#define GICD_BASE		0x2f000000
+#define GICR_BASE		0x2f100000
+#define GICC_BASE		0x2c000000
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+#define PL011_UART0_BASE	0x1c090000
+#define PL011_UART0_CLK_IN_HZ	24000000
+
+#define PLAT_ARM_UART_BASE		PL011_UART0_BASE
+#define PLAT_ARM_UART_CLK_IN_HZ		PL011_UART0_CLK_IN_HZ
+
+#endif /* __FVP_DEF_H__ */
diff --git a/plat/arm/board/fvp/fvp_mem_prot.c b/plat/arm/board/fvp/fvp_mem_prot.c
new file mode 100644
index 0000000..6a7d651
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_mem_prot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+#include <psci.h>
+#include <utils_def.h>
+#include <xlat_tables_v2.h>
+
+#define NS_IMAGE_OFFSET      TFTF_BASE
+#define NS_IMAGE_LIMIT       (NS_IMAGE_OFFSET + (32 << TWO_MB_SHIFT))
+
+static const mem_region_t fvp_ram_ranges[] = {
+	{NS_IMAGE_LIMIT, 1 << ONE_GB_SHIFT},
+#ifdef AARCH64
+	{FVP_DRAM2_BASE, 1 << ONE_GB_SHIFT},
+#endif
+};
+
+const mem_region_t *plat_get_prot_regions(int *nelem)
+{
+	*nelem = ARRAY_SIZE(fvp_ram_ranges);
+	return fvp_ram_ranges;
+}
diff --git a/plat/arm/board/fvp/fvp_pwr_state.c b/plat/arm/board/fvp/fvp_pwr_state.c
new file mode 100644
index 0000000..394818b
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_pwr_state.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform.h>
+#include <psci.h>
+#include <stddef.h>
+
+/*
+ * State IDs for local power states on the FVP.
+ */
+#define FVP_RUN_STATE_ID	0	/* Valid for CPUs and Clusters */
+#define FVP_RETENTION_STATE_ID	1	/* Valid for only CPUs */
+#define FVP_OFF_STATE_ID	2	/* Valid for CPUs and Clusters */
+
+/*
+ * Suspend depth definitions for each power state
+ */
+typedef enum {
+	FVP_RUN_DEPTH = 0,
+	FVP_RETENTION_DEPTH,
+	FVP_OFF_DEPTH,
+} suspend_depth_t;
+
+/* The state property array with details of idle state possible for the core */
+static const plat_state_prop_t core_state_prop[] = {
+	{FVP_RETENTION_DEPTH, FVP_RETENTION_STATE_ID, PSTATE_TYPE_STANDBY},
+	{FVP_OFF_DEPTH, FVP_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+/* The state property array with details of idle state possible
+   for the cluster */
+static const plat_state_prop_t cluster_state_prop[] = {
+	{FVP_OFF_DEPTH, FVP_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+/* The state property array with details of idle state possible
+   for the system level */
+static const plat_state_prop_t system_state_prop[] = {
+	{FVP_OFF_DEPTH, FVP_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+const plat_state_prop_t *plat_get_state_prop(unsigned int level)
+{
+	switch (level) {
+	case MPIDR_AFFLVL0:
+		return core_state_prop;
+	case MPIDR_AFFLVL1:
+		return cluster_state_prop;
+	case MPIDR_AFFLVL2:
+		return system_state_prop;
+	default:
+		return NULL;
+	}
+}
diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c
new file mode 100644
index 0000000..348f8ef
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_topology.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <mmio.h>
+#include <plat_topology.h>
+#include <platform_def.h>
+#include <stddef.h>
+#include <tftf_lib.h>
+
+/* FVP Power controller based defines */
+#define PWRC_BASE		0x1c100000
+#define PSYSR_OFF		0x10
+#define PSYSR_INVALID		0xffffffff
+
+static const struct {
+	unsigned int cluster_id;
+	unsigned int cpu_id;
+} fvp_base_aemv8a_aemv8a_cores[] = {
+	/* Cluster 0 */
+	{ 0, 0 },
+	{ 0, 1 },
+	{ 0, 2 },
+	{ 0, 3 },
+	/* Cluster 1 */
+	{ 1, 0 },
+	{ 1, 1 },
+	{ 1, 2 },
+	{ 1, 3 },
+	/* Cluster 2 */
+	{ 2, 0 },
+	{ 2, 1 },
+	{ 2, 2 },
+	{ 2, 3 },
+	/* Cluster 3 */
+	{ 3, 0 },
+	{ 3, 1 },
+	{ 3, 2 },
+	{ 3, 3 },
+};
+
+/*
+ * The FVP power domain tree descriptor. We always construct a topology
+ * with the maximum number of cluster nodes possible for FVP. During
+ * TFTF initialization, the actual number of nodes present on the model
+ * will be queried dynamically using `tftf_plat_get_mpidr()`.
+ * 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 which
+ * is equal to FVP_CLUSTER_COUNT.
+ */
+static const unsigned char fvp_power_domain_tree_desc[] = {
+	/* Number of system nodes */
+	1,
+	/* Number of cluster nodes */
+	FVP_CLUSTER_COUNT,
+	/* Number of children for the first node */
+	FVP_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the second node */
+	FVP_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the third node */
+	FVP_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the fourth node */
+	FVP_MAX_CPUS_PER_CLUSTER
+};
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+	return fvp_power_domain_tree_desc;
+}
+
+static unsigned int fvp_pwrc_read_psysr(unsigned long mpidr)
+{
+	unsigned int rc;
+	mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr);
+	rc = mmio_read_32(PWRC_BASE + PSYSR_OFF);
+	return rc;
+}
+
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+	unsigned int mpid;
+
+	assert(core_pos < PLATFORM_CORE_COUNT);
+
+	mpid = make_mpid(
+			fvp_base_aemv8a_aemv8a_cores[core_pos].cluster_id,
+			fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id);
+
+	if (fvp_pwrc_read_psysr(mpid) != PSYSR_INVALID)
+		return mpid;
+
+	return INVALID_MPID;
+}
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
new file mode 100644
index 0000000..f09b6b5
--- /dev/null
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arm_def.h>
+#include "../fvp_def.h"
+
+/*******************************************************************************
+ * Platform definitions used by common code
+ ******************************************************************************/
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#ifndef AARCH32
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+#else
+#define PLATFORM_LINKER_FORMAT		"elf32-littlearm"
+#define PLATFORM_LINKER_ARCH		arm
+#endif
+
+/*******************************************************************************
+ * Run-time address of the TFTF image.
+ * It has to match the location where the Trusted Firmware-A loads the BL33
+ * image.
+ ******************************************************************************/
+#define TFTF_BASE			0x88000000
+
+/* Base address of non-trusted watchdog (SP805) */
+#define SP805_WDOG_BASE			0x1C0F0000
+
+/*******************************************************************************
+ * Base address and size of external NVM flash
+ ******************************************************************************/
+#define FLASH_BASE			0x08000000
+
+/*
+ * The flash memory in FVP resembles as a SCSP package of 2-die's and
+ * of a total size of 512Mb, we are using only the main blocks of size
+ * 128KB for storing results. Also the FVP performs data striping and
+ * splits the word into half to each flash die's which leads to a
+ * virtual block size of 256KB to software.
+ */
+#define NOR_FLASH_BLOCK_SIZE		0x40000 /* 256KB */
+#define NOR_FLASH_BLOCKS_COUNT		255
+#define FLASH_SIZE			(NOR_FLASH_BLOCK_SIZE * NOR_FLASH_BLOCKS_COUNT)
+
+/*******************************************************************************
+ * Base address and size for the FIP that contains FWU images.
+ ******************************************************************************/
+#define PLAT_ARM_FWU_FIP_BASE		(FLASH_BASE + 0x400000)
+#define PLAT_ARM_FWU_FIP_SIZE		(0x100000)
+
+/*******************************************************************************
+ * Base address and size for non-trusted SRAM.
+ ******************************************************************************/
+#define NSRAM_BASE				(0x2e000000)
+#define NSRAM_SIZE				(0x00010000)
+
+/*******************************************************************************
+ * Corresponds to the function ID of the BL1 SMC handler for FWU process.
+ ******************************************************************************/
+#define BL1_SMC_CALL_COUNT		0x0
+#define BL1_SMC_UID			0x1
+/* SMC #0x2 reserved */
+#define BL1_SMC_VERSION			0x3
+#define FWU_SMC_IMAGE_COPY		0x10
+#define FWU_SMC_IMAGE_AUTH		0x11
+#define FWU_SMC_IMAGE_EXECUTE		0x12
+#define FWU_SMC_IMAGE_RESUME		0x13
+#define FWU_SMC_SEC_IMAGE_DONE		0x14
+#define FWU_SMC_UPDATE_DONE		0x15
+#define FWU_SMC_IMAGE_RESET		0x16
+
+
+/*******************************************************************************
+ * NS_BL1U specific defines.
+ * NS_BL1U RW data is relocated from NS-ROM to NS-RAM at runtime so we
+ * need 2 sets of addresses.
+ ******************************************************************************/
+#define NS_BL1U_RO_BASE		(0x08000000 + 0x03EB8000)
+#define NS_BL1U_RO_LIMIT	(NS_BL1U_RO_BASE + 0xC000)
+
+/*******************************************************************************
+ * Put NS_BL1U RW at the top of the Non-Trusted SRAM. NS_BL1U_RW_BASE is
+ * calculated using the current NS_BL1U RW debug size plus a little space
+ * for growth.
+ ******************************************************************************/
+#define NS_BL1U_RW_SIZE		(0x7000)
+#define NS_BL1U_RW_BASE		(NSRAM_BASE)
+#define NS_BL1U_RW_LIMIT	(NS_BL1U_RW_BASE + NS_BL1U_RW_SIZE)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define FVP_DRAM1_BASE			0x80000000
+#define FVP_DRAM2_BASE			0x880000000
+#define DRAM_BASE			FVP_DRAM1_BASE
+#define DRAM_SIZE			0x80000000
+
+/*******************************************************************************
+ * Base address and limit for NS_BL2U image.
+ ******************************************************************************/
+#define NS_BL2U_BASE		DRAM_BASE
+#define NS_BL2U_LIMIT		(NS_BL2U_BASE + 0x4D000)
+
+/******************************************************************************
+ * Memory mapped Generic timer interfaces
+ ******************************************************************************/
+/* REFCLK CNTControl, Generic Timer. Secure Access only. */
+#define SYS_CNT_CONTROL_BASE		0x2a430000
+/* REFCLK CNTRead, Generic Timer. */
+#define SYS_CNT_READ_BASE		0x2a800000
+/* AP_REFCLK CNTBase1, Generic Timer. */
+#define SYS_CNT_BASE1			0x2a830000
+
+/* V2M motherboard system registers & offsets */
+#define VE_SYSREGS_BASE		0x1c010000
+#define V2M_SYS_LED		0x8
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if IMAGE_NS_BL1U || IMAGE_NS_BL2U
+#define PLATFORM_STACK_SIZE	0x1000
+#else
+#define PLATFORM_STACK_SIZE	0x1400
+#endif
+
+/* Size of coherent stacks for debug and release builds */
+#if DEBUG
+#define PCPU_DV_MEM_STACK_SIZE	0x600
+#else
+#define PCPU_DV_MEM_STACK_SIZE	0x500
+#endif
+
+#define PLATFORM_CORE_COUNT		(FVP_CLUSTER_COUNT * \
+						FVP_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_NUM_AFFS		(1 + FVP_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+#define PLATFORM_MAX_AFFLVL		MPIDR_AFFLVL2
+
+/* TODO : Migrate complete TFTF from affinity level to power levels */
+#define PLAT_MAX_PWR_LEVEL		PLATFORM_MAX_AFFLVL
+#define PLAT_MAX_PWR_STATES_PER_LVL	2
+
+#if IMAGE_NS_BL1U
+#define MAX_IO_DEVICES			2
+#define MAX_IO_HANDLES			2
+#else
+#define MAX_IO_DEVICES			1
+#define MAX_IO_HANDLES			1
+#endif
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH		4
+
+#if USE_NVM
+/*
+ * The Flash memory is used to store the TFTF data on FVP.
+ * However, it might contain other data that must not be overwritten.
+ * For example, when using the Trusted Firmware-A, the FIP image
+ * (containing the bootloader images) is also stored in Flash.
+ * Hence, consider the first 40MB of Flash as reserved for firmware usage.
+ * The TFTF can use the rest of the Flash memory.
+ */
+#define TFTF_NVM_OFFSET		0x2800000	/* 40 MB */
+#define TFTF_NVM_SIZE		(FLASH_SIZE - TFTF_NVM_OFFSET)
+#else
+/*
+ * If you want to run without support for non-volatile memory (due to
+ * e.g. unavailability of a flash driver), DRAM can be used instead as
+ * a workaround. The TFTF binary itself is loaded at 0x88000000 so the
+ * first 128MB can be used
+ * Please note that this won't be suitable for all test scenarios and
+ * for this reason some tests will be disabled in this configuration.
+ */
+#define TFTF_NVM_OFFSET		0x0
+#define TFTF_NVM_SIZE		(TFTF_BASE - DRAM_BASE - TFTF_NVM_OFFSET)
+#endif
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+#if IMAGE_TFTF
+#define MAX_XLAT_TABLES			6
+#define MAX_MMAP_REGIONS		16
+#else
+#define MAX_XLAT_TABLES			5
+#define MAX_MMAP_REGIONS		16
+#endif
+
+/*******************************************************************************
+ * Used to align variables on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interupts IDs
+ ******************************************************************************/
+#define IRQ_NS_SGI_0			0
+#define IRQ_NS_SGI_1			1
+#define IRQ_NS_SGI_2			2
+#define IRQ_NS_SGI_3			3
+#define IRQ_NS_SGI_4			4
+#define IRQ_NS_SGI_5			5
+#define IRQ_NS_SGI_6			6
+#define IRQ_NS_SGI_7			7
+
+/*
+ * On FVP, consider that the last SPI is the Trusted Random Number Generator
+ * interrupt.
+ */
+#define PLAT_MAX_SPI_OFFSET_ID		107
+
+/* AP_REFCLK, Generic Timer, CNTPSIRQ1. */
+#define IRQ_CNTPSIRQ1			58
+/* Per-CPU Hypervisor Timer Interrupt ID */
+#define IRQ_PCPU_HP_TIMER		26
+/* Per-CPU Non-Secure Timer Interrupt ID */
+#define IRQ_PCPU_NS_TIMER		30
+
+
+/* Times(in ms) used by test code for completion of different events */
+#define PLAT_SUSPEND_ENTRY_TIME		15
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME	30
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/fvp/plat_setup.c b/plat/arm/board/fvp/plat_setup.c
new file mode 100644
index 0000000..0d81686
--- /dev/null
+++ b/plat/arm/board/fvp/plat_setup.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arm_gic.h>
+#include <plat_arm.h>
+#include <platform.h>
+
+/*
+ * Table of regions to map using the MMU.
+ */
+#if IMAGE_NS_BL1U
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_NS),
+	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+	{0}
+ };
+#elif IMAGE_NS_BL2U
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+	{0}
+};
+#elif IMAGE_TFTF
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+#if USE_NVM
+	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
+#endif
+	MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE, MT_MEMORY | MT_RW | MT_NS),
+	{0}
+};
+#endif	/* IMAGE_NS_BL1U */
+
+const mmap_region_t *tftf_platform_get_mmap(void)
+{
+	return mmap;
+}
+
+void plat_arm_gic_init(void)
+{
+	arm_gic_init(GICC_BASE, GICD_BASE, GICR_BASE);
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
new file mode 100644
index 0000000..281a5f3
--- /dev/null
+++ b/plat/arm/board/fvp/platform.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES	:=	-Iplat/arm/board/fvp/include/
+
+PLAT_SOURCES	:=	drivers/arm/gic/arm_gic_v2v3.c			\
+			drivers/arm/gic/gic_v2.c			\
+			drivers/arm/gic/gic_v3.c			\
+			drivers/arm/sp805/sp805.c			\
+			drivers/arm/timer/private_timer.c		\
+			drivers/arm/timer/system_timer.c		\
+			lib/semihosting/${ARCH}/semihosting_call.S	\
+			lib/semihosting/semihosting.c			\
+			plat/arm/board/fvp/${ARCH}/plat_helpers.S	\
+			plat/arm/board/fvp/fvp_pwr_state.c		\
+			plat/arm/board/fvp/fvp_topology.c		\
+			plat/arm/board/fvp/fvp_mem_prot.c		\
+			plat/arm/board/fvp/plat_setup.c
+
+# Firmware update is implemented on FVP.
+FIRMWARE_UPDATE := 1
+
+include plat/arm/common/arm_common.mk
diff --git a/plat/arm/board/juno/aarch32/plat_helpers.S b/plat/arm/board/juno/aarch32/plat_helpers.S
new file mode 100644
index 0000000..6f252c0
--- /dev/null
+++ b/plat/arm/board/juno/aarch32/plat_helpers.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+	.globl	platform_get_core_pos
+
+	/*
+	 * Return 0 to 3 for the Cortex-A53 cores and 4 to 5 for the Cortex-A57
+	 * cores.
+	 */
+func platform_get_core_pos
+	and	r1, r0, #MPIDR_CPU_MASK
+	and	r0, r0, #MPIDR_CLUSTER_MASK
+	/* Swap Cortex-A53/Cortex-A57 order. */
+	eor	r0, r0, #(1 << MPIDR_AFF1_SHIFT)
+	add	r0, r1, r0, LSR #6
+	bx	lr
+endfunc platform_get_core_pos
diff --git a/plat/arm/board/juno/aarch64/plat_helpers.S b/plat/arm/board/juno/aarch64/plat_helpers.S
new file mode 100644
index 0000000..c51a4d9
--- /dev/null
+++ b/plat/arm/board/juno/aarch64/plat_helpers.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+	.globl	platform_get_core_pos
+
+	/*
+	 * Return 0 to 3 for the Cortex-A53 cores and 4 to 5 for the Cortex-A57
+	 * cores.
+	 */
+func platform_get_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	/* Swap Cortex-A53/Cortex-A57 order. */
+	eor	x0, x0, #(1 << MPIDR_AFF1_SHIFT)
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc platform_get_core_pos
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
new file mode 100644
index 0000000..37b419f
--- /dev/null
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arm_def.h>
+#include "../juno_def.h"
+
+/*******************************************************************************
+ * Platform definitions used by common code
+ ******************************************************************************/
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#ifndef AARCH32
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+#else
+#define PLATFORM_LINKER_FORMAT		"elf32-littlearm"
+#define PLATFORM_LINKER_ARCH		arm
+#endif
+
+/*******************************************************************************
+ * Run-time address of the TFTF image.
+ * It has to match the location where the Trusted Firmware-A loads the BL33
+ * image.
+ ******************************************************************************/
+#define TFTF_BASE			0xE0000000
+
+#define JUNO_DRAM1_BASE			0x80000000
+#define JUNO_DRAM2_BASE			0x880000000
+#define DRAM_BASE			JUNO_DRAM1_BASE
+#define DRAM_SIZE			0x80000000
+
+/* Base address of non-trusted watchdog (SP805) */
+#define SP805_WDOG_BASE			0x1C0F0000
+
+/* Memory mapped Generic timer interfaces  */
+#define SYS_CNT_BASE1		0x2a830000
+
+/* V2M motherboard system registers & offsets */
+#define VE_SYSREGS_BASE		0x1c010000
+#define V2M_SYS_LED		0x8
+
+/*******************************************************************************
+ * Base address and size of external NVM flash
+ ******************************************************************************/
+#define FLASH_BASE			0x08000000
+
+/*
+ * The flash chip on Juno is a SCSP package of 2-die's and of a total size of
+ * 512Mb, we are using only the main blocks of size 128KB for storing results.
+ * The SMC controller performs data striping and splits the word into half to
+ * each flash die's which leads to a virtual block size of 256KB to software.
+ */
+#define NOR_FLASH_BLOCK_SIZE		0x40000
+#define NOR_FLASH_BLOCKS_COUNT		255
+#define FLASH_SIZE			(NOR_FLASH_BLOCK_SIZE * NOR_FLASH_BLOCKS_COUNT)
+
+/*******************************************************************************
+ * Base address and size for the FIP that contains FWU images.
+ ******************************************************************************/
+#define PLAT_ARM_FWU_FIP_BASE		(FLASH_BASE + 0x400000)
+#define PLAT_ARM_FWU_FIP_SIZE		(0x100000)
+
+/*******************************************************************************
+ * Base address and size for non-trusted SRAM.
+ ******************************************************************************/
+#define NSRAM_BASE				(0x2e000000)
+#define NSRAM_SIZE				(0x00008000)
+
+/*******************************************************************************
+ * Corresponds to the function ID of the BL1 SMC handler for FWU process.
+ ******************************************************************************/
+#define BL1_SMC_CALL_COUNT		0x0
+#define BL1_SMC_UID			0x1
+/* SMC #0x2 reserved */
+#define BL1_SMC_VERSION			0x3
+#define FWU_SMC_IMAGE_COPY		0x10
+#define FWU_SMC_IMAGE_AUTH		0x11
+#define FWU_SMC_IMAGE_EXECUTE		0x12
+#define FWU_SMC_IMAGE_RESUME		0x13
+#define FWU_SMC_SEC_IMAGE_DONE		0x14
+#define FWU_SMC_UPDATE_DONE		0x15
+#define FWU_SMC_IMAGE_RESET		0x16
+
+/*******************************************************************************
+ * NS_BL1U specific defines.
+ * NS_BL1U RW data is relocated from NS-ROM to NS-RAM at runtime so we
+ * need 2 sets of addresses.
+ ******************************************************************************/
+#define NS_BL1U_RO_BASE		(0x08000000 + 0x03EB8000)
+#define NS_BL1U_RO_LIMIT	(NS_BL1U_RO_BASE + 0xC000)
+
+/*******************************************************************************
+ * Put NS_BL1U RW at the top of the Non-Trusted SRAM. NS_BL1U_RW_BASE is
+ * calculated using the current NS_BL1U RW debug size plus a little space
+ * for growth.
+ ******************************************************************************/
+#define NS_BL1U_RW_SIZE		(0x7000)
+#define NS_BL1U_RW_BASE		(NSRAM_BASE)
+#define NS_BL1U_RW_LIMIT	(NS_BL1U_RW_BASE + NS_BL1U_RW_SIZE)
+
+/*******************************************************************************
+ * Base address and limit for NS_BL2U image.
+ ******************************************************************************/
+#define NS_BL2U_BASE		DRAM_BASE
+#define NS_BL2U_LIMIT		(NS_BL2U_BASE + 0x4D000)
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if IMAGE_NS_BL1U
+#define PLATFORM_STACK_SIZE 0x1000
+#elif IMAGE_NS_BL2U
+#define PLATFORM_STACK_SIZE 0x1000
+#elif IMAGE_TFTF
+#define PLATFORM_STACK_SIZE 0x1400
+#endif
+
+/* Size of coherent stacks for debug and release builds */
+#if DEBUG
+#define PCPU_DV_MEM_STACK_SIZE 0x600
+#else
+#define PCPU_DV_MEM_STACK_SIZE 0x500
+#endif
+
+#define PLATFORM_SYSTEM_COUNT		1
+#define PLATFORM_CLUSTER_COUNT		2
+#define PLATFORM_CLUSTER1_CORE_COUNT	4 /* Cortex-A53 Cluster */
+#define PLATFORM_CLUSTER0_CORE_COUNT	2 /* Cortex-A57 Cluster */
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER1_CORE_COUNT + \
+					PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_NUM_AFFS		(PLATFORM_SYSTEM_COUNT + \
+					PLATFORM_CLUSTER_COUNT + \
+					PLATFORM_CORE_COUNT)
+#define PLATFORM_MAX_AFFLVL		MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LEVEL		PLATFORM_MAX_AFFLVL
+#define PLAT_MAX_PWR_STATES_PER_LVL	2
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH		4
+
+#if IMAGE_NS_BL1U
+#define MAX_IO_DEVICES			2
+#define MAX_IO_HANDLES			2
+#else
+#define MAX_IO_DEVICES			1
+#define MAX_IO_HANDLES			1
+#endif
+
+#if USE_NVM
+/*
+ * The Flash memory is used to store TFTF data on Juno.
+ * However, it might contain other data that must not be overwritten.
+ * For example, when using the Trusted Firmware-A, the FIP image
+ * (containing the bootloader images) is also stored in Flash.
+ * Hence, consider the first 40MB of Flash as reserved for firmware usage.
+ * The TFTF can use the rest of the Flash memory.
+ */
+#define TFTF_NVM_OFFSET		0x2800000	/* 40MB */
+#define TFTF_NVM_SIZE		(FLASH_SIZE - TFTF_NVM_OFFSET)
+#else
+/*
+ * If you want to run without support for non-volatile memory (due to e.g.
+ * unavailability of a flash driver), DRAM can be used instead as workaround.
+ * The TFTF binary itself is loaded at 0xE0000000 so we have plenty of free
+ * memory at the beginning of the DRAM. Let's use the first 128MB.
+ *
+ * Please note that this won't be suitable for all test scenarios and
+ * for this reason some tests will be disabled in this configuration.
+ */
+#define TFTF_NVM_OFFSET		0x0
+#define TFTF_NVM_SIZE		0x8000000	/* 128 MB */
+#endif
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+#define MAX_XLAT_TABLES			5
+#define MAX_MMAP_REGIONS		16
+
+/*******************************************************************************
+ * Used to align variables on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interupts IDs
+ ******************************************************************************/
+#define IRQ_NS_SGI_0		0
+#define IRQ_NS_SGI_1		1
+#define IRQ_NS_SGI_2		2
+#define IRQ_NS_SGI_3		3
+#define IRQ_NS_SGI_4		4
+#define IRQ_NS_SGI_5		5
+#define IRQ_NS_SGI_6		6
+#define IRQ_NS_SGI_7		7
+
+#define PLAT_MAX_SPI_OFFSET_ID	220
+
+/* The IRQ generated by Ethernet controller */
+#define IRQ_ETHERNET	192
+
+#define IRQ_CNTPSIRQ1		92
+/* Per-CPU Hypervisor Timer Interrupt ID */
+#define IRQ_PCPU_HP_TIMER		26
+/* Per-CPU Non-Secure Timer Interrupt ID */
+#define IRQ_PCPU_NS_TIMER		30
+
+/*
+ * Times(in ms) used by test code for completion of different events.
+ * Suspend entry time for debug build is high due to the time taken
+ * by the VERBOSE/INFO prints. The value considers the worst case scenario
+ * where all CPUs are going and coming out of suspend continuously.
+ */
+#if DEBUG
+#define PLAT_SUSPEND_ENTRY_TIME		0x100
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME	0x200
+#else
+#define PLAT_SUSPEND_ENTRY_TIME		10
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME	20
+#endif
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/juno/juno32_tests_to_skip.txt b/plat/arm/board/juno/juno32_tests_to_skip.txt
new file mode 100644
index 0000000..078e363
--- /dev/null
+++ b/plat/arm/board/juno/juno32_tests_to_skip.txt
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# System suspend is not supported on AArch32 Juno.
+PSCI System Suspend Validation
+PSCI STAT/Stats test cases after system suspend
+IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND
+PSCI SYSTEM SUSPEND stress tests
diff --git a/plat/arm/board/juno/juno_def.h b/plat/arm/board/juno/juno_def.h
new file mode 100644
index 0000000..930332f
--- /dev/null
+++ b/plat/arm/board/juno/juno_def.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __JUNO_DEF_H__
+#define __JUNO_DEF_H__
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Juno memory map related constants
+ ******************************************************************************/
+/* First peripherals region excluding Non-Trusted ROM and Non-Trusted RAM */
+#define DEVICE0_BASE		0x20000000
+#define DEVICE0_SIZE		0x0e000000
+
+/* PCIe expansion region and 2nd peripherals region */
+#define DEVICE1_BASE		0x40000000
+#define DEVICE1_SIZE		0x40000000
+
+#define IOFPGA_PERIPHERALS_BASE	0x1c000000
+#define IOFPGA_PERIPHERALS_SIZE	0x3000000
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+#define GICD_BASE		0x2c010000
+#define GICC_BASE		0x2c02f000
+/* Juno doesn't support GIC Redistributor, it's a GICv3 feature */
+#define GICR_BASE		0
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+/* SoC UART0 */
+#define PL011_UART2_BASE		0x7ff80000
+#define PL011_UART2_CLK_IN_HZ		7273800
+
+#define PLAT_ARM_UART_BASE		PL011_UART2_BASE
+#define PLAT_ARM_UART_CLK_IN_HZ		PL011_UART2_CLK_IN_HZ
+
+/*******************************************************************************
+ * Motherboard timer related constants
+ ******************************************************************************/
+#define MB_TIMER1_BASE		0x1C120000
+#define MB_TIMER1_IRQ		198
+#define MB_TIMER1_FREQ		32000
+
+/*******************************************************************************
+ * Ethernet controller related constants
+ ******************************************************************************/
+#define ETHERNET_BASE			0x18000000
+#define ETHERNET_SIZE			0x04000000
+#define ETHERNET_IRQ_CFG_OFFSET		0x54
+#define ETHERNET_IRQ_CFG_VAL		0x11
+
+#endif /* __JUNO_DEF_H__ */
+
diff --git a/plat/arm/board/juno/juno_mem_prot.c b/plat/arm/board/juno/juno_mem_prot.c
new file mode 100644
index 0000000..f0e3506
--- /dev/null
+++ b/plat/arm/board/juno/juno_mem_prot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+#include <psci.h>
+#include <utils_def.h>
+#include <xlat_tables_v2.h>
+
+#define NS_IMAGE_OFFSET		TFTF_BASE
+#define NS_IMAGE_LIMIT		(NS_IMAGE_OFFSET + (32 << TWO_MB_SHIFT))
+
+static const mem_region_t juno_ram_ranges[] = {
+	{NS_IMAGE_LIMIT, 128 << TWO_MB_SHIFT},
+#ifdef AARCH64
+	{JUNO_DRAM2_BASE, 1 << ONE_GB_SHIFT},
+#endif
+};
+
+const mem_region_t *plat_get_prot_regions(int *nelem)
+{
+	*nelem = ARRAY_SIZE(juno_ram_ranges);
+	return juno_ram_ranges;
+}
diff --git a/plat/arm/board/juno/juno_pwr_state.c b/plat/arm/board/juno/juno_pwr_state.c
new file mode 100644
index 0000000..1e067c2
--- /dev/null
+++ b/plat/arm/board/juno/juno_pwr_state.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform.h>
+#include <psci.h>
+#include <stddef.h>
+
+/*
+ * State IDs for local power states on Juno.
+ */
+#define JUNO_RUN_STATE_ID		0 /* Valid for CPUs and Clusters */
+#define JUNO_RETENTION_STATE_ID		1 /* Valid for only CPUs */
+#define JUNO_OFF_STATE_ID		2 /* Valid for CPUs and Clusters */
+
+/*
+ * Suspend depth definitions for each power state
+ */
+typedef enum {
+	JUNO_RUN_DEPTH = 0,
+	JUNO_RETENTION_DEPTH,
+	JUNO_OFF_DEPTH,
+} suspend_depth_t;
+
+/* The state property array with details of idle state possible for the core */
+static const plat_state_prop_t core_state_prop[] = {
+	{JUNO_RETENTION_DEPTH, JUNO_RETENTION_STATE_ID, PSTATE_TYPE_STANDBY},
+	{JUNO_OFF_DEPTH, JUNO_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+/*
+ * The state property array with details of idle state possible
+ * for the cluster
+ */
+static const plat_state_prop_t cluster_state_prop[] = {
+	{JUNO_OFF_DEPTH, JUNO_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+/*
+ * The state property array with details of idle state possible
+ * for the system. Currently Juno does not support CPU SUSPEND
+ * at system power level.
+ */
+static const plat_state_prop_t system_state_prop[] = {
+	{JUNO_OFF_DEPTH, JUNO_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+const plat_state_prop_t *plat_get_state_prop(unsigned int level)
+{
+	switch (level) {
+	case MPIDR_AFFLVL0:
+		return core_state_prop;
+	case MPIDR_AFFLVL1:
+		return cluster_state_prop;
+	case MPIDR_AFFLVL2:
+		return system_state_prop;
+	default:
+		return NULL;
+	}
+}
diff --git a/plat/arm/board/juno/juno_timers.c b/plat/arm/board/juno/juno_timers.c
new file mode 100644
index 0000000..1d1ce48
--- /dev/null
+++ b/plat/arm/board/juno/juno_timers.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <sp804.h>
+#include <stddef.h>
+#include <timer.h>
+
+static const plat_timer_t plat_timers = {
+	.program = sp804_timer_program,
+	.cancel = sp804_timer_cancel,
+	.handler = sp804_timer_handler,
+	.timer_step_value = 2,
+	.timer_irq = MB_TIMER1_IRQ /* Motherboard SP804 timer1 IRQ */
+};
+
+int plat_initialise_timer_ops(const plat_timer_t **timer_ops)
+{
+	assert(timer_ops != NULL);
+	*timer_ops = &plat_timers;
+
+	/* Initialise the system timer */
+	sp804_timer_init(MB_TIMER1_BASE, MB_TIMER1_FREQ);
+
+	return 0;
+}
diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c
new file mode 100644
index 0000000..f7e0044
--- /dev/null
+++ b/plat/arm/board/juno/juno_topology.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <plat_topology.h>
+#include <platform_def.h>
+#include <stddef.h>
+#include <tftf_lib.h>
+
+static const struct {
+	unsigned cluster_id;
+	unsigned cpu_id;
+} juno_cores[] = {
+	/* Cortex-A53 Cluster: 4 cores*/
+	{ 1, 0 },
+	{ 1, 1 },
+	{ 1, 2 },
+	{ 1, 3 },
+	/* Cortex-A57 Cluster: 2 cores */
+	{ 0, 0 },
+	{ 0, 1 },
+};
+
+/*
+ * The Juno power domain tree descriptor. Juno implements a system
+ * power domain at the level 2. The first entry in the power domain descriptor
+ * specifies the number of power domains at the highest power level. For Juno
+ * this is 1 i.e. the number of system power domain.
+ */
+static const unsigned char juno_power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_SYSTEM_COUNT,
+	/* Number of children of root node */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first cluster */
+	PLATFORM_CLUSTER1_CORE_COUNT,
+	/* Number of children for the second cluster */
+	PLATFORM_CLUSTER0_CORE_COUNT
+};
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+	return juno_power_domain_tree_desc;
+}
+
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+	assert(core_pos < PLATFORM_CORE_COUNT);
+
+	return make_mpid(juno_cores[core_pos].cluster_id,
+					juno_cores[core_pos].cpu_id);
+}
diff --git a/plat/arm/board/juno/plat_setup.c b/plat/arm/board/juno/plat_setup.c
new file mode 100644
index 0000000..8792cb3
--- /dev/null
+++ b/plat/arm/board/juno/plat_setup.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arm_gic.h>
+#include <mmio.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <xlat_tables_v2.h>
+
+/*
+ * Table of regions to map using the MMU.
+ */
+#if IMAGE_NS_BL1U
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_NS),
+	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+	{0}
+};
+#elif IMAGE_NS_BL2U
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(IOFPGA_PERIPHERALS_BASE, IOFPGA_PERIPHERALS_SIZE,
+			MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+	{0}
+};
+#elif IMAGE_TFTF
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(ETHERNET_BASE, ETHERNET_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(IOFPGA_PERIPHERALS_BASE, IOFPGA_PERIPHERALS_SIZE,
+			MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+#if USE_NVM
+	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
+#endif
+	MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE, MT_MEMORY | MT_RW | MT_NS),
+	{0}
+};
+#endif	/* IMAGE_NS_BL1U */
+
+const mmap_region_t *tftf_platform_get_mmap(void)
+{
+	return mmap;
+}
+
+void tftf_platform_setup(void)
+{
+	arm_platform_setup();
+
+#if !IMAGE_NS_BL2U
+	/*
+	 * The Ethernet IRQ line is high by default which prevents Juno
+	 * from entering system suspend. Configure it to be low.
+	 *
+	 * Interrupts are disabled in NS_BL2U so there's no need to fix this
+	 * as we are not going to suspend the system.
+	 *
+	 * TODO: Currently this needs to be done in a loop for the write
+	 * to IRQ_CFG register to take effect. Need to find the reason for
+	 * this behavior.
+	 */
+	int val;
+
+	do {
+		mmio_write_32(ETHERNET_BASE + ETHERNET_IRQ_CFG_OFFSET,
+				ETHERNET_IRQ_CFG_VAL);
+
+		val = mmio_read_8(ETHERNET_BASE + ETHERNET_IRQ_CFG_OFFSET);
+	} while (val != ETHERNET_IRQ_CFG_VAL);
+#endif /* IMAGE_NS_BL2U */
+}
+
+void plat_arm_gic_init(void)
+{
+	arm_gic_init(GICC_BASE, GICD_BASE, GICR_BASE);
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
new file mode 100644
index 0000000..97172b5
--- /dev/null
+++ b/plat/arm/board/juno/platform.mk
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES	:=	-Iplat/arm/board/juno/include/
+
+PLAT_SOURCES	:=	drivers/arm/gic/arm_gic_v2.c			\
+			drivers/arm/gic/gic_v2.c			\
+			drivers/arm/sp805/sp805.c			\
+			drivers/arm/timer/private_timer.c		\
+			drivers/arm/timer/sp804.c			\
+			plat/arm/board/juno/${ARCH}/plat_helpers.S	\
+			plat/arm/board/juno/juno_pwr_state.c		\
+			plat/arm/board/juno/juno_timers.c		\
+			plat/arm/board/juno/juno_topology.c		\
+			plat/arm/board/juno/juno_mem_prot.c		\
+			plat/arm/board/juno/plat_setup.c
+
+TESTS_SOURCES	+=	tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
+
+# Some tests are not supported on Juno AArch32.
+ifeq (${ARCH},aarch32)
+PLAT_TESTS_SKIP_LIST	:=	plat/arm/board/juno/juno32_tests_to_skip.txt
+endif
+
+PLAT_SUPPORTS_NS_RESET	:=	1
+
+# Process PLAT_SUPPORTS_NS_RESET flag
+$(eval $(call assert_boolean,PLAT_SUPPORTS_NS_RESET))
+$(eval $(call add_define,TFTF_DEFINES,PLAT_SUPPORTS_NS_RESET))
+
+ifeq (${ARCH},aarch32)
+ifeq (${FIRMWARE_UPDATE},1)
+$(error "FIRMWARE_UPDATE is not supported on Juno aarch32")
+endif
+else
+FIRMWARE_UPDATE := 1
+endif
+
+include plat/arm/common/arm_common.mk
diff --git a/plat/arm/board/juno/tests.xml b/plat/arm/board/juno/tests.xml
new file mode 100644
index 0000000..8e679c3
--- /dev/null
+++ b/plat/arm/board/juno/tests.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2018, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<!-- External references to all individual tests files. -->
+<!DOCTYPE testsuites [
+  <!ENTITY tests-tftf-validation SYSTEM "../../../../tftf/tests/tests-tftf-validation.xml">
+  <!ENTITY tests-boot-req SYSTEM "../../../../tftf/tests/tests-boot-req.xml">
+  <!ENTITY tests-psci SYSTEM "../../../../tftf/tests/tests-psci.xml">
+  <!ENTITY tests-sdei SYSTEM "../../../../tftf/tests/tests-sdei.xml">
+  <!ENTITY tests-rt-instr SYSTEM "../../../../tftf/tests/tests-runtime-instrumentation.xml">
+  <!ENTITY tests-tsp SYSTEM "../../../../tftf/tests/tests-tsp.xml">
+  <!ENTITY tests-el3-pstate SYSTEM "../../../../tftf/tests/tests-el3-power-state.xml">
+  <!ENTITY tests-state-switch SYSTEM "../../../../tftf/tests/tests-arm-state-switch.xml">
+  <!ENTITY tests-cpu-extensions SYSTEM "../../../../tftf/tests/tests-cpu-extensions.xml">
+  <!ENTITY tests-performance SYSTEM "../../../../tftf/tests/tests-performance.xml">
+]>
+
+<testsuites>
+
+  &tests-tftf-validation;
+  &tests-boot-req;
+  &tests-psci;
+  &tests-sdei;
+  &tests-rt-instr;
+  &tests-tsp;
+  &tests-el3-pstate;
+  &tests-state-switch;
+  &tests-cpu-extensions;
+  &tests-performance;
+
+  <testsuite name="Juno - IRQ support in TSP" description="Test the normal IRQ preemption support in TSP.">
+    <testcase name="Juno - Multicore spurious interrupt test" function="test_juno_multicore_spurious_interrupt" />
+  </testsuite>
+
+</testsuites>
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
new file mode 100644
index 0000000..73b4690
--- /dev/null
+++ b/plat/arm/common/arm_common.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES	+=	-Iinclude/plat/arm/common/
+
+PLAT_SOURCES	+=	drivers/arm/gic/gic_common.c			\
+			drivers/arm/pl011/${ARCH}/pl011_console.S	\
+			plat/arm/common/arm_setup.c			\
+			plat/arm/common/arm_timers.c
+
+# Flash driver sources.
+PLAT_SOURCES	+=	drivers/io/io_storage.c				\
+			drivers/io/vexpress_nor/io_vexpress_nor_ops.c	\
+			drivers/io/vexpress_nor/io_vexpress_nor_hw.c	\
+			plat/arm/common/arm_io_storage.c
diff --git a/plat/arm/common/arm_fwu_io_storage.c b/plat/arm/common/arm_fwu_io_storage.c
new file mode 100644
index 0000000..184f2af
--- /dev/null
+++ b/plat/arm/common/arm_fwu_io_storage.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <image_loader.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <tftf_lib.h>
+
+/* May be overridden in specific ARM standard platform */
+#pragma weak plat_arm_fwu_io_setup
+
+/* IO devices */
+static const io_dev_connector_t *fwu_fip_dev_con;
+static uintptr_t fwu_fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fwu_fip_block_spec = {
+	.offset = PLAT_ARM_FWU_FIP_BASE,
+	.length = PLAT_ARM_FWU_FIP_SIZE
+};
+static const io_uuid_spec_t fwu_cert_uuid_spec = {
+	.uuid = UUID_FIRMWARE_UPDATE_FWU_CERT,
+};
+static const io_uuid_spec_t scp_bl2u_uuid_spec = {
+	.uuid = UUID_FIRMWARE_UPDATE_SCP_BL2U,
+};
+static const io_uuid_spec_t bl2u_uuid_spec = {
+	.uuid = UUID_FIRMWARE_UPDATE_BL2U,
+};
+static const io_uuid_spec_t ns_bl2u_uuid_spec = {
+	.uuid = UUID_FIRMWARE_UPDATE_NS_BL2U,
+};
+
+static int open_fwu_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+	[FWU_FIP_IMAGE_ID] = {
+		&memmap_dev_handle,
+		(uintptr_t)&fwu_fip_block_spec,
+		open_memmap
+	},
+	[FWU_CERT_ID] = {
+		&fwu_fip_dev_handle,
+		(uintptr_t)&fwu_cert_uuid_spec,
+		open_fwu_fip
+	},
+	[SCP_BL2U_IMAGE_ID] = {
+		&fwu_fip_dev_handle,
+		(uintptr_t)&scp_bl2u_uuid_spec,
+		open_fwu_fip
+	},
+	[BL2U_IMAGE_ID] = {
+		&fwu_fip_dev_handle,
+		(uintptr_t)&bl2u_uuid_spec,
+		open_fwu_fip
+	},
+	[NS_BL2U_IMAGE_ID] = {
+		&fwu_fip_dev_handle,
+		(uintptr_t)&ns_bl2u_uuid_spec,
+		open_fwu_fip
+	},
+};
+
+
+/* Weak definitions may be overridden in each specific platform */
+#pragma weak plat_get_image_source
+
+static int open_fwu_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fwu_fip_dev_handle,
+						(uintptr_t)FWU_FIP_IMAGE_ID);
+	if (result == IO_SUCCESS) {
+		result = io_open(fwu_fip_dev_handle, spec,
+						&local_image_handle);
+		if (result == IO_SUCCESS) {
+			VERBOSE("Using FIP\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+	if (result == IO_SUCCESS) {
+		result = io_open(memmap_dev_handle, spec, &local_image_handle);
+		if (result == IO_SUCCESS) {
+			VERBOSE("Using Memmap\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+
+void plat_arm_fwu_io_setup(void)
+{
+	int io_result;
+
+	io_result = register_io_dev_fip(&fwu_fip_dev_con);
+	assert(io_result == IO_SUCCESS);
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	assert(io_result == IO_SUCCESS);
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(fwu_fip_dev_con, (uintptr_t)NULL,
+				&fwu_fip_dev_handle);
+	assert(io_result == IO_SUCCESS);
+
+	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+				&memmap_dev_handle);
+	assert(io_result == IO_SUCCESS);
+
+	/* Ignore improbable errors in release builds */
+	(void)io_result;
+}
+
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int result = IO_FAIL;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	result = policy->check(policy->image_spec);
+	if (result == IO_SUCCESS) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return result;
+}
+
+void plat_fwu_io_setup(void)
+{
+	plat_arm_fwu_io_setup();
+}
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
new file mode 100644
index 0000000..d9d8a38
--- /dev/null
+++ b/plat/arm/common/arm_io_storage.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <io_driver.h>
+#include <io_nor_flash.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <tftf.h>
+#include "platform_def.h"
+
+#pragma weak plat_get_nvm_handle
+
+/* IO devices */
+static const io_dev_connector_t *flash_dev_con;
+static uintptr_t flash_dev_spec;
+static uintptr_t flash_init_params;
+static uintptr_t flash_dev_handle;
+static uintptr_t flash_handle;
+static unsigned int flash_init;
+
+static const io_nor_flash_spec_t flash_main_block_spec = {
+	.device_address = FLASH_BASE,
+	.region_address = FLASH_BASE,
+	.block_size = NOR_FLASH_BLOCK_SIZE,
+	.block_count = FLASH_SIZE / NOR_FLASH_BLOCK_SIZE
+};
+
+int arm_io_setup(void)
+{
+	int io_result;
+
+	io_result = register_io_dev_nor_flash(&flash_dev_con);
+	if (io_result != IO_SUCCESS)
+		return io_result;
+
+	io_result = io_dev_open(flash_dev_con, flash_dev_spec,
+				&flash_dev_handle);
+	if (io_result != IO_SUCCESS)
+		return io_result;
+
+	io_result = io_dev_init(flash_dev_handle, flash_init_params);
+	if (io_result != IO_SUCCESS)
+		return io_result;
+
+	io_result = io_open(flash_dev_handle,
+				(uintptr_t)&flash_main_block_spec,
+				 &flash_handle);
+
+	if (io_result == IO_SUCCESS)
+		flash_init = 1;
+	return io_result;
+}
+
+void plat_get_nvm_handle(uintptr_t *handle)
+{
+	assert(handle);
+	assert(flash_init);
+
+	*handle = flash_handle;
+}
+
diff --git a/plat/arm/common/arm_setup.c b/plat/arm/common/arm_setup.c
new file mode 100644
index 0000000..79f4631
--- /dev/null
+++ b/plat/arm/common/arm_setup.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arm_gic.h>
+#include <console.h>
+#include <debug.h>
+#include <io_storage.h>
+#include <pl011.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <platform_def.h>
+
+#pragma weak tftf_platform_setup
+
+void arm_platform_setup(void)
+{
+#if USE_NVM
+	int ret;
+
+	ret = arm_io_setup();
+	if (ret != IO_SUCCESS)
+		WARN("IO setup failed : 0x%x\n", ret);
+#endif
+
+#if IMAGE_NS_BL2U
+	/* NS_BL2U is not expecting interrupts. */
+	return;
+#endif
+
+	plat_arm_gic_init();
+
+	arm_gic_setup_global();
+	arm_gic_setup_local();
+}
+
+void tftf_platform_setup(void)
+{
+	arm_platform_setup();
+}
+
+void tftf_plat_arch_setup(void)
+{
+	tftf_plat_configure_mmu();
+}
+
+void tftf_early_platform_setup(void)
+{
+	console_init(PLAT_ARM_UART_BASE, PLAT_ARM_UART_CLK_IN_HZ,
+		     PL011_BAUDRATE);
+}
diff --git a/plat/arm/common/arm_timers.c b/plat/arm/common/arm_timers.c
new file mode 100644
index 0000000..c84cb84
--- /dev/null
+++ b/plat/arm/common/arm_timers.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform.h>
+#include <stddef.h>
+#include <system_timer.h>
+#include <timer.h>
+
+#pragma weak plat_initialise_timer_ops
+
+static const plat_timer_t plat_timers = {
+	.program = program_systimer,
+	.cancel = cancel_systimer,
+	.handler = handler_systimer,
+	.timer_step_value = 2,
+	.timer_irq = IRQ_CNTPSIRQ1
+};
+
+int plat_initialise_timer_ops(const plat_timer_t **timer_ops)
+{
+	assert(timer_ops != NULL);
+	*timer_ops = &plat_timers;
+
+	/* Initialise the system timer */
+	init_systimer(SYS_CNT_BASE1);
+
+	return 0;
+}
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
new file mode 100644
index 0000000..1a57418
--- /dev/null
+++ b/plat/common/aarch32/platform_helpers.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <pl011.h>
+#include <platform_def.h>
+
+	.weak	platform_get_core_pos
+	.weak	plat_crash_console_init
+	.weak	plat_crash_console_putc
+	.weak	plat_crash_console_flush
+
+	/* -----------------------------------------------------
+	 *  int platform_get_core_pos(u_register_t mpidr);
+	 *  With this function: CorePos = (ClusterId * 4) +
+	 *				  CoreId
+	 * -----------------------------------------------------
+	 */
+func platform_get_core_pos
+	and	r1, r0, #MPIDR_CPU_MASK
+	and	r0, r0, #MPIDR_CLUSTER_MASK
+	add	r0, r1, r0, LSR #6
+	bx	lr
+endfunc platform_get_core_pos
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0 - x4
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	ldr	r0, =PLAT_ARM_UART_BASE
+	ldr	r1, =PLAT_ARM_UART_CLK_IN_HZ
+	ldr	r2, =PL011_BAUDRATE
+	b	console_core_init
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	ldr	r1, =PLAT_ARM_UART_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0 - r1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	ldr	r1, =PLAT_ARM_UART_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/common/aarch32/platform_mp_stack.S b/plat/common/aarch32/platform_mp_stack.S
new file mode 100644
index 0000000..c4ea895
--- /dev/null
+++ b/plat/common/aarch32/platform_mp_stack.S
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+	.local	pcpu_dv_mem_stack
+	.local	platform_normal_stacks
+	.weak	platform_set_stack
+	.weak	platform_get_stack
+	.weak	platform_set_coherent_stack
+
+	/* -----------------------------------------------------
+	 * void platform_set_coherent_stack (unsigned long mpidr)
+	 *
+	 * For a given CPU, this function sets the stack pointer
+	 * to a stack allocated in device memory. This stack can
+	 * be used by C code which enables/disables the SCTLR.M
+	 * SCTLR.C bit e.g. while powering down a cpu
+	 * -----------------------------------------------------
+	 */
+func platform_set_coherent_stack
+	mov	r9, lr
+	get_mp_stack pcpu_dv_mem_stack, PCPU_DV_MEM_STACK_SIZE
+	mov	sp, r0
+	bx	r9
+endfunc platform_set_coherent_stack
+
+	/* -----------------------------------------------------
+	 * uintptr_t platform_get_stack (u_register_t mpidr)
+	 *
+	 * For a given CPU, this function returns the stack
+	 * pointer for a stack allocated in normal memory.
+	 * -----------------------------------------------------
+	 */
+func platform_get_stack
+	mov	r9, lr
+	get_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	bx	r9
+endfunc	platform_get_stack
+
+	/* -----------------------------------------------------
+	 * void platform_set_stack (u_register_t mpidr)
+	 *
+	 * For a given CPU, this function sets the stack
+	 * pointer to a stack allocated in normal memory.
+	 * -----------------------------------------------------
+	 */
+func platform_set_stack
+	mov	r9, lr
+	get_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	mov	sp, r0
+	bx	r9
+endfunc platform_set_stack
+
+	/* -----------------------------------------------------
+	 * Per-cpu stacks in normal memory.
+	 * Used for C code during runtime execution (when coherent
+	 * stacks are not required).
+	 * Each cpu gets a stack of PLATFORM_STACK_SIZE bytes.
+	 * -----------------------------------------------------
+	 */
+declare_stack platform_normal_stacks, tftf_normal_stacks, \
+		PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT
+
+	/* -----------------------------------------------------
+	 * Per-cpu stacks in device memory.
+	 * Used for C code just before power down or right after
+	 * power up when the MMU or caches need to be turned on
+	 * or off.
+	 * Each cpu gets a stack of PCPU_DV_MEM_STACK_SIZE bytes.
+	 * -----------------------------------------------------
+	 */
+declare_stack pcpu_dv_mem_stack, tftf_coherent_stacks, \
+		PCPU_DV_MEM_STACK_SIZE, PLATFORM_CORE_COUNT
diff --git a/plat/common/aarch32/platform_up_stack.S b/plat/common/aarch32/platform_up_stack.S
new file mode 100644
index 0000000..e67ded8
--- /dev/null
+++ b/plat/common/aarch32/platform_up_stack.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+	.local	platform_normal_stacks
+	.globl	platform_set_stack
+	.globl	platform_get_stack
+
+	/* -----------------------------------------------------
+	 * unsigned long platform_get_stack (unsigned long)
+	 *
+	 * For cold-boot images, only the primary CPU needs a
+	 * stack. This function returns the stack pointer for a
+	 * stack allocated in device memory.
+	 * -----------------------------------------------------
+	 */
+func platform_get_stack
+	get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	bx	lr
+endfunc	platform_get_stack
+
+	/* -----------------------------------------------------
+	 * void platform_set_stack (unsigned long)
+	 *
+	 * For cold-boot images, only the primary CPU needs a
+	 * stack. This function sets the stack pointer to a stack
+	 * allocated in normal memory.
+	 * -----------------------------------------------------
+	 */
+func platform_set_stack
+	get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	mov	sp, r0
+	bx	lr
+endfunc platform_set_stack
+
+	/* -----------------------------------------------------
+	 * Single cpu stack in normal memory.
+	 * Used for C code during boot, PLATFORM_STACK_SIZE bytes
+	 * are allocated
+	 * -----------------------------------------------------
+	 */
+declare_stack platform_normal_stacks, ns_bl_normal_stacks, \
+		PLATFORM_STACK_SIZE, 1
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
new file mode 100644
index 0000000..2161638
--- /dev/null
+++ b/plat/common/aarch64/platform_helpers.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <pl011.h>
+#include <platform_def.h>
+
+	.weak	platform_get_core_pos
+	.weak	plat_crash_console_init
+	.weak	plat_crash_console_putc
+	.weak	plat_crash_console_flush
+
+	/* -----------------------------------------------------
+	 *  int platform_get_core_pos(int mpidr);
+	 *  With this function: CorePos = (ClusterId * 4) +
+	 *  				  CoreId
+	 * -----------------------------------------------------
+	 */
+func platform_get_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc platform_get_core_pos
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0 - x4
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, PLAT_ARM_UART_BASE
+	mov_imm	x1, PLAT_ARM_UART_CLK_IN_HZ
+	mov_imm	x2, PL011_BAUDRATE
+	b	console_core_init
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, PLAT_ARM_UART_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0 - r1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x1, PLAT_ARM_UART_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S
new file mode 100644
index 0000000..fe167cc
--- /dev/null
+++ b/plat/common/aarch64/platform_mp_stack.S
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+	.local	pcpu_dv_mem_stack
+	.local	platform_normal_stacks
+	.weak	platform_set_stack
+	.weak	platform_get_stack
+	.weak	platform_set_coherent_stack
+
+
+	/* -----------------------------------------------------
+	 * void platform_set_coherent_stack (unsigned long mpidr)
+	 *
+	 * For a given CPU, this function sets the stack pointer
+	 * to a stack allocated in device memory. This stack can
+	 * be used by C code which enables/disables the SCTLR.M
+	 * SCTLR.C bit e.g. while powering down a cpu
+	 * -----------------------------------------------------
+	 */
+func platform_set_coherent_stack
+	mov x9, x30 // lr
+	get_mp_stack pcpu_dv_mem_stack, PCPU_DV_MEM_STACK_SIZE
+	mov sp, x0
+	ret x9
+endfunc platform_set_coherent_stack
+
+	/* -----------------------------------------------------
+	 * unsigned long platform_get_stack (unsigned long mpidr)
+	 *
+	 * For a given CPU, this function returns the stack
+	 * pointer for a stack allocated in device memory.
+	 * -----------------------------------------------------
+	 */
+func platform_get_stack
+	mov x10, x30 // lr
+	get_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	ret x10
+endfunc platform_get_stack
+
+	/* -----------------------------------------------------
+	 * void platform_set_stack (unsigned long mpidr)
+	 *
+	 * For a given CPU, this function sets the stack pointer
+	 * to a stack allocated in normal memory.
+	 * -----------------------------------------------------
+	 */
+func platform_set_stack
+	mov x9, x30 // lr
+	bl  platform_get_stack
+	mov sp, x0
+	ret x9
+endfunc platform_set_stack
+
+	/* -----------------------------------------------------
+	 * Per-cpu stacks in normal memory.
+	 * Used for C code during runtime execution (when coherent
+	 * stacks are not required).
+	 * Each cpu gets a stack of PLATFORM_STACK_SIZE bytes.
+	 * -----------------------------------------------------
+	 */
+declare_stack platform_normal_stacks, tftf_normal_stacks, \
+		PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT
+
+	/* -----------------------------------------------------
+	 * Per-cpu stacks in device memory.
+	 * Used for C code just before power down or right after
+	 * power up when the MMU or caches need to be turned on
+	 * or off.
+	 * Each cpu gets a stack of PCPU_DV_MEM_STACK_SIZE bytes.
+	 * -----------------------------------------------------
+	 */
+declare_stack pcpu_dv_mem_stack, tftf_coherent_stacks, \
+		PCPU_DV_MEM_STACK_SIZE, PLATFORM_CORE_COUNT
diff --git a/plat/common/aarch64/platform_up_stack.S b/plat/common/aarch64/platform_up_stack.S
new file mode 100644
index 0000000..c61b472
--- /dev/null
+++ b/plat/common/aarch64/platform_up_stack.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+	.local	platform_normal_stacks
+	.globl	platform_set_stack
+	.globl	platform_get_stack
+
+	/* -----------------------------------------------------
+	 * unsigned long platform_get_stack (unsigned long)
+	 *
+	 * For cold-boot images, only the primary CPU needs a
+	 * stack. This function returns the stack pointer for a
+	 * stack allocated in device memory.
+	 * -----------------------------------------------------
+	 */
+func platform_get_stack
+	get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	ret
+endfunc platform_get_stack
+
+	/* -----------------------------------------------------
+	 * void platform_set_stack (unsigned long)
+	 *
+	 * For cold-boot images, only the primary CPU needs a
+	 * stack. This function sets the stack pointer to a stack
+	 * allocated in normal memory.
+	 * -----------------------------------------------------
+	 */
+func platform_set_stack
+	get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+	mov sp, x0
+	ret
+endfunc platform_set_stack
+
+	/* -----------------------------------------------------
+	 * Single cpu stack in normal memory.
+	 * Used for C code during boot, PLATFORM_STACK_SIZE bytes
+	 * are allocated
+	 * -----------------------------------------------------
+	 */
+declare_stack platform_normal_stacks, ns_bl_normal_stacks, \
+		PLATFORM_STACK_SIZE, 1
diff --git a/plat/common/fwu_nvm_accessors.c b/plat/common/fwu_nvm_accessors.c
new file mode 100644
index 0000000..5b32151
--- /dev/null
+++ b/plat/common/fwu_nvm_accessors.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <fwu_nvm.h>
+#include <io_fip.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <status.h>
+#include <string.h>
+#include <uuid_utils.h>
+
+
+STATUS fwu_nvm_write(unsigned long long offset, const void *buffer, size_t size)
+{
+	uintptr_t nvm_handle;
+	int ret;
+	size_t length_write;
+
+	if (offset + size > FLASH_SIZE)
+		return STATUS_OUT_OF_RESOURCES;
+
+	/* Obtain a handle to the NVM by querying the platfom layer */
+	plat_get_nvm_handle(&nvm_handle);
+
+	/* Seek to the given offset. */
+	ret = io_seek(nvm_handle, IO_SEEK_SET, offset);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+	/* Write to the given offset. */
+	ret = io_write(nvm_handle, (const uintptr_t)buffer,
+		size, &length_write);
+	if ((ret != IO_SUCCESS) || (size != length_write))
+		return STATUS_FAIL;
+
+	return STATUS_SUCCESS;
+}
+
+STATUS fwu_nvm_read(unsigned long long offset, void *buffer, size_t size)
+{
+	uintptr_t nvm_handle;
+	int ret;
+	size_t length_read;
+
+	if (offset + size > FLASH_SIZE)
+		return STATUS_OUT_OF_RESOURCES;
+
+	/* Obtain a handle to the NVM by querying the platform layer */
+	plat_get_nvm_handle(&nvm_handle);
+
+	/* Seek to the given offset. */
+	ret = io_seek(nvm_handle, IO_SEEK_SET, offset);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+	/* Read from the given offset. */
+	ret = io_read(nvm_handle, (const uintptr_t)buffer,
+		size, &length_read);
+	if ((ret != IO_SUCCESS) || (size != length_read))
+		return STATUS_FAIL;
+
+	return STATUS_SUCCESS;
+}
+
+
+STATUS fwu_update_fip(unsigned long fip_addr)
+{
+	uintptr_t nvm_handle;
+	int ret;
+	size_t bytes;
+	int fip_size;
+	unsigned int fip_read;
+	fip_toc_header_t *toc_header;
+	fip_toc_entry_t *toc_entry;
+
+	/* Obtain a handle to the NVM by querying the platform layer */
+	plat_get_nvm_handle(&nvm_handle);
+
+#if FWU_BL_TEST
+	/* Read the address of backup fip.bin for Firmware Update. */
+	ret = io_seek(nvm_handle, IO_SEEK_SET,
+			FWU_TFTF_TESTCASE_BUFFER_OFFSET);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+	ret = io_read(nvm_handle, (const uintptr_t)&fip_addr,
+			sizeof(bytes), &bytes);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+#endif /* FWU_BL_TEST */
+
+	/* If the new FIP address is 0 it means no update. */
+	if (fip_addr == 0)
+		return STATUS_SUCCESS;
+
+	/* Set the ToC Header at the base of the buffer */
+	toc_header = (fip_toc_header_t *)fip_addr;
+
+	/* Check if this FIP is Valid */
+	if ((toc_header->name != TOC_HEADER_NAME) ||
+		(toc_header->serial_number == 0))
+		return STATUS_LOAD_ERROR;
+
+	/* Get to the last NULL TOC entry */
+	toc_entry = (fip_toc_entry_t *)(toc_header + 1);
+	while (!is_uuid_null(&toc_entry->uuid))
+		toc_entry++;
+
+	/* get the total size of this FIP */
+	fip_size = (int)toc_entry->offset_address;
+
+	/* Copy the new FIP in DDR. */
+	memcpy((void *)FIP_IMAGE_TMP_DDR_ADDRESS, (void *)fip_addr, fip_size);
+
+	/* Update the FIP */
+	ret = io_seek(nvm_handle, IO_SEEK_SET, 0);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+	ret = io_write(nvm_handle, (const uintptr_t)FIP_IMAGE_TMP_DDR_ADDRESS,
+			fip_size, &bytes);
+	if ((ret != IO_SUCCESS) || fip_size != bytes)
+		return STATUS_LOAD_ERROR;
+
+	/* Read the TOC header after update. */
+	ret = io_seek(nvm_handle, IO_SEEK_SET, 0);
+	if (ret != IO_SUCCESS)
+		return STATUS_LOAD_ERROR;
+
+	ret = io_read(nvm_handle, (const uintptr_t)&fip_read,
+		sizeof(bytes), &bytes);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+	/* Check if this FIP is Valid */
+	if (fip_read != TOC_HEADER_NAME)
+		return STATUS_LOAD_ERROR;
+
+#if FWU_BL_TEST
+	unsigned int done_flag = FIP_IMAGE_UPDATE_DONE_FLAG;
+	/* Update the TFTF test case buffer with DONE flag */
+	ret = io_seek(nvm_handle, IO_SEEK_SET,
+			FWU_TFTF_TESTCASE_BUFFER_OFFSET);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+	ret = io_write(nvm_handle, (const uintptr_t)&done_flag,
+			4, &bytes);
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+#endif /* FWU_BL_TEST */
+
+	INFO("FWU Image update success\n");
+
+	return STATUS_SUCCESS;
+}
+
diff --git a/plat/common/image_loader.c b/plat/common/image_loader.c
new file mode 100644
index 0000000..9b27f6f
--- /dev/null
+++ b/plat/common/image_loader.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <image_loader.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <tftf_lib.h>
+
+unsigned long get_image_offset(unsigned int image_id)
+{
+	uintptr_t dev_handle;
+	uintptr_t image_handle;
+	uintptr_t image_spec;
+	unsigned long img_offset;
+	int io_result;
+	io_entity_t *entity;
+	fip_file_state_t *fp;
+
+	/* Obtain a reference to the image by querying the platform layer */
+	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
+	if (io_result != IO_SUCCESS) {
+		WARN("Failed to obtain reference to image id=%u (%i)\n",
+			image_id, io_result);
+		return 0;
+	}
+
+	/* Attempt to access the image */
+	io_result = io_open(dev_handle, image_spec, &image_handle);
+	if (io_result != IO_SUCCESS) {
+		WARN("Failed to access image id=%u (%i)\n",
+			image_id, io_result);
+		return 0;
+	}
+
+	entity = (io_entity_t *)image_handle;
+
+	fp = (fip_file_state_t *)entity->info;
+	img_offset = PLAT_ARM_FWU_FIP_BASE + fp->entry.offset_address;
+
+	(void)io_close(image_handle);
+	(void)io_dev_close(dev_handle);
+
+	return img_offset;
+}
+
+
+unsigned long get_image_size(unsigned int image_id)
+{
+	uintptr_t dev_handle;
+	uintptr_t image_handle;
+	uintptr_t image_spec;
+	size_t image_size;
+	int io_result;
+
+	/* Obtain a reference to the image by querying the platform layer */
+	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
+	if (io_result != IO_SUCCESS) {
+		WARN("Failed to obtain reference to image id=%u (%i)\n",
+			image_id, io_result);
+		return 0;
+	}
+
+	/* Attempt to access the image */
+	io_result = io_open(dev_handle, image_spec, &image_handle);
+	if (io_result != IO_SUCCESS) {
+		WARN("Failed to access image id=%u (%i)\n",
+			image_id, io_result);
+		return 0;
+	}
+
+	/* Find the size of the image */
+	io_result = io_size(image_handle, &image_size);
+	if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+		WARN("Failed to determine the size of the image id=%u (%i)\n",
+			image_id, io_result);
+	}
+	io_result = io_close(image_handle);
+	io_result = io_dev_close(dev_handle);
+
+	return image_size;
+}
+
+
+int load_image(unsigned int image_id, uintptr_t image_base)
+{
+	uintptr_t dev_handle;
+	uintptr_t image_handle;
+	uintptr_t image_spec;
+	size_t image_size;
+	size_t bytes_read;
+	int io_result;
+
+	/* Obtain a reference to the image by querying the platform layer */
+	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
+	if (io_result != IO_SUCCESS) {
+		WARN("Failed to obtain reference to image id=%u (%i)\n",
+			image_id, io_result);
+		return io_result;
+	}
+
+	/* Attempt to access the image */
+	io_result = io_open(dev_handle, image_spec, &image_handle);
+	if (io_result != IO_SUCCESS) {
+		WARN("Failed to access image id=%u (%i)\n",
+			image_id, io_result);
+		return io_result;
+	}
+
+	INFO("Loading image id=%u at address %p\n", image_id, (void *)image_base);
+
+	/* Find the size of the image */
+	io_result = io_size(image_handle, &image_size);
+	if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+		WARN("Failed to determine the size of the image id=%u (%i)\n",
+			image_id, io_result);
+		goto exit;
+	}
+
+	/* Load the image now */
+	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
+	if ((io_result != IO_SUCCESS) || (bytes_read < image_size)) {
+		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
+		goto exit;
+	}
+
+	/*
+	 * File has been successfully loaded.
+	 * Flush the image so that the next EL can see it.
+	 */
+	flush_dcache_range(image_base, image_size);
+
+	INFO("Image id=%u loaded: %p - %p\n", image_id, (void *)image_base,
+	     (void *)(image_base + image_size - 1));
+
+exit:
+	io_close(image_handle);
+	io_dev_close(dev_handle);
+	return io_result;
+}
+
+
+int load_partial_image(unsigned int image_id,
+		uintptr_t image_base,
+		size_t image_size,
+		unsigned int is_last_block)
+{
+	static uintptr_t dev_handle;
+	static uintptr_t image_handle;
+	uintptr_t image_spec;
+	size_t bytes_read;
+	int io_result;
+
+	if (!image_handle) {
+		/* Obtain a reference to the image by querying the platform layer */
+		io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
+		if (io_result != IO_SUCCESS) {
+			WARN("Failed to obtain reference to image id=%u (%i)\n",
+				image_id, io_result);
+			return io_result;
+		}
+
+		/* Attempt to access the image */
+		io_result = io_open(dev_handle, image_spec, &image_handle);
+		if (io_result != IO_SUCCESS) {
+			WARN("Failed to access image id=%u (%i)\n",
+				image_id, io_result);
+			return io_result;
+		}
+	}
+
+	INFO("Loading image id=%u at address %p\n", image_id, (void *)image_base);
+
+	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
+	if ((io_result != IO_SUCCESS) || (bytes_read < image_size)) {
+		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
+		is_last_block = 0;
+		goto exit;
+	}
+
+	/*
+	 * File has been successfully loaded.
+	 * Flush the image so that the next EL can see it.
+	 */
+	flush_dcache_range(image_base, image_size);
+
+	INFO("Image id=%u loaded: %p - %p\n", image_id, (void *)image_base,
+	     (void *)(image_base + image_size - 1));
+
+exit:
+
+	if (is_last_block == 0) {
+		io_close(image_handle);
+		io_dev_close(dev_handle);
+		image_handle = 0;
+	}
+	return io_result;
+}
+
diff --git a/plat/common/plat_common.c b/plat/common/plat_common.c
new file mode 100644
index 0000000..5713871
--- /dev/null
+++ b/plat/common/plat_common.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <console.h>
+#include <debug.h>
+#include <platform.h>
+#include <sp805.h>
+#include <xlat_tables_v2.h>
+
+/*
+ * The following platform functions are all weakly defined. They provide typical
+ * implementations that may be re-used by multiple platforms but may also be
+ * overridden by a platform if required.
+ */
+
+#pragma weak tftf_platform_end
+#pragma weak tftf_platform_watchdog_set
+#pragma weak tftf_platform_watchdog_reset
+#pragma weak tftf_plat_configure_mmu
+#pragma weak tftf_plat_enable_mmu
+#pragma weak tftf_plat_reset
+#pragma weak plat_get_prot_regions
+
+#if IMAGE_TFTF
+
+#define IMAGE_RO_BASE	TFTF_BASE
+IMPORT_SYM(uintptr_t,	 __RO_END__,		IMAGE_RO_END);
+
+#define IMAGE_RW_BASE	IMAGE_RO_END
+IMPORT_SYM(uintptr_t,	__TFTF_END__,		IMAGE_RW_END);
+
+IMPORT_SYM(uintptr_t,	__COHERENT_RAM_START__,	COHERENT_RAM_START);
+IMPORT_SYM(uintptr_t,	__COHERENT_RAM_END__,	COHERENT_RAM_END);
+
+#elif IMAGE_NS_BL1U
+
+IMPORT_SYM(uintptr_t,	 __RO_END__,		IMAGE_RO_END_UNALIGNED);
+#define IMAGE_RO_BASE	NS_BL1U_RO_BASE
+#define IMAGE_RO_END	round_up(IMAGE_RO_END_UNALIGNED, PAGE_SIZE)
+
+#define IMAGE_RW_BASE	NS_BL1U_RW_BASE
+IMPORT_SYM(uintptr_t,	__NS_BL1U_RAM_END__,	IMAGE_RW_END);
+
+#elif IMAGE_NS_BL2U
+
+#define IMAGE_RO_BASE	NS_BL2U_BASE
+IMPORT_SYM(uintptr_t,	 __RO_END__,		IMAGE_RO_END);
+
+#define IMAGE_RW_BASE	IMAGE_RO_END
+IMPORT_SYM(uintptr_t,	__NS_BL2U_END__,	IMAGE_RW_END_UNALIGNED);
+#define IMAGE_RW_END	round_up(IMAGE_RW_END_UNALIGNED, PAGE_SIZE)
+
+#endif
+
+void tftf_platform_end(void)
+{
+	/*
+	 * Send EOT (End Of Transmission) on the UART.
+	 * This can be used to shutdown a software model.
+	 */
+	static const char ascii_eot = 4;
+	console_putc(ascii_eot);
+}
+
+void tftf_platform_watchdog_set(void)
+{
+	/* Placeholder function which should be redefined by each platform */
+}
+
+void tftf_platform_watchdog_reset(void)
+{
+	/* Placeholder function which should be redefined by each platform */
+}
+
+void tftf_plat_configure_mmu(void)
+{
+	/* RO data + Code */
+	mmap_add_region(IMAGE_RO_BASE, IMAGE_RO_BASE,
+			IMAGE_RO_END - IMAGE_RO_BASE, MT_CODE);
+
+	/* Data + BSS */
+	mmap_add_region(IMAGE_RW_BASE, IMAGE_RW_BASE,
+			IMAGE_RW_END - IMAGE_RW_BASE, MT_RW_DATA);
+
+#if IMAGE_TFTF
+	mmap_add_region(COHERENT_RAM_START, COHERENT_RAM_START,
+			COHERENT_RAM_END - COHERENT_RAM_START,
+			MT_DEVICE | MT_RW | MT_NS);
+#endif
+
+	mmap_add(tftf_platform_get_mmap());
+	init_xlat_tables();
+
+	tftf_plat_enable_mmu();
+}
+
+void tftf_plat_enable_mmu(void)
+{
+#ifndef AARCH32
+	if (IS_IN_EL1())
+		enable_mmu_el1(0);
+	else if (IS_IN_EL2())
+		enable_mmu_el2(0);
+	else
+		panic();
+#else
+	if (IS_IN_HYP())
+		enable_mmu_hyp(0);
+	else
+		enable_mmu_svc_mon(0);
+#endif
+}
+
+void tftf_plat_reset(void)
+{
+	/*
+	 * SP805 peripheral interrupt is not serviced in TFTF. The reset signal
+	 * generated by it is used to reset the platform.
+	 */
+	sp805_wdog_start(1);
+
+	/*
+	 * Reset might take some execution cycles, Depending on the ratio between
+	 * CPU clock frequency and Watchdog clock frequency
+	 */
+	while (1)
+		;
+}
+
+const mem_region_t *plat_get_prot_regions(int *nelem)
+{
+	*nelem = 0;
+	return NULL;
+}
diff --git a/plat/common/plat_state_id.c b/plat/common/plat_state_id.c
new file mode 100644
index 0000000..ce43ba4
--- /dev/null
+++ b/plat/common/plat_state_id.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <tftf.h>
+
+static unsigned int pstate_initialized;
+
+/*
+ * Stores pointer to the state_prop_t for all implemented levels
+ */
+static const plat_state_prop_t *plat_state_ptr[PLAT_MAX_PWR_LEVEL + 1];
+
+/*
+ * Saves number of implemented power states per level
+ */
+static unsigned int power_states_per_level[PLAT_MAX_PWR_LEVEL + 1];
+
+void tftf_init_pstate_framework(void)
+{
+	int i, j;
+
+	if (pstate_initialized)
+		return;
+
+	/* Detect the PSCI power state format used. */
+	tftf_detect_psci_pstate_format();
+
+	/*
+	 * Get and save the pointers to plat_state_prop_t values for all
+	 * levels. Also, store the max number of local states possible for
+	 * each level in power_states_per_level.
+	 */
+	for (i = 0; i <= PLAT_MAX_PWR_LEVEL; i++) {
+		plat_state_ptr[i] = plat_get_state_prop(i);
+		assert(plat_state_ptr[i]);
+
+		for (j = 0; (plat_state_ptr[i]+j)->state_ID != 0; j++)
+			;
+
+		power_states_per_level[i] = j;
+	}
+
+	pstate_initialized = 1;
+}
+
+void tftf_set_next_state_id_idx(unsigned int power_level,
+					unsigned int pstate_id_idx[])
+{
+	unsigned int i;
+#if ENABLE_ASSERTIONS
+	/* Verify that this is a valid power level. */
+	assert(power_level <= PLAT_MAX_PWR_LEVEL);
+
+	/*
+	 * Verify if a level has PWR_STATE_INIT_INDEX index, all higher levels
+	 * have to be in PWR_STATE_INIT_INDEX. Not needed to check the top
+	 * power level in the outer loop.
+	 */
+	for (i = 0; i < power_level; i++) {
+		if (pstate_id_idx[i] == PWR_STATE_INIT_INDEX) {
+			for ( ; i <= power_level; i++)
+				assert(pstate_id_idx[i] == PWR_STATE_INIT_INDEX);
+		}
+	}
+#endif
+
+	/* Increment the pstate_id_idx starting from the lowest power level */
+	for (i = 0; i <= power_level; i++) {
+		pstate_id_idx[i]++;
+
+		/*
+		 * Wraparound index if the maximum power states available for
+		 * that level is reached and proceed to next level.
+		 */
+		if (pstate_id_idx[i] == power_states_per_level[i])
+			pstate_id_idx[i] = 0;
+		else
+			break;
+	}
+
+	/*
+	 * Check if the requested power level has wrapped around. If it has,
+	 * reset pstate_id_idx.
+	 */
+	if (i > power_level) {
+		for (i = 0; i <= power_level; i++)
+			pstate_id_idx[i] = PWR_STATE_INIT_INDEX;
+	}
+}
+
+void tftf_set_deepest_pstate_idx(unsigned int power_level,
+				unsigned int pstate_id_idx[])
+{
+	int i;
+
+	/* Verify that this is a valid power level. */
+	assert(power_level <= PLAT_MAX_PWR_LEVEL);
+
+	/*
+	 * Assign the highest pstate_id_idx starting from the lowest power
+	 * level
+	 */
+	for (i = 0; i <= power_level; i++)
+		pstate_id_idx[i] = power_states_per_level[i] - 1;
+}
+
+
+int tftf_get_pstate_vars(unsigned int *test_power_level,
+				unsigned int *test_suspend_type,
+				unsigned int *suspend_state_id,
+				unsigned int pstate_id_idx[])
+{
+	unsigned int i;
+	int state_id = 0;
+	int suspend_type;
+	int suspend_depth;
+	int psci_ret = PSCI_E_SUCCESS;
+	const plat_state_prop_t *local_state;
+
+	/* Atleast one entry should be valid to generate correct power state params */
+	assert(pstate_id_idx[0] != PWR_STATE_INIT_INDEX &&
+			pstate_id_idx[0] <= power_states_per_level[0]);
+
+	suspend_depth = (plat_state_ptr[0] + pstate_id_idx[0])->suspend_depth;
+	suspend_type = (plat_state_ptr[0] + pstate_id_idx[0])->is_pwrdown;
+
+	for (i = 0; i <= PLAT_MAX_PWR_LEVEL; i++) {
+
+		/* Reached all levels with the valid power index values */
+		if (pstate_id_idx[i] == PWR_STATE_INIT_INDEX)
+			break;
+
+		assert(pstate_id_idx[i] <= power_states_per_level[i]);
+
+		local_state = plat_state_ptr[i] + pstate_id_idx[i];
+		state_id |= (local_state->state_ID << i * PLAT_LOCAL_PSTATE_WIDTH);
+
+		if (local_state->is_pwrdown > suspend_type)
+			suspend_type = local_state->is_pwrdown;
+
+		if (local_state->suspend_depth > suspend_depth)
+			psci_ret = PSCI_E_INVALID_PARAMS;
+		else
+			suspend_depth = local_state->suspend_depth;
+	}
+
+	*test_suspend_type = suspend_type;
+	*suspend_state_id = state_id;
+	*test_power_level = --i;
+
+	return psci_ret;
+}
+
+void tftf_set_next_local_state_id_idx(unsigned int power_level,
+						unsigned int pstate_id_idx[])
+{
+	assert(power_level <= PLAT_MAX_PWR_LEVEL);
+
+	if (pstate_id_idx[power_level] + 1 >= power_states_per_level[power_level]) {
+		pstate_id_idx[power_level] = PWR_STATE_INIT_INDEX;
+		return;
+	}
+
+	pstate_id_idx[power_level]++;
+}
diff --git a/plat/common/plat_topology.c b/plat/common/plat_topology.c
new file mode 100644
index 0000000..a7920c3
--- /dev/null
+++ b/plat/common/plat_topology.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <debug.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <stdlib.h>
+
+#define CPU_INDEX_IS_VALID(_cpu_idx)	\
+	(((_cpu_idx) - tftf_pwr_domain_start_idx[0]) < PLATFORM_CORE_COUNT)
+
+#define IS_A_CPU_NODE(_cpu_idx)		(tftf_pd_nodes[(_cpu_idx)].level == 0)
+
+#define CPU_NODE_IS_VALID(_cpu_node)	\
+	(CPU_INDEX_IS_VALID(_cpu_node) && IS_A_CPU_NODE(_cpu_node))
+
+/*
+ * Global variable to check that the platform topology is not queried until it
+ * has been setup.
+ */
+static unsigned int topology_setup_done;
+
+/*
+ * Store the start indices of power domains at various levels. This array makes it
+ * easier to traverse the topology tree if the power domain level is known.
+ */
+unsigned int tftf_pwr_domain_start_idx[PLATFORM_MAX_AFFLVL + 1];
+
+/* The grand array to store the platform power domain topology */
+tftf_pwr_domain_node_t tftf_pd_nodes[PLATFORM_NUM_AFFS];
+
+#if DEBUG
+/*
+ * Debug function to display the platform topology.
+ * Does not print absent affinity instances.
+ */
+static void dump_topology(void)
+{
+	unsigned int cluster_idx, cpu_idx, count;
+
+	NOTICE("Platform topology:\n");
+
+	NOTICE("  %u cluster(s)\n", tftf_get_total_clusters_count());
+	NOTICE("  %u CPU(s) (total)\n\n", tftf_get_total_cpus_count());
+
+	for (cluster_idx = PWR_DOMAIN_INIT;
+	     cluster_idx = tftf_get_next_peer_domain(cluster_idx, 1),
+	     cluster_idx != PWR_DOMAIN_INIT;) {
+		count = 0;
+		for (cpu_idx = tftf_pd_nodes[cluster_idx].cpu_start_node;
+		     cpu_idx < (tftf_pd_nodes[cluster_idx].cpu_start_node +
+				     tftf_pd_nodes[cluster_idx].ncpus);
+		     cpu_idx++) {
+			if (tftf_pd_nodes[cpu_idx].is_present)
+				count++;
+		}
+		NOTICE("  Cluster #%u   [%u CPUs]\n",
+				cluster_idx - tftf_pwr_domain_start_idx[1],
+				count);
+		for (cpu_idx = PWR_DOMAIN_INIT;
+		     cpu_idx = tftf_get_next_cpu_in_pwr_domain(cluster_idx, cpu_idx),
+		     cpu_idx != PWR_DOMAIN_INIT;) {
+			NOTICE("    CPU #%u   [MPID: 0x%x]\n",
+					cpu_idx - tftf_pwr_domain_start_idx[0],
+					tftf_get_mpidr_from_node(cpu_idx));
+		}
+	}
+	NOTICE("\n");
+}
+#endif
+
+unsigned int tftf_get_total_aff_count(unsigned int aff_lvl)
+{
+	unsigned int count = 0;
+	unsigned int node_idx;
+
+	assert(topology_setup_done == 1);
+
+	if (aff_lvl > PLATFORM_MAX_AFFLVL)
+		return count;
+
+	node_idx = tftf_pwr_domain_start_idx[aff_lvl];
+
+	while (tftf_pd_nodes[node_idx].level == aff_lvl) {
+		if (tftf_pd_nodes[node_idx].is_present)
+			count++;
+		node_idx++;
+	}
+
+	return count;
+}
+
+unsigned int tftf_get_next_peer_domain(unsigned int pwr_domain_idx,
+				      unsigned int pwr_lvl)
+{
+	assert(topology_setup_done == 1);
+
+	assert(pwr_lvl <= PLATFORM_MAX_AFFLVL);
+
+	if (pwr_domain_idx == PWR_DOMAIN_INIT) {
+		pwr_domain_idx = tftf_pwr_domain_start_idx[pwr_lvl];
+		if (tftf_pd_nodes[pwr_domain_idx].is_present)
+			return pwr_domain_idx;
+	}
+
+	assert(pwr_domain_idx < PLATFORM_NUM_AFFS &&
+			tftf_pd_nodes[pwr_domain_idx].level == pwr_lvl);
+
+	for (++pwr_domain_idx; (pwr_domain_idx < PLATFORM_NUM_AFFS)
+				&& (tftf_pd_nodes[pwr_domain_idx].level == pwr_lvl);
+				pwr_domain_idx++) {
+		if (tftf_pd_nodes[pwr_domain_idx].is_present)
+			return pwr_domain_idx;
+	}
+
+	return PWR_DOMAIN_INIT;
+}
+
+unsigned int tftf_get_next_cpu_in_pwr_domain(unsigned int pwr_domain_idx,
+				      unsigned int cpu_node)
+{
+	unsigned int cpu_end_node;
+
+	assert(topology_setup_done == 1);
+	assert(pwr_domain_idx != PWR_DOMAIN_INIT
+			&& pwr_domain_idx < PLATFORM_NUM_AFFS);
+
+	if (cpu_node == PWR_DOMAIN_INIT) {
+		cpu_node = tftf_pd_nodes[pwr_domain_idx].cpu_start_node;
+		if (tftf_pd_nodes[cpu_node].is_present)
+			return cpu_node;
+	}
+
+	assert(CPU_NODE_IS_VALID(cpu_node));
+
+	cpu_end_node = tftf_pd_nodes[pwr_domain_idx].cpu_start_node
+			+ tftf_pd_nodes[pwr_domain_idx].ncpus - 1;
+
+	assert(cpu_end_node < PLATFORM_NUM_AFFS);
+
+	for (++cpu_node; cpu_node <= cpu_end_node; cpu_node++) {
+		if (tftf_pd_nodes[cpu_node].is_present)
+			return cpu_node;
+	}
+
+	return PWR_DOMAIN_INIT;
+}
+
+/*
+ * Helper function to get the parent nodes of a particular CPU power
+ * domain.
+ */
+static void get_parent_pwr_domain_nodes(unsigned int cpu_node,
+				      unsigned int end_lvl,
+				      unsigned int node_index[])
+{
+	unsigned int parent_node = tftf_pd_nodes[cpu_node].parent_node;
+	unsigned int i;
+
+	for (i = 1; i <= end_lvl; i++) {
+		node_index[i - 1] = parent_node;
+		parent_node = tftf_pd_nodes[parent_node].parent_node;
+	}
+}
+
+/*******************************************************************************
+ * This function updates cpu_start_node and ncpus field for each of the nodes
+ * in tftf_pd_nodes[]. It does so by comparing the parent nodes of each of
+ * the CPUs and check whether they match with the parent of the previous
+ * CPU. The basic assumption for this work is that children of the same parent
+ * are allocated adjacent indices. The platform should ensure this through
+ * proper mapping of the CPUs to indices via platform_get_core_pos() API.
+ *
+ * It also updates the 'is_present' field for non-cpu power domains. It does
+ * this by checking the 'is_present' field of the child cpu nodes and updates
+ * it if any of the child cpu nodes are present.
+ *******************************************************************************/
+static void update_pwrlvl_limits(void)
+{
+	int cpu_id, j, is_present;
+	unsigned int nodes_idx[PLATFORM_MAX_AFFLVL] = {-1};
+	unsigned int temp_index[PLATFORM_MAX_AFFLVL];
+
+	unsigned int cpu_node_offset = tftf_pwr_domain_start_idx[0];
+
+	for (cpu_id = 0; cpu_id < PLATFORM_CORE_COUNT; cpu_id++) {
+		get_parent_pwr_domain_nodes(cpu_id + cpu_node_offset,
+						PLATFORM_MAX_AFFLVL,
+						temp_index);
+		is_present = tftf_pd_nodes[cpu_id + cpu_node_offset].is_present;
+
+		for (j = PLATFORM_MAX_AFFLVL - 1; j >= 0; j--) {
+			if (temp_index[j] != nodes_idx[j]) {
+				nodes_idx[j] = temp_index[j];
+				tftf_pd_nodes[nodes_idx[j]].cpu_start_node
+							= cpu_id + cpu_node_offset;
+				if (!tftf_pd_nodes[nodes_idx[j]].is_present)
+					tftf_pd_nodes[nodes_idx[j]].is_present = is_present;
+			}
+			tftf_pd_nodes[nodes_idx[j]].ncpus++;
+		}
+	}
+}
+
+/******************************************************************************
+ * This function populates the power domain topology array 'tftf_pd_nodes[]'
+ * based on the power domain description retrieved from the platform layer.
+ * It also updates the start index of each power domain level in
+ * tftf_pwr_domain_start_idx[]. The uninitialized fields of 'tftf_pd_nodes[]'
+ * for the non CPU power domain will be initialized in update_pwrlvl_limits().
+ *****************************************************************************/
+static void populate_power_domain_tree(void)
+{
+	unsigned int i, j = 0, num_nodes_at_lvl = 1, num_nodes_at_next_lvl,
+			node_index = 0, parent_idx = 0, num_children;
+	int num_level = PLATFORM_MAX_AFFLVL;
+	const unsigned char *plat_array;
+
+	plat_array = tftf_plat_get_pwr_domain_tree_desc();
+
+	/*
+	 * For each level the inputs are:
+	 * - number of nodes at this level in plat_array i.e. num_nodes_at_lvl
+	 *   This is the sum of values of nodes at the parent level.
+	 * - Index of first entry at this level in the plat_array i.e.
+	 *   parent_idx.
+	 * - Index of first free entry in tftf_pd_nodes[].
+	 */
+	while (num_level >= 0) {
+		num_nodes_at_next_lvl = 0;
+
+		/* Store the start index for every level */
+		tftf_pwr_domain_start_idx[num_level] = node_index;
+
+		/*
+		 * For each entry (parent node) at this level in the plat_array:
+		 * - Find the number of children
+		 * - Allocate a node in a power domain array for each child
+		 * - Set the parent of the child to the parent_node_index - 1
+		 * - Increment parent_node_index to point to the next parent
+		 * - Accumulate the number of children at next level.
+		 */
+		for (i = 0; i < num_nodes_at_lvl; i++) {
+			assert(parent_idx <=
+				PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT);
+			num_children = plat_array[parent_idx];
+
+			for (j = node_index;
+				j < node_index + num_children; j++) {
+				/* Initialize the power domain node */
+				tftf_pd_nodes[j].parent_node = parent_idx - 1;
+				tftf_pd_nodes[j].level = num_level;
+
+				/* Additional initializations for CPU power domains */
+				if (num_level == 0) {
+					/* Calculate the cpu id from node index */
+					int cpu_id =  j - tftf_pwr_domain_start_idx[0];
+
+					assert(cpu_id < PLATFORM_CORE_COUNT);
+
+					/* Set the mpidr of cpu node */
+					tftf_pd_nodes[j].mpidr =
+						tftf_plat_get_mpidr(cpu_id);
+					if (tftf_pd_nodes[j].mpidr != INVALID_MPID)
+						tftf_pd_nodes[j].is_present = 1;
+
+					tftf_pd_nodes[j].cpu_start_node = j;
+					tftf_pd_nodes[j].ncpus = 1;
+				}
+			}
+			node_index = j;
+			num_nodes_at_next_lvl += num_children;
+			parent_idx++;
+		}
+
+		num_nodes_at_lvl = num_nodes_at_next_lvl;
+		num_level--;
+	}
+
+	/* Validate the sanity of array exported by the platform */
+	assert(j == PLATFORM_NUM_AFFS);
+}
+
+
+void tftf_init_topology(void)
+{
+	populate_power_domain_tree();
+	update_pwrlvl_limits();
+	topology_setup_done = 1;
+#if DEBUG
+	dump_topology();
+#endif
+}
+
+unsigned int tftf_topology_next_cpu(unsigned int cpu_node)
+{
+	assert(topology_setup_done == 1);
+
+	if (cpu_node == PWR_DOMAIN_INIT) {
+		cpu_node = tftf_pwr_domain_start_idx[0];
+		if (tftf_pd_nodes[cpu_node].is_present)
+			return cpu_node;
+	}
+
+	assert(CPU_NODE_IS_VALID(cpu_node));
+
+	for (++cpu_node; cpu_node < PLATFORM_NUM_AFFS; cpu_node++) {
+		if (tftf_pd_nodes[cpu_node].is_present)
+			return cpu_node;
+	}
+
+	return PWR_DOMAIN_INIT;
+}
+
+
+unsigned int tftf_get_mpidr_from_node(unsigned int cpu_node)
+{
+	assert(topology_setup_done == 1);
+
+	assert(CPU_NODE_IS_VALID(cpu_node));
+
+	if (tftf_pd_nodes[cpu_node].is_present)
+		return tftf_pd_nodes[cpu_node].mpidr;
+
+	return INVALID_MPID;
+}
+
+unsigned int tftf_find_any_cpu_other_than(unsigned exclude_mpid)
+{
+	unsigned int cpu_node, mpidr;
+
+	for_each_cpu(cpu_node) {
+		mpidr = tftf_get_mpidr_from_node(cpu_node);
+		if (mpidr != exclude_mpid)
+			return mpidr;
+	}
+
+	return INVALID_MPID;
+}
+
+unsigned int tftf_find_random_cpu_other_than(unsigned int exclude_mpid)
+{
+	unsigned int cpu_node, mpidr;
+	unsigned int possible_cpus_cnt = 0;
+	unsigned int possible_cpus[PLATFORM_CORE_COUNT];
+
+	for_each_cpu(cpu_node) {
+		mpidr = tftf_get_mpidr_from_node(cpu_node);
+		if (mpidr != exclude_mpid)
+			possible_cpus[possible_cpus_cnt++] = mpidr;
+	}
+
+	if (possible_cpus_cnt == 0)
+		return INVALID_MPID;
+
+	return possible_cpus[rand() % possible_cpus_cnt];
+}
diff --git a/plat/common/tftf_nvm_accessors.c b/plat/common/tftf_nvm_accessors.c
new file mode 100644
index 0000000..f6d0031
--- /dev/null
+++ b/plat/common/tftf_nvm_accessors.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <spinlock.h>
+#include <status.h>
+#include <string.h>
+#include <tftf_lib.h>
+
+#if USE_NVM
+/* Used to serialize write operations from different CPU's */
+static spinlock_t flash_access_lock;
+#endif
+
+STATUS tftf_nvm_write(unsigned long long offset, const void *buffer, size_t size)
+{
+#if USE_NVM
+	int ret;
+	uintptr_t nvm_handle;
+	size_t length_written;
+#endif
+
+	if (offset + size > TFTF_NVM_SIZE)
+		return STATUS_OUT_OF_RESOURCES;
+
+#if USE_NVM
+	/* Obtain a handle to the NVM by querying the platfom layer */
+	plat_get_nvm_handle(&nvm_handle);
+
+	spin_lock(&flash_access_lock);
+
+	ret = io_seek(nvm_handle, IO_SEEK_SET,
+					offset + TFTF_NVM_OFFSET);
+	if (ret != IO_SUCCESS)
+		goto fail;
+
+	ret = io_write(nvm_handle, (const uintptr_t)buffer, size,
+							 &length_written);
+	if (ret != IO_SUCCESS)
+		goto fail;
+
+	assert(length_written == size);
+fail:
+	spin_unlock(&flash_access_lock);
+
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+
+#else
+	uintptr_t addr = DRAM_BASE + TFTF_NVM_OFFSET + offset;
+	memcpy((void *)addr, buffer, size);
+#endif
+
+	return STATUS_SUCCESS;
+}
+
+STATUS tftf_nvm_read(unsigned long long offset, void *buffer, size_t size)
+{
+#if USE_NVM
+	int ret;
+	uintptr_t nvm_handle;
+	size_t length_read;
+#endif
+
+	if (offset + size > TFTF_NVM_SIZE)
+		return STATUS_OUT_OF_RESOURCES;
+
+#if USE_NVM
+	/* Obtain a handle to the NVM by querying the platfom layer */
+	plat_get_nvm_handle(&nvm_handle);
+
+	spin_lock(&flash_access_lock);
+
+	ret = io_seek(nvm_handle, IO_SEEK_SET, TFTF_NVM_OFFSET + offset);
+	if (ret != IO_SUCCESS)
+		goto fail;
+
+	ret = io_read(nvm_handle, (uintptr_t)buffer, size, &length_read);
+	if (ret != IO_SUCCESS)
+		goto fail;
+
+	assert(length_read == size);
+fail:
+	spin_unlock(&flash_access_lock);
+
+	if (ret != IO_SUCCESS)
+		return STATUS_FAIL;
+#else
+	uintptr_t addr = DRAM_BASE + TFTF_NVM_OFFSET + offset;
+	memcpy(buffer, (void *)addr, size);
+#endif
+
+	return STATUS_SUCCESS;
+}
+