Merge pull request #584 from soby-mathew/sm/enable_scr_sif

Enable SCR_EL3.SIF bit
diff --git a/.gitignore b/.gitignore
index cc5cbfb..7447227 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,12 @@
 # Ignore build products from tools
 tools/**/*.o
 tools/fip_create/fip_create
+tools/fip_create/fip_create.exe
 tools/cert_create/src/*.o
 tools/cert_create/src/**/*.o
 tools/cert_create/cert_create
+tools/cert_create/cert_create.exe
+
+# Ignore header files copied.
+tools/fip_create/firmware_image_package.h
+tools/fip_create/uuid.h
diff --git a/Makefile b/Makefile
index d7a7a36..b2ca916 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,9 @@
 # Default goal is build all images
 .DEFAULT_GOAL			:= all
 
-include make_helpers/build_macros.mk
+MAKE_HELPERS_DIRECTORY := make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
 
 ################################################################################
 # Default values for build configurations
@@ -111,9 +113,10 @@
 CHECKPATCH_ARGS		:=	--no-tree --no-signoff ${CHECK_IGNORE}
 CHECKCODE_ARGS		:=	--no-patch --no-tree --no-signoff ${CHECK_IGNORE}
 # Do not check the coding style on C library files
-CHECK_PATHS		:=	$(shell ls -I include -I lib) \
-				$(addprefix include/,$(shell ls -I stdlib include)) \
-				$(addprefix lib/,$(shell ls -I stdlib lib))
+INCLUDE_DIRS_TO_CHECK	:=	$(sort $(filter-out include/stdlib, $(wildcard include/*)))
+LIB_DIRS_TO_CHECK	:=	$(sort $(filter-out lib/stdlib, $(wildcard lib/*)))
+ROOT_DIRS_TO_CHECK	:=	$(sort $(filter-out lib include, $(wildcard *))))
+CHECK_PATHS		:=	${ROOT_DIRS_TO_CHECK} ${INCLUDE_DIRS_TO_CHECK} ${LIB_DIRS_TO_CHECK}
 
 
 ################################################################################
@@ -122,10 +125,10 @@
 
 # Verbose flag
 ifeq (${V},0)
-        Q=@
+        Q:=@
         CHECKCODE_ARGS	+=	--no-summary --terse
 else
-        Q=
+        Q:=
 endif
 export Q
 
@@ -234,17 +237,12 @@
 # Generic definitions
 ################################################################################
 
+include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
+
 BUILD_BASE		:=	./build
 BUILD_PLAT		:=	${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
 
-PLAT_MAKEFILE		:=	platform.mk
-# Generate the platforms list by recursively searching for all directories
-# under /plat containing a PLAT_MAKEFILE. Append each platform with a `|`
-# char and strip out the final '|'.
-PLATFORMS		:=	$(shell find plat/ -name '${PLAT_MAKEFILE}' -print0 |			\
-					sed -r 's%[^\x00]*\/([^/]*)\/${PLAT_MAKEFILE}\x00%\1|%g' |	\
-					sed -r 's/\|$$//')
-SPDS			:=	$(shell ls -I none services/spd)
+SPDS			:=	$(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*))))
 
 # Platforms providing their own TBB makefile may override this value
 INCLUDE_TBBR_MK		:=	1
@@ -260,7 +258,7 @@
         $(warning "The SPD and its BL32 companion will be present but ignored.")
 endif
         # We expect to locate an spd.mk under the specified SPD directory
-        SPD_MAKE	:=	$(shell m="services/spd/${SPD}/${SPD}.mk"; [ -f "$$m" ] && echo "$$m")
+        SPD_MAKE	:=	$(wildcard services/spd/${SPD}/${SPD}.mk)
 
         ifeq (${SPD_MAKE},)
                 $(error Error: No services/spd/${SPD}/${SPD}.mk located)
@@ -285,14 +283,6 @@
 # makefile may use all previous definitions in this file)
 ################################################################################
 
-ifeq (${PLAT},)
-        $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
-endif
-PLAT_MAKEFILE_FULL	:=	$(shell find plat/ -wholename '*/${PLAT}/${PLAT_MAKEFILE}')
-ifeq ($(PLAT_MAKEFILE_FULL),)
-        $(error "Error: Invalid platform. The following platforms are available: ${PLATFORMS}")
-endif
-
 include ${PLAT_MAKEFILE_FULL}
 
 # If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default
@@ -386,11 +376,11 @@
 
 # Variables for use with Certificate Generation Tool
 CRTTOOLPATH		?=	tools/cert_create
-CRTTOOL			?=	${CRTTOOLPATH}/cert_create
+CRTTOOL			?=	${CRTTOOLPATH}/cert_create${BIN_EXT}
 
 # Variables for use with Firmware Image Package
 FIPTOOLPATH		?=	tools/fip_create
-FIPTOOL			?=	${FIPTOOLPATH}/fip_create
+FIPTOOL			?=	${FIPTOOLPATH}/fip_create${BIN_EXT}
 
 
 ################################################################################
@@ -545,14 +535,14 @@
 
 clean:
 	@echo "  CLEAN"
-	${Q}rm -rf ${BUILD_PLAT}
+	$(call SHELL_REMOVE_DIR,${BUILD_PLAT})
 	${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
 
 realclean distclean:
 	@echo "  REALCLEAN"
-	${Q}rm -rf ${BUILD_BASE}
-	${Q}rm -f ${CURDIR}/cscope.*
+	$(call SHELL_REMOVE_DIR,${BUILD_BASE})
+	$(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*)
 	${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
 
@@ -573,24 +563,24 @@
 .PHONY: ${CRTTOOL}
 ${CRTTOOL}:
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH}
-	@echo
+	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
-	@echo
+	@${ECHO_BLANK_LINE}
 
 ifneq (${GENERATE_COT},0)
 certificates: ${CRT_DEPS} ${CRTTOOL}
 	${Q}${CRTTOOL} ${CRT_ARGS}
-	@echo
+	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@echo "Certificates can be found in ${BUILD_PLAT}"
-	@echo
+	@${ECHO_BLANK_LINE}
 endif
 
 ${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL}
 	${Q}${FIPTOOL} --dump ${FIP_ARGS} $@
-	@echo
+	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
-	@echo
+	@${ECHO_BLANK_LINE}
 
 ifneq (${GENERATE_COT},0)
 fwu_certificates: ${FWU_CRT_DEPS} ${CRTTOOL}
@@ -621,7 +611,7 @@
 	${Q}cscope -b -q -k
 
 help:
-	@echo "usage: ${MAKE} PLAT=<${PLATFORMS}> [OPTIONS] [TARGET]"
+	@echo "usage: ${MAKE} PLAT=<${PLATFORM_LIST}> [OPTIONS] [TARGET]"
 	@echo ""
 	@echo "PLAT is used to specify which platform you wish to build."
 	@echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
diff --git a/bl32/tsp/tsp.mk b/bl32/tsp/tsp.mk
index 9919fe4..a502428 100644
--- a/bl32/tsp/tsp.mk
+++ b/bl32/tsp/tsp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -52,8 +52,8 @@
 # Include the platform-specific TSP Makefile
 # If no platform-specific TSP Makefile exists, it means TSP is not supported
 # on this platform.
-TSP_PLAT_MAKEFILE := $(shell find plat/ -wholename '*/${PLAT}/tsp/tsp-${PLAT}.mk')
-ifeq (,$(wildcard ${TSP_PLAT_MAKEFILE}))
+TSP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/tsp/tsp-${PLAT}.mk)
+ifeq (,${TSP_PLAT_MAKEFILE})
   $(error TSP is not supported on platform ${PLAT})
 else
   include ${TSP_PLAT_MAKEFILE}
diff --git a/common/tf_printf.c b/common/tf_printf.c
index c1d4188..9a7667a 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -69,6 +69,7 @@
  * %ld and %lld - signed 64 bit decimal format
  * %lu and %llu - unsigned 64 bit decimal format
  * %p - pointer format
+ * %z - size_t format
  * Exits on all other formats.
  *******************************************************************/
 
@@ -124,6 +125,11 @@
 
 				unsigned_num_print(unum, 16);
 				break;
+			case 'z':
+				if (sizeof(size_t) == 8)
+					bit64 = 1;
+				fmt++;
+				goto loop;
 			case 'l':
 				bit64 = 1;
 				fmt++;
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index f8d0ff3..3b6e242 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -633,6 +633,35 @@
 to the ROTPK in the flags parameter.
 
 
+### Function: plat_get_nv_ctr()
+
+    Argument : void *, unsigned int *
+    Return   : int
+
+This function is mandatory when Trusted Board Boot is enabled. It returns the
+non-volatile counter value stored in the platform in the second argument. The
+cookie in the first argument may be used to select the counter in case the
+platform provides more than one (for example, on platforms that use the default
+TBBR CoT, the cookie will correspond to the OID values defined in
+TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID).
+
+The function returns 0 on success. Any other value means the counter value could
+not be retrieved from the platform.
+
+
+### Function: plat_set_nv_ctr()
+
+    Argument : void *, unsigned int
+    Return   : int
+
+This function is mandatory when Trusted Board Boot is enabled. It sets a new
+counter value in the platform. The cookie in the first argument may be used to
+select the counter (as explained in plat_get_nv_ctr()).
+
+The function returns 0 on success. Any other value means the counter value could
+not be updated.
+
+
 2.3 Common mandatory modifications
 ---------------------------------
 
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 37e2034..8d7376d 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -42,6 +42,9 @@
 building the software were installed from that distribution unless otherwise
 specified.
 
+The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE,
+Cygwin, and Msys (MinGW) shells, using version 4.9.1 of the GNU toolchain.
+
 3.  Tools
 ---------
 
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
new file mode 100644
index 0000000..ee6bf8d
--- /dev/null
+++ b/drivers/arm/tzc/tzc400.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc400.h>
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_400_REGION_BASE_LOW_0_OFFSET	0x100
+#define TZC_400_REGION_BASE_HIGH_0_OFFSET	0x104
+#define TZC_400_REGION_TOP_LOW_0_OFFSET		0x108
+#define TZC_400_REGION_TOP_HIGH_0_OFFSET	0x10c
+#define TZC_400_REGION_ATTR_0_OFFSET		0x110
+#define TZC_400_REGION_ID_ACCESS_0_OFFSET	0x114
+
+/*
+ * Implementation defined values used to validate inputs later.
+ * Filters : max of 4 ; 0 to 3
+ * Regions : max of 9 ; 0 to 8
+ * Address width : Values between 32 to 64
+ */
+typedef struct tzc400_instance {
+	uintptr_t base;
+	uint8_t addr_width;
+	uint8_t num_filters;
+	uint8_t num_regions;
+} tzc400_instance_t;
+
+tzc400_instance_t tzc400;
+
+static inline unsigned int _tzc400_read_build_config(uintptr_t base)
+{
+	return mmio_read_32(base + BUILD_CONFIG_OFF);
+}
+
+static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base)
+{
+	return mmio_read_32(base + GATE_KEEPER_OFF);
+}
+
+static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GATE_KEEPER_OFF, val);
+}
+
+/*
+ * Get the open status information for all filter units.
+ */
+#define get_gate_keeper_os(base)	((_tzc400_read_gate_keeper(base) >>	\
+					GATE_KEEPER_OS_SHIFT) &		\
+					GATE_KEEPER_OS_MASK)
+
+
+/* Define common core functions used across different TZC peripherals. */
+DEFINE_TZC_COMMON_WRITE_ACTION(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
+
+static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
+				unsigned int filter)
+{
+	unsigned int open_status;
+
+	open_status = get_gate_keeper_os(base);
+
+	return (open_status >> filter) & GATE_KEEPER_FILTER_MASK;
+}
+
+/* This function is not MP safe. */
+static void _tzc400_set_gate_keeper(uintptr_t base,
+				unsigned int filter,
+				int val)
+{
+	unsigned int open_status;
+
+	/* Upper half is current state. Lower half is requested state. */
+	open_status = get_gate_keeper_os(base);
+
+	if (val)
+		open_status |=  (1 << filter);
+	else
+		open_status &= ~(1 << filter);
+
+	_tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) <<
+			      GATE_KEEPER_OR_SHIFT);
+
+	/* Wait here until we see the change reflected in the TZC status. */
+	while ((get_gate_keeper_os(base)) != open_status)
+		;
+}
+
+void tzc400_set_action(tzc_action_t action)
+{
+	assert(tzc400.base);
+	assert(action <= TZC_ACTION_ERR_INT);
+
+	/*
+	 * - Currently no handler is provided to trap an error via interrupt
+	 *   or exception.
+	 * - The interrupt action has not been tested.
+	 */
+	_tzc400_write_action(tzc400.base, action);
+}
+
+void tzc400_init(uintptr_t base)
+{
+#if DEBUG
+	unsigned int tzc400_id;
+#endif
+	unsigned int tzc400_build;
+
+	assert(base);
+	tzc400.base = base;
+
+#if DEBUG
+	tzc400_id = _tzc_read_peripheral_id(base);
+	if (tzc400_id != TZC_400_PERIPHERAL_ID) {
+		ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id);
+		panic();
+	}
+#endif
+
+	/* Save values we will use later. */
+	tzc400_build = _tzc400_read_build_config(tzc400.base);
+	tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
+			   BUILD_CONFIG_NF_MASK) + 1;
+	tzc400.addr_width  = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
+			   BUILD_CONFIG_AW_MASK) + 1;
+	tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
+			   BUILD_CONFIG_NR_MASK) + 1;
+}
+
+/*
+ * `tzc400_configure_region0` is used to program region 0 into the TrustZone
+ * controller. Region 0 covers the whole address space that is not mapped
+ * to any other region, and is enabled on all filters; this cannot be
+ * changed. This function only changes the access permissions.
+ */
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+			   unsigned int ns_device_access)
+{
+	assert(tzc400.base);
+	assert(sec_attr <= TZC_REGION_S_RDWR);
+
+	_tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access);
+}
+
+/*
+ * `tzc400_configure_region` is used to program regions into the TrustZone
+ * controller. A region can be associated with more than one filter. The
+ * associated filters are passed in as a bitmap (bit0 = filter0).
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc400_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc400_configure_region(unsigned int filters,
+			  int region,
+			  uintptr_t region_base,
+			  uintptr_t region_top,
+			  tzc_region_attributes_t sec_attr,
+			  unsigned int nsaid_permissions)
+{
+	assert(tzc400.base);
+
+	/* Do range checks on filters and regions. */
+	assert(((filters >> tzc400.num_filters) == 0) &&
+	       (region >= 0) && (region < tzc400.num_regions));
+
+	/*
+	 * Do address range check based on TZC configuration. A 64bit address is
+	 * the max and expected case.
+	 */
+	assert(((region_top <= (UINT64_MAX >> (64 - tzc400.addr_width))) &&
+		(region_base < region_top)));
+
+	/* region_base and (region_top + 1) must be 4KB aligned */
+	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+	assert(sec_attr <= TZC_REGION_S_RDWR);
+
+	_tzc400_configure_region(tzc400.base, filters, region, region_base,
+						region_top,
+						sec_attr, nsaid_permissions);
+}
+
+void tzc400_enable_filters(void)
+{
+	unsigned int state;
+	unsigned int filter;
+
+	assert(tzc400.base);
+
+	for (filter = 0; filter < tzc400.num_filters; filter++) {
+		state = _tzc400_get_gate_keeper(tzc400.base, filter);
+		if (state) {
+			/* The TZC filter is already configured. Changing the
+			 * programmer's view in an active system can cause
+			 * unpredictable behavior therefore panic for now rather
+			 * than try to determine whether this is safe in this
+			 * instance. See:
+			 * http://infocenter.arm.com/help/index.jsp?\
+			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
+			ERROR("TZC-400 : Filter %d Gatekeeper already"
+				" enabled.\n", filter);
+			panic();
+		}
+		_tzc400_set_gate_keeper(tzc400.base, filter, 1);
+	}
+}
+
+void tzc400_disable_filters(void)
+{
+	unsigned int filter;
+
+	assert(tzc400.base);
+
+	/*
+	 * We don't do the same state check as above as the Gatekeepers are
+	 * disabled after reset.
+	 */
+	for (filter = 0; filter < tzc400.num_filters; filter++)
+		_tzc400_set_gate_keeper(tzc400.base, filter, 0);
+}
diff --git a/drivers/arm/tzc/tzc_common_private.c b/drivers/arm/tzc/tzc_common_private.c
new file mode 100644
index 0000000..f570daf
--- /dev/null
+++ b/drivers/arm/tzc/tzc_common_private.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mmio.h>
+#include <tzc_common.h>
+
+#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_write_action(		\
+					uintptr_t base,			\
+					tzc_action_t action)		\
+	{								\
+		mmio_write_32(base + TZC_##macro_name##_ACTION_OFF,	\
+			action);					\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name)	\
+	static inline void _tzc##fn_name##_write_region_base(		\
+						uintptr_t base,		\
+						int region_no,		\
+						uintptr_t region_base)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+				TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET,	\
+			(unsigned int)region_base);			\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET,	\
+			(unsigned int)(region_base >> 32));		\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_write_region_top(		\
+						uintptr_t base,		\
+						int region_no,		\
+						uintptr_t region_top)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET				\
+				(TZC_##macro_name##_REGION_SIZE,	\
+				region_no) +				\
+			TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET,	\
+			(unsigned int)region_top);			\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET,	\
+			(unsigned int)(region_top >> 32));		\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name)	\
+	static inline void _tzc##fn_name##_write_region_attributes(	\
+						uintptr_t base,		\
+						int region_no,		\
+						unsigned int attr)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ATTR_0_OFFSET,	\
+			attr);						\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name)	\
+	static inline void _tzc##fn_name##_write_region_id_access(	\
+						uintptr_t base,		\
+						int region_no,		\
+						unsigned int val)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET,	\
+			val);						\
+	}
+
+/*
+ * It is used to program region 0 ATTRIBUTES and ACCESS register.
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
+	void _tzc##fn_name##_configure_region0(uintptr_t base,		\
+			   tzc_region_attributes_t sec_attr,		\
+			   unsigned int ns_device_access)		\
+	{								\
+		assert(base);						\
+		VERBOSE("TrustZone : Configuring region 0 "		\
+			"(TZC Interface Base=%p sec_attr=0x%x,"		\
+			" ns_devs=0x%x)\n", (void *)base,		\
+			sec_attr, ns_device_access);			\
+									\
+		/* Set secure attributes on region 0 */			\
+		_tzc##fn_name##_write_region_attributes(base, 0,	\
+			sec_attr << TZC_REGION_ATTR_SEC_SHIFT);		\
+									\
+		/***************************************************/	\
+		/* Specify which non-secure devices have permission*/	\
+		/* to access region 0.				   */	\
+		/***************************************************/	\
+		_tzc##fn_name##_write_region_id_access(base,		\
+						0,			\
+						ns_device_access);	\
+	}
+
+/*
+ * It is used to program a region from 1 to 8 in the TrustZone controller.
+ * NOTE:
+ * Region 0 is special; it is preferable to use
+ * ##fn_name##_configure_region0 for this region (see comment for
+ * that function).
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name)			\
+	void _tzc##fn_name##_configure_region(uintptr_t base,		\
+				unsigned int filters,			\
+				int region_no,				\
+				uintptr_t region_base,			\
+				uintptr_t region_top,			\
+				tzc_region_attributes_t sec_attr,	\
+				unsigned int nsaid_permissions)	\
+	{								\
+		assert(base);						\
+		VERBOSE("TrustZone : Configuring region "		\
+			"(TZC Interface Base: %p, region_no = %d)"	\
+			"...\n", (void *)base, region_no);		\
+		VERBOSE("TrustZone : ... base = %p, top = %p,"		\
+			"\n", (void *)region_base, (void *)region_top);\
+		VERBOSE("TrustZone : ... sec_attr = 0x%x,"		\
+			" ns_devs = 0x%x)\n",				\
+			sec_attr, nsaid_permissions);			\
+									\
+		/***************************************************/	\
+		/* Inputs look ok, start programming registers.    */	\
+		/* All the address registers are 32 bits wide and  */	\
+		/* have a LOW and HIGH				   */	\
+		/* component used to construct an address up to a  */	\
+		/* 64bit.					   */	\
+		/***************************************************/	\
+		_tzc##fn_name##_write_region_base(base,			\
+					region_no, region_base);	\
+		_tzc##fn_name##_write_region_top(base,			\
+					region_no, region_top);		\
+									\
+		/* Enable filter to the region and set secure attributes */\
+		_tzc##fn_name##_write_region_attributes(base,		\
+				region_no,				\
+				(sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\
+				(filters << TZC_REGION_ATTR_F_EN_SHIFT));\
+									\
+		/***************************************************/	\
+		/* Specify which non-secure devices have permission*/	\
+		/* to access this region.			   */	\
+		/***************************************************/	\
+		_tzc##fn_name##_write_region_id_access(base,		\
+						region_no,		\
+						nsaid_permissions);	\
+	}
+
+#if DEBUG
+static unsigned int _tzc_read_peripheral_id(uintptr_t base)
+{
+	unsigned int id;
+
+	id = mmio_read_32(base + PID0_OFF);
+	/* Masks DESC part in PID1 */
+	id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
+
+	return id;
+}
+#endif
diff --git a/drivers/arm/tzc/tzc_dmc500.c b/drivers/arm/tzc/tzc_dmc500.c
new file mode 100644
index 0000000..16a53a4
--- /dev/null
+++ b/drivers/arm/tzc/tzc_dmc500.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <tzc_dmc500.h>
+#include "tzc_common.h"
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET		0x054
+#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET		0x058
+#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET		0x05C
+#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET		0x060
+#define TZC_DMC500_REGION_ATTR_0_OFFSET			0x064
+#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET		0x068
+
+#define TZC_DMC500_ACTION_OFF				0x50
+
+/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */
+static const tzc_dmc500_driver_data_t *g_driver_data;
+
+#define verify_region_attr(region, attr)	\
+		((g_conf_regions[(region)].sec_attr ==			\
+			((attr) >> TZC_REGION_ATTR_SEC_SHIFT))		\
+		&& ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT)))
+
+/*
+ * Structure for configured regions attributes in DMC500.
+ */
+typedef struct tzc_dmc500_regions {
+	tzc_region_attributes_t sec_attr;
+	int is_enabled;
+} tzc_dmc500_regions_t;
+
+/*
+ * Array storing the attributes of the configured regions. This array
+ * will be used by the `tzc_dmc500_verify_complete` to verify the flush
+ * completion.
+ */
+static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1];
+
+/* Helper Macros for making the code readable */
+#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance])
+#define DMC_INST_SI_BASE(instance, interface) \
+		(DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface))
+
+DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500)
+
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500)
+
+static inline unsigned int _tzc_dmc500_read_region_attr_0(
+					uintptr_t dmc_si_base,
+					int region_no)
+{
+	return mmio_read_32(dmc_si_base +
+			TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) +
+			TZC_DMC500_REGION_ATTR_0_OFFSET);
+}
+
+static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base)
+{
+	mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1);
+}
+
+/*
+ * Sets the Flush controls for all the DMC Instances and System Interfaces.
+ * This initiates the flush of configuration settings from the shadow
+ * registers to the actual configuration register. The caller should poll
+ * changed register to confirm update.
+ */
+void tzc_dmc500_config_complete(void)
+{
+	int dmc_inst, sys_if;
+
+	assert(g_driver_data);
+
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+			_tzc_dmc500_write_flush_control(
+					DMC_INST_SI_BASE(dmc_inst, sys_if));
+	}
+}
+
+/*
+ * This function reads back the secure attributes from the configuration
+ * register for each DMC Instance and System Interface and compares it with
+ * the configured value. The successful verification of the region attributes
+ * confirms that the flush operation has completed.
+ * If the verification fails, the caller is expected to invoke this API again
+ * till it succeeds.
+ * Returns 0 on success and 1 on failure.
+ */
+int tzc_dmc500_verify_complete(void)
+{
+	int dmc_inst, sys_if, region_no;
+	unsigned int attr;
+
+	assert(g_driver_data);
+	/* Region 0 must be configured */
+	assert(g_conf_regions[0].is_enabled);
+
+	/* Iterate over all configured regions */
+	for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) {
+		if (!g_conf_regions[region_no].is_enabled)
+			continue;
+		for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count;
+								dmc_inst++) {
+			assert(DMC_INST_BASE_ADDR(dmc_inst));
+			for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT;
+							sys_if++) {
+				attr = _tzc_dmc500_read_region_attr_0(
+					DMC_INST_SI_BASE(dmc_inst, sys_if),
+					region_no);
+				VERBOSE("Verifying DMC500 region:%d"
+					" dmc_inst:%d sys_if:%d attr:%x\n",
+					region_no, dmc_inst, sys_if, attr);
+				if (!verify_region_attr(region_no, attr))
+					return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * `tzc_dmc500_configure_region0` is used to program region 0 in both the
+ * system interfaces of all the DMC-500 instances. Region 0 covers the whole
+ * address space that is not mapped to any other region for a system interface,
+ * and is always enabled; this cannot be changed. This function only changes
+ * the access permissions.
+ */
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+					unsigned int nsaid_permissions)
+{
+	int dmc_inst, sys_if;
+
+	/* Assert if DMC-500 is not initialized */
+	assert(g_driver_data);
+
+	/* Configure region_0 in all DMC instances */
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+			_tzc_dmc500_configure_region0(
+					DMC_INST_SI_BASE(dmc_inst, sys_if),
+					sec_attr, nsaid_permissions);
+	}
+
+	g_conf_regions[0].sec_attr = sec_attr;
+	g_conf_regions[0].is_enabled = 1;
+}
+
+/*
+ * `tzc_dmc500_configure_region` is used to program a region into all system
+ * interfaces of all the DMC instances.
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc_dmc500_configure_region(int region_no,
+			uintptr_t region_base,
+			uintptr_t region_top,
+			tzc_region_attributes_t sec_attr,
+			unsigned int nsaid_permissions)
+{
+	int dmc_inst, sys_if;
+
+	assert(g_driver_data);
+	/* Do range checks on regions. */
+	assert(region_no >= 0 && region_no <= MAX_REGION_VAL);
+
+	/*
+	 * Do address range check based on DMC-TZ configuration. A 43bit address
+	 * is the max and expected case.
+	 */
+	assert(((region_top <= (UINT64_MAX >> (64 - 43))) &&
+		(region_base < region_top)));
+
+	/* region_base and (region_top + 1) must be 4KB aligned */
+	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+			_tzc_dmc500_configure_region(
+					DMC_INST_SI_BASE(dmc_inst, sys_if),
+					TZC_DMC500_REGION_ATTR_F_EN_MASK,
+					region_no, region_base, region_top,
+					sec_attr, nsaid_permissions);
+	}
+
+	g_conf_regions[region_no].sec_attr = sec_attr;
+	g_conf_regions[region_no].is_enabled = 1;
+}
+
+/* Sets the action value for all the DMC instances */
+void tzc_dmc500_set_action(tzc_action_t action)
+{
+	int dmc_inst;
+
+	assert(g_driver_data);
+
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		/*
+		 * - Currently no handler is provided to trap an error via
+		 *   interrupt or exception.
+		 * - The interrupt action has not been tested.
+		 */
+		_tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action);
+	}
+}
+
+/*
+ * A DMC-500 instance must be present at each base address provided by the
+ * platform. It also expects platform to pass at least one instance of
+ * DMC-500.
+ */
+static void validate_plat_driver_data(
+			const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+#if DEBUG
+	int i;
+	unsigned int dmc_id;
+	uintptr_t dmc_base;
+
+	assert(plat_driver_data);
+	assert(plat_driver_data->dmc_count > 0 &&
+		(plat_driver_data->dmc_count <= MAX_DMC_COUNT));
+
+	for (i = 0; i < plat_driver_data->dmc_count; i++) {
+		dmc_base = plat_driver_data->dmc_base[i];
+		assert(dmc_base);
+
+		dmc_id = _tzc_read_peripheral_id(dmc_base);
+		assert(dmc_id == DMC500_PERIPHERAL_ID);
+	}
+#endif /* DEBUG */
+}
+
+
+/*
+ * Initializes the base address and count of DMC instances.
+ *
+ * Note : Only pointer to plat_driver_data is saved, so it is caller's
+ * responsibility to keep it valid until the driver is used.
+ */
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+	/* Check valid pointer is passed */
+	assert(plat_driver_data);
+
+	/*
+	 * NOTE: This driver expects the DMC-500 controller is already in
+	 * READY state. Hence, it uses the reconfiguration method for
+	 * programming TrustZone regions
+	 */
+	/* Validates the information passed by platform */
+	validate_plat_driver_data(plat_driver_data);
+	g_driver_data = plat_driver_data;
+}
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 7194443..97adf81 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -28,313 +28,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <assert.h>
-#include <debug.h>
-#include <mmio.h>
-#include <stddef.h>
-#include <tzc400.h>
-
-/*
- * Implementation defined values used to validate inputs later.
- * Filters : max of 4 ; 0 to 3
- * Regions : max of 9 ; 0 to 8
- * Address width : Values between 32 to 64
- */
-typedef struct tzc_instance {
-	uintptr_t base;
-	uint8_t addr_width;
-	uint8_t num_filters;
-	uint8_t num_regions;
-} tzc_instance_t;
-
-tzc_instance_t tzc;
-
-
-static inline uint32_t tzc_read_build_config(uintptr_t base)
-{
-	return mmio_read_32(base + BUILD_CONFIG_OFF);
-}
-
-static inline uint32_t tzc_read_gate_keeper(uintptr_t base)
-{
-	return mmio_read_32(base + GATE_KEEPER_OFF);
-}
-
-static inline void tzc_write_gate_keeper(uintptr_t base, uint32_t val)
-{
-	mmio_write_32(base + GATE_KEEPER_OFF, val);
-}
-
-static inline void tzc_write_action(uintptr_t base, tzc_action_t action)
-{
-	mmio_write_32(base + ACTION_OFF, action);
-}
-
-static inline void tzc_write_region_base_low(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_BASE_LOW_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_base_high(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_BASE_HIGH_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_low(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_TOP_LOW_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_high(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_TOP_HIGH_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_attributes(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_ATTRIBUTES_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_id_access(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_ID_ACCESS_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static unsigned int tzc_read_peripheral_id(uintptr_t base)
-{
-	unsigned int id;
-
-	id = mmio_read_8(base + PID0_OFF);
-	/* Masks jep106_id_3_0 part in PID1 */
-	id |= ((mmio_read_8(base + PID1_OFF) & 0xF) << 8);
-
-	return id;
-}
-
-static uint32_t tzc_get_gate_keeper(uintptr_t base, uint8_t filter)
-{
-	uint32_t tmp;
-
-	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK;
-
-	return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
-}
-
-/* This function is not MP safe. */
-static void tzc_set_gate_keeper(uintptr_t base, uint8_t filter, uint32_t val)
-{
-	uint32_t tmp;
-
-	/* Upper half is current state. Lower half is requested state. */
-	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK;
-
-	if (val)
-		tmp |=  (1 << filter);
-	else
-		tmp &= ~(1 << filter);
-
-	tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
-			      GATE_KEEPER_OR_SHIFT);
-
-	/* Wait here until we see the change reflected in the TZC status. */
-	while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK) != tmp)
-	  ;
-}
-
-
-void tzc_init(uintptr_t base)
-{
-	unsigned int tzc_id;
-	unsigned int tzc_build;
-
-	assert(base);
-
-	tzc.base = base;
-
-	/*
-	 * We expect to see a tzc400. Check peripheral ID.
-	 */
-	tzc_id = tzc_read_peripheral_id(tzc.base);
-	if (tzc_id != TZC400_PERIPHERAL_ID) {
-		ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
-		panic();
-	}
-
-	/* Save values we will use later. */
-	tzc_build = tzc_read_build_config(tzc.base);
-	tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
-			   BUILD_CONFIG_NF_MASK) + 1;
-	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
-			   BUILD_CONFIG_AW_MASK) + 1;
-	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
-			   BUILD_CONFIG_NR_MASK) + 1;
-}
-
-/*
- * `tzc_configure_region0` is used to program region 0 into the TrustZone
- * controller. Region 0 covers the whole address space that is not mapped
- * to any other region, and is enabled on all filters; this cannot be
- * changed. This function only changes the access permissions.
- */
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
-			   uint32_t ns_device_access)
-{
-	assert(tzc.base);
-
-	VERBOSE("TZC : Configuring region 0 (sec_attr=0x%x, ns_devs=0x%x)\n",
-		sec_attr, ns_device_access);
-
-	assert(sec_attr <= TZC_REGION_S_RDWR);
-
-	/* Set secure attributes on region 0 */
-	tzc_write_region_attributes(tzc.base, 0,
-		sec_attr << REG_ATTR_SEC_SHIFT);
-
-	/*
-	 * Specify which non-secure devices have permission to access
-	 * region 0.
-	 */
-	tzc_write_region_id_access(tzc.base, 0, ns_device_access);
-}
-
-
-/*
- * `tzc_configure_region` is used to program regions into the TrustZone
- * controller. A region can be associated with more than one filter. The
- * associated filters are passed in as a bitmap (bit0 = filter0).
- * NOTE:
- * Region 0 is special; it is preferable to use tzc_configure_region0
- * for this region (see comment for that function).
- */
-void tzc_configure_region(uint32_t filters,
-			  uint8_t  region,
-			  uint64_t region_base,
-			  uint64_t region_top,
-			  tzc_region_attributes_t sec_attr,
-			  uint32_t ns_device_access)
-{
-	assert(tzc.base);
-
-	VERBOSE("TZC : Configuring region (filters=0x%x, region=%d, ...\n",
-		filters, region);
-	VERBOSE("TZC : ... base=0x%lx, top=0x%lx, ...\n",
-		region_base, region_top);
-	VERBOSE("TZC : ... sec_attr=0x%x, ns_devs=0x%x)\n",
-		sec_attr, ns_device_access);
-
-	/* Do range checks on filters and regions. */
-	assert(((filters >> tzc.num_filters) == 0) &&
-	       (region < tzc.num_regions));
-
-	/*
-	 * Do address range check based on TZC configuration. A 64bit address is
-	 * the max and expected case.
-	 */
-	assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
-		(region_base < region_top)));
-
-	/* region_base and (region_top + 1) must be 4KB aligned */
-	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
-
-	assert(sec_attr <= TZC_REGION_S_RDWR);
-
-	/*
-	 * Inputs look ok, start programming registers.
-	 * All the address registers are 32 bits wide and have a LOW and HIGH
-	 * component used to construct a up to a 64bit address.
-	 */
-	tzc_write_region_base_low(tzc.base, region,
-				(uint32_t)(region_base));
-	tzc_write_region_base_high(tzc.base, region,
-				(uint32_t)(region_base >> 32));
-
-	tzc_write_region_top_low(tzc.base, region,
-				(uint32_t)(region_top));
-	tzc_write_region_top_high(tzc.base, region,
-				(uint32_t)(region_top >> 32));
-
-	/* Assign the region to a filter and set secure attributes */
-	tzc_write_region_attributes(tzc.base, region,
-		(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
-
-	/*
-	 * Specify which non-secure devices have permission to access this
-	 * region.
-	 */
-	tzc_write_region_id_access(tzc.base, region, ns_device_access);
-}
-
-
-void tzc_set_action(tzc_action_t action)
-{
-	assert(tzc.base);
-
-	/*
-	 * - Currently no handler is provided to trap an error via interrupt
-	 *   or exception.
-	 * - The interrupt action has not been tested.
-	 */
-	tzc_write_action(tzc.base, action);
-}
-
-
-void tzc_enable_filters(void)
-{
-	uint32_t state;
-	uint32_t filter;
-
-	assert(tzc.base);
-
-	for (filter = 0; filter < tzc.num_filters; filter++) {
-		state = tzc_get_gate_keeper(tzc.base, filter);
-		if (state) {
-			/* The TZC filter is already configured. Changing the
-			 * programmer's view in an active system can cause
-			 * unpredictable behavior therefore panic for now rather
-			 * than try to determine whether this is safe in this
-			 * instance. See:
-			 * http://infocenter.arm.com/help/index.jsp?\
-			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
-			ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
-				filter);
-			panic();
-		}
-		tzc_set_gate_keeper(tzc.base, filter, 1);
-	}
-}
-
-
-void tzc_disable_filters(void)
-{
-	uint32_t filter;
-
-	assert(tzc.base);
-
-	/*
-	 * We don't do the same state check as above as the Gatekeepers are
-	 * disabled after reset.
-	 */
-	for (filter = 0; filter < tzc.num_filters; filter++)
-		tzc_set_gate_keeper(tzc.base, filter, 0);
-}
+#if ERROR_DEPRECATED
+#error "Using deprecated TZC-400 source file"
+#else
+#include "../tzc/tzc400.c"
+#endif /* ERROR_DEPRECATED */
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index bdd3c5a..4184556 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -40,6 +40,9 @@
 #include <stdint.h>
 #include <string.h>
 
+/* ASN.1 tags */
+#define ASN1_INTEGER                 0x02
+
 #define return_if_error(rc) \
 	do { \
 		if (rc != 0) { \
@@ -227,6 +230,83 @@
 }
 
 /*
+ * Authenticate by Non-Volatile counter
+ *
+ * To protect the system against rollback, the platform includes a non-volatile
+ * counter whose value can only be increased. All certificates include a counter
+ * value that should not be lower than the value stored in the platform. If the
+ * value is larger, the counter in the platform must be updated to the new
+ * value.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
+		      const auth_img_desc_t *img_desc,
+		      void *img, unsigned int img_len)
+{
+	char *p;
+	void *data_ptr = NULL;
+	unsigned int data_len, len, i;
+	unsigned int cert_nv_ctr, plat_nv_ctr;
+	int rc = 0;
+
+	/* Get the counter value from current image. The AM expects the IPM
+	 * to return the counter value as a DER encoded integer */
+	rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr,
+				       img, img_len, &data_ptr, &data_len);
+	return_if_error(rc);
+
+	/* Parse the DER encoded integer */
+	assert(data_ptr);
+	p = (char *)data_ptr;
+	if (*p != ASN1_INTEGER) {
+		/* Invalid ASN.1 integer */
+		return 1;
+	}
+	p++;
+
+	/* NV-counters are unsigned integers up to 32-bit */
+	len = (unsigned int)(*p & 0x7f);
+	if ((*p & 0x80) || (len > 4)) {
+		return 1;
+	}
+	p++;
+
+	/* Check the number is not negative */
+	if (*p & 0x80) {
+		return 1;
+	}
+
+	/* Convert to unsigned int. This code is for a little-endian CPU */
+	cert_nv_ctr = 0;
+	for (i = 0; i < len; i++) {
+		cert_nv_ctr = (cert_nv_ctr << 8) | *p++;
+	}
+
+	/* Get the counter from the platform */
+	rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr);
+	return_if_error(rc);
+
+	if (cert_nv_ctr < plat_nv_ctr) {
+		/* Invalid NV-counter */
+		return 1;
+	} else if (cert_nv_ctr > plat_nv_ctr) {
+		if (img_desc->parent == NULL) {
+			/* This certificate has been signed with the ROT key.
+			 * Update the platform counter value */
+			rc = plat_set_nv_ctr(param->plat_nv_ctr->cookie,
+					     cert_nv_ctr);
+			return_if_error(rc);
+		} else {
+			/* Secondary certificates cannot modify the counter */
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
  * Return the parent id in the output parameter '*parent_id'
  *
  * Return value:
@@ -310,6 +390,10 @@
 			rc = auth_signature(&auth_method->param.sig,
 					img_desc, img_ptr, img_len);
 			break;
+		case AUTH_METHOD_NV_CTR:
+			rc = auth_nvctr(&auth_method->param.nv_ctr,
+					img_desc, img_ptr, img_len);
+			break;
 		default:
 			/* Unknown authentication method */
 			rc = 1;
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
index 52e6971..1a6a9a7 100644
--- a/drivers/auth/mbedtls/mbedtls_x509_parser.c
+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -405,6 +405,13 @@
 
 /*
  * Extract an authentication parameter from an X509v3 certificate
+ *
+ * This function returns a pointer to the extracted data and its length.
+ * Depending on the type of parameter, a pointer to the data stored in the
+ * certificate may be returned (i.e. an octet string containing a hash). Other
+ * data may need to be copied and formatted (i.e. integers). In the later case,
+ * a buffer of the correct type needs to be statically allocated, filled and
+ * returned.
  */
 static int get_auth_param(const auth_param_type_desc_t *type_desc,
 		void *img, unsigned int img_len,
@@ -422,6 +429,7 @@
 		*param_len = (unsigned int)tbs.len;
 		break;
 	case AUTH_PARAM_HASH:
+	case AUTH_PARAM_NV_CTR:
 		/* All these parameters are included as X509v3 extensions */
 		rc = get_ext(type_desc->cookie, param, param_len);
 		break;
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 6023c78..dae35d1 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -56,6 +56,11 @@
 /*
  * Parameter type descriptors
  */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+
 static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_PUB_KEY, 0);
 static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
@@ -116,6 +121,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -158,6 +170,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -193,6 +212,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -218,6 +244,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -260,6 +293,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -285,6 +325,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -327,6 +374,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -352,6 +406,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -394,6 +455,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &non_trusted_nv_ctr,
+					.plat_nv_ctr = &non_trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -419,6 +487,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &non_trusted_nv_ctr,
+					.plat_nv_ctr = &non_trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index f8e1664..3085688 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -31,178 +31,179 @@
 #ifndef __TZC400_H__
 #define __TZC400_H__
 
+#include <tzc_common.h>
 
-#define BUILD_CONFIG_OFF	0x000
-#define ACTION_OFF		0x004
-#define GATE_KEEPER_OFF		0x008
-#define SPECULATION_CTRL_OFF	0x00c
-#define INT_STATUS		0x010
-#define INT_CLEAR		0x014
+#define BUILD_CONFIG_OFF			0x000
+#define GATE_KEEPER_OFF				0x008
+#define SPECULATION_CTRL_OFF			0x00c
+#define INT_STATUS				0x010
+#define INT_CLEAR				0x014
 
-#define FAIL_ADDRESS_LOW_OFF	0x020
-#define FAIL_ADDRESS_HIGH_OFF	0x024
-#define FAIL_CONTROL_OFF	0x028
-#define FAIL_ID			0x02c
+#define FAIL_ADDRESS_LOW_OFF			0x020
+#define FAIL_ADDRESS_HIGH_OFF			0x024
+#define FAIL_CONTROL_OFF			0x028
+#define FAIL_ID					0x02c
 
-#define REGION_BASE_LOW_OFF	0x100
-#define REGION_BASE_HIGH_OFF	0x104
-#define REGION_TOP_LOW_OFF	0x108
-#define REGION_TOP_HIGH_OFF	0x10c
-#define REGION_ATTRIBUTES_OFF	0x110
-#define REGION_ID_ACCESS_OFF	0x114
-#define REGION_NUM_OFF(region)  (0x20 * region)
+/* ID registers not common across different varieties of TZC */
+#define PID5					0xFD4
+#define PID6					0xFD8
+#define PID7					0xFDC
 
-/* ID Registers */
-#define PID0_OFF		0xfe0
-#define PID1_OFF		0xfe4
-#define PID2_OFF		0xfe8
-#define PID3_OFF		0xfec
-#define PID4_OFF		0xfd0
-#define PID5_OFF		0xfd4
-#define PID6_OFF		0xfd8
-#define PID7_OFF		0xfdc
-#define CID0_OFF		0xff0
-#define CID1_OFF		0xff4
-#define CID2_OFF		0xff8
-#define CID3_OFF		0xffc
-
-#define BUILD_CONFIG_NF_SHIFT	24
-#define BUILD_CONFIG_NF_MASK	0x3
-#define BUILD_CONFIG_AW_SHIFT	8
-#define BUILD_CONFIG_AW_MASK	0x3f
-#define BUILD_CONFIG_NR_SHIFT	0
-#define BUILD_CONFIG_NR_MASK	0x1f
-
-/* Not describing the case where regions 1 to 8 overlap */
-#define ACTION_RV_SHIFT		0
-#define ACTION_RV_MASK		0x3
-#define  ACTION_RV_LOWOK	0x0
-#define  ACTION_RV_LOWERR	0x1
-#define  ACTION_RV_HIGHOK	0x2
-#define  ACTION_RV_HIGHERR	0x3
+#define BUILD_CONFIG_NF_SHIFT			24
+#define BUILD_CONFIG_NF_MASK			0x3
+#define BUILD_CONFIG_AW_SHIFT			8
+#define BUILD_CONFIG_AW_MASK			0x3f
+#define BUILD_CONFIG_NR_SHIFT			0
+#define BUILD_CONFIG_NR_MASK			0x1f
 
 /*
  * Number of gate keepers is implementation defined. But we know the max for
  * this device is 4. Get implementation details from BUILD_CONFIG.
  */
-#define GATE_KEEPER_OS_SHIFT	16
-#define GATE_KEEPER_OS_MASK	0xf
-#define GATE_KEEPER_OR_SHIFT	0
-#define GATE_KEEPER_OR_MASK	0xf
-#define GATE_KEEPER_FILTER_MASK	0x1
+#define GATE_KEEPER_OS_SHIFT			16
+#define GATE_KEEPER_OS_MASK			0xf
+#define GATE_KEEPER_OR_SHIFT			0
+#define GATE_KEEPER_OR_MASK			0xf
+#define GATE_KEEPER_FILTER_MASK			0x1
 
 /* Speculation is enabled by default. */
-#define SPECULATION_CTRL_WRITE_DISABLE	(1 << 1)
-#define SPECULATION_CTRL_READ_DISABLE	(1 << 0)
+#define SPECULATION_CTRL_WRITE_DISABLE		(1 << 1)
+#define SPECULATION_CTRL_READ_DISABLE		(1 << 0)
 
 /* Max number of filters allowed is 4. */
-#define INT_STATUS_OVERLAP_SHIFT	16
-#define INT_STATUS_OVERLAP_MASK		0xf
-#define INT_STATUS_OVERRUN_SHIFT	8
-#define INT_STATUS_OVERRUN_MASK		0xf
-#define INT_STATUS_STATUS_SHIFT		0
-#define INT_STATUS_STATUS_MASK		0xf
+#define INT_STATUS_OVERLAP_SHIFT		16
+#define INT_STATUS_OVERLAP_MASK			0xf
+#define INT_STATUS_OVERRUN_SHIFT		8
+#define INT_STATUS_OVERRUN_MASK			0xf
+#define INT_STATUS_STATUS_SHIFT			0
+#define INT_STATUS_STATUS_MASK			0xf
 
-#define INT_CLEAR_CLEAR_SHIFT		0
-#define INT_CLEAR_CLEAR_MASK		0xf
+#define INT_CLEAR_CLEAR_SHIFT			0
+#define INT_CLEAR_CLEAR_MASK			0xf
 
-#define FAIL_CONTROL_DIR_SHIFT		(1 << 24)
-#define  FAIL_CONTROL_DIR_READ		0x0
-#define  FAIL_CONTROL_DIR_WRITE		0x1
-#define FAIL_CONTROL_NS_SHIFT		(1 << 21)
-#define  FAIL_CONTROL_NS_SECURE		0x0
-#define  FAIL_CONTROL_NS_NONSECURE	0x1
-#define FAIL_CONTROL_PRIV_SHIFT		(1 << 20)
-#define  FAIL_CONTROL_PRIV_PRIV		0x0
-#define  FAIL_CONTROL_PRIV_UNPRIV	0x1
+#define FAIL_CONTROL_DIR_SHIFT			(1 << 24)
+#define FAIL_CONTROL_DIR_READ			0x0
+#define FAIL_CONTROL_DIR_WRITE			0x1
+#define FAIL_CONTROL_NS_SHIFT			(1 << 21)
+#define FAIL_CONTROL_NS_SECURE			0x0
+#define FAIL_CONTROL_NS_NONSECURE		0x1
+#define FAIL_CONTROL_PRIV_SHIFT			(1 << 20)
+#define FAIL_CONTROL_PRIV_PRIV			0x0
+#define FAIL_CONTROL_PRIV_UNPRIV		0x1
 
 /*
  * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
  * Platform should provide the value on initialisation.
  */
-#define FAIL_ID_VNET_SHIFT		24
-#define FAIL_ID_VNET_MASK		0xf
-#define FAIL_ID_ID_SHIFT		0
-
-/* Used along with 'tzc_region_attributes_t' below */
-#define REG_ATTR_SEC_SHIFT		30
-#define REG_ATTR_F_EN_SHIFT		0
-#define REG_ATTR_F_EN_MASK		0xf
-#define REG_ATTR_FILTER_BIT(x)		((1 << x) << REG_ATTR_F_EN_SHIFT)
-#define REG_ATTR_FILTER_BIT_ALL		(REG_ATTR_F_EN_MASK << \
-					REG_ATTR_F_EN_SHIFT)
+#define FAIL_ID_VNET_SHIFT			24
+#define FAIL_ID_VNET_MASK			0xf
+#define FAIL_ID_ID_SHIFT			0
 
-#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT	16
-#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT	0
-#define REGION_ID_ACCESS_NSAID_ID_MASK		0xf
+#define TZC_400_PERIPHERAL_ID			0x460
 
+/* Filter enable bits in a TZC */
+#define TZC_400_REGION_ATTR_F_EN_MASK		0xf
+#define TZC_400_REGION_ATTR_FILTER_BIT(x)	((1 << x)		\
+					<< TZC_REGION_ATTR_F_EN_SHIFT)
+#define TZC_400_REGION_ATTR_FILTER_BIT_ALL				\
+				(TZC_400_REGION_ATTR_F_EN_MASK <<	\
+				TZC_REGION_ATTR_F_EN_SHIFT)
 
-/* Macros for setting Region ID access permissions based on NSAID */
-#define TZC_REGION_ACCESS_RD(id)					\
-		((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) <<	\
-		 REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
-#define TZC_REGION_ACCESS_WR(id)					\
-		((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) <<	\
-		 REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
-#define TZC_REGION_ACCESS_RDWR(id)					\
-		(TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id))
-
-/* Consist of part_number_1 and part_number_0 */
-#define TZC400_PERIPHERAL_ID	0x0460
-
+/*
+ * Define some macros for backward compatibility with existing tzc400 clients.
+ */
+#if !ERROR_DEPRECATED
+#define REG_ATTR_FILTER_BIT(x)			((1 << x)		\
+					<< TZC_REGION_ATTR_F_EN_SHIFT)
+#define REG_ATTR_FILTER_BIT_ALL	(TZC_400_REGION_ATTR_F_EN_MASK <<	\
+					TZC_REGION_ATTR_F_EN_SHIFT)
+#endif /* __ERROR_DEPRECATED__ */
 
+/*
+ * All TZC region configuration registers are placed one after another. It
+ * depicts size of block of registers for programming each region.
+ */
+#define TZC_400_REGION_SIZE			0x20
+#define TZC_400_ACTION_OFF			0x4
 
 #ifndef __ASSEMBLY__
 
+#include <cdefs.h>
 #include <stdint.h>
 
 /*******************************************************************************
  * Function & variable prototypes
  ******************************************************************************/
+void tzc400_init(uintptr_t base);
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+			   unsigned int ns_device_access);
+void tzc400_configure_region(unsigned int filters,
+			  int region,
+			  uintptr_t region_base,
+			  uintptr_t region_top,
+			  tzc_region_attributes_t sec_attr,
+			  unsigned int ns_device_access);
+void tzc400_set_action(tzc_action_t action);
+void tzc400_enable_filters(void);
+void tzc400_disable_filters(void);
 
 /*
- * What type of action is expected when an access violation occurs.
- * The memory requested is zeroed. But we can also raise and event to
- * let the system know it happened.
- * We can raise an interrupt(INT) and/or cause an exception(ERR).
- *  TZC_ACTION_NONE    - No interrupt, no Exception
- *  TZC_ACTION_ERR     - No interrupt, raise exception -> sync external
- *                       data abort
- *  TZC_ACTION_INT     - Raise interrupt, no exception
- *  TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
- *                       external data abort
+ * Deprecated APIs
  */
-typedef enum {
-	TZC_ACTION_NONE = 0,
-	TZC_ACTION_ERR = 1,
-	TZC_ACTION_INT = 2,
-	TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
-} tzc_action_t;
-
-/*
- * Controls secure access to a region. If not enabled secure access is not
- * allowed to region.
- */
-typedef enum {
-	TZC_REGION_S_NONE = 0,
-	TZC_REGION_S_RD = 1,
-	TZC_REGION_S_WR = 2,
-	TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
-} tzc_region_attributes_t;
+static inline void tzc_init(uintptr_t base) __deprecated;
+static inline void tzc_configure_region0(
+			tzc_region_attributes_t sec_attr,
+			unsigned int ns_device_access) __deprecated;
+static inline void tzc_configure_region(
+			  unsigned int filters,
+			  int region,
+			  uintptr_t region_base,
+			  uintptr_t region_top,
+			  tzc_region_attributes_t sec_attr,
+			  unsigned int ns_device_access) __deprecated;
+static inline void tzc_set_action(tzc_action_t action) __deprecated;
+static inline void tzc_enable_filters(void) __deprecated;
+static inline void tzc_disable_filters(void) __deprecated;
 
+static inline void tzc_init(uintptr_t base)
+{
+	tzc400_init(base);
+}
 
-void tzc_init(uintptr_t base);
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
-			uint32_t ns_device_access);
-void tzc_configure_region(uint32_t filters,
-			uint8_t region,
-			uint64_t region_base,
-			uint64_t region_top,
+static inline void tzc_configure_region0(
 			tzc_region_attributes_t sec_attr,
-			uint32_t ns_device_access);
-void tzc_enable_filters(void);
-void tzc_disable_filters(void);
-void tzc_set_action(tzc_action_t action);
+			unsigned int ns_device_access)
+{
+	tzc400_configure_region0(sec_attr, ns_device_access);
+}
+
+static inline void tzc_configure_region(
+			  unsigned int filters,
+			  int region,
+			  uintptr_t region_base,
+			  uintptr_t region_top,
+			  tzc_region_attributes_t sec_attr,
+			  unsigned int ns_device_access)
+{
+	tzc400_configure_region(filters, region, region_base,
+			region_top, sec_attr, ns_device_access);
+}
+
+static inline void tzc_set_action(tzc_action_t action)
+{
+	tzc400_set_action(action);
+}
+
+
+static inline void tzc_enable_filters(void)
+{
+	tzc400_enable_filters();
+}
+
+static inline void tzc_disable_filters(void)
+{
+	tzc400_disable_filters();
+}
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/drivers/arm/tzc_common.h b/include/drivers/arm/tzc_common.h
new file mode 100644
index 0000000..9b73c3f
--- /dev/null
+++ b/include/drivers/arm/tzc_common.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TZC_COMMON_H__
+#define __TZC_COMMON_H__
+
+/*
+ * Offset of core registers from the start of the base of configuration
+ * registers for each region.
+ */
+
+/* ID Registers */
+#define PID0_OFF					0xfe0
+#define PID1_OFF					0xfe4
+#define PID2_OFF					0xfe8
+#define PID3_OFF					0xfec
+#define PID4_OFF					0xfd0
+#define CID0_OFF					0xff0
+#define CID1_OFF					0xff4
+#define CID2_OFF					0xff8
+#define CID3_OFF					0xffc
+
+/* Bit positions of TZC_ACTION registers */
+#define TZC_ACTION_RV_SHIFT				0
+#define TZC_ACTION_RV_MASK				0x3
+#define TZC_ACTION_RV_LOWOK				0x0
+#define TZC_ACTION_RV_LOWERR				0x1
+#define TZC_ACTION_RV_HIGHOK				0x2
+#define TZC_ACTION_RV_HIGHERR				0x3
+
+/* Used along with 'tzc_region_attributes_t' below */
+#define TZC_REGION_ATTR_S_RD_SHIFT			30
+#define TZC_REGION_ATTR_S_WR_SHIFT			31
+#define TZC_REGION_ATTR_F_EN_SHIFT			0
+#define TZC_REGION_ATTR_SEC_SHIFT			30
+#define TZC_REGION_ATTR_S_RD_MASK			0x1
+#define TZC_REGION_ATTR_S_WR_MASK			0x1
+#define TZC_REGION_ATTR_SEC_MASK			0x3
+
+#define TZC_REGION_ACCESS_WR_EN_SHIFT			16
+#define TZC_REGION_ACCESS_RD_EN_SHIFT			0
+#define TZC_REGION_ACCESS_ID_MASK			0xf
+
+/* Macros for allowing Non-Secure access to a region based on NSAID */
+#define TZC_REGION_ACCESS_RD(nsaid)				\
+	((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) <<		\
+	 TZC_REGION_ACCESS_RD_EN_SHIFT)
+#define TZC_REGION_ACCESS_WR(nsaid)				\
+	((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) <<		\
+	 TZC_REGION_ACCESS_WR_EN_SHIFT)
+#define TZC_REGION_ACCESS_RDWR(nsaid)				\
+	(TZC_REGION_ACCESS_RD(nsaid) |				\
+	TZC_REGION_ACCESS_WR(nsaid))
+
+#ifndef __ASSEMBLY__
+
+/* Returns offset of registers to program for a given region no */
+#define TZC_REGION_OFFSET(region_size, region_no)	\
+				((region_size) * (region_no))
+
+/*
+ * What type of action is expected when an access violation occurs.
+ * The memory requested is returned as zero. But we can also raise an event to
+ * let the system know it happened.
+ * We can raise an interrupt(INT) and/or cause an exception(ERR).
+ *  TZC_ACTION_NONE    - No interrupt, no Exception
+ *  TZC_ACTION_ERR     - No interrupt, raise exception -> sync external
+ *                       data abort
+ *  TZC_ACTION_INT     - Raise interrupt, no exception
+ *  TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
+ *                       external data abort
+ */
+typedef enum {
+	TZC_ACTION_NONE = 0,
+	TZC_ACTION_ERR = 1,
+	TZC_ACTION_INT = 2,
+	TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
+} tzc_action_t;
+
+/*
+ * Controls secure access to a region. If not enabled secure access is not
+ * allowed to region.
+ */
+typedef enum {
+	TZC_REGION_S_NONE = 0,
+	TZC_REGION_S_RD = 1,
+	TZC_REGION_S_WR = 2,
+	TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
+} tzc_region_attributes_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __TZC_COMMON_H__ */
diff --git a/include/drivers/arm/tzc_dmc500.h b/include/drivers/arm/tzc_dmc500.h
new file mode 100644
index 0000000..70f8ad2
--- /dev/null
+++ b/include/drivers/arm/tzc_dmc500.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TZC_DMC500_H__
+#define __TZC_DMC500_H__
+
+#include <tzc_common.h>
+
+#define SI_STATUS_OFFSET				0x000
+#define SI_STATE_CTRL_OFFSET				0x030
+#define SI_FLUSH_CTRL_OFFSET				0x034
+#define SI_INT_CONTROL_OFFSET				0x048
+
+#define SI_INT_STATUS_OFFSET				0x004
+#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET			0x008
+#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET			0x00c
+#define SI_FAIL_CONTROL_OFFSET				0x010
+#define SI_FAIL_ID_OFFSET				0x014
+#define SI_INT_CLR_OFFSET				0x04c
+
+/*
+ * DMC-500 has 2 system interfaces each having a similar set of regs
+ * to configure each interface.
+ */
+#define SI0_BASE					0x0000
+#define SI1_BASE					0x0200
+
+/* Bit positions of SIx_SI_STATUS */
+#define SI_EMPTY_SHIFT					0x01
+#define SI_STALL_ACK_SHIFT				0x00
+#define SI_EMPTY_MASK					0x01
+#define SI_STALL_ACK_MASK				0x01
+
+/* Bit positions of SIx_SI_INT_STATUS */
+#define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT		18
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_SHIFT		16
+#define PMU_REQ_INT_STATUS_SHIFT			2
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT	1
+#define FAILED_ACCESS_INT_STATUS_SHIFT			0
+#define PMU_REQ_INT_OVERFLOW_STATUS_MASK		0x1
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK		0x1
+#define PMU_REQ_INT_STATUS_MASK				0x1
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK	0x1
+#define FAILED_ACCESS_INT_STATUS_MASK			0x1
+
+/* Bit positions of SIx_TZ_FAIL_CONTROL */
+#define DIRECTION_SHIFT					24
+#define NON_SECURE_SHIFT				21
+#define PRIVILEGED_SHIFT				20
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT	3
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT		2
+#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT			0x1
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT	0
+#define DIRECTION_MASK					0x1
+#define NON_SECURE_MASK					0x1
+#define PRIVILEGED_MASK					0x1
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK		0x1
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK		0x1
+#define FAILED_ACCESS_INT_TZ_FAIL_MASK			1
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK	0x1
+
+/* Bit positions of SIx_FAIL_STATUS */
+#define FAIL_ID_VNET_SHIFT				24
+#define FAIL_ID_ID_SHIFT				0
+#define FAIL_ID_VNET_MASK				0xf
+#define FAIL_ID_ID_MASK					0xffffff
+
+/* Bit positions of SIx_SI_STATE_CONTRL */
+#define SI_STALL_REQ_GO					0x0
+#define SI_STALL_REQ_STALL				0x1
+
+/* Bit positions of SIx_SI_FLUSH_CONTROL */
+#define SI_FLUSH_REQ_INACTIVE				0x0
+#define SI_FLUSH_REQ_ACTIVE				0x1
+#define SI_FLUSH_REQ_MASK				0x1
+
+/* Bit positions of SIx_SI_INT_CONTROL */
+#define PMU_REQ_INT_EN_SHIFT				2
+#define OVERLAP_DETECT_INT_EN_SHIFT			1
+#define FAILED_ACCESS_INT_EN_SHIFT			0
+#define PMU_REQ_INT_EN_MASK				0x1
+#define OVERLAP_DETECT_INT_EN_MASK			0x1
+#define FAILED_ACCESS_INT_EN_MASK			0x1
+#define PMU_REQ_INT_EN					0x1
+#define OVERLAP_DETECT_INT_EN				0x1
+#define FAILED_ACCESS_INT_EN				0x1
+
+/* Bit positions of SIx_SI_INT_CLR */
+#define PMU_REQ_OFLOW_CLR_SHIFT				18
+#define FAILED_ACCESS_OFLOW_CLR_SHIFT			16
+#define PMU_REQ_INT_CLR_SHIFT				2
+#define FAILED_ACCESS_INT_CLR_SHIFT			0
+#define PMU_REQ_OFLOW_CLR_MASK				0x1
+#define FAILED_ACCESS_OFLOW_CLR_MASK			0x1
+#define PMU_REQ_INT_CLR_MASK				0x1
+#define FAILED_ACCESS_INT_CLR_MASK			0x1
+#define PMU_REQ_OFLOW_CLR				0x1
+#define FAILED_ACCESS_OFLOW_CLR				0x1
+#define PMU_REQ_INT_CLR					0x1
+#define FAILED_ACCESS_INT_CLR				0x1
+
+/* Macro to get the correct base register for a system interface */
+#define IFACE_OFFSET(sys_if)	((sys_if) ? SI1_BASE : SI0_BASE)
+
+#define MAX_SYS_IF_COUNT				2
+#define MAX_REGION_VAL					8
+
+/* DMC-500 supports striping across a max of 4 DMC instances */
+#define MAX_DMC_COUNT					4
+
+/* Consist of part_number_1 and part_number_0 */
+#define DMC500_PERIPHERAL_ID				0x0450
+
+/* Filter enable bits in a TZC */
+#define TZC_DMC500_REGION_ATTR_F_EN_MASK		0x1
+
+/* Length of registers for configuring each region */
+#define TZC_DMC500_REGION_SIZE				0x018
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/*
+ * Contains the base addresses of all the DMC instances.
+ */
+typedef struct tzc_dmc500_driver_data {
+	uintptr_t dmc_base[MAX_DMC_COUNT];
+	int dmc_count;
+} tzc_dmc500_driver_data_t;
+
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data);
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+				unsigned int nsaid_permissions);
+void tzc_dmc500_configure_region(int region_no,
+				uintptr_t region_base,
+				uintptr_t region_top,
+				tzc_region_attributes_t sec_attr,
+				unsigned int nsaid_permissions);
+void tzc_dmc500_set_action(tzc_action_t action);
+void tzc_dmc500_config_complete(void);
+int tzc_dmc500_verify_complete(void);
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __TZC_DMC500_H__ */
+
diff --git a/include/drivers/auth/auth_common.h b/include/drivers/auth/auth_common.h
index 52a895e..456f69f 100644
--- a/include/drivers/auth/auth_common.h
+++ b/include/drivers/auth/auth_common.h
@@ -46,6 +46,7 @@
 	AUTH_PARAM_SIG_ALG,		/* The image signature algorithm */
 	AUTH_PARAM_HASH,		/* A hash (including the algorithm) */
 	AUTH_PARAM_PUB_KEY,		/* A public key */
+	AUTH_PARAM_NV_CTR,		/* A non-volatile counter */
 } auth_param_type_t;
 
 /*
@@ -80,6 +81,7 @@
 	AUTH_METHOD_NONE = 0,
 	AUTH_METHOD_HASH,	/* Authenticate by hash matching */
 	AUTH_METHOD_SIG,	/* Authenticate by PK operation */
+	AUTH_METHOD_NV_CTR,	/* Authenticate by Non-Volatile Counter */
 	AUTH_METHOD_NUM 	/* Number of methods */
 } auth_method_type_t;
 
@@ -105,7 +107,8 @@
  * Parameters for authentication by NV counter
  */
 typedef struct auth_method_param_nv_ctr_s {
-	auth_param_type_desc_t *nv_ctr;	/* NV counter value */
+	auth_param_type_desc_t *cert_nv_ctr;	/* NV counter in certificate */
+	auth_param_type_desc_t *plat_nv_ctr;	/* NV counter in platform */
 } auth_method_param_nv_ctr_t;
 
 /*
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index e9eebaa..2fe0a69 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -130,7 +130,9 @@
 void arm_io_setup(void);
 
 /* Security utility functions */
-void arm_tzc_setup(void);
+void arm_tzc400_setup(void);
+struct tzc_dmc500_driver_data;
+void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data);
 
 /* Systimer utility function */
 void arm_configure_sys_timer(void);
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index f92126b..636daf2 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -143,7 +143,7 @@
 #define PLAT_ARM_NS_IMAGE_OFFSET	0xE0000000
 
 /* TZC related constants */
-#define PLAT_ARM_TZC_FILTERS		REG_ATTR_FILTER_BIT_ALL
+#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
diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h
index 428df4d..f1396a6 100644
--- a/include/plat/arm/soc/common/soc_css_def.h
+++ b/include/plat/arm/soc/common/soc_css_def.h
@@ -65,6 +65,13 @@
  */
 #define SOC_CSS_NIC400_APB4_BRIDGE	4
 
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE		0x7fe70000
+#define TFW_NVCTR_BASE			(SOC_TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE			4
+#define NTFW_CTR_BASE			(SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE			4
+
 /* Keys */
 #define SOC_KEYS_BASE			0x7fe80000
 #define TZ_PUB_KEY_HASH_BASE		(SOC_KEYS_BASE + 0x0000)
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 6f0a8a0..5857501 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -249,6 +249,8 @@
  ******************************************************************************/
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags);
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr);
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
 
 #if ENABLE_PLAT_COMPAT
 /*
diff --git a/make_helpers/build_env.mk b/make_helpers/build_env.mk
new file mode 100644
index 0000000..62c7f68
--- /dev/null
+++ b/make_helpers/build_env.mk
@@ -0,0 +1,96 @@
+#
+#  Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are met:
+#
+#  Redistributions of source code must retain the above copyright notice, this
+#  list of conditions and the following disclaimer.
+#
+#  Redistributions in binary form must reproduce the above copyright notice,
+#  this list of conditions and the following disclaimer in the documentation
+#  and/or other materials provided with the distribution.
+#
+#  Neither the name of ARM nor the names of its contributors may be used
+#  to endorse or promote products derived from this software without specific
+#  prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+#  POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This file contains the logic to identify and include any relevant
+# build environment specific make include files.
+
+ifndef BUILD_ENV_MK
+    BUILD_ENV_MK        :=      $(lastword $(MAKEFILE_LIST))
+
+    # Block possible built-in command definitions that are not fully portable.
+    # This traps occurences that need replacing with our OS portable macros
+    COPY                :=      $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.")
+    CP                  :=      $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.")
+    DEL                 :=      $$(error "Replace DEL with call to SHELL_DELETE.")
+    MD                  :=      $$(error "Replace MD with call to MAKE_PREREQ_DIR.")
+    MKDIR               :=      $$(error "Replace MKDIR with call to MAKE_PREREQ_DIR.")
+    RD                  :=      $$(error "Replace RD with call to SHELL_REMOVE_DIR.")
+    RM                  :=      $$(error "Replace RM with call to SHELL_DELETE.")
+    RMDIR               :=      $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.")
+
+    ENV_FILE_TO_INCLUDE := unix.mk
+    ifdef OSTYPE
+        ifneq ($(findstring ${OSTYPE}, cygwin),)
+            ENV_FILE_TO_INCLUDE := cygwin.mk
+        else
+            ifneq ($(findstring ${OSTYPE}, MINGW32 mingw msys),)
+                ENV_FILE_TO_INCLUDE := msys.mk
+            endif
+        endif
+    else
+        ifdef MSYSTEM
+            # Although the MINGW MSYS shell sets OSTYPE as msys in its environment,
+            # it does not appear in the GNU make view of environment variables.
+            # We use MSYSTEM as an alternative, as that is seen by make
+            ifneq ($(findstring ${MSYSTEM}, MINGW32 mingw msys),)
+                OSTYPE ?= msys
+                ENV_FILE_TO_INCLUDE := msys.mk
+            endif
+        else
+            ifdef OS
+                ifneq ($(findstring ${OS}, Windows_NT),)
+                    ENV_FILE_TO_INCLUDE := windows.mk
+                endif
+            endif
+        endif
+    endif
+    include ${MAKE_HELPERS_DIRECTORY}${ENV_FILE_TO_INCLUDE}
+    ENV_FILE_TO_INCLUDE :=
+
+    ifndef SHELL_COPY
+        $(error "SHELL_COPY not defined for build environment.")
+    endif
+    ifndef SHELL_COPY_TREE
+        $(error "SHELL_COPY_TREE not defined for build environment.")
+    endif
+    ifndef SHELL_DELETE_ALL
+        $(error "SHELL_DELETE_ALL not defined for build environment.")
+    endif
+    ifndef SHELL_DELETE
+        $(error "SHELL_DELETE not defined for build environment.")
+    endif
+    ifndef MAKE_PREREQ_DIR
+        $(error "MAKE_PREREQ_DIR not defined for build environment.")
+    endif
+    ifndef SHELL_REMOVE_DIR
+        $(error "SHELL_REMOVE_DIR not defined for build environment.")
+    endif
+
+endif
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index b22eaf9..5171ff0 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,23 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+# Report an error if the eval make function is not available.
+$(eval eval_available := T)
+ifneq (${eval_available},T)
+    $(error This makefile only works with a Make program that supports $$(eval))
+endif
+
+# Some utility macros for manipulating awkward (whitespace) characters.
+blank			:=
+space			:=${blank} ${blank}
+
+# A user defined function to recursively search for a filename below a directory
+#    $1 is the directory root of the recursive search (blank for current directory).
+#    $2 is the file name to search for.
+define rwildcard
+$(strip $(foreach d,$(wildcard ${1}*),$(call rwildcard,${d}/,${2}) $(filter $(subst *,%,%${2}),${d})))
+endef
+
 # This table is used in converting lower case to upper case.
 uppercase_table:=a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z
 
@@ -193,10 +210,8 @@
 	@echo "  CC      $$<"
 	$$(Q)$$(CC) $$(CFLAGS) -D$(IMAGE) -c $$< -o $$@
 
-
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | bl$(3)_dirs
 	@echo "  DEPS    $$@"
-	@mkdir -p $(1)
 	$$(Q)$$(CC) $$(CFLAGS) -M -MT $(OBJ) -MF $$@ $$<
 
 ifdef IS_ANYTHING_TO_BUILD
@@ -220,9 +235,8 @@
 	@echo "  AS      $$<"
 	$$(Q)$$(AS) $$(ASFLAGS) -D$(IMAGE) -c $$< -o $$@
 
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | bl$(3)_dirs
 	@echo "  DEPS    $$@"
-	@mkdir -p $(1)
 	$$(Q)$$(AS) $$(ASFLAGS) -M -MT $(OBJ) -MF $$@ $$<
 
 ifdef IS_ANYTHING_TO_BUILD
@@ -243,9 +257,8 @@
 	@echo "  PP      $$<"
 	$$(Q)$$(AS) $$(ASFLAGS) -P -E -D__LINKER__ -o $$@ $$<
 
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | $(dir ${1})
 	@echo "  DEPS    $$@"
-	@mkdir -p $$(dir $$@)
 	$$(Q)$$(AS) $$(ASFLAGS) -M -MT $(1) -MF $$@ $$<
 
 ifdef IS_ANYTHING_TO_BUILD
@@ -274,7 +287,7 @@
 
 # NOTE: The line continuation '\' is required in the next define otherwise we
 # end up with a line-feed characer at the end of the last c filename.
-# Also bare this issue in mind if extending the list of supported filetypes.
+# Also bear this issue in mind if extending the list of supported filetypes.
 define SOURCES_TO_OBJS
         $(notdir $(patsubst %.c,%.o,$(filter %.c,$(1)))) \
         $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
@@ -310,18 +323,36 @@
         $(eval DUMP       := $(call IMG_DUMP,$(1)))
         $(eval BIN        := $(call IMG_BIN,$(1)))
         $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
+        # We use sort only to get a list of unique object directory names.
+        # ordering is not relevant but sort removes duplicates.
+        $(eval TEMP_OBJ_DIRS := $(sort $(BUILD_DIR)/ $(dir ${OBJS})))
+        # The $(dir ) function leaves a trailing / on the directory names
+        # We append a . then strip /. from each, to remove the trailing / characters
+        # This gives names suitable for use as make rule targets.
+        $(eval OBJ_DIRS   := $(subst /.,,$(addsuffix .,$(TEMP_OBJ_DIRS))))
+
+# Create generators for object directory structure
 
-        $(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
-        $(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
+$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},)))
 
-$(BUILD_DIR):
-	$$(Q)mkdir -p "$$@"
+.PHONY : bl${1}_dirs
 
-$(ELF): $(OBJS) $(LINKERFILE)
+# We use order-only prerequisites to ensure that directories are created,
+# but do not cause re-builds every time a file is written.
+bl${1}_dirs: | ${OBJ_DIRS}
+
+$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
+$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
+
+$(ELF): $(OBJS) $(LINKERFILE) | bl$(1)_dirs
 	@echo "  LD      $$@"
+ifdef MAKE_BUILD_STRINGS
+	$(call MAKE_BUILD_STRINGS, $(BUILD_DIR)/build_message.o)
+else
 	@echo 'const char build_message[] = "Built : "$(BUILD_MESSAGE_TIMESTAMP); \
 	       const char version_string[] = "${VERSION_STRING}";' | \
 		$$(CC) $$(CFLAGS) -xc - -o $(BUILD_DIR)/build_message.o
+endif
 	$$(Q)$$(LD) -o $$@ $$(LDFLAGS) -Map=$(MAPFILE) --script $(LINKERFILE) \
 					$(BUILD_DIR)/build_message.o $(OBJS)
 
@@ -337,7 +368,7 @@
 	@echo
 
 .PHONY: bl$(1)
-bl$(1): $(BUILD_DIR) $(BIN) $(DUMP)
+bl$(1): $(BIN) $(DUMP)
 
 all: bl$(1)
 
diff --git a/make_helpers/cygwin.mk b/make_helpers/cygwin.mk
new file mode 100644
index 0000000..e69c0b1
--- /dev/null
+++ b/make_helpers/cygwin.mk
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# OS specific definitions for builds in a Cygwin environment.
+# Cygwin allows us to use unix style commands on a windows platform.
+
+ifndef CYGWIN_MK
+    CYGWIN_MK := $(lastword $(MAKEFILE_LIST))
+
+    include ${MAKE_HELPERS_DIRECTORY}unix.mk
+
+    # In cygwin executable files have the Windows .exe extension type.
+    BIN_EXT := .exe
+
+endif
diff --git a/make_helpers/msys.mk b/make_helpers/msys.mk
new file mode 100644
index 0000000..188dc6c
--- /dev/null
+++ b/make_helpers/msys.mk
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# OS specific definitions for builds in a Mingw32 MSYS environment.
+# Mingw32 allows us to use some unix style commands on a windows platform.
+
+ifndef MSYS_MK
+    MSYS_MK := $(lastword $(MAKEFILE_LIST))
+
+    include ${MAKE_HELPERS_DIRECTORY}unix.mk
+
+    # In MSYS executable files have the Windows .exe extension type.
+    BIN_EXT := .exe
+
+endif
+
diff --git a/make_helpers/plat_helpers.mk b/make_helpers/plat_helpers.mk
new file mode 100644
index 0000000..85ba84f
--- /dev/null
+++ b/make_helpers/plat_helpers.mk
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+################################################################################
+# Helpers for finding and referencing platform directories
+################################################################################
+
+ifndef PLAT_HELPERS_MK
+    PLAT_HELPERS_MK := $(lastword $(MAKEFILE_LIST))
+
+    ifeq (${PLAT},)
+        $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
+    endif
+
+    # PLATFORM_ROOT can be overridden for when building tools directly
+    PLATFORM_ROOT               ?= plat/
+    PLAT_MAKEFILE               := platform.mk
+
+    # Generate the platforms list by recursively searching for all directories
+    # under /plat containing a PLAT_MAKEFILE. Append each platform with a `|`
+    # char and strip out the final '|'.
+    ALL_PLATFORM_MK_FILES       := $(call rwildcard,${PLATFORM_ROOT},${PLAT_MAKEFILE})
+    ALL_PLATFORM_DIRS           := $(patsubst %/,%,$(dir ${ALL_PLATFORM_MK_FILES}))
+    ALL_PLATFORMS               := $(sort $(notdir ${ALL_PLATFORM_DIRS}))
+
+    PLAT_MAKEFILE_FULL          := $(filter %/${PLAT}/${PLAT_MAKEFILE},${ALL_PLATFORM_MK_FILES})
+    PLATFORM_LIST               := $(subst ${space},|,${ALL_PLATFORMS})
+    ifeq ($(PLAT_MAKEFILE_FULL),)
+        $(error "Error: Invalid platform. The following platforms are available: ${PLATFORM_LIST}")
+    endif
+
+    # Record the directory where the platform make file was found.
+    PLAT_DIR                    := $(dir ${PLAT_MAKEFILE_FULL})
+
+endif
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index e934d72..71d9747 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -58,6 +58,14 @@
 TRUSTED_KEY_CERT	:=	${BUILD_PLAT}/trusted_key.crt
 FWU_CERT		:=	${BUILD_PLAT}/fwu_cert.crt
 
+# Default non-volatile counter values (overridable by the platform)
+TFW_NVCTR_VAL		?=	0
+NTFW_NVCTR_VAL		?=	0
+
+# Pass the non-volatile counters to the cert_create tool
+$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr))
+$(eval $(call CERT_ADD_CMD_OPT,${NTFW_NVCTR_VAL},--ntfw-nvctr))
+
 # Add Trusted Key certificate to the fip_create and cert_create command line options
 $(eval $(call FIP_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert))
 $(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_KEY_CERT},--trusted-key-cert))
diff --git a/make_helpers/unix.mk b/make_helpers/unix.mk
new file mode 100644
index 0000000..ab60435
--- /dev/null
+++ b/make_helpers/unix.mk
@@ -0,0 +1,81 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# Trusted Firmware shell command definitions for a Unix style environment.
+
+ifndef UNIX_MK
+    UNIX_MK := $(lastword $(MAKEFILE_LIST))
+
+    ECHO_BLANK_LINE := echo
+
+    DIR_DELIM := /
+    PATH_SEP := :
+
+    # These defines provide Unix style equivalents of the shell commands
+    # required by the Trusted Firmware build environment.
+
+    # ${1} is the file to be copied.
+    # ${2} is the destination file name.
+    define SHELL_COPY
+	${Q}cp -f  "${1}"  "${2}"
+    endef
+
+    # ${1} is the directory to be copied.
+    # ${2} is the destination directory path.
+    define SHELL_COPY_TREE
+	${Q}cp -rf  "${1}"  "${2}"
+    endef
+
+    # ${1} is the file to be deleted.
+    define SHELL_DELETE
+	-${Q}rm -f  "${1}"
+    endef
+
+    # ${1} is a space delimited list of files to be deleted.
+    # Note that we do not quote ${1}, as multiple parameters may be passed.
+    define SHELL_DELETE_ALL
+	-${Q}rm -rf  ${1}
+    endef
+
+    # ${1} is the directory to be generated.
+    # ${2} is optional, and allows a prerequisite to be specified.
+    define MAKE_PREREQ_DIR
+
+${1} : ${2}
+	${Q}mkdir -p  "${1}"
+
+    endef
+
+    define SHELL_REMOVE_DIR
+	-${Q}rm -rf  "${1}"
+    endef
+
+endif
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
new file mode 100644
index 0000000..8ac8246
--- /dev/null
+++ b/make_helpers/windows.mk
@@ -0,0 +1,109 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# OS specific parts for builds in a Windows_NT environment. The
+# environment variable OS is set to Windows_NT on all modern Windows platforms
+
+# Include generic windows command definitions.
+
+ifndef WINDOWS_MK
+    WINDOWS_MK := $(lastword $(MAKEFILE_LIST))
+
+    ECHO_BLANK_LINE := @cmd /c echo.
+    DIR_DELIM := $(strip \)
+    BIN_EXT   := .exe
+    PATH_SEP  := ;
+
+    # For some Windows native commands there is a problem with the directory delimiter.
+    # Make uses / (slash) and the commands expect \ (backslash)
+    # We have to provide a means of translating these, so we define local functions.
+
+    # ${1} is the file to be copied.
+    # ${2} is the destination file name.
+    define SHELL_COPY
+	$(eval tmp_from_file:=$(subst /,\,${1}))
+	$(eval tmp_to_file:=$(subst /,\,${2}))
+	copy "${tmp_from_file}" "${tmp_to_file}"
+    endef
+
+    # ${1} is the directory to be copied.
+    # ${2} is the destination directory path.
+    define SHELL_COPY_TREE
+	$(eval tmp_from_dir:=$(subst /,\,${1}))
+	$(eval tmp_to_dir:=$(subst /,\,${2}))
+	xcopy /HIVE "${tmp_from_dir}" "${tmp_to_dir}"
+    endef
+
+    # ${1} is the file to be deleted.
+    define SHELL_DELETE
+	$(eval tmp_del_file:=$(subst /,\,${*}))
+	-@if exist $(tmp_del_file)  del /Q $(tmp_del_file)
+    endef
+
+    # ${1} is a space delimited list of files to be deleted.
+    define SHELL_DELETE_ALL
+	$(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename})))
+    endef
+
+    # ${1} is the directory to be generated.
+    # ${2} is optional, and allows prerequisites to be specified.
+    define MAKE_PREREQ_DIR
+
+${1} : ${2}
+	$(eval tmp_dir:=$(subst /,\,${1}))
+	-@if not exist "$(tmp_dir)"  mkdir "${tmp_dir}"
+
+    endef
+
+    # ${1} is the directory to be removed.
+    define SHELL_REMOVE_DIR
+	$(eval tmp_dir:=$(subst /,\,${1}))
+	-@if exist "$(tmp_dir)"  rd /Q /S "$(tmp_dir)"
+    endef
+
+endif
+
+# Because git is not available from CMD.EXE, we need to avoid
+# the BUILD_STRING generation which uses git.
+# For now we use "development build".
+# This can be overridden from the command line or environment.
+BUILD_STRING ?= development build
+
+# The DOS echo shell command does not strip ' characters from the command
+# parameters before printing. We therefore use an alternative method invoked
+# by defining the MAKE_BUILD_STRINGS macro.
+BUILT_TIME_DATE_STRING = const char build_message[] = "Built : "${BUILD_MESSAGE_TIMESTAMP};
+VERSION_STRING_MESSAGE = const char version_string[] = "${VERSION_STRING}";
+define MAKE_BUILD_STRINGS
+	@echo $$(BUILT_TIME_DATE_STRING) $$(VERSION_STRING_MESSAGE) | \
+		$$(CC) $$(CFLAGS) -x c - -o $1
+endef
+
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index 103aafb..7ae00cc 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -31,11 +31,14 @@
 #include <arm_def.h>
 #include <assert.h>
 #include <platform.h>
+#include <platform_oid.h>
 #include <stdint.h>
 #include <string.h>
 
 /* Weak definition may be overridden in specific platform */
 #pragma weak plat_match_rotpk
+#pragma weak plat_get_nv_ctr
+#pragma weak plat_set_nv_ctr
 
 /* SHA256 algorithm */
 #define SHA256_BYTES			32
@@ -148,3 +151,43 @@
 	return 0;
 }
 
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+	const char *oid;
+	uint32_t *nv_ctr_addr;
+
+	assert(cookie != NULL);
+	assert(nv_ctr != NULL);
+
+	oid = (const char *)cookie;
+	if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+		nv_ctr_addr = (uint32_t *)TFW_NVCTR_BASE;
+	} else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+		nv_ctr_addr = (uint32_t *)NTFW_CTR_BASE;
+	} else {
+		return 1;
+	}
+
+	*nv_ctr = (unsigned int)(*nv_ctr_addr);
+
+	return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. On Juno and FVP, the non-volatile
+ * counters are RO and cannot be modified. We expect the values in the
+ * certificates to always match the RO values so that this function is never
+ * called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+	return 1;
+}
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index da6beec..6ddc0c9 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -51,6 +51,11 @@
     endif
     $(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
 
+    # Certificate NV-Counters. Use values corresponding to tied off values in
+    # ARM development platforms
+    TFW_NVCTR_VAL	?=	31
+    NTFW_NVCTR_VAL	?=	223
+
     BL1_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c
     BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c
 endif
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index dbca280..b0f07ef 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -69,7 +69,13 @@
 
 #define PCIE_EXP_BASE			0x40000000
 #define TZRNG_BASE			0x7fe60000
-#define TZNVCTR_BASE			0x7fe70000
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE		0x7fe70000
+#define TFW_NVCTR_BASE			(TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE			4
+#define NTFW_CTR_BASE			(TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE			4
 
 /* Keys */
 #define SOC_KEYS_BASE			0x7fe80000
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
index 0cf8450..b1de977 100644
--- a/plat/arm/board/fvp/fvp_security.c
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -46,5 +46,5 @@
 	 */
 
 	if (get_arm_config()->flags & ARM_CONFIG_HAS_TZC)
-		arm_tzc_setup();
+		arm_tzc400_setup();
 }
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 3428cb5..ca8e35e 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -113,7 +113,7 @@
  * would normally use the default ID so allow that too.
  */
 #define PLAT_ARM_TZC_BASE		0x2a4a0000
-#define PLAT_ARM_TZC_FILTERS		REG_ATTR_FILTER_BIT(0)
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
 
 #define PLAT_ARM_TZC_NS_DEV_ACCESS	(				\
 		TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT)	|	\
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index aad2e2e..afd939d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -65,7 +65,7 @@
 FVP_INTERCONNECT_SOURCES	:= 	drivers/arm/cci/cci.c		\
 					plat/arm/common/arm_cci.c
 
-FVP_SECURITY_SOURCES	:=	drivers/arm/tzc400/tzc400.c		\
+FVP_SECURITY_SOURCES	:=	drivers/arm/tzc/tzc400.c		\
 				plat/arm/board/fvp/fvp_security.c	\
 				plat/arm/common/arm_tzc400.c
 
diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c
index f9386ca..202342a 100644
--- a/plat/arm/board/juno/juno_security.c
+++ b/plat/arm/board/juno/juno_security.c
@@ -65,7 +65,7 @@
 void plat_arm_security_setup(void)
 {
 	/* Initialize the TrustZone Controller */
-	arm_tzc_setup();
+	arm_tzc400_setup();
 	/* Do ARM CSS internal NIC setup */
 	css_init_nic400();
 	/* Do ARM CSS SoC security setup */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 0a2244d..4fda4ca 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -37,7 +37,7 @@
 JUNO_INTERCONNECT_SOURCES	:=	drivers/arm/cci/cci.c		\
 					plat/arm/common/arm_cci.c
 
-JUNO_SECURITY_SOURCES	:=	drivers/arm/tzc400/tzc400.c		\
+JUNO_SECURITY_SOURCES	:=	drivers/arm/tzc/tzc400.c		\
 				plat/arm/board/juno/juno_security.c	\
 				plat/arm/common/arm_tzc400.c
 
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 8b46aae..3962940 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -48,53 +48,53 @@
  * When booting an EL3 payload, this is simplified: we configure region 0 with
  * secure access only and do not enable any other region.
  ******************************************************************************/
-void arm_tzc_setup(void)
+void arm_tzc400_setup(void)
 {
 	INFO("Configuring TrustZone Controller\n");
 
-	tzc_init(PLAT_ARM_TZC_BASE);
+	tzc400_init(PLAT_ARM_TZC_BASE);
 
 	/* Disable filters. */
-	tzc_disable_filters();
+	tzc400_disable_filters();
 
 #ifndef EL3_PAYLOAD_BASE
 	/* Region 0 set to no access by default */
-	tzc_configure_region0(TZC_REGION_S_NONE, 0);
+	tzc400_configure_region0(TZC_REGION_S_NONE, 0);
 
 	/* Region 1 set to cover Secure part of DRAM */
-	tzc_configure_region(PLAT_ARM_TZC_FILTERS, 1,
+	tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 1,
 			ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END,
 			TZC_REGION_S_RDWR,
 			0);
 
 	/* Region 2 set to cover Non-Secure access to 1st DRAM address range.
 	 * Apply the same configuration to given filters in the TZC. */
-	tzc_configure_region(PLAT_ARM_TZC_FILTERS, 2,
+	tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 2,
 			ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END,
 			TZC_REGION_S_NONE,
 			PLAT_ARM_TZC_NS_DEV_ACCESS);
 
 	/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
-	tzc_configure_region(PLAT_ARM_TZC_FILTERS, 3,
+	tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 3,
 			ARM_DRAM2_BASE, ARM_DRAM2_END,
 			TZC_REGION_S_NONE,
 			PLAT_ARM_TZC_NS_DEV_ACCESS);
 #else
 	/* Allow secure access only to DRAM for EL3 payloads. */
-	tzc_configure_region0(TZC_REGION_S_RDWR, 0);
+	tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
 #endif /* EL3_PAYLOAD_BASE */
 
 	/*
 	 * Raise an exception if a NS device tries to access secure memory
 	 * TODO: Add interrupt handling support.
 	 */
-	tzc_set_action(TZC_ACTION_ERR);
+	tzc400_set_action(TZC_ACTION_ERR);
 
 	/* Enable filters. */
-	tzc_enable_filters();
+	tzc400_enable_filters();
 }
 
 void plat_arm_security_setup(void)
 {
-	arm_tzc_setup();
+	arm_tzc400_setup();
 }
diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
new file mode 100644
index 0000000..f0ed9a6
--- /dev/null
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arm_def.h>
+#include <assert.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <tzc_dmc500.h>
+
+/*******************************************************************************
+ * Initialize the DMC500-TrustZone Controller for ARM standard platforms.
+ * Configure both the interfaces on Region 0 with no access, Region 1 with
+ * secure access only, and the remaining DRAM regions access from the
+ * given Non-Secure masters.
+ *
+ * When booting an EL3 payload, this is simplified: we configure region 0 with
+ * secure access only and do not enable any other region.
+ ******************************************************************************/
+void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data)
+{
+	assert(plat_driver_data);
+
+	INFO("Configuring DMC-500 TZ Settings\n");
+
+	tzc_dmc500_driver_init(plat_driver_data);
+
+#ifndef EL3_PAYLOAD_BASE
+	/* Region 0 set to no access by default */
+	tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
+
+	/* Region 1 set to cover Secure part of DRAM */
+	tzc_dmc500_configure_region(1, ARM_AP_TZC_DRAM1_BASE,
+		ARM_AP_TZC_DRAM1_END,
+		TZC_REGION_S_RDWR,
+		0);
+
+	/* Region 2 set to cover Non-Secure access to 1st DRAM address range.*/
+	tzc_dmc500_configure_region(2,
+		ARM_NS_DRAM1_BASE,
+		ARM_NS_DRAM1_END,
+		TZC_REGION_S_NONE,
+		PLAT_ARM_TZC_NS_DEV_ACCESS);
+
+	/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
+	tzc_dmc500_configure_region(3,
+		ARM_DRAM2_BASE,
+		ARM_DRAM2_END,
+		TZC_REGION_S_NONE,
+		PLAT_ARM_TZC_NS_DEV_ACCESS);
+#else
+	/* Allow secure access only to DRAM for EL3 payloads */
+	tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0);
+#endif
+	/*
+	 * Raise an exception if a NS device tries to access secure memory
+	 * TODO: Add interrupt handling support.
+	 */
+	tzc_dmc500_set_action(TZC_ACTION_RV_LOWERR);
+
+	/*
+	 * Flush the configuration settings to have an affect. Validate
+	 * flush by checking FILTER_EN is set on region 1 attributes
+	 * register.
+	 */
+	tzc_dmc500_config_complete();
+
+	/*
+	 * Wait for the flush to complete.
+	 * TODO: Have a timeout for this loop
+	 */
+	while (tzc_dmc500_verify_complete())
+		;
+}
diff --git a/plat/mediatek/mt8173/drivers/spm/spm.c b/plat/mediatek/mt8173/drivers/spm/spm.c
index f28b264..75eb61a 100644
--- a/plat/mediatek/mt8173/drivers/spm/spm.c
+++ b/plat/mediatek/mt8173/drivers/spm/spm.c
@@ -49,10 +49,6 @@
 
 #define SPM_SYSCLK_SETTLE       128	/* 3.9ms */
 
-#if DEBUG
-static int spm_dormant_sta = CPU_DORMANT_RESET;
-#endif
-
 DEFINE_BAKERY_LOCK(spm_lock);
 
 static int spm_hotplug_ready __section("tzfw_coherent_mem");
@@ -378,7 +374,6 @@
 	     wakesta->raw_sta, wakesta->idle_sta, wakesta->event_reg,
 	     wakesta->isr);
 
-	INFO("dormant state = %d\n", spm_dormant_sta);
 	return wr;
 }
 
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index 8d7b8a5..27545ba 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -32,7 +32,7 @@
 PLAT		:= none
 V		:= 0
 DEBUG		:= 0
-BINARY		:= ${PROJECT}
+BINARY		:= ${PROJECT}${BIN_EXT}
 OPENSSL_DIR	:= /usr
 
 OBJECTS := src/cert.o \
@@ -47,15 +47,17 @@
 
 CFLAGS := -Wall -std=c99
 
-# Check the platform
-ifeq (${PLAT},none)
-  $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
-endif
-PLAT_MAKEFILE		:=	platform.mk
-PLAT_INCLUDE	:=	$(shell find ../../plat/ -wholename '*/${PLAT}/${PLAT_MAKEFILE}' |	\
-				sed 's/${PLAT_MAKEFILE}/include/')
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+
+PLATFORM_ROOT		:=	../../plat/
+include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
+
+PLAT_INCLUDE		:=	$(wildcard ${PLAT_DIR}include)
+
 ifeq ($(PLAT_INCLUDE),)
-  $(error "Error: Invalid platform '${PLAT}'")
+  $(error "Error: Invalid platform '${PLAT}' has no include directory.")
 endif
 
 ifeq (${DEBUG},1)
@@ -76,9 +78,8 @@
 LIB := -lssl -lcrypto
 
 CC := gcc
-RM := rm -rf
 
-.PHONY: all clean
+.PHONY: all clean realclean
 
 all: clean ${BINARY}
 
@@ -94,7 +95,8 @@
 	${Q}${CC} -c ${CFLAGS} ${INC_DIR} $< -o $@
 
 clean:
-	${Q}${RM} -f src/build_msg.o ${OBJECTS}
+	$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
 
 realclean: clean
-	${Q}${RM} -f ${BINARY}
+	$(call SHELL_DELETE, ${BINARY})
+
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
index 82a4bcb..95bde6c 100644
--- a/tools/cert_create/include/ext.h
+++ b/tools/cert_create/include/ext.h
@@ -35,12 +35,18 @@
 #include <openssl/x509v3.h>
 
 /* Extension types supported */
-enum {
+enum ext_type_e {
 	EXT_TYPE_NVCOUNTER,
 	EXT_TYPE_PKEY,
 	EXT_TYPE_HASH
 };
 
+/* NV-Counter types */
+enum nvctr_type_e {
+	NVCTR_TYPE_TFW,
+	NVCTR_TYPE_NTFW
+};
+
 /*
  * This structure contains the relevant information to create the extensions
  * to be included in the certificates. This extensions will be used to
@@ -50,20 +56,21 @@
 	const char *oid;	/* OID of the extension */
 	const char *sn;		/* Short name */
 	const char *ln;		/* Long description */
+	const char *opt;	/* Command line option to specify data */
 	const char *help_msg;	/* Help message */
+	const char *arg;	/* Argument passed from command line */
 	int asn1_type;		/* OpenSSL ASN1 type of the extension data.
 				 * Supported types are:
 				 *   - V_ASN1_INTEGER
 				 *   - V_ASN1_OCTET_STRING
 				 */
-	int type;
-	const char *opt;	/* Command line option to specify data */
-	/* Extension data (depends on extension type) */
+	int type;		/* See ext_type_e */
+
+	/* Extension attributes (depends on extension type) */
 	union {
-		const char *fn;	/* File with extension data */
-		int nvcounter;	/* Non volatile counter */
-		int key;	/* Public key */
-	} data;
+		int nvctr_type;	/* See nvctr_type_e */
+		int key;	/* Index into array of registered public keys */
+	} attr;
 
 	int alias;		/* In case OpenSSL provides an standard
 				 * extension of the same type, add the new
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index 3d2b4ba..c87d988 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -196,9 +196,17 @@
 		for (j = 0; j < cert->num_ext; j++) {
 			ext = &extensions[cert->ext[j]];
 			switch (ext->type) {
+			case EXT_TYPE_NVCOUNTER:
+				/* Counter value must be specified */
+				if ((!ext->optional) && (ext->arg == NULL)) {
+					ERROR("Value for '%s' not specified\n",
+					      ext->ln);
+					exit(1);
+				}
+				break;
 			case EXT_TYPE_PKEY:
 				/* Key filename must be specified */
-				key = &keys[ext->data.key];
+				key = &keys[ext->attr.key];
 				if (!new_keys && key->fn == NULL) {
 					ERROR("Key '%s' required by '%s' not "
 					      "specified\n", key->desc,
@@ -211,15 +219,15 @@
 				 * Binary image must be specified
 				 * unless it is explicitly made optional.
 				 */
-				if ((!ext->optional) && (ext->data.fn == NULL)) {
+				if ((!ext->optional) && (ext->arg == NULL)) {
 					ERROR("Image for '%s' not specified\n",
 					      ext->ln);
 					exit(1);
 				}
 				break;
 			default:
-				ERROR("Unknown extension type in '%s'\n",
-				      ext->ln);
+				ERROR("Unknown extension type '%d' in '%s'\n",
+				      ext->type, ext->ln);
 				exit(1);
 				break;
 			}
@@ -259,7 +267,7 @@
 	key_t *key = NULL;
 	cert_t *cert = NULL;
 	FILE *file = NULL;
-	int i, j, ext_nid;
+	int i, j, ext_nid, nvctr;
 	int c, opt_idx = 0;
 	const struct option *cmd_opt;
 	const char *cur_opt;
@@ -331,7 +339,7 @@
 		case CMD_OPT_EXT:
 			cur_opt = cmd_opt_get_name(opt_idx);
 			ext = ext_get_by_opt(cur_opt);
-			ext->data.fn = strdup(optarg);
+			ext->arg = strdup(optarg);
 			break;
 		case CMD_OPT_KEY:
 			cur_opt = cmd_opt_get_name(opt_idx);
@@ -420,11 +428,12 @@
 			 */
 			switch (ext->type) {
 			case EXT_TYPE_NVCOUNTER:
+				nvctr = atoi(ext->arg);
 				CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
-						EXT_CRIT, ext->data.nvcounter));
+						EXT_CRIT, nvctr));
 				break;
 			case EXT_TYPE_HASH:
-				if (ext->data.fn == NULL) {
+				if (ext->arg == NULL) {
 					if (ext->optional) {
 						/* Include a hash filled with zeros */
 						memset(md, 0x0, SHA256_DIGEST_LENGTH);
@@ -434,9 +443,9 @@
 					}
 				} else {
 					/* Calculate the hash of the file */
-					if (!sha_file(ext->data.fn, md)) {
+					if (!sha_file(ext->arg, md)) {
 						ERROR("Cannot calculate hash of %s\n",
-							ext->data.fn);
+							ext->arg);
 						exit(1);
 					}
 				}
@@ -446,11 +455,11 @@
 				break;
 			case EXT_TYPE_PKEY:
 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
-					EXT_CRIT, keys[ext->data.key].key));
+					EXT_CRIT, keys[ext->attr.key].key));
 				break;
 			default:
-				ERROR("Unknown extension type in %s\n",
-						cert->cn);
+				ERROR("Unknown extension type '%d' in %s\n",
+						ext->type, cert->cn);
 				exit(1);
 			}
 
diff --git a/tools/cert_create/src/tbbr/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
index 7a50ab3..8f7feb5 100644
--- a/tools/cert_create/src/tbbr/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.c
@@ -49,9 +49,10 @@
 		.key = ROT_KEY,
 		.issuer = TRUSTED_BOOT_FW_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			TRUSTED_BOOT_FW_HASH_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[TRUSTED_KEY_CERT] = {
 		.id = TRUSTED_KEY_CERT,
@@ -62,10 +63,11 @@
 		.key = ROT_KEY,
 		.issuer = TRUSTED_KEY_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			TRUSTED_WORLD_PK_EXT,
 			NON_TRUSTED_WORLD_PK_EXT
 		},
-		.num_ext = 2
+		.num_ext = 3
 	},
 	[SCP_FW_KEY_CERT] = {
 		.id = SCP_FW_KEY_CERT,
@@ -76,9 +78,10 @@
 		.key = TRUSTED_WORLD_KEY,
 		.issuer = SCP_FW_KEY_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			SCP_FW_CONTENT_CERT_PK_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[SCP_FW_CONTENT_CERT] = {
 		.id = SCP_FW_CONTENT_CERT,
@@ -89,9 +92,10 @@
 		.key = SCP_FW_CONTENT_CERT_KEY,
 		.issuer = SCP_FW_CONTENT_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			SCP_FW_HASH_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[SOC_FW_KEY_CERT] = {
 		.id = SOC_FW_KEY_CERT,
@@ -102,9 +106,10 @@
 		.key = TRUSTED_WORLD_KEY,
 		.issuer = SOC_FW_KEY_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			SOC_FW_CONTENT_CERT_PK_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[SOC_FW_CONTENT_CERT] = {
 		.id = SOC_FW_CONTENT_CERT,
@@ -115,9 +120,10 @@
 		.key = SOC_FW_CONTENT_CERT_KEY,
 		.issuer = SOC_FW_CONTENT_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			SOC_AP_FW_HASH_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[TRUSTED_OS_FW_KEY_CERT] = {
 		.id = TRUSTED_OS_FW_KEY_CERT,
@@ -128,9 +134,10 @@
 		.key = TRUSTED_WORLD_KEY,
 		.issuer = TRUSTED_OS_FW_KEY_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			TRUSTED_OS_FW_CONTENT_CERT_PK_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[TRUSTED_OS_FW_CONTENT_CERT] = {
 		.id = TRUSTED_OS_FW_CONTENT_CERT,
@@ -141,9 +148,10 @@
 		.key = TRUSTED_OS_FW_CONTENT_CERT_KEY,
 		.issuer = TRUSTED_OS_FW_CONTENT_CERT,
 		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
 			TRUSTED_OS_FW_HASH_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[NON_TRUSTED_FW_KEY_CERT] = {
 		.id = NON_TRUSTED_FW_KEY_CERT,
@@ -154,9 +162,10 @@
 		.key = NON_TRUSTED_WORLD_KEY,
 		.issuer = NON_TRUSTED_FW_KEY_CERT,
 		.ext = {
+			NON_TRUSTED_FW_NVCOUNTER_EXT,
 			NON_TRUSTED_FW_CONTENT_CERT_PK_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[NON_TRUSTED_FW_CONTENT_CERT] = {
 		.id = NON_TRUSTED_FW_CONTENT_CERT,
@@ -167,9 +176,10 @@
 		.key = NON_TRUSTED_FW_CONTENT_CERT_KEY,
 		.issuer = NON_TRUSTED_FW_CONTENT_CERT,
 		.ext = {
+			NON_TRUSTED_FW_NVCOUNTER_EXT,
 			NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT
 		},
-		.num_ext = 1
+		.num_ext = 2
 	},
 	[FWU_CERT] = {
 		.id = FWU_CERT,
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index 8bcb070..5304bd5 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.c
@@ -44,19 +44,23 @@
 static ext_t tbb_ext[] = {
 	[TRUSTED_FW_NVCOUNTER_EXT] = {
 		.oid = TRUSTED_FW_NVCOUNTER_OID,
+		.opt = "tfw-nvctr",
+		.help_msg = "Trusted Firmware Non-Volatile counter value",
 		.sn = "TrustedWorldNVCounter",
 		.ln = "Trusted World Non-Volatile counter",
 		.asn1_type = V_ASN1_INTEGER,
 		.type = EXT_TYPE_NVCOUNTER,
-		.data.nvcounter = TRUSTED_WORLD_NVCTR_VALUE
+		.attr.nvctr_type = NVCTR_TYPE_TFW
 	},
 	[NON_TRUSTED_FW_NVCOUNTER_EXT] = {
 		.oid = NON_TRUSTED_FW_NVCOUNTER_OID,
+		.opt = "ntfw-nvctr",
+		.help_msg = "Non-Trusted Firmware Non-Volatile counter value",
 		.sn = "NormalWorldNVCounter",
-		.ln = "Normal World Non-Volatile counter",
+		.ln = "Non-Trusted Firmware Non-Volatile counter",
 		.asn1_type = V_ASN1_INTEGER,
 		.type = EXT_TYPE_NVCOUNTER,
-		.data.nvcounter = NORMAL_WORLD_NVCTR_VALUE
+		.attr.nvctr_type = NVCTR_TYPE_NTFW
 	},
 	[TRUSTED_BOOT_FW_HASH_EXT] = {
 		.oid = TRUSTED_BOOT_FW_HASH_OID,
@@ -73,7 +77,7 @@
 		.ln = "Trusted World Public Key",
 		.asn1_type = V_ASN1_OCTET_STRING,
 		.type = EXT_TYPE_PKEY,
-		.data.key = TRUSTED_WORLD_KEY
+		.attr.key = TRUSTED_WORLD_KEY
 	},
 	[NON_TRUSTED_WORLD_PK_EXT] = {
 		.oid = NON_TRUSTED_WORLD_PK_OID,
@@ -81,7 +85,7 @@
 		.ln = "Non-Trusted World Public Key",
 		.asn1_type = V_ASN1_OCTET_STRING,
 		.type = EXT_TYPE_PKEY,
-		.data.key = NON_TRUSTED_WORLD_KEY
+		.attr.key = NON_TRUSTED_WORLD_KEY
 	},
 	[SCP_FW_CONTENT_CERT_PK_EXT] = {
 		.oid = SCP_FW_CONTENT_CERT_PK_OID,
@@ -89,7 +93,7 @@
 		.ln = "SCP Firmware content certificate public key",
 		.asn1_type = V_ASN1_OCTET_STRING,
 		.type = EXT_TYPE_PKEY,
-		.data.key = SCP_FW_CONTENT_CERT_KEY
+		.attr.key = SCP_FW_CONTENT_CERT_KEY
 	},
 	[SCP_FW_HASH_EXT] = {
 		.oid = SCP_FW_HASH_OID,
@@ -106,7 +110,7 @@
 		.ln = "SoC Firmware content certificate public key",
 		.asn1_type = V_ASN1_OCTET_STRING,
 		.type = EXT_TYPE_PKEY,
-		.data.key = SOC_FW_CONTENT_CERT_KEY
+		.attr.key = SOC_FW_CONTENT_CERT_KEY
 	},
 	[SOC_AP_FW_HASH_EXT] = {
 		.oid = SOC_AP_FW_HASH_OID,
@@ -123,7 +127,7 @@
 		.ln = "Trusted OS Firmware content certificate public key",
 		.asn1_type = V_ASN1_OCTET_STRING,
 		.type = EXT_TYPE_PKEY,
-		.data.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
+		.attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
 	},
 	[TRUSTED_OS_FW_HASH_EXT] = {
 		.oid = TRUSTED_OS_FW_HASH_OID,
@@ -140,7 +144,7 @@
 		.ln = "Non-Trusted Firmware content certificate public key",
 		.asn1_type = V_ASN1_OCTET_STRING,
 		.type = EXT_TYPE_PKEY,
-		.data.key = NON_TRUSTED_FW_CONTENT_CERT_KEY
+		.attr.key = NON_TRUSTED_FW_CONTENT_CERT_KEY
 	},
 	[NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = {
 		.oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID,
diff --git a/tools/fip_create/Makefile b/tools/fip_create/Makefile
index c72bae5..2e367c2 100644
--- a/tools/fip_create/Makefile
+++ b/tools/fip_create/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -28,38 +28,56 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-PROJECT = fip_create
-OBJECTS = fip_create.o
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
 
-CFLAGS = -Wall -Werror -pedantic -std=c99
+PROJECT := fip_create${BIN_EXT}
+OBJECTS := fip_create.o
+COPIED_H_FILES := uuid.h firmware_image_package.h
+
+CFLAGS := -Wall -Werror -pedantic -std=c99
 ifeq (${DEBUG},1)
   CFLAGS += -g -O0 -DDEBUG
 else
   CFLAGS += -O2
 endif
 
-# Make soft links and include from local directory otherwise wrong headers
-# could get pulled in from firmware tree.
-INCLUDE_PATHS = -I.
+# Only include from local directory (see comment below).
+INCLUDE_PATHS := -I.
 
 CC := gcc
-RM := rm -rf
 
-.PHONY: all clean
+.PHONY: all clean distclean
 
 all: ${PROJECT}
 
 ${PROJECT}: ${OBJECTS} Makefile
 	@echo "  LD      $@"
 	${Q}${CC} ${OBJECTS} -o $@
-	@echo
+	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
-	@echo
+	@${ECHO_BLANK_LINE}
 
-%.o: %.c %.h Makefile
+%.o: %.c %.h ${COPIED_H_FILES} Makefile
 	@echo "  CC      $<"
 	${Q}${CC} -c ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
 
+#
+# Copy required library headers to a local directory so they can be included
+# by this project without adding the library directories to the system include
+# path. This avoids conflicts with definitions in the compiler standard
+# include path.
+#
+uuid.h : ../../include/stdlib/sys/uuid.h
+	$(call SHELL_COPY,$<,$@)
+
+firmware_image_package.h : ../../include/common/firmware_image_package.h
+	$(call SHELL_COPY,$<,$@)
+
 clean:
-	${Q}${RM} ${PROJECT}
-	${Q}${RM} ${OBJECTS}
+	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+
+distclean: clean
+	$(call SHELL_DELETE_ALL, ${COPIED_H_FILES})
+
diff --git a/tools/fip_create/fip_create.c b/tools/fip_create/fip_create.c
index 19afc74..7bce348 100644
--- a/tools/fip_create/fip_create.c
+++ b/tools/fip_create/fip_create.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -40,12 +40,19 @@
 
 /* Values returned by getopt() as part of the command line parsing */
 #define OPT_TOC_ENTRY 0
-#define OPT_DUMP 1
-#define OPT_HELP 2
+#define OPT_DUMP 'd'
+#define OPT_HELP 'h'
+#define OPT_UNPACK 'u'
+#define OPT_FORCE 'f'
+#define OPT_STR "dfhu"
 
-file_info_t files[MAX_FILES];
-unsigned file_info_count = 0;
-uuid_t uuid_null = {0};
+static file_info_t files[MAX_FILES];
+static unsigned file_info_count;
+static uuid_t uuid_null = {0};
+static int do_dump;
+static int do_pack;
+static int do_unpack;
+static int do_force;
 
 /*
  * TODO: Add ability to specify and flag different file types.
@@ -118,12 +125,15 @@
 {
 	entry_lookup_list_t *entry = toc_entry_lookup_list;
 
-	printf("Usage: fip_create [options] FIP_FILENAME\n\n");
-	printf("\tThis tool is used to create a Firmware Image Package.\n\n");
+	printf("\nThis tool is used to create a Firmware Image Package.\n\n");
+	printf("Usage:\n");
+	printf("\tfip_create [options] FIP_FILENAME\n\n");
 	printf("Options:\n");
-	printf("\t--help: Print this help message and exit\n");
-	printf("\t--dump: Print contents of FIP\n\n");
-	printf("\tComponents that can be added/updated:\n");
+	printf("\t-h,--help: Print this help message and exit\n");
+	printf("\t-d,--dump: Print contents of FIP after update\n");
+	printf("\t-u,--unpack: Unpack images from an existing FIP\n");
+	printf("\t-f,--force: Overwrite existing files when unpacking images\n\n");
+	printf("Components that can be added/updated:\n");
 	for (; entry->command_line_name != NULL; entry++) {
 		printf("\t--%s%s\t\t%s",
 		       entry->command_line_name,
@@ -131,6 +141,7 @@
 		       entry->name);
 		printf("\n");
 	}
+	printf("\n");
 }
 
 
@@ -371,6 +382,109 @@
 }
 
 
+/*
+ * Unpack all images from an existing FIP
+ *
+ * Images will be unpacked into the working directory using filenames as
+ * specified by the corresponding command line option plus the 'bin' extension.
+ * For example, the image specified by the --soc-fw option will be unpacked as
+ * 'soc-fw.bin'
+ */
+static int unpack_images(void)
+{
+	FILE *stream;
+	size_t bytes_written;
+	file_info_t *file_info;
+	char *filename[MAX_FILES];
+	int status, ret = 0;
+	unsigned int i, idx, num_img;
+	struct stat st;
+	size_t len;
+
+	/* Make the output filenames */
+	for (idx = 0; idx < file_info_count; idx++) {
+		filename[idx] = NULL;
+		file_info = &files[idx];
+		if (file_info->image_buffer == NULL) {
+			continue;
+		}
+		len = strlen(file_info->entry->command_line_name);
+		filename[idx] = malloc(len + 5); /* ".bin" + '\0' */
+		if (filename[idx] == NULL) {
+			printf("ERROR: out of memory\n");
+			for (i = 0; i < idx; i++) {
+				free(filename[i]);
+			}
+			return ENOMEM;
+		}
+		strcpy(filename[idx], file_info->entry->command_line_name);
+		strcat(filename[idx], ".bin");
+	}
+
+
+	/* Check if output files already exist in the filesystem. We perform
+	 * this check before any other action, so if any of the files
+	 * exists, nothing is unpacked. If force overwrite is enabled, we skip
+	 * this check */
+	if (!do_force) {
+		for (idx = 0; idx < file_info_count; idx++) {
+			file_info = &files[idx];
+			if (file_info->image_buffer == NULL) {
+				continue;
+			}
+			status = stat(filename[idx], &st);
+			if (!status) {
+				printf("File '%s' exists. Use --force to overwrite.\n",
+				       filename[idx]);
+				printf("Process aborted.\n");
+				ret = EEXIST;
+				goto unpack_images_free;
+			}
+		}
+	}
+
+	printf("Unpacking images...\n");
+
+	/* Write the images to files */
+	num_img = 0;
+	for (idx = 0; idx < file_info_count; idx++) {
+		file_info = &files[idx];
+		if (file_info->image_buffer == NULL) {
+			continue;
+		}
+		/* Unpack the image to a file */
+		stream = fopen(filename[idx], "w");
+		if (!stream) {
+			printf("ERROR: cannot open '%s' for writing\n",
+			       filename[idx]);
+			ret = EIO;
+			goto unpack_images_free;
+		}
+		bytes_written = fwrite(file_info->image_buffer, sizeof(uint8_t),
+				       file_info->size, stream);
+		fclose(stream);
+
+		if (bytes_written != file_info->size) {
+			printf("ERROR: Incorrect write for file \"%s\": Size=%u,"
+			       "Written=%lu bytes.\n", filename[idx], file_info->size,
+			       bytes_written);
+			ret = EIO;
+			goto unpack_images_free;
+		}
+		num_img++;
+	}
+
+	printf("Done. %u images unpacked\n", num_img);
+
+unpack_images_free:
+	for (idx = 0; idx < file_info_count; idx++) {
+		free(filename[idx]);
+	}
+
+	return ret;
+}
+
+
 static void dump_toc(void)
 {
 	unsigned int index = 0;
@@ -528,7 +642,7 @@
 	 */
 	optind = 1;
 	while (1) {
-		c = getopt_long(argc, argv, "", options, NULL);
+		c = getopt_long(argc, argv, OPT_STR, options, NULL);
 		if (c == -1)
 			break;
 
@@ -549,19 +663,17 @@
 
 
 /* Work through command-line options */
-static int parse_cmdline(int argc, char **argv, struct option *options,
-			 int *do_pack)
+static int parse_cmdline(int argc, char **argv, struct option *options)
 {
 	int c;
 	int status = 0;
 	int option_index = 0;
 	entry_lookup_list_t *lookup_entry;
-	int do_dump = 0;
 
 	/* restart parse to process all options. starts at 1. */
 	optind = 1;
 	while (1) {
-		c = getopt_long(argc, argv, "", options, &option_index);
+		c = getopt_long(argc, argv, OPT_STR, options, &option_index);
 		if (c == -1)
 			break;
 
@@ -578,7 +690,7 @@
 						return status;
 					} else {
 						/* Update package */
-						*do_pack = 1;
+						do_pack = 1;
 					}
 				}
 			}
@@ -586,24 +698,26 @@
 
 		case OPT_DUMP:
 			do_dump = 1;
-			continue;
+			break;
 
 		case OPT_HELP:
 			print_usage();
 			exit(0);
 
+		case OPT_UNPACK:
+			do_unpack = 1;
+			break;
+
+		case OPT_FORCE:
+			do_force = 1;
+			break;
+
 		default:
 			/* Unrecognised options are caught in get_filename() */
 			break;
 		}
 	}
 
-
-	/* Do not dump toc if we have an error as it could hide the error */
-	if ((status == 0) && (do_dump)) {
-		dump_toc();
-	}
-
 	return status;
 
 }
@@ -613,17 +727,17 @@
 	int i;
 	int status;
 	char *fip_filename;
-	int do_pack = 0;
+	struct stat st;
 
 	/* Clear file list table. */
 	memset(files, 0, sizeof(files));
 
 	/* Initialise for getopt_long().
 	 * Use image table as defined at top of file to get options.
-	 * Add 'dump' option, 'help' option and end marker.
+	 * Add common options and end marker.
 	 */
 	static struct option long_options[(sizeof(toc_entry_lookup_list)/
-					   sizeof(entry_lookup_list_t)) + 2];
+					   sizeof(entry_lookup_list_t)) + 4];
 
 	for (i = 0;
 	     /* -1 because we dont want to process end marker in toc table */
@@ -648,6 +762,18 @@
 	long_options[i].flag = 0;
 	long_options[i].val = OPT_HELP;
 
+	/* Add '--unpack' option */
+	long_options[++i].name = "unpack";
+	long_options[i].has_arg = 0;
+	long_options[i].flag = 0;
+	long_options[i].val = OPT_UNPACK;
+
+	/* Add '--force' option */
+	long_options[++i].name = "force";
+	long_options[i].has_arg = 0;
+	long_options[i].flag = 0;
+	long_options[i].val = OPT_FORCE;
+
 	/* Zero the last entry (required) */
 	long_options[++i].name = 0;
 	long_options[i].has_arg = 0;
@@ -677,7 +803,7 @@
 	}
 
 	/* Work through provided program arguments and perform actions */
-	status = parse_cmdline(argc, argv, long_options, &do_pack);
+	status = parse_cmdline(argc, argv, long_options);
 	if (status != 0) {
 		return status;
 	};
@@ -688,10 +814,28 @@
 		return 0;
 	}
 
-	/* Processed all command line options. Create/update the package if
-	 * required.
-	 */
-	if (do_pack) {
+	/* Unpack images from FIP always takes precedence over packaging. In
+	 * the future, there will be different commands for each action and
+	 * only one will be specified in the command line */
+	if (do_unpack) {
+		status = stat(fip_filename, &st);
+		if (status != 0) {
+			printf("ERROR: cannot open %s\n", fip_filename);
+			return status;
+		}
+		/* Warning if user has specified images */
+		if (do_pack) {
+			printf("WARNING: Unpack option specified. Input images "
+			       "will be ignored.\n");
+		}
+		status = unpack_images();
+		if (status != 0) {
+			printf("ERROR: failed to unpack package (status = %d).\n",
+			       status);
+			return status;
+		}
+	} else if (do_pack) {
+		/* Create/update FIP */
 		status = pack_images(fip_filename);
 		if (status != 0) {
 			printf("Failed to create package (status = %d).\n",
@@ -699,5 +843,10 @@
 		}
 	}
 
+	/* Do not dump toc if we have an error as it could hide the error */
+	if ((status == 0) && (do_dump)) {
+		dump_toc();
+	}
+
 	return status;
 }
diff --git a/tools/fip_create/firmware_image_package.h b/tools/fip_create/firmware_image_package.h
deleted file mode 120000
index cc61903..0000000
--- a/tools/fip_create/firmware_image_package.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/common/firmware_image_package.h
\ No newline at end of file
diff --git a/tools/fip_create/uuid.h b/tools/fip_create/uuid.h
deleted file mode 120000
index c77762f..0000000
--- a/tools/fip_create/uuid.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/stdlib/sys/uuid.h
\ No newline at end of file