Merge "TF-A GICv3 driver: Separate GICD and GICR accessor functions" into integration
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index b20859b..e65ab90 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -148,15 +149,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index c1338e2..d08b046 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -6,6 +6,7 @@
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -125,15 +126,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index b6570ee..a72818c 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -188,15 +189,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index 8d257ce..96545a3 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -102,15 +103,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 4a1c5f3..e0138ac 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -6,6 +6,7 @@
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -287,15 +288,7 @@
         __BSS_END__ = .;
     } >NOBITS
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >NOBITS
+    XLAT_TABLE_SECTION >NOBITS
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 6997a7f..3b1ca1b 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(elf32-littlearm)
@@ -196,15 +197,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
      __BSS_SIZE__ = SIZEOF(.bss);
 
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index 592e245..da60c63 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <platform_def.h>
 
@@ -125,15 +126,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/docs/design_documents/cmake_framework.rst b/docs/design_documents/cmake_framework.rst
new file mode 100644
index 0000000..d88942e
--- /dev/null
+++ b/docs/design_documents/cmake_framework.rst
@@ -0,0 +1,165 @@
+TF-A CMake buildsystem
+======================
+
+:Author: Balint Dobszay
+:Organization: Arm Limited
+:Contact: Balint Dobszay <balint.dobszay@arm.com>
+:Status: Accepted
+
+.. contents:: Table of Contents
+
+Abstract
+--------
+This document presents a proposal for a new buildsystem for TF-A using CMake,
+and as part of this a reusable CMake framework for embedded projects. For a
+summary about the proposal, please see the `Phabricator wiki page
+<https://developer.trustedfirmware.org/w/tf_a/cmake-buildsystem-proposal/>`_. As
+mentioned there, the proposal consists of two phases. The subject of this
+document is the first phase only.
+
+Introduction
+------------
+The current Makefile based buildsystem of TF-A has become complicated and hard
+to maintain, there is a need for a new, more flexible solution. The proposal is
+to use CMake language for the new buildsystem. The main reasons of this decision
+are the following:
+
+* It is a well-established, mature tool, widely accepted by open-source
+  projects.
+* TF-M is already using CMake, reducing fragmentation for tf.org projects can be
+  beneficial.
+* CMake has various advantages over Make, e.g.:
+
+  * Host and target system agnostic project.
+  * CMake project is scalable, supports project modularization.
+  * Supports software integration.
+  * Out-of-the-box support for integration with several tools (e.g. project
+    generation for various IDEs, integration with cppcheck, etc).
+
+Of course there are drawbacks too:
+
+* Language is problematic (e.g. variable scope).
+* Not embedded approach.
+
+To overcome these and other problems, we need to create workarounds for some
+tasks, wrap CMake functions, etc. Since this functionality can be useful in
+other embedded projects too, it is beneficial to collect the new code into a
+reusable framework and store this in a separate repository. The following
+diagram provides an overview of the framework structure:
+
+|Framework structure|
+
+Main features
+-------------
+
+Structured configuration description
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+In the current Makefile system the build configuration description, validation,
+processing, and the target creation, source file description are mixed and
+spread across several files. One of the goals of the framework is to organize
+this.
+
+The framework provides a solution to describe the input build parameters, flags,
+macros, etc. in a structured way. It contains two utilities for this purpose:
+
+* Map: simple key-value pair implementation.
+* Group: collection of related maps.
+
+The related parameters shall be packed into a group (or "setting group"). The
+setting groups shall be defined and filled with content in config files.
+Currently the config files are created and edited manually, but later a
+configuration management tool (e.g. Kconfig) shall be used to generate these
+files. Therefore, the framework does not contain parameter validation and
+conflict checking, these shall be handled by the configuration tool.
+
+Target description
+^^^^^^^^^^^^^^^^^^
+The framework provides an API called STGT ('simple target') to describe the
+targets, i.e. what is the build output, what source files are used, what
+libraries are linked, etc. The API wraps the CMake target functions, and also
+extends the built-in functionality, it can use the setting groups described in
+the previous section. A group can be applied onto a target, i.e. a collection of
+macros, flags, etc. can be applied onto the given output executable/library.
+This provides a more granular way than the current Makefile system where most of
+these are global and applied onto each target.
+
+Compiler abstraction
+^^^^^^^^^^^^^^^^^^^^
+Apart from the built-in CMake usage of the compiler, there are some common tasks
+that CMake does not solve (e.g. preprocessing a file). For these tasks the
+framework uses wrapper functions instead of direct calls to the compiler. This
+way it is not tied to one specific compiler.
+
+External tools
+^^^^^^^^^^^^^^
+In the TF-A buildsystem some external tools are used, e.g. fiptool for image
+generation or dtc for device tree compilation. These tools have to be found
+and/or built by the framework. For this, the CMake find_package functionality is
+used, any other necessary tools can be added later.
+
+Workflow
+--------
+The following diagram demonstrates the development workflow using the framework:
+
+|Framework workflow|
+
+The process can be split into two main phases:
+
+In the provisioning phase, first we have to obtain the necessary resources, i.e.
+clone the code repository and other dependencies. Next we have to do the
+configuration, preferably using a config tool like KConfig.
+
+In the development phase first we run CMake, which will generate the buildsystem
+using the selected generator backend (currently only the Makefile generator is
+supported). After this we run the selected build tool which in turn calls the
+compiler, linker, packaging tool, etc. Finally we can run and debug the output
+executables.
+
+Usually during development only the steps in this second phase have to be
+repeated, while the provisioning phase needs to be done only once (or rarely).
+
+Example
+-------
+This is a short example for the basic framework usage.
+
+First, we create a setting group called *mem_conf* and fill it with several
+parameters. It is worth noting the difference between *CONFIG* and *DEFINE*
+types: the former is only a CMake domain option, the latter is only a C language
+macro.
+
+Next, we create a target called *fw1* and add the *mem_conf* setting group to
+it. This means that all source and header files used by the target will have all
+the parameters declared in the setting group. Then we set the target type to
+executable, and add some source files. Since the target has the parameters from
+the settings group, we can use it for conditionally adding source files. E.g.
+*dram_controller.c* will only be added if MEM_TYPE equals dram.
+
+.. code-block:: cmake
+
+   group_new(NAME mem_conf)
+   group_add(NAME mem_conf TYPE DEFINE KEY MEM_SIZE VAL 1024)
+   group_add(NAME mem_conf TYPE CONFIG DEFINE KEY MEM_TYPE VAL dram)
+   group_add(NAME mem_conf TYPE CFLAG KEY -Os)
+
+   stgt_create(NAME fw1)
+   stgt_add_setting(NAME fw1 GROUPS mem_conf)
+   stgt_set_target(NAME fw1 TYPE exe)
+
+   stgt_add_src(NAME fw1 SRC
+       ${CMAKE_SOURCE_DIR}/main.c
+   )
+
+   stgt_add_src_cond(NAME fw1 KEY MEM_TYPE VAL dram SRC
+       ${CMAKE_SOURCE_DIR}/dram_controller.c
+   )
+
+.. |Framework structure| image::
+   ../resources/diagrams/cmake_framework_structure.png
+   :width: 75 %
+
+.. |Framework workflow| image::
+   ../resources/diagrams/cmake_framework_workflow.png
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design_documents/index.rst b/docs/design_documents/index.rst
new file mode 100644
index 0000000..187510a
--- /dev/null
+++ b/docs/design_documents/index.rst
@@ -0,0 +1,13 @@
+Design Documents
+================
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Contents
+   :numbered:
+
+   cmake_framework
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index 3e0c8ff..13e25cd 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -60,7 +60,7 @@
 
 The following libraries are required for Trusted Board Boot support:
 
-- mbed TLS == 2.16.2 (tag: ``mbedtls-2.16.2``)
+- mbed TLS == 2.18.0 (tag: ``mbedtls-2.18.0``)
 
 These tools are optional:
 
diff --git a/docs/index.rst b/docs/index.rst
index 5088bfd..7413edd 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,6 +14,7 @@
    plat/index
    perf/index
    security_advisories/index
+   design_documents/index
    change-log
    change-log-upcoming
    glossary
@@ -82,7 +83,7 @@
 
 --------------
 
-*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile
 .. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php
diff --git a/docs/resources/diagrams/cmake_framework_structure.png b/docs/resources/diagrams/cmake_framework_structure.png
new file mode 100644
index 0000000..6006f1c
--- /dev/null
+++ b/docs/resources/diagrams/cmake_framework_structure.png
Binary files differ
diff --git a/docs/resources/diagrams/cmake_framework_workflow.png b/docs/resources/diagrams/cmake_framework_workflow.png
new file mode 100644
index 0000000..7311529
--- /dev/null
+++ b/docs/resources/diagrams/cmake_framework_workflow.png
Binary files differ
diff --git a/drivers/auth/cryptocell/712/cryptocell_crypto.c b/drivers/auth/cryptocell/712/cryptocell_crypto.c
index cf43175..c7ee36f 100644
--- a/drivers/auth/cryptocell/712/cryptocell_crypto.c
+++ b/drivers/auth/cryptocell/712/cryptocell_crypto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,7 @@
 #include <lib/utils.h>
 
 #include <mbedtls/oid.h>
+#include <mbedtls/x509.h>
 
 #define LIB_NAME		"CryptoCell 712 SBROM"
 #define RSA_SALT_LEN		32
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
new file mode 100644
index 0000000..eb0b020
--- /dev/null
+++ b/drivers/auth/dualroot/cot.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <platform_def.h>
+
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <drivers/auth/auth_mod.h>
+#include <tools_share/dualroot_oid.h>
+
+/*
+ * TODO: Remove dependency on mbedTLS. The chain of trust should be agnostic of
+ * the specific cryptographic library in use.
+*/
+/*
+ * Maximum key and hash sizes (in DER format).
+ *
+ * Both RSA and ECDSA keys may be used at the same time. In this case, the key
+ * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA
+ * ones for all key sizes we support, they impose the minimum size of these
+ * buffers.
+ */
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE == 1024
+#define PK_DER_LEN			162
+#elif TF_MBEDTLS_KEY_SIZE == 2048
+#define PK_DER_LEN			294
+#elif TF_MBEDTLS_KEY_SIZE == 3072
+#define PK_DER_LEN			422
+#elif TF_MBEDTLS_KEY_SIZE == 4096
+#define PK_DER_LEN			550
+#else
+#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
+#endif
+#else /* Only using ECDSA keys. */
+#define PK_DER_LEN			91
+#endif
+
+#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
+#define HASH_DER_LEN			51
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384
+#define HASH_DER_LEN			67
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512
+#define HASH_DER_LEN			83
+#else
+#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID"
+#endif
+
+/*
+ * Allocate static buffers to store the authentication parameters extracted from
+ * the certificates.
+ */
+static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char hw_config_hash_buf[HASH_DER_LEN];
+static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
+static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+#ifdef IMAGE_BL2
+static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
+static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
+
+static unsigned char trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char content_pk_buf[PK_DER_LEN];
+#endif
+
+/*
+ * 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 subject_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
+#ifdef IMAGE_BL1
+static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, FWU_HASH_OID);
+#endif /* IMAGE_BL1 */
+
+#ifdef IMAGE_BL2
+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 trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, PROT_PK_OID);
+
+static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SCP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
+static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
+static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
+static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+#endif /* IMAGE_BL2 */
+
+
+/* BL2 */
+static const auth_img_desc_t trusted_boot_fw_cert = {
+	.img_id = TRUSTED_BOOT_FW_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tb_fw_hash,
+			.data = {
+				.ptr = (void *)tb_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &tb_fw_config_hash,
+			.data = {
+				.ptr = (void *)tb_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &hw_config_hash,
+			.data = {
+				.ptr = (void *)hw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+#ifdef IMAGE_BL1
+static const auth_img_desc_t bl2_image = {
+	.img_id = BL2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tb_fw_hash
+			}
+		}
+	}
+};
+#endif /* IMAGE_BL1 */
+
+/* HW Config */
+static const auth_img_desc_t hw_config = {
+	.img_id = HW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &hw_config_hash
+			}
+		}
+	}
+};
+
+/* TB FW Config */
+#ifdef IMAGE_BL1
+static const auth_img_desc_t tb_fw_config = {
+	.img_id = TB_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tb_fw_config_hash
+			}
+		}
+	}
+};
+#endif /* IMAGE_BL1 */
+
+#ifdef IMAGE_BL2
+/* Trusted key certificate */
+static const auth_img_desc_t trusted_key_cert = {
+	.img_id = TRUSTED_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &trusted_world_pk,
+			.data = {
+				.ptr = (void *)trusted_world_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		},
+	}
+};
+
+/* SCP Firmware */
+static const auth_img_desc_t scp_fw_key_cert = {
+	.img_id = SCP_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t scp_fw_content_cert = {
+	.img_id = SCP_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &scp_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &scp_fw_content_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_fw_hash,
+			.data = {
+				.ptr = (void *)scp_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t scp_bl2_image = {
+	.img_id = SCP_BL2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &scp_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &scp_fw_hash
+			}
+		}
+	}
+};
+
+/* SoC Firmware */
+static const auth_img_desc_t soc_fw_key_cert = {
+	.img_id = SOC_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &soc_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t soc_fw_content_cert = {
+	.img_id = SOC_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &soc_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &soc_fw_content_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &soc_fw_hash,
+			.data = {
+				.ptr = (void *)soc_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &soc_fw_config_hash,
+			.data = {
+				.ptr = (void *)soc_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl31_image = {
+	.img_id = BL31_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &soc_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &soc_fw_hash
+			}
+		}
+	}
+};
+
+/* SOC FW Config */
+static const auth_img_desc_t soc_fw_config = {
+	.img_id = SOC_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &soc_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &soc_fw_config_hash
+			}
+		}
+	}
+};
+
+/* Trusted OS Firmware */
+static const auth_img_desc_t trusted_os_fw_key_cert = {
+	.img_id = TRUSTED_OS_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tos_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t trusted_os_fw_content_cert = {
+	.img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_os_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &tos_fw_content_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tos_fw_hash,
+			.data = {
+				.ptr = (void *)tos_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &tos_fw_extra1_hash,
+			.data = {
+				.ptr = (void *)tos_fw_extra1_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &tos_fw_extra2_hash,
+			.data = {
+				.ptr = (void *)tos_fw_extra2_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[3] = {
+			.type_desc = &tos_fw_config_hash,
+			.data = {
+				.ptr = (void *)tos_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl32_image = {
+	.img_id = BL32_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_hash
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl32_extra1_image = {
+	.img_id = BL32_EXTRA1_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_extra1_hash
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl32_extra2_image = {
+	.img_id = BL32_EXTRA2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_extra2_hash
+			}
+		}
+	}
+};
+
+/* TOS FW Config */
+static const auth_img_desc_t tos_fw_config = {
+	.img_id = TOS_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_config_hash
+			}
+		}
+	}
+};
+
+/* Non-Trusted Firmware */
+static const auth_img_desc_t non_trusted_fw_content_cert = {
+	.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL, /* Root certificate.  */
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &prot_pk,
+				.sig = &sig,
+				.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 = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &nt_world_bl_hash,
+			.data = {
+				.ptr = (void *)nt_world_bl_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &nt_fw_config_hash,
+			.data = {
+				.ptr = (void *)nt_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl33_image = {
+	.img_id = BL33_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &non_trusted_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &nt_world_bl_hash
+			}
+		}
+	}
+};
+
+/* NT FW Config */
+static const auth_img_desc_t nt_fw_config = {
+	.img_id = NT_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &non_trusted_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &nt_fw_config_hash
+			}
+		}
+	}
+};
+
+#else  /* IMAGE_BL2 */
+
+/* FWU auth descriptor */
+static const auth_img_desc_t fwu_cert = {
+	.img_id = FWU_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_bl2u_hash,
+			.data = {
+				.ptr = (void *)scp_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &bl2u_hash,
+			.data = {
+				.ptr = (void *)tb_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &ns_bl2u_hash,
+			.data = {
+				.ptr = (void *)nt_world_bl_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+/* SCP_BL2U */
+static const auth_img_desc_t scp_bl2u_image = {
+	.img_id = SCP_BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &scp_bl2u_hash
+			}
+		}
+	}
+};
+
+/* BL2U */
+static const auth_img_desc_t bl2u_image = {
+	.img_id = BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &bl2u_hash
+			}
+		}
+	}
+};
+
+/* NS_BL2U */
+static const auth_img_desc_t ns_bl2u_image = {
+	.img_id = NS_BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &ns_bl2u_hash
+			}
+		}
+	}
+};
+#endif /* IMAGE_BL2 */
+
+/*
+ * Chain of trust definition
+ */
+#ifdef IMAGE_BL1
+static const auth_img_desc_t * const cot_desc[] = {
+	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
+	[BL2_IMAGE_ID]				=	&bl2_image,
+	[HW_CONFIG_ID]				=	&hw_config,
+	[TB_FW_CONFIG_ID]			=	&tb_fw_config,
+	[FWU_CERT_ID]				=	&fwu_cert,
+	[SCP_BL2U_IMAGE_ID]			=	&scp_bl2u_image,
+	[BL2U_IMAGE_ID]				=	&bl2u_image,
+	[NS_BL2U_IMAGE_ID]			=	&ns_bl2u_image
+};
+#else /* IMAGE_BL2 */
+static const auth_img_desc_t * const cot_desc[] = {
+	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
+	[HW_CONFIG_ID]				=	&hw_config,
+	[TRUSTED_KEY_CERT_ID]			=	&trusted_key_cert,
+	[SCP_FW_KEY_CERT_ID]			=	&scp_fw_key_cert,
+	[SCP_FW_CONTENT_CERT_ID]		=	&scp_fw_content_cert,
+	[SCP_BL2_IMAGE_ID]			=	&scp_bl2_image,
+	[SOC_FW_KEY_CERT_ID]			=	&soc_fw_key_cert,
+	[SOC_FW_CONTENT_CERT_ID]		=	&soc_fw_content_cert,
+	[BL31_IMAGE_ID]				=	&bl31_image,
+	[SOC_FW_CONFIG_ID]			=	&soc_fw_config,
+	[TRUSTED_OS_FW_KEY_CERT_ID]		=	&trusted_os_fw_key_cert,
+	[TRUSTED_OS_FW_CONTENT_CERT_ID]		=	&trusted_os_fw_content_cert,
+	[BL32_IMAGE_ID]				=	&bl32_image,
+	[BL32_EXTRA1_IMAGE_ID]			=	&bl32_extra1_image,
+	[BL32_EXTRA2_IMAGE_ID]			=	&bl32_extra2_image,
+	[TOS_FW_CONFIG_ID]			=	&tos_fw_config,
+	[NON_TRUSTED_FW_CONTENT_CERT_ID]	=	&non_trusted_fw_content_cert,
+	[BL33_IMAGE_ID]				=	&bl33_image,
+	[NT_FW_CONFIG_ID]			=	&nt_fw_config,
+};
+#endif
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c
index 2a98014..6d6efb5 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.c
+++ b/drivers/auth/mbedtls/mbedtls_crypto.c
@@ -14,6 +14,7 @@
 #include <mbedtls/memory_buffer_alloc.h>
 #include <mbedtls/oid.h>
 #include <mbedtls/platform.h>
+#include <mbedtls/x509.h>
 
 #include <common/debug.h>
 #include <drivers/auth/crypto_mod.h>
diff --git a/include/common/bl_common.ld.h b/include/common/bl_common.ld.h
new file mode 100644
index 0000000..32c54b4
--- /dev/null
+++ b/include/common/bl_common.ld.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL_COMMON_LD_H
+#define BL_COMMON_LD_H
+
+/*
+ * The xlat_table section is for full, aligned page tables (4K).
+ * Removing them from .bss avoids forcing 4K alignment on
+ * the .bss section. The tables are initialized to zero by the translation
+ * tables library.
+ */
+#define XLAT_TABLE_SECTION				\
+	xlat_table (NOLOAD) : {				\
+		*(xlat_table)				\
+	}
+
+#endif /* BL_COMMON_LD_H */
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index a80fab0..ab311f4 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -164,14 +164,20 @@
  *   Would typically be PLAT_VIRT_ADDR_SPACE_SIZE
  *   (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the
  *   BL image currently executing.
+
+ * _base_table_section:
+ *   Specify the name of the section where the base translation tables have to
+ *   be placed by the linker.
  */
 #define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \
-			_virt_addr_space_size, _phy_addr_space_size)	\
+			      _virt_addr_space_size, _phy_addr_space_size, \
+			      _base_table_section)			\
 	REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count),	\
 					 (_xlat_tables_count),		\
 					 (_virt_addr_space_size),	\
 					 (_phy_addr_space_size),	\
-					 EL_REGIME_INVALID, "xlat_table")
+					 EL_REGIME_INVALID,		\
+					 "xlat_table", (_base_table_section))
 
 /*
  * Same as REGISTER_XLAT_CONTEXT plus the additional parameters:
@@ -191,7 +197,9 @@
 					 (_xlat_tables_count),		\
 					 (_virt_addr_space_size),	\
 					 (_phy_addr_space_size),	\
-					 (_xlat_regime), (_section_name))
+					 (_xlat_regime),		\
+					 (_section_name), ".bss"	\
+)
 
 /******************************************************************************
  * Generic translation table APIs.
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index c88fa4d..62f853d 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -24,6 +24,7 @@
 #include <platform_def.h>
 
 #include <lib/cassert.h>
+#include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_arch.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
@@ -135,7 +136,8 @@
 
 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,		\
 			_xlat_tables_count, _virt_addr_space_size,	\
-			_phy_addr_space_size, _xlat_regime, _section_name)\
+			_phy_addr_space_size, _xlat_regime,		\
+			_table_section, _base_table_section)		\
 	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
 		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
 									\
@@ -143,52 +145,13 @@
 									\
 	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]	\
 		[XLAT_TABLE_ENTRIES]					\
-		__aligned(XLAT_TABLE_SIZE) __section(_section_name);	\
-									\
-	static uint64_t _ctx_name##_base_xlat_table			\
-		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]	\
-		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
-			* sizeof(uint64_t));				\
-									\
-	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
-									\
-	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
-		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
-		.va_max_address = (_virt_addr_space_size) - 1UL,	\
-		.mmap = _ctx_name##_mmap,				\
-		.mmap_num = (_mmap_count),				\
-		.tables = _ctx_name##_xlat_tables,			\
-		.tables_num = _xlat_tables_count,			\
-		 XLAT_CTX_INIT_TABLE_ATTR()				\
-		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
-		.next_table = 0,					\
-		.base_table = _ctx_name##_base_xlat_table,		\
-		.base_table_entries =					\
-			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
-		.max_pa = 0U,						\
-		.max_va = 0U,						\
-		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
-		.initialized = false,					\
-		.xlat_regime = (_xlat_regime)				\
-	}
-
-#define REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(_ctx_name, _mmap_count,	\
-			_xlat_tables_count, _virt_addr_space_size,	\
-			_phy_addr_space_size, _xlat_regime, _section_name)\
-	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
-		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
-									\
-	static mmap_region_t _ctx_name##_mmap[_mmap_count + 1];		\
-									\
-	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]	\
-		[XLAT_TABLE_ENTRIES]					\
-		__aligned(XLAT_TABLE_SIZE) __section(_section_name);	\
+		__aligned(XLAT_TABLE_SIZE) __section(_table_section);	\
 									\
 	static uint64_t _ctx_name##_base_xlat_table			\
 		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]	\
 		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
 			* sizeof(uint64_t))				\
-		__section(".rodata");					\
+		__section(_base_table_section);				\
 									\
 	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
 									\
@@ -198,13 +161,13 @@
 		.mmap = _ctx_name##_mmap,				\
 		.mmap_num = (_mmap_count),				\
 		.tables = _ctx_name##_xlat_tables,			\
-		.tables_num = _xlat_tables_count,			\
+		.tables_num = ARRAY_SIZE(_ctx_name##_xlat_tables),	\
 		 XLAT_CTX_INIT_TABLE_ATTR()				\
 		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
 		.next_table = 0,					\
 		.base_table = _ctx_name##_base_xlat_table,		\
 		.base_table_entries =					\
-			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
+			ARRAY_SIZE(_ctx_name##_base_xlat_table),	\
 		.max_pa = 0U,						\
 		.max_va = 0U,						\
 		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index ff1b979..babde41 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -268,7 +268,7 @@
  * Optional functions in ARM standard platforms
  */
 void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames);
-int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
+int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 	unsigned int *flags);
 int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
 	unsigned int *flags);
diff --git a/include/tools_share/dualroot_oid.h b/include/tools_share/dualroot_oid.h
new file mode 100644
index 0000000..3e88a6d
--- /dev/null
+++ b/include/tools_share/dualroot_oid.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUALROOT_OID_H
+#define DUALROOT_OID_H
+
+/* Reuse the Object IDs defined by TBBR for certificate extensions. */
+#include "tbbr_oid.h"
+
+/*
+ * Platform root-of-trust public key.
+ * Arbitrary value that does not conflict with any of the TBBR reserved OIDs.
+ */
+#define PROT_PK_OID				"1.3.6.1.4.1.4128.2100.1102"
+
+#endif /* DUALROOT_OID_H */
diff --git a/lib/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c
index adca578..a1c974e 100644
--- a/lib/xlat_tables_v2/xlat_tables_context.c
+++ b/lib/xlat_tables_v2/xlat_tables_context.c
@@ -26,14 +26,15 @@
  * currently executing.
  */
 #if PLAT_RO_XLAT_TABLES
-REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
-		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
-		EL_REGIME_INVALID, "xlat_table");
+#define BASE_XLAT_TABLE_SECTION		".rodata"
 #else
-REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
-		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
+#define BASE_XLAT_TABLE_SECTION		".bss"
 #endif
 
+REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
+		      PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
+		      BASE_XLAT_TABLE_SECTION);
+
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
 		     unsigned int attr)
 {
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 9c47cc7..f0adfe1 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -23,6 +23,7 @@
 #   KEY_ALG
 #   KEY_SIZE
 #   ROT_KEY
+#   PROT_KEY
 #   TRUSTED_WORLD_KEY
 #   NON_TRUSTED_WORLD_KEY
 #   SCP_BL2_KEY
@@ -57,6 +58,7 @@
 $(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg)))
 $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key)))
 $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_)))
+$(if ${PROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${PROT_KEY},--prot-key)))
 $(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key)))
 $(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key)))
 
@@ -93,5 +95,7 @@
 ifneq (${BL33},)
     $(if ${BL33_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL33_KEY},--nt-fw-key)))
     $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_content.crt,--nt-fw-cert))
+ifneq (${COT},dualroot)
     $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_key.crt,--nt-fw-key-cert))
 endif
+endif
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index 3c19230..38cbba9 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -16,8 +16,12 @@
 #include <plat/common/common_def.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
-#include <tools_share/tbbr_oid.h>
 
+#if defined(ARM_COT_tbbr)
+#include <tools_share/tbbr_oid.h>
+#elif defined(ARM_COT_dualroot)
+#include <tools_share/dualroot_oid.h>
+#endif
 
 #if !ARM_CRYPTOCELL_INTEG
 #if !ARM_ROTPK_LOCATION_ID
@@ -108,10 +112,10 @@
 #endif
 
 /*
- * Wraper function for most Arm platforms to get ROTPK hash.
+ * Wrapper function for most Arm platforms to get ROTPK hash.
  */
-int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
-			unsigned int *flags)
+static int get_rotpk_info(void **key_ptr, unsigned int *key_len,
+				unsigned int *flags)
 {
 #if ARM_CRYPTOCELL_INTEG
 	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
@@ -125,10 +129,44 @@
 #else
 	return 1;
 #endif
-
 #endif /* ARM_CRYPTOCELL_INTEG */
 }
 
+#if defined(ARM_COT_tbbr)
+
+int arm_get_rotpk_info(void *cookie __unused, void **key_ptr,
+		       unsigned int *key_len, unsigned int *flags)
+{
+	return get_rotpk_info(key_ptr, key_len, flags);
+}
+
+#elif defined(ARM_COT_dualroot)
+
+int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+		       unsigned int *flags)
+{
+	/*
+	 * Return the right root of trust key hash based on the cookie value:
+	 *  - NULL means the primary ROTPK.
+	 *  - Otherwise, interpret cookie as the OID of the certificate
+	 *    extension containing the key.
+	 */
+	if (cookie == NULL) {
+		return get_rotpk_info(key_ptr, key_len, flags);
+	} else if (strcmp(cookie, PROT_PK_OID) == 0) {
+		extern unsigned char arm_protpk_hash[];
+		extern unsigned char arm_protpk_hash_end[];
+		*key_ptr = arm_protpk_hash;
+		*key_len = arm_protpk_hash_end - arm_protpk_hash;
+		*flags = ROTPK_IS_HASH;
+		return 0;
+	} else {
+		/* Invalid key ID. */
+		return 1;
+	}
+}
+#endif
+
 /*
  * Return the non-volatile counter value stored in the platform. The cookie
  * will contain the OID of the counter in the certificate.
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 459156b..1885a60 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -68,4 +68,25 @@
 BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c \
 				plat/arm/board/common/rotpk/arm_dev_rotpk.S
 
+# Allows platform code to provide implementation variants depending on the
+# selected chain of trust.
+$(eval $(call add_define,ARM_COT_${COT}))
+
+ifeq (${COT},dualroot)
+# Platform Root of Trust key files.
+ARM_PROT_KEY		:=	plat/arm/board/common/protpk/arm_protprivk_rsa.pem
+ARM_PROTPK_HASH		:=	plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
+
+# Provide the private key to cert_create tool. It needs it to sign the images.
+PROT_KEY		:=	${ARM_PROT_KEY}
+
+$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"'))
+
+BL1_SOURCES		+=	plat/arm/board/common/protpk/arm_dev_protpk.S
+BL2_SOURCES		+=	plat/arm/board/common/protpk/arm_dev_protpk.S
+
+$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+endif
+
 endif
diff --git a/plat/arm/board/common/protpk/README b/plat/arm/board/common/protpk/README
new file mode 100644
index 0000000..3aca180
--- /dev/null
+++ b/plat/arm/board/common/protpk/README
@@ -0,0 +1,14 @@
+This directory contains some development keys to be used as the platform
+root-of-trust key.
+
+* arm_protprivk_rsa.pem is a 2K RSA private key in PEM format. It has been
+  generated using the openssl command line tool:
+
+  openssl genrsa 2048 > arm_protprivk_rsa.pem
+
+* arm_protpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key
+  associated with the above private key. It has been generated using the openssl
+  command line tool:
+
+  openssl rsa -in arm_protprivk_rsa.pem -pubout -outform DER | \
+    openssl dgst -sha256 -binary > arm_protpk_rsa_sha256.bin
diff --git a/plat/arm/board/common/protpk/arm_dev_protpk.S b/plat/arm/board/common/protpk/arm_dev_protpk.S
new file mode 100644
index 0000000..2688cbb
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_dev_protpk.S
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+	.global arm_protpk_hash
+	.global arm_protpk_hash_end
+
+	.section .rodata.arm_protpk_hash, "a"
+
+arm_protpk_hash:
+	/* DER header. */
+	.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+	.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+	/* Key hash. */
+	.incbin ARM_PROTPK_HASH
+arm_protpk_hash_end:
diff --git a/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin b/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
new file mode 100644
index 0000000..587da66
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
@@ -0,0 +1 @@
+œó6{W*Â…`Ÿtíve×·§è£	€¾PžÆK{9
\ No newline at end of file
diff --git a/plat/arm/board/common/protpk/arm_protprivk_rsa.pem b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem
new file mode 100644
index 0000000..eeaad9e
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAzR0h/Z4Up17wfuRlYrUWseGDmlGKpl1PflGiYbyVmI7PwTTp
+y/T77EiljGp52suLWntHsc0lee50pW16DU2c5bVfmyofau3GjJ1Yqw5XFAahr6eM
+/0mkN8utrevvcRT9CP07D+zdhb/WlRUAnedqr/AUHU8BXS+Bxe8P0Z0Z7+DKjYZp
+thzXxsjKM02BFFzNwyVrlyBFDkW/53A4M+dpmuWDjAGCJH88W/u0LdmLcii11IzD
+/Ofz8Jxc/ZhqL+9FFK4qU+AJp8yXAnACSB46DlNltJrode0y5tmPhtS37ZF7EFb8
+UZWwZVgtuQyuyz9RYUS6jtiGuq6s8GlRwjTe7wIDAQABAoIBAFoWIYeyln+sQxR4
+W88umfkmgxaUGcFX2kIwuJEUst9+WeERzF24C62LeqphWYOvQlVLMAH3iC41fSXr
+H2AYZoC9WHBd386nAD1iHj+C3Nv+zaTIgjTdszKOUonAxjl0bm40SmyELAdCaoyv
+3MV9jm4Xk74LpR24b9bvWJNH3MxttH9hiYS+n0IzeTXDfO8GrNvHh92zx+jo8yMm
+Khhu+TDC9jA2pHpJcF/0EXxYMhwYiQT16nnHb+xMgS4JpalQhvVK01s4VYGHRoFk
+K6xh4TIS336LDLyalrGsPlfNfEdx+DimShDIfBUx9Jp3Pp11TUQUz4rhIHB9WdfG
+b6bV4wECgYEA+cgPS2TQ7XQ1RJq1S7OGePtBXvnoH226KwGS6Fey8838tLxbblim
+MU+EOYs3O66V6U2YpzmIakXo8030k8thY+jKbZl3l0m/hMuPOG66hfE5i7dYsiP4
+atok5wFiNeNYYjHMEayzk53MhG8EOh36msAO7ohKmenONUBA7pk6yTkCgYEA0jhk
+HPshwi+wKkx+JLTnuoEgx40tkRgSF2xBqKssMTasaQmX8qG+w9CEs0R8nZCI70Vc
+tXSFcidjdkHUVE2WsygIFuS1tbsAnpaxtn3E6rjie30X/Z280+TV0HjR0EMETmwl
+ShC5lZ0oP3LpEZfjbR5qs2kFW4MOxA7tjQVaMWcCgYEA5ZbVMBifzdMl70RA5i9C
+qEtSQAl3KgRCvar5rKSHsX+iC0Kiy9+iCusq/3WONEZ6NvMDIJpKYFyYDaOW7o5f
+m2TrRChu+1lnN5mfsGBfBCTBH0JMvZlAin6ussLb0eqBX+ijyY8zlLjTttsQSJcr
+tThZwTj3UVfOGbZQuL+RgEkCgYBXO3U3nXI9vUIx2zoBC1yZRNoQVGITMlTXiWGZ
+lyYoadKTZ5q44Sti4BUguounaoGYIEU/OtHhM70PJnPwY53kS/lHXrKUbbvtEwU9
+f+UFraC1s4wP/rOLjgq3jlsqO5T+4dt7Z4NLNUKtSYazeT6zWgrW1f6WIcUv0C38
+9bqegwKBgFCK3Oa5ibL5sPaPQ/1UfdeW4JVuu6A4JhHS7r+cVLsmcrvE1Qv7Wcvw
+B5aqXeqLu2dtIN8/f++3tzccs9LXKY/fh72D4TVjfrqOSSZoGTH9l4U5NXbqWM3I
+skkAYb2bMST/d1qSyYesgXVNAlaQHRh3vEz8x853nJ3v9OFj8/rW
+-----END RSA PRIVATE KEY-----
diff --git a/plat/arm/board/fvp/fvp_trusted_boot.c b/plat/arm/board/fvp/fvp_trusted_boot.c
index a09b80e..8825198 100644
--- a/plat/arm/board/fvp/fvp_trusted_boot.c
+++ b/plat/arm/board/fvp/fvp_trusted_boot.c
@@ -30,7 +30,7 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
 
 /*
diff --git a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
+++ b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
+++ b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/board/sgi575/sgi575_trusted_boot.c b/plat/arm/board/sgi575/sgi575_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/sgi575/sgi575_trusted_boot.c
+++ b/plat/arm/board/sgi575/sgi575_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/board/sgm775/sgm775_trusted_boot.c b/plat/arm/board/sgm775/sgm775_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/sgm775/sgm775_trusted_boot.c
+++ b/plat/arm/board/sgm775/sgm775_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 4fb85fb..65f6bf3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -297,6 +297,8 @@
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)
         AUTH_SOURCES	+=	drivers/auth/tbbr/tbbr_cot.c
+    else ifeq (${COT},dualroot)
+        AUTH_SOURCES	+=	drivers/auth/dualroot/cot.c
     else
         $(error Unknown chain of trust ${COT})
     endif
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index d3b4e4f..f5f8ffe 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -166,6 +166,7 @@
 
 	hikey960_edma_init();
 	hikey960_iomcu_dma_init();
+	hikey960_gpio_init();
 
 	hisi_ipc_init();
 }
diff --git a/plat/hisilicon/hikey960/hikey960_bl_common.c b/plat/hisilicon/hikey960/hikey960_bl_common.c
index 89adccb..3c4a164 100644
--- a/plat/hisilicon/hikey960/hikey960_bl_common.c
+++ b/plat/hisilicon/hikey960/hikey960_bl_common.c
@@ -466,6 +466,13 @@
 	pl061_gpio_register(GPIO19_BASE, 19);
 	pl061_gpio_register(GPIO20_BASE, 20);
 	pl061_gpio_register(GPIO21_BASE, 21);
+	pl061_gpio_register(GPIO22_BASE, 22);
+	pl061_gpio_register(GPIO23_BASE, 23);
+	pl061_gpio_register(GPIO24_BASE, 24);
+	pl061_gpio_register(GPIO25_BASE, 25);
+	pl061_gpio_register(GPIO26_BASE, 26);
+	pl061_gpio_register(GPIO27_BASE, 27);
+	pl061_gpio_register(GPIO28_BASE, 28);
 
 	/* PCIE_PERST_N output low */
 	gpio_set_direction(89, GPIO_DIR_OUT);
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
index 9f96fc3..f836508 100644
--- a/plat/hisilicon/hikey960/hikey960_pm.c
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -11,6 +11,7 @@
 #include <drivers/arm/cci.h>
 #include <drivers/arm/gicv2.h>
 #include <drivers/arm/pl011.h>
+#include <drivers/arm/pl061_gpio.h>
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
@@ -116,6 +117,13 @@
 	}
 }
 
+static void __dead2 hikey960_system_off(void)
+{
+	gpio_set_direction(176, GPIO_DIR_OUT);
+	gpio_set_value(176, GPIO_LEVEL_LOW);
+	panic();
+}
+
 static void __dead2 hikey960_system_reset(void)
 {
 	dsb();
@@ -293,7 +301,7 @@
 	.pwr_domain_off			= hikey960_pwr_domain_off,
 	.pwr_domain_suspend		= hikey960_pwr_domain_suspend,
 	.pwr_domain_suspend_finish	= hikey960_pwr_domain_suspend_finish,
-	.system_off			= NULL,
+	.system_off			= hikey960_system_off,
 	.system_reset			= hikey960_system_reset,
 	.validate_power_state		= hikey960_validate_power_state,
 	.validate_ns_entrypoint		= hikey960_validate_ns_entrypoint,
diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h
index 7cc1ee0..17b495f 100644
--- a/plat/hisilicon/hikey960/include/hi3660.h
+++ b/plat/hisilicon/hikey960/include/hi3660.h
@@ -260,6 +260,13 @@
 #define GPIO17_BASE			UL(0xE8A1C000)
 #define GPIO20_BASE			UL(0xE8A1F000)
 #define GPIO21_BASE			UL(0xE8A20000)
+#define GPIO22_BASE			UL(0xFFF0B000)
+#define GPIO23_BASE			UL(0xFFF0C000)
+#define GPIO24_BASE			UL(0xFFF0D000)
+#define GPIO25_BASE			UL(0xFFF0E000)
+#define GPIO26_BASE			UL(0xFFF0F000)
+#define GPIO27_BASE			UL(0xFFF10000)
+#define GPIO28_BASE			UL(0xFFF1D000)
 
 #define TZC_REG_BASE			0xE8A21000
 #define TZC_STAT0_REG			(TZC_REG_BASE + 0x800)
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index 6cb53c7..8ebabeb 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -19,7 +19,7 @@
 
 CRASH_CONSOLE_BASE		:=	PL011_UART6_BASE
 COLD_BOOT_SINGLE_CPU		:=	1
-PLAT_PL061_MAX_GPIOS		:=	176
+PLAT_PL061_MAX_GPIOS		:=	232
 PROGRAMMABLE_RESET_ADDRESS	:=	1
 ENABLE_SVE_FOR_NS		:=	0
 PLAT_PARTITION_BLOCK_SIZE	:=	4096
@@ -95,12 +95,15 @@
 endif
 
 BL31_SOURCES		+=	drivers/arm/cci/cci.c			\
+				drivers/arm/pl061/pl061_gpio.c		\
+				drivers/gpio/gpio.c			\
 				lib/cpus/aarch64/cortex_a53.S           \
 				lib/cpus/aarch64/cortex_a72.S		\
 				lib/cpus/aarch64/cortex_a73.S		\
 				plat/common/plat_psci_common.c  \
 				plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \
 				plat/hisilicon/hikey960/hikey960_bl31_setup.c \
+				plat/hisilicon/hikey960/hikey960_bl_common.c \
 				plat/hisilicon/hikey960/hikey960_pm.c	\
 				plat/hisilicon/hikey960/hikey960_topology.c \
 				plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index 56caab7..f25ceb0 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -47,7 +47,6 @@
 
 #define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
 
-#define IMX_BOOT_UART_BASE		U(0x30890000)
 #define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
 
 #define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index 1ff576d..5fa3003 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -53,3 +53,6 @@
 
 BL32_SIZE		?=	0x2000000
 $(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE	?=	0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index cf68b71..0fd3866 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -1,9 +1,10 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <platform_def.h>
 
@@ -131,15 +132,7 @@
 
     ASSERT(. <= BL31_LIMIT, "BL3-1 image has exceeded its limit.")
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM2
+    XLAT_TABLE_SECTION >RAM2
 
 #if USE_COHERENT_MEM
     /*
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index b86287b..bd1a16b 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -149,14 +149,8 @@
 
 # Macros and rules to build TF binary
 STM32_TF_ELF_LDFLAGS	:=	--hash-style=gnu --as-needed
-STM32_DT_BASENAME	:=	$(DTB_FILE_NAME:.dtb=)
-STM32_TF_STM32		:=	${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32
-STM32_TF_BINARY		:=	$(STM32_TF_STM32:.stm32=.bin)
-STM32_TF_MAPFILE	:=	$(STM32_TF_STM32:.stm32=.map)
-STM32_TF_LINKERFILE	:=	$(STM32_TF_STM32:.stm32=.ld)
-STM32_TF_ELF		:=	$(STM32_TF_STM32:.stm32=.elf)
-STM32_TF_DTBFILE	:=      ${BUILD_PLAT}/fdts/${DTB_FILE_NAME}
-STM32_TF_OBJS		:=	${BUILD_PLAT}/stm32mp1.o
+STM32_TF_STM32		:=	$(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
+STM32_TF_LINKERFILE	:=	${BUILD_PLAT}/stm32mp1.ld
 
 BL2_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
 
@@ -164,7 +158,7 @@
 STM32IMAGEPATH		?= tools/stm32image
 STM32IMAGE		?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
 
-.PHONY:			${STM32_TF_STM32}
+.PHONY:			check_dtc_version stm32image clean_stm32image
 .SUFFIXES:
 
 all: check_dtc_version ${STM32_TF_STM32} stm32image
@@ -192,32 +186,32 @@
 	fi
 
 
-${STM32_TF_OBJS}:	plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE}
-			@echo "  AS      $<"
+${BUILD_PLAT}/stm32mp1-%.o:	${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP}
+			@echo "  AS      stm32mp1.S"
 			${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
 				${BL32_PATH} \
 				-DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" \
-				-DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \
+				-DDTB_BIN_PATH=\"$<\" \
 				-c plat/st/stm32mp1/stm32mp1.S -o $@
 
 ${STM32_TF_LINKERFILE}:	plat/st/stm32mp1/stm32mp1.ld.S ${BUILD_PLAT}
 			@echo "  LDS     $<"
 			${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@
 
-${STM32_TF_ELF}:	${STM32_TF_OBJS} ${STM32_TF_LINKERFILE}
+tf-a-%.elf:		stm32mp1-%.o ${STM32_TF_LINKERFILE}
 			@echo "  LDS     $<"
-			${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=${STM32_TF_MAPFILE} --script ${STM32_TF_LINKERFILE} ${STM32_TF_OBJS}
+			${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
 
-${STM32_TF_BINARY}:	${STM32_TF_ELF}
-			${Q}${OC} -O binary ${STM32_TF_ELF} $@
+tf-a-%.bin:		tf-a-%.elf
+			${Q}${OC} -O binary $< $@
 			@echo
 			@echo "Built $@ successfully"
 			@echo
 
-${STM32_TF_STM32}:	stm32image ${STM32_TF_BINARY}
+tf-a-%.stm32:		tf-a-%.bin stm32image
 			@echo
 			@echo "Generated $@"
-			$(eval LOADADDR =  $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}'))
-			$(eval ENTRY =  $(shell cat ${STM32_TF_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
-			${STM32IMAGE} -s ${STM32_TF_BINARY} -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION}
+			$(eval LOADADDR =  $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}'))
+			$(eval ENTRY =  $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
+			${STM32IMAGE} -s $< -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION}
 			@echo
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index eff929e..19f736f 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -27,6 +27,8 @@
 # Chain of trust.
 ifeq (${COT},tbbr)
   include src/tbbr/tbbr.mk
+else ifeq (${COT},dualroot)
+  include src/dualroot/cot.mk
 else
   $(error Unknown chain of trust ${COT})
 endif
diff --git a/tools/cert_create/include/dualroot/cot.h b/tools/cert_create/include/dualroot/cot.h
new file mode 100644
index 0000000..5701206
--- /dev/null
+++ b/tools/cert_create/include/dualroot/cot.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUALROOT_COT_H
+#define DUALROOT_COT_H
+
+/* Certificates. */
+enum {
+	/* Certificates owned by the silicon provider. */
+	TRUSTED_BOOT_FW_CERT,
+	TRUSTED_KEY_CERT,
+	SCP_FW_KEY_CERT,
+	SCP_FW_CONTENT_CERT,
+	SOC_FW_KEY_CERT,
+	SOC_FW_CONTENT_CERT,
+	TRUSTED_OS_FW_KEY_CERT,
+	TRUSTED_OS_FW_CONTENT_CERT,
+	FWU_CERT,
+
+	/* Certificates owned by the platform owner. */
+	NON_TRUSTED_FW_CONTENT_CERT,
+};
+
+/* Certificate extensions. */
+enum {
+	/* Extensions used in certificates owned by the silicon provider. */
+	TRUSTED_FW_NVCOUNTER_EXT,
+	TRUSTED_BOOT_FW_HASH_EXT,
+	TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
+	HW_CONFIG_HASH_EXT,
+	TRUSTED_WORLD_PK_EXT,
+	SCP_FW_CONTENT_CERT_PK_EXT,
+	SCP_FW_HASH_EXT,
+	SOC_FW_CONTENT_CERT_PK_EXT,
+	SOC_AP_FW_HASH_EXT,
+	SOC_FW_CONFIG_HASH_EXT,
+	TRUSTED_OS_FW_CONTENT_CERT_PK_EXT,
+	TRUSTED_OS_FW_HASH_EXT,
+	TRUSTED_OS_FW_EXTRA1_HASH_EXT,
+	TRUSTED_OS_FW_EXTRA2_HASH_EXT,
+	TRUSTED_OS_FW_CONFIG_HASH_EXT,
+	SCP_FWU_CFG_HASH_EXT,
+	AP_FWU_CFG_HASH_EXT,
+	FWU_HASH_EXT,
+
+	/* Extensions used in certificates owned by the platform owner. */
+	PROT_PK_EXT,
+	NON_TRUSTED_FW_NVCOUNTER_EXT,
+	NON_TRUSTED_FW_CONTENT_CERT_PK_EXT,
+	NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
+	NON_TRUSTED_FW_CONFIG_HASH_EXT,
+};
+
+/* Keys. */
+enum {
+	/* Keys owned by the silicon provider. */
+	ROT_KEY,
+	TRUSTED_WORLD_KEY,
+	SCP_FW_CONTENT_CERT_KEY,
+	SOC_FW_CONTENT_CERT_KEY,
+	TRUSTED_OS_FW_CONTENT_CERT_KEY,
+
+	/* Keys owned by the platform owner. */
+	PROT_KEY,
+};
+
+#endif /* DUALROOT_COT_H */
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
new file mode 100644
index 0000000..8117ffc
--- /dev/null
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dualroot_oid.h>
+
+#include "cert.h"
+#include "ext.h"
+#include "key.h"
+
+#include "dualroot/cot.h"
+
+/*
+ * Certificates used in the chain of trust.
+ *
+ * All certificates are self-signed so the issuer certificate field points to
+ * itself.
+ */
+static cert_t cot_certs[] = {
+	[TRUSTED_BOOT_FW_CERT] = {
+		.id = TRUSTED_BOOT_FW_CERT,
+		.opt = "tb-fw-cert",
+		.help_msg = "Trusted Boot FW Certificate (output file)",
+		.cn = "Trusted Boot FW Certificate",
+		.key = ROT_KEY,
+		.issuer = TRUSTED_BOOT_FW_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_BOOT_FW_HASH_EXT,
+			TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
+			HW_CONFIG_HASH_EXT
+		},
+		.num_ext = 4
+	},
+
+	[TRUSTED_KEY_CERT] = {
+		.id = TRUSTED_KEY_CERT,
+		.opt = "trusted-key-cert",
+		.help_msg = "Trusted Key Certificate (output file)",
+		.cn = "Trusted Key Certificate",
+		.key = ROT_KEY,
+		.issuer = TRUSTED_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_WORLD_PK_EXT,
+		},
+		.num_ext = 2
+	},
+
+	[SCP_FW_KEY_CERT] = {
+		.id = SCP_FW_KEY_CERT,
+		.opt = "scp-fw-key-cert",
+		.help_msg = "SCP Firmware Key Certificate (output file)",
+		.cn = "SCP Firmware Key Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = SCP_FW_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SCP_FW_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 2
+	},
+
+	[SCP_FW_CONTENT_CERT] = {
+		.id = SCP_FW_CONTENT_CERT,
+		.opt = "scp-fw-cert",
+		.help_msg = "SCP Firmware Content Certificate (output file)",
+		.cn = "SCP Firmware Content Certificate",
+		.key = SCP_FW_CONTENT_CERT_KEY,
+		.issuer = SCP_FW_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SCP_FW_HASH_EXT
+		},
+		.num_ext = 2
+	},
+
+	[SOC_FW_KEY_CERT] = {
+		.id = SOC_FW_KEY_CERT,
+		.opt = "soc-fw-key-cert",
+		.help_msg = "SoC Firmware Key Certificate (output file)",
+		.cn = "SoC Firmware Key Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = SOC_FW_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SOC_FW_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 2
+	},
+
+	[SOC_FW_CONTENT_CERT] = {
+		.id = SOC_FW_CONTENT_CERT,
+		.opt = "soc-fw-cert",
+		.help_msg = "SoC Firmware Content Certificate (output file)",
+		.cn = "SoC Firmware Content Certificate",
+		.key = SOC_FW_CONTENT_CERT_KEY,
+		.issuer = SOC_FW_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SOC_AP_FW_HASH_EXT,
+			SOC_FW_CONFIG_HASH_EXT,
+		},
+		.num_ext = 3
+	},
+
+	[TRUSTED_OS_FW_KEY_CERT] = {
+		.id = TRUSTED_OS_FW_KEY_CERT,
+		.opt = "tos-fw-key-cert",
+		.help_msg = "Trusted OS Firmware Key Certificate (output file)",
+		.cn = "Trusted OS Firmware Key Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = TRUSTED_OS_FW_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_OS_FW_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 2
+	},
+
+	[TRUSTED_OS_FW_CONTENT_CERT] = {
+		.id = TRUSTED_OS_FW_CONTENT_CERT,
+		.opt = "tos-fw-cert",
+		.help_msg = "Trusted OS Firmware Content Certificate (output file)",
+		.cn = "Trusted OS Firmware Content Certificate",
+		.key = TRUSTED_OS_FW_CONTENT_CERT_KEY,
+		.issuer = TRUSTED_OS_FW_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_OS_FW_HASH_EXT,
+			TRUSTED_OS_FW_EXTRA1_HASH_EXT,
+			TRUSTED_OS_FW_EXTRA2_HASH_EXT,
+			TRUSTED_OS_FW_CONFIG_HASH_EXT,
+		},
+		.num_ext = 5
+	},
+
+	[FWU_CERT] = {
+		.id = FWU_CERT,
+		.opt = "fwu-cert",
+		.help_msg = "Firmware Update Certificate (output file)",
+		.cn = "Firmware Update Certificate",
+		.key = ROT_KEY,
+		.issuer = FWU_CERT,
+		.ext = {
+			SCP_FWU_CFG_HASH_EXT,
+			AP_FWU_CFG_HASH_EXT,
+			FWU_HASH_EXT
+		},
+		.num_ext = 3
+	},
+
+	[NON_TRUSTED_FW_CONTENT_CERT] = {
+		.id = NON_TRUSTED_FW_CONTENT_CERT,
+		.opt = "nt-fw-cert",
+		.help_msg = "Non-Trusted Firmware Content Certificate (output file)",
+		.cn = "Non-Trusted Firmware Content Certificate",
+		.key = PROT_KEY,
+		.issuer = NON_TRUSTED_FW_CONTENT_CERT,
+		.ext = {
+			NON_TRUSTED_FW_NVCOUNTER_EXT,
+			NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
+			NON_TRUSTED_FW_CONFIG_HASH_EXT,
+			PROT_PK_EXT,
+		},
+		.num_ext = 4
+	},
+};
+
+REGISTER_COT(cot_certs);
+
+
+/* Certificate extensions. */
+static ext_t cot_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,
+		.attr.nvctr_type = NVCTR_TYPE_TFW
+	},
+
+	[TRUSTED_BOOT_FW_HASH_EXT] = {
+		.oid = TRUSTED_BOOT_FW_HASH_OID,
+		.opt = "tb-fw",
+		.help_msg = "Trusted Boot Firmware image file",
+		.sn = "TrustedBootFirmwareHash",
+		.ln = "Trusted Boot Firmware hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = {
+		.oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID,
+		.opt = "tb-fw-config",
+		.help_msg = "Trusted Boot Firmware Config file",
+		.sn = "TrustedBootFirmwareConfigHash",
+		.ln = "Trusted Boot Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[HW_CONFIG_HASH_EXT] = {
+		.oid = HW_CONFIG_HASH_OID,
+		.opt = "hw-config",
+		.help_msg = "HW Config file",
+		.sn = "HWConfigHash",
+		.ln = "HW Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_WORLD_PK_EXT] = {
+		.oid = TRUSTED_WORLD_PK_OID,
+		.sn = "TrustedWorldPublicKey",
+		.ln = "Trusted World Public Key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = TRUSTED_WORLD_KEY
+	},
+
+	[SCP_FW_CONTENT_CERT_PK_EXT] = {
+		.oid = SCP_FW_CONTENT_CERT_PK_OID,
+		.sn = "SCPFirmwareContentCertPK",
+		.ln = "SCP Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = SCP_FW_CONTENT_CERT_KEY
+	},
+
+	[SCP_FW_HASH_EXT] = {
+		.oid = SCP_FW_HASH_OID,
+		.opt = "scp-fw",
+		.help_msg = "SCP Firmware image file",
+		.sn = "SCPFirmwareHash",
+		.ln = "SCP Firmware hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[SOC_FW_CONTENT_CERT_PK_EXT] = {
+		.oid = SOC_FW_CONTENT_CERT_PK_OID,
+		.sn = "SoCFirmwareContentCertPK",
+		.ln = "SoC Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = SOC_FW_CONTENT_CERT_KEY
+	},
+
+	[SOC_AP_FW_HASH_EXT] = {
+		.oid = SOC_AP_FW_HASH_OID,
+		.opt = "soc-fw",
+		.help_msg = "SoC AP Firmware image file",
+		.sn = "SoCAPFirmwareHash",
+		.ln = "SoC AP Firmware hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[SOC_FW_CONFIG_HASH_EXT] = {
+		.oid = SOC_FW_CONFIG_HASH_OID,
+		.opt = "soc-fw-config",
+		.help_msg = "SoC Firmware Config file",
+		.sn = "SocFirmwareConfigHash",
+		.ln = "SoC Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = {
+		.oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID,
+		.sn = "TrustedOSFirmwareContentCertPK",
+		.ln = "Trusted OS Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
+	},
+
+	[TRUSTED_OS_FW_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_HASH_OID,
+		.opt = "tos-fw",
+		.help_msg = "Trusted OS image file",
+		.sn = "TrustedOSHash",
+		.ln = "Trusted OS hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[TRUSTED_OS_FW_EXTRA1_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_EXTRA1_HASH_OID,
+		.opt = "tos-fw-extra1",
+		.help_msg = "Trusted OS Extra1 image file",
+		.sn = "TrustedOSExtra1Hash",
+		.ln = "Trusted OS Extra1 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_OS_FW_EXTRA2_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_EXTRA2_HASH_OID,
+		.opt = "tos-fw-extra2",
+		.help_msg = "Trusted OS Extra2 image file",
+		.sn = "TrustedOSExtra2Hash",
+		.ln = "Trusted OS Extra2 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_OS_FW_CONFIG_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_CONFIG_HASH_OID,
+		.opt = "tos-fw-config",
+		.help_msg = "Trusted OS Firmware Config file",
+		.sn = "TrustedOSFirmwareConfigHash",
+		.ln = "Trusted OS Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[SCP_FWU_CFG_HASH_EXT] = {
+		.oid = SCP_FWU_CFG_HASH_OID,
+		.opt = "scp-fwu-cfg",
+		.help_msg = "SCP Firmware Update Config image file",
+		.sn = "SCPFWUpdateConfig",
+		.ln = "SCP Firmware Update Config hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[AP_FWU_CFG_HASH_EXT] = {
+		.oid = AP_FWU_CFG_HASH_OID,
+		.opt = "ap-fwu-cfg",
+		.help_msg = "AP Firmware Update Config image file",
+		.sn = "APFWUpdateConfig",
+		.ln = "AP Firmware Update Config hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[FWU_HASH_EXT] = {
+		.oid = FWU_HASH_OID,
+		.opt = "fwu",
+		.help_msg = "Firmware Updater image file",
+		.sn = "FWUpdaterHash",
+		.ln = "Firmware Updater hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[PROT_PK_EXT] = {
+		.oid = PROT_PK_OID,
+		.sn = "PlatformRoTKey",
+		.ln = "Platform Root of Trust Public Key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = PROT_KEY
+	},
+
+	[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 = "Non-Trusted Firmware Non-Volatile counter",
+		.asn1_type = V_ASN1_INTEGER,
+		.type = EXT_TYPE_NVCOUNTER,
+		.attr.nvctr_type = NVCTR_TYPE_NTFW
+	},
+
+	[NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = {
+		.oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID,
+		.opt = "nt-fw",
+		.help_msg = "Non-Trusted World Bootloader image file",
+		.sn = "NonTrustedWorldBootloaderHash",
+		.ln = "Non-Trusted World hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[NON_TRUSTED_FW_CONFIG_HASH_EXT] = {
+		.oid = NON_TRUSTED_FW_CONFIG_HASH_OID,
+		.opt = "nt-fw-config",
+		.help_msg = "Non Trusted OS Firmware Config file",
+		.sn = "NonTrustedOSFirmwareConfigHash",
+		.ln = "Non-Trusted OS Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+};
+
+REGISTER_EXTENSIONS(cot_ext);
+
+
+/* Keys used to establish the chain of trust. */
+static key_t cot_keys[] = {
+	[ROT_KEY] = {
+		.id = ROT_KEY,
+		.opt = "rot-key",
+		.help_msg = "Root Of Trust key (input/output file)",
+		.desc = "Root Of Trust key"
+	},
+
+	[TRUSTED_WORLD_KEY] = {
+		.id = TRUSTED_WORLD_KEY,
+		.opt = "trusted-world-key",
+		.help_msg = "Trusted World key (input/output file)",
+		.desc = "Trusted World key"
+	},
+
+	[SCP_FW_CONTENT_CERT_KEY] = {
+		.id = SCP_FW_CONTENT_CERT_KEY,
+		.opt = "scp-fw-key",
+		.help_msg = "SCP Firmware Content Certificate key (input/output file)",
+		.desc = "SCP Firmware Content Certificate key"
+	},
+
+	[SOC_FW_CONTENT_CERT_KEY] = {
+		.id = SOC_FW_CONTENT_CERT_KEY,
+		.opt = "soc-fw-key",
+		.help_msg = "SoC Firmware Content Certificate key (input/output file)",
+		.desc = "SoC Firmware Content Certificate key"
+	},
+
+	[TRUSTED_OS_FW_CONTENT_CERT_KEY] = {
+		.id = TRUSTED_OS_FW_CONTENT_CERT_KEY,
+		.opt = "tos-fw-key",
+		.help_msg = "Trusted OS Firmware Content Certificate key (input/output file)",
+		.desc = "Trusted OS Firmware Content Certificate key"
+	},
+
+	[PROT_KEY] = {
+		.id = PROT_KEY,
+		.opt = "prot-key",
+		.help_msg = "Platform Root of Trust key",
+		.desc = "Platform Root of Trust key"
+	},
+};
+
+REGISTER_KEYS(cot_keys);
diff --git a/tools/cert_create/src/dualroot/cot.mk b/tools/cert_create/src/dualroot/cot.mk
new file mode 100644
index 0000000..a572484
--- /dev/null
+++ b/tools/cert_create/src/dualroot/cot.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_MSG		:=	Dual root of trust
+PLAT_INCLUDE		:=	../../include/tools_share
+
+OBJECTS += src/dualroot/cot.o