Merge pull request #1089 from Leo-Yan/hikey_enable_debug_module

Hikey: enable CPU debug module
diff --git a/Makefile b/Makefile
index 0a64514..267fc82 100644
--- a/Makefile
+++ b/Makefile
@@ -305,6 +305,12 @@
                 $(warning "PRELOADED_BL33_BASE and EL3_PAYLOAD_BASE are \
                 incompatible build options. EL3_PAYLOAD_BASE has priority.")
         endif
+        ifneq (${GENERATE_COT},0)
+                $(error "GENERATE_COT and EL3_PAYLOAD_BASE are incompatible build options.")
+        endif
+        ifneq (${TRUSTED_BOARD_BOOT},0)
+                $(error "TRUSTED_BOARD_BOOT and EL3_PAYLOAD_BASE are incompatible build options.")
+        endif
 endif
 
 ifeq (${NEED_BL33},yes)
diff --git a/bl32/sp_min/sp_min_main.c b/bl32/sp_min/sp_min_main.c
index 06b0f33..4e8e685 100644
--- a/bl32/sp_min/sp_min_main.c
+++ b/bl32/sp_min/sp_min_main.c
@@ -196,6 +196,8 @@
 void sp_min_warm_boot(void)
 {
 	smc_ctx_t *next_smc_ctx;
+	cpu_context_t *ctx = cm_get_context(NON_SECURE);
+	u_register_t ns_sctlr;
 
 	psci_warmboot_entrypoint();
 
@@ -206,6 +208,16 @@
 
 	copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
 			next_smc_ctx);
+
+	/* Temporarily set the NS bit to access NS SCTLR */
+	write_scr(read_scr() | SCR_NS_BIT);
+	isb();
+	ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR);
+	write_sctlr(ns_sctlr);
+	isb();
+
+	write_scr(read_scr() & ~SCR_NS_BIT);
+	isb();
 }
 
 #if SP_MIN_WITH_SECURE_FIQ
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index 5738927..f74b459 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -21,6 +21,7 @@
 
 -  `Cortex-A53 MPCore Software Developers Errata Notice`_
 -  `Cortex-A57 MPCore Software Developers Errata Notice`_
+-  `Cortex-A72 MPCore Software Developers Errata Notice`_
 
 The errata workarounds are implemented for a particular revision or a set of
 processor revisions. This is checked by the reset handler at runtime. Each
@@ -30,7 +31,8 @@
 is for example ``A57`` for the ``Cortex_A57`` CPU.
 
 Refer to the section *CPU errata status reporting* in
-`Firmware Design guide`_ for information on to write errata workaround functions.
+`Firmware Design guide`_ for information on how to write errata workaround
+functions.
 
 All workarounds are disabled by default. The platform is responsible for
 enabling these workarounds according to its requirement by defining the
@@ -98,6 +100,15 @@
 -  ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57
    CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
 
+-  ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57
+   CPU. This needs to be enabled only for revision <= r1p3 of the CPU.
+
+
+For Cortex-A72, following errata build flags are defined :
+
+-  ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72
+   CPU. This needs to be enabled only for revision <= r0p3 of the CPU.
+
 CPU Specific optimizations
 --------------------------
 
@@ -131,7 +142,8 @@
 
 *Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.*
 
-.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html
+.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf
 .. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/cortex_a57_mpcore_software_developers_errata_notice.pdf
+.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html
 .. _Firmware Design guide: firmware-design.rst
 .. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf
diff --git a/docs/plat/hikey.rst b/docs/plat/hikey.rst
index 125941f..e194ede 100644
--- a/docs/plat/hikey.rst
+++ b/docs/plat/hikey.rst
@@ -126,7 +126,7 @@
 
    And you could open the console remotely, too.
 
-Flush images in recovery mode
+Flash images in recovery mode
 -----------------------------
 
 -  Make sure Pin3-Pin4 on J15 are connected for recovery mode. Then power on HiKey.
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 043af63..1ff080d 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -405,6 +405,13 @@
    AArch64 and facilitates the loading of ``SP_MIN`` and BL33 as AArch32 executable
    images.
 
+-  ``KEY_ALG``: This build flag enables the user to select the algorithm to be
+   used for generating the PKCS keys and subsequent signing of the certificate.
+   It accepts 3 values viz ``rsa``, ``rsa_1_5``, ``ecdsa``. The ``rsa_1_5`` is
+   the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR compliant and is
+   retained only for compatibility. The default value of this flag is ``rsa``
+   which is the TBBR compliant PKCS#1 RSA 2.1 scheme.
+
 -  ``LDFLAGS``: Extra user options appended to the linkers' command line in
    addition to the one set by the build system.
 
@@ -669,9 +676,10 @@
    SCP\_BL2U to the FIP and FWU\_FIP respectively, and enables them to be loaded
    during boot. Default is 1.
 
--  ``CSS_USE_SCMI_DRIVER``: Boolean flag which selects SCMI driver instead of
-   SCPI driver for communicating with the SCP during power management operations.
-   If this option is set to 1, then SCMI driver will be used. Default is 0.
+-  ``CSS_USE_SCMI_SDS_DRIVER``: Boolean flag which selects SCMI/SDS drivers
+   instead of SCPI/BOM driver for communicating with the SCP during power
+   management operations and for SCP RAM Firmware transfer. If this option
+   is set to 1, then SCMI/SDS drivers will be used. Default is 0.
 
 ARM FVP platform specific build options
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1585,15 +1593,15 @@
     -C cluster0.NUM_CORES=4                                      \
     -C cluster1.NUM_CORES=4                                      \
     -C cache_state_modelled=1                                    \
-    -C cluster0.cpu0.RVBAR=0x04023000                            \
-    -C cluster0.cpu1.RVBAR=0x04023000                            \
-    -C cluster0.cpu2.RVBAR=0x04023000                            \
-    -C cluster0.cpu3.RVBAR=0x04023000                            \
-    -C cluster1.cpu0.RVBAR=0x04023000                            \
-    -C cluster1.cpu1.RVBAR=0x04023000                            \
-    -C cluster1.cpu2.RVBAR=0x04023000                            \
-    -C cluster1.cpu3.RVBAR=0x04023000                            \
-    --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04023000    \
+    -C cluster0.cpu0.RVBAR=0x04020000                            \
+    -C cluster0.cpu1.RVBAR=0x04020000                            \
+    -C cluster0.cpu2.RVBAR=0x04020000                            \
+    -C cluster0.cpu3.RVBAR=0x04020000                            \
+    -C cluster1.cpu0.RVBAR=0x04020000                            \
+    -C cluster1.cpu1.RVBAR=0x04020000                            \
+    -C cluster1.cpu2.RVBAR=0x04020000                            \
+    -C cluster1.cpu3.RVBAR=0x04020000                            \
+    --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04020000    \
     --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000    \
     --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000    \
     --data cluster0.cpu0="<path-to>/<fdt>"@0x82000000            \
@@ -1670,15 +1678,15 @@
     -C bp.secure_memory=1                                        \
     -C bp.tzc_400.diagnostics=1                                  \
     -C cache_state_modelled=1                                    \
-    -C cluster0.cpu0.RVBARADDR=0x04023000                        \
-    -C cluster0.cpu1.RVBARADDR=0x04023000                        \
-    -C cluster0.cpu2.RVBARADDR=0x04023000                        \
-    -C cluster0.cpu3.RVBARADDR=0x04023000                        \
-    -C cluster1.cpu0.RVBARADDR=0x04023000                        \
-    -C cluster1.cpu1.RVBARADDR=0x04023000                        \
-    -C cluster1.cpu2.RVBARADDR=0x04023000                        \
-    -C cluster1.cpu3.RVBARADDR=0x04023000                        \
-    --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04023000    \
+    -C cluster0.cpu0.RVBARADDR=0x04020000                        \
+    -C cluster0.cpu1.RVBARADDR=0x04020000                        \
+    -C cluster0.cpu2.RVBARADDR=0x04020000                        \
+    -C cluster0.cpu3.RVBARADDR=0x04020000                        \
+    -C cluster1.cpu0.RVBARADDR=0x04020000                        \
+    -C cluster1.cpu1.RVBARADDR=0x04020000                        \
+    -C cluster1.cpu2.RVBARADDR=0x04020000                        \
+    -C cluster1.cpu3.RVBARADDR=0x04020000                        \
+    --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04020000    \
     --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000    \
     --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000    \
     --data cluster0.cpu0="<path-to>/<fdt>"@0x82000000            \
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk
index cb81d4d..21b857b 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.mk
+++ b/drivers/auth/mbedtls/mbedtls_crypto.mk
@@ -7,9 +7,15 @@
 include drivers/auth/mbedtls/mbedtls_common.mk
 
 # The platform may define the variable 'TF_MBEDTLS_KEY_ALG' to select the key
-# algorithm to use. Default algorithm is RSA.
+# algorithm to use. If the variable is not defined, select it based on algorithm
+# used for key generation `KEY_ALG`. If `KEY_ALG` is not defined or is
+# defined to `rsa`/`rsa_1_5`, then set the variable to `rsa`.
 ifeq (${TF_MBEDTLS_KEY_ALG},)
-    TF_MBEDTLS_KEY_ALG		:=	rsa
+    ifeq (${KEY_ALG}, ecdsa)
+        TF_MBEDTLS_KEY_ALG		:=	ecdsa
+    else
+        TF_MBEDTLS_KEY_ALG		:=	rsa
+    endif
 endif
 
 # If MBEDTLS_KEY_ALG build flag is defined use it to set TF_MBEDTLS_KEY_ALG for
diff --git a/include/common/aarch32/asm_macros.S b/include/common/aarch32/asm_macros.S
index 3adcbf5..f573744 100644
--- a/include/common/aarch32/asm_macros.S
+++ b/include/common/aarch32/asm_macros.S
@@ -80,6 +80,19 @@
 	.endm
 
 	/*
+	 * Helper macro to generate the best mov/movw/movt combinations
+	 * according to the value to be moved.
+	 */
+	.macro mov_imm _reg, _val
+		.if ((\_val) & 0xffff0000) == 0
+			mov	\_reg, #(\_val)
+		.else
+			movw	\_reg, #((\_val) & 0xffff)
+			movt	\_reg, #((\_val) >> 16)
+		.endif
+	.endm
+
+	/*
 	 * Macro to mark instances where we're jumping to a function and don't
 	 * expect a return. To provide the function being jumped to with
 	 * additional information, we use 'bl' instruction to jump rather than
diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S
index 528e29e..6d6989c 100644
--- a/include/common/aarch64/asm_macros.S
+++ b/include/common/aarch64/asm_macros.S
@@ -65,8 +65,12 @@
 	 * security, robustness and potentially facilitates debugging.
 	 */
 	.macro vector_entry  label
+	.cfi_sections .debug_frame
 	.section .vectors, "ax"
 	.align 7, 0
+	.type \label, %function
+	.func \label
+	.cfi_startproc
 	\label:
 	.endm
 
@@ -77,6 +81,8 @@
 	 * vector entry as the parameter
 	 */
 	.macro check_vector_size since
+	  .endfunc
+	  .cfi_endproc
 	  .if (. - \since) > (32 * 4)
 	    .error "Vector exceeds 32 instructions"
 	  .endif
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index 56163c8..5fbb83a 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -7,6 +7,8 @@
 #ifndef __ARCH_H__
 #define __ARCH_H__
 
+#include <utils_def.h>
+
 /*******************************************************************************
  * MIDR bit definitions
  ******************************************************************************/
@@ -459,4 +461,53 @@
 #define ICC_ASGI1R_EL1_64	p15, 1, c12
 #define ICC_SGI0R_EL1_64	p15, 2, c12
 
+/*******************************************************************************
+ * Definitions of MAIR encodings for device and normal memory
+ ******************************************************************************/
+/*
+ * MAIR encodings for device memory attributes.
+ */
+#define MAIR_DEV_nGnRnE		U(0x0)
+#define MAIR_DEV_nGnRE		U(0x4)
+#define MAIR_DEV_nGRE		U(0x8)
+#define MAIR_DEV_GRE		U(0xc)
+
+/*
+ * MAIR encodings for normal memory attributes.
+ *
+ * Cache Policy
+ *  WT:	 Write Through
+ *  WB:	 Write Back
+ *  NC:	 Non-Cacheable
+ *
+ * Transient Hint
+ *  NTR: Non-Transient
+ *  TR:	 Transient
+ *
+ * Allocation Policy
+ *  RA:	 Read Allocate
+ *  WA:	 Write Allocate
+ *  RWA: Read and Write Allocate
+ *  NA:	 No Allocation
+ */
+#define MAIR_NORM_WT_TR_WA	U(0x1)
+#define MAIR_NORM_WT_TR_RA	U(0x2)
+#define MAIR_NORM_WT_TR_RWA	U(0x3)
+#define MAIR_NORM_NC		U(0x4)
+#define MAIR_NORM_WB_TR_WA	U(0x5)
+#define MAIR_NORM_WB_TR_RA	U(0x6)
+#define MAIR_NORM_WB_TR_RWA	U(0x7)
+#define MAIR_NORM_WT_NTR_NA	U(0x8)
+#define MAIR_NORM_WT_NTR_WA	U(0x9)
+#define MAIR_NORM_WT_NTR_RA	U(0xa)
+#define MAIR_NORM_WT_NTR_RWA	U(0xb)
+#define MAIR_NORM_WB_NTR_NA	U(0xc)
+#define MAIR_NORM_WB_NTR_WA	U(0xd)
+#define MAIR_NORM_WB_NTR_RA	U(0xe)
+#define MAIR_NORM_WB_NTR_RWA	U(0xf)
+
+#define MAIR_NORM_OUTER_SHIFT	4
+
+#define MAKE_MAIR_NORMAL_MEMORY(inner, outer)	((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 2adf769..e38a530 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -504,4 +504,53 @@
 #define PMCR_EL0_N_MASK		U(0x1f)
 #define PMCR_EL0_N_BITS		(PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT)
 
+/*******************************************************************************
+ * Definitions of MAIR encodings for device and normal memory
+ ******************************************************************************/
+/*
+ * MAIR encodings for device memory attributes.
+ */
+#define MAIR_DEV_nGnRnE		ULL(0x0)
+#define MAIR_DEV_nGnRE		ULL(0x4)
+#define MAIR_DEV_nGRE		ULL(0x8)
+#define MAIR_DEV_GRE		ULL(0xc)
+
+/*
+ * MAIR encodings for normal memory attributes.
+ *
+ * Cache Policy
+ *  WT:	 Write Through
+ *  WB:	 Write Back
+ *  NC:	 Non-Cacheable
+ *
+ * Transient Hint
+ *  NTR: Non-Transient
+ *  TR:	 Transient
+ *
+ * Allocation Policy
+ *  RA:	 Read Allocate
+ *  WA:	 Write Allocate
+ *  RWA: Read and Write Allocate
+ *  NA:	 No Allocation
+ */
+#define MAIR_NORM_WT_TR_WA	ULL(0x1)
+#define MAIR_NORM_WT_TR_RA	ULL(0x2)
+#define MAIR_NORM_WT_TR_RWA	ULL(0x3)
+#define MAIR_NORM_NC		ULL(0x4)
+#define MAIR_NORM_WB_TR_WA	ULL(0x5)
+#define MAIR_NORM_WB_TR_RA	ULL(0x6)
+#define MAIR_NORM_WB_TR_RWA	ULL(0x7)
+#define MAIR_NORM_WT_NTR_NA	ULL(0x8)
+#define MAIR_NORM_WT_NTR_WA	ULL(0x9)
+#define MAIR_NORM_WT_NTR_RA	ULL(0xa)
+#define MAIR_NORM_WT_NTR_RWA	ULL(0xb)
+#define MAIR_NORM_WB_NTR_NA	ULL(0xc)
+#define MAIR_NORM_WB_NTR_WA	ULL(0xd)
+#define MAIR_NORM_WB_NTR_RA	ULL(0xe)
+#define MAIR_NORM_WB_NTR_RWA	ULL(0xf)
+
+#define MAIR_NORM_OUTER_SHIFT	4
+
+#define MAKE_MAIR_NORMAL_MEMORY(inner, outer)	((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/cpus/aarch32/cortex_a57.h b/include/lib/cpus/aarch32/cortex_a57.h
index d3ae5b9..3fac9c7 100644
--- a/include/lib/cpus/aarch32/cortex_a57.h
+++ b/include/lib/cpus/aarch32/cortex_a57.h
@@ -49,6 +49,7 @@
 #define CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA		(ULL(1) << 49)
 #define CORTEX_A57_CPUACTLR_DCC_AS_DCCI			(ULL(1) << 44)
 #define CORTEX_A57_CPUACTLR_FORCE_FPSCR_FLUSH		(ULL(1) << 38)
+#define CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH		(ULL(1) << 32)
 #define CORTEX_A57_CPUACTLR_DIS_STREAMING		(ULL(3) << 27)
 #define CORTEX_A57_CPUACTLR_DIS_L1_STREAMING		(ULL(3) << 25)
 #define CORTEX_A57_CPUACTLR_DIS_INDIRECT_PREDICTOR	(ULL(1) << 4)
diff --git a/include/lib/cpus/aarch32/cortex_a72.h b/include/lib/cpus/aarch32/cortex_a72.h
index 306253d..f7da1f0 100644
--- a/include/lib/cpus/aarch32/cortex_a72.h
+++ b/include/lib/cpus/aarch32/cortex_a72.h
@@ -34,6 +34,7 @@
 #define CORTEX_A72_CPUACTLR_DISABLE_L1_DCACHE_HW_PFTCH	(ULL(1) << 56)
 #define CORTEX_A72_CPUACTLR_NO_ALLOC_WBWA		(ULL(1) << 49)
 #define CORTEX_A72_CPUACTLR_DCC_AS_DCCI			(ULL(1) << 44)
+#define CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH		(ULL(1) << 32)
 
 /*******************************************************************************
  * L2 Control register specific definitions.
diff --git a/include/lib/cpus/aarch64/cortex_a57.h b/include/lib/cpus/aarch64/cortex_a57.h
index 070108d..6c45c06 100644
--- a/include/lib/cpus/aarch64/cortex_a57.h
+++ b/include/lib/cpus/aarch64/cortex_a57.h
@@ -49,6 +49,7 @@
 #define CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA		(ULL(1) << 49)
 #define CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI		(ULL(1) << 44)
 #define CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH	(ULL(1) << 38)
+#define CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH	(ULL(1) << 32)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING		(ULL(3) << 27)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING	(ULL(3) << 25)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR	(ULL(1) << 4)
diff --git a/include/lib/cpus/aarch64/cortex_a72.h b/include/lib/cpus/aarch64/cortex_a72.h
index aed714c..6fbb707 100644
--- a/include/lib/cpus/aarch64/cortex_a72.h
+++ b/include/lib/cpus/aarch64/cortex_a72.h
@@ -34,6 +34,7 @@
 #define CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH	(ULL(1) << 56)
 #define CORTEX_A72_CPUACTLR_EL1_NO_ALLOC_WBWA			(ULL(1) << 49)
 #define CORTEX_A72_CPUACTLR_EL1_DCC_AS_DCCI			(ULL(1) << 44)
+#define CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH		(ULL(1) << 32)
 
 /*******************************************************************************
  * L2 Control register specific definitions.
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 1e8bfa7..c0c3a19 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -7,12 +7,15 @@
 #ifndef __CPU_DATA_H__
 #define __CPU_DATA_H__
 
+#include <platform_def.h>	/* CACHE_WRITEBACK_GRANULE required */
+
 #ifdef AARCH32
 
 #if CRASH_REPORTING
 #error "Crash reporting is not supported in AArch32"
 #endif
 #define CPU_DATA_CPU_OPS_PTR		0x0
+#define CPU_DATA_CRASH_BUF_OFFSET	0x4
 
 #else /* AARCH32 */
 
@@ -25,14 +28,18 @@
 #endif /* AARCH32 */
 
 #if CRASH_REPORTING
-#define CPU_DATA_LOG2SIZE		7
 #define CPU_DATA_CRASH_BUF_END		(CPU_DATA_CRASH_BUF_OFFSET + \
 						CPU_DATA_CRASH_BUF_SIZE)
 #else
-#define CPU_DATA_LOG2SIZE		6
 #define CPU_DATA_CRASH_BUF_END		CPU_DATA_CRASH_BUF_OFFSET
 #endif
 
+/* cpu_data size is the data size rounded up to the platform cache line size */
+#define CPU_DATA_SIZE			(((CPU_DATA_CRASH_BUF_END + \
+					CACHE_WRITEBACK_GRANULE - 1) / \
+						CACHE_WRITEBACK_GRANULE) * \
+							CACHE_WRITEBACK_GRANULE)
+
 #if ENABLE_RUNTIME_INSTRUMENTATION
 /* Temporary space to store PMF timestamps from assembly code */
 #define CPU_DATA_PMF_TS_COUNT		1
@@ -98,8 +105,8 @@
 	assert_cpu_data_crash_stack_offset_mismatch);
 #endif
 
-CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
-	assert_cpu_data_log2size_mismatch);
+CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t),
+		assert_cpu_data_size_mismatch);
 
 CASSERT(CPU_DATA_CPU_OPS_PTR == __builtin_offsetof
 		(cpu_data_t, cpu_ops_ptr),
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 008ae9b..b0f5a04 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -7,6 +7,7 @@
 #ifndef __XLAT_TABLES_DEFS_H__
 #define __XLAT_TABLES_DEFS_H__
 
+#include <arch.h>
 #include <utils_def.h>
 
 /* Miscellaneous MMU related constants */
@@ -96,12 +97,13 @@
 #define ATTR_DEVICE_INDEX		U(0x1)
 #define ATTR_IWBWA_OWBWA_NTR_INDEX	U(0x0)
 #define LOWER_ATTRS(x)			(((x) & U(0xfff)) << 2)
+
 /* Normal Memory, Outer Write-Through non-transient, Inner Non-cacheable */
-#define ATTR_NON_CACHEABLE		U(0x44)
+#define ATTR_NON_CACHEABLE		MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_NC, MAIR_NORM_NC)
 /* Device-nGnRE */
-#define ATTR_DEVICE			U(0x4)
+#define ATTR_DEVICE			MAIR_DEV_nGnRE
 /* Normal Memory, Outer Write-Back non-transient, Inner Write-Back non-transient */
-#define ATTR_IWBWA_OWBWA_NTR		U(0xff)
+#define ATTR_IWBWA_OWBWA_NTR		MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_WB_NTR_RWA, MAIR_NORM_WB_NTR_RWA)
 #define MAIR_ATTR_SET(attr, index)	((attr) << ((index) << 3))
 #define ATTR_INDEX_MASK			U(0x3)
 #define ATTR_INDEX_GET(attr)		(((attr) >> 2) & ATTR_INDEX_MASK)
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 2b0d894..787ccb0 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -266,7 +266,7 @@
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
-#if ARM_BL31_IN_DRAM || defined(AARCH32)
+#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
 /*
  * For AArch32 BL31 is not applicable.
  * For AArch64 BL31 is loaded in the DRAM.
@@ -292,6 +292,13 @@
 #define BL31_BASE			ARM_AP_TZC_DRAM1_BASE
 #define BL31_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
+#elif (RESET_TO_BL31)
+/*
+ * Put BL31_BASE in the middle of the Trusted SRAM.
+ */
+#define BL31_BASE			(ARM_TRUSTED_SRAM_BASE + \
+						(PLAT_ARM_TRUSTED_SRAM_SIZE >> 1))
+#define BL31_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 #else
 /*
  * Put BL31 at the top of the Trusted SRAM.
@@ -353,7 +360,7 @@
  * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
  ******************************************************************************/
 #define BL2U_BASE			BL2_BASE
-#if ARM_BL31_IN_DRAM || defined(AARCH32)
+#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
 /*
  * For AArch32 BL31 is not applicable.
  * For AArch64 BL31 is loaded in the DRAM.
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index 9d025f6..ac0769c 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -37,6 +37,9 @@
 #define CSS_IRQ_TZ_WDOG			86
 #define CSS_IRQ_SEC_SYS_TIMER		91
 
+/* MHU register offsets */
+#define MHU_CPU_INTR_S_SET_OFFSET	0x308
+
 /*
  * Define a list of Group 1 Secure interrupts as per GICv3 terminology. On a
  * GICv2 system or mode, the interrupts will be treated as Group 0 interrupts.
@@ -47,17 +50,24 @@
 					CSS_IRQ_TZ_WDOG,	\
 					CSS_IRQ_SEC_SYS_TIMER
 
+#if CSS_USE_SCMI_SDS_DRIVER
+/* Memory region for shared data storage */
+#define PLAT_ARM_SDS_MEM_BASE		ARM_SHARED_RAM_BASE
+#define PLAT_ARM_SDS_MEM_SIZE_MAX	0xDC0 /* 3520 bytes */
 /*
- * The lower Non-secure MHU channel is being used for SCMI for ARM Trusted
- * Firmware.
- * TODO: Move SCMI to Secure channel once the migration to SCMI in SCP is
- * complete.
+ * The SCMI Channel is placed right after the SDS region
  */
-#define MHU_CPU_INTR_L_SET_OFFSET	0x108
-#define MHU_CPU_INTR_H_SET_OFFSET	0x128
-#define CSS_SCMI_PAYLOAD_BASE		(NSRAM_BASE + 0x500)
-#define CSS_SCMI_MHU_DB_REG_OFF		MHU_CPU_INTR_L_SET_OFFSET
+#define CSS_SCMI_PAYLOAD_BASE		(PLAT_ARM_SDS_MEM_BASE + PLAT_ARM_SDS_MEM_SIZE_MAX)
+#define CSS_SCMI_MHU_DB_REG_OFF		MHU_CPU_INTR_S_SET_OFFSET
 
+/* Trusted mailbox base address common to all CSS */
+/* If SDS is present, then mailbox is at top of SRAM */
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE	(ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE - 0x8)
+
+/* Number of retries for SCP_RAM_READY flag */
+#define CSS_SCP_READY_10US_RETRIES		1000000 /* Effective timeout of 10000 ms */
+
+#else
 /*
  * SCP <=> AP boot configuration
  *
@@ -69,6 +79,12 @@
  */
 #define SCP_BOOT_CFG_ADDR		PLAT_CSS_SCP_COM_SHARED_MEM_BASE
 
+/* Trusted mailbox base address common to all CSS */
+/* If SDS is not present, then the mailbox is at the bottom of SRAM */
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE	ARM_TRUSTED_SRAM_BASE
+
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
+
 #define CSS_MAP_DEVICE			MAP_REGION_FLAT(		\
 						CSS_DEVICE_BASE,	\
 						CSS_DEVICE_SIZE,	\
@@ -152,9 +168,6 @@
 /* TZC related constants */
 #define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT_ALL
 
-/* Trusted mailbox base address common to all CSS */
-#define PLAT_ARM_TRUSTED_MAILBOX_BASE	ARM_TRUSTED_SRAM_BASE
-
 /*
  * Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP
  * command
diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S
index e4aad79..b5189e7 100644
--- a/lib/cpus/aarch32/cortex_a57.S
+++ b/lib/cpus/aarch32/cortex_a57.S
@@ -306,6 +306,32 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_833471
 
+	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A57 Errata #859972.
+	 * This applies only to revision <= r1p3 of Cortex A57.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ---------------------------------------------------
+	 */
+func errata_a57_859972_wa
+	mov		r2, lr
+	bl		check_errata_859972
+	mov		lr, r2
+	cmp		r0, #ERRATA_NOT_APPLIES
+	beq		1f
+	ldcopr16	r0, r1, CORTEX_A57_CPUACTLR
+	orr64_imm	r1, r1, CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH
+	stcopr16	r0, r1, CORTEX_A57_CPUACTLR
+1:
+	bx		lr
+endfunc errata_a57_859972_wa
+
+func check_errata_859972
+	mov	r1, #0x13
+	b	cpu_rev_var_ls
+endfunc check_errata_859972
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A57.
 	 * Shall clobber: r0-r6
@@ -356,6 +382,11 @@
 	bl	errata_a57_833471_wa
 #endif
 
+#if ERRATA_A57_859972
+	mov	r0, r4
+	bl	errata_a57_859972_wa
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -487,6 +518,7 @@
 	report_errata ERRATA_A57_828024, cortex_a57, 828024
 	report_errata ERRATA_A57_829520, cortex_a57, 829520
 	report_errata ERRATA_A57_833471, cortex_a57, 833471
+	report_errata ERRATA_A57_859972, cortex_a57, 859972
 
 	pop	{r12, lr}
 	bx	lr
diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S
index d164cfd..69cc2ea 100644
--- a/lib/cpus/aarch32/cortex_a72.S
+++ b/lib/cpus/aarch32/cortex_a72.S
@@ -61,11 +61,46 @@
 	bx	lr
 endfunc cortex_a72_disable_ext_debug
 
+	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A72 Errata #859971.
+	 * This applies only to revision <= r0p3 of Cortex A72.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ---------------------------------------------------
+	 */
+func errata_a72_859971_wa
+	mov		r2,lr
+	bl		check_errata_859971
+	mov		lr, r2
+	cmp		r0, #ERRATA_NOT_APPLIES
+	beq		1f
+	ldcopr16	r0, r1, CORTEX_A72_CPUACTLR
+	orr64_imm	r1, r1, CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH
+	stcopr16	r0, r1, CORTEX_A72_CPUACTLR
+1:
+	bx   		lr
+endfunc errata_a72_859971_wa
+
+func check_errata_859971
+	mov		r1, #0x03
+	b		cpu_rev_var_ls
+endfunc check_errata_859971
+
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A72.
 	 * -------------------------------------------------
 	 */
 func cortex_a72_reset_func
+	mov	r5, lr
+	bl	cpu_get_rev_var
+	mov	r4, r0
+
+#if ERRATA_A72_859971
+	mov	r0, r4
+	bl	errata_a72_859971_wa
+#endif
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -186,6 +221,27 @@
 	b	cortex_a72_disable_ext_debug
 endfunc cortex_a72_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex A72. Must follow AAPCS.
+ */
+func cortex_a72_errata_report
+	push	{r12, lr}
+
+	bl	cpu_get_rev_var
+	mov	r4, r0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A72_859971, cortex_a72, 859971
+
+	pop	{r12, lr}
+	bx	lr
+endfunc cortex_a72_errata_report
+#endif
+
 declare_cpu_ops cortex_a72, CORTEX_A72_MIDR, \
 	cortex_a72_reset_func, \
 	cortex_a72_core_pwr_dwn, \
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 289d0d4..a720e98 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -304,6 +304,30 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_833471
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A57 Errata #859972.
+	 * This applies only to revision <= r1p3 of Cortex A57.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber:
+	 * --------------------------------------------------
+	 */
+func errata_a57_859972_wa
+	mov	x17, x30
+	bl	check_errata_859972
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A57_CPUACTLR_EL1
+	orr	x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH
+	msr	CORTEX_A57_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a57_859972_wa
+
+func check_errata_859972
+	mov	x1, #0x13
+	b	cpu_rev_var_ls
+endfunc check_errata_859972
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A57.
 	 * Shall clobber: x0-x19
@@ -354,6 +378,11 @@
 	bl	errata_a57_833471_wa
 #endif
 
+#if ERRATA_A57_859972
+	mov	x0, x18
+	bl	errata_a57_859972_wa
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
@@ -483,6 +512,8 @@
 	report_errata ERRATA_A57_828024, cortex_a57, 828024
 	report_errata ERRATA_A57_829520, cortex_a57, 829520
 	report_errata ERRATA_A57_833471, cortex_a57, 833471
+	report_errata ERRATA_A57_859972, cortex_a57, 859972
+
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index 5de2bf0..b034125 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -73,20 +73,52 @@
 	ret
 endfunc cortex_a72_disable_ext_debug
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A72 Errata #859971.
+	 * This applies only to revision <= r0p3 of Cortex A72.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber:
+	 * --------------------------------------------------
+	 */
+func errata_a72_859971_wa
+	mov	x17,x30
+	bl	check_errata_859971
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A72_CPUACTLR_EL1
+	orr	x1, x1, #CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH
+	msr	CORTEX_A72_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a72_859971_wa
+
+func check_errata_859971
+	mov	x1, #0x03
+	b	cpu_rev_var_ls
+endfunc check_errata_859971
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A72.
 	 * -------------------------------------------------
 	 */
 func cortex_a72_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A72_859971
+	mov	x0, x18
+	bl	errata_a72_859971_wa
+#endif
 	/* ---------------------------------------------
-	 * As a bare minimum enable the SMP bit.
+	 * Enable the SMP bit.
 	 * ---------------------------------------------
 	 */
 	mrs	x0, CORTEX_A72_ECTLR_EL1
 	orr	x0, x0, #CORTEX_A72_ECTLR_SMP_BIT
 	msr	CORTEX_A72_ECTLR_EL1, x0
 	isb
-	ret
+	ret x19
 endfunc cortex_a72_reset_func
 
 	/* ----------------------------------------------------
@@ -196,6 +228,27 @@
 	b	cortex_a72_disable_ext_debug
 endfunc cortex_a72_cluster_pwr_dwn
 
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex A72. Must follow AAPCS.
+ */
+func cortex_a72_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A72_859971, cortex_a72, 859971
+
+	ldp	x8, x30, [sp], #16
+	ret
+endfunc cortex_a72_errata_report
+#endif
+
 	/* ---------------------------------------------
 	 * This function provides cortex_a72 specific
 	 * register information for crash reporting.
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index ad32971..31adfb4 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -91,6 +91,14 @@
 # only to revision <= r1p2 of the Cortex A57 cpu.
 ERRATA_A57_833471	?=0
 
+# Flag to apply erratum 855972 workaround during reset. This erratum applies
+# only to revision <= r1p3 of the Cortex A57 cpu.
+ERRATA_A57_859972	?=0
+
+# Flag to apply erratum 855971 workaround during reset. This erratum applies
+# only to revision <= r0p3 of the Cortex A72 cpu.
+ERRATA_A72_859971	?=0
+
 # Process ERRATA_A53_826319 flag
 $(eval $(call assert_boolean,ERRATA_A53_826319))
 $(eval $(call add_define,ERRATA_A53_826319))
@@ -143,6 +151,14 @@
 $(eval $(call assert_boolean,ERRATA_A57_833471))
 $(eval $(call add_define,ERRATA_A57_833471))
 
+# Process ERRATA_A57_859972 flag
+$(eval $(call assert_boolean,ERRATA_A57_859972))
+$(eval $(call add_define,ERRATA_A57_859972))
+
+# Process ERRATA_A72_859971 flag
+$(eval $(call assert_boolean,ERRATA_A72_859971))
+$(eval $(call add_define,ERRATA_A72_859971))
+
 # Errata build flags
 ifneq (${ERRATA_A53_843419},0)
 TF_LDFLAGS_aarch64	+= --fix-cortex-a53-843419
diff --git a/lib/el3_runtime/aarch32/cpu_data.S b/lib/el3_runtime/aarch32/cpu_data.S
index 3d6b806..68d6415 100644
--- a/lib/el3_runtime/aarch32/cpu_data.S
+++ b/lib/el3_runtime/aarch32/cpu_data.S
@@ -34,7 +34,9 @@
  * -----------------------------------------------------------------
  */
 func _cpu_data_by_index
+	mov_imm	r1, CPU_DATA_SIZE
+	mul	r0, r0, r1
 	ldr	r1, =percpu_data
-	add	r0, r1, r0, LSL #CPU_DATA_LOG2SIZE
+	add	r0, r0, r1
 	bx	lr
 endfunc _cpu_data_by_index
diff --git a/lib/el3_runtime/aarch64/cpu_data.S b/lib/el3_runtime/aarch64/cpu_data.S
index de48816..96be081 100644
--- a/lib/el3_runtime/aarch64/cpu_data.S
+++ b/lib/el3_runtime/aarch64/cpu_data.S
@@ -39,7 +39,9 @@
  * -----------------------------------------------------------------
  */
 func _cpu_data_by_index
+	mov_imm	x1, CPU_DATA_SIZE
+	mul	x0, x0, x1
 	adr	x1, percpu_data
-	add	x0, x1, x0, LSL #CPU_DATA_LOG2SIZE
+	add	x0, x0, x1
 	ret
 endfunc _cpu_data_by_index
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index e7fb653..231deea 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -49,6 +49,9 @@
 	 */
 	assert(psci_plat_pm_ops->pwr_domain_off);
 
+	/* Construct the psci_power_state for CPU_OFF */
+	psci_set_power_off_state(&state_info);
+
 	/*
 	 * This function acquires the lock corresponding to each power
 	 * level so that by the time all locks are taken, the system topology
@@ -68,9 +71,6 @@
 			goto exit;
 	}
 
-	/* Construct the psci_power_state for CPU_OFF */
-	psci_set_power_off_state(&state_info);
-
 	/*
 	 * This function is passed the requested state info and
 	 * it returns the negotiated state info for each power level upto
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 302d937..8601046 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -81,6 +81,9 @@
 # operations.
 HW_ASSISTED_COHERENCY		:= 0
 
+# Set the default algorithm for the generation of Trusted Board Boot keys
+KEY_ALG				:= rsa
+
 # Flag to enable new version of image loading
 LOAD_IMAGE_V2			:= 0
 
diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c
index 68f70a7..159bf86 100644
--- a/plat/arm/board/common/board_css_common.c
+++ b/plat/arm/board/common/board_css_common.c
@@ -56,15 +56,6 @@
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
 	CSS_MAP_DEVICE,
-#if CSS_USE_SCMI_DRIVER
-	/*
-	 * The SCMI payload area is currently in the Non Secure SRAM. This is
-	 * a potential security risk but this will be resolved once SCP
-	 * completely replaces SCPI with SCMI as the only communication
-	 * protocol.
-	 */
-	CSS_MAP_NSRAM,
-#endif
 	SOC_CSS_MAP_DEVICE,
 	{0}
 };
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 0b6e1da..6d8aa5f 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -117,7 +117,6 @@
 
 
 BL2_SOURCES		+=	drivers/io/io_semihosting.c			\
-				drivers/delay_timer/delay_timer.c		\
 				lib/semihosting/semihosting.c			\
 				lib/semihosting/${ARCH}/semihosting_call.S	\
 				plat/arm/board/fvp/fvp_bl2_setup.c		\
@@ -128,8 +127,6 @@
 
 ifeq (${FVP_USE_SP804_TIMER},1)
 BL2_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
-else
-BL2_SOURCES		+=	drivers/delay_timer/generic_delay_timer.c
 endif
 
 BL2U_SOURCES		+=	plat/arm/board/fvp/fvp_bl2u_setup.c		\
diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S
index 5e7f08e..29c2c0a 100644
--- a/plat/arm/board/juno/aarch64/juno_helpers.S
+++ b/plat/arm/board/juno/aarch64/juno_helpers.S
@@ -199,6 +199,7 @@
 	msr	rmr_el3, x0
 	isb
 	wfi
+	b	plat_panic_handler
 endfunc juno_do_reset_to_aarch32_state
 
 	/* -----------------------------------------------------
@@ -233,8 +234,6 @@
 	ldr	x0, [x0]
 	cbz	x0, return
 	b	juno_do_reset_to_aarch32_state
-1:
-	b	1b
 return:
 	ret
 endfunc plat_get_my_entrypoint
@@ -287,9 +286,7 @@
 	str	w1, [x3], #4
 	str	w2, [x3]
 
-	bl	juno_do_reset_to_aarch32_state
-1:
-	b	1b
+	b	juno_do_reset_to_aarch32_state
 endfunc juno_reset_to_aarch32_state
 
 #endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 873c569..f1714e1 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -82,13 +82,8 @@
 #endif
 
 #ifdef IMAGE_BL31
-# if CSS_USE_SCMI_DRIVER
-#  define PLAT_ARM_MMAP_ENTRIES		6
-#  define MAX_XLAT_TABLES		3
-# else
 #  define PLAT_ARM_MMAP_ENTRIES		5
 #  define MAX_XLAT_TABLES		2
-# endif
 #endif
 
 #ifdef IMAGE_BL32
@@ -168,7 +163,9 @@
 /*
  * Base address of the first memory region used for communication between AP
  * and SCP. Used by the BOM and SCPI protocols.
- *
+ */
+#if !CSS_USE_SCMI_SDS_DRIVER
+/*
  * Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which
  * means the SCP/AP configuration data gets overwritten when the AP initiates
  * communication with the SCP. The configuration data is expected to be a
@@ -178,6 +175,7 @@
 #define PLAT_CSS_SCP_COM_SHARED_MEM_BASE	(ARM_TRUSTED_SRAM_BASE + 0x80)
 #define PLAT_CSS_PRIMARY_CPU_SHIFT		8
 #define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH		4
+#endif
 
 /*
  * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current
diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c
index abceb0f..2771e0f 100644
--- a/plat/arm/board/juno/juno_bl2_setup.c
+++ b/plat/arm/board/juno/juno_bl2_setup.c
@@ -30,9 +30,12 @@
 	return err;
 }
 
+#if !CSS_USE_SCMI_SDS_DRIVER
 /*
  * We need to override some of the platform functions when booting SP_MIN
- * on Juno AArch32.
+ * on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as
+ * in case of SDS, the structures remain in memory and doesn't need to be
+ * overwritten.
  */
 
 static unsigned int scp_boot_config;
@@ -53,4 +56,6 @@
 	mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
 	VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config);
 }
+#endif
+
 #endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index b972d26..79916cd 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -55,10 +55,14 @@
 				${JUNO_SECURITY_SOURCES}
 endif
 
-# Enable workarounds for selected Cortex-A53 and A57 errata.
+# Errata workarounds for Cortex-A53:
+ERRATA_A53_826319		:=	1
 ERRATA_A53_835769		:=	1
+ERRATA_A53_836870		:=	1
 ERRATA_A53_843419		:=	1
 ERRATA_A53_855873		:=	1
+
+# Errata workarounds for Cortex-A57:
 ERRATA_A57_806969		:=	0
 ERRATA_A57_813419		:=	1
 ERRATA_A57_813420		:=	1
@@ -67,10 +71,10 @@
 ERRATA_A57_828024		:=	1
 ERRATA_A57_829520		:=	1
 ERRATA_A57_833471		:=	1
+ERRATA_A57_859972		:=	0
 
-# Enable workarounds for selected Cortex-A53 errata.
-ERRATA_A53_826319		:=	1
-ERRATA_A53_836870		:=	1
+# Errata workarounds for Cortex-A72:
+ERRATA_A72_859971		:=	0
 
 # Enable option to skip L1 data cache flush during the Cortex-A57 cluster
 # power down sequence
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index 9e2ab5f..336c4e7 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -9,14 +9,10 @@
 			lib/cpus/aarch32/cortex_a57.S		\
 			lib/cpus/aarch32/cortex_a72.S		\
 			plat/arm/board/juno/juno_topology.c	\
-			plat/arm/css/common/css_pm.c		\
-			plat/arm/css/common/css_topology.c	\
 			plat/arm/soc/common/soc_css_security.c	\
-			plat/arm/css/drivers/scp/css_pm_scpi.c	\
-			plat/arm/css/drivers/scpi/css_mhu.c	\
-			plat/arm/css/drivers/scpi/css_scpi.c	\
 			${JUNO_GIC_SOURCES}			\
 			${JUNO_INTERCONNECT_SOURCES}		\
 			${JUNO_SECURITY_SOURCES}
 
 include plat/arm/common/sp_min/arm_sp_min.mk
+include plat/arm/css/common/sp_min/css_sp_min.mk
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 9182bd1..cab6113 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -11,6 +11,7 @@
 #include <console.h>
 #include <debug.h>
 #include <desc_image_load.h>
+#include <generic_delay_timer.h>
 #ifdef SPD_opteed
 #include <optee_utils.h>
 #endif
@@ -182,6 +183,7 @@
 void bl2_early_platform_setup(meminfo_t *mem_layout)
 {
 	arm_bl2_early_platform_setup(mem_layout);
+	generic_delay_timer_init();
 }
 
 /*
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 20372c2..82f02b1 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -139,7 +139,9 @@
 BL1_SOURCES		+=	plat/arm/common/arm_pm.c
 endif
 
-BL2_SOURCES		+=	drivers/io/io_fip.c				\
+BL2_SOURCES		+=	drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				drivers/io/io_fip.c				\
 				drivers/io/io_memmap.c				\
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl2_setup.c			\
@@ -159,7 +161,9 @@
 endif
 endif
 
-BL2U_SOURCES		+=	plat/arm/common/arm_bl2u_setup.c
+BL2U_SOURCES		+=	drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				plat/arm/common/arm_bl2u_setup.c
 
 BL31_SOURCES		+=	plat/arm/common/arm_bl31_setup.c		\
 				plat/arm/common/arm_pm.c			\
@@ -174,9 +178,6 @@
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
 
-    # By default, ARM platforms use RSA keys
-    KEY_ALG		:=	rsa
-
     # Include common TBB sources
     AUTH_SOURCES	:=	drivers/auth/auth_mod.c				\
 				drivers/auth/crypto_mod.c			\
@@ -195,8 +196,6 @@
 
     $(eval $(call FWU_FIP_ADD_IMG,NS_BL2U,--fwu))
 
-    TF_MBEDTLS_KEY_ALG	:=	${KEY_ALG}
-
     # We expect to locate the *.mk files under the directories specified below
 ifeq (${ARM_CRYPTOCELL_INTEG},0)
     CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
diff --git a/plat/arm/css/common/aarch32/css_helpers.S b/plat/arm/css/common/aarch32/css_helpers.S
index f131e67..80aa24c 100644
--- a/plat/arm/css/common/aarch32/css_helpers.S
+++ b/plat/arm/css/common/aarch32/css_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -68,6 +68,24 @@
 	 * cpu (applicable ony after a cold boot)
 	 * -----------------------------------------------------
 	 */
+#if CSS_USE_SCMI_SDS_DRIVER
+func plat_is_my_cpu_primary
+	mov	r10, lr
+	bl	plat_my_core_pos
+	mov	r4, r0
+	bl	sds_get_primary_cpu_id
+	/* Check for error */
+	mov	r1, #0xffffffff
+	cmp	r0, r1
+	beq	1f
+	cmp	r0, r4
+	moveq	r0, #1
+	movne	r0, #0
+	bx	r10
+1:
+	no_ret	plat_panic_handler
+endfunc plat_is_my_cpu_primary
+#else
 func plat_is_my_cpu_primary
 	mov	r10, lr
 	bl	plat_my_core_pos
@@ -80,3 +98,4 @@
 	movne	r0, #0
 	bx	r10
 endfunc plat_is_my_cpu_primary
+#endif
diff --git a/plat/arm/css/common/aarch64/css_helpers.S b/plat/arm/css/common/aarch64/css_helpers.S
index 0cf8f86..59d9206 100644
--- a/plat/arm/css/common/aarch64/css_helpers.S
+++ b/plat/arm/css/common/aarch64/css_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -88,6 +88,23 @@
 	 * cpu (applicable ony after a cold boot)
 	 * -----------------------------------------------------
 	 */
+#if CSS_USE_SCMI_SDS_DRIVER
+func plat_is_my_cpu_primary
+	mov	x9, x30
+	bl	plat_my_core_pos
+	mov	x4, x0
+	bl	sds_get_primary_cpu_id
+	/* Check for error */
+	mov	x1, #0xffffffff
+	cmp	x0, x1
+	b.eq	1f
+	cmp	x0, x4
+	cset	w0, eq
+	ret	x9
+1:
+	no_ret	plat_panic_handler
+endfunc plat_is_my_cpu_primary
+#else
 func plat_is_my_cpu_primary
 	mov	x9, x30
 	bl	plat_my_core_pos
@@ -99,3 +116,4 @@
 	cset	w0, eq
 	ret	x9
 endfunc plat_is_my_cpu_primary
+#endif
diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c
index c98b2ff..9b4800e 100644
--- a/plat/arm/css/common/css_bl2_setup.c
+++ b/plat/arm/css/common/css_bl2_setup.c
@@ -48,10 +48,14 @@
 	return ret;
 }
 
-#ifdef EL3_PAYLOAD_BASE
+#if !CSS_USE_SCMI_SDS_DRIVER
+# ifdef EL3_PAYLOAD_BASE
+
 /*
  * We need to override some of the platform functions when booting an EL3
- * payload.
+ * payload. These needs to be done only for SCPI/BOM SCP systems as
+ * in case of SDS, the structures remain in memory and doesn't need to be
+ * overwritten.
  */
 
 static unsigned int scp_boot_config;
@@ -82,4 +86,7 @@
 	zeromem((void *) ARM_SHARED_RAM_BASE, 128);
 	mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
 }
-#endif /* EL3_PAYLOAD_BASE */
+
+# endif /* EL3_PAYLOAD_BASE */
+
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 9381e4c..63e3059 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -9,7 +9,7 @@
 CSS_LOAD_SCP_IMAGES	?=	1
 
 # By default, SCMI driver is disabled for CSS platforms
-CSS_USE_SCMI_DRIVER	?=	0
+CSS_USE_SCMI_SDS_DRIVER	?=	0
 
 PLAT_INCLUDES		+=	-Iinclude/plat/arm/css/common			\
 				-Iinclude/plat/arm/css/common/aarch64
@@ -19,18 +19,14 @@
 
 BL1_SOURCES		+=	plat/arm/css/common/css_bl1_setup.c
 
-BL2_SOURCES		+=	plat/arm/css/common/css_bl2_setup.c		\
-				plat/arm/css/drivers/scpi/css_mhu.c		\
-				plat/arm/css/drivers/scpi/css_scpi.c
+BL2_SOURCES		+=	plat/arm/css/common/css_bl2_setup.c
 
-BL2U_SOURCES		+=	plat/arm/css/common/css_bl2u_setup.c		\
-				plat/arm/css/drivers/scpi/css_mhu.c		\
-				plat/arm/css/drivers/scpi/css_scpi.c
+BL2U_SOURCES		+=	plat/arm/css/common/css_bl2u_setup.c
 
 BL31_SOURCES		+=	plat/arm/css/common/css_pm.c			\
 				plat/arm/css/common/css_topology.c
 
-ifeq (${CSS_USE_SCMI_DRIVER},0)
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
 BL31_SOURCES		+=	plat/arm/css/drivers/scp/css_pm_scpi.c		\
 				plat/arm/css/drivers/scpi/css_mhu.c		\
 				plat/arm/css/drivers/scpi/css_scpi.c
@@ -56,19 +52,34 @@
     $(eval $(call FWU_FIP_ADD_IMG,SCP_BL2U,--scp-fwu-cfg))
   endif
 
-  BL2U_SOURCES		+=	plat/arm/css/drivers/scp/css_bom_bootloader.c
-  BL2_SOURCES		+=	plat/arm/css/drivers/scp/css_bom_bootloader.c
+  ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
+    BL2U_SOURCES	+=	plat/arm/css/drivers/scp/css_sds.c	\
+				plat/arm/css/drivers/sds/sds.c
+
+    BL2_SOURCES		+=	plat/arm/css/drivers/scp/css_sds.c	\
+				plat/arm/css/drivers/sds/sds.c
+  else
+    BL2U_SOURCES	+=	plat/arm/css/drivers/scp/css_bom_bootloader.c	\
+				plat/arm/css/drivers/scpi/css_mhu.c		\
+				plat/arm/css/drivers/scpi/css_scpi.c
+
+    BL2_SOURCES		+=	plat/arm/css/drivers/scp/css_bom_bootloader.c	\
+				plat/arm/css/drivers/scpi/css_mhu.c		\
+				plat/arm/css/drivers/scpi/css_scpi.c
+    # Enable option to detect whether the SCP ROM firmware in use predates version
+    # 1.7.0 and therefore, is incompatible.
+    CSS_DETECT_PRE_1_7_0_SCP	:=	1
+
+    # Process CSS_DETECT_PRE_1_7_0_SCP flag
+    $(eval $(call assert_boolean,CSS_DETECT_PRE_1_7_0_SCP))
+    $(eval $(call add_define,CSS_DETECT_PRE_1_7_0_SCP))
+  endif
 endif
 
-# Enable option to detect whether the SCP ROM firmware in use predates version
-# 1.7.0 and therefore, is incompatible.
-CSS_DETECT_PRE_1_7_0_SCP	:=	1
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
+  PLAT_BL_COMMON_SOURCES	+=	plat/arm/css/drivers/sds/${ARCH}/sds_helpers.S
+endif
 
-# Process CSS_DETECT_PRE_1_7_0_SCP flag
-$(eval $(call assert_boolean,CSS_DETECT_PRE_1_7_0_SCP))
-$(eval $(call add_define,CSS_DETECT_PRE_1_7_0_SCP))
-
-# Process CSS_USE_SCMI_DRIVER flag
-$(eval $(call assert_boolean,CSS_USE_SCMI_DRIVER))
-$(eval $(call add_define,CSS_USE_SCMI_DRIVER))
-
+# Process CSS_USE_SCMI_SDS_DRIVER flag
+$(eval $(call assert_boolean,CSS_USE_SCMI_SDS_DRIVER))
+$(eval $(call add_define,CSS_USE_SCMI_SDS_DRIVER))
diff --git a/plat/arm/css/common/sp_min/css_sp_min.mk b/plat/arm/css/common/sp_min/css_sp_min.mk
new file mode 100644
index 0000000..28eb2db
--- /dev/null
+++ b/plat/arm/css/common/sp_min/css_sp_min.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP MIN source files common to CSS platforms
+BL32_SOURCES		+=	plat/arm/css/common/css_pm.c			\
+				plat/arm/css/common/css_topology.c
+
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
+BL32_SOURCES		+=	plat/arm/css/drivers/scp/css_pm_scpi.c		\
+				plat/arm/css/drivers/scpi/css_mhu.c		\
+				plat/arm/css/drivers/scpi/css_scpi.c
+else
+BL32_SOURCES		+=	plat/arm/css/drivers/scp/css_pm_scmi.c		\
+				plat/arm/css/drivers/scmi/scmi_common.c		\
+				plat/arm/css/drivers/scmi/scmi_pwr_dmn_proto.c	\
+				plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c
+endif
diff --git a/plat/arm/css/drivers/scp/css_bom_bootloader.c b/plat/arm/css/drivers/scp/css_bom_bootloader.c
index 047e069..a92ce6b 100644
--- a/plat/arm/css/drivers/scp/css_bom_bootloader.c
+++ b/plat/arm/css/drivers/scp/css_bom_bootloader.c
@@ -6,12 +6,12 @@
 
 #include <arch_helpers.h>
 #include <assert.h>
-#include <cassert.h>
 #include <css_def.h>
 #include <debug.h>
 #include <platform.h>
 #include <stdint.h>
 #include "../scpi/css_mhu.h"
+#include "../scpi/css_scpi.h"
 
 /* ID of the MHU slot used for the BOM protocol */
 #define BOM_MHU_SLOT_ID		0
@@ -183,3 +183,11 @@
 
 	return 0;
 }
+
+int css_scp_boot_ready(void)
+{
+	VERBOSE("Waiting for SCP to signal it is ready to go on\n");
+
+	/* Wait for SCP to signal it's ready */
+	return scpi_wait_ready();
+}
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index 9098d3f..c39bc4b 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -324,8 +324,8 @@
 scmi_channel_plat_info_t plat_css_scmi_plat_info = {
 		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
 		.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
-		.db_preserve_mask = 0xfffffffd,
-		.db_modify_mask = 0x2,
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
 };
 
 void plat_arm_pwrc_setup(void)
diff --git a/plat/arm/css/drivers/scp/css_scp.h b/plat/arm/css/drivers/scp/css_scp.h
index 097a9f5..223e372 100644
--- a/plat/arm/css/drivers/scp/css_scp.h
+++ b/plat/arm/css/drivers/scp/css_scp.h
@@ -7,8 +7,9 @@
 #ifndef __CSS_SCP_H__
 #define __CSS_SCP_H__
 
+#include <cassert.h>
+#include <platform_def.h>
 #include <types.h>
-#include "../scpi/css_scpi.h"
 
 /* Forward declarations */
 struct psci_power_state;
@@ -28,10 +29,20 @@
  * API to wait for SCP to signal till it's ready after booting the transferred
  * image.
  */
-static inline int css_scp_boot_ready(void)
-{
-	VERBOSE("Waiting for SCP to signal it is ready to go on\n");
-	return scpi_wait_ready();
-}
+int css_scp_boot_ready(void);
+
+#if CSS_LOAD_SCP_IMAGES
+/*
+ * All CSS platforms load SCP_BL2/SCP_BL2U just below BL rw-data and above
+ * BL2/BL2U (this is where BL31 usually resides except when ARM_BL31_IN_DRAM is
+ * set. Ensure that SCP_BL2/SCP_BL2U do not overflow into BL1 rw-data nor
+ * BL2/BL2U.
+ */
+CASSERT(SCP_BL2_LIMIT <= BL1_RW_BASE, assert_scp_bl2_limit_overwrite_bl1);
+CASSERT(SCP_BL2U_LIMIT <= BL1_RW_BASE, assert_scp_bl2u_limit_overwrite_bl1);
+
+CASSERT(SCP_BL2_BASE >= BL2_LIMIT, assert_scp_bl2_overwrite_bl2);
+CASSERT(SCP_BL2U_BASE >= BL2U_LIMIT, assert_scp_bl2u_overwrite_bl2u);
+#endif
 
 #endif	/* __CSS_SCP_H__ */
diff --git a/plat/arm/css/drivers/scp/css_sds.c b/plat/arm/css/drivers/scp/css_sds.c
new file mode 100644
index 0000000..a7a51ba
--- /dev/null
+++ b/plat/arm/css/drivers/scp/css_sds.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <css_def.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <platform.h>
+#include <stdint.h>
+#include "../sds/sds.h"
+
+int css_scp_boot_image_xfer(void *image, unsigned int image_size)
+{
+	int ret;
+	unsigned int image_offset, image_flags;
+
+	ret = sds_init();
+	if (ret != SDS_OK) {
+		ERROR("SCP SDS initialization failed\n");
+		panic();
+	}
+
+	VERBOSE("Writing SCP image metadata\n");
+	image_offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE;
+	ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET,
+			&image_offset, SDS_SCP_IMG_ADDR_SIZE,
+			SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK)
+		goto sds_fail;
+
+	ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET,
+			&image_size, SDS_SCP_IMG_SIZE_SIZE,
+			SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK)
+		goto sds_fail;
+
+	VERBOSE("Marking SCP image metadata as valid\n");
+	image_flags = SDS_SCP_IMG_VALID_FLAG_BIT;
+	ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET,
+			&image_flags, SDS_SCP_IMG_FLAG_SIZE,
+			SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK)
+		goto sds_fail;
+
+	return 0;
+sds_fail:
+	ERROR("SCP SDS write to SCP IMG struct failed\n");
+	panic();
+}
+
+/*
+ * API to wait for SCP to signal till it's ready after booting the transferred
+ * image.
+ */
+int css_scp_boot_ready(void)
+{
+	uint32_t scp_feature_availability_flags;
+	int ret, retry = CSS_SCP_READY_10US_RETRIES;
+
+
+	VERBOSE("Waiting for SCP RAM to complete its initialization process\n");
+
+	/* Wait for the SCP RAM Firmware to complete its initialization process */
+	while (retry > 0) {
+		ret = sds_struct_read(SDS_FEATURE_AVAIL_STRUCT_ID, 0,
+				&scp_feature_availability_flags,
+				SDS_FEATURE_AVAIL_SIZE,
+				SDS_ACCESS_MODE_NON_CACHED);
+		if (ret == SDS_ERR_STRUCT_NOT_FINALIZED)
+			continue;
+
+		if (ret != SDS_OK) {
+			ERROR(" sds_struct_read failed\n");
+			panic();
+		}
+
+		if (scp_feature_availability_flags &
+				SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT)
+			return 0;
+
+		udelay(10);
+		retry--;
+	}
+
+	ERROR("Timeout of %d ms expired waiting for SCP RAM Ready flag\n",
+			CSS_SCP_READY_10US_RETRIES/100);
+
+	plat_panic_handler();
+}
diff --git a/plat/arm/css/drivers/sds/aarch32/sds_helpers.S b/plat/arm/css/drivers/sds/aarch32/sds_helpers.S
new file mode 100644
index 0000000..f68cb35
--- /dev/null
+++ b/plat/arm/css/drivers/sds/aarch32/sds_helpers.S
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include "../sds.h"
+#include "../sds_private.h"
+
+	.globl	sds_get_primary_cpu_id
+
+	/*
+	 * int sds_get_primary_cpu_id(void);
+	 * Return the primary CPU ID from SDS Structure
+	 * Returns CPUID on success or -1 on failure
+	 */
+func sds_get_primary_cpu_id
+	ldr	r0, =PLAT_ARM_SDS_MEM_BASE
+	ldr	r2, =SDS_REGION_SIGNATURE
+	ldr	r1, [r0]
+	ubfx	r3, r1, #0, #16
+
+	/* Check if the SDS region signature found */
+	cmp	r2, r3
+	bne	2f
+
+	/* Get the structure count from region descriptor in r1 */
+	ubfx	r1, r1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH
+	cmp	r1, #0
+	beq	2f
+	add	r0, r0, #SDS_REGION_DESC_SIZE
+
+	/* Initialize the loop iterator count in r3 */
+	mov	r3, #0
+loop_begin:
+	ldrh	r2, [r0]
+	cmp	r2, #SDS_AP_CPU_INFO_STRUCT_ID
+	bne	continue_loop
+
+	/* We have found the required structure */
+	ldr	r0, [r0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)]
+	bx	lr
+continue_loop:
+	/* Increment the loop counter and exit loop if counter == structure count */
+	add	r3, r3, #0x1
+	cmp	r1, r3
+	beq	2f
+
+	/* Read the 2nd word in header */
+	ldr	r2, [r0,#4]
+	/* Get the structure size from header */
+	ubfx	r2, r2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH
+	/* Add the structure size and SDS HEADER SIZE to point to next header */
+	add	r2, r2, #SDS_HEADER_SIZE
+	add	r0, r0, r2
+	b	loop_begin
+2:
+	mov	r0, #0xffffffff
+	bx	lr
+endfunc sds_get_primary_cpu_id
diff --git a/plat/arm/css/drivers/sds/aarch64/sds_helpers.S b/plat/arm/css/drivers/sds/aarch64/sds_helpers.S
new file mode 100644
index 0000000..3b9c562
--- /dev/null
+++ b/plat/arm/css/drivers/sds/aarch64/sds_helpers.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include "../sds.h"
+#include "../sds_private.h"
+
+	.globl	sds_get_primary_cpu_id
+
+	/*
+	 * int sds_get_primary_cpu_id(void);
+	 * Return the primary CPI ID from SDS Structure
+	 * Returns CPUID on success or -1 on failure
+	 */
+func sds_get_primary_cpu_id
+	mov_imm	x0, PLAT_ARM_SDS_MEM_BASE
+	mov	w2, #SDS_REGION_SIGNATURE
+	ldr	w1, [x0]
+
+	/* Check if the SDS region signature found */
+	cmp	w2, w1, uxth
+	b.ne	2f
+
+	/* Get the structure count from region descriptor in `w1 */
+	ubfx	w1, w1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH
+	cbz	w1, 2f
+	add	x0, x0, #SDS_REGION_DESC_SIZE
+
+	/* Initialize the loop iterator count in w3 */
+	mov	w3, #0
+loop_begin:
+	ldrh	w2, [x0]
+	cmp	w2, #SDS_AP_CPU_INFO_STRUCT_ID
+	b.ne	continue_loop
+
+	/* We have found the required structure */
+	ldr	w0, [x0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)]
+	ret
+continue_loop:
+	/* Increment the loop counter and exit loop if counter == structure count */
+	add	w3, w3, #0x1
+	cmp	w1, w3
+	b.eq	2f
+
+	/* Read the 2nd word in header */
+	ldr	w2, [x0,#4]
+	/* Get the structure size from header */
+	ubfx	x2, x2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH
+	/* Add the structure size and SDS HEADER SIZE to point to next header */
+	add	x2, x2, #SDS_HEADER_SIZE
+	add	x0, x0, x2
+	b	loop_begin
+2:
+	mov	w0, #0xffffffff
+	ret
+endfunc sds_get_primary_cpu_id
diff --git a/plat/arm/css/drivers/sds/sds.c b/plat/arm/css/drivers/sds/sds.c
new file mode 100644
index 0000000..e2fac54
--- /dev/null
+++ b/plat/arm/css/drivers/sds/sds.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <css_def.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "sds.h"
+#include "sds_private.h"
+
+/*
+ * Variables used to track and maintain the state of the memory region reserved
+ * for usage by the SDS framework.
+ */
+
+/* Pointer to the base of the SDS memory region */
+static uintptr_t sds_mem_base;
+
+/* Size of the SDS memory region in bytes */
+static size_t sds_mem_size;
+
+/*
+ * Perform some non-exhaustive tests to determine whether any of the fields
+ * within a Structure Header contain obviously invalid data.
+ * Returns SDS_OK on success, SDS_ERR_FAIL on error.
+ */
+static int sds_struct_is_valid(uintptr_t header)
+{
+	size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header);
+
+	/* Zero is not a valid identifier */
+	if (GET_SDS_HEADER_ID(header) == 0)
+		return SDS_ERR_FAIL;
+
+	/* Check SDS Schema version */
+	if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION)
+		return SDS_ERR_FAIL;
+
+	/* The SDS Structure sizes have to be multiple of 8 */
+	if ((struct_size == 0) || ((struct_size % 8) != 0))
+		return SDS_ERR_FAIL;
+
+	if (struct_size > sds_mem_size)
+		return SDS_ERR_FAIL;
+
+	return SDS_OK;
+}
+
+/*
+ * Validate the SDS structure headers.
+ * Returns SDS_OK on success, SDS_ERR_FAIL on error.
+ */
+static int validate_sds_struct_headers(void)
+{
+	unsigned int i, structure_count;
+	uintptr_t header;
+
+	structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
+
+	if (structure_count == 0)
+		return SDS_ERR_FAIL;
+
+	header = sds_mem_base + SDS_REGION_DESC_SIZE;
+
+	/* Iterate over structure headers and validate each one */
+	for (i = 0; i < structure_count; i++) {
+		if (sds_struct_is_valid(header) != SDS_OK) {
+			WARN("SDS: Invalid structure header detected\n");
+			return SDS_ERR_FAIL;
+		}
+		header += GET_SDS_HEADER_STRUCT_SIZE(header) + SDS_HEADER_SIZE;
+	}
+	return SDS_OK;
+}
+
+/*
+ * Get the structure header pointer corresponding to the structure ID.
+ * Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error.
+ */
+static int get_struct_header(uint32_t structure_id, struct_header_t **header)
+{
+	unsigned int i, structure_count;
+	uintptr_t current_header;
+
+	assert(header);
+
+	structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
+	if (structure_count == 0)
+		return SDS_ERR_STRUCT_NOT_FOUND;
+
+	current_header = ((uintptr_t)sds_mem_base) + SDS_REGION_DESC_SIZE;
+
+	/* Iterate over structure headers to find one with a matching ID */
+	for (i = 0; i < structure_count; i++) {
+		if (GET_SDS_HEADER_ID(current_header) == structure_id) {
+			*header = (struct_header_t *)current_header;
+			return SDS_OK;
+		}
+		current_header += GET_SDS_HEADER_STRUCT_SIZE(current_header) +
+						SDS_HEADER_SIZE;
+	}
+
+	*header = NULL;
+	return SDS_ERR_STRUCT_NOT_FOUND;
+}
+
+/*
+ * Check if a structure header corresponding to the structure ID exists.
+ * Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND
+ * if not found.
+ */
+int sds_struct_exists(unsigned int structure_id)
+{
+	struct_header_t *header = NULL;
+	int ret;
+
+	ret = get_struct_header(structure_id, &header);
+	if (ret == SDS_OK) {
+		assert(header);
+	}
+
+	return ret;
+}
+
+/*
+ * Read from field in the structure corresponding to `structure_id`.
+ * `fld_off` is the offset to the field in the structure and `mode`
+ * indicates whether cache maintenance need to performed prior to the read.
+ * The `data` is the pointer to store the read data of size specified by `size`.
+ * Returns SDS_OK on success or corresponding error codes on failure.
+ */
+int sds_struct_read(uint32_t structure_id, unsigned int fld_off,
+		void *data, size_t size, sds_access_mode_t mode)
+{
+	int status;
+	uintptr_t field_base;
+	struct_header_t *header = NULL;
+
+	if (!data)
+		return SDS_ERR_INVALID_PARAMS;
+
+	/* Check if a structure with this ID exists */
+	status = get_struct_header(structure_id, &header);
+	if (status != SDS_OK)
+		return status;
+
+	assert(header);
+
+	if (mode == SDS_ACCESS_MODE_CACHED)
+		inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);
+
+	if (!IS_SDS_HEADER_VALID(header)) {
+		WARN("SDS: Reading from un-finalized structure 0x%x\n",
+				structure_id);
+		return SDS_ERR_STRUCT_NOT_FINALIZED;
+	}
+
+	if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
+		return SDS_ERR_FAIL;
+
+	field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
+	if (check_uptr_overflow(field_base, size - 1))
+		return SDS_ERR_FAIL;
+
+	/* Copy the required field in the struct */
+	memcpy(data, (void *)field_base, size);
+
+	return SDS_OK;
+}
+
+/*
+ * Write to the field in the structure corresponding to `structure_id`.
+ * `fld_off` is the offset to the field in the structure and `mode`
+ * indicates whether cache maintenance need to performed for the write.
+ * The `data` is the pointer to data of size specified by `size`.
+ * Returns SDS_OK on success or corresponding error codes on failure.
+ */
+int sds_struct_write(uint32_t structure_id, unsigned int fld_off,
+		void *data, size_t size, sds_access_mode_t mode)
+{
+	int status;
+	uintptr_t field_base;
+	struct_header_t *header = NULL;
+
+	if (!data)
+		return SDS_ERR_INVALID_PARAMS;
+
+	/* Check if a structure with this ID exists */
+	status = get_struct_header(structure_id, &header);
+	if (status != SDS_OK)
+		return status;
+
+	assert(header);
+
+	if (mode == SDS_ACCESS_MODE_CACHED)
+		inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);
+
+	if (!IS_SDS_HEADER_VALID(header)) {
+		WARN("SDS: Writing to un-finalized structure 0x%x\n",
+				structure_id);
+		return SDS_ERR_STRUCT_NOT_FINALIZED;
+	}
+
+	if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
+		return SDS_ERR_FAIL;
+
+	field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
+	if (check_uptr_overflow(field_base, size - 1))
+		return SDS_ERR_FAIL;
+
+	/* Copy the required field in the struct */
+	memcpy((void *)field_base, data, size);
+
+	if (mode == SDS_ACCESS_MODE_CACHED)
+		flush_dcache_range((uintptr_t)field_base, size);
+
+	return SDS_OK;
+}
+
+/*
+ * Initialize the SDS driver. Also verifies the SDS version and sanity of
+ * the SDS structure headers.
+ * Returns SDS_OK on success, SDS_ERR_FAIL on error.
+ */
+int sds_init(void)
+{
+	sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE;
+
+	if (!IS_SDS_REGION_VALID(sds_mem_base)) {
+		WARN("SDS: No valid SDS Memory Region found\n");
+		return SDS_ERR_FAIL;
+	}
+
+	if (GET_SDS_REGION_SCHEMA_VERSION(sds_mem_base)
+				!= SDS_REGION_SCH_VERSION) {
+		WARN("SDS: Unsupported SDS schema version\n");
+		return SDS_ERR_FAIL;
+	}
+
+	sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base);
+	if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) {
+		WARN("SDS: SDS Memory Region exceeds size limit\n");
+		return SDS_ERR_FAIL;
+	}
+
+	INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size);
+
+	if (validate_sds_struct_headers() != SDS_OK)
+		return SDS_ERR_FAIL;
+
+	return SDS_OK;
+}
diff --git a/plat/arm/css/drivers/sds/sds.h b/plat/arm/css/drivers/sds/sds.h
new file mode 100644
index 0000000..ff3787d
--- /dev/null
+++ b/plat/arm/css/drivers/sds/sds.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SDS_H__
+#define __SDS_H__
+
+/* SDS Structure Identifier defines */
+/* AP CPU INFO defines */
+#define SDS_AP_CPU_INFO_STRUCT_ID		1
+#define SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET	0x0
+#define SDS_AP_CPU_INFO_PRIMARY_CPUID_SIZE	0x4
+
+/* ROM Firmware Version defines */
+#define SDS_ROM_VERSION_STRUCT_ID		2
+#define SDS_ROM_VERSION_OFFSET			0x0
+#define SDS_ROM_VERSION_SIZE 			0x4
+
+/* RAM Firmware version defines */
+#define SDS_RAM_VERSION_STRUCT_ID		3
+#define SDS_RAM_VERSION_OFFSET			0x0
+#define SDS_RAM_VERSION_SIZE			0x4
+
+/* Platform Identity defines */
+#define SDS_PLATFORM_IDENTITY_STRUCT_ID		4
+#define SDS_PLATFORM_IDENTITY_ID_OFFSET		0x0
+#define SDS_PLATFORM_IDENTITY_ID_SIZE		0x4
+#define SDS_PLATFORM_IDENTITY_ID_CONFIG_SHIFT	28
+#define SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH	4
+#define SDS_PLATFORM_IDENTITY_ID_CONFIG_MASK	\
+	((1 << SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH) - 1)
+
+#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_OFFSET	0x4
+#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_SIZE	0x4
+
+/* Reset Syndrome defines */
+#define SDS_RESET_SYNDROME_STRUCT_ID		5
+#define SDS_RESET_SYNDROME_OFFSET		0
+#define SDS_RESET_SYNDROME_SIZE			4
+#define SDS_RESET_SYNDROME_POW_ON_RESET_BIT	(1 << 0)
+#define SDS_RESET_SYNDROME_SCP_WD_RESET_BIT	(1 << 1)
+#define SDS_RESET_SYNDROME_AP_WD_RESET_BIT	(1 << 2)
+#define SDS_RESET_SYNDROME_SYS_RESET_REQ_BIT	(1 << 3)
+#define SDS_RESET_SYNDROME_M3_LOCKUP_BIT	(1 << 4)
+
+/* SCP Firmware Feature Availability defines */
+#define SDS_FEATURE_AVAIL_STRUCT_ID		6
+#define SDS_FEATURE_AVAIL_OFFSET		0
+#define SDS_FEATURE_AVAIL_SIZE			4
+#define SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT	(1 << 0)
+#define SDS_FEATURE_AVAIL_DMC_READY_BIT		(1 << 1)
+#define SDS_FEATURE_AVAIL_MSG_IF_READY_BIT	(1 << 2)
+
+/* SCP BL2 Image Metadata defines */
+#define SDS_SCP_IMG_STRUCT_ID			9
+#define SDS_SCP_IMG_FLAG_OFFSET			0
+#define SDS_SCP_IMG_FLAG_SIZE			4
+#define SDS_SCP_IMG_VALID_FLAG_BIT		(1 << 0)
+#define SDS_SCP_IMG_ADDR_OFFSET			4
+#define SDS_SCP_IMG_ADDR_SIZE			4
+#define SDS_SCP_IMG_SIZE_OFFSET			8
+#define SDS_SCP_IMG_SIZE_SIZE			4
+
+/* SDS Driver Error Codes */
+#define SDS_OK				0
+#define SDS_ERR_FAIL			-1
+#define SDS_ERR_INVALID_PARAMS		-2
+#define SDS_ERR_STRUCT_NOT_FOUND	-3
+#define SDS_ERR_STRUCT_NOT_FINALIZED	-4
+
+#ifndef __ASSEMBLY__
+#include <stddef.h>
+#include <stdint.h>
+
+typedef enum {
+	SDS_ACCESS_MODE_NON_CACHED,
+	SDS_ACCESS_MODE_CACHED,
+} sds_access_mode_t;
+
+int sds_init(void);
+int sds_struct_exists(uint32_t structure_id);
+int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data,
+		size_t size, sds_access_mode_t mode);
+int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data,
+		size_t size, sds_access_mode_t mode);
+#endif /*__ASSEMBLY__ */
+#endif /* __SDS_H__ */
diff --git a/plat/arm/css/drivers/sds/sds_private.h b/plat/arm/css/drivers/sds/sds_private.h
new file mode 100644
index 0000000..649576b
--- /dev/null
+++ b/plat/arm/css/drivers/sds/sds_private.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SDS_PRIVATE_H__
+#define __SDS_PRIVATE_H__
+
+/* SDS Header defines */
+#define SDS_HEADER_ID_SHIFT			0
+#define SDS_HEADER_ID_WIDTH			16
+#define SDS_HEADER_ID_MASK			((1 << SDS_HEADER_ID_WIDTH) - 1)
+
+#define SDS_HEADER_MINOR_VERSION_WIDTH		8
+#define SDS_HEADER_MINOR_VERSION_SHIFT		16
+#define SDS_HEADER_MAJOR_VERSION_WIDTH		8
+
+#define MAKE_SDS_HEADER_VERSION(major, minor)	\
+	(((((major) & 0xff) << SDS_HEADER_MINOR_VERSION_WIDTH) | ((minor) & 0xff)))
+#define SDS_HEADER_VERSION_MASK			\
+	((1 << (SDS_HEADER_MINOR_VERSION_WIDTH + SDS_HEADER_MAJOR_VERSION_WIDTH)) - 1)
+
+#define SDS_HEADER_VERSION			MAKE_SDS_HEADER_VERSION(1, 0)
+#define SDS_HEADER_STRUCT_SIZE_WIDTH		23
+#define SDS_HEADER_STRUCT_SIZE_SHIFT		1
+#define SDS_HEADER_STRUCT_SIZE_MASK		((1 << SDS_HEADER_STRUCT_SIZE_WIDTH) - 1)
+#define SDS_HEADER_VALID_MASK			0x1
+#define SDS_HEADER_VALID_SHIFT			0
+#define SDS_HEADER_SIZE				0x8
+
+/* Arbitrary, 16 bit value that indicates a valid SDS Memory Region */
+#define SDS_REGION_SIGNATURE			0xAA7A
+#define SDS_REGION_SIGNATURE_WIDTH		16
+#define SDS_REGION_SIGNATURE_SHIFT		0
+#define SDS_REGION_SIGNATURE_MASK		((1 << SDS_REGION_SIGNATURE_WIDTH) - 1)
+
+#define SDS_REGION_STRUCT_COUNT_SHIFT		16
+#define SDS_REGION_STRUCT_COUNT_WIDTH		8
+#define SDS_REGION_STRUCT_COUNT_MASK		((1 << SDS_REGION_STRUCT_COUNT_WIDTH) - 1)
+
+#define SDS_REGION_SCH_MINOR_SHIFT		24
+#define SDS_REGION_SCH_MINOR_WIDTH		4
+#define SDS_REGION_SCH_MINOR_MASK		((1 << SDS_REGION_SCH_MINOR_WIDTH) - 1)
+
+#define SDS_REGION_SCH_MAJOR_SHIFT		28
+#define SDS_REGION_SCH_MAJOR_WIDTH		4
+#define SDS_REGION_SCH_MAJOR_MASK		((1 << SDS_REGION_SCH_MAJOR_WIDTH) - 1)
+
+#define SDS_REGION_SCH_VERSION_MASK		\
+	((1 << (SDS_REGION_SCH_MINOR_WIDTH + SDS_REGION_SCH_MAJOR_WIDTH)) - 1)
+
+#define MAKE_SDS_REGION_SCH_VERSION(maj, min)	\
+	((((maj) & SDS_REGION_SCH_MAJOR_MASK) << SDS_REGION_SCH_MINOR_WIDTH) |	\
+	((min) & SDS_REGION_SCH_MINOR_MASK))
+
+#define SDS_REGION_SCH_VERSION			MAKE_SDS_REGION_SCH_VERSION(1, 0)
+#define SDS_REGION_REGIONSIZE_OFFSET		0x4
+#define SDS_REGION_DESC_SIZE			0x8
+
+#ifndef __ASSEMBLY__
+#include <stddef.h>
+#include <stdint.h>
+
+/* Header containing Shared Data Structure metadata */
+typedef struct structure_header {
+	uint32_t reg[2];
+} struct_header_t;
+
+#define GET_SDS_HEADER_ID(header)			\
+	((((struct_header_t *)(header))->reg[0]) & SDS_HEADER_ID_MASK)
+#define GET_SDS_HEADER_VERSION(header)			\
+	(((((struct_header_t *)(header))->reg[0]) >> SDS_HEADER_MINOR_VERSION_SHIFT)\
+	& SDS_HEADER_VERSION_MASK)
+#define GET_SDS_HEADER_STRUCT_SIZE(header)		\
+	(((((struct_header_t *)(header))->reg[1]) >> SDS_HEADER_STRUCT_SIZE_SHIFT)\
+	& SDS_HEADER_STRUCT_SIZE_MASK)
+#define IS_SDS_HEADER_VALID(header)			\
+	((((struct_header_t *)(header))->reg[1]) & SDS_HEADER_VALID_MASK)
+#define GET_SDS_STRUCT_FIELD(header, field_offset)	\
+	((((uint8_t *)(header)) + sizeof(struct_header_t)) + (field_offset))
+
+/* Region Descriptor describing the SDS Memory Region */
+typedef struct region_descriptor {
+	uint32_t reg[2];
+} region_desc_t;
+
+#define IS_SDS_REGION_VALID(region)			\
+	(((((region_desc_t *)(region))->reg[0]) & SDS_REGION_SIGNATURE_MASK) == SDS_REGION_SIGNATURE)
+#define GET_SDS_REGION_STRUCTURE_COUNT(region)		\
+	(((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_STRUCT_COUNT_SHIFT)\
+	& SDS_REGION_STRUCT_COUNT_MASK)
+#define GET_SDS_REGION_SCHEMA_VERSION(region)		\
+	(((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_SCH_MINOR_SHIFT)\
+	& SDS_REGION_SCH_VERSION_MASK)
+#define GET_SDS_REGION_SIZE(region)		((((region_desc_t *)(region))->reg[1]))
+
+#endif /* __ASSEMBLY__ */
+#endif /* __SDS_PRIVATE_H__ */
diff --git a/plat/hisilicon/hikey/aarch64/hikey_common.c b/plat/hisilicon/hikey/aarch64/hikey_common.c
index 20a95bf..02a00ac 100644
--- a/plat/hisilicon/hikey/aarch64/hikey_common.c
+++ b/plat/hisilicon/hikey/aarch64/hikey_common.c
@@ -28,6 +28,15 @@
 					TSP_SEC_MEM_SIZE,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+#define MAP_OPTEE_PAGEABLE	MAP_REGION_FLAT(		\
+					HIKEY_OPTEE_PAGEABLE_LOAD_BASE,	\
+					HIKEY_OPTEE_PAGEABLE_LOAD_SIZE,	\
+					MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+#endif
+
 #define MAP_ROM_PARAM	MAP_REGION_FLAT(XG2RAM0_BASE,			\
 					BL1_XG2RAM0_OFFSET,		\
 					MT_DEVICE | MT_RO | MT_SECURE)
@@ -64,6 +73,11 @@
 	MAP_DDR,
 	MAP_DEVICE,
 	MAP_TSP_MEM,
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+	MAP_OPTEE_PAGEABLE,
+#endif
+#endif
 	{0}
 };
 #endif
diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c
index 05e2e35..f59a545 100644
--- a/plat/hisilicon/hikey/hikey_bl1_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl1_setup.c
@@ -58,13 +58,35 @@
 	return &bl1_tzram_layout;
 }
 
+#if LOAD_IMAGE_V2
+/*******************************************************************************
+ * Function that takes a memory layout into which BL2 has been loaded and
+ * populates a new memory layout for BL2 that ensures that BL1's data sections
+ * resident in secure RAM are not visible to BL2.
+ ******************************************************************************/
+void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
+			     meminfo_t *bl2_mem_layout)
+{
+
+	assert(bl1_mem_layout != NULL);
+	assert(bl2_mem_layout != NULL);
+
+	/*
+	 * Cannot remove BL1 RW data from the scope of memory visible to BL2
+	 * like arm platforms because they overlap in hikey
+	 */
+	bl2_mem_layout->total_base = BL2_BASE;
+	bl2_mem_layout->total_size = BL32_SRAM_LIMIT - BL2_BASE;
+
+	flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
+}
+#endif /* LOAD_IMAGE_V2 */
+
 /*
  * Perform any BL1 specific platform actions.
  */
 void bl1_early_platform_setup(void)
 {
-	const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
-
 	/* Initialize the console to provide early debug support */
 	console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
 
@@ -72,16 +94,18 @@
 	bl1_tzram_layout.total_base = BL1_RW_BASE;
 	bl1_tzram_layout.total_size = BL1_RW_SIZE;
 
+#if !LOAD_IMAGE_V2
 	/* Calculate how much RAM BL1 is using and how much remains free */
 	bl1_tzram_layout.free_base = BL1_RW_BASE;
 	bl1_tzram_layout.free_size = BL1_RW_SIZE;
 	reserve_mem(&bl1_tzram_layout.free_base,
 		    &bl1_tzram_layout.free_size,
 		    BL1_RAM_BASE,
-		    bl1_size);
+		    BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */
+#endif
 
 	INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
-	     bl1_size);
+	     BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */
 }
 
 /*
diff --git a/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c b/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c
new file mode 100644
index 0000000..50ca015
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+	/* Fill SCP_BL2 related information if it exists */
+    {
+	    .image_id = SCP_BL2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = SCP_BL2_BASE,
+	    .image_info.image_max_size = SCP_BL2_SIZE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+	/* Fill EL3 payload related information (BL31 is EL3 payload)*/
+    {
+	    .image_id = BL31_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t,
+		    SECURE | EXECUTABLE | EP_FIRST_EXE),
+	    .ep_info.pc = EL3_PAYLOAD_BASE,
+	    .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+		    DISABLE_ALL_EXCEPTIONS),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t,
+		    IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+
+#else /* EL3_PAYLOAD_BASE */
+
+	/* Fill BL31 related information */
+    {
+	    .image_id = BL31_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t,
+		    SECURE | EXECUTABLE | EP_FIRST_EXE),
+	    .ep_info.pc = BL31_BASE,
+	    .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+		    DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+	    .ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL,
+#endif
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+	    .image_info.image_base = BL31_BASE,
+	    .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+	    .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+    },
+
+# ifdef BL32_BASE
+	/* Fill BL32 related information */
+    {
+	    .image_id = BL32_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+	    .ep_info.pc = BL32_BASE,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+    },
+
+	/*
+	 * Fill BL32 external 1 related information.
+	 * A typical use for extra1 image is with OP-TEE where it is the pager image.
+	 */
+    {
+	    .image_id = BL32_EXTRA1_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+
+	/*
+	 * Fill BL32 external 2 related information.
+	 * A typical use for extra2 image is with OP-TEE where it is the paged image.
+	 */
+    {
+	    .image_id = BL32_EXTRA2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+	    .image_info.image_base = HIKEY_OPTEE_PAGEABLE_LOAD_BASE,
+	    .image_info.image_max_size = HIKEY_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+# endif /* BL32_BASE */
+
+	/* Fill BL33 related information */
+    {
+	    .image_id = BL33_IMAGE_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+	    .ep_info.pc = PRELOADED_BL33_BASE,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+	    .ep_info.pc = HIKEY_NS_IMAGE_OFFSET,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = HIKEY_NS_IMAGE_OFFSET,
+	    .image_info.image_max_size = 0x200000 /* 2MB */,
+# endif /* PRELOADED_BL33_BASE */
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index 13dc6c9..86c205d 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -9,6 +9,7 @@
 #include <bl_common.h>
 #include <console.h>
 #include <debug.h>
+#include <desc_image_load.h>
 #include <dw_mmc.h>
 #include <emmc.h>
 #include <errno.h>
@@ -16,6 +17,11 @@
 #include <hisi_mcu.h>
 #include <hisi_sram_map.h>
 #include <mmio.h>
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
+#endif
 #include <platform_def.h>
 #include <sp804_delay_timer.h>
 #include <string.h>
@@ -44,6 +50,13 @@
 
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
+#if !LOAD_IMAGE_V2
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL31, e.g. while passing control to it from BL2, bl31_params
+ * and other platform specific params
+ ******************************************************************************/
 typedef struct bl2_to_bl31_params_mem {
 	bl31_params_t		bl31_params;
 	image_info_t		bl31_image_info;
@@ -68,8 +81,17 @@
 	scp_bl2_meminfo->free_base = SCP_BL2_BASE;
 	scp_bl2_meminfo->free_size = SCP_BL2_SIZE;
 }
+#endif /* LOAD_IMAGE_V2 */
 
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+#if LOAD_IMAGE_V2
+int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+#else
 int bl2_plat_handle_scp_bl2(struct image_info *scp_bl2_image_info)
+#endif
 {
 	/* Enable MCU SRAM */
 	hisi_mcu_enable_sram();
@@ -87,6 +109,121 @@
 	return 0;
 }
 
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t hikey_get_spsr_for_bl32_entry(void)
+{
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL3-2 image.
+	 */
+	return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifndef AARCH32
+uint32_t hikey_get_spsr_for_bl33_entry(void)
+{
+	unsigned int mode;
+	uint32_t spsr;
+
+	/* Figure out what mode we enter the non-secure world in */
+	mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+#else
+uint32_t hikey_get_spsr_for_bl33_entry(void)
+{
+	unsigned int hyp_status, mode, spsr;
+
+	hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+	mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+			SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+#endif /* AARCH32 */
+
+#if LOAD_IMAGE_V2
+int hikey_bl2_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+	assert(bl_mem_params);
+
+	switch (image_id) {
+#ifdef AARCH64
+	case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+				&pager_mem_params->image_info,
+				&paged_mem_params->image_info);
+		if (err != 0) {
+			WARN("OPTEE header parse error.\n");
+		}
+#endif
+		bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry();
+		break;
+#endif
+
+	case BL33_IMAGE_ID:
+		/* BL33 expects to receive the primary CPU MPID (through r0) */
+		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+		bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry();
+		break;
+
+#ifdef SCP_BL2_BASE
+	case SCP_BL2_IMAGE_ID:
+		/* The subsequent handling of SCP_BL2 is platform specific */
+		err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+		if (err) {
+			WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+		}
+		break;
+#endif
+	}
+
+	return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	return hikey_bl2_handle_post_image_load(image_id);
+}
+
+#else /* LOAD_IMAGE_V2 */
+
 bl31_params_t *bl2_plat_get_bl31_params(void)
 {
 	bl31_params_t *bl2_to_bl31_params = NULL;
@@ -107,7 +244,7 @@
 		VERSION_1, 0);
 
 	/* Fill BL3-2 related information if it exists */
-#if BL32_BASE
+#ifdef BL32_BASE
 	bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
 	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
 		VERSION_1, 0);
@@ -133,6 +270,10 @@
 
 struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
 {
+#if DEBUG
+	bl31_params_mem.bl31_ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL;
+#endif
+
 	return &bl31_params_mem.bl31_ep_info;
 }
 
@@ -217,6 +358,7 @@
 	bl33_meminfo->free_base = DDR_BASE;
 	bl33_meminfo->free_size = DDR_SIZE;
 }
+#endif /* LOAD_IMAGE_V2 */
 
 static void reset_dwmmc_clk(void)
 {
diff --git a/plat/hisilicon/hikey/hikey_bl31_setup.c b/plat/hisilicon/hikey/hikey_bl31_setup.c
index 82bd97e..c592fc7 100644
--- a/plat/hisilicon/hikey/hikey_bl31_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl31_setup.c
@@ -69,7 +69,7 @@
 	CCI400_SL_IFACE4_CLUSTER_IX
 };
 
-entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
 	entry_point_info_t *next_image_info;
 
@@ -81,8 +81,13 @@
 	return NULL;
 }
 
+#if LOAD_IMAGE_V2
+void bl31_early_platform_setup(void *from_bl2,
+			       void *plat_params_from_bl2)
+#else
 void bl31_early_platform_setup(bl31_params_t *from_bl2,
 			       void *plat_params_from_bl2)
+#endif
 {
 	/* Initialize the console to provide early debug support */
 	console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
@@ -91,12 +96,50 @@
 	cci_init(CCI400_BASE, cci_map, ARRAY_SIZE(cci_map));
 	cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
 
+#if LOAD_IMAGE_V2
+	/*
+	 * Check params passed from BL2 should not be NULL,
+	 */
+	bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+	assert(params_from_bl2 != NULL);
+	assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+	assert(params_from_bl2->h.version >= VERSION_2);
+
+	bl_params_node_t *bl_params = params_from_bl2->head;
+
+	/*
+	 * Copy BL33 and BL32 (if present), entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	while (bl_params) {
+		if (bl_params->image_id == BL32_IMAGE_ID)
+			bl32_ep_info = *bl_params->ep_info;
+
+		if (bl_params->image_id == BL33_IMAGE_ID)
+			bl33_ep_info = *bl_params->ep_info;
+
+		bl_params = bl_params->next_params_info;
+	}
+
+	if (bl33_ep_info.pc == 0)
+		panic();
+
+#else /* LOAD_IMAGE_V2 */
+
+	/*
+	 * Check params passed from BL2 should not be NULL,
+	 */
+	assert(from_bl2 != NULL);
+	assert(from_bl2->h.type == PARAM_BL31);
+	assert(from_bl2->h.version >= VERSION_1);
+
 	/*
 	 * Copy BL3-2 and BL3-3 entry point information.
 	 * They are stored in Secure RAM, in BL2's address space.
 	 */
 	bl32_ep_info = *from_bl2->bl32_ep_info;
 	bl33_ep_info = *from_bl2->bl33_ep_info;
+#endif /* LOAD_IMAGE_V2 */
 }
 
 void bl31_plat_arch_setup(void)
diff --git a/plat/hisilicon/hikey/hikey_def.h b/plat/hisilicon/hikey/hikey_def.h
index bbad10f..668b459 100644
--- a/plat/hisilicon/hikey/hikey_def.h
+++ b/plat/hisilicon/hikey/hikey_def.h
@@ -33,7 +33,7 @@
  *   - Non-secure DDR (8MB) reserved for OP-TEE's future use
  */
 #define DDR_SEC_SIZE			0x01000000
-#define DDR_SEC_BASE			(DDR_BASE + DDR_SIZE - DDR_SEC_SIZE)
+#define DDR_SEC_BASE			(DDR_BASE + DDR_SIZE - DDR_SEC_SIZE) /* 0x3F000000 */
 
 #define DDR_SDP_SIZE			0x00400000
 #define DDR_SDP_BASE			(DDR_SEC_BASE - 0x400000 /* align */ - \
diff --git a/plat/hisilicon/hikey/hikey_image_load.c b/plat/hisilicon/hikey/hikey_image_load.c
new file mode 100644
index 0000000..32ca36d
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_image_load.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/hisilicon/hikey/hikey_io_storage.c b/plat/hisilicon/hikey/hikey_io_storage.c
index c61ec2c..60ec42b 100644
--- a/plat/hisilicon/hikey/hikey_io_storage.c
+++ b/plat/hisilicon/hikey/hikey_io_storage.c
@@ -77,6 +77,14 @@
 	.uuid = UUID_SECURE_PAYLOAD_BL32,
 };
 
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -111,6 +119,16 @@
 		(uintptr_t)&bl32_uuid_spec,
 		check_fip
 	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		check_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		check_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/hisilicon/hikey/include/platform_def.h b/plat/hisilicon/hikey/include/platform_def.h
index af15232..0180654 100644
--- a/plat/hisilicon/hikey/include/platform_def.h
+++ b/plat/hisilicon/hikey/include/platform_def.h
@@ -10,6 +10,9 @@
 #include <arch.h>
 #include "../hikey_def.h"
 
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define HIKEY_BL31_PLAT_PARAM_VAL	0x0f1e2d3c4b5a6978ULL
+
 /*
  * Generic platform constants
  */
@@ -94,7 +97,7 @@
 /*
  * BL31 specific defines.
  */
-#define BL31_BASE			BL2_LIMIT
+#define BL31_BASE			BL2_LIMIT /* 0xf985_8000 */
 #define BL31_LIMIT			0xF9898000
 
 /*
@@ -110,6 +113,14 @@
 #define BL32_DRAM_BASE			DDR_SEC_BASE
 #define BL32_DRAM_LIMIT			(DDR_SEC_BASE+DDR_SEC_SIZE)
 
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define HIKEY_OPTEE_PAGEABLE_LOAD_BASE	(BL32_DRAM_LIMIT - HIKEY_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */
+#define HIKEY_OPTEE_PAGEABLE_LOAD_SIZE	0x400000 /* 4MB */
+#endif
+#endif
+
 #if (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_DRAM_ID)
 #define TSP_SEC_MEM_BASE		BL32_DRAM_BASE
 #define TSP_SEC_MEM_SIZE		(BL32_DRAM_LIMIT - BL32_DRAM_BASE)
@@ -124,6 +135,13 @@
 #error "Currently unsupported HIKEY_TSP_LOCATION_ID value"
 #endif
 
+/* BL32 is mandatory in AArch32 */
+#ifndef AARCH32
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
 #define NS_BL1U_BASE			(BL2_BASE)
 #define NS_BL1U_SIZE			(0x00010000)
 #define NS_BL1U_LIMIT			(NS_BL1U_BASE + NS_BL1U_SIZE)
@@ -133,7 +151,7 @@
  */
 #define ADDR_SPACE_SIZE			(1ull << 32)
 
-#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL32
+#if IMAGE_BL1 || IMAGE_BL32
 #define MAX_XLAT_TABLES			3
 #endif
 
@@ -141,6 +159,18 @@
 #define MAX_XLAT_TABLES			4
 #endif
 
+#if IMAGE_BL2
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+#define MAX_XLAT_TABLES			4
+#else
+#define MAX_XLAT_TABLES			3
+#endif
+#else
+#define MAX_XLAT_TABLES			3
+#endif
+#endif
+
 #define MAX_MMAP_REGIONS		16
 
 #define HIKEY_NS_IMAGE_OFFSET		(DDR_BASE + 0x35000000)
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
index 8da3998..26218a4 100644
--- a/plat/hisilicon/hikey/platform.mk
+++ b/plat/hisilicon/hikey/platform.mk
@@ -4,6 +4,9 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Enable version2 of image loading
+LOAD_IMAGE_V2	:=	1
+
 # On Hikey, the TSP can execute from TZC secure area in DRAM (default)
 # or SRAM.
 HIKEY_TSP_RAM_LOCATION	:=	dram
@@ -29,6 +32,15 @@
 $(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
 $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
 
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call FIP_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call FIP_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+
 ENABLE_PLAT_COMPAT	:=	0
 
 USE_COHERENT_MEM	:=	1
@@ -70,6 +82,16 @@
 				plat/hisilicon/hikey/hisi_dvfs.c	\
 				plat/hisilicon/hikey/hisi_mcu.c
 
+ifeq (${LOAD_IMAGE_V2},1)
+BL2_SOURCES		+=	plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c \
+				plat/hisilicon/hikey/hikey_image_load.c \
+				common/desc_image_load.c
+
+ifeq (${SPD},opteed)
+BL2_SOURCES		+=	lib/optee/optee_utils.c
+endif
+endif
+
 HIKEY_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v2/gicv2_main.c		\
 				drivers/arm/gic/v2/gicv2_helpers.c	\
diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/plat/hisilicon/hikey960/aarch64/hikey960_common.c
index 7068fb6..bce0c96 100644
--- a/plat/hisilicon/hikey960/aarch64/hikey960_common.c
+++ b/plat/hisilicon/hikey960/aarch64/hikey960_common.c
@@ -41,6 +41,15 @@
 					TSP_SEC_MEM_SIZE,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+#define MAP_OPTEE_PAGEABLE	MAP_REGION_FLAT(		\
+					HIKEY960_OPTEE_PAGEABLE_LOAD_BASE,	\
+					HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE,	\
+					MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+#endif
+
 /*
  * Table of regions for different BL stages to map using the MMU.
  * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
@@ -61,6 +70,11 @@
 	MAP_DDR,
 	MAP_DEVICE,
 	MAP_TSP_MEM,
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+	MAP_OPTEE_PAGEABLE,
+#endif
+#endif
 	{0}
 };
 #endif
diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
index 54e7347..6dfada7 100644
--- a/plat/hisilicon/hikey960/hikey960_bl1_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
@@ -74,12 +74,35 @@
 	return &bl1_tzram_layout;
 }
 
+#if LOAD_IMAGE_V2
+/*******************************************************************************
+ * Function that takes a memory layout into which BL2 has been loaded and
+ * populates a new memory layout for BL2 that ensures that BL1's data sections
+ * resident in secure RAM are not visible to BL2.
+ ******************************************************************************/
+void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
+			     meminfo_t *bl2_mem_layout)
+{
+
+	assert(bl1_mem_layout != NULL);
+	assert(bl2_mem_layout != NULL);
+
+	/*
+	 * Cannot remove BL1 RW data from the scope of memory visible to BL2
+	 * like arm platforms because they overlap in hikey960
+	 */
+	bl2_mem_layout->total_base = BL2_BASE;
+	bl2_mem_layout->total_size = NS_BL1U_LIMIT - BL2_BASE;
+
+	flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
+}
+#endif /* LOAD_IMAGE_V2 */
+
 /*
  * Perform any BL1 specific platform actions.
  */
 void bl1_early_platform_setup(void)
 {
-	const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
 	unsigned int id, uart_base;
 
 	generic_delay_timer_init();
@@ -95,16 +118,18 @@
 	bl1_tzram_layout.total_base = BL1_RW_BASE;
 	bl1_tzram_layout.total_size = BL1_RW_SIZE;
 
+#if !LOAD_IMAGE_V2
 	/* Calculate how much RAM BL1 is using and how much remains free */
 	bl1_tzram_layout.free_base = BL1_RW_BASE;
 	bl1_tzram_layout.free_size = BL1_RW_SIZE;
 	reserve_mem(&bl1_tzram_layout.free_base,
 		    &bl1_tzram_layout.free_size,
 		    BL1_RAM_BASE,
-		    bl1_size);
+		    BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */
+#endif /* LOAD_IMAGE_V2 */
 
 	INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
-	     bl1_size);
+	     BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */
 }
 
 /*
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c b/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c
new file mode 100644
index 0000000..b59f897
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+	/* Fill SCP_BL2 related information if it exists */
+    {
+	    .image_id = SCP_BL2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = SCP_BL2_BASE,
+	    .image_info.image_max_size = SCP_BL2_SIZE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+	/* Fill EL3 payload related information (BL31 is EL3 payload)*/
+    {
+	    .image_id = BL31_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t,
+		    SECURE | EXECUTABLE | EP_FIRST_EXE),
+	    .ep_info.pc = EL3_PAYLOAD_BASE,
+	    .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+		    DISABLE_ALL_EXCEPTIONS),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t,
+		    IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+
+#else /* EL3_PAYLOAD_BASE */
+
+	/* Fill BL31 related information */
+    {
+	    .image_id = BL31_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t,
+		    SECURE | EXECUTABLE | EP_FIRST_EXE),
+	    .ep_info.pc = BL31_BASE,
+	    .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+		    DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+	    .ep_info.args.arg1 = HIKEY960_BL31_PLAT_PARAM_VAL,
+#endif
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+	    .image_info.image_base = BL31_BASE,
+	    .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+	    .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+    },
+
+# ifdef BL32_BASE
+	/* Fill BL32 related information */
+    {
+	    .image_id = BL32_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+	    .ep_info.pc = BL32_BASE,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+    },
+
+	/*
+	 * Fill BL32 external 1 related information.
+	 * A typical use for extra1 image is with OP-TEE where it is the pager image.
+	 */
+    {
+	    .image_id = BL32_EXTRA1_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+
+	/*
+	 * Fill BL32 external 2 related information.
+	 * A typical use for extra2 image is with OP-TEE where it is the paged image.
+	 */
+    {
+	    .image_id = BL32_EXTRA2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+	    .image_info.image_base = HIKEY960_OPTEE_PAGEABLE_LOAD_BASE,
+	    .image_info.image_max_size = HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    },
+# endif /* BL32_BASE */
+
+	/* Fill BL33 related information */
+    {
+	    .image_id = BL33_IMAGE_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+	    .ep_info.pc = PRELOADED_BL33_BASE,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+	    .ep_info.pc = NS_BL1U_BASE,
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = NS_BL1U_BASE,
+	    .image_info.image_max_size = 0x200000 /* 2MB */,
+# endif /* PRELOADED_BL33_BASE */
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+    }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
index de676a7..b50ed87 100644
--- a/plat/hisilicon/hikey960/hikey960_bl2_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
@@ -9,10 +9,16 @@
 #include <bl_common.h>
 #include <console.h>
 #include <debug.h>
+#include <desc_image_load.h>
 #include <errno.h>
 #include <generic_delay_timer.h>
 #include <hi3660.h>
 #include <mmio.h>
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
+#endif
 #include <platform_def.h>
 #include <string.h>
 #include <ufs.h>
@@ -41,6 +47,13 @@
 
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
+#if !LOAD_IMAGE_V2
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL31, e.g. while passing control to it from BL2, bl31_params
+ * and other platform specific params
+ ******************************************************************************/
 typedef struct bl2_to_bl31_params_mem {
 	bl31_params_t		bl31_params;
 	image_info_t		bl31_image_info;
@@ -78,7 +91,7 @@
 		VERSION_1, 0);
 
 	/* Fill BL3-2 related information if it exists */
-#if BL32_BASE
+#ifdef BL32_BASE
 	bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
 	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
 		VERSION_1, 0);
@@ -108,28 +121,29 @@
  ******************************************************************************/
 void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)
 {
-	ufs_params_t ufs_params;
-
-	memset(&ufs_params, 0, sizeof(ufs_params_t));
-	ufs_params.reg_base = UFS_REG_BASE;
-	ufs_params.desc_base = HIKEY960_UFS_DESC_BASE;
-	ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE;
-	ufs_params.flags = UFS_FLAGS_SKIPINIT;
-	ufs_init(NULL, &ufs_params);
-
+	hikey960_init_ufs();
 	hikey960_io_setup();
 
 	*scp_bl2_meminfo = bl2_tzram_layout;
 }
+#endif /* LOAD_IMAGE_V2 */
 
 extern int load_lpm3(void);
 
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+#if LOAD_IMAGE_V2
+int plat_hikey960_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+#else
 int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+#endif
 {
 	int i;
 	int *buf;
 
-	assert(scp_bl2_image_info->image_size < SCP_MEM_SIZE);
+	assert(scp_bl2_image_info->image_size < SCP_BL2_SIZE);
 
 	INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
 
@@ -152,10 +166,6 @@
 		INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n",
 			buf[i], buf[i+1], buf[i+2], buf[i+3]);
 
-	memcpy((void *)SCP_MEM_BASE,
-	       (void *)scp_bl2_image_info->image_base,
-	       scp_bl2_image_info->image_size);
-
 	INFO("BL2: SCP_BL2 transferred to SCP\n");
 
 	load_lpm3();
@@ -164,8 +174,139 @@
 	return 0;
 }
 
+void hikey960_init_ufs(void)
+{
+	ufs_params_t ufs_params;
+
+	memset(&ufs_params, 0, sizeof(ufs_params_t));
+	ufs_params.reg_base = UFS_REG_BASE;
+	ufs_params.desc_base = HIKEY960_UFS_DESC_BASE;
+	ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE;
+	ufs_params.flags = UFS_FLAGS_SKIPINIT;
+	ufs_init(NULL, &ufs_params);
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t hikey960_get_spsr_for_bl32_entry(void)
+{
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL3-2 image.
+	 */
+	return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifndef AARCH32
+uint32_t hikey960_get_spsr_for_bl33_entry(void)
+{
+	unsigned int mode;
+	uint32_t spsr;
+
+	/* Figure out what mode we enter the non-secure world in */
+	mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+#else
+uint32_t hikey960_get_spsr_for_bl33_entry(void)
+{
+	unsigned int hyp_status, mode, spsr;
+
+	hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+	mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+			SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+#endif /* AARCH32 */
+
+#if LOAD_IMAGE_V2
+int hikey960_bl2_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+	assert(bl_mem_params);
+
+	switch (image_id) {
+#ifdef AARCH64
+	case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+				&pager_mem_params->image_info,
+				&paged_mem_params->image_info);
+		if (err != 0) {
+			WARN("OPTEE header parse error.\n");
+		}
+#endif
+		bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl32_entry();
+		break;
+#endif
+
+	case BL33_IMAGE_ID:
+		/* BL33 expects to receive the primary CPU MPID (through r0) */
+		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+		bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl33_entry();
+		break;
+
+#ifdef SCP_BL2_BASE
+	case SCP_BL2_IMAGE_ID:
+		/* The subsequent handling of SCP_BL2 is platform specific */
+		err = plat_hikey960_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+		if (err) {
+			WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+		}
+		break;
+#endif
+	}
+
+	return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	return hikey960_bl2_handle_post_image_load(image_id);
+}
+
+#else /* LOAD_IMAGE_V2 */
+
 struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
 {
+#if DEBUG
+	bl31_params_mem.bl31_ep_info.args.arg1 = HIKEY960_BL31_PLAT_PARAM_VAL;
+#endif
+
 	return &bl31_params_mem.bl31_ep_info;
 }
 
@@ -250,6 +391,7 @@
 	bl33_meminfo->free_base = DDR_BASE;
 	bl33_meminfo->free_size = DDR_SIZE;
 }
+#endif /* LOAD_IMAGE_V2 */
 
 void bl2_early_platform_setup(meminfo_t *mem_layout)
 {
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index 41c591b..f685f9c 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -64,7 +64,7 @@
 	CCI400_SL_IFACE4_CLUSTER_IX
 };
 
-entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
 	entry_point_info_t *next_image_info;
 
@@ -76,8 +76,13 @@
 	return NULL;
 }
 
+#if LOAD_IMAGE_V2
+void bl31_early_platform_setup(void *from_bl2,
+			       void *plat_params_from_bl2)
+#else
 void bl31_early_platform_setup(bl31_params_t *from_bl2,
 		void *plat_params_from_bl2)
+#endif
 {
 	unsigned int id, uart_base;
 
@@ -95,12 +100,50 @@
 	cci_init(CCI400_REG_BASE, cci_map, ARRAY_SIZE(cci_map));
 	cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
 
+#if LOAD_IMAGE_V2
+	/*
+	 * Check params passed from BL2 should not be NULL,
+	 */
+	bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+	assert(params_from_bl2 != NULL);
+	assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+	assert(params_from_bl2->h.version >= VERSION_2);
+
+	bl_params_node_t *bl_params = params_from_bl2->head;
+
+	/*
+	 * Copy BL33 and BL32 (if present), entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	while (bl_params) {
+		if (bl_params->image_id == BL32_IMAGE_ID)
+			bl32_ep_info = *bl_params->ep_info;
+
+		if (bl_params->image_id == BL33_IMAGE_ID)
+			bl33_ep_info = *bl_params->ep_info;
+
+		bl_params = bl_params->next_params_info;
+	}
+
+	if (bl33_ep_info.pc == 0)
+		panic();
+
+#else /* LOAD_IMAGE_V2 */
+
+	/*
+	 * Check params passed from BL2 should not be NULL,
+	 */
+	assert(from_bl2 != NULL);
+	assert(from_bl2->h.type == PARAM_BL31);
+	assert(from_bl2->h.version >= VERSION_1);
+
 	/*
 	 * Copy BL3-2 and BL3-3 entry point information.
 	 * They are stored in Secure RAM, in BL2's address space.
 	 */
 	bl32_ep_info = *from_bl2->bl32_ep_info;
 	bl33_ep_info = *from_bl2->bl33_ep_info;
+#endif /* LOAD_IMAGE_V2 */
 }
 
 void bl31_plat_arch_setup(void)
diff --git a/plat/hisilicon/hikey960/hikey960_image_load.c b/plat/hisilicon/hikey960/hikey960_image_load.c
new file mode 100644
index 0000000..8e91adb
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_image_load.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+
+#include "hikey960_private.h"
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+	/* Required before loading scp_bl2 */
+	hikey960_init_ufs();
+	hikey960_io_setup();
+
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/hisilicon/hikey960/hikey960_io_storage.c b/plat/hisilicon/hikey960/hikey960_io_storage.c
index 57d97e5..1a1d846 100644
--- a/plat/hisilicon/hikey960/hikey960_io_storage.c
+++ b/plat/hisilicon/hikey960/hikey960_io_storage.c
@@ -73,6 +73,14 @@
 	.uuid = UUID_SECURE_PAYLOAD_BL32,
 };
 
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -103,6 +111,16 @@
 		(uintptr_t)&bl32_uuid_spec,
 		check_fip
 	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		check_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		check_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/hisilicon/hikey960/hikey960_private.h b/plat/hisilicon/hikey960/hikey960_private.h
index 8f2a842..e3c9d21 100644
--- a/plat/hisilicon/hikey960/hikey960_private.h
+++ b/plat/hisilicon/hikey960/hikey960_private.h
@@ -24,6 +24,7 @@
 			unsigned long ro_limit,
 			unsigned long coh_start,
 			unsigned long coh_limit);
+void hikey960_init_ufs(void);
 void hikey960_io_setup(void);
 int hikey960_read_boardid(unsigned int *id);
 void set_retention_ticks(unsigned int val);
diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h
index 8bf32c3..202952c 100644
--- a/plat/hisilicon/hikey960/include/platform_def.h
+++ b/plat/hisilicon/hikey960/include/platform_def.h
@@ -10,6 +10,8 @@
 #include <arch.h>
 #include "../hikey960_def.h"
 
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define HIKEY960_BL31_PLAT_PARAM_VAL	0x0f1e2d3c4b5a6978ULL
 
 /*
  * Generic platform constants
@@ -73,6 +75,14 @@
 #define BL32_DRAM_BASE                  DDR_SEC_BASE
 #define BL32_DRAM_LIMIT                 (DDR_SEC_BASE+DDR_SEC_SIZE)
 
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define HIKEY960_OPTEE_PAGEABLE_LOAD_BASE	(BL32_DRAM_LIMIT - HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */
+#define HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE	0x400000 /* 4MB */
+#endif
+#endif
+
 #if (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_DRAM_ID)
 #define TSP_SEC_MEM_BASE		BL32_DRAM_BASE
 #define TSP_SEC_MEM_SIZE		(BL32_DRAM_LIMIT - BL32_DRAM_BASE)
@@ -84,6 +94,13 @@
 #error "Currently unsupported HIKEY960_TSP_LOCATION_ID value"
 #endif
 
+/* BL32 is mandatory in AArch32 */
+#ifndef AARCH32
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
 #define NS_BL1U_BASE			(BL31_LIMIT)		/* 1AC9_8000 */
 #define NS_BL1U_SIZE			(0x00100000)
 #define NS_BL1U_LIMIT			(NS_BL1U_BASE + NS_BL1U_SIZE)
@@ -91,20 +108,30 @@
 #define HIKEY960_NS_IMAGE_OFFSET	(0x1AC18000)	/* offset in l-loader */
 #define HIKEY960_NS_TMP_OFFSET		(0x1AE00000)
 
-#define SCP_BL2_BASE			BL31_BASE /* 1AC5_8000 */
-
-#define SCP_MEM_BASE			(0x89C80000)
-#define SCP_MEM_SIZE			(0x00040000)
+#define SCP_BL2_BASE			(0x89C80000)
+#define SCP_BL2_SIZE			(0x00040000)
 
 /*
  * Platform specific page table and MMU setup constants
  */
 #define ADDR_SPACE_SIZE			(1ull << 32)
 
-#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL31 || IMAGE_BL32
+#if IMAGE_BL1 || IMAGE_BL31 || IMAGE_BL32
 #define MAX_XLAT_TABLES			3
 #endif
 
+#if IMAGE_BL2
+#if LOAD_IMAGE_V2
+#ifdef SPD_opteed
+#define MAX_XLAT_TABLES			4
+#else
+#define MAX_XLAT_TABLES			3
+#endif
+#else
+#define MAX_XLAT_TABLES			3
+#endif
+#endif
+
 #define MAX_MMAP_REGIONS		16
 
 /*
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index edbce63..da7bb82 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -4,6 +4,9 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Enable version2 of image loading
+LOAD_IMAGE_V2	:=	1
+
 # On Hikey960, the TSP can execute from TZC secure area in DRAM.
 HIKEY960_TSP_RAM_LOCATION	:=	dram
 ifeq (${HIKEY960_TSP_RAM_LOCATION}, dram)
@@ -22,6 +25,15 @@
 $(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID))
 $(eval $(call add_define,CRASH_CONSOLE_BASE))
 
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call FIP_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call FIP_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+
 ENABLE_PLAT_COMPAT	:=	0
 
 USE_COHERENT_MEM	:=	1
@@ -61,6 +73,16 @@
 				plat/hisilicon/hikey960/hikey960_io_storage.c \
 				plat/hisilicon/hikey960/hikey960_mcu_load.c
 
+ifeq (${LOAD_IMAGE_V2},1)
+BL2_SOURCES		+=	plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c \
+				plat/hisilicon/hikey960/hikey960_image_load.c \
+				common/desc_image_load.c
+
+ifeq (${SPD},opteed)
+BL2_SOURCES		+=	lib/optee/optee_utils.c
+endif
+endif
+
 BL31_SOURCES		+=	drivers/arm/cci/cci.c			\
 				lib/cpus/aarch64/cortex_a53.S           \
 				lib/cpus/aarch64/cortex_a72.S		\
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index eae76df..437b692 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -10,6 +10,7 @@
 DEBUG		:= 0
 BINARY		:= ${PROJECT}${BIN_EXT}
 OPENSSL_DIR	:= /usr
+USE_TBBR_DEFS   := 1
 
 OBJECTS := src/cert.o \
            src/cmd_opt.o \
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
index 543f122..256e7af 100644
--- a/tools/cert_create/include/cert.h
+++ b/tools/cert_create/include/cert.h
@@ -48,7 +48,7 @@
 int cert_init(void);
 cert_t *cert_get_by_opt(const char *opt);
 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value);
-int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk);
+int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk);
 
 /* Macro to register the certificates used in the CoT */
 #define REGISTER_COT(_certs) \
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
index 4b9e882..304fa61 100644
--- a/tools/cert_create/include/key.h
+++ b/tools/cert_create/include/key.h
@@ -22,7 +22,8 @@
 
 /* Supported key algorithms */
 enum {
-	KEY_ALG_RSA,
+	KEY_ALG_RSA,		/* RSA PSS as defined by PKCS#1 v2.1 (default) */
+	KEY_ALG_RSA_1_5,	/* RSA as defined by PKCS#1 v1.5 */
 #ifndef OPENSSL_NO_EC
 	KEY_ALG_ECDSA,
 #endif /* OPENSSL_NO_EC */
diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c
index 9775664..1b84e36 100644
--- a/tools/cert_create/src/cert.c
+++ b/tools/cert_create/src/cert.c
@@ -79,7 +79,7 @@
 	return 1;
 }
 
-int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
+int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
 {
 	EVP_PKEY *pkey = keys[cert->key].key;
 	cert_t *issuer_cert = &certs[cert->issuer];
@@ -90,7 +90,7 @@
 	X509_NAME *name;
 	ASN1_INTEGER *sno;
 	int i, num, rc = 0;
-	EVP_MD_CTX  mdCtx;
+	EVP_MD_CTX mdCtx;
 	EVP_PKEY_CTX *pKeyCtx = NULL;
 
 	/* Create the certificate structure */
@@ -112,24 +112,32 @@
 	}
 
 	EVP_MD_CTX_init(&mdCtx);
+
+	/* Sign the certificate with the issuer key */
 	if (!EVP_DigestSignInit(&mdCtx, &pKeyCtx, EVP_sha256(), NULL, ikey)) {
 		ERR_print_errors_fp(stdout);
 		goto END;
 	}
 
-	if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
-		ERR_print_errors_fp(stdout);
-		goto END;
-	}
+	/*
+	 * Set additional parameters if algorithm is RSA PSS. This is not
+	 * required for RSA 1.5 or ECDSA.
+	 */
+	if (key_alg == KEY_ALG_RSA) {
+		if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
+			ERR_print_errors_fp(stdout);
+			goto END;
+		}
 
-	if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) {
-		ERR_print_errors_fp(stdout);
-		goto END;
-	}
+		if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) {
+			ERR_print_errors_fp(stdout);
+			goto END;
+		}
 
-	if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, EVP_sha256())) {
-		ERR_print_errors_fp(stdout);
-		goto END;
+		if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, EVP_sha256())) {
+			ERR_print_errors_fp(stdout);
+			goto END;
+		}
 	}
 
 	/* x509.v3 */
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index f14601c..df59961 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -89,6 +89,7 @@
 
 static const char *key_algs_str[] = {
 	[KEY_ALG_RSA] = "rsa",
+	[KEY_ALG_RSA_1_5] = "rsa_1_5",
 #ifndef OPENSSL_NO_EC
 	[KEY_ALG_ECDSA] = "ecdsa"
 #endif /* OPENSSL_NO_EC */
@@ -223,7 +224,8 @@
 	},
 	{
 		{ "key-alg", required_argument, NULL, 'a' },
-		"Key algorithm: 'rsa' (default), 'ecdsa'"
+		"Key algorithm: 'rsa' (default) - RSAPSS scheme as per \
+PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'"
 	},
 	{
 		{ "save-keys", no_argument, NULL, 'k' },
@@ -450,8 +452,8 @@
 			sk_X509_EXTENSION_push(sk, cert_ext);
 		}
 
-		/* Create certificate. Signed with ROT key */
-		if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) {
+		/* Create certificate. Signed with corresponding key */
+		if (cert->fn && !cert_new(key_alg, cert, VAL_DAYS, 0, sk)) {
 			ERROR("Cannot create %s\n", cert->cn);
 			exit(1);
 		}