Merge changes from topic "qemu" into integration

* changes:
  docs: qemu: bump to QEMU 5.0.0
  docs: qemu: remove unneeded root=/dev/vda2 kernel parameter
  docs: qemu: add build instructions for QEMU_EFI.fd and rootfs.cpio.gz
diff --git a/Makefile b/Makefile
index becbf03..1d6c5f7 100644
--- a/Makefile
+++ b/Makefile
@@ -484,6 +484,10 @@
                 $(error SPMD with SPM at S-EL2 requires CTX_INCLUDE_EL2_REGS option)
             endif
         endif
+
+        ifeq ($(findstring optee_sp,$(ARM_SPMC_MANIFEST_DTS)),optee_sp)
+            DTC_CPPFLAGS	+=	-DOPTEE_SP_FW_CONFIG
+        endif
     else
         # All other SPDs in spd directory
         SPD_DIR := spd
@@ -659,6 +663,10 @@
 	SDEI_SUPPORT is enabled")
 endif
 
+ifeq ($(COT_DESC_IN_DTB),1)
+    $(info CoT in device tree is an experimental feature)
+endif
+
 # If pointer authentication is used in the firmware, make sure that all the
 # registers associated to it are also saved and restored.
 # Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1.
@@ -903,6 +911,7 @@
 $(eval $(call assert_boolean,ENCRYPT_BL32))
 $(eval $(call assert_boolean,ERRATA_SPECULATIVE_AT))
 $(eval $(call assert_boolean,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call assert_boolean,COT_DESC_IN_DTB))
 
 $(eval $(call assert_numeric,ARM_ARCH_MAJOR))
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -983,6 +992,7 @@
 $(eval $(call add_define,USE_SPINLOCK_CAS))
 $(eval $(call add_define,ERRATA_SPECULATIVE_AT))
 $(eval $(call add_define,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call add_define,COT_DESC_IN_DTB))
 
 ifeq (${SANITIZE_UB},trap)
         $(eval $(call add_define,MONITOR_TRAPS))
@@ -1195,7 +1205,7 @@
 
 .PHONY: ${CRTTOOL}
 ${CRTTOOL}:
-	${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} --no-print-directory -C ${CRTTOOLPATH}
+	${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${CRTTOOLPATH}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
@@ -1261,7 +1271,7 @@
 
 .PHONY: ${ENCTOOL}
 ${ENCTOOL}:
-	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 --no-print-directory -C ${ENCTOOLPATH}
+	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${ENCTOOLPATH}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 802c174..203e1d4 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -1,5 +1,5 @@
 /*
- * 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
  */
@@ -14,6 +14,9 @@
 #include <common/debug.h>
 #include <drivers/auth/auth_mod.h>
 #include <drivers/console.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
 #include <lib/extensions/pauth.h>
 #include <plat/common/platform.h>
 
@@ -88,14 +91,25 @@
 #if TRUSTED_BOARD_BOOT
 	/* Initialize authentication module */
 	auth_mod_init();
+
+#if MEASURED_BOOT
+	/* Initialize measured boot module */
+	measured_boot_init();
+
+#endif /* MEASURED_BOOT */
 #endif /* TRUSTED_BOARD_BOOT */
 
-	/* initialize boot source */
+	/* Initialize boot source */
 	bl2_plat_preload_setup();
 
 	/* Load the subsequent bootloader images. */
 	next_bl_ep_info = bl2_load_images();
 
+#if MEASURED_BOOT
+	/* Finalize measured boot */
+	measured_boot_finish();
+#endif /* MEASURED_BOOT */
+
 #if !BL2_AT_EL3
 #ifndef __aarch64__
 	/*
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index bf29186..0014d3b 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -21,7 +21,7 @@
 :G: `soby-mathew`_
 :M: Sandrine Bailleux <sandrine.bailleux@arm.com>
 :G: `sandrine-bailleux-arm`_
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Manish Pandey <manish.pandey2@arm.com>
 :G: `manish-pandey-arm`_
@@ -60,6 +60,14 @@
 :M: Etienne Carriere <etienne.carriere@linaro.org>
 :G: `etienne-lms`_
 
+Build Definitions for CMake Build System
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:M: Jack Bond-Preston <Jack.Bond-Preston@arm.com>
+:G: `jackbondpreston-arm`_
+:F: /
+
 Software Delegated Exception Interface (SDEI)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :M: Mark Dykes <mark.dykes@arm.com>
@@ -185,7 +193,7 @@
 
 Activity Monitors Unit (AMU) extensions
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :F: lib/extensions/amu/
 
@@ -199,7 +207,7 @@
 
 Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Zelalem Aweke <Zelalem.Aweke@arm.com>
 :G: `zelalem-aweke`_
@@ -221,7 +229,7 @@
 
 Standard C library
 ^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: John Powell <John.Powell@arm.com>
 :G: `john-powell-arm`_
@@ -251,7 +259,7 @@
 
 GIC driver
 ^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Manish Pandey <manish.pandey2@arm.com>
 :G: `manish-pandey-arm`_
@@ -277,6 +285,15 @@
 :F: include/drivers/io/io_encrypted.h
 :F: include/tools_share/firmware_encrypted.h
 
+Measured Boot
+^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: drivers/measured_boot
+:F: include/drivers/measured_boot
+:F: plat/arm/board/fvp/fvp_measured_boot.c
 
 Platform Ports
 ~~~~~~~~~~~~~~
@@ -320,6 +337,14 @@
 :F: docs/plat/meson-axg.rst
 :F: plat/amlogic/axg/
 
+Arm FPGA platform port
+^^^^^^^^^^^^^^^^^^^^^^
+:M: Andre Przywara <andre.przywara@arm.com>
+:G: `Andre-ARM`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: plat/arm/board/arm_fpga
+
 Arm System Guidance for Infrastructure / Mobile FVP platforms
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :M: Nariman Poushin <nariman.poushin@linaro.org>
@@ -613,6 +638,6 @@
 .. _madhukar-Arm: https://github.com/madhukar-Arm
 .. _john-powell-arm: https://github.com/john-powell-arm
 .. _raghuncstate: https://github.com/raghuncstate
-
+.. _jackbondpreston-arm: https://github.com/jackbondpreston-arm
 
 .. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
index cc69d79..46915db 100644
--- a/docs/components/cot-binding.rst
+++ b/docs/components/cot-binding.rst
@@ -1,23 +1,23 @@
 Chain of trust bindings
 =======================
 
-The device tree allows to describes the chain of trust with the help of
-certificates and images nodes, which in turn contains number of sub-nodes
-(i.e. certificate and image) mentioning properties for every certificate
-and image respectively.
-Also, this binding allows to describe OID of non-volatile counters, memory
-mapped address and size of non-volatile counter register.
+The device tree allows to describe the chain of trust with the help of
+'cot' node which contain 'manifests' and 'images' as sub-nodes.
+'manifests' and 'images' nodes contains number of sub-nodes (i.e. 'certificate'
+and 'image' nodes) mentioning properties of the certificate and image respectively.
 
-Convention used in this document
---------------------------------
+Also, device tree describes 'non-volatile-counters' node which contains number of
+sub-nodes mentioning properties of all non-volatile-counters used in the chain of trust.
 
-This document follows the conventions described in the Device-tree
-Specification
+cot
+------------------------------------------------------------------
+This is root node which contains 'manifests' and 'images' as sub-nodes
 
-certificates, certificate and extension node bindings definition
+
+Manifests and Certificate node bindings definition
 ----------------------------------------------------------------
 
-- Certificates node
+- Manifests node
         Description: Container of certificate nodes.
 
         PROPERTIES
@@ -27,20 +27,24 @@
 
                 Value type: <string>
 
-                Definition: must be "arm, certificate-descriptors"
+                Definition: must be "arm, cert-descs"
 
 - Certificate node
-        Description: Describes certificate properties which are used
-                     during the authentication process.
+        Description:
+
+        Describes certificate properties which are used
+        during the authentication process.
 
         PROPERTIES
 
         - root-certificate
-                Usage: Required for the certificate with no parent.
-                       In other words, Certificates which are validated
-                       using root of trust public key.
+               Usage:
 
-                Value type: <boolean>
+               Required for the certificate with no parent.
+               In other words, certificates which are validated
+               using root of trust public key.
+
+               Value type: <boolean>
 
         - image-id
                 Usage: Required for every certificate with unique id.
@@ -48,99 +52,121 @@
                 Value type: <u32>
 
         - parent
-                Usage: It refers to their parent image, which typically contains
-                       information to authenticate the certificate.
-                       This property is required for all non-root certificates.
+                Usage:
 
-                       This property is not required for root-certificates
-                       as it is validated using root of trust public key
-                       provided by platform.
+                It refers to their parent image, which typically contains
+                information to authenticate the certificate.
+                This property is required for all non-root certificates.
+
+                This property is not required for root-certificates
+                as root-certificates are validated using root of trust
+                public key provided by platform.
 
                 Value type: <phandle>
 
         - signing-key
-                Usage: This property is used to refer extension node present in
-                       parent certificate and it is required property for all non-
-                       root certificates which are authenticated using public-key
-                       present in parent certificate.
+                Usage:
 
-                       This property is not required for root-certificates
-                       as root-certificates are validated using root of trust
-                       public key provided by platform.
+                This property is used to refer public key node present in
+                parent certificate node and it is required property for all
+                non-root certificates which are authenticated using public-key
+                present in parent certificate.
+
+                This property is not required for root-certificates
+                as root-certificates are validated using root of trust
+                public key provided by platform.
 
                 Value type: <phandle>
 
         - antirollback-counter
-                Usage: This property is used by all certificates which are protected
-                       against rollback attacks using a non-volatile counter and it
-                       is optional property.
+                Usage:
 
-                       This property is used to refer trusted or non-trusted
-                       non-volatile counter node.
+                This property is used by all certificates which are
+                protected against rollback attacks using a non-volatile
+                counter and it is an optional property.
+
+                This property is used to refer one of the non-volatile
+                counter sub-node present in 'non-volatile counters' node.
 
                 Value type: <phandle>
 
+
         SUBNODES
+            - Description:
 
-        - extensions node
-                Description: This is sub-node of certificate node.
-                             Describes OIDs present in the certificate which will
-                             be used during authentication process to extract
-                             hash/public key information from this certificate.
-                             OIDs in extension node are represented using number of
-                             sub-nodes which contains 'oid' as property
+              Hash and public key information present in the certificate
+              are shown by these nodes.
 
-                PROPERTIES
+            - public key node
+                  Description: Provide public key information in the certificate.
 
-                - oid
-                        Usage: This property provides the Object ID of an extension
-                               provided in the certificate.
+                  PROPERTIES
 
-                        Value type: <string>
+                  - oid
+                     Usage:
+
+                     This property provides the Object ID of public key
+                     provided in the certificate which the help of which
+                     public key information can be extracted.
+
+                     Value type: <string>
+
+            - hash node
+                 Description: Provide the hash information in the certificate.
+
+                 PROPERTIES
+
+                 - oid
+                     Usage:
+
+                     This property provides the Object ID of hash provided in
+                     the certificate which the help of which hash information
+                     can be extracted.
+
+                     Value type: <string>
 
 Example:
 
 .. code:: c
 
-   certificates {
-         compatible = "arm, certificate-descriptors”
+   cot {
+      manifests {
+         compatible = "arm, cert-descs”
 
          trusted-key-cert: trusted-key-cert {
-                  root-certificate;
-                  image-id = <TRUSTED_KEY_CERT_ID>;
-                  antirollback-counter = <&trusted_nv_counter>;
-                  extensions {
-                        trusted-world-pk: trusted-world-pk {
-                              oid = TRUSTED_WORLD_PK_OID;
-                        };
-                        non-trusted-world-pk: non-trusted-world-pk {
-                              oid = NON_TRUSTED_WORLD_PK_OID;
-                        };
-                };
-        };
+            root-certificate;
+            image-id = <TRUSTED_KEY_CERT_ID>;
+            antirollback-counter = <&trusted_nv_counter>;
 
-        scp_fw_key_cert: scp_fw_key_cert {
-                image-id = <SCP_FW_KEY_CERT_ID>;
-                parent = <&trusted-key-cert>;
-                signing-key = <&trusted_world_pk>;
-                antirollback-counter = <&trusted_nv_counter>;
-                extensions {
-                        scp_fw_content_pk: scp_fw_content_pk {
-                              oid = SCP_FW_CONTENT_CERT_PK_OID;
-                        };
-                };
-        };
+            trusted-world-pk: trusted-world-pk {
+               oid = TRUSTED_WORLD_PK_OID;
+            };
+            non-trusted-world-pk: non-trusted-world-pk {
+               oid = NON_TRUSTED_WORLD_PK_OID;
+            };
+         };
 
-        .
-        .
-        .
+         scp_fw_key_cert: scp_fw_key_cert {
+            image-id = <SCP_FW_KEY_CERT_ID>;
+            parent = <&trusted-key-cert>;
+            signing-key = <&trusted_world_pk>;
+            antirollback-counter = <&trusted_nv_counter>;
 
-        next-cert {
+            scp_fw_content_pk: scp_fw_content_pk {
+               oid = SCP_FW_CONTENT_CERT_PK_OID;
+            };
+         };
+         .
+         .
+         .
 
-        };
+         next-certificate {
+
+         };
+      };
    };
 
-Images and image node bindings definition
+Images and Image node bindings definition
 -----------------------------------------
 
 - Images node
@@ -153,11 +179,13 @@
 
                 Value type: <string>
 
-                Definition: must be "arm, image-descriptors"
+                Definition: must be "arm, img-descs"
 
 - Image node
-        Description: Describes image properties which will be used during
-                     authentication process.
+        Description:
+
+        Describes image properties which will be used during
+        authentication process.
 
         PROPERTIES
 
@@ -167,35 +195,41 @@
                 Value type: <u32>
 
         - parent
-                Usage: Required for every image to provide a reference to
-                       it's parent image, which contains the necessary information
-                       to authenticate it.
+                Usage:
+
+                Required for every image to provide a reference to
+                its parent image, which contains the necessary information
+                to authenticate it.
 
                 Value type: <phandle>
 
         - hash
-                Usage: Required for all images which are validated using
-                       hash method. This property is used to refer extension
-                       node present in parent certificate and it is required
-                       property for all images.
+                Usage:
+
+                Required for all images which are validated using
+                hash method. This property is used to refer hash
+                node present in parent certificate node.
 
                 Value type: <phandle>
 
-                Note: Currently, all images are validated using "hash"
-                      method. In future, there may be multiple methods can
-                      be used to validate the image.
+                Note:
+
+                Currently, all images are validated using 'hash'
+                method. In future, there may be multiple methods can
+                be used to validate the image.
 
 Example:
 
 .. code:: c
 
-   images {
-         compatible = "arm, imgage-descriptors";
+   cot {
+      images {
+         compatible = "arm, img-descs";
 
          scp_bl2_image {
-               image-id = <SCP_BL2_IMAGE_ID>;
-               parent = <&scp_fw_content_cert>;
-               hash = <&scp_fw_hash>;
+            image-id = <SCP_BL2_IMAGE_ID>;
+            parent = <&scp_fw_content_cert>;
+            hash = <&scp_fw_hash>;
          };
 
          .
@@ -203,7 +237,9 @@
          .
 
          next-img {
+
          };
+      };
    };
 
 non-volatile counter node binding definition
@@ -226,8 +262,10 @@
 
                 Value type: <u32>
 
-                Definition: Must be set according to address size
-                            of non-volatile counter register
+                Definition:
+
+                Must be set according to address size
+                of non-volatile counter register
 
         - #size-cells
                 Usage: required
@@ -243,14 +281,18 @@
             PROPERTIES
 
                 - reg
-                    Usage: Register base address of non-volatile counter and it is required
-                           property.
+                    Usage:
+
+                    Register base address of non-volatile counter and it is required
+                    property.
 
                     Value type: <u32>
 
                 - oid
-                    Usage: This property provides the Object ID of non-volatile counter
-                           provided in the certificate and it is required property.
+                    Usage:
+
+                    This property provides the Object ID of non-volatile counter
+                    provided in the certificate and it is required property.
 
                     Value type: <string>
 
@@ -280,8 +322,7 @@
 Future update to chain of trust binding
 ---------------------------------------
 
-This binding document need to be revisited to generalise some terminologies
-like Object IDs, extensions etc which are currently specific to X.509
-certificates.
+This binding document needs to be revisited to generalise some terminologies
+which are currently specific to X.509 certificates for e.g. Object IDs.
 
-*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/docs/components/debugfs-design.rst b/docs/components/debugfs-design.rst
index 2096bdb..2536515 100644
--- a/docs/components/debugfs-design.rst
+++ b/docs/components/debugfs-design.rst
@@ -80,8 +80,8 @@
 The communication with the 9p layer in BL31 is made through an SMC conduit
 (`SMC Calling Convention`_), using a specific SiP Function Id. An NS
 shared buffer is used to pass path string parameters, or e.g. to exchange
-data on a read operation. Refer to `ARM SiP Services`_ for a description
-of the SMC interface.
+data on a read operation. Refer to :ref:`ARM SiP Services <arm sip services>`
+for a description of the SMC interface.
 
 Security considerations
 -----------------------
diff --git a/docs/components/exception-handling.rst b/docs/components/exception-handling.rst
index 4cca5f4..86ed87c 100644
--- a/docs/components/exception-handling.rst
+++ b/docs/components/exception-handling.rst
@@ -10,13 +10,9 @@
 -  Asynchronous External Aborts
 
 |TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is
-described in the `Firmware Design document`__. However, the |EHF| changes the
-semantics of `interrupt handling`__ and `synchronous exceptions`__ other than
-SMCs.
-
-.. __: firmware-design.rst#handling-an-smc
-.. __: `Interrupt handling`_
-.. __: `Effect on SMC calls`_
+described in the :ref:`Firmware Design document <handling-an-smc>`. However, the
+|EHF| changes the semantics of `Interrupt handling`_ and :ref:`synchronous
+exceptions <Effect on SMC calls>` other than SMCs.
 
 The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to
 ``1``, and is only available for AArch64 systems.
@@ -77,10 +73,9 @@
 independently depending on platform choice and the nature of the exception
 received.
 
-.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an
-   EL3 component that operates in EL3 on behalf of Secure OS.
-
-.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers
+.. [#spd] Not to be confused with :ref:`Secure Payload Dispatcher
+   <firmware_design_sel1_spd>`, which is an EL3 component that operates in EL3
+   on behalf of Secure OS.
 
 The role of Exception Handling Framework
 ----------------------------------------
@@ -139,6 +134,8 @@
 the case; for non-interrupts, the |EHF| monitors and asserts this. See
 `Transition of priority levels`_.
 
+.. _interrupt-handling:
+
 Interrupt handling
 ------------------
 
@@ -151,15 +148,12 @@
    sufficient priority are signalled as FIQs, and therefore will be routed to
    EL3. As a result, S-EL1 software cannot expect to handle Non-secure
    interrupts at S-EL1. Essentially, this deprecates the routing mode described
-   as `CSS=0, TEL3=0`__.
-
-   .. __: interrupt-framework-design.rst#el3-interrupts
+   as :ref:`CSS=0, TEL3=0 <EL3 interrupts>`.
 
    In order for S-EL1 software to handle Non-secure interrupts while having
    |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts
-   are received at EL3, but are then `synchronously`__ handled over to S-EL1.
-
-   .. __: interrupt-framework-design.rst#secure-payload
+   are received at EL3, but are then :ref:`synchronously <sp-synchronous-int>`
+   handled over to S-EL1.
 
 -  On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is
    set to ``1`` so that *Group 0* interrupts target EL3.
@@ -176,6 +170,8 @@
 
 Dispatchers are assigned interrupt priority levels in two steps:
 
+.. _Partitioning priority levels:
+
 Partitioning priority levels
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -281,15 +277,13 @@
    typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle,
                    void *cookie);
 
-The parameters are as obtained from the top-level `EL3 interrupt handler`__.
+The parameters are as obtained from the top-level :ref:`EL3 interrupt handler
+<el3-runtime-firmware>`.
 
-.. __: interrupt-framework-design.rst#el3-runtime-firmware
-
-The `SDEI dispatcher`__, for example, expects the platform to allocate two
-different priority levels—``PLAT_SDEI_CRITICAL_PRI``, and
-``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels.
-
-.. __: sdei.rst
+The :ref:`SDEI dispatcher<SDEI: Software Delegated Exception Interface>`, for
+example, expects the platform to allocate two different priority levels—
+``PLAT_SDEI_CRITICAL_PRI``, and ``PLAT_SDEI_NORMAL_PRI`` —and registers the
+same handler to handle both levels.
 
 Interrupt handling example
 --------------------------
@@ -365,16 +359,16 @@
 
 See also the `Build-time flow`_ and the `Run-time flow`_.
 
+.. _Activating and Deactivating priorities:
+
 Activating and Deactivating priorities
 --------------------------------------
 
 A priority level is said to be *active* when an exception of that priority is
 being handled: for interrupts, this is implied when the interrupt is
-acknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit
-dispatches`__, this has to be done via calling ``ehf_activate_priority()``. See
-`Run-time flow`_.
-
-.. __: sdei.rst#explicit-dispatch-of-events
+acknowledged; for non-interrupt exceptions, such as SErrors or :ref:`SDEI
+explicit dispatches <explicit-dispatch-of-events>`, this has to be done via
+calling ``ehf_activate_priority()``. See `Run-time flow`_.
 
 Conversely, when the dispatcher has reached a logical resolution for the cause
 of the exception, the corresponding priority level ought to be deactivated. As
@@ -453,6 +447,8 @@
 
 If these are violated, a panic will result.
 
+.. _Effect on SMC calls:
+
 Effect on SMC calls
 -------------------
 
@@ -538,10 +534,8 @@
    interrupts belonging to different dispatchers.
 
 #. The |EHF|, during its initialisation, registers a top-level interrupt handler
-   with the `Interrupt Management Framework`__ for EL3 interrupts. This also
-   results in setting the routing bits in ``SCR_EL3``.
-
-   .. __: interrupt-framework-design.rst#el3-runtime-firmware
+   with the :ref:`Interrupt Management Framework<el3-runtime-firmware>` for EL3
+   interrupts. This also results in setting the routing bits in ``SCR_EL3``.
 
 #. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0
    interrupt, and is taken to EL3.
diff --git a/docs/components/index.rst b/docs/components/index.rst
index 18b1e38..ffeef80 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -12,11 +12,13 @@
    exception-handling
    fconf/index
    firmware-update
+   measured_boot/index
    platform-interrupt-controller-API
    ras
    romlib-design
    sdei
-   secure-partition-manager-design
+   secure-partition-manager
+   secure-partition-manager-mm
    psa-ffa-manifest-binding
    xlat-tables-lib-v2-design
    cot-binding
diff --git a/docs/components/measured_boot/event_log.rst b/docs/components/measured_boot/event_log.rst
new file mode 100644
index 0000000..5347dcc
--- /dev/null
+++ b/docs/components/measured_boot/event_log.rst
@@ -0,0 +1,35 @@
+DTB binding for Event Log properties
+====================================
+
+This document describes the device tree format of Event Log properties.
+These properties are not related to a specific platform and can be queried
+from common code.
+
+Dynamic configuration for Event Log
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Measured Boot driver expects a *tpm_event_log* node with the following field
+in 'nt_fw_config' and 'tsp_fw_config' DTS files:
+
+- compatible [mandatory]
+   - value type: <string>
+   - Must be the string "arm,tpm_event_log".
+
+Then a list of properties representing Event Log configuration, which
+can be used by Measured Boot driver. Each property is named according
+to the information it contains:
+
+- tpm_event_log_sm_addr [fvp_nt_fw_config.dts with OP-TEE]
+    - value type: <u64>
+    - Event Log base address in secure memory.
+
+Note. Currently OP-TEE does not support reading DTBs from Secure memory
+and this property should be removed when this feature is supported.
+
+- tpm_event_log_addr [mandatory]
+    - value type: <u64>
+    - Event Log base address in non-secure memory.
+
+- tpm_event_log_size [mandatory]
+    - value type: <u32>
+    - Event Log size.
diff --git a/docs/components/measured_boot/index.rst b/docs/components/measured_boot/index.rst
new file mode 100644
index 0000000..e7f2634
--- /dev/null
+++ b/docs/components/measured_boot/index.rst
@@ -0,0 +1,12 @@
+Measured Boot Driver (MBD)
+==========================
+
+.. _measured-boot-document:
+
+Properties binding information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. toctree::
+   :maxdepth: 1
+
+   event_log
diff --git a/docs/components/platform-interrupt-controller-API.rst b/docs/components/platform-interrupt-controller-API.rst
index 9d02f45..069c87b 100644
--- a/docs/components/platform-interrupt-controller-API.rst
+++ b/docs/components/platform-interrupt-controller-API.rst
@@ -286,6 +286,8 @@
 *Priority Mask Register*, and make sure memory updates are visible before
 potential trigger due to mask update.
 
+.. _plat_ic_get_interrupt_id:
+
 Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/components/ras.rst b/docs/components/ras.rst
index 86529d7..02207d8 100644
--- a/docs/components/ras.rst
+++ b/docs/components/ras.rst
@@ -9,10 +9,8 @@
 paradigm for handling platform errors: exceptions resulting from errors are
 routed to and handled in EL3. Said errors are Synchronous External Abort (SEA),
 Asynchronous External Abort (signalled as SErrors), Fault Handling and Error
-Recovery interrupts.  The |EHF| document mentions various `error handling
-use-cases`__.
-
-.. __: exception-handling.rst#delegation-use-cases
+Recovery interrupts.  The |EHF| document mentions various :ref:`error handling
+use-cases <delegation-use-cases>` .
 
 For the description of Arm RAS extensions, Standard Error Records, and the
 precise definition of RAS terminology, please refer to the Arm Architecture
@@ -46,9 +44,7 @@
 
 The RAS framework allows the platform to define handlers for External Abort,
 Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please
-refer to the porting guide for the `RAS platform API descriptions`__.
-
-.. __: ../getting_started/porting-guide.rst#external-abort-handling-and-ras-support
+refer to :ref:`RAS Porting Guide <External Abort handling and RAS Support>`.
 
 Registering RAS error records
 -----------------------------
@@ -114,9 +110,8 @@
 
 The ``data`` constant parameter describes the various properties of the error,
 including the reason for the error, exception syndrome, and also ``flags``,
-``cookie``, and ``handle`` parameters from the `top-level exception handler`__.
-
-.. __: interrupt-framework-design.rst#el3-interrupts
+``cookie``, and ``handle`` parameters from the :ref:`top-level exception handler
+<EL3 interrupts>`.
 
 The platform is expected populate an array using the macros above, and register
 the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``,
@@ -229,21 +224,17 @@
 
 As mentioned in earlier sections, RAS framework interacts with the |EHF| to
 arbitrate handling of RAS exceptions with others that are routed to EL3. This
-means that the platform must partition a `priority level`__ for handling RAS
-exceptions. The platform must then define the macro ``PLAT_RAS_PRI`` to the
-priority level used for RAS exceptions. Platforms would typically want to
-allocate the highest secure priority for RAS handling.
+means that the platform must partition a :ref:`priority level <Partitioning
+priority levels>` for handling RAS exceptions. The platform must then define
+the macro ``PLAT_RAS_PRI`` to the priority level used for RAS exceptions.
+Platforms would typically want to allocate the highest secure priority for
+RAS handling.
 
-.. __: exception-handling.rst#partitioning-priority-levels
-
-Handling of both `interrupt`__ and `non-interrupt`__ exceptions follow the
-sequences outlined in the |EHF| documentation. I.e., for interrupts, the
-priority management is implicit; but for non-interrupt exceptions, they're
-explicit using `EHF APIs`__.
-
-.. __: exception-handling.rst#interrupt-flow
-.. __: exception-handling.rst#non-interrupt-flow
-.. __: exception-handling.rst#activating-and-deactivating-priorities
+Handling of both :ref:`interrupt <interrupt-flow>` and :ref:`non-interrupt
+<non-interrupt-flow>` exceptions follow the sequences outlined in the |EHF|
+documentation. I.e., for interrupts, the priority management is implicit; but
+for non-interrupt exceptions, they're explicit using :ref:`EHF APIs
+<Activating and Deactivating priorities>`.
 
 --------------
 
diff --git a/docs/components/sdei.rst b/docs/components/sdei.rst
index c5275a0..60259c8 100644
--- a/docs/components/sdei.rst
+++ b/docs/components/sdei.rst
@@ -205,6 +205,8 @@
 
 See the function ``sdei_client_el()`` in ``sdei_private.h``.
 
+.. _explicit-dispatch-of-events:
+
 Explicit dispatch of events
 ---------------------------
 
diff --git a/docs/components/secure-partition-manager-design.rst b/docs/components/secure-partition-manager-mm.rst
similarity index 97%
rename from docs/components/secure-partition-manager-design.rst
rename to docs/components/secure-partition-manager-mm.rst
index 4f67185..d532901 100644
--- a/docs/components/secure-partition-manager-design.rst
+++ b/docs/components/secure-partition-manager-mm.rst
@@ -1,5 +1,20 @@
-Secure Partition Manager
-************************
+Secure Partition Manager (MM)
+*****************************
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+-  SPM based on the PSA FF-A specification (:ref:`Secure Partition Manager`).
+-  SPM based on the MM interface.
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document describes the latter implementation where the Secure Partition Manager
+resides at EL3 and management services run from isolated Secure Partitions at S-EL0.
+The communication protocol is established through the Management Mode (MM) interface.
 
 Background
 ==========
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
new file mode 100644
index 0000000..e09da53
--- /dev/null
+++ b/docs/components/secure-partition-manager.rst
@@ -0,0 +1,865 @@
+Secure Partition Manager
+************************
+
+.. contents::
+
+Acronyms
+========
+
++--------+-----------------------------------+
+| DTB    | Device Tree Blob                  |
++--------+-----------------------------------+
+| DTS    | Device Tree Source                |
++--------+-----------------------------------+
+| EC     | Execution Context                 |
++--------+-----------------------------------+
+| FIP    | Firmware Image Package            |
++--------+-----------------------------------+
+| FF-A   | Firmware Framework for A-class    |
++--------+-----------------------------------+
+| IPA    | Intermediate Physical Address     |
++--------+-----------------------------------+
+| NWd    | Normal World                      |
++--------+-----------------------------------+
+| ODM    | Original Design Manufacturer      |
++--------+-----------------------------------+
+| OEM    | Original Equipment Manufacturer   |
++--------+-----------------------------------+
+| PA     | Physical Address                  |
++--------+-----------------------------------+
+| PE     | Processing Element                |
++--------+-----------------------------------+
+| PVM    | Primary VM                        |
++--------+-----------------------------------+
+| PSA    | Platform Security Architecture    |
++--------+-----------------------------------+
+| SP     | Secure Partition                  |
++--------+-----------------------------------+
+| SPM    | Secure Partition Manager          |
++--------+-----------------------------------+
+| SPMC   | SPM Core                          |
++--------+-----------------------------------+
+| SPMD   | SPM Dispatcher                    |
++--------+-----------------------------------+
+| SiP    | Silicon Provider                  |
++--------+-----------------------------------+
+| SWd    | Secure World                      |
++--------+-----------------------------------+
+| TLV    | Tag-Length-Value                  |
++--------+-----------------------------------+
+| TOS    | Trusted Operating System          |
++--------+-----------------------------------+
+| VM     | Virtual Machine                   |
++--------+-----------------------------------+
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+-  SPM based on the PSA FF-A specification `[1]`_.
+-  SPM based on the MM interface to communicate with an S-EL0 partition `[2]`_.
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document:
+
+-  describes the PSA FF-A implementation where the Secure Partition Manager
+   resides at EL3 and S-EL2 (or EL3 and S-EL1).
+-  is not an architecture specification and it might provide assumptions
+   on sections mandated as implementation-defined in the specification.
+-  covers the implications to TF-A used as a bootloader, and Hafnium
+   used as a reference code base for an S-EL2 secure firmware on
+   platforms implementing Armv8.4-SecEL2.
+
+Terminology
+-----------
+
+-  Hypervisor refers to the NS-EL2 component managing Virtual Machines (or
+   partitions) in the Normal World.
+-  SPMC refers to the S-EL2 component managing Virtual Machines (or Secure
+   Partitions) in the Secure World when Armv8.4-SecEL2 extension is implemented.
+-  Alternatively, SPMC can refer to an S-EL1 component, itself being a Secure
+   Partition and implementing the FF-A ABI on pre-Armv8.4 platforms.
+-  VM refers to a Normal World Virtual Machine managed by an Hypervisor.
+-  SP refers to a Secure World "Virtual Machine" managed by the SPMC component.
+
+Support for legacy platforms
+----------------------------
+
+In the implementation, the SPM is split into SPMD and SPMC components
+(although not strictly mandated by the specification). SPMD is located
+at EL3 and principally relays FF-A messages from NWd (Hypervisor or OS
+kernel) to SPMC located either at S-EL1 or S-EL2.
+
+Hence TF-A must support both cases where SPMC is either located at:
+
+-  S-EL1 supporting pre-Armv8.4 platforms. SPMD conveys FF-A protocol
+   from EL3 to S-EL1.
+-  S-EL2 supporting platforms implementing Armv8.4-SecEL2 extension.
+   SPMD conveys FF-A protocol from EL3 to S-EL2.
+
+The same SPMD component is used to support both configurations. The SPMC
+execution level is a build time choice.
+
+Sample reference stack
+======================
+
+The following diagram illustrates a possible configuration with SPMD and SPMC,
+one or multiple Secure Partitions, with or without an optional Hypervisor:
+
+.. image:: ../resources/diagrams/ff-a-spm-sel2.png
+
+TF-A build options
+==================
+
+The following TF-A build options are provisioned:
+
+-  **SPD=spmd**: this option selects the SPMD component to relay FF-A
+   protocol from NWd to SWd back and forth. It is not possible to
+   enable another Secure Payload Dispatcher when this option is chosen.
+-  **SPMD_SPM_AT_SEL2**: this option adjusts the SPMC execution
+   level to being S-EL1 or S-EL2. It defaults to enabled (value 1) when
+   SPD=spmd is chosen.
+-  **CTX_INCLUDE_EL2_REGS**: this option permits saving (resp.
+   restoring) the EL2 system register context before entering (resp.
+   after leaving) the SPMC. It is mandatory when ``SPMD_SPM_AT_SEL2`` is
+   enabled. The context save/restore routine and exhaustive list of
+   registers is visible at `[4] <#References>`__.
+-  **SP_LAYOUT_FILE**: this option provides a text description file
+   providing paths to SP binary images and DTS format manifests
+   (see `Specifying partition binary image and DT`_). It
+   is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
+   secure partitions are to be loaded on behalf of SPMC.
+
++------------------------------+----------------------+------------------+
+|                              | CTX_INCLUDE_EL2_REGS | SPMD_SPM_AT_SEL2 |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL1 (e.g. OP-TEE)  |           0          |        0         |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL2 (e.g. Hafnium) |           1          | 1 (default when  |
+|                              |                      |    SPD=spmd)     |
++------------------------------+----------------------+------------------+
+
+Other combinations of such build options either break the build or are not
+supported.
+
+Note, the ``CTX_INCLUDE_EL2_REGS`` option provides the generic support for
+barely saving/restoring EL2 registers from an Arm arch perspective. As such
+it is decoupled from the ``SPD=spmd`` option.
+
+BL32 option is re-purposed to specify the SPMC image. It can specify either the
+Hafnium binary path (built for the secure world) or the path to a TEE binary
+implementing the FF-A protocol.
+
+BL33 option can specify either:
+
+-  the TFTF binary or
+-  the Hafnium binary path (built for the normal world) if VMs were loaded by
+   TF-A beforehand or
+-  a minimal loader performing the loading of VMs and Hafnium.
+
+Sample TF-A build command line when SPMC is located at S-EL1
+(typically pre-Armv8.4):
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    SPMD_SPM_AT_SEL2=0 \
+    BL32=<path-to-tee-binary> \
+    BL33=<path-to-nwd-binary> \
+    PLAT=fvp \
+    all fip
+
+Sample TF-A build command line for an Armv8.4-SecEL2 enabled system
+where SPMC is located at S-EL2:
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    CTX_INCLUDE_EL2_REGS=1 \
+    ARM_ARCH_MINOR=4 \
+    BL32=<path-to-swd-hafnium-binary>
+    BL33=<path-to-nwd-binary> \
+    SP_LAYOUT_FILE=sp_layout.json \
+    PLAT=fvp \
+    all fip
+
+Build options to enable secure boot:
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    CTX_INCLUDE_EL2_REGS=1 \
+    ARM_ARCH_MINOR=4 \
+    BL32=<path-to-swd-hafnium-binary>
+    BL33=<path-to-nwd-binary> \
+    SP_LAYOUT_FILE=../tf-a-tests/build/fvp/debug/sp_layout.json \
+    MBEDTLS_DIR=<path-to-mbedtls-lib> \
+    TRUSTED_BOARD_BOOT=1 \
+    COT=dualroot \
+    ARM_ROTPK_LOCATION=devel_rsa \
+    ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
+    GENERATE_COT=1 \
+    PLAT=fvp \
+    all fip
+
+Boot process
+============
+
+Loading Hafnium and Secure Partitions in the secure world
+---------------------------------------------------------
+
+The Hafnium implementation in normal world requires VMs to be loaded in
+memory prior to booting. The mechanism upon which VMs are loaded and
+exposed to Hafnium are either:
+
+-  by supplying a ramdisk image where VM images are concatenated (1)
+-  or by providing VM load addresses within Hafnium manifest (2)
+
+TF-A is the bootlader for the Hafnium and SPs in the secure world. TF-A
+does not provide tooling or libraries manipulating ramdisks as required
+by (1). Thus BL2 loads SPs payloads independently.
+SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
+Thus they are supplied as distinct “self-contained” signed entities within
+the FIP flash image. The FIP image itself is not signed hence providing
+ability to upgrade SPs in the field.
+
+Booting through TF-A
+--------------------
+
+SP manifests
+~~~~~~~~~~~~
+
+An SP manifest describes SP attributes as defined in `[1]`_
+section 3.1 (partition manifest at virtual FF-A instance) in DTS text format. It
+is represented as a single file associated with the SP. A sample is
+provided by `[5]`_. A binding document is provided by `[6]`_.
+
+Secure Partition packages
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Secure Partitions are bundled as independent package files consisting
+of:
+
+-  a header
+-  a DTB
+-  an image payload
+
+The header starts with a magic value and offset values to SP DTB and
+image payload. Each SP package is loaded independently by BL2 loader
+and verified for authenticity and integrity.
+
+The SP package identified by its UUID (matching FF-A uuid) is inserted
+as a single entry into the FIP at end of the TF-A build flow as shown:
+
+.. code:: shell
+
+    Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw"
+    EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw"
+    Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw"
+    Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw"
+    HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config"
+    TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config"
+    SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config"
+    TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config"
+    NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config"
+    B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob"
+    D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob"
+
+.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml
+
+Specifying partition binary image and DT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A description file (json format) is passed to the build flow specifying
+paths to the SP binary image and associated DTS partition manifest file.
+The latter is going through the dtc compiler to generate the dtb fed into
+the SP package.
+
+.. code:: shell
+
+    {
+        "tee1" : {
+            "image": "tee1.bin",
+             "pm": "tee1.dts"
+        },
+
+        "tee2" : {
+            "image": "tee2.bin",
+            "pm": "tee2.dts"
+        }
+    }
+
+SPMC manifest
+~~~~~~~~~~~~~
+
+This manifest contains an SPMC attributes node consumed by SPMD at boot time. It
+is implementing the description from `[1]`_ section 3.2 (SP manifest at physical
+FF-A instance). The SP manifest at physical FF-A instance is used by the SPMD to
+setup a SP that co-resides with the SPMC and executes at S-EL1 or Secure
+Supervisor mode.
+
+In this implementation its usage is extended to the secure physical FF-A
+instance where SPMC executes at S-EL2.
+
+.. code:: shell
+
+    attribute {
+        spmc_id = <0x8000>;
+        maj_ver = <0x1>;
+        min_ver = <0x0>;
+        exec_state = <0x0>;
+        load_address = <0x0 0x6000000>;
+        entrypoint = <0x0 0x6000000>;
+        binary_size = <0x60000>;
+    };
+
+-  *spmc_id* defines the endpoint ID value that SPMC can query through
+   ``FFA_ID_GET``.
+-  *maj_ver/min_ver*. SPMD checks provided version versus its internal
+   version and aborts if not matching.
+-  *exec_state* defines SPMC execution state (can be AArch64 for
+   Hafnium, or AArch64/AArch32 for OP-TEE at S-EL1).
+-  *load_address* and *binary_size* are mostly used to verify secondary
+   entry points fit into the loaded binary image.
+-  *entrypoint* defines the cold boot primary core entry point used by
+   SPMD (currently matches ``BL32_BASE``)
+
+Other nodes in the manifest are consumed by Hafnium in the secure world.
+A sample can be found at [7]:
+
+-  The *chosen* node is currently unused in SWd. It is meant for NWd to
+   specify the init ramdisk image.
+-  The *hypervisor* node describes SPs. *is_ffa_partition* boolean
+   attribute indicates an SP. Load-addr field specifies the load address
+   at which TF-A loaded the SP package.
+-  *cpus* node provide the platform topology and allows MPIDR to VMPIDR
+   mapping. Notice with current implementation primary cpu is declared
+   first, then secondary cpus must be declared in reverse order.
+
+SPMC boot
+~~~~~~~~~
+
+The SPMC is loaded by BL2 as the BL32 image.
+
+The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image.
+
+BL2 passes the SPMC manifest address to BL31 through a register.
+
+BL31(SPMD) runs from primary core, initializes the core contexts and
+launches BL32 passing the SPMC manifest address through a register.
+
+Loading of SPs
+~~~~~~~~~~~~~~
+
+.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
+
+
+Notice this boot flow is an implementation sample on Arm's FVP platform. Platforms
+not using FW_CONFIG would adjust to a different implementation.
+
+Secure boot
+~~~~~~~~~~~
+
+The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
+SPMC manifest and Secure Partitions and verifies them for authenticity and integrity.
+Refer to TBBR specification `[3]`_.
+
+The multiple-signing domain feature (in current state dual signing domain) allows
+the use of two root keys namely S-ROTPK and NS-ROTPK (see `[8]`_):
+
+-  SPMC(BL32), SPMC manifest, SPs may be signed by the SiP using the S-ROTPK.
+-  BL33 may be signed by the OEM using NS-ROTPK.
+
+Longer term multiple signing domain will allow additional signing keys, e.g.
+if SPs originate from different parties.
+
+See `TF-A build options`_ for a sample build command line.
+
+Hafnium in the secure world
+===========================
+
+**NOTE: this section is work in progress. Descriptions and implementation choices
+are subject to evolve.**
+
+General considerations
+----------------------
+
+Build platform for the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The implementation might add specific code parts only relevant to the
+secure world. Such code parts might be isolated into different files
+and/or conditional code enclosed by a ``SECURE_WORLD`` macro.
+
+Secure Partitions CPU scheduling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the normal world, VMs are scheduled by the FFA_RUN ABI invoked from the
+primary scheduler (in the primary VM), or by a direct message request or
+response.
+
+With the FF-A EAC specification, Secure Partitions are scheduled by direct
+message invocations from a NWd VM or another SP.
+
+Platform topology
+~~~~~~~~~~~~~~~~~
+
+As stated in `[1]`_ section 4.4.1 the SPMC implementation assumes the
+following SP types:
+
+-  Pinned MP SPs: an Execution Context id matches a physical PE id. MP
+   SPs must implement the same number of ECs as the number of PEs in the
+   platform. Hence the *execution-ctx-count* as defined by
+   `[1]`_ (or NWd-Hafnium *vcpu_count*) can only take the
+   value of one or the number of physical PEs.
+-  Migratable UP SPs: a single execution context can run and be migrated
+   on any physical PE. It declares a single EC in its SP manifest. An UP
+   SP can receive a direct message request on any physical core.
+
+Usage of PSCI services in the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The normal world Hypervisor (optional) or OS kernel issues PSCI service
+  invocations e.g. to request PSCI version, wake-up a secondary core, or request
+  core suspend. This happens at the non-secure physical FF-A instance. In the
+  example case of Hafnium in the normal world, it boots on the primary core and
+  one of the first initialization step is to request the PSCI version. It then
+  launches the primary VM. The primary VM upon initializing performs PSCI service
+  calls (at non-secure virtual FF-A instance) which are trapped by the
+  Hypervisor. Invocation from OS Kernel ends straight at EL3. The PVM issues
+  ``PSCI_CPU_ON`` service calls to wake-up secondary cores by passing an
+  ``MPIDR``, entry point address and a CPU context address. The EL3 PSCI layer
+  then performs an exception return to the secondary core entry point on the
+  targeted core. Other PSCI calls can happen at run-time from the PVM e.g. to
+  request core suspend.
+- In the existing TF-A PSCI standard library, PSCI service calls are filtered at
+  EL3 to only originate from the NWd. Thus concerning the SPMC (at secure
+  physical FF-A instance) the PSCI service invocations cannot happen as in the
+  normal world. For example, a ``PSCI_CPU_ON`` service invocation from the SPMC
+  does not reach the PSCI layer.
+
+Parsing SP partition manifests
+------------------------------
+
+Hafnium must be able to consume SP manifests as defined in
+`[1]`_ section 3.1, at least for the mandatory fields.
+
+The SP manifest may contain memory and device regions nodes.
+
+-  Memory regions shall be mapped in the SP Stage-2 translation regime at
+   load time. A memory region node can specify RX/TX buffer regions in which
+   case it is not necessary for an SP to explicitly call the ``FFA_RXTX_MAP``
+   service.
+-  Device regions shall be mapped in SP Stage-2 translation regime as
+   peripherals and possibly allocate additional resources (e.g. interrupts)
+
+Base addresses for memory and device region nodes are IPAs provided SPMC
+identity maps IPAs to PAs within SP Stage-2 translation regime.
+
+Note: currently both VTTBR_EL2 and VSTTBR_EL2 resolve to the same set of page
+tables. It is still open whether two sets of page tables shall be provided per
+SP. The memory region node as defined in the spec (section 3.1 Table 10)
+provides a memory security attribute hinting to map either to the secure or
+non-secure stage-2 table.
+
+Passing boot data to the SP
+---------------------------
+
+`[1]`_ Section 3.4.2 “Protocol for passing data” defines a
+method to passing boot data to SPs (not currently implemented).
+
+Provided that the whole Secure Partition package image (see `Secure
+Partition packages`_) is mapped to the SP's secure Stage-2 translation
+regime, an SP can access its own manifest DTB blob and extract its partition
+manifest properties.
+
+SP Boot order
+-------------
+
+SP manifests provide an optional boot order attribute meant to resolve
+dependencies such as an SP providing a service required to properly boot
+another SP.
+
+Boot phases
+-----------
+
+Primary core boot-up
+~~~~~~~~~~~~~~~~~~~~
+
+The SPMC performs its platform initializations then loads and creates
+secure partitions based on SP packages and manifests. Then each secure
+partition is launched in sequence (see `SP Boot order`_) on their primary
+Execution Context.
+
+Notice the primary physical core may not be core 0. Hence if the primary
+core linear id is N, the 1:1 mapping requires MP SPs are launched using
+EC[N] on PE[N] (see `Platform topology`_).
+
+The SP's primary Execution Context (or the EC used when the partition is booted)
+exits through ``FFA_MSG_WAIT`` to indicate successful initialization.
+
+Secondary physical core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Upon boot-up, the SPMC running on the primary core performs
+implementation-defined SPMD service calls at secure physical FF-A instance
+to register the secondary physical cores entry points and context information:
+
+-  This is done through a direct message request invocation to the SPMD
+   (``SET_ENTRY_POINT``). This service call does not wake-up the targeted
+   core immediately. The secondary core is woken up later by a NWd
+   ``PSCI_CPU_ON`` service invocation. A notification is passed from EL3
+   PSCI layer to the SPMD, and then to SPMC through an implementation-defined
+   interface.
+-  The SPMC/SPMD interface can consist of FF-A direct message requests/responses
+   transporting PM events.
+
+If there is no Hypervisor in the normal world, the OS Kernel issues
+``PSCI_CPU_ON`` calls that are directly trapped to EL3.
+
+When a secondary physical core wakes-up the SPMD notifies the SPMC which updates
+its internal states reflecting current physical core is being turned on.
+It might then return straight to the SPMD and then to the NWd.
+
+*(under discussion)* There may be possibility that an SP registers "PM events"
+(during primary EC boot stage) through an ad-hoc interface. Such events would
+be relayed by SPMC to one or more registered SPs on need basis
+(see `Power management`_).
+
+Secondary virtual core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the example case where Hafnium exists in the normal world, secondary VMs
+issue a ``PSCI_CPU_ON`` service call which is trapped to the Hypervisor. The
+latter then enables the vCPU context for the targeted core, and switches to
+the PVM down to the kernel driver with an ``HF_WAKE_UP`` message. The NWd
+driver in PVM can then schedule the newly woken up vCPU context.
+
+In the secure world the primary EC of a given SP passes the secondary EC entry
+point and context. The SMC service call is trapped into the SPMC. This can be
+either *(under discussion)*:
+
+-  a specific interface registering the secondary EC entry point,
+   similarly to above ``SET_ENTRY_POINT`` service.
+-  Re-purposing the ``PSCI_CPU_ON`` function id. It is
+   assumed that even if the input arguments are the same as the ones defined in
+   the PSCI standard, the usage deviates by the fact the secondary EC is not
+   woken up immediately. At least for the PSA-FF-A EAC where only
+   direct messaging is allowed, it is only after the first direct
+   message invocation that the secondary EC is entered. This option
+   might be preferred when the same code base is re-used for a VM or
+   an SP. The ABI to wake-up a secondary EC can remain similar.
+
+SPs are always scheduled from the NWd, this paradigm did not change from legacy
+TEEs. There must always be some logic (or driver) in the NWd to relinquish CPU
+cycles to the SWd. If primary core is 0, an SP EC[x>0] entry point is supplied
+by the SP EC[0] when the system boots in SWd. But this EC[x] is not immediately
+entered at boot. Later in the boot process when NWd is up, a direct message
+request issued from physical core 1 ends up in SP EC[1], and only at this stage
+this context is effectively scheduled.
+
+It should be possible for an SP to call into another SP through direct message
+provided the latter SP has been booted already. The "boot-order" field in
+partition manifests (`SP Boot order`_) fulfills the dependency towards availability
+of a service within an SP offered to another SP.
+
+Mandatory interfaces
+--------------------
+
+The following interfaces must be exposed to any VM or SP:
+
+-  ``FFA_STATUS``
+-  ``FFA_ERROR``
+-  ``FFA_INTERRUPT``
+-  ``FFA_VERSION``
+-  ``FFA_FEATURES``
+-  ``FFA_RX_RELEASE``
+-  ``FFA_RXTX_MAP``
+-  ``FFA_RXTX_UNMAP``
+-  ``FFA_PARTITION_INFO_GET``
+-  ``FFA_ID_GET``
+
+FFA_VERSION
+~~~~~~~~~~~
+
+Per `[1]`_ section 8.1 ``FFA_VERSION`` requires a
+*requested_version* parameter from the caller.
+
+In the current implementation when ``FFA_VERSION`` is invoked from:
+
+-  Hypervisor in NS-EL2: the SPMD returns the SPMC version specified
+   in the SPMC manifest.
+-  OS kernel in NS-EL1 when NS-EL2 is not present: the SPMD returns the
+   SPMC version specified in the SPMC manifest.
+-  VM in NWd: the Hypervisor returns its implemented version.
+-  SP in SWd: the SPMC returns its implemented version.
+-  SPMC at S-EL1/S-EL2: the SPMD returns its implemented version.
+
+FFA_FEATURES
+~~~~~~~~~~~~
+
+FF-A features may be discovered by Secure Partitions while booting
+through the SPMC. However, SPMC cannot get features from Hypervisor
+early at boot time as NS world is not setup yet.
+
+The Hypervisor may decide to gather FF-A features from SPMC through SPMD
+once at boot time and store the result. Later when a VM requests FF-A
+features, the Hypervisor can adjust its own set of features with what
+SPMC advertised, if necessary. Another approach is to always forward FF-A
+features to the SPMC when a VM requests it to the Hypervisor. Although
+the result is not supposed to change over time so there may not be added
+value doing the systematic forwarding.
+
+FFA_RXTX_MAP/FFA_RXTX_UNMAP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+VM mailboxes are re-purposed to serve as SP RX/TX buffers. The RX/TX
+map API maps the send and receive buffer IPAs to the SP Stage-2 translation regime.
+
+Hafnium in the normal world defines VMs and their attributes as logical structures,
+including a mailbox used for FF-A indirect messaging, memory sharing, or the
+`FFA_PARTITION_INFO_GET`_  ABI.
+This same mailbox structure is re-used in the SPMC. `[1]`_ states only direct
+messaging is allowed to SPs. Thus mailbox usage is restricted to implementing
+`FFA_PARTITION_INFO_GET`_ and memory sharing ABIs.
+
+FFA_PARTITION_INFO_GET
+~~~~~~~~~~~~~~~~~~~~~~
+
+Partition info get service call can originate:
+
+-  from SP to SPM
+-  from VM to Hypervisor
+-  from Hypervisor to SPM
+
+For the latter case, the service call must be forwarded through the SPMD.
+
+FFA_ID_GET
+~~~~~~~~~~
+
+The SPMD returns:
+
+-  a default zero value on invocation from the Hypervisor.
+-  The ``spmc_id`` value specified in the SPMC manifest on invocation from
+   the SPMC (see `SPMC manifest`_)
+
+The FF-A id space is split into a non-secure space and secure space:
+
+-  FF-A id with bit 15 clear refer to normal world VMs.
+-  FF-A id with bit 15 set refer to secure world SPs
+
+Such convention helps the SPMC discriminating the origin and destination worlds
+in an FF-A service invocation. In particular the SPMC shall filter unauthorized
+transactions in its world switch routine. It must not be permitted for a VM to
+use a secure FF-A id as origin world through spoofing:
+
+-  A VM-to-SP messaging passing shall have an origin world being non-secure
+   (FF-A id bit 15 clear) and destination world being secure (FF-A id bit 15
+   set).
+-  Similarly, an SP-to-SP message shall have FF-A id bit 15 set for both origin
+   and destination ids.
+
+An incoming direct message request arriving at SPMD from NWd is forwarded to
+SPMC without a specific check. The SPMC is resumed through eret and "knows" the
+message is coming from normal world in this specific code path. Thus the origin
+endpoint id must be checked by SPMC for being a normal world id.
+
+An SP sending a direct message request must have bit 15 set in its origin
+endpoint id and this can be checked by the SPMC when the SP invokes the ABI.
+
+The SPMC shall reject the direct message if the claimed world in origin endpoint
+id is not consistent:
+
+-  It is either forwarded by SPMD and thus origin endpoint id must be a "normal
+   world id",
+-  or initiated by an SP and thus origin endpoint id must be a "secure world id".
+
+Direct messaging
+----------------
+
+This is a mandatory interface for Secure Partitions consisting in direct
+message request and responses.
+
+The ``ffa_handler`` Hafnium function may:
+
+-  trigger a world change e.g. when an SP invokes the direct message
+   response ABI to a VM.
+-  handle multiple requests from the NWd without resuming an SP.
+
+SP-to-SP
+~~~~~~~~
+
+-  An SP can send a direct message request to another SP
+-  An SP can receive a direct message response from another SP.
+
+VM-to-SP
+~~~~~~~~
+
+-  A VM can send a direct message request to an SP
+-  An SP can send a direct message response to a VM
+
+SPMC-SPMD messaging
+~~~~~~~~~~~~~~~~~~~
+
+Specific implementation-defined endpoint IDs are allocated to the SPMC and SPMD.
+Referring those IDs in source/destination fields of a direct message
+request/response permits SPMD to SPMC messaging back and forth.
+
+Per `[1]`_ Table 114 Config No. 1 (physical FF-A instance):
+
+-  SPMC=>SPMD direct message request uses SMC conduit
+-  SPMD=>SPMC direct message request uses ERET conduit
+
+Per `[1]`_ Table 118 Config No. 1 (physical FF-A instance):
+
+-  SPMC=>SPMD direct message response uses SMC conduit
+-  SPMD=>SPMC direct message response uses ERET conduit
+
+Memory management
+-----------------
+
+This section only deals with the PE MMU configuration.
+
+Hafnium in the normal world deals with NS buffers only and provisions
+a single root page table directory to VMs. In context of S-EL2 enabled
+firmware, two IPA spaces are output from Stage-1 translation (secure
+and non-secure). The Stage-2 translation handles:
+
+-  A single secure IPA space when an SP Stage-1 MMU is disabled.
+-  Two IPA spaces (secure and non-secure) when Stage-1 MMU is enabled.
+
+``VTCR_EL2`` and ``VSTCR_EL2`` provide additional bits for controlling the
+NS/S IPA translations (``VSTCR_EL2.SW``, ``VSTCR_EL2.SA``, ``VTCR_EL2.NSW``,
+``VTCR_EL2.NSA``). There may be two approaches:
+
+-  secure and non-secure mappings are rooted as two separate root page
+   tables
+-  secure and non-secure mappings use the same root page table. Access
+   from S-EL1 to an NS region translates to a secure physical address
+   space access.
+
+Interrupt management
+--------------------
+
+Road to a para-virtualized interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Current Hafnium implementation uses an ad-hoc mechanism for a VM to get
+a pending interrupt number through an hypercall. The PVM injects
+interrupts to VMs by delegation from the Hypervisor. The PVM probes a
+pending interrupt directly from the GIC distributor.
+
+The short-term plan is to have Hafnium/SPMC in the secure world owner
+of the GIC configuration.
+
+The SPMC fully owns the GIC configuration at S-EL2. The SPMC manages
+interrupt resources and allocates interrupt ID based on SP manifests.
+The SPMC acknowledges physical interrupts and injects virtual interrupts
+by setting the vIRQ bit when resuming an SP. A Secure Partition gathers
+the interrupt number through an hypercall.
+
+Notice the SPMC/SPMD has to handle Group0 secure interrupts in addition
+to Group1 S/NS interrupts.
+
+Power management
+----------------
+
+Assumption on the Nwd:
+
+-  NWd is the best candidate to own the platform Power Management
+   policy. It is master to invoking PSCI service calls from physical
+   CPUs.
+-  EL3 monitor is in charge of the PM control part (its PSCI layer
+   actually writing to platform registers).
+-  It is fine for the Hypervisor to trap PSCI calls and relay to EL3, or
+   OS kernel driver to emit PSCI service calls.
+
+PSCI notification are relayed through the SPMD/SPD PM hooks to the SPMC.
+This can either be through re-use of PSCI FIDs or an FF-A direct message
+from SPMD to SPMC.
+
+The SPMD performs an exception return to the SPMC which is resumed to
+its ``eret_handler`` routine. It is then either consuming a PSCI FID or
+an FF-A FID. Depending on the servicing, the SPMC may return directly to
+the SPMD (and then NWd) without resuming an SP at this stage. An example
+of this is invocation of ``FFA_PARTITION_INFO_GET`` from NWd relayed by
+the SPMD to the SPMC. The SPMC returns the needed partition information
+to the SPMD (then NWd) without actually resuming a partition in secure world.
+
+*(under discussion)*
+About using PSCI FIDs from SPMD to SPMC to notify of PM events, it is still
+questioned what to use as the return code from the SPMC.
+If the function ID used by the SPMC is not an FF-A ID when doing SMC, then the
+EL3 std svc handler won't route the response to the SPMD. That's where comes the
+idea to embed the notification into an FF-A message. The SPMC can discriminate
+this message as being a PSCI event, process it, and reply with an FF-A return
+message that the SPMD receives as an acknowledgement.
+
+SP notification
+---------------
+
+Power management notifications are conveyed from PSCI library to the
+SPMD / SPD hooks. A range of events can be relayed to SPMC.
+
+SPs may need to be notified about specific PM events.
+
+-  SPs might register PM events to the SPMC
+-  On SPMD to SPMC notification, a limited range of SPs may be notified
+   through a direct message.
+-  This assumes the mentioned SPs supports managed exit.
+
+The SPMC is the first to be notified about PM events from the SPMD. It is up
+to the SPMC to arbitrate to which SP it needs to send PM events.
+An SP explicitly registers to receive notifications to specific PM events.
+The register operation can either be an implementation-defined service call
+to the SPMC when the primary SP EC boots, or be supplied through the SP
+manifest.
+
+References
+==========
+
+.. _[1]:
+
+[1] `Platform Security Architecture Firmware Framework for Arm® v8-A 1.0 Platform Design Document <https://developer.arm.com/docs/den0077/latest>`__
+
+.. _[2]:
+
+[2] :ref:`Secure Partition Manager using MM interface<Secure Partition Manager (MM)>`
+
+.. _[3]:
+
+[3] `Trusted Boot Board Requirements
+Client <https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a>`__
+
+.. _[4]:
+
+[4] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime/aarch64/context.S#n45
+
+.. _[5]:
+
+[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/cactus.dts
+
+.. _[6]:
+
+[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/psa-ffa-manifest-binding.html
+
+.. _[7]:
+
+[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+
+.. _[8]:
+
+[8] https://developer.trustedfirmware.org/w/tf_a/poc-multiple-signing-domains/
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 891a9a2..a357d58 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -957,6 +957,8 @@
 
 |Image 1|
 
+.. _handling-an-smc:
+
 Handling an SMC
 ~~~~~~~~~~~~~~~
 
@@ -988,7 +990,7 @@
 Exception Handling Framework
 ----------------------------
 
-Please refer to the `Exception Handling Framework`_ document.
+Please refer to the :ref:`Exception Handling Framework` document.
 
 Power State Coordination Interface
 ----------------------------------
@@ -1300,6 +1302,8 @@
 already been performed and act as appropriate. Possible courses of actions are,
 e.g. skip the action the second time, or undo/redo it.
 
+.. _configuring-secure-interrupts:
+
 Configuring secure interrupts
 -----------------------------
 
diff --git a/docs/design/interrupt-framework-design.rst b/docs/design/interrupt-framework-design.rst
index 14f7227..dfb2eac 100644
--- a/docs/design/interrupt-framework-design.rst
+++ b/docs/design/interrupt-framework-design.rst
@@ -138,6 +138,8 @@
    reason to route the interrupt to EL3 software and then hand it back to
    non-secure software for handling.
 
+.. _EL3 interrupts:
+
 EL3 interrupts
 ^^^^^^^^^^^^^^
 
@@ -148,10 +150,8 @@
 
    However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is
    invalid as EL3 interrupts are unconditionally routed to EL3, and EL3
-   interrupts will always preempt Secure EL1/EL0 execution. See `exception
-   handling`__ documentation.
-
-   .. __: exception-handling.rst#interrupt-handling
+   interrupts will always preempt Secure EL1/EL0 execution. See :ref:`exception
+   handling<interrupt-handling>` documentation.
 
 #. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in
    Secure-EL1/Secure-EL0. This is a valid routing model as secure software
@@ -301,6 +301,8 @@
 `Software components`_) during the registration of a handler for an interrupt
 type.
 
+.. _el3-runtime-firmware:
+
 EL3 runtime firmware
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -899,14 +901,14 @@
 
 |Image 2|
 
-Secure payload
-~~~~~~~~~~~~~~
+.. _sp-synchronous-int:
+
+Secure payload interrupt handling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The SP should implement one or both of the synchronous and asynchronous
 interrupt handling models depending upon the interrupt routing model it has
-chosen (as described in section `Secure Payload`__).
-
-.. __: #sp-int-registration
+chosen (as described in section :ref:`Secure Payload <sp-int-registration>`).
 
 In the synchronous model, it should begin handling a Secure-EL1 interrupt after
 receiving control from the SPD service at an entrypoint agreed upon during build
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 81903e1..b15ea1b 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -346,16 +346,14 @@
 -  ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have
    inherent support for specific EL3 type interrupts. Setting this build option
    to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both
-   by `platform abstraction layer`__ and `Interrupt Management Framework`__.
+   by :ref:`platform abstraction layer<platform Interrupt Controller API>` and
+   :ref:`Interrupt Management Framework<Interrupt Management Framework>`.
    This allows GICv2 platforms to enable features requiring EL3 interrupt type.
    This also means that all GICv2 Group 0 interrupts are delivered to EL3, and
    the Secure Payload interrupts needs to be synchronously handed over to Secure
    EL1 for handling. The default value of this option is ``0``, which means the
    Group 0 interrupts are assumed to be handled by Secure EL1.
 
-   .. __: platform-interrupt-controller-API.rst
-   .. __: interrupt-framework-design.rst
-
 -  ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError
    Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to
    ``0`` (default), these exceptions will be trapped in the current exception
@@ -648,6 +646,13 @@
    configuration device tree, instead of static structure in the code base.
    This is currently an experimental feature.
 
+-  ``COT_DESC_IN_DTB``: This flag determines whether to create COT descriptors
+   at runtime using fconf. If this flag is enabled, COT descriptors are
+   statically captured in tb_fw_config file in the form of device tree nodes
+   and properties. Currently, COT descriptors used by BL2 are moved to the
+   device tree and COT descriptors used by BL1 are retained in the code
+   base statically. This is currently an experimental feature.
+
 -  ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in
    runtime using firmware configuration framework. The platform specific SDEI
    shared and private events configuration is retrieved from device tree rather
@@ -714,6 +719,10 @@
   bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs.
   This flag is disabled by default.
 
+- ``OPENSSL_DIR``: This flag is used to provide the installed openssl directory
+  path on the host machine which is used to build certificate generation and
+  firmware encryption tool.
+
 GICv3 driver options
 --------------------
 
diff --git a/docs/getting_started/docs-build.rst b/docs/getting_started/docs-build.rst
index 91b1b3a..87c677f 100644
--- a/docs/getting_started/docs-build.rst
+++ b/docs/getting_started/docs-build.rst
@@ -67,7 +67,7 @@
 
 ::
 
-   docs/build/html/
+   docs/build/html
 
 We also support building documentation in other formats. From the ``docs``
 directory of the project, run the following command to see the supported
@@ -79,6 +79,31 @@
 
    make help
 
+Building rendered documentation from a container
+------------------------------------------------
+
+There may be cases where you can not either install or upgrade required
+dependencies to generate the documents, so in this case, one way to
+create the documentation is through a docker container. The first step is
+to check if `docker`_ is installed in your host, otherwise check main docker
+page for installation instructions. Once installed, run the following script
+from project root directory
+
+.. code:: shell
+
+   docker run --rm -v $PWD:/TF sphinxdoc/sphinx \
+          bash -c 'cd /TF && \
+          pip3 install plantuml -r ./docs/requirements.txt && make doc'
+
+The above command fetches the ``sphinxdoc/sphinx`` container from `docker
+hub`_, launches the container, installs documentation requirements and finally
+creates the documentation. Once done, exit the container and output from the
+build process will be placed in:
+
+::
+
+   docs/build/html
+
 --------------
 
 *Copyright (c) 2019, Arm Limited. All rights reserved.*
@@ -86,3 +111,5 @@
 .. _Sphinx: http://www.sphinx-doc.org/en/master/
 .. _pip homepage: https://pip.pypa.io/en/stable/
 .. _Dia: https://wiki.gnome.org/Apps/Dia
+.. _docker: https://www.docker.com/
+.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 45c27ad..6b8bbc6 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1130,6 +1130,7 @@
 
     soc_version[30:24] = JEP-106 continuation code for the SiP
     soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+    soc_version[15:0]  = Implementation defined SoC ID
 
 Function : plat_get_soc_revision()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1145,6 +1146,18 @@
 
     soc_revision[0:30] = SOC revision of specific SOC
 
+Function : plat_is_smccc_feature_available()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : u_register_t
+    Return   : int32_t
+
+This function returns SMC_ARCH_CALL_SUCCESS if the platform supports
+the SMCCC function specified in the argument; otherwise returns
+SMC_ARCH_CALL_NOT_SUPPORTED.
+
 Modifications specific to a Boot Loader stage
 ---------------------------------------------
 
@@ -2469,9 +2482,7 @@
 ``FVP_USE_GIC_DRIVER`` (See :ref:`build_options_arm_fvp_platform` for more
 details).
 
-See also: `Interrupt Controller Abstraction APIs`__.
-
-.. __: ../design/platform-interrupt-controller-API.rst
+See also: :ref:`Interrupt Controller Abstraction APIs<Platform Interrupt Controller API>`.
 
 Function : plat_interrupt_type_to_line() [mandatory]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2596,9 +2607,7 @@
 the highest pending interrupt has begun. It should return the raw, unmodified
 value obtained from the interrupt controller when acknowledging an interrupt.
 The actual interrupt number shall be extracted from this raw value using the API
-`plat_ic_get_interrupt_id()`__.
-
-.. __: ../design/platform-interrupt-controller-API.rst#function-unsigned-int-plat-ic-get-interrupt-id-unsigned-int-raw-optional
+`plat_ic_get_interrupt_id()<plat_ic_get_interrupt_id>`.
 
 This function in Arm standard platforms using GICv2, reads the *Interrupt
 Acknowledge Register* (``GICC_IAR``). This changes the state of the highest
@@ -2729,6 +2738,8 @@
 registers x0 through x5 to do its work. The return value is 0 on successful
 completion; otherwise the return value is -1.
 
+.. _External Abort handling and RAS Support:
+
 External Abort handling and RAS Support
 ---------------------------------------
 
diff --git a/docs/perf/psci-performance-juno.rst b/docs/perf/psci-performance-juno.rst
index c127c1c..eab3e4d 100644
--- a/docs/perf/psci-performance-juno.rst
+++ b/docs/perf/psci-performance-juno.rst
@@ -286,7 +286,7 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
 
-.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf
+.. _Juno R1 platform: https://static.docs.arm.com/100122/0100/arm_versatile_express_juno_r1_development_platform_(v2m_juno_r1)_technical_reference_manual_100122_0100_05_en.pdf
 .. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index a1e0659..d82380d 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -34,7 +34,7 @@
 
     make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
 
-.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
+.. _U-Boot documentation: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/sunxi/README.sunxi64
 
 Trusted OS dispatcher
 ---------------------
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 9622de6..2e50068 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -91,6 +91,9 @@
    platforms. If this option is specified, then the path to the CryptoCell
    SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag.
 
+-  ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
+   SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
+
 For a better understanding of these options, the Arm development platform memory
 map is explained in the :ref:`Firmware Design`.
 
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index f23ec28..745e31f 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -37,12 +37,16 @@
 -  ``FVP_Base_Cortex-A76AEx4``
 -  ``FVP_Base_Cortex-A76AEx8``
 -  ``FVP_Base_Cortex-A77x4``
+-  ``FVP_Base_Neoverse-E1x1``
+-  ``FVP_Base_Neoverse-E1x2``
+-  ``FVP_Base_Neoverse-E1x4``
 -  ``FVP_Base_Neoverse-N1x4``
 -  ``FVP_Base_Zeusx4``
--  ``FVP_CSS_SGI-575`` (Version 11.10 build 25)
+-  ``FVP_CSS_SGI-575``     (Version 11.10 build 36)
 -  ``FVP_CSS_SGM-775``
--  ``FVP_RD_E1Edge``
--  ``FVP_RD_N1Edge`` (Version 11.10 build 25)
+-  ``FVP_RD_E1_edge``      (Version 11.10 build 36)
+-  ``FVP_RD_N1_edge``      (Version 11.10 build 36)
+-  ``FVP_RD_N1_edge_dual`` (Version 11.10 build 36)
 -  ``Foundation_Platform``
 
 The latest version of the AArch32 build of TF-A has been tested on the
@@ -631,7 +635,7 @@
 
 *Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
 
-.. _TB_FW_CONFIG for FVP: ../plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+.. _TB_FW_CONFIG for FVP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
 .. _Arm's website: `FVP models`_
 .. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms
 .. _Linaro Release 19.06: http://releases.linaro.org/members/arm/platforms/19.06
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
index ba087a2..f184b69 100644
--- a/docs/plat/imx8m.rst
+++ b/docs/plat/imx8m.rst
@@ -33,6 +33,7 @@
    Target_SoC should be "imx8mq" for i.MX8MQ SoC.
    Target_SoC should be "imx8mm" for i.MX8MM SoC.
    Target_SoC should be "imx8mn" for i.MX8MN SoC.
+   Target_SoC should be "imx8mp" for i.MX8MP SoC.
 
 Deploy TF-A Images
 ~~~~~~~~~~~~~~~~~~
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index bec0bcb..da4ba56 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -79,10 +79,12 @@
 
 - LLC_SRAM
 
-        Flag defining the LLC (L3) cache SRAM support. The feature is
-        disabled by default (``LLC_ENABLE=0``).
-        When LLC SRAM is enabled, the secure payload (BL32) is loaded into this
-        SRAM area instead of the DRAM.
+        Flag enabling the LLC (L3) cache SRAM support. The LLC SRAM is activated and used
+        by Trusted OS (OP-TEE OS, BL32). The TF-A only prepares CCU address translation windows
+        for SRAM address range at BL31 execution stage with window target set to DRAM-0.
+        When Trusted OS activates LLC SRAM, the CCU window target is changed to SRAM.
+        There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n.
+        Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y.
 
 - MARVELL_SECURE_BOOT
 
diff --git a/docs/plat/meson-axg.rst b/docs/plat/meson-axg.rst
index 1e4b2c2..6f6732e 100644
--- a/docs/plat/meson-axg.rst
+++ b/docs/plat/meson-axg.rst
@@ -24,4 +24,4 @@
 instructions in the `U-Boot repository`_, replacing the mentioned **bl31.img**
 by the one built from this port.
 
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/s400/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/s400.rst
diff --git a/docs/plat/meson-g12a.rst b/docs/plat/meson-g12a.rst
index 7cd1bf7..9588ec4 100644
--- a/docs/plat/meson-g12a.rst
+++ b/docs/plat/meson-g12a.rst
@@ -20,8 +20,8 @@
     CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a
 
 This port has been tested on a SEI510 board. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
 mentioned **bl31.img** by the one built from this port.
 
 .. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README.g12a
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/sei510/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/sei510.rst
diff --git a/docs/plat/meson-gxl.rst b/docs/plat/meson-gxl.rst
index c6d8504..0751f1d 100644
--- a/docs/plat/meson-gxl.rst
+++ b/docs/plat/meson-gxl.rst
@@ -20,8 +20,8 @@
     CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl
 
 This port has been tested on a Lepotato. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
 mentioned **bl31.img** by the one built from this port.
 
 .. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/p212/README.libretech-cc
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/p212.rst
diff --git a/docs/resources/diagrams/ff-a-spm-sel2.png b/docs/resources/diagrams/ff-a-spm-sel2.png
new file mode 100644
index 0000000..6479ff5
--- /dev/null
+++ b/docs/resources/diagrams/ff-a-spm-sel2.png
Binary files differ
diff --git a/docs/resources/diagrams/plantuml/bl2-loading-sp.puml b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
new file mode 100644
index 0000000..3cf7c36
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
@@ -0,0 +1,44 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+participant bl1
+participant FIP
+
+bl1 -> FIP : read(FW_CONFIG)
+create FW_CONFIG
+bl1 -> FW_CONFIG : load
+
+bl1 -> FIP : read(bl2)
+create bl2
+bl1 -> bl2 : load
+bl1 --> bl2 : hand off (FW_CONFIG)
+
+bl2 -> FW_CONFIG : read_node(SPKs)
+loop for each spkg subnode
+  bl2 -> FW_CONFIG : read(UUID)
+  bl2 -> FW_CONFIG : read(load_address)
+  bl2 -> FIP : read(spkg@UUID)
+  create SPKG
+  bl2 -> SPKG : load
+end loop
+
+bl2 -> FW_CONFIG : read_node(TOS_FW_CONFIG)
+create TOS_FW_CONFIG
+bl2 -> TOS_FW_CONFIG : load
+
+bl2 -> FIP : read(bl32/SPMC)
+create SPMC
+bl2 -> SPMC : load
+
+bl2 -> FIP : read(bl31)
+create bl31
+bl2 -> bl31 : load
+bl2 --> bl31 : hand off (TOS_FW_CONFIG)
+
+bl31 --> SPMC : hand off (TOS_FW_CONFIG)
+
+@enduml
diff --git a/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
new file mode 100644
index 0000000..40621db
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
@@ -0,0 +1,122 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+
+folder SP_vendor_1 {
+ artifact sp_binary_1
+ artifact sp_manifest_1 [
+ sp_manifest_1
+ ===
+ UUID = xxx
+ load_address = 0xaaa
+ ...
+ ]
+}
+
+folder SP_vendor_2 {
+ artifact sp_binary_2
+ artifact sp_manifest_2 [
+ sp_manifest_2
+ ===
+ UUID = yyy
+ load_address = 0xbbb
+ ]
+}
+
+artifact config.json [
+ SP_LAYOUT.json
+ ===
+ path to sp_binary_1
+ path to sp_manifest_1
+ ---
+ path to sp_binary_2
+ path to sp_manifest_2
+ ---
+ ...
+]
+
+control sp_mk_generator
+
+artifact fconf_node [
+ fconf_sp.dts
+ ===
+ spkg_1 UUID
+ spkg_1 load_address
+ ---
+ spkg_2 UUID
+ spkg_2 load_address
+]
+
+artifact sp_gen [
+ sp_gen.mk
+ ===
+ FDT_SOURCE = ...
+ SPTOOL_ARGS = ...
+ FIP_ARG = ...
+]
+
+control dtc
+control sptool
+
+artifact FW_CONFIG
+
+artifact spkg_1 [
+ spkg_1.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+artifact spkg_2 [
+ spkg_2.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+control fiptool
+
+artifact fip [
+ fip.bin
+ ===
+ FW_CONFIG.dtb
+ ---
+ ...
+ ---
+ SPKG1
+ ---
+ SPKG2
+ ---
+ ...
+]
+
+config.json .up.> SP_vendor_1
+config.json .up.> SP_vendor_2
+config.json --> sp_mk_generator
+sp_mk_generator --> fconf_node
+sp_mk_generator --> sp_gen
+
+sp_gen --> sptool
+sptool --> spkg_1
+sptool --> spkg_2
+
+fconf_node -down-> dtc
+dtc --> FW_CONFIG
+
+sp_gen --> fiptool
+FW_CONFIG --> fiptool
+spkg_1 -down-> fiptool
+spkg_2 -down-> fiptool
+fiptool -down-> fip
+
+@enduml
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
index 38b2f67..bf6405f 100644
--- a/drivers/arm/gic/common/gic_common.c
+++ b/drivers/arm/gic/common/gic_common.c
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#pragma message __FILE__ " is deprecated, use gicv2.mk instead"
+
 #include <assert.h>
 
 #include <drivers/arm/gic_common.h>
diff --git a/drivers/arm/gic/v2/gicdv2_helpers.c b/drivers/arm/gic/v2/gicdv2_helpers.c
new file mode 100644
index 0000000..db9ba87
--- /dev/null
+++ b/drivers/arm/gic/v2/gicdv2_helpers.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+
+#include "../common/gic_common_private.h"
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+/*
+ * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
+ * `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IGROUPR_SHIFT;
+
+	return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISPENDR_SHIFT;
+
+	return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICPENDR_SHIFT;
+
+	return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISACTIVER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICACTIVER_SHIFT;
+
+	return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICGFR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICFGR_SHIFT;
+
+	return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> NSACR_SHIFT;
+
+	return mmio_read_32(base + GICD_NSACR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+/*
+ * Accessor to write the GIC Distributor IGROUPR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IGROUPR_SHIFT;
+
+	mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICENABLER_SHIFT;
+
+	mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISPENDR_SHIFT;
+
+	mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICPENDR_SHIFT;
+
+	mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISACTIVER_SHIFT;
+
+	mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICACTIVER_SHIFT;
+
+	mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICFGR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICFGR_SHIFT;
+
+	mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> NSACR_SHIFT;
+
+	mmio_write_32(base + GICD_NSACR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor functions for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
+}
+
+void gicd_clr_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
+}
+
+void gicd_set_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
+
+	gicd_write_isenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
+
+	gicd_write_icenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
+
+	gicd_write_ispendr(base, id, (1U << bit_num));
+}
+
+void gicd_set_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
+
+	gicd_write_icpendr(base, id, (1U << bit_num));
+}
+
+unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_isactiver(base, id);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+
+	gicd_write_isactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
+
+	gicd_write_icactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+	uint8_t val = pri & GIC_PRI_MASK;
+
+	mmio_write_8(base + GICD_IPRIORITYR + id, val);
+}
+
+void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+	/* Interrupt configuration is a 2-bit field */
+	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
+	unsigned int bit_shift = bit_num << 1;
+
+	uint32_t reg_val = gicd_read_icfgr(base, id);
+
+	/* Clear the field, and insert required configuration */
+	reg_val &= ~(GIC_CFG_MASK << bit_shift);
+	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
+
+	gicd_write_icfgr(base, id, reg_val);
+}
diff --git a/drivers/arm/gic/v2/gicv2.mk b/drivers/arm/gic/v2/gicv2.mk
new file mode 100644
index 0000000..49996bb
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# No support for extended PPI and SPI range
+GIC_EXT_INTID	:=	0
+
+GICV2_SOURCES	+=	drivers/arm/gic/v2/gicv2_main.c		\
+			drivers/arm/gic/v2/gicv2_helpers.c	\
+			drivers/arm/gic/v2/gicdv2_helpers.c
+
+# Set GICv2 build option
+$(eval $(call add_define,GIC_EXT_INTID))
\ No newline at end of file
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
index c1a9f0d..6e106ba 100644
--- a/drivers/arm/gic/v3/gic-x00.c
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,30 +21,32 @@
 #include "gicv3_private.h"
 
 /* GIC-600 specific register offsets */
-#define GICR_PWRR		0x24
-#define IIDR_MODEL_ARM_GIC_600	0x0200043b
+#define GICR_PWRR			0x24U
+#define IIDR_MODEL_ARM_GIC_600		U(0x0200043b)
+#define IIDR_MODEL_ARM_GIC_600AE	U(0x0300043b)
+#define IIDR_MODEL_ARM_GIC_CLAYTON	U(0x0400043b)
 
 /* GICR_PWRR fields */
-#define PWRR_RDPD_SHIFT		0
-#define PWRR_RDAG_SHIFT		1
-#define PWRR_RDGPD_SHIFT	2
-#define PWRR_RDGPO_SHIFT	3
+#define PWRR_RDPD_SHIFT			0
+#define PWRR_RDAG_SHIFT			1
+#define PWRR_RDGPD_SHIFT		2
+#define PWRR_RDGPO_SHIFT		3
 
-#define PWRR_RDPD	(1 << PWRR_RDPD_SHIFT)
-#define PWRR_RDAG	(1 << PWRR_RDAG_SHIFT)
-#define PWRR_RDGPD	(1 << PWRR_RDGPD_SHIFT)
-#define PWRR_RDGPO	(1 << PWRR_RDGPO_SHIFT)
+#define PWRR_RDPD			(1U << PWRR_RDPD_SHIFT)
+#define PWRR_RDAG			(1U << PWRR_RDAG_SHIFT)
+#define PWRR_RDGPD			(1U << PWRR_RDGPD_SHIFT)
+#define PWRR_RDGPO			(1U << PWRR_RDGPO_SHIFT)
 
 /*
  * Values to write to GICR_PWRR register to power redistributor
  * for operating through the core (GICR_PWRR.RDAG = 0)
  */
-#define PWRR_ON		(0 << PWRR_RDPD_SHIFT)
-#define PWRR_OFF	(1 << PWRR_RDPD_SHIFT)
+#define PWRR_ON				(0U << PWRR_RDPD_SHIFT)
+#define PWRR_OFF			(1U << PWRR_RDPD_SHIFT)
 
 #if GICV3_SUPPORT_GIC600
 
-/* GIC-600 specific accessor functions */
+/* GIC-600/Clayton specific accessor functions */
 static void gicr_write_pwrr(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_PWRR, val);
@@ -56,10 +59,14 @@
 
 static void gicr_wait_group_not_in_transit(uintptr_t base)
 {
+	uint32_t pwrr;
+
+	do {
+		pwrr = gicr_read_pwrr(base);
+
 	/* Check group not transitioning: RDGPD == RDGPO */
-	while (((gicr_read_pwrr(base) & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
-		((gicr_read_pwrr(base) & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT))
-		;
+	} while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
+		 ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT));
 }
 
 static void gic600_pwr_on(uintptr_t base)
@@ -91,7 +98,7 @@
 	 * In that case, wait as long as it's in transition, or has aborted
 	 * the transition altogether for any reason.
 	 */
-	if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0) {
+	if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) {
 		/* Wait until group not transitioning */
 		gicr_wait_group_not_in_transit(base);
 	}
@@ -101,24 +108,30 @@
 {
 	uintptr_t gicr_base;
 
-	assert(gicv3_driver_data);
+	assert(gicv3_driver_data != NULL);
 	assert(proc_num < gicv3_driver_data->rdistif_num);
-	assert(gicv3_driver_data->rdistif_base_addrs);
+	assert(gicv3_driver_data->rdistif_base_addrs != NULL);
 
 	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
-	assert(gicr_base);
+	assert(gicr_base != 0UL);
 
 	return gicr_base;
 }
 
-static bool gicv3_is_gic600(uintptr_t gicr_base)
+static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base)
 {
 	uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
 
-	return (reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600;
+	/*
+	 * The Arm GIC-600 and GIC-Clayton models have their redistributors
+	 * powered down at reset.
+	 */
+	return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
 }
 
-#endif
+#endif	/* GICV3_SUPPORT_GIC600 */
 
 void gicv3_distif_pre_save(unsigned int proc_num)
 {
@@ -130,7 +143,6 @@
 	arm_gicv3_distif_post_restore(proc_num);
 }
 
-
 /*
  * Power off GIC-600 redistributor (if configured and detected)
  */
@@ -140,7 +152,7 @@
 	uintptr_t gicr_base = get_gicr_base(proc_num);
 
 	/* Attempt to power redistributor off */
-	if (gicv3_is_gic600(gicr_base)) {
+	if (gicv3_redists_need_power_mgmt(gicr_base)) {
 		gic600_pwr_off(gicr_base);
 	}
 #endif
@@ -155,7 +167,7 @@
 	uintptr_t gicr_base = get_gicr_base(proc_num);
 
 	/* Power redistributor on */
-	if (gicv3_is_gic600(gicr_base)) {
+	if (gicv3_redists_need_power_mgmt(gicr_base)) {
 		gic600_pwr_on(gicr_base);
 	}
 #endif
diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c
index 64ec5ab..7e307ee 100644
--- a/drivers/arm/tzc/tzc_dmc620.c
+++ b/drivers/arm/tzc/tzc_dmc620.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,7 +17,7 @@
 
 /* Helper macro for getting dmc_base addr of a dmc_inst */
 #define DMC_BASE(plat_data, dmc_inst) \
-	((uintptr_t)(plat_data->dmc_base[dmc_inst]))
+	((uintptr_t)((plat_data)->dmc_base[(dmc_inst)]))
 
 /* Pointer to the tzc_dmc620_config_data structure populated by the platform */
 static const tzc_dmc620_config_data_t *g_plat_config_data;
@@ -31,8 +31,7 @@
 static void tzc_dmc620_validate_plat_driver_data(
 			const tzc_dmc620_driver_data_t *plat_driver_data)
 {
-	uint8_t dmc_inst, dmc_count;
-	unsigned int dmc_id;
+	unsigned int dmc_inst, dmc_count, dmc_id;
 	uintptr_t base;
 
 	assert(plat_driver_data != NULL);
@@ -59,7 +58,7 @@
 {
 	uint32_t min_31_00, min_47_32;
 	uint32_t max_31_00, max_47_32;
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -67,19 +66,19 @@
 	assert(plat_driver_data != NULL);
 
 	/* Do range checks on regions. */
-	assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT));
+	assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT));
 
 	/* region_base and (region_top + 1) must be 4KB aligned */
 	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
 
 	dmc_count = plat_driver_data->dmc_count;
 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
-		min_31_00 = (region_base & MASK_31_16) | sec_attr;
-		min_47_32 = (region_base & MASK_47_32)
-				>> DMC620_ACC_ADDR_WIDTH;
-		max_31_00 = (region_top  & MASK_31_16);
-		max_47_32 = (region_top  & MASK_47_32)
-				>> DMC620_ACC_ADDR_WIDTH;
+		min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr);
+		min_47_32 = (uint32_t)((region_base & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH);
+		max_31_00 = (uint32_t)(region_top  & MASK_31_16);
+		max_47_32 = (uint32_t)((region_top  & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH);
 
 		/* Extract the base address of the DMC-620 instance */
 		base = DMC_BASE(plat_driver_data, dmc_inst);
@@ -100,7 +99,7 @@
  */
 static void tzc_dmc620_set_action(void)
 {
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -123,7 +122,7 @@
  */
 static void tzc_dmc620_verify_complete(void)
 {
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -133,8 +132,9 @@
 		/* Extract the base address of the DMC-620 instance */
 		base = DMC_BASE(plat_driver_data, dmc_inst);
 		while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
-				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO)
+				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) {
 			continue;
+		}
 	}
 }
 
@@ -145,7 +145,7 @@
  */
 void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
 {
-	int i;
+	uint8_t i;
 
 	/* Check if valid pointer is passed */
 	assert(plat_config_data != NULL);
@@ -164,11 +164,12 @@
 	g_plat_config_data = plat_config_data;
 
 	INFO("Configuring DMC-620 TZC settings\n");
-	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++)
+	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) {
 		tzc_dmc620_configure_region(i,
 			g_plat_config_data->plat_acc_addr_data[i].region_base,
 			g_plat_config_data->plat_acc_addr_data[i].region_top,
 			g_plat_config_data->plat_acc_addr_data[i].sec_attr);
+	}
 
 	tzc_dmc620_set_action();
 	tzc_dmc620_verify_complete();
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
index 31e5d65..68f3d46 100644
--- a/drivers/auth/dualroot/cot.c
+++ b/drivers/auth/dualroot/cot.c
@@ -693,8 +693,8 @@
  * Secure Partitions
  */
 #if defined(SPD_spmd)
-static const auth_img_desc_t sp_content_cert = {
-	.img_id = SP_CONTENT_CERT_ID,
+static const auth_img_desc_t sip_sp_content_cert = {
+	.img_id = SIP_SP_CONTENT_CERT_ID,
 	.img_type = IMG_CERT,
 	.parent = &trusted_key_cert,
 	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
@@ -775,14 +775,14 @@
 	}
 };
 
-DEFINE_SP_PKG(1);
-DEFINE_SP_PKG(2);
-DEFINE_SP_PKG(3);
-DEFINE_SP_PKG(4);
-DEFINE_SP_PKG(5);
-DEFINE_SP_PKG(6);
-DEFINE_SP_PKG(7);
-DEFINE_SP_PKG(8);
+DEFINE_SIP_SP_PKG(1);
+DEFINE_SIP_SP_PKG(2);
+DEFINE_SIP_SP_PKG(3);
+DEFINE_SIP_SP_PKG(4);
+DEFINE_SIP_SP_PKG(5);
+DEFINE_SIP_SP_PKG(6);
+DEFINE_SIP_SP_PKG(7);
+DEFINE_SIP_SP_PKG(8);
 #endif /* SPD_spmd */
 
 #else  /* IMAGE_BL2 */
@@ -914,15 +914,15 @@
 	[BL33_IMAGE_ID]				=	&bl33_image,
 	[NT_FW_CONFIG_ID]			=	&nt_fw_config,
 #if defined(SPD_spmd)
-	[SP_CONTENT_CERT_ID]			=	&sp_content_cert,
-	[SP_CONTENT_CERT_ID + 1]		=	&sp_pkg1,
-	[SP_CONTENT_CERT_ID + 2]		=	&sp_pkg2,
-	[SP_CONTENT_CERT_ID + 3]		=	&sp_pkg3,
-	[SP_CONTENT_CERT_ID + 4]		=	&sp_pkg4,
-	[SP_CONTENT_CERT_ID + 5]		=	&sp_pkg5,
-	[SP_CONTENT_CERT_ID + 6]		=	&sp_pkg6,
-	[SP_CONTENT_CERT_ID + 7]		=	&sp_pkg7,
-	[SP_CONTENT_CERT_ID + 8]		=       &sp_pkg8,
+	[SIP_SP_CONTENT_CERT_ID]		=	&sip_sp_content_cert,
+	[SP_PKG1_ID]				=	&sp_pkg1,
+	[SP_PKG2_ID]				=	&sp_pkg2,
+	[SP_PKG3_ID]				=	&sp_pkg3,
+	[SP_PKG4_ID]				=	&sp_pkg4,
+	[SP_PKG5_ID]				=	&sp_pkg5,
+	[SP_PKG6_ID]				=	&sp_pkg6,
+	[SP_PKG7_ID]				=	&sp_pkg7,
+	[SP_PKG8_ID]				=       &sp_pkg8,
 #endif
 };
 #endif
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 564a4c9..94f2f59 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -75,19 +75,10 @@
 
 ifeq (${HASH_ALG}, sha384)
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA384
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA384
-    TPM_ALG_ID			:=	TPM_ALG_SHA384
-    TCG_DIGEST_SIZE		:=	48
 else ifeq (${HASH_ALG}, sha512)
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA512
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA512
-    TPM_ALG_ID			:=	TPM_ALG_SHA512
-    TCG_DIGEST_SIZE		:=	64
 else
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA256
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA256
-    TPM_ALG_ID			:=	TPM_ALG_SHA256
-    TCG_DIGEST_SIZE		:=	32
 endif
 
 ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa)
@@ -112,11 +103,6 @@
 $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
 $(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM))
 
-# Set definitions for measured boot driver
-$(eval $(call add_define,MBEDTLS_MD_ID))
-$(eval $(call add_define,TPM_ALG_ID))
-$(eval $(call add_define,TCG_DIGEST_SIZE))
-
 $(eval $(call MAKE_LIB,mbedtls))
 
 endif
diff --git a/drivers/auth/tbbr/tbbr_cot_bl2.c b/drivers/auth/tbbr/tbbr_cot_bl2.c
index 63c18fa..65a0478 100644
--- a/drivers/auth/tbbr/tbbr_cot_bl2.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl2.c
@@ -558,8 +558,8 @@
 };
 /* Secure Partitions */
 #if defined(SPD_spmd)
-static const auth_img_desc_t sp_content_cert = {
-	.img_id = SP_CONTENT_CERT_ID,
+static const auth_img_desc_t sip_sp_content_cert = {
+	.img_id = SIP_SP_CONTENT_CERT_ID,
 	.img_type = IMG_CERT,
 	.parent = &trusted_key_cert,
 	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
@@ -640,14 +640,14 @@
 	}
 };
 
-DEFINE_SP_PKG(1);
-DEFINE_SP_PKG(2);
-DEFINE_SP_PKG(3);
-DEFINE_SP_PKG(4);
-DEFINE_SP_PKG(5);
-DEFINE_SP_PKG(6);
-DEFINE_SP_PKG(7);
-DEFINE_SP_PKG(8);
+DEFINE_SIP_SP_PKG(1);
+DEFINE_SIP_SP_PKG(2);
+DEFINE_SIP_SP_PKG(3);
+DEFINE_SIP_SP_PKG(4);
+DEFINE_SIP_SP_PKG(5);
+DEFINE_SIP_SP_PKG(6);
+DEFINE_SIP_SP_PKG(7);
+DEFINE_SIP_SP_PKG(8);
 #endif /* SPD_spmd */
 
 static const auth_img_desc_t * const cot_desc[] = {
@@ -672,15 +672,15 @@
 	[BL33_IMAGE_ID]				=	&bl33_image,
 	[NT_FW_CONFIG_ID]			=	&nt_fw_config,
 #if defined(SPD_spmd)
-	[SP_CONTENT_CERT_ID]			=	&sp_content_cert,
-	[SP_CONTENT_CERT_ID + 1]		=	&sp_pkg1,
-	[SP_CONTENT_CERT_ID + 2]		=	&sp_pkg2,
-	[SP_CONTENT_CERT_ID + 3]		=	&sp_pkg3,
-	[SP_CONTENT_CERT_ID + 4]		=	&sp_pkg4,
-	[SP_CONTENT_CERT_ID + 5]		=	&sp_pkg5,
-	[SP_CONTENT_CERT_ID + 6]		=	&sp_pkg6,
-	[SP_CONTENT_CERT_ID + 7]		=	&sp_pkg7,
-	[SP_CONTENT_CERT_ID + 8]		=       &sp_pkg8,
+	[SIP_SP_CONTENT_CERT_ID]		=	&sip_sp_content_cert,
+	[SP_PKG1_ID]				=	&sp_pkg1,
+	[SP_PKG2_ID]				=	&sp_pkg2,
+	[SP_PKG3_ID]				=	&sp_pkg3,
+	[SP_PKG4_ID]				=	&sp_pkg4,
+	[SP_PKG5_ID]				=	&sp_pkg5,
+	[SP_PKG6_ID]				=	&sp_pkg6,
+	[SP_PKG7_ID]				=	&sp_pkg7,
+	[SP_PKG8_ID]				=       &sp_pkg8,
 #endif
 };
 
diff --git a/drivers/brcm/rng.c b/drivers/brcm/rng.c
new file mode 100644
index 0000000..ee2e656
--- /dev/null
+++ b/drivers/brcm/rng.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define RNG_CTRL_REG		(RNG_BASE_ADDR + 0x00)
+#define RNG_CTRL_MASK		0x00001FFF
+#define RNG_CTRL_ENABLE		0x00000001
+#define RNG_CTRL_DISABLE	0x00000000
+
+#define RNG_SOFT_RESET_REG	(RNG_BASE_ADDR + 0x04)
+#define RNG_SOFT_RESET_MASK	0x00000001
+
+#define RNG_FIFO_DATA_REG	(RNG_BASE_ADDR + 0x20)
+
+#define RNG_FIFO_COUNT_REG	(RNG_BASE_ADDR + 0x24)
+#define RNG_FIFO_COUNT_MASK	0x000000FF
+
+#define RNG_FIFO_WORDS_MAX	16
+#define MAX_WAIT_COUNT_50US	20000
+
+
+static void rng_reset(void)
+{
+	/* Disable RBG */
+	mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK);
+
+	/* Reset RNG and RBG */
+	mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+
+	/* Take all out of reset */
+	mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+}
+
+static void rng_enable(void)
+{
+	/* Setup RNG. */
+	mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE);
+}
+
+int rng_init(void)
+{
+	rng_reset();
+
+	rng_enable();
+
+	return 0;
+}
+
+int rng_read(uint32_t *p_out, uint32_t *words_read)
+{
+	uint32_t available_words;
+	uint32_t i;
+	uint32_t word_processed = 0;
+	uint32_t wait_count = MAX_WAIT_COUNT_50US;
+
+	if (*words_read == 0) {
+		ERROR("RNG Parameter: No word requested\n");
+		return -1;
+	}
+
+	do {
+		available_words = mmio_read_32(RNG_FIFO_COUNT_REG);
+		available_words &= RNG_FIFO_COUNT_MASK;
+
+		if (available_words != 0) {
+			available_words = MIN(available_words,
+					*words_read - word_processed);
+
+			for (i = 0; i < available_words; i++)
+				p_out[word_processed + i] =
+					mmio_read_32(RNG_FIFO_DATA_REG);
+			word_processed += available_words;
+		} else {
+			udelay(50);
+		}
+
+		if (word_processed == *words_read)
+			break;
+
+	} while (--wait_count);
+
+	if (word_processed != *words_read) {
+		ERROR("RNG Timeout: requested %d word(s) got %d\n",
+				*words_read, word_processed);
+		*words_read = word_processed;
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 02f85d6..6e15295 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -36,7 +36,7 @@
 typedef struct {
 	unsigned int file_pos;
 	fip_toc_entry_t entry;
-} file_state_t;
+} fip_file_state_t;
 
 /*
  * Maintain dev_spec per FIP Device
@@ -49,7 +49,6 @@
 	uint16_t plat_toc_flag;
 } fip_dev_state_t;
 
-static const uuid_t uuid_null;
 /*
  * Only one file can be open across all FIP device
  * as backends like io_memmap don't support
@@ -57,7 +56,7 @@
  * backend handle should be maintained per FIP device
  * if the same support is available in the backend
  */
-static file_state_t current_file = {0};
+static fip_file_state_t current_fip_file = {0};
 static uintptr_t backend_dev_handle;
 static uintptr_t backend_image_spec;
 
@@ -288,6 +287,7 @@
 	int result;
 	uintptr_t backend_handle;
 	const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
+	static const uuid_t uuid_null = { {0} }; /* Double braces for clang */
 	size_t bytes_read;
 	int found_file = 0;
 
@@ -300,9 +300,9 @@
 	 * When the system supports dynamic memory allocation we can allow more
 	 * than one open file at a time if needed.
 	 */
-	if (current_file.entry.offset_address != 0) {
+	if (current_fip_file.entry.offset_address != 0U) {
 		WARN("fip_file_open : Only one open file at a time.\n");
-		return -ENOMEM;
+		return -ENFILE;
 	}
 
 	/* Attempt to access the FIP image */
@@ -326,31 +326,32 @@
 	found_file = 0;
 	do {
 		result = io_read(backend_handle,
-				 (uintptr_t)&current_file.entry,
-				 sizeof(current_file.entry),
+				 (uintptr_t)&current_fip_file.entry,
+				 sizeof(current_fip_file.entry),
 				 &bytes_read);
 		if (result == 0) {
-			if (compare_uuids(&current_file.entry.uuid,
+			if (compare_uuids(&current_fip_file.entry.uuid,
 					  &uuid_spec->uuid) == 0) {
 				found_file = 1;
-				break;
 			}
 		} else {
 			WARN("Failed to read FIP (%i)\n", result);
 			goto fip_file_open_close;
 		}
-	} while (compare_uuids(&current_file.entry.uuid, &uuid_null) != 0);
+	} while ((found_file == 0) &&
+			(compare_uuids(&current_fip_file.entry.uuid,
+				&uuid_null) != 0));
 
 	if (found_file == 1) {
 		/* All fine. Update entity info with file state and return. Set
-		 * the file position to 0. The 'current_file.entry' holds the
-		 * base and size of the file.
+		 * the file position to 0. The 'current_fip_file.entry' holds
+		 * the base and size of the file.
 		 */
-		current_file.file_pos = 0;
-		entity->info = (uintptr_t)&current_file;
+		current_fip_file.file_pos = 0;
+		entity->info = (uintptr_t)&current_fip_file;
 	} else {
 		/* Did not find the file in the FIP. */
-		current_file.entry.offset_address = 0;
+		current_fip_file.entry.offset_address = 0;
 		result = -ENOENT;
 	}
 
@@ -368,7 +369,7 @@
 	assert(entity != NULL);
 	assert(length != NULL);
 
-	*length =  ((file_state_t *)entity->info)->entry.size;
+	*length =  ((fip_file_state_t *)entity->info)->entry.size;
 
 	return 0;
 }
@@ -379,7 +380,7 @@
 			  size_t *length_read)
 {
 	int result;
-	file_state_t *fp;
+	fip_file_state_t *fp;
 	size_t file_offset;
 	size_t bytes_read;
 	uintptr_t backend_handle;
@@ -397,7 +398,7 @@
 		goto fip_file_read_exit;
 	}
 
-	fp = (file_state_t *)entity->info;
+	fp = (fip_file_state_t *)entity->info;
 
 	/* Seek to the position in the FIP where the payload lives */
 	file_offset = fp->entry.offset_address + fp->file_pos;
@@ -436,8 +437,8 @@
 	/* Clear our current file pointer.
 	 * If we had malloc() we would free() here.
 	 */
-	if (current_file.entry.offset_address != 0) {
-		zeromem(&current_file, sizeof(current_file));
+	if (current_fip_file.entry.offset_address != 0U) {
+		zeromem(&current_fip_file, sizeof(current_fip_file));
 	}
 
 	/* Clear the Entity info. */
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index eed50cc..eb69163 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,9 +27,9 @@
 	uintptr_t		base;
 	unsigned long long	file_pos;
 	unsigned long long	size;
-} file_state_t;
+} memmap_file_state_t;
 
-static file_state_t current_file = {0};
+static memmap_file_state_t current_memmap_file = {0};
 
 /* Identify the device type as memmap */
 static io_type_t device_type_memmap(void)
@@ -71,7 +71,7 @@
 
 
 /* No state associated with this device so structure can be const */
-static const io_dev_info_t memmap_dev_info = {
+static io_dev_info_t memmap_dev_info = {
 	.funcs = &memmap_dev_funcs,
 	.info = (uintptr_t)NULL
 };
@@ -82,8 +82,7 @@
 			   io_dev_info_t **dev_info)
 {
 	assert(dev_info != NULL);
-	*dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
-
+	*dev_info = &memmap_dev_info;
 	return 0;
 }
 
@@ -109,16 +108,16 @@
 	 * spec at a time. When we have dynamic memory we can malloc and set
 	 * entity->info.
 	 */
-	if (current_file.in_use == 0) {
+	if (current_memmap_file.in_use == 0) {
 		assert(block_spec != NULL);
 		assert(entity != NULL);
 
-		current_file.in_use = 1;
-		current_file.base = block_spec->offset;
+		current_memmap_file.in_use = 1;
+		current_memmap_file.base = block_spec->offset;
 		/* File cursor offset for seek and incremental reads etc. */
-		current_file.file_pos = 0;
-		current_file.size = block_spec->length;
-		entity->info = (uintptr_t)&current_file;
+		current_memmap_file.file_pos = 0;
+		current_memmap_file.size = block_spec->length;
+		entity->info = (uintptr_t)&current_memmap_file;
 		result = 0;
 	} else {
 		WARN("A Memmap device is already active. Close first.\n");
@@ -133,13 +132,13 @@
 			     signed long long offset)
 {
 	int result = -ENOENT;
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 
 	/* We only support IO_SEEK_SET for the moment. */
 	if (mode == IO_SEEK_SET) {
 		assert(entity != NULL);
 
-		fp = (file_state_t *) entity->info;
+		fp = (memmap_file_state_t *) entity->info;
 
 		/* Assert that new file position is valid */
 		assert((offset >= 0) &&
@@ -160,7 +159,7 @@
 	assert(entity != NULL);
 	assert(length != NULL);
 
-	*length = (size_t)((file_state_t *)entity->info)->size;
+	*length = (size_t)((memmap_file_state_t *)entity->info)->size;
 
 	return 0;
 }
@@ -170,13 +169,13 @@
 static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
 			     size_t length, size_t *length_read)
 {
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 	unsigned long long pos_after;
 
 	assert(entity != NULL);
 	assert(length_read != NULL);
 
-	fp = (file_state_t *) entity->info;
+	fp = (memmap_file_state_t *) entity->info;
 
 	/* Assert that file position is valid for this read operation */
 	pos_after = fp->file_pos + length;
@@ -198,13 +197,13 @@
 static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
 			      size_t length, size_t *length_written)
 {
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 	unsigned long long pos_after;
 
 	assert(entity != NULL);
 	assert(length_written != NULL);
 
-	fp = (file_state_t *) entity->info;
+	fp = (memmap_file_state_t *) entity->info;
 
 	/* Assert that file position is valid for this write operation */
 	pos_after = fp->file_pos + length;
@@ -230,7 +229,7 @@
 	entity->info = 0;
 
 	/* This would be a mem free() if we had malloc.*/
-	zeromem((void *)&current_file, sizeof(current_file));
+	zeromem((void *)&current_memmap_file, sizeof(current_memmap_file));
 
 	return 0;
 }
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
index 4ceddc6..1c2f84d 100644
--- a/drivers/io/io_semihosting.c
+++ b/drivers/io/io_semihosting.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -51,8 +51,7 @@
 };
 
 
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t sh_dev_info = {
+static io_dev_info_t sh_dev_info = {
 	.funcs = &sh_dev_funcs,
 	.info = (uintptr_t)NULL
 };
@@ -63,7 +62,7 @@
 		io_dev_info_t **dev_info)
 {
 	assert(dev_info != NULL);
-	*dev_info = (io_dev_info_t *)&sh_dev_info; /* cast away const */
+	*dev_info = &sh_dev_info;
 	return 0;
 }
 
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index b8c1d64..0534268 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,36 +32,34 @@
 #if ENABLE_ASSERTIONS
 
 /* Return a boolean value indicating whether a device connector is valid */
-static int is_valid_dev_connector(const io_dev_connector_t *dev_con)
+static bool is_valid_dev_connector(const io_dev_connector_t *dev_con)
 {
-	int result = (dev_con != NULL) && (dev_con->dev_open != NULL);
-	return result;
+	return (dev_con != NULL) && (dev_con->dev_open != NULL);
 }
 
-
 /* Return a boolean value indicating whether a device handle is valid */
-static int is_valid_dev(const uintptr_t dev_handle)
+static bool is_valid_dev(const uintptr_t dev_handle)
 {
 	const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
-	int result = (dev != NULL) && (dev->funcs != NULL) &&
+
+	return (dev != NULL) && (dev->funcs != NULL) &&
 			(dev->funcs->type != NULL) &&
 			(dev->funcs->type() < IO_TYPE_MAX);
-	return result;
 }
 
 
 /* Return a boolean value indicating whether an IO entity is valid */
-static int is_valid_entity(const uintptr_t handle)
+static bool is_valid_entity(const uintptr_t handle)
 {
 	const io_entity_t *entity = (io_entity_t *)handle;
-	int result = (entity != NULL) &&
+
+	return (entity != NULL) &&
 			(is_valid_dev((uintptr_t)entity->dev_handle));
-	return result;
 }
 
 
 /* Return a boolean value indicating whether a seek mode is valid */
-static int is_valid_seek_mode(io_seek_mode_t mode)
+static bool is_valid_seek_mode(io_seek_mode_t mode)
 {
 	return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
 }
@@ -71,15 +69,14 @@
 
 
 /* Open a connection to a specific device */
-static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
+static int io_storage_dev_open(const io_dev_connector_t *dev_con,
+		const uintptr_t dev_spec,
 		io_dev_info_t **dev_info)
 {
-	int result;
 	assert(dev_info != NULL);
 	assert(is_valid_dev_connector(dev_con));
 
-	result = dev_con->dev_open(dev_spec, dev_info);
-	return result;
+	return dev_con->dev_open(dev_spec, dev_info);
 }
 
 
@@ -116,7 +113,8 @@
 		unsigned int index = 0;
 		result = find_first_entity(NULL, &index);
 		assert(result == 0);
-		*entity = entity_map[index] = &entity_pool[index];
+		*entity = &entity_pool[index];
+		entity_map[index] = &entity_pool[index];
 		++entity_count;
 	}
 
@@ -163,11 +161,8 @@
 int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
 		uintptr_t *handle)
 {
-	int result;
 	assert(handle != NULL);
-
-	result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
-	return result;
+	return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
 }
 
 
diff --git a/drivers/marvell/cache_llc.c b/drivers/marvell/cache_llc.c
index 836aae7..4b06b47 100644
--- a/drivers/marvell/cache_llc.c
+++ b/drivers/marvell/cache_llc.c
@@ -111,28 +111,36 @@
 }
 
 #if LLC_SRAM
-void llc_sram_enable(int ap_index)
+int llc_sram_enable(int ap_index, int size)
 {
-	uint32_t tc, way;
+	uint32_t tc, way, ways_to_allocate;
 	uint32_t way_addr;
 
+	if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE))
+		return -1;
+
+	llc_enable(ap_index, 1);
+	llc_inv_all(ap_index);
+
+	ways_to_allocate = size / LLC_WAY_SIZE;
+
 	/* Lockdown all available ways for all traffic classes */
 	for (tc = 0; tc < LLC_TC_NUM; tc++)
-		mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_WAY_MASK);
+		mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK);
 
 	/* Clear the high bits of SRAM address */
 	mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0);
 
 	way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE;
-	for (way = 0; way < LLC_WAYS; way++) {
+	for (way = 0; way < ways_to_allocate; way++) {
 		/* Trigger allocation block command */
 		mmio_write_32(LLC_BLK_ALOC(ap_index),
 			      LLC_BLK_ALOC_BASE_ADDR(way_addr) |
-			      LLC_BLK_ALOC_WAY_DATA_CLR |
+			      LLC_BLK_ALOC_WAY_DATA_SET |
 			      LLC_BLK_ALOC_WAY_ID(way));
 		way_addr += LLC_WAY_SIZE;
 	}
-	llc_enable(ap_index, 1);
+	return 0;
 }
 
 void llc_sram_disable(int ap_index)
@@ -146,4 +154,36 @@
 	/* Invalidate all ways */
 	llc_inv_all(ap_index);
 }
+
+int llc_sram_test(int ap_index, int size, char *msg)
+{
+	uintptr_t addr, end_addr;
+	uint32_t data = 0;
+
+	if ((size <= 0) || (size > LLC_SIZE))
+		return -1;
+
+	INFO("=== LLC SRAM WRITE test %s\n", msg);
+	for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+	     end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+	     addr < end_addr; addr += 4) {
+		mmio_write_32(addr, addr);
+	}
+	INFO("=== LLC SRAM WRITE test %s PASSED\n", msg);
+	INFO("=== LLC SRAM READ test %s\n", msg);
+	for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+	     end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+	     addr < end_addr; addr += 4) {
+		data = mmio_read_32(addr);
+		if (data != addr) {
+			INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n",
+			     msg, addr);
+			return -1;
+		}
+	}
+	INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n",
+	     msg, data);
+	return 0;
+}
+
 #endif /* LLC_SRAM */
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 2760f46..1d5b6f5 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -11,6 +11,7 @@
 
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
 #include <lib/mmio.h>
 #include <lib/spinlock.h>
 
@@ -2231,6 +2232,7 @@
 					  uint32_t comphy_mode)
 {
 	uint32_t mask, data;
+	uint8_t ap_nr, cp_nr;
 	uintptr_t comphy_addr = comphy_addr =
 				COMPHY_ADDR(comphy_base, comphy_index);
 
@@ -2247,6 +2249,10 @@
 	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
 	debug_exit();
 
+	/* Start AP Firmware */
+	mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
+	mg_start_ap_fw(cp_nr, comphy_index);
+
 	return 0;
 }
 
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
new file mode 100644
index 0000000..98e1896
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mss_scp_bl2_format.h>
+
+/* CONFI REGISTERS */
+#define MG_CM3_CONFI_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
+#define MG_CM3_SRAM_BASE(CP)		MG_CM3_CONFI_BASE(CP)
+#define MG_CM3_CONFI_GLOB_CFG_REG(CP)	(MG_CM3_CONFI_BASE(CP) + 0x2B500)
+#define CM3_CPU_EN_BIT			BIT(28)
+#define MG_CM3_MG_INT_MFX_REG(CP)	(MG_CM3_CONFI_BASE(CP) + 0x2B054)
+#define CM3_SYS_RESET_BIT		BIT(0)
+
+#define MG_CM3_SHARED_MEM_BASE(CP)	(MG_CM3_SRAM_BASE(CP) + 0x1FC00ULL)
+
+#define MG_SRAM_SIZE	0x20000 /* 128KB */
+
+#define MG_ACK_TIMEOUT 10
+
+/**
+ * struct ap_sharedmem_ctrl - used to pass information between the HOST and CM3
+ * @init_done:	Set by CM3 when ap_proces initialzied. Host check if CM3 set
+ *		this flag to confirm that the process is running
+ * @lane_nr:	Set by Host to mark which comphy lane should be configure. E.g.:
+ *		- A8K development board uses comphy lane 2 for eth0
+ *		- CN913x development board uses comphy lane 4 for eth0
+ */
+struct ap_sharedmem_ctrl {
+	uint32_t init_done;
+	uint32_t lane_nr;
+};
+
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index)
+{
+	uintptr_t mg_regs = MG_CM3_SRAM_BASE(cp_index);
+
+	if (size > MG_SRAM_SIZE) {
+		ERROR("image is too big to fit into MG CM3 memory\n");
+		return 1;
+	}
+
+	NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
+	       src_addr, size, mg_regs);
+
+	/* Copy image to MG CM3 SRAM */
+	memcpy((void *)mg_regs, (void *)src_addr, size);
+
+	/* Don't release MG CM3 from reset - it will be done by next step
+	 * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
+	 * has enabeld 802.3. auto-neg) will be choosen.
+	 */
+
+	return 0;
+}
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index)
+{
+	volatile struct ap_sharedmem_ctrl *ap_shared_ctrl =
+					(void *)MG_CM3_SHARED_MEM_BASE(cp_nr);
+	int timeout = MG_ACK_TIMEOUT;
+
+	if (mmio_read_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr)) & CM3_CPU_EN_BIT) {
+		VERBOSE("cm3 already running\n");
+		return;  /* cm3 already running */
+	}
+
+	/*
+	 * Mark which comphy lane should be used - it will be read via shared
+	 * mem by ap process
+	 */
+	ap_shared_ctrl->lane_nr = comphy_index;
+	/* Make sure it took place before enabling cm3 */
+	dmbst();
+
+	mmio_setbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), CM3_CPU_EN_BIT);
+	mmio_setbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), CM3_SYS_RESET_BIT);
+
+	/* Check for ap process initialization by fw */
+	while (ap_shared_ctrl->init_done != 1 && timeout--)
+		VERBOSE("Waiting for ap process ack, timeout %d\n", timeout);
+
+	if (timeout == 0) {
+		ERROR("AP process failed, disabling cm3\n");
+		mmio_clrbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr),
+				CM3_SYS_RESET_BIT);
+		mmio_clrbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr),
+				CM3_CPU_EN_BIT);
+	}
+}
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
new file mode 100644
index 0000000..e2756de
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index);
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index);
diff --git a/drivers/measured_boot/event_log.c b/drivers/measured_boot/event_log.c
new file mode 100644
index 0000000..0042c96
--- /dev/null
+++ b/drivers/measured_boot/event_log.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <arch_helpers.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/event_log.h>
+#include <mbedtls/md.h>
+
+#include <plat/common/platform.h>
+
+/* Event Log data */
+static uint8_t event_log[EVENT_LOG_SIZE];
+
+/* End of Event Log */
+#define	EVENT_LOG_END	((uintptr_t)event_log + sizeof(event_log) - 1U)
+
+CASSERT(sizeof(event_log) >= LOG_MIN_SIZE, assert_event_log_size);
+
+/* Pointer in event_log[] */
+static uint8_t *log_ptr = event_log;
+
+/* Pointer to measured_boot_data_t */
+const static measured_boot_data_t *plat_data_ptr;
+
+static uintptr_t tos_fw_config_base;
+static uintptr_t nt_fw_config_base;
+
+/* TCG_EfiSpecIdEvent */
+static const id_event_headers_t id_event_header = {
+	.header = {
+		.pcr_index = PCR_0,
+		.event_type = EV_NO_ACTION,
+		.digest = {0},
+		.event_size = (uint32_t)(sizeof(id_event_struct_t) +
+				(sizeof(id_event_algorithm_size_t) *
+				HASH_ALG_COUNT))
+	},
+
+	.struct_header = {
+		.signature = TCG_ID_EVENT_SIGNATURE_03,
+		.platform_class = PLATFORM_CLASS_CLIENT,
+		.spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
+		.spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
+		.spec_errata = TCG_SPEC_ERRATA_TPM2,
+		.uintn_size = (uint8_t)(sizeof(unsigned int) /
+					sizeof(uint32_t)),
+		.number_of_algorithms = HASH_ALG_COUNT
+	}
+};
+
+static const event2_header_t locality_event_header = {
+		/*
+		 * All EV_NO_ACTION events SHALL set
+		 * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
+		 */
+		.pcr_index = PCR_0,
+
+		/*
+		 * All EV_NO_ACTION events SHALL set
+		 * TCG_PCR_EVENT2.eventType = 03h
+		 */
+		.event_type = EV_NO_ACTION,
+
+		/*
+		 * All EV_NO_ACTION events SHALL set
+		 * TCG_PCR_EVENT2.digests to all
+		 * 0x00's for each allocated Hash algorithm
+		 */
+		.digests = {
+			.count = HASH_ALG_COUNT
+		}
+};
+
+/* Platform's table with platform specific image IDs, names and PCRs */
+static const image_data_t plat_images_data[] = {
+	{ BL2_IMAGE_ID, BL2_STRING, PCR_0 },		/* Reserved for BL2 */
+	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+};
+
+static const measured_boot_data_t plat_measured_boot_data = {
+	plat_images_data,
+	NULL,	/* platform_set_nt_fw_info */
+	NULL	/* platform_set_tos_fw_info */
+};
+
+/*
+ * Function retuns pointer to platform's measured_boot_data_t structure
+ *
+ * Must be overridden in the platform code
+ */
+#pragma weak plat_get_measured_boot_data
+
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+	return &plat_measured_boot_data;
+}
+
+/*
+ * Add TCG_PCR_EVENT2 event
+ *
+ * @param[in] hash	Pointer to hash data of TCG_DIGEST_SIZE bytes
+ * @param[in] image_ptr	Pointer to image_data_t structure
+ * @return:
+ *	0 = success
+ *    < 0 = error code
+ */
+static int add_event2(const uint8_t *hash, const image_data_t *image_ptr)
+{
+	void *ptr = log_ptr;
+	uint32_t name_len;
+	uint32_t size_of_event;
+
+	assert(image_ptr != NULL);
+	assert(image_ptr->name != NULL);
+
+	name_len = (uint32_t)strlen(image_ptr->name) + 1U;
+	size_of_event = name_len + (uint32_t)EVENT2_HDR_SIZE;
+
+	/* Check for space in Event Log buffer */
+	if (((uintptr_t)ptr + size_of_event) > EVENT_LOG_END) {
+		ERROR("%s(): Event Log is short of memory", __func__);
+		return -ENOMEM;
+	}
+
+	/*
+	 * As per TCG specifications, firmware components that are measured
+	 * into PCR[0] must be logged in the event log using the event type
+	 * EV_POST_CODE.
+	 */
+	/* TCG_PCR_EVENT2.PCRIndex */
+	((event2_header_t *)ptr)->pcr_index = image_ptr->pcr;
+
+	/* TCG_PCR_EVENT2.EventType */
+	((event2_header_t *)ptr)->event_type = EV_POST_CODE;
+
+	/* TCG_PCR_EVENT2.Digests.Count */
+	ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
+	((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
+
+	/* TCG_PCR_EVENT2.Digests[] */
+	ptr = (uint8_t *)ptr + offsetof(tpml_digest_values, digests);
+
+	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+	/* TCG_PCR_EVENT2.Digests[].Digest[] */
+	ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest);
+
+	/* Check for space in Event Log buffer */
+	if (((uintptr_t)ptr + TCG_DIGEST_SIZE) > EVENT_LOG_END) {
+		ERROR("%s(): Event Log is short of memory", __func__);
+		return -ENOMEM;
+	}
+
+	if (hash == NULL) {
+		/* Get BL2 hash from DTB */
+		bl2_plat_get_hash(ptr);
+	} else {
+		/* Copy digest */
+		(void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
+	}
+
+	/* TCG_PCR_EVENT2.EventSize */
+	ptr = (uint8_t *)ptr + TCG_DIGEST_SIZE;
+	((event2_data_t *)ptr)->event_size = name_len;
+
+	/* Copy event data to TCG_PCR_EVENT2.Event */
+	(void)memcpy((void *)(((event2_data_t *)ptr)->event),
+			(const void *)image_ptr->name, name_len);
+
+	/* End of event data */
+	log_ptr = (uint8_t *)ptr + offsetof(event2_data_t, event) + name_len;
+
+	return 0;
+}
+
+/*
+ * Init Event Log
+ *
+ * Initialises Event Log by writing Specification ID and
+ * Startup Locality events.
+ */
+void event_log_init(void)
+{
+	const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
+	const uint8_t *start_ptr;
+	void *ptr = event_log;
+
+	/* Get pointer to platform's measured_boot_data_t structure */
+	plat_data_ptr = plat_get_measured_boot_data();
+
+	/*
+	 * Add Specification ID Event first
+	 *
+	 * Copy TCG_EfiSpecIDEventStruct structure header
+	 */
+	(void)memcpy(ptr, (const void *)&id_event_header,
+			sizeof(id_event_header));
+	ptr = (uint8_t *)ptr + sizeof(id_event_header);
+
+	/* TCG_EfiSpecIdEventAlgorithmSize structure */
+	((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
+	((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
+	ptr = (uint8_t *)ptr + sizeof(id_event_algorithm_size_t);
+
+	/*
+	 * TCG_EfiSpecIDEventStruct.vendorInfoSize
+	 * No vendor data
+	 */
+	((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
+	ptr = (uint8_t *)ptr + offsetof(id_event_struct_data_t, vendor_info);
+	if ((uintptr_t)ptr != ((uintptr_t)event_log + ID_EVENT_SIZE)) {
+		panic();
+	}
+
+	start_ptr = (uint8_t *)ptr;
+
+	/*
+	 * The Startup Locality event should be placed in the log before
+	 * any event which extends PCR[0].
+	 *
+	 * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+	 */
+
+	/* Copy Startup Locality Event Header */
+	(void)memcpy(ptr, (const void *)&locality_event_header,
+			sizeof(locality_event_header));
+	ptr = (uint8_t *)ptr + sizeof(locality_event_header);
+
+	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+	/* TCG_PCR_EVENT2.Digests[].Digest[] */
+	(void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID);
+	ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE;
+
+	/* TCG_PCR_EVENT2.EventSize */
+	((event2_data_t *)ptr)->event_size =
+		(uint32_t)sizeof(startup_locality_event_t);
+	ptr = (uint8_t *)ptr + offsetof(event2_data_t, event);
+
+	/* TCG_EfiStartupLocalityEvent.Signature */
+	(void)memcpy(ptr, (const void *)locality_signature,
+		sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
+
+	/*
+	 * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
+	 * the platform's boot firmware
+	 */
+	((startup_locality_event_t *)ptr)->startup_locality = 0U;
+	ptr = (uint8_t *)ptr + sizeof(startup_locality_event_t);
+	if ((uintptr_t)ptr != ((uintptr_t)start_ptr + LOC_EVENT_SIZE)) {
+		panic();
+	}
+
+	log_ptr = (uint8_t *)ptr;
+
+	/* Add BL2 event */
+	if (add_event2(NULL, plat_data_ptr->images_data) != 0) {
+		panic();
+	}
+}
+
+/*
+ * Calculate and write hash of image, configuration data, etc.
+ * to Event Log.
+ *
+ * @param[in] data_base		Address of data
+ * @param[in] data_size		Size of data
+ * @param[in] data_id		Data ID
+ * @return:
+ *	0 = success
+ *    < 0 = error
+ */
+int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
+			   uint32_t data_id)
+{
+	const image_data_t *data_ptr = plat_data_ptr->images_data;
+	unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
+	int rc;
+
+	/* Check if image_id is supported */
+	while (data_ptr->id != data_id) {
+		if ((data_ptr++)->id == INVALID_ID) {
+			ERROR("%s(): image_id %u not supported\n",
+				__func__, data_id);
+			return -EINVAL;
+		}
+	}
+
+	if (data_id == TOS_FW_CONFIG_ID) {
+		tos_fw_config_base = data_base;
+	} else if (data_id == NT_FW_CONFIG_ID) {
+		nt_fw_config_base = data_base;
+	} else {
+		/* No action */
+	}
+
+	/* Calculate hash */
+	rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
+				(void *)data_base, data_size, hash_data);
+	if (rc != 0) {
+		return rc;
+	}
+
+	return add_event2(hash_data, data_ptr);
+}
+
+/*
+ * Finalise Event Log
+ *
+ * @param[out] log_addr	Pointer to return Event Log address
+ * @param[out] log_size	Pointer to return Event Log size
+ * @return:
+ *	0 = success
+ *    < 0 = error code
+ */
+int event_log_finalise(uint8_t **log_addr, size_t *log_size)
+{
+	/* Event Log size */
+	size_t num_bytes = (uintptr_t)log_ptr - (uintptr_t)event_log;
+	int rc;
+
+	assert(log_addr != NULL);
+	assert(log_size != NULL);
+
+	if (nt_fw_config_base == 0UL) {
+		ERROR("%s(): %s_FW_CONFIG not loaded\n", __func__, "NT");
+		return -ENOENT;
+	}
+
+	/*
+	 * Set Event Log data in NT_FW_CONFIG and
+	 * get Event Log address in Non-Secure memory
+	 */
+	if (plat_data_ptr->set_nt_fw_info != NULL) {
+
+		/* Event Log address in Non-Secure memory */
+		uintptr_t ns_log_addr;
+
+		rc = plat_data_ptr->set_nt_fw_info(
+				nt_fw_config_base,
+#ifdef SPD_opteed
+				(uintptr_t)event_log,
+#endif
+				num_bytes, &ns_log_addr);
+		if (rc != 0) {
+			ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+						__func__, "NT");
+			return rc;
+		}
+
+		/* Copy Event Log to Non-secure memory */
+		(void)memcpy((void *)ns_log_addr, (const void *)event_log,
+				num_bytes);
+
+		/* Ensure that the Event Log is visible in Non-secure memory */
+		flush_dcache_range(ns_log_addr, num_bytes);
+
+		/* Return Event Log address in Non-Secure memory */
+		*log_addr = (uint8_t *)ns_log_addr;
+
+	} else {
+		INFO("%s(): set_%s_fw_info not set\n", __func__, "nt");
+
+		/* Return Event Log address in Secure memory */
+		*log_addr = event_log;
+	}
+
+	if (tos_fw_config_base != 0UL) {
+		if (plat_data_ptr->set_tos_fw_info != NULL) {
+
+			/* Set Event Log data in TOS_FW_CONFIG */
+			rc = plat_data_ptr->set_tos_fw_info(
+						tos_fw_config_base,
+						(uintptr_t)event_log,
+						num_bytes);
+			if (rc != 0) {
+				ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+						__func__, "TOS");
+				return rc;
+			}
+		} else {
+			INFO("%s(): set_%s_fw_info not set\n", __func__, "tos");
+		}
+	} else {
+		INFO("%s(): %s_FW_CONFIG not loaded\n", __func__, "TOS");
+	}
+
+	/* Ensure that the Event Log is visible in Secure memory */
+	flush_dcache_range((uintptr_t)event_log, num_bytes);
+
+	/* Return Event Log size */
+	*log_size = num_bytes;
+
+	return 0;
+}
diff --git a/drivers/measured_boot/event_print.c b/drivers/measured_boot/event_print.c
new file mode 100644
index 0000000..ed970b8
--- /dev/null
+++ b/drivers/measured_boot/event_print.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/event_log.h>
+
+#if LOG_LEVEL >= EVENT_LOG_LEVEL
+
+/*
+ * Print TCG_EfiSpecIDEventStruct
+ *
+ * @param[in/out] log_addr	Pointer to Event Log
+ * @param[in/out] log_size	Pointer to Event Log size
+ */
+static void id_event_print(uint8_t **log_addr, size_t *log_size)
+{
+	unsigned int i;
+	uint8_t info_size, *info_size_ptr;
+	void *ptr = *log_addr;
+	id_event_headers_t *event = (id_event_headers_t *)ptr;
+	id_event_algorithm_size_t *alg_ptr;
+	uint32_t event_size, number_of_algorithms;
+	size_t digest_len;
+#if ENABLE_ASSERTIONS
+	const uint8_t *end_ptr = *log_addr + *log_size;
+	bool valid = true;
+#endif
+
+	assert(*log_size >= sizeof(id_event_headers_t));
+
+	/* The fields of the event log header are defined to be PCRIndex of 0,
+	 * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
+	 * Event content defined as TCG_EfiSpecIDEventStruct.
+	 */
+	LOG_EVENT("TCG_EfiSpecIDEvent:\n");
+	LOG_EVENT("  PCRIndex           : %u\n", event->header.pcr_index);
+	assert(event->header.pcr_index == (uint32_t)PCR_0);
+
+	LOG_EVENT("  EventType          : %u\n", event->header.event_type);
+	assert(event->header.event_type == EV_NO_ACTION);
+
+	LOG_EVENT("  Digest             :");
+	for (i = 0U; i < sizeof(event->header.digest); ++i) {
+		uint8_t val = event->header.digest[i];
+
+		(void)printf(" %02x", val);
+		if ((i & U(0xF)) == 0U) {
+			(void)printf("\n");
+			LOG_EVENT("\t\t      :");
+		}
+#if ENABLE_ASSERTIONS
+		if (val != 0U) {
+			valid = false;
+		}
+#endif
+	}
+	if ((i & U(0xF)) != 0U) {
+		(void)printf("\n");
+	}
+
+	assert(valid);
+
+	/* EventSize */
+	event_size = event->header.event_size;
+	LOG_EVENT("  EventSize          : %u\n", event_size);
+
+	LOG_EVENT("  Signature          : %s\n",
+			event->struct_header.signature);
+	LOG_EVENT("  PlatformClass      : %u\n",
+			event->struct_header.platform_class);
+	LOG_EVENT("  SpecVersion        : %u.%u.%u\n",
+			event->struct_header.spec_version_major,
+			event->struct_header.spec_version_minor,
+			event->struct_header.spec_errata);
+	LOG_EVENT("  UintnSize          : %u\n",
+			event->struct_header.uintn_size);
+
+	/* NumberOfAlgorithms */
+	number_of_algorithms = event->struct_header.number_of_algorithms;
+	LOG_EVENT("  NumberOfAlgorithms : %u\n", number_of_algorithms);
+
+	/* Address of DigestSizes[] */
+	alg_ptr = event->struct_header.digest_size;
+
+	/* Size of DigestSizes[] */
+	digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
+	assert(((uint8_t *)alg_ptr + digest_len) <= end_ptr);
+
+	LOG_EVENT("  DigestSizes        :\n");
+	for (i = 0U; i < number_of_algorithms; ++i) {
+		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
+		uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+
+		switch (algorithm_id) {
+		case TPM_ALG_SHA256:
+			(void)printf("256\n");
+			break;
+		case TPM_ALG_SHA384:
+			(void)printf("384\n");
+			break;
+		case TPM_ALG_SHA512:
+			(void)printf("512\n");
+			break;
+		default:
+			(void)printf("?\n");
+			ERROR("Algorithm 0x%x not found\n", algorithm_id);
+			assert(false);
+		}
+
+		LOG_EVENT("       DigestSize    : %u\n",
+					alg_ptr[i].digest_size);
+	}
+
+	/* Address of VendorInfoSize */
+	info_size_ptr = (uint8_t *)alg_ptr + digest_len;
+	assert(info_size_ptr <= end_ptr);
+
+	info_size = *info_size_ptr++;
+	LOG_EVENT("  VendorInfoSize     : %u\n", info_size);
+
+	/* Check VendorInfo end address */
+	assert((info_size_ptr + info_size) <= end_ptr);
+
+	/* Check EventSize */
+	assert(event_size == (sizeof(id_event_struct_t) +
+				digest_len + info_size));
+	if (info_size != 0U) {
+		LOG_EVENT("  VendorInfo         :");
+		for (i = 0U; i < info_size; ++i) {
+			(void)printf(" %02x", *info_size_ptr++);
+		}
+		(void)printf("\n");
+	}
+
+	*log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
+	*log_addr = info_size_ptr;
+}
+
+/*
+ * Print TCG_PCR_EVENT2
+ *
+ * @param[in/out] log_addr	Pointer to Event Log
+ * @param[in/out] log_size	Pointer to Event Log size
+ */
+static void event2_print(uint8_t **log_addr, size_t *log_size)
+{
+	uint32_t event_size, count;
+	size_t sha_size, digests_size = 0U;
+	void *ptr = *log_addr;
+#if ENABLE_ASSERTIONS
+	const uint8_t *end_ptr = *log_addr + *log_size;
+#endif
+
+	assert(*log_size >= sizeof(event2_header_t));
+
+	LOG_EVENT("PCR_Event2:\n");
+	LOG_EVENT("  PCRIndex           : %u\n",
+			((event2_header_t *)ptr)->pcr_index);
+	LOG_EVENT("  EventType          : %u\n",
+			((event2_header_t *)ptr)->event_type);
+
+	count = ((event2_header_t *)ptr)->digests.count;
+	LOG_EVENT("  Digests Count      : %u\n", count);
+
+	/* Address of TCG_PCR_EVENT2.Digests[] */
+	ptr = (uint8_t *)ptr + sizeof(event2_header_t);
+	assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U));
+
+	for (unsigned int i = 0U; i < count; ++i) {
+		/* Check AlgorithmId address */
+		assert(((uint8_t *)ptr + offsetof(tpmt_ha, digest)) <= end_ptr);
+
+		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
+		switch (((tpmt_ha *)ptr)->algorithm_id) {
+		case TPM_ALG_SHA256:
+			sha_size = SHA256_DIGEST_SIZE;
+			(void)printf("256\n");
+			break;
+		case TPM_ALG_SHA384:
+			sha_size = SHA384_DIGEST_SIZE;
+			(void)printf("384\n");
+			break;
+		case TPM_ALG_SHA512:
+			sha_size = SHA512_DIGEST_SIZE;
+			(void)printf("512\n");
+			break;
+		default:
+			(void)printf("?\n");
+			ERROR("Algorithm 0x%x not found\n",
+				((tpmt_ha *)ptr)->algorithm_id);
+			panic();
+		}
+
+		/* End of Digest[] */
+		ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest);
+		assert(((uint8_t *)ptr + sha_size) <= end_ptr);
+
+		/* Total size of all digests */
+		digests_size += sha_size;
+
+		LOG_EVENT("       Digest        :");
+		for (unsigned int j = 0U; j < sha_size; ++j) {
+			(void)printf(" %02x", *(uint8_t *)ptr++);
+			if ((j & U(0xF)) == U(0xF)) {
+				(void)printf("\n");
+				if (j < (sha_size - 1U)) {
+					LOG_EVENT("\t\t      :");
+				}
+			}
+		}
+	}
+
+	/* TCG_PCR_EVENT2.EventSize */
+	assert(((uint8_t *)ptr + offsetof(event2_data_t, event)) <= end_ptr);
+
+	event_size = ((event2_data_t *)ptr)->event_size;
+	LOG_EVENT("  EventSize          : %u\n", event_size);
+
+	/* Address of TCG_PCR_EVENT2.Event[EventSize] */
+	ptr = (uint8_t *)ptr + offsetof(event2_data_t, event);
+
+	/* End of TCG_PCR_EVENT2.Event[EventSize] */
+	assert(((uint8_t *)ptr + event_size) <= end_ptr);
+
+	if ((event_size == sizeof(startup_locality_event_t)) &&
+	     (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
+		LOG_EVENT("  Signature          : %s\n",
+			((startup_locality_event_t *)ptr)->signature);
+		LOG_EVENT("  StartupLocality    : %u\n",
+			((startup_locality_event_t *)ptr)->startup_locality);
+	} else {
+		LOG_EVENT("  Event              : %s\n", (uint8_t *)ptr);
+	}
+
+	*log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
+	*log_addr = (uint8_t *)ptr + event_size;
+}
+#endif	/* LOG_LEVEL >= EVENT_LOG_LEVEL */
+
+/*
+ * Print Event Log
+ *
+ * @param[in]	log_addr	Pointer to Event Log
+ * @param[in]	log_size	Event Log size
+ */
+void dump_event_log(uint8_t *log_addr, size_t log_size)
+{
+#if LOG_LEVEL >= EVENT_LOG_LEVEL
+	assert(log_addr != NULL);
+
+	/* Print TCG_EfiSpecIDEvent */
+	id_event_print(&log_addr, &log_size);
+
+	while (log_size != 0U) {
+		event2_print(&log_addr, &log_size);
+	}
+#endif
+}
diff --git a/drivers/measured_boot/measured_boot.c b/drivers/measured_boot/measured_boot.c
new file mode 100644
index 0000000..37fddfb
--- /dev/null
+++ b/drivers/measured_boot/measured_boot.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/measured_boot.h>
+
+/*
+ * Init Measured Boot driver
+ *
+ * Initialises Event Log.
+ */
+void measured_boot_init(void)
+{
+	event_log_init();
+}
+
+/*
+ * Finish Measured Boot driver
+ *
+ * Finalises Event Log and dumps the records to the debug console.
+ */
+void measured_boot_finish(void)
+{
+	uint8_t *log_addr;
+	size_t log_size;
+	int rc;
+
+	rc = event_log_finalise(&log_addr, &log_size);
+	if (rc != 0) {
+		panic();
+	}
+
+	dump_event_log(log_addr, log_size);
+}
diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/measured_boot.mk
new file mode 100644
index 0000000..fc005d5
--- /dev/null
+++ b/drivers/measured_boot/measured_boot.mk
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TPM hash algorithm
+TPM_HASH_ALG			:=	sha256
+
+ifeq (${TPM_HASH_ALG}, sha512)
+    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA512
+    TPM_ALG_ID			:=	TPM_ALG_SHA512
+    TCG_DIGEST_SIZE		:=	64U
+else ifeq (${TPM_HASH_ALG}, sha384)
+    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA384
+    TPM_ALG_ID			:=	TPM_ALG_SHA384
+    TCG_DIGEST_SIZE		:=	48U
+else
+    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA256
+    TPM_ALG_ID			:=	TPM_ALG_SHA256
+    TCG_DIGEST_SIZE		:=	32U
+endif
+
+# Event Log length in bytes
+EVENT_LOG_SIZE			:= 1024
+
+# Set definitions for mbed TLS library and Measured Boot driver
+$(eval $(call add_define,MBEDTLS_MD_ID))
+$(eval $(call add_define,TPM_ALG_ID))
+$(eval $(call add_define,TCG_DIGEST_SIZE))
+$(eval $(call add_define,EVENT_LOG_SIZE))
+
+ifeq (${HASH_ALG}, sha256)
+ifneq (${TPM_HASH_ALG}, sha256)
+$(eval $(call add_define,MBEDTLS_SHA512_C))
+endif
+endif
+
+MEASURED_BOOT_SRC_DIR	:= drivers/measured_boot/
+
+MEASURED_BOOT_SOURCES	:= ${MEASURED_BOOT_SRC_DIR}measured_boot.c	\
+    			   ${MEASURED_BOOT_SRC_DIR}event_log.c		\
+    			   ${MEASURED_BOOT_SRC_DIR}event_print.c
+
+BL2_SOURCES		+= ${MEASURED_BOOT_SOURCES}
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 2f4dcad..d6cd8b1 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -577,6 +577,43 @@
 	1, 2, 3, 4, 4, 4, 4, 4
 };
 
+static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
+	[_HSI] = "HSI",
+	[_HSE] = "HSE",
+	[_CSI] = "CSI",
+	[_LSI] = "LSI",
+	[_LSE] = "LSE",
+	[_I2S_CKIN] = "I2S_CKIN",
+	[_HSI_KER] = "HSI_KER",
+	[_HSE_KER] = "HSE_KER",
+	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
+	[_CSI_KER] = "CSI_KER",
+	[_PLL1_P] = "PLL1_P",
+	[_PLL1_Q] = "PLL1_Q",
+	[_PLL1_R] = "PLL1_R",
+	[_PLL2_P] = "PLL2_P",
+	[_PLL2_Q] = "PLL2_Q",
+	[_PLL2_R] = "PLL2_R",
+	[_PLL3_P] = "PLL3_P",
+	[_PLL3_Q] = "PLL3_Q",
+	[_PLL3_R] = "PLL3_R",
+	[_PLL4_P] = "PLL4_P",
+	[_PLL4_Q] = "PLL4_Q",
+	[_PLL4_R] = "PLL4_R",
+	[_ACLK] = "ACLK",
+	[_PCLK1] = "PCLK1",
+	[_PCLK2] = "PCLK2",
+	[_PCLK3] = "PCLK3",
+	[_PCLK4] = "PCLK4",
+	[_PCLK5] = "PCLK5",
+	[_HCLK6] = "KCLK6",
+	[_HCLK2] = "HCLK2",
+	[_CK_PER] = "CK_PER",
+	[_CK_MPU] = "CK_MPU",
+	[_CK_MCU] = "CK_MCU",
+	[_USB_PHY_48] = "USB_PHY_48",
+};
+
 /* RCC clock device driver private */
 static unsigned long stm32mp1_osc[NB_OSC];
 static struct spinlock reg_lock;
@@ -2007,6 +2044,165 @@
 	}
 }
 
+#ifdef STM32MP_SHARED_RESOURCES
+/*
+ * Get the parent ID of the target parent clock, for tagging as secure
+ * shared clock dependencies.
+ */
+static int get_parent_id_parent(unsigned int parent_id)
+{
+	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
+	enum stm32mp1_pll_id pll_id;
+	uint32_t p_sel;
+	uintptr_t rcc_base = stm32mp_rcc_base();
+
+	switch (parent_id) {
+	case _ACLK:
+	case _PCLK4:
+	case _PCLK5:
+		s = _AXIS_SEL;
+		break;
+	case _PLL1_P:
+	case _PLL1_Q:
+	case _PLL1_R:
+		pll_id = _PLL1;
+		break;
+	case _PLL2_P:
+	case _PLL2_Q:
+	case _PLL2_R:
+		pll_id = _PLL2;
+		break;
+	case _PLL3_P:
+	case _PLL3_Q:
+	case _PLL3_R:
+		pll_id = _PLL3;
+		break;
+	case _PLL4_P:
+	case _PLL4_Q:
+	case _PLL4_R:
+		pll_id = _PLL4;
+		break;
+	case _PCLK1:
+	case _PCLK2:
+	case _HCLK2:
+	case _HCLK6:
+	case _CK_PER:
+	case _CK_MPU:
+	case _CK_MCU:
+	case _USB_PHY_48:
+		/* We do not expect to access these */
+		panic();
+		break;
+	default:
+		/* Other parents have no parent */
+		return -1;
+	}
+
+	if (s != _UNKNOWN_SEL) {
+		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
+
+		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
+			sel->msk;
+
+		if (p_sel < sel->nb_parent) {
+			return (int)sel->parent[p_sel];
+		}
+	} else {
+		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+
+		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
+			RCC_SELR_REFCLK_SRC_MASK;
+
+		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
+			return (int)pll->refclk[p_sel];
+		}
+	}
+
+	VERBOSE("No parent selected for %s\n",
+		stm32mp1_clk_parent_name[parent_id]);
+
+	return -1;
+}
+
+static void secure_parent_clocks(unsigned long parent_id)
+{
+	int grandparent_id;
+
+	switch (parent_id) {
+	case _PLL3_P:
+	case _PLL3_Q:
+	case _PLL3_R:
+		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+		break;
+
+	/* These clocks are always secure when RCC is secure */
+	case _ACLK:
+	case _HCLK2:
+	case _HCLK6:
+	case _PCLK4:
+	case _PCLK5:
+	case _PLL1_P:
+	case _PLL1_Q:
+	case _PLL1_R:
+	case _PLL2_P:
+	case _PLL2_Q:
+	case _PLL2_R:
+	case _HSI:
+	case _HSI_KER:
+	case _LSI:
+	case _CSI:
+	case _CSI_KER:
+	case _HSE:
+	case _HSE_KER:
+	case _HSE_KER_DIV2:
+	case _LSE:
+		break;
+
+	default:
+		VERBOSE("Cannot secure parent clock %s\n",
+			stm32mp1_clk_parent_name[parent_id]);
+		panic();
+	}
+
+	grandparent_id = get_parent_id_parent(parent_id);
+	if (grandparent_id >= 0) {
+		secure_parent_clocks(grandparent_id);
+	}
+}
+
+void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
+{
+	int parent_id;
+
+	if (!stm32mp1_rcc_is_secure()) {
+		return;
+	}
+
+	switch (clock_id) {
+	case PLL1:
+	case PLL2:
+		/* PLL1/PLL2 are always secure: nothing to do */
+		break;
+	case PLL3:
+		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+		break;
+	case PLL4:
+		ERROR("PLL4 cannot be secured\n");
+		panic();
+		break;
+	default:
+		/* Others are expected gateable clock */
+		parent_id = stm32mp1_clk_get_parent(clock_id);
+		if (parent_id < 0) {
+			INFO("No parent found for clock %lu\n", clock_id);
+		} else {
+			secure_parent_clocks(parent_id);
+		}
+		break;
+	}
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+
 static void sync_earlyboot_clocks_state(void)
 {
 	unsigned int idx;
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 3184df9..515947c 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -300,7 +300,9 @@
 			break;
 		}
 #else
+		/* BL32 uses hash if it is assigned only to secure world */
 		if (hash_info.status == DT_SECURE) {
+			stm32mp_register_secure_periph_iomem(hash_info.base);
 			break;
 		}
 #endif
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index a13c341..bb77371 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -254,6 +254,15 @@
 		mmio_read_32(base + GPIO_AFRH_OFFSET));
 
 	stm32mp_clk_disable(clock);
+
+	if (status == DT_SECURE) {
+		stm32mp_register_secure_gpio(bank, pin);
+		set_gpio_secure_cfg(bank, pin, true);
+
+	} else {
+		stm32mp_register_non_secure_gpio(bank, pin);
+		set_gpio_secure_cfg(bank, pin, false);
+	}
 }
 
 void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
index ea6fbb2..c052b4d 100644
--- a/drivers/st/iwdg/stm32_iwdg.c
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -137,6 +137,12 @@
 			((dt_info.status & DT_NON_SECURE) != 0) ?
 			"non-" : "");
 
+		if ((dt_info.status & DT_NON_SECURE) != 0) {
+			stm32mp_register_non_secure_periph_iomem(iwdg->base);
+		} else {
+			stm32mp_register_secure_periph_iomem(iwdg->base);
+		}
+
 #if defined(IMAGE_BL2)
 		if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) {
 			return -1;
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 9e9dddc..b2bb482 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -54,6 +54,15 @@
 	return fdt_get_status(node);
 }
 
+static bool dt_pmic_is_secure(void)
+{
+	int status = dt_pmic_status();
+
+	return (status >= 0) &&
+	       (status == DT_SECURE) &&
+	       (i2c_handle.dt_status == DT_SECURE);
+}
+
 /*
  * Get PMIC and its I2C bus configuration from the device tree.
  * Return 0 on success, negative on error, 1 if no PMIC node is found.
@@ -223,6 +232,19 @@
 	return true;
 }
 
+static void register_pmic_shared_peripherals(void)
+{
+	uintptr_t i2c_base = i2c_handle.i2c_base_addr;
+
+	if (dt_pmic_is_secure()) {
+		stm32mp_register_secure_periph_iomem(i2c_base);
+	} else {
+		if (i2c_base != 0U) {
+			stm32mp_register_non_secure_periph_iomem(i2c_base);
+		}
+	}
+}
+
 void initialize_pmic(void)
 {
 	unsigned long pmic_version;
@@ -232,6 +254,8 @@
 		return;
 	}
 
+	register_pmic_shared_peripherals();
+
 	if (stpmic1_get_version(&pmic_version) != 0) {
 		ERROR("Failed to access PMIC\n");
 		panic();
diff --git a/fdts/corstone700.dts b/fdts/corstone700.dtsi
similarity index 88%
rename from fdts/corstone700.dts
rename to fdts/corstone700.dtsi
index 851f5e6..2372207 100644
--- a/fdts/corstone700.dts
+++ b/fdts/corstone700.dtsi
@@ -1,22 +1,18 @@
 /*
- * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-/dts-v1/;
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
-	model = "corstone700";
 	compatible = "arm,Corstone-700";
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
-	chosen {
-		bootargs = "console=ttyAMA0 \
-		loglevel=9";
-	};
+	chosen { };
 
 	cpus {
 		#address-cells = <1>;
@@ -28,7 +24,6 @@
 			reg = <0>;
 			next-level-cache = <&L2_0>;
 		};
-
 	};
 
 	memory@80000000 {
@@ -99,7 +94,21 @@
 				<1 14 0xf08>,
 				<1 11 0xf08>,
 				<1 10 0xf08>;
+	};
+
+	refclk: refclk@1a220000 {
+		compatible = "arm,armv7-timer-mem";
+		reg = <0x1a220000  0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		frame@1a230000 {
+			frame-number = <0>;
+			interrupts = <0 2 0xf04>;
+			reg = <0x1a230000 0x1000>;
 		};
+	};
 
 	mbox_es0mhu0: mhu@1b000000 {
 		compatible = "arm,mhuv2","arm,primecell";
@@ -149,5 +158,4 @@
 		      <0x1A010314 0x4>;
 		reg-names = "rstreg", "streg";
 	};
-
 };
diff --git a/fdts/corstone700_fpga.dts b/fdts/corstone700_fpga.dts
new file mode 100644
index 0000000..814d6a8
--- /dev/null
+++ b/fdts/corstone700_fpga.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "corstone700.dtsi"
+
+/ {
+	model = "corstone700-fpga";
+
+	ethernet: eth@40100000 {
+		compatible = "smsc,lan9115";
+		reg = <0x40100000 0x10000>;
+		phy-mode = "mii";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
+	};
+};
+
+&refclk {
+	clock-frequency = <32000000>;
+};
diff --git a/fdts/corstone700_fvp.dts b/fdts/corstone700_fvp.dts
new file mode 100644
index 0000000..3b1202d
--- /dev/null
+++ b/fdts/corstone700_fvp.dts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "corstone700.dtsi"
+
+/ {
+	model = "corstone700-fvp";
+
+	/*
+	* Intel StrataFlash J3 NOR flash: 2 x 16-bit interleaved components
+	* Flash total size: 32 MB
+	* Allocated flash space: 8 MB
+	*/
+
+	flash@8500000 {
+		compatible = "cfi-flash";
+		reg = <0x8500000 0x800000>;
+		bank-width = <4>;
+		device-width= <2>;
+	};
+
+	ethernet: eth@4010000 {
+		compatible = "smsc,lan91c111";
+		reg = <0x40100000 0x10000>;
+		phy-mode = "mii";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 116 0xf04>;
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
+	};
+};
+
+&refclk {
+	clock-frequency = <50000000>;
+};
diff --git a/fdts/cot_descriptors.dtsi b/fdts/cot_descriptors.dtsi
new file mode 100644
index 0000000..9308e17
--- /dev/null
+++ b/fdts/cot_descriptors.dtsi
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tools_share/tbbr_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+
+cot {
+	manifests {
+		compatible = "arm, cert-descs";
+
+		trusted_boot_fw_cert: trusted_boot_fw_cert {
+			root-certificate;
+			image-id =<TRUSTED_BOOT_FW_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tb_fw_hash: tb_fw_hash {
+				oid = TRUSTED_BOOT_FW_HASH_OID;
+			};
+			tb_fw_config_hash: tb_fw_config_hash {
+				oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+			};
+			hw_config_hash: hw_config_hash {
+				oid = HW_CONFIG_HASH_OID;
+			};
+			fw_config_hash: fw_config_hash {
+				oid = FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_key_cert: trusted_key_cert {
+			root-certificate;
+			image-id = <TRUSTED_KEY_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			trusted_world_pk: trusted_world_pk {
+				oid = TRUSTED_WORLD_PK_OID;
+			};
+			non_trusted_world_pk: non_trusted_world_pk {
+				oid = NON_TRUSTED_WORLD_PK_OID;
+			};
+		};
+
+		scp_fw_key_cert: scp_fw_key_cert {
+			image-id = <SCP_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			scp_fw_content_pk: scp_fw_content_pk {
+				oid = SCP_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		scp_fw_content_cert: scp_fw_content_cert {
+			image-id = <SCP_FW_CONTENT_CERT_ID>;
+			parent = <&scp_fw_key_cert>;
+			signing-key = <&scp_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			scp_fw_hash: scp_fw_hash {
+				oid = SCP_FW_HASH_OID;
+			};
+		};
+
+		soc_fw_key_cert: soc_fw_key_cert {
+			image-id = <SOC_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+			soc_fw_content_pk: soc_fw_content_pk {
+				oid = SOC_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		soc_fw_content_cert: soc_fw_content_cert {
+			image-id = <SOC_FW_CONTENT_CERT_ID>;
+			parent = <&soc_fw_key_cert>;
+			signing-key = <&soc_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			soc_fw_hash: soc_fw_hash {
+				oid = SOC_AP_FW_HASH_OID;
+			};
+			soc_fw_config_hash: soc_fw_config_hash {
+				oid = SOC_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_os_fw_key_cert: trusted_os_fw_key_cert {
+			image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_content_pk: tos_fw_content_pk {
+				oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+			image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+			parent = <&trusted_os_fw_key_cert>;
+			signing-key = <&tos_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_hash: tos_fw_hash {
+				oid = TRUSTED_OS_FW_HASH_OID;
+			};
+			tos_fw_extra1_hash: tos_fw_extra1_hash {
+				oid = TRUSTED_OS_FW_EXTRA1_HASH_OID;
+			};
+			tos_fw_extra2_hash: tos_fw_extra2_hash {
+				oid = TRUSTED_OS_FW_EXTRA2_HASH_OID;
+			};
+			tos_fw_config_hash: tos_fw_config_hash {
+				oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		non_trusted_fw_key_cert: non_trusted_fw_key_cert {
+			image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&non_trusted_world_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_fw_content_pk: nt_fw_content_pk {
+				oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+			image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+			parent = <&non_trusted_fw_key_cert>;
+			signing-key = <&nt_fw_content_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_world_bl_hash: nt_world_bl_hash {
+				oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+			};
+			nt_fw_config_hash: nt_fw_config_hash {
+				oid = NON_TRUSTED_FW_CONFIG_HASH_OID;
+			};
+		};
+
+#if defined(SPD_spmd)
+		sip_sp_content_cert: sip_sp_content_cert {
+			image-id = <SIP_SP_CONTENT_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			sp_pkg1_hash: sp_pkg1_hash {
+				oid = SP_PKG1_HASH_OID;
+			};
+			sp_pkg2_hash: sp_pkg2_hash {
+				oid = SP_PKG2_HASH_OID;
+			};
+			sp_pkg3_hash: sp_pkg3_hash {
+				oid = SP_PKG3_HASH_OID;
+			};
+			sp_pkg4_hash: sp_pkg4_hash {
+				oid = SP_PKG4_HASH_OID;
+			};
+			sp_pkg5_hash: sp_pkg5_hash {
+				oid = SP_PKG5_HASH_OID;
+			};
+			sp_pkg6_hash: sp_pkg6_hash {
+				oid = SP_PKG6_HASH_OID;
+			};
+			sp_pkg7_hash: sp_pkg7_hash {
+				oid = SP_PKG7_HASH_OID;
+			};
+			sp_pkg8_hash: sp_pkg8_hash {
+				oid = SP_PKG8_HASH_OID;
+			};
+		};
+#endif
+	};
+
+	images {
+		compatible = "arm, img-descs";
+
+		hw_config {
+			image-id = <HW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&hw_config_hash>;
+		};
+
+		tb_fw_config {
+			image-id = <TB_FW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&tb_fw_config_hash>;
+		};
+
+		scp_bl2_image {
+			image-id = <SCP_BL2_IMAGE_ID>;
+			parent = <&scp_fw_content_cert>;
+			hash = <&scp_fw_hash>;
+		};
+
+		bl31_image {
+			image-id = <BL31_IMAGE_ID>;
+			parent = <&soc_fw_content_cert>;
+			hash = <&soc_fw_hash>;
+		};
+
+		soc_fw_config {
+			image-id = <SOC_FW_CONFIG_ID>;
+			parent = <&soc_fw_content_cert>;
+			hash = <&soc_fw_config_hash>;
+		};
+
+		bl32_image {
+			image-id = <BL32_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_hash>;
+		};
+
+		bl32_extra1_image {
+			image-id = <BL32_EXTRA1_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra1_hash>;
+		};
+
+		bl32_extra2_image {
+			image-id = <BL32_EXTRA2_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra2_hash>;
+		};
+
+		tos_fw_config {
+			image-id = <TOS_FW_CONFIG_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_config_hash>;
+		};
+
+		bl33_image {
+			image-id = <BL33_IMAGE_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_world_bl_hash>;
+		};
+
+		nt_fw_config {
+			image-id = <NT_FW_CONFIG_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_fw_config_hash>;
+		};
+
+#if defined(SPD_spmd)
+		sp_pkg1 {
+			image-id = <SP_PKG1_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg1_hash>;
+		};
+
+		sp_pkg2 {
+			image-id = <SP_PKG2_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg2_hash>;
+		};
+
+		sp_pkg3 {
+			image-id = <SP_PKG3_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg3_hash>;
+		};
+
+		sp_pkg4 {
+			image-id = <SP_PKG4_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg4_hash>;
+		};
+
+		sp_pkg5 {
+			image-id = <SP_PKG5_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg5_hash>;
+		};
+
+		sp_pkg6 {
+			image-id = <SP_PKG6_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg6_hash>;
+		};
+
+		sp_pkg7 {
+			image-id = <SP_PKG7_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg7_hash>;
+		};
+
+		sp_pkg8 {
+			image-id = <SP_PKG8_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg8_hash>;
+		};
+#endif
+	};
+};
+
+non-volatile-counters {
+	compatible = "arm, non-volatile-counter";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	counters {
+		trusted_nv_counter: trusted_nv_counter {
+			oid = TRUSTED_FW_NVCOUNTER_OID;
+		};
+		non_trusted_nv_counter: non_trusted_nv_counter {
+			oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+		};
+	};
+};
diff --git a/fdts/n1sdp-multi-chip.dts b/fdts/n1sdp-multi-chip.dts
new file mode 100644
index 0000000..b58d9d8
--- /dev/null
+++ b/fdts/n1sdp-multi-chip.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+#include "n1sdp-single-chip.dts"
+
+/ {
+	cpus {
+		cpu4@100000000 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x0>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu5@100000100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x00000100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu6@100010000 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x00010000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu7@100010100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x00010100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+	};
+
+	/* Remote N1SDP board address is mapped at offset 4TB.
+	 * First DRAM Bank of remote N1SDP board is mapped at 4TB + 2GB.
+	 */
+	memory@40080000000 {
+		device_type = "memory";
+		reg = <0x00000400 0x80000000 0x0 0x80000000>,
+			<0x00000480 0x80000000 0x3 0x80000000>;
+		numa-node-id = <1>;
+	};
+
+	distance-map {
+		compatible = "numa-distance-map-v1";
+		distance-matrix =   <0 0 10>,
+				    <0 1 20>,
+				    <1 1 10>;
+	};
+};
+
+&gic {
+	#redistributor-regions = <2>;
+	reg =   <0x0 0x30000000 0 0x10000>,	/* GICD */
+		<0x0 0x300c0000 0 0x80000>,	/* GICR */
+		<0x400 0x300c0000 0 0x80000>;	/* GICR */
+};
diff --git a/fdts/n1sdp-single-chip.dts b/fdts/n1sdp-single-chip.dts
new file mode 100644
index 0000000..bd48273
--- /dev/null
+++ b/fdts/n1sdp-single-chip.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+/dts-v1/;
+
+#include "n1sdp.dtsi"
+
+/ {
+	model = "Arm Neoverse N1 System Development Platform";
+	compatible = "arm,neoverse-n1-sdp", "arm,neoverse-n1-soc";
+
+	aliases {
+		serial0 = &soc_uart0;
+	};
+
+	chosen {
+		stdout-path = "soc_uart0:115200n8";
+	};
+
+	/* This configuration assumes that standard setup with two DIMM modules.
+	 * In the first 2GB of DRAM bank the top 16MB are reserved by firmware as secure memory.
+	 * This configuration assumes 16GB of total DRAM being populated.
+	 */
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000 0x0 0x7f000000>,
+			<0x00000080 0x80000000 0x3 0x80000000>;
+		numa-node-id = <0>;
+	};
+
+	soc_refclk60mhz: refclk60mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <60000000>;
+		clock-output-names = "iofpga_clk";
+	};
+
+	soc_hdlcdclk:  hdlcdclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <23750000>;
+		clock-output-names = "hdlcdclk";
+	};
+
+	hdlcd: hdlcd@1c050000 {
+		compatible = "arm,hdlcd";
+		reg = <0 0x1c050000 0 0x1000>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&soc_hdlcdclk>;
+		clock-names = "pxlclk";
+
+		port {
+			hdlcd0_output: endpoint {
+				remote-endpoint = <&tda998x_0_input>;
+			};
+		};
+	};
+
+	i2c@1c0f0000 {
+		compatible = "arm,versatile-i2c";
+		reg = <0x0 0x1c0f0000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <400000>;
+		i2c-sda-hold-time-ns = <500>;
+		clocks = <&soc_refclk60mhz>;
+
+		hdmi-transmitter@70 {
+			compatible = "nxp,tda998x";
+			reg = <0x70>;
+			port {
+				tda998x_0_input: endpoint {
+					remote-endpoint = <&hdlcd0_output>;
+				};
+			};
+		};
+	};
+};
+
+&pcie_ctlr {
+	status = "okay";
+};
+
+&ccix_pcie_ctlr {
+	status = "okay";
+};
+
+&soc_uart0 {
+	status = "okay";
+};
diff --git a/fdts/n1sdp.dtsi b/fdts/n1sdp.dtsi
new file mode 100644
index 0000000..88f8734
--- /dev/null
+++ b/fdts/n1sdp.dtsi
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0@0 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x0>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu1@100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu2@10000 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x10000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu3@10100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x10100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+	};
+
+	pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	spe-pmu {
+		compatible = "arm,statistical-profiling-extension-v1";
+		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	soc_refclk100mhz: refclk100mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "apb_pclk";
+	};
+
+	soc_uartclk:  uartclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "uartclk";
+	};
+
+	soc {
+		compatible = "arm,neoverse-n1-soc", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller@30000000 {
+			compatible = "arm,gic-v3";
+			#address-cells = <2>;
+			#interrupt-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+			interrupt-controller;
+			reg = <0x0 0x30000000 0 0x10000>,	/* GICD */
+				<0x0 0x300c0000 0 0x80000>;	/* GICR */
+
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+			its1: its@30040000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x30040000 0x0 0x20000>;
+			};
+
+			its2: its@30060000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x30060000 0x0 0x20000>;
+			};
+
+			its_ccix: its@30080000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x30080000 0x0 0x20000>;
+			};
+
+			its_pcie: its@300a0000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x300a0000 0x0 0x20000>;
+			};
+		};
+
+		smmu_ccix: iommu@4f000000 {
+			compatible = "arm,smmu-v3";
+			reg = <0 0x4f000000 0 0x40000>;
+			interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "eventq", "cmdq-sync", "gerror";
+			msi-parent = <&its1 0>;
+			#iommu-cells = <1>;
+			dma-coherent;
+		};
+
+		smmu_pcie: iommu@4f400000 {
+			compatible = "arm,smmu-v3";
+			reg = <0 0x4f400000 0 0x40000>;
+			interrupts = <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 237 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "eventq", "cmdq-sync", "gerror";
+			msi-parent = <&its2 0>;
+			#iommu-cells = <1>;
+			dma-coherent;
+		};
+
+		pcie_ctlr: pcie@70000000 {
+			compatible = "arm,n1sdp-pcie";
+			device_type = "pci";
+			reg = <0 0x70000000 0 0x1200000>;
+			bus-range = <0 17>;
+			linux,pci-domain = <0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			ranges = <0x01000000 0x00 0x00000000 0x00 0x75200000 0x00 0x00010000>,
+				 <0x02000000 0x00 0x71200000 0x00 0x71200000 0x00 0x04000000>,
+				 <0x42000000 0x09 0x00000000 0x09 0x00000000 0x20 0x00000000>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>;
+			msi-map = <0 &its_pcie 0 0x10000>;
+			iommu-map = <0 &smmu_pcie 0 0x10000>;
+			status = "disabled";
+		};
+
+		ccix_pcie_ctlr: pcie@68000000 {
+			compatible = "arm,n1sdp-pcie";
+			device_type = "pci";
+			reg = <0 0x68000000 0 0x1200000>;
+			bus-range = <0 17>;
+			linux,pci-domain = <1>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			ranges = <0x01000000 0x00 0x00000000 0x00 0x6d200000 0x00 0x00010000>,
+				 <0x02000000 0x00 0x69200000 0x00 0x69200000 0x00 0x04000000>,
+				 <0x42000000 0x29 0x00000000 0x29 0x00000000 0x20 0x00000000>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>;
+			msi-map = <0 &its_ccix 0 0x10000>;
+			iommu-map = <0 &smmu_ccix 0 0x10000>;
+			status = "disabled";
+		};
+
+		soc_uart0: serial@2a400000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0x2a400000 0x0 0x1000>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+			clock-names = "uartclk", "apb_pclk";
+			status = "disabled";
+		};
+	};
+};
diff --git a/fdts/optee_sp_manifest.dts b/fdts/optee_sp_manifest.dts
new file mode 100644
index 0000000..02a5ef3
--- /dev/null
+++ b/fdts/optee_sp_manifest.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
+ * that has additional optional properties defined.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "arm,ffa-manifest-1.0";
+
+	/* Properties */
+	description = "op-tee";
+	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+	uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+	id = <1>;
+	execution-ctx-count = <8>;
+	exception-level = <2>; /* S-EL1 */
+	execution-state = <0>; /* AARCH64 */
+	load-address = <0x6280000>;
+	entrypoint-offset = <0x1000>;
+	xlat-granule = <0>; /* 4KiB */
+	boot-order = <0>;
+	messaging-method = <0>; /* Direct messaging only */
+	run-time-model = <1>; /* Run to completion */
+
+	/* Boot protocol */
+	gp-register-num = <0x0>;
+};
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index 1d8da18..a571092 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -9,6 +9,8 @@
 #ifndef FDT_WRAPPERS_H
 #define FDT_WRAPPERS_H
 
+#include <libfdt_env.h>
+
 /* Number of cells, given total length in bytes. Each cell is 4 bytes long */
 #define NCELLS(len) ((len) / 4U)
 
@@ -37,4 +39,11 @@
 uint64_t fdtw_translate_address(const void *dtb, int bus_node,
 				uint64_t base_address);
 
+static inline uint32_t fdt_blob_size(const void *dtb)
+{
+	const uint32_t *dtb_header = dtb;
+
+	return fdt32_to_cpu(dtb_header[1]);
+}
+
 #endif /* FDT_WRAPPERS_H */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index 1f9aab1..b29b135 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -10,7 +10,15 @@
 #include <export/common/tbbr/tbbr_img_def_exp.h>
 
 #if defined(SPD_spmd)
-#define SP_CONTENT_CERT_ID		MAX_IMAGE_IDS
+#define SIP_SP_CONTENT_CERT_ID		MAX_IMAGE_IDS
+#define SP_PKG1_ID			(MAX_IMAGE_IDS + 1)
+#define SP_PKG2_ID			(MAX_IMAGE_IDS + 2)
+#define SP_PKG3_ID			(MAX_IMAGE_IDS + 3)
+#define SP_PKG4_ID			(MAX_IMAGE_IDS + 4)
+#define SP_PKG5_ID			(MAX_IMAGE_IDS + 5)
+#define SP_PKG6_ID			(MAX_IMAGE_IDS + 6)
+#define SP_PKG7_ID			(MAX_IMAGE_IDS + 7)
+#define SP_PKG8_ID			(MAX_IMAGE_IDS + 8)
 #define MAX_SP_IDS			U(8)
 #define MAX_NUMBER_IDS			(MAX_IMAGE_IDS + MAX_SP_IDS + U(1))
 #else
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 97b75b0..18d5b73 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -223,10 +223,10 @@
 #define TYPER_PPI_NUM_MASK	U(0x1f)
 
 /* GICR_IIDR bit definitions */
-#define IIDR_PRODUCT_ID_MASK	0xff000000
-#define IIDR_VARIANT_MASK	0x000f0000
-#define IIDR_REVISION_MASK	0x0000f000
-#define IIDR_IMPLEMENTER_MASK	0x00000fff
+#define IIDR_PRODUCT_ID_MASK	U(0xff000000)
+#define IIDR_VARIANT_MASK	U(0x000f0000)
+#define IIDR_REVISION_MASK	U(0x0000f000)
+#define IIDR_IMPLEMENTER_MASK	U(0x00000fff)
 #define IIDR_MODEL_MASK		(IIDR_PRODUCT_ID_MASK | \
 				 IIDR_IMPLEMENTER_MASK)
 
diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h
index e0e6760..26c444d 100644
--- a/include/drivers/arm/tzc_dmc620.h
+++ b/include/drivers/arm/tzc_dmc620.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,16 +32,16 @@
 /* Address offsets of access address next registers */
 #define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 
 /* Number of TZC address regions in DMC-620 */
 #define DMC620_ACC_ADDR_COUNT	U(8)
diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h
index 01d144d..504e539 100644
--- a/include/drivers/auth/auth_mod.h
+++ b/include/drivers/auth/auth_mod.h
@@ -51,11 +51,11 @@
 extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
 
 #if defined(SPD_spmd)
-#define DEFINE_SP_PKG(n) \
+#define DEFINE_SIP_SP_PKG(n) \
 	static const auth_img_desc_t sp_pkg##n = { \
-		.img_id = SP_CONTENT_CERT_ID + (n), \
+		.img_id = SP_PKG##n##_ID, \
 		.img_type = IMG_RAW, \
-		.parent = &sp_content_cert, \
+		.parent = &sip_sp_content_cert, \
 		.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { \
 			[0] = { \
 				.type = AUTH_METHOD_HASH, \
diff --git a/include/drivers/marvell/cache_llc.h b/include/drivers/marvell/cache_llc.h
index b326474..d6dd653 100644
--- a/include/drivers/marvell/cache_llc.h
+++ b/include/drivers/marvell/cache_llc.h
@@ -41,7 +41,7 @@
 #define LLC_BLK_ALOC_WAY_DATA_DSBL	(0x0 << 6)
 #define LLC_BLK_ALOC_WAY_DATA_CLR	(0x1 << 6)
 #define LLC_BLK_ALOC_WAY_DATA_SET	(0x3 << 6)
-#define LLC_BLK_ALOC_BASE_ADDR(addr)	((addr) & (LLC_WAY_SIZE - 1))
+#define LLC_BLK_ALOC_BASE_ADDR(addr)	((addr) & ~(LLC_WAY_SIZE - 1))
 
 #ifndef __ASSEMBLER__
 void llc_cache_sync(int ap_index);
@@ -53,8 +53,9 @@
 int llc_is_exclusive(int ap_index);
 void llc_runtime_enable(int ap_index);
 #if LLC_SRAM
-void llc_sram_enable(int ap_index);
+int llc_sram_enable(int ap_index, int size);
 void llc_sram_disable(int ap_index);
+int llc_sram_test(int ap_index, int size, char *msg);
 #endif /* LLC_SRAM */
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/drivers/measured_boot/event_log.h b/include/drivers/measured_boot/event_log.h
new file mode 100644
index 0000000..10dfbb3
--- /dev/null
+++ b/include/drivers/measured_boot/event_log.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_H
+#define EVENT_LOG_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/tcg.h>
+
+/*
+ * Set Event Log debug level to one of:
+ *
+ * LOG_LEVEL_ERROR
+ * LOG_LEVEL_INFO
+ * LOG_LEVEL_WARNING
+ * LOG_LEVEL_VERBOSE
+ */
+#define	EVENT_LOG_LEVEL	LOG_LEVEL_INFO
+
+#if EVENT_LOG_LEVEL   == LOG_LEVEL_ERROR
+#define	LOG_EVENT	ERROR
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
+#define	LOG_EVENT	NOTICE
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
+#define	LOG_EVENT	WARN
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
+#define	LOG_EVENT	INFO
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
+#define	LOG_EVENT	VERBOSE
+#else
+#error "Not supported EVENT_LOG_LEVEL"
+#endif
+
+/* Number of hashing algorithms supported */
+#define HASH_ALG_COUNT	1U
+
+#define	INVALID_ID	MAX_NUMBER_IDS
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+#define BL2_STRING			"BL_2"
+#define BL31_STRING			"BL_31"
+#define BL32_STRING			"BL_32"
+#define	BL32_EXTRA1_IMAGE_STRING	"BL32_EXTRA1_IMAGE"
+#define	BL32_EXTRA2_IMAGE_STRING	"BL32_EXTRA2_IMAGE"
+#define BL33_STRING			"BL_33"
+#define GPT_IMAGE_STRING		"GPT"
+#define HW_CONFIG_STRING		"HW_CONFIG"
+#define NT_FW_CONFIG_STRING		"NT_FW_CONFIG"
+#define SCP_BL2_IMAGE_STRING		"SCP_BL2_IMAGE"
+#define SOC_FW_CONFIG_STRING		"SOC_FW_CONFIG"
+#define STM32_IMAGE_STRING		"STM32"
+#define	TOS_FW_CONFIG_STRING		"TOS_FW_CONFIG"
+
+typedef struct {
+	unsigned int id;
+	const char *name;
+	unsigned int pcr;
+} image_data_t;
+
+typedef struct {
+	const image_data_t *images_data;
+	int (*set_nt_fw_info)(uintptr_t config_base,
+#ifdef SPD_opteed
+				uintptr_t log_addr,
+#endif
+				size_t log_size, uintptr_t *ns_log_addr);
+	int (*set_tos_fw_info)(uintptr_t config_base, uintptr_t log_addr,
+				size_t log_size);
+} measured_boot_data_t;
+
+#define	ID_EVENT_SIZE	(sizeof(id_event_headers_t) + \
+			(sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
+			sizeof(id_event_struct_data_t))
+
+#define	LOC_EVENT_SIZE	(sizeof(event2_header_t) + \
+			sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+			sizeof(event2_data_t) + \
+			sizeof(startup_locality_event_t))
+
+#define	LOG_MIN_SIZE	(ID_EVENT_SIZE + LOC_EVENT_SIZE)
+
+#define EVENT2_HDR_SIZE	(sizeof(event2_header_t) + \
+			sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+			sizeof(event2_data_t))
+
+/* Functions' declarations */
+void event_log_init(void);
+int event_log_finalise(uint8_t **log_addr, size_t *log_size);
+void dump_event_log(uint8_t *log_addr, size_t log_size);
+const measured_boot_data_t *plat_get_measured_boot_data(void);
+int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
+			   uint32_t data_id);
+#endif /* EVENT_LOG_H */
diff --git a/include/drivers/measured_boot/measured_boot.h b/include/drivers/measured_boot/measured_boot.h
new file mode 100644
index 0000000..f8769ab
--- /dev/null
+++ b/include/drivers/measured_boot/measured_boot.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEASURED_BOOT_H
+#define MEASURED_BOOT_H
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log.h>
+
+/* Platform specific table of image IDs, names and PCRs */
+extern const image_data_t images_data[];
+
+/* Functions' declarations */
+void measured_boot_init(void);
+void measured_boot_finish(void);
+
+#endif /* MEASURED_BOOT_H */
diff --git a/include/drivers/measured_boot/tcg.h b/include/drivers/measured_boot/tcg.h
new file mode 100644
index 0000000..ab27a08
--- /dev/null
+++ b/include/drivers/measured_boot/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03	"Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE	"StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2   2
+#define TCG_SPEC_VERSION_MINOR_TPM2   0
+#define TCG_SPEC_ERRATA_TPM2          2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT				U(0x00000000)
+#define EV_POST_CODE				U(0x00000001)
+#define	EV_UNUSED				U(0x00000002)
+#define EV_NO_ACTION				U(0x00000003)
+#define EV_SEPARATOR				U(0x00000004)
+#define EV_ACTION				U(0x00000005)
+#define	EV_EVENT_TAG				U(0x00000006)
+#define EV_S_CRTM_CONTENTS			U(0x00000007)
+#define EV_S_CRTM_VERSION			U(0x00000008)
+#define EV_CPU_MICROCODE			U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS		U(0x0000000A)
+#define EV_TABLE_OF_DEVICES			U(0x0000000B)
+#define EV_COMPACT_HASH				U(0x0000000C)
+#define	EV_IPL					U(0x0000000D)
+#define	EV_IPL_PARTITION_DATA			U(0x0000000E)
+#define EV_NONHOST_CODE				U(0x0000000F)
+#define EV_NONHOST_CONFIG			U(0x00000010)
+#define EV_NONHOST_INFO				U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS		U(0x00000012)
+#define	EV_EFI_EVENT_BASE			U(0x80000000)
+#define	EV_EFI_VARIABLE_DRIVER_CONFIG		U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT			U(0x80000002)
+#define	EV_EFI_BOOT_SERVICES_APPLICATION	U(0x80000003)
+#define	EV_EFI_BOOT_SERVICES_DRIVER		U(0x80000004)
+#define	EV_EFI_RUNTIME_SERVICES_DRIVER		U(0x80000005)
+#define	EV_EFI_GPT_EVENT			U(0x80000006)
+#define	EV_EFI_ACTION				U(0x80000007)
+#define	EV_EFI_PLATFORM_FIRMWARE_BLOB		U(0x80000008)
+#define	EV_EFI_HANDOFF_TABLES			U(0x80000009)
+#define	EV_EFI_HCRTM_EVENT			U(0x80000010)
+#define	EV_EFI_VARIABLE_AUTHORITY		U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256		0x000B
+#define TPM_ALG_SHA384		0x000C
+#define TPM_ALG_SHA512		0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT   0
+#define PLATFORM_CLASS_SERVER   1
+
+/* SHA digest sizes in bytes */
+#define SHA1_DIGEST_SIZE	20
+#define SHA256_DIGEST_SIZE	32
+#define SHA384_DIGEST_SIZE	48
+#define SHA512_DIGEST_SIZE	64
+
+enum {
+	/*
+	 * SRTM, BIOS, Host Platform Extensions, Embedded
+	 * Option ROMs and PI Drivers
+	 */
+	PCR_0 = 0,
+	/* Host Platform Configuration */
+	PCR_1,
+	/* UEFI driver and application Code */
+	PCR_2,
+	/* UEFI driver and application Configuration and Data */
+	PCR_3,
+	/* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+	PCR_4,
+	/*
+	 * Boot Manager Code Configuration and Data (for use
+	 * by the Boot Manager Code) and GPT/Partition Table
+	 */
+	PCR_5,
+	/* Host Platform Manufacturer Specific */
+	PCR_6,
+	/* Secure Boot Policy */
+	PCR_7,
+	/* 8-15: Defined for use by the Static OS */
+	PCR_8,
+	/* Debug */
+	PCR_16 = 16
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+	/* PCRIndex:
+	 * The PCR Index to which this event is extended
+	 */
+	uint32_t	pcr_index;
+
+	/* EventType:
+	 * SHALL be an EV_NO_ACTION event
+	 */
+	uint32_t	event_type;
+
+	/* SHALL be 20 Bytes of 0x00 */
+	uint8_t		digest[SHA1_DIGEST_SIZE];
+
+	/* The size of the event */
+	uint32_t	event_size;
+
+	/* SHALL be a TCG_EfiSpecIdEvent */
+	uint8_t		event[];	/* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/* Algorithm ID (hashAlg) of the Hash used by BIOS */
+	uint16_t	algorithm_id;
+
+	/* The size of the digest produced by the implemented Hash algorithm */
+	uint16_t	digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "Spec ID Event03".
+	 * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+	 * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+	 */
+	uint8_t		signature[16];
+
+	/*
+	 * The value for the Platform Class.
+	 * The enumeration is defined in the TCG ACPI Specification Client
+	 * Common Header.
+	 */
+	uint32_t	platform_class;
+
+	/*
+	 * The PC Client Platform Profile Specification minor version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+	 */
+	uint8_t		spec_version_minor;
+
+	/*
+	 * The PC Client Platform Profile Specification major version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_version_major;
+
+	/*
+	 * The PC Client Platform Profile Specification errata version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_errata;
+
+	/*
+	 * Specifies the size of the UINTN fields used in various data
+	 * structures used in this specification.
+	 * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+	 */
+	uint8_t		uintn_size;
+
+	/*
+	 * The number of Hash algorithms in the digestSizes field.
+	 * This field MUST be set to a value of 0x01 or greater.
+	 */
+	uint32_t	number_of_algorithms;
+
+	/*
+	 * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+	 * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+	 * structure, the first of which is a Hash algorithmID and the second
+	 * is the size of the respective digest.
+	 */
+	id_event_algorithm_size_t    digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+	/*
+	 * Size in bytes of the VendorInfo field.
+	 * Maximum value MUST be FFh bytes.
+	 */
+	uint8_t		vendor_info_size;
+
+	/*
+	 * Provided for use by Platform Firmware implementer. The value might
+	 * be used, for example, to provide more detailed information about the
+	 * specific BIOS such as BIOS revision numbers, etc. The values within
+	 * this field are not standardized and are implementer-specific.
+	 * Platform-specific or -unique information MUST NOT be provided in
+	 * this field.
+	 *
+	 */
+	uint8_t		vendor_info[];	/* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+	id_event_struct_header_t	struct_header;
+	id_event_struct_data_t		struct_data;
+} id_event_struct_t;
+
+typedef struct {
+	tcg_pcr_event_t			header;
+	id_event_struct_header_t	struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+	/* Selector of the hash contained in the digest that implies
+	 * the size of the digest
+	 */
+	uint16_t	algorithm_id;	/* AlgorithmId */
+
+	/* Digest, depends on AlgorithmId */
+	uint8_t		digest[];	/* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+	/* The number of digests in the list */
+	uint32_t	count;			/* Count */
+
+	/* The list of tagged digests, as sent to the TPM as part of a
+	 * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+	 */
+	tpmt_ha		digests[];		/* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+	 /* The PCR Index to which this event was extended */
+	uint32_t		pcr_index;	/* PCRIndex */
+
+	/* Type of event */
+	uint32_t		event_type;	/* EventType */
+
+	/* Digests:
+	 * A counted list of tagged digests, which contain the digest of
+	 * the event data (or external data) for all active PCR banks
+	 */
+	tpml_digest_values	digests;	/* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+	/* The size of the event data */
+	uint32_t		event_size;	/* EventSize */
+
+	/* The data of the event */
+	uint8_t			event[];	/* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "StartupLocality" SHALL be
+	 * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+	 * 0x61 0x6C 0x69 0x74 0x79 0x00}
+	 */
+	uint8_t		signature[16];
+
+	/* The Locality Indicator which sent the TPM2_Startup command */
+	uint8_t		startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
index 1ebd39f..c46892b 100644
--- a/include/drivers/st/stm32mp1_clk.h
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -59,4 +59,7 @@
 
 void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
 
+#ifdef STM32MP_SHARED_RESOURCES
+void stm32mp1_register_clock_parents_secure(unsigned long id);
+#endif
 #endif /* STM32MP1_CLK_H */
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
index 18bdb57..67e66b2 100644
--- a/include/dt-bindings/clock/stm32mp1-clks.h
+++ b/include/dt-bindings/clock/stm32mp1-clks.h
@@ -248,4 +248,31 @@
 
 #define STM32MP1_LAST_CLK 232
 
+/* SCMI clock identifiers */
+#define CK_SCMI0_HSE		0
+#define CK_SCMI0_HSI		1
+#define CK_SCMI0_CSI		2
+#define CK_SCMI0_LSE		3
+#define CK_SCMI0_LSI		4
+#define CK_SCMI0_PLL2_Q		5
+#define CK_SCMI0_PLL2_R		6
+#define CK_SCMI0_MPU		7
+#define CK_SCMI0_AXI		8
+#define CK_SCMI0_BSEC		9
+#define CK_SCMI0_CRYP1		10
+#define CK_SCMI0_GPIOZ		11
+#define CK_SCMI0_HASH1		12
+#define CK_SCMI0_I2C4		13
+#define CK_SCMI0_I2C6		14
+#define CK_SCMI0_IWDG1		15
+#define CK_SCMI0_RNG1		16
+#define CK_SCMI0_RTC		17
+#define CK_SCMI0_RTCAPB		18
+#define CK_SCMI0_SPI6		19
+#define CK_SCMI0_USART1		20
+
+#define CK_SCMI1_PLL3_Q		0
+#define CK_SCMI1_PLL3_R		1
+#define CK_SCMI1_MCU		2
+
 #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
index f0c3aae..bc71924 100644
--- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -105,4 +105,17 @@
 #define GPIOJ_R		19785
 #define GPIOK_R		19786
 
+/* SCMI reset domain identifiers */
+#define RST_SCMI0_SPI6		0
+#define RST_SCMI0_I2C4		1
+#define RST_SCMI0_I2C6		2
+#define RST_SCMI0_USART1	3
+#define RST_SCMI0_STGEN		4
+#define RST_SCMI0_GPIOZ		5
+#define RST_SCMI0_CRYP1		6
+#define RST_SCMI0_HASH1		7
+#define RST_SCMI0_RNG1		8
+#define RST_SCMI0_MDMA		9
+#define RST_SCMI0_MCU		10
+
 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
index 9816d6f..6f8da0d 100644
--- a/include/lib/fconf/fconf_dyn_cfg_getter.h
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -14,14 +14,15 @@
 
 struct dyn_cfg_dtb_info_t {
 	uintptr_t config_addr;
-	size_t config_max_size;
+	uint32_t config_max_size;
 	unsigned int config_id;
 };
 
 struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id);
 int fconf_populate_dtb_registry(uintptr_t config);
 
-/* Set fw_config information in global DTB array */
-void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size);
+/* Set config information in global DTB array */
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+			unsigned int config_id);
 
 #endif /* FCONF_DYN_CFG_GETTER_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
index db98b68..6066af6 100644
--- a/include/lib/fconf/fconf_tbbr_getter.h
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -23,6 +23,9 @@
 	uint32_t disable_auth;
 	void *mbedtls_heap_addr;
 	size_t mbedtls_heap_size;
+#if MEASURED_BOOT
+	uint8_t bl2_hash_data[TCG_DIGEST_SIZE];
+#endif
 };
 
 extern struct tbbr_dyn_config_t tbbr_dyn_config;
diff --git a/include/lib/libc/stdbool.h b/include/lib/libc/stdbool.h
index e39aef7..b58334c 100644
--- a/include/lib/libc/stdbool.h
+++ b/include/lib/libc/stdbool.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,8 +9,8 @@
 
 #define bool	_Bool
 
-#define true	1
-#define false	0
+#define true	(0 < 1)
+#define false	(0 > 1)
 
 #define __bool_true_false_are_defined	1
 
diff --git a/include/lib/libfdt/fdt.h b/include/lib/libfdt/fdt.h
index ef7c86b..eb9edb7 100644
--- a/include/lib/libfdt/fdt.h
+++ b/include/lib/libfdt/fdt.h
@@ -1,55 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef FDT_H
 #define FDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 __ASSEMBLER__
@@ -90,7 +45,7 @@
 	char data[0];
 };
 
-#endif /* !__ASSEMBLER__ */
+#endif /* !__ASSEMBLER__*/
 
 #define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
 #define FDT_TAGSIZE	sizeof(fdt32_t)
diff --git a/include/lib/libfdt/libfdt.h b/include/lib/libfdt/libfdt.h
index c8c00fa..48f375c 100644
--- a/include/lib/libfdt/libfdt.h
+++ b/include/lib/libfdt/libfdt.h
@@ -1,54 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_H
 #define LIBFDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 <libfdt_env.h>
@@ -90,8 +45,9 @@
 
 /* Error codes: codes for bad device tree blobs */
 #define FDT_ERR_TRUNCATED	8
-	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
-	 * ends without an FDT_END tag. */
+	/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+	 * terminated (overflows, goes outside allowed bounds, or
+	 * isn't properly terminated).  */
 #define FDT_ERR_BADMAGIC	9
 	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
 	 * device tree at all - it is missing the flattened device
@@ -137,7 +93,15 @@
 	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
 	 * phandle available anymore without causing an overflow */
 
-#define FDT_ERR_MAX		17
+#define FDT_ERR_BADFLAGS	18
+	/* FDT_ERR_BADFLAGS: The function was passed a flags field that
+	 * contains invalid flags or an invalid combination of flags. */
+
+#define FDT_ERR_MAX		18
+
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+	/* Valid values for phandles range from 1 to 2^32-2. */
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -153,6 +117,61 @@
 
 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
+/*
+ * Alignment helpers:
+ *     These helpers access words from a device tree blob.  They're
+ *     built to work even with unaligned pointers on platforms (ike
+ *     ARM) that don't like unaligned loads and stores
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint32_t)bp[0] << 24)
+		| ((uint32_t)bp[1] << 16)
+		| ((uint32_t)bp[2] << 8)
+		| bp[3];
+}
+
+static inline void fdt32_st(void *property, uint32_t value)
+{
+	uint8_t *bp = (uint8_t *)property;
+
+	bp[0] = value >> 24;
+	bp[1] = (value >> 16) & 0xff;
+	bp[2] = (value >> 8) & 0xff;
+	bp[3] = value & 0xff;
+}
+
+static inline uint64_t fdt64_ld(const fdt64_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint64_t)bp[0] << 56)
+		| ((uint64_t)bp[1] << 48)
+		| ((uint64_t)bp[2] << 40)
+		| ((uint64_t)bp[3] << 32)
+		| ((uint64_t)bp[4] << 24)
+		| ((uint64_t)bp[5] << 16)
+		| ((uint64_t)bp[6] << 8)
+		| bp[7];
+}
+
+static inline void fdt64_st(void *property, uint64_t value)
+{
+	uint8_t *bp = (uint8_t *)property;
+
+	bp[0] = value >> 56;
+	bp[1] = (value >> 48) & 0xff;
+	bp[2] = (value >> 40) & 0xff;
+	bp[3] = (value >> 32) & 0xff;
+	bp[4] = (value >> 24) & 0xff;
+	bp[5] = (value >> 16) & 0xff;
+	bp[6] = (value >> 8) & 0xff;
+	bp[7] = value & 0xff;
+}
+
 /**********************************************************************/
 /* Traversal functions                                                */
 /**********************************************************************/
@@ -195,7 +214,7 @@
  *		...
  *	}
  *
- *	if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ *	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
  *		Error handling
  *	}
  *
@@ -213,7 +232,7 @@
 /* General functions                                                  */
 /**********************************************************************/
 #define fdt_get_header(fdt, field) \
-	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+	(fdt32_ld(&((const struct fdt_header *)(fdt))->field))
 #define fdt_magic(fdt)			(fdt_get_header(fdt, magic))
 #define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
 #define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
@@ -244,18 +263,32 @@
 #undef fdt_set_hdr_
 
 /**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_header_size - return the size of the tree's header
+ * @fdt: pointer to a flattened device tree
+ */
+size_t fdt_header_size(const void *fdt);
+
+/**
+ * fdt_header_size_ - internal function which takes a version number
+ */
+size_t fdt_header_size_(uint32_t version);
+
+/**
+ * fdt_check_header - sanity check a device tree header
+
  * @fdt: pointer to data which might be a flattened device tree
  *
  * fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
  *
  * returns:
  *     0, if the buffer appears to contain a valid device tree
  *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings, as above
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_TRUNCATED, standard meanings, as above
  */
 int fdt_check_header(const void *fdt);
 
@@ -284,6 +317,24 @@
 /* Read-only functions                                                */
 /**********************************************************************/
 
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
 /**
  * fdt_string - retrieve a string from the strings block of a device tree
  * @fdt: pointer to the device tree blob
@@ -294,11 +345,25 @@
  *
  * returns:
  *     a pointer to the string, on success
- *     NULL, if stroffset is out of bounds
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
 /**
+ * fdt_find_max_phandle - find and return the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the highest phandle value found in the tree
+ *
+ * fdt_find_max_phandle() finds the highest phandle value in the given device
+ * tree. The value returned in @phandle is only valid if the function returns
+ * success.
+ *
+ * returns:
+ *     0 on success or a negative error code on failure
+ */
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
+
+/**
  * fdt_get_max_phandle - retrieves the highest phandle in a tree
  * @fdt: pointer to the device tree blob
  *
@@ -306,12 +371,39 @@
  * device tree. This will ignore badly formatted phandles, or phandles
  * with a value of 0 or -1.
  *
+ * This function is deprecated in favour of fdt_find_max_phandle().
+ *
  * returns:
  *      the highest phandle on success
  *      0, if no phandle was found in the device tree
  *      -1, if an error occurred
  */
-uint32_t fdt_get_max_phandle(const void *fdt);
+static inline uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t phandle;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &phandle);
+	if (err < 0)
+		return (uint32_t)-1;
+
+	return phandle;
+}
+
+/**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ *   0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
 
 /**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
@@ -503,7 +595,7 @@
  *		...
  *	}
  *
- *	if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ *	if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
  *		Error handling
  *	}
  *
@@ -606,7 +698,7 @@
 /**
  * fdt_getprop_by_offset - retrieve the value of a property at a given offset
  * @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
+ * @offset: offset of the property to read
  * @namep: pointer to a string variable (will be overwritten) or NULL
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
  *
@@ -1090,7 +1182,7 @@
  *
  * returns:
  *	0 <= n < FDT_MAX_NCELLS, on success
- *      2, if the node has no #address-cells property
+ *      1, if the node has no #size-cells property
  *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
  *		#size-cells property
  *	-FDT_ERR_BADMAGIC,
@@ -1297,7 +1389,45 @@
 /* Sequential write functions                                         */
 /**********************************************************************/
 
+/* fdt_create_with_flags flags */
+#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
+	/* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
+	 * names in the fdt. This can result in faster creation times, but
+	 * a larger fdt. */
+
+#define FDT_CREATE_FLAGS_ALL	(FDT_CREATE_FLAG_NO_NAME_DEDUP)
+
+/**
+ * fdt_create_with_flags - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
+ *
+ * fdt_create_with_flags() begins the process of creating a new fdt with
+ * the sequential write interface.
+ *
+ * fdt creation process must end with fdt_finished() to produce a valid fdt.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ *	-FDT_ERR_BADFLAGS, flags is not valid
+ */
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
+
+/**
+ * fdt_create - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ *
+ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ */
 int fdt_create(void *buf, int bufsize);
+
 int fdt_resize(void *fdt, void *buf, int bufsize);
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
@@ -1313,10 +1443,13 @@
 	fdt64_t tmp = cpu_to_fdt64(val);
 	return fdt_property(fdt, name, &tmp, sizeof(tmp));
 }
+
+#ifndef SWIG /* Not available in Python */
 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
 	return fdt_property_u32(fdt, name, val);
 }
+#endif
 
 /**
  * fdt_property_placeholder - add a new property and return a ptr to its value
@@ -1766,6 +1899,43 @@
 	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop_addrrange - append a address range property
+ * @fdt: pointer to the device tree blob
+ * @parent: offset of the parent node
+ * @nodeoffset: offset of the node to add a property at
+ * @name: name of property
+ * @addr: start address of a given range
+ * @size: size of a given range
+ *
+ * fdt_appendprop_addrrange() appends an address range value (start
+ * address and size) to the value of the named property in the given
+ * node, or creates a new property with that value if it does not
+ * already exist.
+ * If "name" is not specified, a default "reg" is used.
+ * Cell sizes are determined by parent's #address-cells and #size-cells.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *		#address-cells property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain a new property
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+			     const char *name, uint64_t addr, uint64_t size);
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
diff --git a/include/lib/libfdt/libfdt_env.h b/include/lib/libfdt/libfdt_env.h
index bd24746..73b6d40 100644
--- a/include/lib/libfdt/libfdt_env.h
+++ b/include/lib/libfdt/libfdt_env.h
@@ -1,61 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_ENV_H
 #define LIBFDT_ENV_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #ifdef __CHECKER__
 #define FDT_FORCE __attribute__((force))
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 5c11e5f..293e7ce 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -81,7 +81,7 @@
 					 ARM_SCP_TZC_DRAM1_SIZE)
 #define ARM_SCP_TZC_DRAM1_SIZE		PLAT_ARM_SCP_TZC_DRAM1_SIZE
 #define ARM_SCP_TZC_DRAM1_END		(ARM_SCP_TZC_DRAM1_BASE +	\
-					 ARM_SCP_TZC_DRAM1_SIZE - 1)
+					 ARM_SCP_TZC_DRAM1_SIZE - 1U)
 
 /*
  * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime
@@ -92,7 +92,7 @@
 #define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
 #define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00200000) /* 2 MB */
 #define ARM_EL3_TZC_DRAM1_END		(ARM_EL3_TZC_DRAM1_BASE +	\
-					ARM_EL3_TZC_DRAM1_SIZE - 1)
+					ARM_EL3_TZC_DRAM1_SIZE - 1U)
 
 #define ARM_AP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
 					 ARM_DRAM1_SIZE -		\
@@ -101,7 +101,7 @@
 					 (ARM_SCP_TZC_DRAM1_SIZE +	\
 					 ARM_EL3_TZC_DRAM1_SIZE))
 #define ARM_AP_TZC_DRAM1_END		(ARM_AP_TZC_DRAM1_BASE +	\
-					 ARM_AP_TZC_DRAM1_SIZE - 1)
+					 ARM_AP_TZC_DRAM1_SIZE - 1U)
 
 /* Define the Access permissions for Secure peripherals to NS_DRAM */
 #if ARM_CRYPTOCELL_INTEG
@@ -148,17 +148,17 @@
 #define ARM_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE)
 #define ARM_NS_DRAM1_END		(ARM_NS_DRAM1_BASE +		\
-					 ARM_NS_DRAM1_SIZE - 1)
+					 ARM_NS_DRAM1_SIZE - 1U)
 
 #define ARM_DRAM1_BASE			ULL(0x80000000)
 #define ARM_DRAM1_SIZE			ULL(0x80000000)
 #define ARM_DRAM1_END			(ARM_DRAM1_BASE +		\
-					 ARM_DRAM1_SIZE - 1)
+					 ARM_DRAM1_SIZE - 1U)
 
 #define ARM_DRAM2_BASE			PLAT_ARM_DRAM2_BASE
 #define ARM_DRAM2_SIZE			PLAT_ARM_DRAM2_SIZE
 #define ARM_DRAM2_END			(ARM_DRAM2_BASE +		\
-					 ARM_DRAM2_SIZE - 1)
+					 ARM_DRAM2_SIZE - 1U)
 
 #define ARM_IRQ_SEC_PHY_TIMER		29
 
@@ -294,12 +294,19 @@
 #define ARM_V2M_MAP_MEM_PROTECT		MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR,	\
 						V2M_FLASH_BLOCK_SIZE,		\
 						MT_DEVICE | MT_RW | MT_SECURE)
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
 
 /*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -350,14 +357,15 @@
  * and limit. Leave enough space of BL2 meminfo.
  */
 #define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_LIMIT		((ARM_BL_RAM_BASE + PAGE_SIZE) \
+					+ (PAGE_SIZE / 2U))
 
 /*
  * Boot parameters passed from BL2 to BL31/BL32 are stored here
  */
-#define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
-#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE +	\
-							(PAGE_SIZE / 2U))
+#define ARM_BL2_MEM_DESC_BASE		(ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 /*
  * Define limit of firmware configuration memory:
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
index 38c30fb..236254b 100644
--- a/include/plat/arm/common/fconf_arm_sp_getter.h
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -13,7 +13,7 @@
 /* arm_sp getter */
 #define arm__sp_getter(prop)	arm_sp.prop
 
-#define ARM_SP_MAX_SIZE		U(0x10000)
+#define ARM_SP_MAX_SIZE		U(0x80000)
 
 struct arm_sp_t {
 	unsigned int		number_of_sp;
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 3625530..95fc18e 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -235,8 +235,20 @@
 
 #if MEASURED_BOOT
 /* Measured boot related functions */
-void arm_bl1_set_bl2_hash(image_desc_t *image_desc);
+void arm_bl1_set_bl2_hash(const image_desc_t *image_desc);
+void arm_bl2_get_hash(void *data);
+int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+			size_t log_size);
+int arm_set_nt_fw_info(uintptr_t config_base,
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this option should be removed when feature is supported.
+ */
+#ifdef SPD_opteed
+			uintptr_t log_addr,
 #endif
+			size_t log_size, uintptr_t *ns_log_addr);
+#endif /* MEASURED_BOOT */
 
 /*
  * Free the memory storing initialization code only used during an images boot
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 720c259..2c1a180 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -175,6 +175,14 @@
 int bl1_plat_handle_pre_image_load(unsigned int image_id);
 int bl1_plat_handle_post_image_load(unsigned int image_id);
 
+#if MEASURED_BOOT
+/*
+ * Calculates and writes BL2 hash data to the platform's defined location.
+ * For ARM platforms the data are written to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc);
+#endif
+
 /*******************************************************************************
  * Mandatory BL2 functions
  ******************************************************************************/
@@ -190,11 +198,13 @@
 int bl2_plat_handle_pre_image_load(unsigned int image_id);
 int bl2_plat_handle_post_image_load(unsigned int image_id);
 
-
 /*******************************************************************************
  * Optional BL2 functions (may be overridden)
  ******************************************************************************/
-
+#if MEASURED_BOOT
+/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
+void bl2_plat_get_hash(void *data);
+#endif
 
 /*******************************************************************************
  * Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is
@@ -204,7 +214,6 @@
 				  u_register_t arg2, u_register_t arg3);
 void bl2_el3_plat_arch_setup(void);
 
-
 /*******************************************************************************
  * Optional BL2 at EL3 functions (may be overridden)
  ******************************************************************************/
@@ -332,4 +341,9 @@
  */
 int32_t plat_get_soc_revision(void);
 
+/*
+ * Optional function to check for SMCCC function availability for platform
+ */
+int32_t plat_is_smccc_feature_available(u_register_t fid);
+
 #endif /* PLATFORM_H */
diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S
index 6d2ec1c..e9734ac 100644
--- a/lib/aarch32/misc_helpers.S
+++ b/lib/aarch32/misc_helpers.S
@@ -1,5 +1,5 @@
 /*
- * 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
  */
@@ -149,17 +149,16 @@
 	blo	m_loop1
 	ldr	r3, [r1], #4
 	str	r3, [r0], #4
-	sub	r2, r2, #4
-	b	m_loop4
+	subs	r2, r2, #4
+	bne	m_loop4
+	bx	lr
+
 /* copy byte per byte */
 m_loop1:
-	cmp	r2,#0
-	beq	m_end
 	ldrb	r3, [r1], #1
 	strb	r3, [r0], #1
 	subs	r2, r2, #1
 	bne	m_loop1
-m_end:
 	bx	lr
 endfunc memcpy4
 
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
index bc4fa8e..24b6bcc 100644
--- a/lib/fconf/fconf.c
+++ b/lib/fconf/fconf.c
@@ -32,8 +32,7 @@
 	assert(config_info != NULL);
 
 	config_image_info.image_base = config_info->config_addr;
-	config_image_info.image_max_size =
-		(uint32_t)config_info->config_max_size;
+	config_image_info.image_max_size = config_info->config_max_size;
 
 	VERBOSE("FCONF: Loading config with image ID: %d\n", image_id);
 	err = load_auth_image(image_id, &config_image_info);
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 902c07d..25dd7f9 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -12,66 +12,59 @@
 #include <lib/object_pool.h>
 #include <libfdt.h>
 
-/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs  */
+/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs  */
 #define MAX_DTB_INFO	U(6)
+/*
+ * Compile time assert if FW_CONFIG_ID is 0 which is more
+ * unlikely as 0 is a valid image ID for FIP as per the current
+ * code but still to avoid code breakage in case of unlikely
+ * event when image IDs get changed.
+ */
+CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id);
 
 static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
 static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
 
 /*
- * This function is used to alloc memory for fw config information from
- * global pool and set fw configuration information.
- * Specifically used by BL1 to set fw_config information in global array
+ * This function is used to alloc memory for config information from
+ * global pool and set the configuration information.
  */
-void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size)
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+			unsigned int config_id)
 {
 	struct dyn_cfg_dtb_info_t *dtb_info;
 
 	dtb_info = pool_alloc(&dtb_info_pool);
 	dtb_info->config_addr = config_addr;
 	dtb_info->config_max_size = config_max_size;
-	dtb_info->config_id = FW_CONFIG_ID;
+	dtb_info->config_id = config_id;
 }
 
 struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
 {
 	unsigned int index;
-	struct dyn_cfg_dtb_info_t *info;
 
 	/* Positions index to the proper config-id */
-	for (index = 0; index < MAX_DTB_INFO; index++) {
+	for (index = 0U; index < MAX_DTB_INFO; index++) {
 		if (dtb_infos[index].config_id == config_id) {
-			info = &dtb_infos[index];
-			break;
+			return &dtb_infos[index];
 		}
 	}
 
-	if (index == MAX_DTB_INFO) {
-		WARN("FCONF: Invalid config id %u\n", config_id);
-		info = NULL;
-	}
+	WARN("FCONF: Invalid config id %u\n", config_id);
 
-	return info;
+	return NULL;
 }
 
 int fconf_populate_dtb_registry(uintptr_t config)
 {
 	int rc;
 	int node, child;
-	struct dyn_cfg_dtb_info_t *dtb_info;
 
 	/* As libfdt use void *, we can't avoid this cast */
 	const void *dtb = (void *)config;
 
 	/*
-	 * Compile time assert if FW_CONFIG_ID is 0 which is more
-	 * unlikely as 0 is a valid image id for FIP as per the current
-	 * code but still to avoid code breakage in case of unlikely
-	 * event when image ids gets changed.
-	 */
-	CASSERT(FW_CONFIG_ID != 0, assert_invalid_fw_config_id);
-
-	/*
 	 * In case of BL1, fw_config dtb information is already
 	 * populated in global dtb_infos array by 'set_fw_config_info'
 	 * function, Below check is present to avoid re-population of
@@ -80,11 +73,9 @@
 	 * Other BLs, satisfy below check and populate fw_config information
 	 * in global dtb_infos array.
 	 */
-	if (dtb_infos[0].config_id == 0) {
-		dtb_info = pool_alloc(&dtb_info_pool);
-		dtb_info->config_addr = config;
-		dtb_info->config_max_size = fdt_totalsize(dtb);
-		dtb_info->config_id = FW_CONFIG_ID;
+	if (dtb_infos[0].config_id == 0U) {
+		uint32_t config_max_size = fdt_totalsize(dtb);
+		set_config_info(config, config_max_size, FW_CONFIG_ID);
 	}
 
 	/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
@@ -96,37 +87,36 @@
 	}
 
 	fdt_for_each_subnode(child, dtb, node) {
-		uint32_t val32;
+		uint32_t config_max_size, config_id;
+		uintptr_t config_addr;
 		uint64_t val64;
 
-		dtb_info = pool_alloc(&dtb_info_pool);
-
 		/* Read configuration dtb information */
 		rc = fdt_read_uint64(dtb, child, "load-address", &val64);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_addr = (uintptr_t)val64;
+		config_addr = (uintptr_t)val64;
 
-		rc = fdt_read_uint32(dtb, child, "max-size", &val32);
+		rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_max_size = val32;
 
-		rc = fdt_read_uint32(dtb, child, "id", &val32);
+		rc = fdt_read_uint32(dtb, child, "id", &config_id);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_id = val32;
 
 		VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
-		VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
-		VERBOSE("\tmax-size = 0x%zx\n", dtb_info->config_max_size);
-		VERBOSE("\tconfig-id = %u\n", dtb_info->config_id);
+		VERBOSE("\tload-address = %lx\n", config_addr);
+		VERBOSE("\tmax-size = 0x%x\n", config_max_size);
+		VERBOSE("\tconfig-id = %u\n", config_id);
+
+		set_config_info(config_addr, config_max_size, config_id);
 	}
 
 	if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index 2127801..9a20ced 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -27,20 +27,25 @@
 	const char *compatible_str = "arm,tb_fw";
 	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
 	if (node < 0) {
-		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		ERROR("FCONF: Can't find `%s` compatible in dtb\n",
+						compatible_str);
 		return node;
 	}
 
 	/* Locate the disable_auth cell and read the value */
-	err = fdt_read_uint32(dtb, node, "disable_auth", &tbbr_dyn_config.disable_auth);
+	err = fdt_read_uint32(dtb, node, "disable_auth",
+					&tbbr_dyn_config.disable_auth);
 	if (err < 0) {
-		WARN("FCONF: Read cell failed for `disable_auth`\n");
+		WARN("FCONF: Read %s failed for `%s`\n",
+				"cell", "disable_auth");
 		return err;
 	}
 
 	/* Check if the value is boolean */
-	if ((tbbr_dyn_config.disable_auth != 0U) && (tbbr_dyn_config.disable_auth != 1U)) {
-		WARN("Invalid value for `disable_auth` cell %d\n", tbbr_dyn_config.disable_auth);
+	if ((tbbr_dyn_config.disable_auth != 0U) &&
+	    (tbbr_dyn_config.disable_auth != 1U)) {
+		WARN("Invalid value for `%s` cell %d\n",
+			"disable_auth", tbbr_dyn_config.disable_auth);
 		return -1;
 	}
 
@@ -52,25 +57,40 @@
 	/* Retrieve the Mbed TLS heap details from the DTB */
 	err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64);
 	if (err < 0) {
-		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		ERROR("FCONF: Read %s failed for `%s`\n",
+			"cell", "mbedtls_heap_addr");
 		return err;
 	}
 	tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64;
 
 	err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32);
 	if (err < 0) {
-		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		ERROR("FCONF: Read %s failed for `%s`\n",
+			"cell", "mbedtls_heap_size");
 		return err;
 	}
 	tbbr_dyn_config.mbedtls_heap_size = val32;
 
-	VERBOSE("FCONF:tbbr.disable_auth cell found with value = %d\n",
-					tbbr_dyn_config.disable_auth);
-	VERBOSE("FCONF:tbbr.mbedtls_heap_addr cell found with value = %p\n",
-					tbbr_dyn_config.mbedtls_heap_addr);
-	VERBOSE("FCONF:tbbr.mbedtls_heap_size cell found with value = %zu\n",
-					tbbr_dyn_config.mbedtls_heap_size);
-
+#if MEASURED_BOOT
+	/* Retrieve BL2 hash data details from the DTB */
+	err = fdtw_read_bytes(dtb, node, "bl2_hash_data", TCG_DIGEST_SIZE,
+				&tbbr_dyn_config.bl2_hash_data);
+	if (err < 0) {
+		ERROR("FCONF: Read %s failed for '%s'\n",
+				"bytes", "bl2_hash_data");
+		return err;
+	}
+#endif
+	VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth",
+		"` cell found with value =", tbbr_dyn_config.disable_auth);
+	VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
+		"` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
+	VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size",
+		"` cell found with value =", tbbr_dyn_config.mbedtls_heap_size);
+#if MEASURED_BOOT
+	VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "bl2_hash_data",
+		"` array found at address =", tbbr_dyn_config.bl2_hash_data);
+#endif
 	return 0;
 }
 
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 7855a17..c28fcc1 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
@@ -55,22 +10,125 @@
 
 #include "libfdt_internal.h"
 
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int32_t fdt_ro_probe_(const void *fdt)
 {
+	uint32_t totalsize = fdt_totalsize(fdt);
+
+	if (can_assume(VALID_DTB))
+		return totalsize;
+
 	if (fdt_magic(fdt) == FDT_MAGIC) {
 		/* Complete tree */
-		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
-		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
+		if (!can_assume(LATEST)) {
+			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+			if (fdt_last_comp_version(fdt) >
+					FDT_LAST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+		}
 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
 		/* Unfinished sequential-write blob */
-		if (fdt_size_dt_struct(fdt) == 0)
+		if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
 			return -FDT_ERR_BADSTATE;
 	} else {
 		return -FDT_ERR_BADMAGIC;
 	}
 
+	if (totalsize < INT32_MAX)
+		return totalsize;
+	else
+		return -FDT_ERR_TRUNCATED;
+}
+
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+	return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+			uint32_t base, uint32_t size)
+{
+	if (!check_off_(hdrsize, totalsize, base))
+		return 0; /* block start out of bounds */
+	if ((base + size) < base)
+		return 0; /* overflow */
+	if (!check_off_(hdrsize, totalsize, base + size))
+		return 0; /* block end out of bounds */
+	return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+	if (version <= 1)
+		return FDT_V1_SIZE;
+	else if (version <= 2)
+		return FDT_V2_SIZE;
+	else if (version <= 3)
+		return FDT_V3_SIZE;
+	else if (version <= 16)
+		return FDT_V16_SIZE;
+	else
+		return FDT_V17_SIZE;
+}
+
+size_t fdt_header_size(const void *fdt)
+{
+	return can_assume(LATEST) ? FDT_V17_SIZE :
+		fdt_header_size_(fdt_version(fdt));
+}
+
+int fdt_check_header(const void *fdt)
+{
+	size_t hdrsize;
+
+	if (fdt_magic(fdt) != FDT_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	if (!can_assume(LATEST)) {
+		if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+		    || (fdt_last_comp_version(fdt) >
+			FDT_LAST_SUPPORTED_VERSION))
+			return -FDT_ERR_BADVERSION;
+		if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+			return -FDT_ERR_BADVERSION;
+	}
+	hdrsize = fdt_header_size(fdt);
+	if (!can_assume(VALID_DTB)) {
+
+		if ((fdt_totalsize(fdt) < hdrsize)
+		    || (fdt_totalsize(fdt) > INT_MAX))
+			return -FDT_ERR_TRUNCATED;
+
+		/* Bounds check memrsv block */
+		if (!check_off_(hdrsize, fdt_totalsize(fdt),
+				fdt_off_mem_rsvmap(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
+	if (!can_assume(VALID_DTB)) {
+		/* Bounds check structure block */
+		if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
+			if (!check_off_(hdrsize, fdt_totalsize(fdt),
+					fdt_off_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		} else {
+			if (!check_block_(hdrsize, fdt_totalsize(fdt),
+					  fdt_off_dt_struct(fdt),
+					  fdt_size_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		}
+
+		/* Bounds check strings block */
+		if (!check_block_(hdrsize, fdt_totalsize(fdt),
+				  fdt_off_dt_strings(fdt),
+				  fdt_size_dt_strings(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
 	return 0;
 }
 
@@ -78,12 +136,13 @@
 {
 	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
 
-	if ((absoffset < offset)
-	    || ((absoffset + len) < absoffset)
-	    || (absoffset + len) > fdt_totalsize(fdt))
-		return NULL;
+	if (!can_assume(VALID_INPUT))
+		if ((absoffset < offset)
+		    || ((absoffset + len) < absoffset)
+		    || (absoffset + len) > fdt_totalsize(fdt))
+			return NULL;
 
-	if (fdt_version(fdt) >= 0x11)
+	if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
 		if (((offset + len) < offset)
 		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 			return NULL;
@@ -100,7 +159,7 @@
 
 	*nextoffset = -FDT_ERR_TRUNCATED;
 	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
-	if (!tagp)
+	if (!can_assume(VALID_DTB) && !tagp)
 		return FDT_END; /* premature end */
 	tag = fdt32_to_cpu(*tagp);
 	offset += FDT_TAGSIZE;
@@ -112,18 +171,19 @@
 		do {
 			p = fdt_offset_ptr(fdt, offset++, 1);
 		} while (p && (*p != '\0'));
-		if (!p)
+		if (!can_assume(VALID_DTB) && !p)
 			return FDT_END; /* premature end */
 		break;
 
 	case FDT_PROP:
 		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
-		if (!lenp)
+		if (!can_assume(VALID_DTB) && !lenp)
 			return FDT_END; /* premature end */
 		/* skip-name offset, length and value */
 		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
 			+ fdt32_to_cpu(*lenp);
-		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+		if (!can_assume(LATEST) &&
+		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
 		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
 			offset += 4;
 		break;
@@ -146,6 +206,8 @@
 
 int fdt_check_node_offset_(const void *fdt, int offset)
 {
+	if (can_assume(VALID_INPUT))
+		return offset;
 	if ((offset < 0) || (offset % FDT_TAGSIZE)
 	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
 		return -FDT_ERR_BADOFFSET;
@@ -244,7 +306,7 @@
 
 int fdt_move(const void *fdt, void *buf, int bufsize)
 {
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (fdt_totalsize(fdt) > bufsize)
 		return -FDT_ERR_NOSPACE;
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
index eff4dbc..9a82cd0 100644
--- a/lib/libfdt/fdt_addresses.c
+++ b/lib/libfdt/fdt_addresses.c
@@ -1,52 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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.
+ * Copyright (C) 2018 embedded brains GmbH
  */
 #include "libfdt_env.h"
 
@@ -55,42 +11,91 @@
 
 #include "libfdt_internal.h"
 
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
 {
-	const fdt32_t *ac;
-	int val;
+	const fdt32_t *c;
+	uint32_t val;
 	int len;
 
-	ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
-	if (!ac)
+	c = fdt_getprop(fdt, nodeoffset, name, &len);
+	if (!c)
+		return len;
+
+	if (len != sizeof(*c))
+		return -FDT_ERR_BADNCELLS;
+
+	val = fdt32_to_cpu(*c);
+	if (val > FDT_MAX_NCELLS)
+		return -FDT_ERR_BADNCELLS;
+
+	return (int)val;
+}
+
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+	int val;
+
+	val = fdt_cells(fdt, nodeoffset, "#address-cells");
+	if (val == 0)
+		return -FDT_ERR_BADNCELLS;
+	if (val == -FDT_ERR_NOTFOUND)
 		return 2;
-
-	if (len != sizeof(*ac))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*ac);
-	if ((val <= 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
 	return val;
 }
 
 int fdt_size_cells(const void *fdt, int nodeoffset)
 {
-	const fdt32_t *sc;
 	int val;
-	int len;
 
-	sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
-	if (!sc)
-		return 2;
-
-	if (len != sizeof(*sc))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*sc);
-	if ((val < 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
+	val = fdt_cells(fdt, nodeoffset, "#size-cells");
+	if (val == -FDT_ERR_NOTFOUND)
+		return 1;
 	return val;
 }
+
+/* This function assumes that [address|size]_cells is 1 or 2 */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+			     const char *name, uint64_t addr, uint64_t size)
+{
+	int addr_cells, size_cells, ret;
+	uint8_t data[sizeof(fdt64_t) * 2], *prop;
+
+	ret = fdt_address_cells(fdt, parent);
+	if (ret < 0)
+		return ret;
+	addr_cells = ret;
+
+	ret = fdt_size_cells(fdt, parent);
+	if (ret < 0)
+		return ret;
+	size_cells = ret;
+
+	/* check validity of address */
+	prop = data;
+	if (addr_cells == 1) {
+		if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+			return -FDT_ERR_BADVALUE;
+
+		fdt32_st(prop, (uint32_t)addr);
+	} else if (addr_cells == 2) {
+		fdt64_st(prop, addr);
+	} else {
+		return -FDT_ERR_BADNCELLS;
+	}
+
+	/* check validity of size */
+	prop += addr_cells * sizeof(fdt32_t);
+	if (size_cells == 1) {
+		if (size > UINT32_MAX)
+			return -FDT_ERR_BADVALUE;
+
+		fdt32_st(prop, (uint32_t)size);
+	} else if (size_cells == 2) {
+		fdt64_st(prop, size);
+	} else {
+		return -FDT_ERR_BADNCELLS;
+	}
+
+	return fdt_appendprop(fdt, nodeoffset, name, data,
+			      (addr_cells + size_cells) * sizeof(fdt32_t));
+}
diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c
index f2ae9b7..49d54d4 100644
--- a/lib/libfdt/fdt_empty_tree.c
+++ b/lib/libfdt/fdt_empty_tree.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2012 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index bf75388..b310e49 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -1,53 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2016 Free Electrons
  * Copyright (C) 2016 NextThing Co.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
@@ -93,11 +48,11 @@
  * @pathp: pointer which receives the path of the target (or NULL)
  *
  * overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targetting is
+ * device tree of a fragment, no matter how the actual targeting is
  * done (through a phandle or a path)
  *
  * returns:
- *      the targetted node offset in the base device tree
+ *      the targeted node offset in the base device tree
  *      Negative error code on error
  */
 static int overlay_get_target(const void *fdt, const void *fdto,
@@ -697,7 +652,7 @@
 	int len = 0, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (;;) {
 		name = fdt_get_name(fdt, nodeoffset, &namelen);
@@ -778,26 +733,36 @@
 		/* keep end marker to avoid strlen() */
 		e = path + path_len;
 
-		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
-
 		if (*path != '/')
 			return -FDT_ERR_BADVALUE;
 
 		/* get fragment name first */
 		s = strchr(path + 1, '/');
-		if (!s)
-			return -FDT_ERR_BADOVERLAY;
+		if (!s) {
+			/* Symbol refers to something that won't end
+			 * up in the target tree */
+			continue;
+		}
 
 		frag_name = path + 1;
 		frag_name_len = s - path - 1;
 
 		/* verify format; safe since "s" lies in \0 terminated prop */
 		len = sizeof("/__overlay__/") - 1;
-		if ((e - s) < len || memcmp(s, "/__overlay__/", len))
-			return -FDT_ERR_BADOVERLAY;
-
-		rel_path = s + len;
-		rel_path_len = e - rel_path;
+		if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
+			/* /<fragment-name>/__overlay__/<relative-subnode-path> */
+			rel_path = s + len;
+			rel_path_len = e - rel_path - 1;
+		} else if ((e - s) == len
+			   && (memcmp(s, "/__overlay__", len - 1) == 0)) {
+			/* /<fragment-name>/__overlay__ */
+			rel_path = "";
+			rel_path_len = 0;
+		} else {
+			/* Symbol refers to something that won't end
+			 * up in the target tree */
+			continue;
+		}
 
 		/* find the fragment index in which the symbol lies */
 		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
@@ -863,11 +828,15 @@
 
 int fdt_overlay_apply(void *fdt, void *fdto)
 {
-	uint32_t delta = fdt_get_max_phandle(fdt);
+	uint32_t delta;
 	int ret;
 
-	FDT_CHECK_HEADER(fdt);
-	FDT_CHECK_HEADER(fdto);
+	FDT_RO_PROBE(fdt);
+	FDT_RO_PROBE(fdto);
+
+	ret = fdt_find_max_phandle(fdt, &delta);
+	if (ret)
+		goto err;
 
 	ret = overlay_adjust_local_phandles(fdto, delta);
 	if (ret)
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index dfb3236..e03570a 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
@@ -76,60 +31,169 @@
 		return 0;
 }
 
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+	int32_t totalsize;
+	uint32_t absoffset;
+	size_t len;
+	int err;
+	const char *s, *n;
+
+	if (can_assume(VALID_INPUT)) {
+		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+
+		if (lenp)
+			*lenp = strlen(s);
+		return s;
+	}
+	totalsize = fdt_ro_probe_(fdt);
+	err = totalsize;
+	if (totalsize < 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	absoffset = stroffset + fdt_off_dt_strings(fdt);
+	if (absoffset >= totalsize)
+		goto fail;
+	len = totalsize - absoffset;
+
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		if (stroffset < 0)
+			goto fail;
+		if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
+			if (stroffset >= fdt_size_dt_strings(fdt))
+				goto fail;
+			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+				len = fdt_size_dt_strings(fdt) - stroffset;
+		}
+	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+		if ((stroffset >= 0)
+		    || (stroffset < -fdt_size_dt_strings(fdt)))
+			goto fail;
+		if ((-stroffset) < len)
+			len = -stroffset;
+	} else {
+		err = -FDT_ERR_INTERNAL;
+		goto fail;
+	}
+
+	s = (const char *)fdt + absoffset;
+	n = memchr(s, '\0', len);
+	if (!n) {
+		/* missing terminating NULL */
+		err = -FDT_ERR_TRUNCATED;
+		goto fail;
+	}
+
+	if (lenp)
+		*lenp = n - s;
+	return s;
+
+fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
+
 const char *fdt_string(const void *fdt, int stroffset)
 {
-	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+	return fdt_get_string(fdt, stroffset, NULL);
 }
 
 static int fdt_string_eq_(const void *fdt, int stroffset,
 			  const char *s, int len)
 {
-	const char *p = fdt_string(fdt, stroffset);
+	int slen;
+	const char *p = fdt_get_string(fdt, stroffset, &slen);
 
-	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+	return p && (slen == len) && (memcmp(p, s, len) == 0);
 }
 
-uint32_t fdt_get_max_phandle(const void *fdt)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
 {
-	uint32_t max_phandle = 0;
-	int offset;
+	uint32_t max = 0;
+	int offset = -1;
 
-	for (offset = fdt_next_node(fdt, -1, NULL);;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		uint32_t phandle;
+	while (true) {
+		uint32_t value;
 
-		if (offset == -FDT_ERR_NOTFOUND)
-			return max_phandle;
+		offset = fdt_next_node(fdt, offset, NULL);
+		if (offset < 0) {
+			if (offset == -FDT_ERR_NOTFOUND)
+				break;
 
-		if (offset < 0)
-			return (uint32_t)-1;
+			return offset;
+		}
 
-		phandle = fdt_get_phandle(fdt, offset);
-		if (phandle == (uint32_t)-1)
-			continue;
+		value = fdt_get_phandle(fdt, offset);
 
-		if (phandle > max_phandle)
-			max_phandle = phandle;
+		if (value > max)
+			max = value;
 	}
 
+	if (phandle)
+		*phandle = max;
+
 	return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+	uint32_t max;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &max);
+	if (err < 0)
+		return err;
+
+	if (max == FDT_MAX_PHANDLE)
+		return -FDT_ERR_NOPHANDLES;
+
+	if (phandle)
+		*phandle = max + 1;
+
+	return 0;
+}
+
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+	int offset = n * sizeof(struct fdt_reserve_entry);
+	int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+	if (!can_assume(VALID_INPUT)) {
+		if (absoffset < fdt_off_mem_rsvmap(fdt))
+			return NULL;
+		if (absoffset > fdt_totalsize(fdt) -
+		    sizeof(struct fdt_reserve_entry))
+			return NULL;
+	}
+	return fdt_mem_rsv_(fdt, n);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-	FDT_CHECK_HEADER(fdt);
-	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
-	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
+	const struct fdt_reserve_entry *re;
+
+	FDT_RO_PROBE(fdt);
+	re = fdt_mem_rsv(fdt, n);
+	if (!can_assume(VALID_INPUT) && !re)
+		return -FDT_ERR_BADOFFSET;
+
+	*address = fdt64_ld(&re->address);
+	*size = fdt64_ld(&re->size);
 	return 0;
 }
 
 int fdt_num_mem_rsv(const void *fdt)
 {
-	int i = 0;
+	int i;
+	const struct fdt_reserve_entry *re;
 
-	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
-		i++;
-	return i;
+	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+		if (fdt64_ld(&re->size) == 0)
+			return i;
+	}
+	return -FDT_ERR_TRUNCATED;
 }
 
 static int nextprop_(const void *fdt, int offset)
@@ -161,7 +225,7 @@
 {
 	int depth;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (depth = 0;
 	     (offset >= 0) && (depth >= 0);
@@ -187,7 +251,7 @@
 	const char *p = path;
 	int offset = 0;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* see if we have an alias */
 	if (*path != '/') {
@@ -237,13 +301,13 @@
 	const char *nameptr;
 	int err;
 
-	if (((err = fdt_check_header(fdt)) != 0)
+	if (((err = fdt_ro_probe_(fdt)) < 0)
 	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
 			goto fail;
 
 	nameptr = nh->name;
 
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		/*
 		 * For old FDT versions, match the naming conventions of V16:
 		 * give only the leaf name (after all /). The actual tree
@@ -294,7 +358,8 @@
 	int err;
 	const struct fdt_property *prop;
 
-	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+	if (!can_assume(VALID_INPUT) &&
+	    (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
 		if (lenp)
 			*lenp = err;
 		return NULL;
@@ -303,7 +368,7 @@
 	prop = fdt_offset_ptr_(fdt, offset);
 
 	if (lenp)
-		*lenp = fdt32_to_cpu(prop->len);
+		*lenp = fdt32_ld(&prop->len);
 
 	return prop;
 }
@@ -315,7 +380,7 @@
 	/* Prior to version 16, properties may need realignment
 	 * and this API does not work. fdt_getprop_*() will, however. */
 
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		if (lenp)
 			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
@@ -336,11 +401,12 @@
 	     (offset = fdt_next_property_offset(fdt, offset))) {
 		const struct fdt_property *prop;
 
-		if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
+		prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+		if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
 			offset = -FDT_ERR_INTERNAL;
 			break;
 		}
-		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
 				   name, namelen)) {
 			if (poffset)
 				*poffset = offset;
@@ -361,7 +427,7 @@
 {
 	/* Prior to version 16, properties may need realignment
 	 * and this API does not work. fdt_getprop_*() will, however. */
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		if (lenp)
 			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
@@ -392,8 +458,8 @@
 		return NULL;
 
 	/* Handle realignment */
-	if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
-	    fdt32_to_cpu(prop->len) >= 8)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+	    (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
 		return prop->data + 4;
 	return prop->data;
 }
@@ -406,12 +472,27 @@
 	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
 	if (!prop)
 		return NULL;
-	if (namep)
-		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	if (namep) {
+		const char *name;
+		int namelen;
+
+		if (!can_assume(VALID_INPUT)) {
+			name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+					      &namelen);
+			if (!name) {
+				if (lenp)
+					*lenp = namelen;
+				return NULL;
+			}
+			*namep = name;
+		} else {
+			*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+		}
+	}
 
 	/* Handle realignment */
-	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
-	    fdt32_to_cpu(prop->len) >= 8)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+	    (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
 		return prop->data + 4;
 	return prop->data;
 }
@@ -436,7 +517,7 @@
 			return 0;
 	}
 
-	return fdt32_to_cpu(*php);
+	return fdt32_ld(php);
 }
 
 const char *fdt_get_alias_namelen(const void *fdt,
@@ -462,7 +543,7 @@
 	int offset, depth, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (buflen < 2)
 		return -FDT_ERR_NOSPACE;
@@ -514,7 +595,7 @@
 	int offset, depth;
 	int supernodeoffset = -FDT_ERR_INTERNAL;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (supernodedepth < 0)
 		return -FDT_ERR_NOTFOUND;
@@ -536,10 +617,12 @@
 		}
 	}
 
-	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
-		return -FDT_ERR_BADOFFSET;
-	else if (offset == -FDT_ERR_BADOFFSET)
-		return -FDT_ERR_BADSTRUCTURE;
+	if (!can_assume(VALID_INPUT)) {
+		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+			return -FDT_ERR_BADOFFSET;
+		else if (offset == -FDT_ERR_BADOFFSET)
+			return -FDT_ERR_BADSTRUCTURE;
+	}
 
 	return offset; /* error from fdt_next_node() */
 }
@@ -551,7 +634,8 @@
 
 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
 	if (err)
-		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+		return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
+			-FDT_ERR_INTERNAL;
 	return nodedepth;
 }
 
@@ -573,7 +657,7 @@
 	const void *val;
 	int len;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_getprop(), then if that didn't
@@ -599,7 +683,7 @@
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we
 	 * potentially scan each property of a node in
@@ -752,7 +836,7 @@
 {
 	int offset, err;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_node_check_compatible(), then if
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 9b82905..93e4a2b 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
@@ -67,29 +22,31 @@
 		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
 }
 
-static int fdt_rw_check_header_(void *fdt)
+static int fdt_rw_probe_(void *fdt)
 {
-	FDT_CHECK_HEADER(fdt);
+	if (can_assume(VALID_DTB))
+		return 0;
+	FDT_RO_PROBE(fdt);
 
-	if (fdt_version(fdt) < 17)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 17)
 		return -FDT_ERR_BADVERSION;
 	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
 				   fdt_size_dt_struct(fdt)))
 		return -FDT_ERR_BADLAYOUT;
-	if (fdt_version(fdt) > 17)
+	if (!can_assume(LATEST) && fdt_version(fdt) > 17)
 		fdt_set_version(fdt, 17);
 
 	return 0;
 }
 
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
 	{ \
 		int err_; \
-		if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
+		if ((err_ = fdt_rw_probe_(fdt)) != 0) \
 			return err_; \
 	}
 
-static inline int fdt_data_size_(void *fdt)
+static inline unsigned int fdt_data_size_(void *fdt)
 {
 	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 }
@@ -97,15 +54,16 @@
 static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
 {
 	char *p = splicepoint;
-	char *end = (char *)fdt + fdt_data_size_(fdt);
+	unsigned int dsize = fdt_data_size_(fdt);
+	size_t soff = p - (char *)fdt;
 
-	if (((p + oldlen) < p) || ((p + oldlen) > end))
+	if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
 		return -FDT_ERR_BADOFFSET;
-	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+	if ((p < (char *)fdt) || (dsize + newlen < oldlen))
 		return -FDT_ERR_BADOFFSET;
-	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+	if (dsize - oldlen + newlen > fdt_totalsize(fdt))
 		return -FDT_ERR_NOSPACE;
-	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
 	return 0;
 }
 
@@ -136,6 +94,14 @@
 	return 0;
 }
 
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+	int newlen = strlen(s) + 1;
+
+	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
+}
+
 static int fdt_splice_string_(void *fdt, int newlen)
 {
 	void *p = (char *)fdt
@@ -149,7 +115,16 @@
 	return 0;
 }
 
-static int fdt_find_add_string_(void *fdt, const char *s)
+/**
+ * fdt_find_add_string_() - Find or allocate a string
+ *
+ * @fdt: pointer to the device tree to check/adjust
+ * @s: string to find/add
+ * @allocated: Set to 0 if the string was found, 1 if not found and so
+ *	allocated. Ignored if can_assume(NO_ROLLBACK)
+ * @return offset of string in the string table (whether found or added)
+ */
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
 {
 	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
 	const char *p;
@@ -157,6 +132,9 @@
 	int len = strlen(s) + 1;
 	int err;
 
+	if (!can_assume(NO_ROLLBACK))
+		*allocated = 0;
+
 	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
 	if (p)
 		/* found it */
@@ -167,6 +145,9 @@
 	if (err)
 		return err;
 
+	if (!can_assume(NO_ROLLBACK))
+		*allocated = 1;
+
 	memcpy(new, s, len);
 	return (new - strtab);
 }
@@ -176,7 +157,7 @@
 	struct fdt_reserve_entry *re;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
 	err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@@ -192,7 +173,7 @@
 {
 	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	if (n >= fdt_num_mem_rsv(fdt))
 		return -FDT_ERR_NOTFOUND;
@@ -225,11 +206,12 @@
 	int nextoffset;
 	int namestroff;
 	int err;
+	int allocated;
 
 	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
 		return nextoffset;
 
-	namestroff = fdt_find_add_string_(fdt, name);
+	namestroff = fdt_find_add_string_(fdt, name, &allocated);
 	if (namestroff < 0)
 		return namestroff;
 
@@ -237,8 +219,12 @@
 	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
 
 	err = fdt_splice_struct_(fdt, *prop, 0, proplen);
-	if (err)
+	if (err) {
+		/* Delete the string if we failed to add it */
+		if (!can_assume(NO_ROLLBACK) && allocated)
+			fdt_del_last_string_(fdt, name);
 		return err;
+	}
 
 	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
 	(*prop)->nameoff = cpu_to_fdt32(namestroff);
@@ -252,7 +238,7 @@
 	int oldlen, newlen;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
 	if (!namep)
@@ -275,7 +261,7 @@
 	struct fdt_property *prop;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
 	if (err == -FDT_ERR_NOTFOUND)
@@ -308,7 +294,7 @@
 	struct fdt_property *prop;
 	int err, oldlen, newlen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
 	if (prop) {
@@ -334,7 +320,7 @@
 	struct fdt_property *prop;
 	int len, proplen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
 	if (!prop)
@@ -354,7 +340,7 @@
 	uint32_t tag;
 	fdt32_t *endtag;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
 	if (offset >= 0)
@@ -394,7 +380,7 @@
 {
 	int endoffset;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
 	if (endoffset < 0)
@@ -435,12 +421,12 @@
 	const char *fdtend = fdtstart + fdt_totalsize(fdt);
 	char *tmp;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
 
-	if (fdt_version(fdt) >= 17) {
+	if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
 		struct_size = fdt_size_dt_struct(fdt);
 	} else {
 		struct_size = 0;
@@ -450,7 +436,8 @@
 			return struct_size;
 	}
 
-	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
+	if (can_assume(LIBFDT_ORDER) ||
+	    !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
 		/* no further work necessary */
 		err = fdt_move(fdt, buf, bufsize);
 		if (err)
@@ -494,7 +481,7 @@
 {
 	int mem_rsv_size;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
index 9677a18..768db66 100644
--- a/lib/libfdt/fdt_strerror.c
+++ b/lib/libfdt/fdt_strerror.c
@@ -1,51 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
@@ -82,6 +38,7 @@
 	FDT_ERRTABENT(FDT_ERR_BADVALUE),
 	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
 	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
+	FDT_ERRTABENT(FDT_ERR_BADFLAGS),
 };
 #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
 
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 6d33cc2..26759d5 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
@@ -55,21 +10,87 @@
 
 #include "libfdt_internal.h"
 
-static int fdt_sw_check_header_(void *fdt)
+static int fdt_sw_probe_(void *fdt)
 {
-	if (fdt_magic(fdt) != FDT_SW_MAGIC)
-		return -FDT_ERR_BADMAGIC;
-	/* FIXME: should check more details about the header state */
+	if (!can_assume(VALID_INPUT)) {
+		if (fdt_magic(fdt) == FDT_MAGIC)
+			return -FDT_ERR_BADSTATE;
+		else if (fdt_magic(fdt) != FDT_SW_MAGIC)
+			return -FDT_ERR_BADMAGIC;
+	}
+
 	return 0;
 }
 
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE(fdt) \
 	{ \
 		int err; \
-		if ((err = fdt_sw_check_header_(fdt)) != 0) \
+		if ((err = fdt_sw_probe_(fdt)) != 0) \
 			return err; \
 	}
 
+/* 'memrsv' state:	Initial state after fdt_create()
+ *
+ * Allowed functions:
+ *	fdt_add_reservmap_entry()
+ *	fdt_finish_reservemap()		[moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+			return err; \
+	}
+
+/* 'struct' state:	Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ *	fdt_begin_node()
+ *	fdt_end_node()
+ *	fdt_property*()
+ *	fdt_finish()			[moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (!can_assume(VALID_INPUT) &&
+	    fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_STRUCT(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
+			return err; \
+	}
+
+static inline uint32_t sw_flags(void *fdt)
+{
+	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
+	return fdt_last_comp_version(fdt);
+}
+
+/* 'complete' state:	Enter this state after fdt_finish()
+ *
+ * Allowed functions: none
+ */
+
 static void *fdt_grab_space_(void *fdt, size_t len)
 {
 	int offset = fdt_size_dt_struct(fdt);
@@ -85,38 +106,59 @@
 	return fdt_offset_ptr_w_(fdt, offset);
 }
 
-int fdt_create(void *buf, int bufsize)
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
 {
+	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+					 sizeof(struct fdt_reserve_entry));
 	void *fdt = buf;
 
-	if (bufsize < sizeof(struct fdt_header))
+	if (bufsize < hdrsize)
 		return -FDT_ERR_NOSPACE;
 
+	if (flags & ~FDT_CREATE_FLAGS_ALL)
+		return -FDT_ERR_BADFLAGS;
+
 	memset(buf, 0, bufsize);
 
+	/*
+	 * magic and last_comp_version keep intermediate state during the fdt
+	 * creation process, which is replaced with the proper FDT format by
+	 * fdt_finish().
+	 *
+	 * flags should be accessed with sw_flags().
+	 */
 	fdt_set_magic(fdt, FDT_SW_MAGIC);
 	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
-	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_last_comp_version(fdt, flags);
+
 	fdt_set_totalsize(fdt,  bufsize);
 
-	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
-					      sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_mem_rsvmap(fdt, hdrsize);
 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
-	fdt_set_off_dt_strings(fdt, bufsize);
+	fdt_set_off_dt_strings(fdt, 0);
 
 	return 0;
 }
 
+int fdt_create(void *buf, int bufsize)
+{
+	return fdt_create_with_flags(buf, bufsize, 0);
+}
+
 int fdt_resize(void *fdt, void *buf, int bufsize)
 {
 	size_t headsize, tailsize;
 	char *oldtail, *newtail;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE(fdt);
 
-	headsize = fdt_off_dt_struct(fdt);
+	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	tailsize = fdt_size_dt_strings(fdt);
 
+	if (!can_assume(VALID_DTB) &&
+	    headsize + tailsize > fdt_totalsize(fdt))
+		return -FDT_ERR_INTERNAL;
+
 	if ((headsize + tailsize) > bufsize)
 		return -FDT_ERR_NOSPACE;
 
@@ -133,8 +175,9 @@
 		memmove(buf, fdt, headsize);
 	}
 
-	fdt_set_off_dt_strings(buf, bufsize);
 	fdt_set_totalsize(buf, bufsize);
+	if (fdt_off_dt_strings(buf))
+		fdt_set_off_dt_strings(buf, bufsize);
 
 	return 0;
 }
@@ -144,10 +187,7 @@
 	struct fdt_reserve_entry *re;
 	int offset;
 
-	FDT_SW_CHECK_HEADER(fdt);
-
-	if (fdt_size_dt_struct(fdt))
-		return -FDT_ERR_BADSTATE;
+	FDT_SW_PROBE_MEMRSV(fdt);
 
 	offset = fdt_off_dt_struct(fdt);
 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,16 +204,23 @@
 
 int fdt_finish_reservemap(void *fdt)
 {
-	return fdt_add_reservemap_entry(fdt, 0, 0);
+	int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+	if (err)
+		return err;
+
+	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+	return 0;
 }
 
 int fdt_begin_node(void *fdt, const char *name)
 {
 	struct fdt_node_header *nh;
-	int namelen = strlen(name) + 1;
+	int namelen;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
+	namelen = strlen(name) + 1;
 	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
 	if (! nh)
 		return -FDT_ERR_NOSPACE;
@@ -187,7 +234,7 @@
 {
 	fdt32_t *en;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
 	if (! en)
@@ -197,19 +244,13 @@
 	return 0;
 }
 
-static int fdt_find_add_string_(void *fdt, const char *s)
+static int fdt_add_string_(void *fdt, const char *s)
 {
 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
-	const char *p;
 	int strtabsize = fdt_size_dt_strings(fdt);
 	int len = strlen(s) + 1;
 	int struct_top, offset;
 
-	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
-	if (p)
-		return p - strtab;
-
-	/* Add it */
 	offset = -strtabsize - len;
 	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	if (fdt_totalsize(fdt) + offset < struct_top)
@@ -220,20 +261,56 @@
 	return offset;
 }
 
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+
+	fdt_set_size_dt_strings(fdt, strtabsize - len);
+}
+
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	int strtabsize = fdt_size_dt_strings(fdt);
+	const char *p;
+
+	*allocated = 0;
+
+	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	*allocated = 1;
+
+	return fdt_add_string_(fdt, s);
+}
+
 int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
 {
 	struct fdt_property *prop;
 	int nameoff;
+	int allocated;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
-	nameoff = fdt_find_add_string_(fdt, name);
+	/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
+	if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
+		allocated = 1;
+		nameoff = fdt_add_string_(fdt, name);
+	} else {
+		nameoff = fdt_find_add_string_(fdt, name, &allocated);
+	}
 	if (nameoff == 0)
 		return -FDT_ERR_NOSPACE;
 
 	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
-	if (! prop)
+	if (! prop) {
+		if (allocated)
+			fdt_del_last_string_(fdt, name);
 		return -FDT_ERR_NOSPACE;
+	}
 
 	prop->tag = cpu_to_fdt32(FDT_PROP);
 	prop->nameoff = cpu_to_fdt32(nameoff);
@@ -262,7 +339,7 @@
 	uint32_t tag;
 	int offset, nextoffset;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	/* Add terminator */
 	end = fdt_grab_space_(fdt, sizeof(*end));
@@ -295,6 +372,10 @@
 
 	/* Finally, adjust the header */
 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+
+	/* And fix up fields that were keeping intermediate state. */
+	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
 	fdt_set_magic(fdt, FDT_MAGIC);
+
 	return 0;
 }
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 534c1cb..f64139e 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 "libfdt_env.h"
 
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 7681e19..d4e0bd4 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -1,65 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_INTERNAL_H
 #define LIBFDT_INTERNAL_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. 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.
- *
- *     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 OWNER 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 <fdt.h>
 
 #define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
 #define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))
 
-#define FDT_CHECK_HEADER(fdt) \
-	{ \
-		int err_; \
-		if ((err_ = fdt_check_header(fdt)) != 0) \
-			return err_; \
+int32_t fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt)					\
+	{							\
+		int32_t totalsize_;				\
+		if ((totalsize_ = fdt_ro_probe_(fdt)) < 0)	\
+			return totalsize_;			\
 	}
 
 int fdt_check_node_offset_(const void *fdt, int offset);
@@ -92,4 +48,126 @@
 
 #define FDT_SW_MAGIC		(~FDT_MAGIC)
 
+/**********************************************************************/
+/* Checking controls                                                  */
+/**********************************************************************/
+
+#ifndef FDT_ASSUME_MASK
+#define FDT_ASSUME_MASK 0
+#endif
+
+/*
+ * Defines assumptions which can be enabled. Each of these can be enabled
+ * individually. For maximum safety, don't enable any assumptions!
+ *
+ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
+ * You should have another method of validating the device tree, such as a
+ * signature or hash check before using libfdt.
+ *
+ * For situations where security is not a concern it may be safe to enable
+ * ASSUME_SANE.
+ */
+enum {
+	/*
+	 * This does essentially no checks. Only the latest device-tree
+	 * version is correctly handled. Inconsistencies or errors in the device
+	 * tree may cause undefined behaviour or crashes. Invalid parameters
+	 * passed to libfdt may do the same.
+	 *
+	 * If an error occurs when modifying the tree it may leave the tree in
+	 * an intermediate (but valid) state. As an example, adding a property
+	 * where there is insufficient space may result in the property name
+	 * being added to the string table even though the property itself is
+	 * not added to the struct section.
+	 *
+	 * Only use this if you have a fully validated device tree with
+	 * the latest supported version and wish to minimise code size.
+	 */
+	ASSUME_PERFECT		= 0xff,
+
+	/*
+	 * This assumes that the device tree is sane. i.e. header metadata
+	 * and basic hierarchy are correct.
+	 *
+	 * With this assumption enabled, normal device trees produced by libfdt
+	 * and the compiler should be handled safely. Malicious device trees and
+	 * complete garbage may cause libfdt to behave badly or crash. Truncated
+	 * device trees (e.g. those only partially loaded) can also cause
+	 * problems.
+	 *
+	 * Note: Only checks that relate exclusively to the device tree itself
+	 * (not the parameters passed to libfdt) are disabled by this
+	 * assumption. This includes checking headers, tags and the like.
+	 */
+	ASSUME_VALID_DTB	= 1 << 0,
+
+	/*
+	 * This builds on ASSUME_VALID_DTB and further assumes that libfdt
+	 * functions are called with valid parameters, i.e. not trigger
+	 * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
+	 * extensive checking of parameters and the device tree, making various
+	 * assumptions about correctness.
+	 *
+	 * It doesn't make sense to enable this assumption unless
+	 * ASSUME_VALID_DTB is also enabled.
+	 */
+	ASSUME_VALID_INPUT	= 1 << 1,
+
+	/*
+	 * This disables checks for device-tree version and removes all code
+	 * which handles older versions.
+	 *
+	 * Only enable this if you know you have a device tree with the latest
+	 * version.
+	 */
+	ASSUME_LATEST		= 1 << 2,
+
+	/*
+	 * This assumes that it is OK for a failed addition to the device tree,
+	 * due to lack of space or some other problem, to skip any rollback
+	 * steps (such as dropping the property name from the string table).
+	 * This is safe to enable in most circumstances, even though it may
+	 * leave the tree in a sub-optimal state.
+	 */
+	ASSUME_NO_ROLLBACK	= 1 << 3,
+
+	/*
+	 * This assumes that the device tree components appear in a 'convenient'
+	 * order, i.e. the memory reservation block first, then the structure
+	 * block and finally the string block.
+	 *
+	 * This order is not specified by the device-tree specification,
+	 * but is expected by libfdt. The device-tree compiler always created
+	 * device trees with this order.
+	 *
+	 * This assumption disables a check in fdt_open_into() and removes the
+	 * ability to fix the problem there. This is safe if you know that the
+	 * device tree is correctly ordered. See fdt_blocks_misordered_().
+	 */
+	ASSUME_LIBFDT_ORDER	= 1 << 4,
+
+	/*
+	 * This assumes that libfdt itself does not have any internal bugs. It
+	 * drops certain checks that should never be needed unless libfdt has an
+	 * undiscovered bug.
+	 *
+	 * This can generally be considered safe to enable.
+	 */
+	ASSUME_LIBFDT_FLAWLESS	= 1 << 5,
+};
+
+/**
+ * can_assume_() - check if a particular assumption is enabled
+ *
+ * @mask: Mask to check (ASSUME_...)
+ * @return true if that assumption is enabled, else false
+ */
+static inline bool can_assume_(int mask)
+{
+	return FDT_ASSUME_MASK & mask;
+}
+
+/** helper macros for checking assumptions */
+#define can_assume(_assume)	can_assume_(ASSUME_ ## _assume)
+
 #endif /* LIBFDT_INTERNAL_H */
diff --git a/lib/xlat_tables/aarch32/nonlpae_tables.c b/lib/xlat_tables/aarch32/nonlpae_tables.c
index b8c2686..7cd509d 100644
--- a/lib/xlat_tables/aarch32/nonlpae_tables.c
+++ b/lib/xlat_tables/aarch32/nonlpae_tables.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2017, Linaro Limited. All rights reserved.
- * Copyright (c) 2014-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2014-2020, Arm Limited. All rights reserved.
  * Copyright (c) 2014, STMicroelectronics International N.V.
  * All rights reserved.
  *
@@ -30,8 +30,8 @@
 CASSERT(PLAT_VIRT_ADDR_SPACE_SIZE == (1ULL << 32), invalid_vaddr_space_size);
 CASSERT(PLAT_PHY_ADDR_SPACE_SIZE == (1ULL << 32), invalid_paddr_space_size);
 
-#define MMU32B_UNSET_DESC	~0ul
-#define MMU32B_INVALID_DESC	0ul
+#define MMU32B_UNSET_DESC	~0UL
+#define MMU32B_INVALID_DESC	0UL
 
 #define MT_UNKNOWN	~0U
 
@@ -40,38 +40,38 @@
  */
 
 /* Sharable */
-#define MMU32B_TTB_S           (1 << 1)
+#define MMU32B_TTB_S           (1U << 1)
 
 /* Not Outer Sharable */
-#define MMU32B_TTB_NOS         (1 << 5)
+#define MMU32B_TTB_NOS         (1U << 5)
 
 /* Normal memory, Inner Non-cacheable */
-#define MMU32B_TTB_IRGN_NC     0
+#define MMU32B_TTB_IRGN_NC     0U
 
 /* Normal memory, Inner Write-Back Write-Allocate Cacheable */
-#define MMU32B_TTB_IRGN_WBWA   (1 << 6)
+#define MMU32B_TTB_IRGN_WBWA   (1U << 6)
 
 /* Normal memory, Inner Write-Through Cacheable */
-#define MMU32B_TTB_IRGN_WT     1
+#define MMU32B_TTB_IRGN_WT     1U
 
 /* Normal memory, Inner Write-Back no Write-Allocate Cacheable */
-#define MMU32B_TTB_IRGN_WB     (1 | (1 << 6))
+#define MMU32B_TTB_IRGN_WB     (1U | (1U << 6))
 
 /* Normal memory, Outer Write-Back Write-Allocate Cacheable */
-#define MMU32B_TTB_RNG_WBWA    (1 << 3)
+#define MMU32B_TTB_RNG_WBWA    (1U << 3)
 
 #define MMU32B_DEFAULT_ATTRS \
 		(MMU32B_TTB_S | MMU32B_TTB_NOS | \
 		 MMU32B_TTB_IRGN_WBWA | MMU32B_TTB_RNG_WBWA)
 
 /* armv7 memory mapping attributes: section mapping */
-#define SECTION_SECURE			(0 << 19)
-#define SECTION_NOTSECURE		(1 << 19)
-#define SECTION_SHARED			(1 << 16)
-#define SECTION_NOTGLOBAL		(1 << 17)
-#define SECTION_ACCESS_FLAG		(1 << 10)
-#define SECTION_UNPRIV			(1 << 11)
-#define SECTION_RO			(1 << 15)
+#define SECTION_SECURE			(0U << 19)
+#define SECTION_NOTSECURE		(1U << 19)
+#define SECTION_SHARED			(1U << 16)
+#define SECTION_NOTGLOBAL		(1U << 17)
+#define SECTION_ACCESS_FLAG		(1U << 10)
+#define SECTION_UNPRIV			(1U << 11)
+#define SECTION_RO			(1U << 15)
 #define SECTION_TEX(tex)		((((tex) >> 2) << 12) | \
 					((((tex) >> 1) & 0x1) << 3) | \
 					(((tex) & 0x1) << 2))
@@ -80,16 +80,16 @@
 #define SECTION_NORMAL_CACHED		\
 				SECTION_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX)
 
-#define SECTION_XN			(1 << 4)
-#define SECTION_PXN			(1 << 0)
-#define SECTION_SECTION			(2 << 0)
+#define SECTION_XN			(1U << 4)
+#define SECTION_PXN			(1U << 0)
+#define SECTION_SECTION			(2U << 0)
 
-#define SECTION_PT_NOTSECURE		(1 << 3)
-#define SECTION_PT_PT			(1 << 0)
+#define SECTION_PT_NOTSECURE		(1U << 3)
+#define SECTION_PT_PT			(1U << 0)
 
-#define SMALL_PAGE_SMALL_PAGE		(1 << 1)
-#define SMALL_PAGE_SHARED		(1 << 10)
-#define SMALL_PAGE_NOTGLOBAL		(1 << 11)
+#define SMALL_PAGE_SMALL_PAGE		(1U << 1)
+#define SMALL_PAGE_SHARED		(1U << 10)
+#define SMALL_PAGE_NOTGLOBAL		(1U << 11)
 #define SMALL_PAGE_TEX(tex)		((((tex) >> 2) << 6) | \
 					((((tex) >> 1) & 0x1) << 3) | \
 					(((tex) & 0x1) << 2))
@@ -99,39 +99,39 @@
 				SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX)
 #define SMALL_PAGE_NORMAL_CACHED	\
 				SMALL_PAGE_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX)
-#define SMALL_PAGE_ACCESS_FLAG		(1 << 4)
-#define SMALL_PAGE_UNPRIV		(1 << 5)
-#define SMALL_PAGE_RO			(1 << 9)
-#define SMALL_PAGE_XN			(1 << 0)
+#define SMALL_PAGE_ACCESS_FLAG		(1U << 4)
+#define SMALL_PAGE_UNPRIV		(1U << 5)
+#define SMALL_PAGE_RO			(1U << 9)
+#define SMALL_PAGE_XN			(1U << 0)
 
 /* The TEX, C and B bits concatenated */
-#define MMU32B_ATTR_DEVICE_INDEX		0x0
-#define MMU32B_ATTR_IWBWA_OWBWA_INDEX		0x1
+#define MMU32B_ATTR_DEVICE_INDEX	0U
+#define MMU32B_ATTR_IWBWA_OWBWA_INDEX	1U
 
 #define MMU32B_PRRR_IDX(idx, tr, nos)	(((tr) << (2 * (idx))) | \
 					 ((uint32_t)(nos) << ((idx) + 24)))
 #define MMU32B_NMRR_IDX(idx, ir, or)	(((ir) << (2 * (idx))) | \
 					 ((uint32_t)(or) << (2 * (idx) + 16)))
-#define MMU32B_PRRR_DS0			(1 << 16)
-#define MMU32B_PRRR_DS1			(1 << 17)
-#define MMU32B_PRRR_NS0			(1 << 18)
-#define MMU32B_PRRR_NS1			(1 << 19)
+#define MMU32B_PRRR_DS0			(1U << 16)
+#define MMU32B_PRRR_DS1			(1U << 17)
+#define MMU32B_PRRR_NS0			(1U << 18)
+#define MMU32B_PRRR_NS1			(1U << 19)
 
 #define DACR_DOMAIN(num, perm)		((perm) << ((num) * 2))
-#define DACR_DOMAIN_PERM_NO_ACCESS	0x0
-#define DACR_DOMAIN_PERM_CLIENT		0x1
-#define DACR_DOMAIN_PERM_MANAGER	0x3
+#define DACR_DOMAIN_PERM_NO_ACCESS	0U
+#define DACR_DOMAIN_PERM_CLIENT		1U
+#define DACR_DOMAIN_PERM_MANAGER	3U
 
-#define NUM_1MB_IN_4GB		(1U << 12)
-#define NUM_4K_IN_1MB		(1U << 8)
+#define NUM_1MB_IN_4GB		(1UL << 12)
+#define NUM_4K_IN_1MB		(1UL << 8)
 
 #define ONE_MB_SHIFT		20
 
 /* mmu 32b integration */
 #define MMU32B_L1_TABLE_SIZE		(NUM_1MB_IN_4GB * 4)
 #define MMU32B_L2_TABLE_SIZE		(NUM_4K_IN_1MB * 4)
-#define MMU32B_L1_TABLE_ALIGN		(1 << 14)
-#define MMU32B_L2_TABLE_ALIGN		(1 << 10)
+#define MMU32B_L1_TABLE_ALIGN		(1U << 14)
+#define MMU32B_L2_TABLE_ALIGN		(1U << 10)
 
 static unsigned int next_xlat;
 static unsigned long long xlat_max_pa;
@@ -190,8 +190,9 @@
 	assert(IS_PAGE_ALIGNED(base_va));
 	assert(IS_PAGE_ALIGNED(size));
 
-	if (size == 0U)
+	if (size == 0U) {
 		return;
+	}
 
 	assert(base_pa < end_pa); /* Check for overflows */
 	assert(base_va < end_va);
@@ -249,8 +250,9 @@
 #endif /* ENABLE_ASSERTIONS */
 
 	/* Find correct place in mmap to insert new region */
-	while ((mm->base_va < base_va) && (mm->size != 0U))
+	while ((mm->base_va < base_va) && (mm->size != 0U)) {
 		++mm;
+	}
 
 	/*
 	 * If a section is contained inside another one with the same base
@@ -263,8 +265,9 @@
 	 * This is required for mmap_region_attr() to get the attributes of the
 	 * small region correctly.
 	 */
-	while ((mm->base_va == base_va) && (mm->size > size))
+	while ((mm->base_va == base_va) && (mm->size > size)) {
 		++mm;
+	}
 
 	/* Make room for new region by moving other regions up by one place */
 	(void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm);
@@ -277,10 +280,12 @@
 	mm->size = size;
 	mm->attr = attr;
 
-	if (end_pa > xlat_max_pa)
+	if (end_pa > xlat_max_pa) {
 		xlat_max_pa = end_pa;
-	if (end_va > xlat_max_va)
+	}
+	if (end_va > xlat_max_va) {
 		xlat_max_va = end_va;
+	}
 }
 
 /* map all memory as shared/global/domain0/no-usr access */
@@ -290,42 +295,44 @@
 	uint32_t desc;
 
 	switch (level) {
-	case 1:
-		assert(!(addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)));
+	case 1U:
+		assert((addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U);
 
 		desc = SECTION_SECTION | SECTION_SHARED;
 
-		desc |= attr & MT_NS ? SECTION_NOTSECURE : 0;
+		desc |= (attr & MT_NS) != 0U ? SECTION_NOTSECURE : 0U;
 
 		desc |= SECTION_ACCESS_FLAG;
-		desc |= attr & MT_RW ? 0 : SECTION_RO;
+		desc |= (attr & MT_RW) != 0U ? 0U : SECTION_RO;
 
-		desc |= attr & MT_MEMORY ?
+		desc |= (attr & MT_MEMORY) != 0U ?
 			SECTION_NORMAL_CACHED : SECTION_DEVICE;
 
-		if ((attr & MT_RW) || !(attr & MT_MEMORY))
+		if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) {
 			desc |= SECTION_XN;
+		}
 		break;
-	case 2:
-		assert(!(addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)));
+	case 2U:
+		assert((addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U);
 
 		desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED;
 
 		desc |= SMALL_PAGE_ACCESS_FLAG;
-		desc |= attr & MT_RW ? 0 : SMALL_PAGE_RO;
+		desc |= (attr & MT_RW) != 0U ? 0U : SMALL_PAGE_RO;
 
-		desc |= attr & MT_MEMORY ?
+		desc |= (attr & MT_MEMORY) != 0U ?
 			SMALL_PAGE_NORMAL_CACHED : SMALL_PAGE_DEVICE;
 
-		if ((attr & MT_RW) || !(attr & MT_MEMORY))
+		if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) {
 			desc |= SMALL_PAGE_XN;
+		}
 		break;
 	default:
 		panic();
 	}
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 	/* dump only the non-lpae level 2 tables */
-	if (level == 2) {
+	if (level == 2U) {
 		printf(attr & MT_MEMORY ? "MEM" : "dev");
 		printf(attr & MT_RW ? "-rw" : "-RO");
 		printf(attr & MT_NS ? "-NS" : "-S");
@@ -357,26 +364,31 @@
 	 */
 	for ( ; ; ++mm) {
 
-		if (mm->size == 0U)
+		if (mm->size == 0U) {
 			return ret; /* Reached end of list */
+		}
 
-		if (mm->base_va > (base_va + size - 1U))
+		if (mm->base_va > (base_va + size - 1U)) {
 			return ret; /* Next region is after area so end */
+		}
 
-		if ((mm->base_va + mm->size - 1U) < base_va)
+		if ((mm->base_va + mm->size - 1U) < base_va) {
 			continue; /* Next region has already been overtaken */
+		}
 
-		if ((ret == 0U) && (mm->attr == *attr))
+		if ((ret == 0U) && (mm->attr == *attr)) {
 			continue; /* Region doesn't override attribs so skip */
+		}
 
 		if ((mm->base_va > base_va) ||
-			((mm->base_va + mm->size - 1U) < (base_va + size - 1U)))
+			((mm->base_va + mm->size - 1U) <
+					(base_va + size - 1U))) {
 			return MT_UNKNOWN; /* Region doesn't fully cover area */
+		}
 
 		*attr = mm->attr;
 		ret = 0U;
 	}
-	return ret;
 }
 
 static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm,
@@ -384,16 +396,16 @@
 						uint32_t *table,
 						unsigned int level)
 {
-	unsigned int level_size_shift = (level == 1) ?
+	unsigned int level_size_shift = (level == 1U) ?
 					ONE_MB_SHIFT : FOUR_KB_SHIFT;
-	unsigned int level_size = 1 << level_size_shift;
-	unsigned int level_index_mask = (level == 1) ?
+	unsigned int level_size = 1U << level_size_shift;
+	unsigned int level_index_mask = (level == 1U) ?
 					(NUM_1MB_IN_4GB - 1) << ONE_MB_SHIFT :
 					(NUM_4K_IN_1MB - 1) << FOUR_KB_SHIFT;
 
-	assert(level == 1 || level == 2);
+	assert((level == 1U) || (level == 2U));
 
-	VERBOSE("init xlat table at %p (level%1d)\n", (void *)table, level);
+	VERBOSE("init xlat table at %p (level%1u)\n", (void *)table, level);
 
 	do  {
 		uint32_t desc = MMU32B_UNSET_DESC;
@@ -405,15 +417,17 @@
 		}
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 		/* dump only non-lpae level 2 tables content */
-		if (level == 2)
+		if (level == 2U) {
 			printf("      0x%lx %x " + 6 - 2 * level,
 						base_va, level_size);
+		}
 #endif
 		if (mm->base_va >= base_va + level_size) {
 			/* Next region is after area so nothing to map yet */
 			desc = MMU32B_INVALID_DESC;
-		} else if (mm->base_va <= base_va && mm->base_va + mm->size >=
-				base_va + level_size) {
+		} else if ((mm->base_va <= base_va) &&
+				(mm->base_va + mm->size) >=
+				(base_va + level_size)) {
 			/* Next region covers all of area */
 			unsigned int attr = mm->attr;
 			unsigned int r = mmap_region_attr(mm, base_va,
@@ -436,8 +450,8 @@
 			 */
 			if (*table) {
 				assert((*table & 3) == SECTION_PT_PT);
-				assert(!(*table & SECTION_PT_NOTSECURE) ==
-							!(mm->attr & MT_NS));
+				assert(((*table & SECTION_PT_NOTSECURE) == 0U)
+						== ((mm->attr & MT_NS) == 0U));
 
 				xlat_table = (*table) &
 						~(MMU32B_L1_TABLE_ALIGN - 1);
@@ -447,11 +461,11 @@
 					next_xlat * MMU32B_L2_TABLE_SIZE;
 				next_xlat++;
 				assert(next_xlat <= MAX_XLAT_TABLES);
-				memset((char *)xlat_table, 0,
+				(void)memset((char *)xlat_table, 0,
 					MMU32B_L2_TABLE_SIZE);
 
 				desc = xlat_table | SECTION_PT_PT;
-				desc |= mm->attr & MT_NS ?
+				desc |= (mm->attr & MT_NS) != 0U ?
 					SECTION_PT_NOTSECURE : 0;
 			}
 			/* Recurse to fill in new table */
@@ -461,12 +475,13 @@
 		}
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 		/* dump only non-lpae level 2 tables content */
-		if (level == 2)
+		if (level == 2U) {
 			printf("\n");
+		}
 #endif
 		*table++ = desc;
 		base_va += level_size;
-	} while (mm->size && (base_va & level_index_mask));
+	} while ((mm->size != 0U) && ((base_va & level_index_mask) != 0U));
 
 	return mm;
 }
@@ -475,17 +490,16 @@
 {
 	print_mmap();
 
-	assert(!((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)));
-	assert(!((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)));
+	assert(((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U);
+	assert(((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U);
 
-	memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE);
+	(void)memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE);
 
 	init_xlation_table_inner(mmap, 0, (uint32_t *)mmu_l1_base, 1);
 
 	VERBOSE("init xlat - max_va=%p, max_pa=%llx\n",
 			(void *)xlat_max_va, xlat_max_pa);
-	assert(xlat_max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
-	assert(xlat_max_pa <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
+	assert(xlat_max_pa <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1));
 }
 
 /*******************************************************************************
@@ -499,7 +513,7 @@
 	unsigned int sctlr;
 
 	assert(IS_IN_SECURE());
-	assert((read_sctlr() & SCTLR_M_BIT) == 0);
+	assert((read_sctlr() & SCTLR_M_BIT) == 0U);
 
 	/* Enable Access flag (simplified access permissions) and TEX remap */
 	write_sctlr(read_sctlr() | SCTLR_AFE_BIT | SCTLR_TRE_BIT);
@@ -522,7 +536,7 @@
 
 	/* set MMU base xlat table entry (use only TTBR0) */
 	write_ttbr0((uint32_t)mmu_l1_base | MMU32B_DEFAULT_ATTRS);
-	write_ttbr1(0);
+	write_ttbr1(0U);
 
 	/*
 	 * Ensure all translation table writes have drained
@@ -535,14 +549,15 @@
 
 	sctlr = read_sctlr();
 	sctlr |= SCTLR_M_BIT;
-#if ARMV7_SUPPORTS_VIRTUALIZATION
+#ifdef ARMV7_SUPPORTS_VIRTUALIZATION
 	sctlr |= SCTLR_WXN_BIT;
 #endif
 
-	if (flags & DISABLE_DCACHE)
+	if ((flags & DISABLE_DCACHE) != 0U) {
 		sctlr &= ~SCTLR_C_BIT;
-	else
+	} else {
 		sctlr |= SCTLR_C_BIT;
+	}
 
 	write_sctlr(sctlr);
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 6db228f..caf5990 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -305,3 +305,9 @@
 
 # Trap RAS error record access from lower EL
 RAS_TRAP_LOWER_EL_ERR_ACCESS	:= 0
+
+# Build option to create cot descriptors using fconf
+COT_DESC_IN_DTB			:= 0
+
+# Build option to provide openssl directory path
+OPENSSL_DIR			:= /usr
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index 0745316..792a754 100644
--- a/plat/arm/board/a5ds/include/platform_def.h
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -152,10 +152,18 @@
 #endif
 
 /*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -194,6 +202,12 @@
 #define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
 #define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
 
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
 /*******************************************************************************
  * BL1 specific defines.
  * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
@@ -221,6 +235,8 @@
 
 /* Put BL32 below BL2 in NS DRAM.*/
 #define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 #define BL32_BASE			((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
 						- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index 7693e46..5d610f4 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -14,9 +14,10 @@
 				plat/arm/common/arm_dyn_cfg_helpers.c	\
 				common/fdt_wrappers.c
 
-A5DS_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+A5DS_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
index aeed310..20120c9 100644
--- a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
+++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
@@ -7,6 +7,8 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <common/bl_common.h>
+#include "../fpga_private.h"
+
 #include <platform_def.h>
 
 	.globl	plat_get_my_entrypoint
@@ -14,10 +16,10 @@
 	.globl	plat_is_my_cpu_primary
 	.globl	platform_mem_init
 	.globl	plat_my_core_pos
-	.globl	plat_fpga_calc_core_pos
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
 	.globl	plat_crash_console_flush
+	.globl	plat_fpga_calc_core_pos
 
 /* -----------------------------------------------------------------------
  * Indicate a cold boot for every CPU - warm boot is unsupported for the
@@ -34,23 +36,59 @@
  * -----------------------------------------------------------------------
  */
 func plat_secondary_cold_boot_setup
+
+	/*
+	 * Wait for the primary processor to initialise the .BSS segment
+	 * to avoid a race condition that would erase fpga_valid_mpids
+	 * if it is populated before the C runtime is ready.
+	 *
+	 * We cannot use the current spin-lock implementation until the
+	 * runtime is up and we should not rely on sevl/wfe instructions as
+	 * it is optional whether they are implemented or not, so we use
+	 * a global variable as lock and wait for the primary processor to
+	 * finish the C runtime bring-up.
+	 */
+
+	ldr	w0, =C_RUNTIME_READY_KEY
+	adrp	x1, secondary_core_spinlock
+	add	x1, x1, :lo12:secondary_core_spinlock
+1:
+	wfe
+	ldr	w2, [x1]
+	cmp	w2, w0
+	b.ne	1b
+	/* Prevent reordering of the store into fpga_valid_mpids below */
+	dmb	ish
+
+	mov	x10, x30
+	bl	plat_my_core_pos
+	mov	x30, x10
+
+	adrp	x4, fpga_valid_mpids
+	add	x4, x4, :lo12:fpga_valid_mpids
+	mov	x5, #VALID_MPID
+	strb	w5, [x4, x0]
+
 	/*
 	 * Poll the CPU's hold entry until it indicates to jump
 	 * to the entrypoint address.
 	 */
-	bl	plat_my_core_pos
-	lsl	x0, x0, #PLAT_FPGA_HOLD_ENTRY_SHIFT
-	ldr	x1, =hold_base
-	ldr	x2, =fpga_sec_entrypoint
+
+	adrp	x1, hold_base
+	add	x1, x1, :lo12:hold_base
 poll_hold_entry:
-	ldr	x3, [x1, x0]
+	ldr	x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
 	cmp	x3, #PLAT_FPGA_HOLD_STATE_GO
 	b.ne	1f
+
+	adrp	x2, fpga_sec_entrypoint
+	add	x2, x2, :lo12:fpga_sec_entrypoint
 	ldr	x3, [x2]
 	br	x3
 1:
 	wfe
 	b	poll_hold_entry
+
 endfunc plat_secondary_cold_boot_setup
 
 /* -----------------------------------------------------------------------
@@ -73,12 +111,16 @@
 endfunc platform_mem_init
 
 func plat_my_core_pos
+	ldr	x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
 	mrs	x0, mpidr_el1
+	and	x0, x0, x1
 	b	plat_fpga_calc_core_pos
+
 endfunc plat_my_core_pos
 
 /* -----------------------------------------------------------------------
- * unsigned int plat_fpga_calc_core_pos(u_register_t mpidr)
+ * unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
+ * Clobber registers: x0 to x5
  * -----------------------------------------------------------------------
  */
 func plat_fpga_calc_core_pos
@@ -88,6 +130,7 @@
 	 *
 	 * If not set, shift MPIDR to left to make it look as if in a
 	 * multi-threaded implementation.
+	 *
 	 */
 	tst	x0, #MPIDR_MT_MASK
 	lsl	x3, x0, #MPIDR_AFFINITY_BITS
@@ -98,11 +141,13 @@
 	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
 	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
 
-	/* Compute linear position */
 	mov	x4, #FPGA_MAX_CPUS_PER_CLUSTER
-	madd	x1, x2, x4, x1
 	mov	x5, #FPGA_MAX_PE_PER_CPU
+
+	/* Compute linear position */
+	madd	x1, x2, x4, x1
 	madd	x0, x1, x5, x0
+
 	ret
 endfunc plat_fpga_calc_core_pos
 
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index e4b9767..9db107c 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -7,23 +7,23 @@
 #include <assert.h>
 
 #include <common/fdt_wrappers.h>
+#include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
-#include <lib/mmio.h>
 #include <libfdt.h>
 
+#include "fpga_private.h"
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
-#include "fpga_private.h"
-
 static entry_point_info_t bl33_image_ep_info;
+volatile uint32_t secondary_core_spinlock;
 
 uintptr_t plat_get_ns_image_entrypoint(void)
 {
 #ifdef PRELOADED_BL33_BASE
 	return PRELOADED_BL33_BASE;
 #else
-	return 0;
+	return 0ULL;
 #endif
 }
 
@@ -35,6 +35,17 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
+	/* Add this core to the VALID mpids list */
+	fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
+
+	/*
+	 * Notify the secondary CPUs that the C runtime is ready
+	 * so they can announce themselves.
+	 */
+	secondary_core_spinlock = C_RUNTIME_READY_KEY;
+	dsbish();
+	sev();
+
 	fpga_console_init();
 
 	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
@@ -54,11 +65,37 @@
 
 void bl31_platform_setup(void)
 {
-	/* Initialize the GIC driver, cpu and distributor interfaces */
-	plat_fpga_gic_init();
-
 	/* Write frequency to CNTCRL and initialize timer */
 	generic_delay_timer_init();
+
+	/*
+	 * Before doing anything else, wait for some time to ensure that
+	 * the secondary CPUs have populated the fpga_valid_mpids array.
+	 * As the number of secondary cores is unknown and can even be 0,
+	 * it is not possible to rely on any signal from them, so use a
+	 * delay instead.
+	 */
+	mdelay(5);
+
+	/*
+	 * On the event of a cold reset issued by, for instance, a reset pin
+	 * assertion, we cannot guarantee memory to be initialized to zero.
+	 * In such scenario, if the secondary cores reached
+	 * plat_secondary_cold_boot_setup before the primary one initialized
+	 * .BSS, we could end up having a race condition if the spinlock
+	 * was not cleared before.
+	 *
+	 * Similarly, if there were a reset before the spinlock had been
+	 * cleared, the secondary cores would find the lock opened before
+	 * .BSS is cleared, causing another race condition.
+	 *
+	 * So clean the spinlock as soon as we think it is safe to reduce the
+	 * chances of any race condition on a reset.
+	 */
+	secondary_core_spinlock = 0UL;
+
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	plat_fpga_gic_init();
 }
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
@@ -91,6 +128,84 @@
 				       FPGA_DEFAULT_TIMER_FREQUENCY);
 }
 
+static void fpga_prepare_dtb(void)
+{
+	void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+	const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE;
+	int err;
+
+	err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE);
+	if (err < 0) {
+		ERROR("cannot open devicetree at %p: %d\n", fdt, err);
+		panic();
+	}
+
+	/* Check for the command line signature. */
+	if (!strncmp(cmdline, "CMD:", 4)) {
+		int chosen;
+
+		INFO("using command line at 0x%x\n", FPGA_PRELOADED_CMD_LINE);
+
+		chosen = fdt_add_subnode(fdt, 0, "chosen");
+		if (chosen == -FDT_ERR_EXISTS) {
+			chosen = fdt_path_offset(fdt, "/chosen");
+		}
+		if (chosen < 0) {
+			ERROR("cannot find /chosen node: %d\n", chosen);
+		} else {
+			const char *eol;
+			char nul = 0;
+			int slen;
+
+			/*
+			 * There is most likely an EOL at the end of the
+			 * command line, make sure we terminate the line there.
+			 * We can't replace the EOL with a NUL byte in the
+			 * source, as this is in read-only memory. So we first
+			 * create the property without any termination, then
+			 * append a single NUL byte.
+			 */
+			eol = strchr(cmdline, '\n');
+			if (!eol) {
+				eol = strchr(cmdline, 0);
+			}
+			/* Skip the signature and omit the EOL/NUL byte. */
+			slen = eol - (cmdline + 4);
+
+			/*
+			 * Let's limit the size of the property, just in case
+			 * we find the signature by accident. The Linux kernel
+			 * limits to 4096 characters at most (in fact 2048 for
+			 * arm64), so that sounds like a reasonable number.
+			 */
+			if (slen > 4095) {
+				slen = 4095;
+			}
+			err = fdt_setprop(fdt, chosen, "bootargs",
+					  cmdline + 4, slen);
+			if (!err) {
+				err = fdt_appendprop(fdt, chosen, "bootargs",
+						     &nul, 1);
+			}
+			if (err) {
+				ERROR("Could not set command line: %d\n", err);
+			}
+		}
+	}
+
+	err = fdt_pack(fdt);
+	if (err < 0) {
+		ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err);
+	}
+
+	clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	fpga_prepare_dtb();
+}
+
 void bl31_plat_enable_mmu(uint32_t flags)
 {
 	/* TODO: determine if MMU needs to be enabled */
diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h
index 0378729..2884ea6 100644
--- a/plat/arm/board/arm_fpga/fpga_def.h
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -18,7 +18,8 @@
  * that are present will still be indexed appropriately regardless of any empty
  * entries in the array used to represent the topology.
  */
-#define FPGA_MAX_CLUSTER_COUNT			2
+
+#define FPGA_MAX_CLUSTER_COUNT			4
 #define FPGA_MAX_CPUS_PER_CLUSTER		8
 #define FPGA_MAX_PE_PER_CPU			4
 
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 7545bd1..47059d6 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -7,12 +7,24 @@
 #ifndef FPGA_PRIVATE_H
 #define FPGA_PRIVATE_H
 
-unsigned int plat_fpga_calc_core_pos(u_register_t mpidr);
+#include "../fpga_def.h"
+#include <platform_def.h>
+
+#define C_RUNTIME_READY_KEY	(0xaa55aa55)
+#define VALID_MPID		(1U)
+#define FPGA_MAX_DTB_SIZE	0x10000
+
+#ifndef __ASSEMBLER__
+
+extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
 
 void fpga_console_init(void);
 
 void plat_fpga_gic_init(void);
 void fpga_pwr_gic_on_finish(void);
 void fpga_pwr_gic_off(void);
+unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
 
-#endif
+#endif /* __ASSEMBLER__ */
+
+#endif /* FPGA_PRIVATE_H */
diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c
index a705429..7fead86 100644
--- a/plat/arm/board/arm_fpga/fpga_topology.c
+++ b/plat/arm/board/arm_fpga/fpga_topology.c
@@ -5,15 +5,20 @@
  */
 
 #include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/spinlock.h>
 
 #include "fpga_private.h"
+#include <plat/common/platform.h>
 #include <platform_def.h>
 
-static unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
 
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	int i;
+	unsigned int i;
+
 	/*
 	* The highest level is the system level. The next level is constituted
 	* by clusters and then cores in clusters.
@@ -21,12 +26,26 @@
 	* This description of the power domain topology is aligned with the CPU
 	* indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
 	* APIs.
+	*
+	* A description of the topology tree can be found at
+	* https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
 	*/
-	fpga_power_domain_tree_desc[0] = 1;
-	fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
 
-	for (i = 0; i < FPGA_MAX_CLUSTER_COUNT; i++) {
-		fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER;
+	if (fpga_power_domain_tree_desc[0] == 0U) {
+		/*
+		 * As fpga_power_domain_tree_desc[0] == 0, assume that the
+		 * Power Domain Topology Tree has not been initialized, so
+		 * perform the initialization here.
+		 */
+
+		fpga_power_domain_tree_desc[0] = 1U;
+		fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
+
+		for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
+			fpga_power_domain_tree_desc[2 + i] =
+				(FPGA_MAX_CPUS_PER_CLUSTER *
+				 FPGA_MAX_PE_PER_CPU);
+		}
 	}
 
 	return fpga_power_domain_tree_desc;
@@ -34,38 +53,25 @@
 
 int plat_core_pos_by_mpidr(u_register_t mpidr)
 {
-	unsigned int cluster_id, cpu_id, thread_id;
+	unsigned int core_pos;
 
-	mpidr &= MPIDR_AFFINITY_MASK;
-	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
-		return -1;
-	}
-
-	if (mpidr & MPIDR_MT_MASK) {
-		thread_id = MPIDR_AFFLVL0_VAL(mpidr);
-	} else {
-		thread_id = 0;
-	}
-
-	cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
-	cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
-
-	if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) {
-		return -1;
-	} else if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
-		return -1;
-	} else if (thread_id >= FPGA_MAX_PE_PER_CPU) {
-		return -1;
-	}
-
-	/*
-	 * The image running on the FPGA may or may not implement multithreading,
-	 * and it shouldn't be assumed this is consistent across all CPUs.
-	 * This ensures that any passed mpidr values reflect the status of the
-	 * primary CPU's MT bit.
-	 */
+	mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
 	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
 
-	/* Calculate the correct core, catering for multi-threaded images */
-	return (int) plat_fpga_calc_core_pos(mpidr);
+	if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
+	    (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
+	    (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
+		ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
+		panic();
+	}
+
+	/* Calculate the core position, based on the maximum topology. */
+	core_pos = plat_fpga_calc_core_pos(mpidr);
+
+	/* Check whether this core is actually present. */
+	if (fpga_valid_mpids[core_pos] != VALID_MPID) {
+		return -1;
+	}
+
+	return core_pos;
 }
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index 31fc987..411b936 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -21,11 +21,12 @@
 #define CACHE_WRITEBACK_SHIFT		U(6)
 #define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
 
-#define PLATFORM_CORE_COUNT \
-	(FPGA_MAX_CLUSTER_COUNT * FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU)
+#define PLATFORM_CORE_COUNT		\
+	(FPGA_MAX_CLUSTER_COUNT *	\
+	 FPGA_MAX_CPUS_PER_CLUSTER *	\
+	 FPGA_MAX_PE_PER_CPU)
 
-#define PLAT_NUM_PWR_DOMAINS		(FPGA_MAX_CLUSTER_COUNT + \
-					PLATFORM_CORE_COUNT) + 1
+#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1)
 
 #if !ENABLE_PIE
 #define BL31_BASE			UL(0x80000000)
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 34e50ea..1e7badf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -24,15 +24,13 @@
 $(error "TRUSTED_BOARD_BOOT must be disabled")
 endif
 
-ifndef PRELOADED_BL33_BASE
-$(error "PRELOADED_BL33_BASE is not set")
-endif
+PRELOADED_BL33_BASE := 0x80080000
 
-ifndef FPGA_PRELOADED_DTB_BASE
-$(error "FPGA_PRELOADED_DTB_BASE is not set")
-else
+FPGA_PRELOADED_DTB_BASE := 0x80070000
 $(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
-endif
+
+FPGA_PRELOADED_CMD_LINE := 0x1000
+$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
 
 # Treating this as a memory-constrained port for now
 USE_COHERENT_MEM	:=	0
@@ -64,7 +62,10 @@
 				lib/cpus/aarch64/neoverse_zeus.S	\
 				lib/cpus/aarch64/cortex_hercules_ae.S	\
 				lib/cpus/aarch64/cortex_a65.S		\
-				lib/cpus/aarch64/cortex_a65ae.S
+				lib/cpus/aarch64/cortex_a65ae.S		\
+				lib/cpus/aarch64/cortex_klein.S		\
+				lib/cpus/aarch64/cortex_matterhorn.S
+
 # AArch64/AArch32 cores
 	FPGA_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S	\
 				lib/cpus/aarch64/cortex_a75.S
diff --git a/plat/arm/board/corstone700/corstone700_helpers.S b/plat/arm/board/corstone700/common/corstone700_helpers.S
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_helpers.S
rename to plat/arm/board/corstone700/common/corstone700_helpers.S
diff --git a/plat/arm/board/corstone700/corstone700_plat.c b/plat/arm/board/corstone700/common/corstone700_plat.c
similarity index 86%
rename from plat/arm/board/corstone700/corstone700_plat.c
rename to plat/arm/board/corstone700/common/corstone700_plat.c
index e2ade70..629f076 100644
--- a/plat/arm/board/corstone700/corstone700_plat.c
+++ b/plat/arm/board/corstone700/common/corstone700_plat.c
@@ -18,6 +18,7 @@
 
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
+	ARM_MAP_NS_SHARED_RAM,
 	ARM_MAP_NS_DRAM1,
 	CORSTONE700_MAP_DEVICE,
 	{0}
@@ -33,5 +34,6 @@
 
 unsigned int plat_get_syscnt_freq2(void)
 {
-	return CORSTONE700_TIMER_BASE_FREQUENCY;
+	/* Returning the Generic Timer Frequency */
+	return SYS_COUNTER_FREQ_IN_TICKS;
 }
diff --git a/plat/arm/board/corstone700/corstone700_pm.c b/plat/arm/board/corstone700/common/corstone700_pm.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_pm.c
rename to plat/arm/board/corstone700/common/corstone700_pm.c
diff --git a/plat/arm/board/corstone700/corstone700_security.c b/plat/arm/board/corstone700/common/corstone700_security.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_security.c
rename to plat/arm/board/corstone700/common/corstone700_security.c
diff --git a/plat/arm/board/corstone700/corstone700_stack_protector.c b/plat/arm/board/corstone700/common/corstone700_stack_protector.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_stack_protector.c
rename to plat/arm/board/corstone700/common/corstone700_stack_protector.c
diff --git a/plat/arm/board/corstone700/corstone700_topology.c b/plat/arm/board/corstone700/common/corstone700_topology.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_topology.c
rename to plat/arm/board/corstone700/common/corstone700_topology.c
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.c b/plat/arm/board/corstone700/common/drivers/mhu/mhu.c
similarity index 100%
rename from plat/arm/board/corstone700/drivers/mhu/mhu.c
rename to plat/arm/board/corstone700/common/drivers/mhu/mhu.c
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.h b/plat/arm/board/corstone700/common/drivers/mhu/mhu.h
similarity index 100%
rename from plat/arm/board/corstone700/drivers/mhu/mhu.h
rename to plat/arm/board/corstone700/common/drivers/mhu/mhu.h
diff --git a/plat/arm/board/corstone700/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h
similarity index 86%
rename from plat/arm/board/corstone700/include/platform_def.h
rename to plat/arm/board/corstone700/common/include/platform_def.h
index 7799cec..57b0551 100644
--- a/plat/arm/board/corstone700/include/platform_def.h
+++ b/plat/arm/board/corstone700/common/include/platform_def.h
@@ -67,6 +67,9 @@
 #define ARM_BL_RAM_SIZE			(PLAT_ARM_TRUSTED_SRAM_SIZE -   \
 					ARM_SHARED_RAM_SIZE)
 
+#define ARM_NS_SHARED_RAM_BASE		ARM_TRUSTED_SRAM_BASE + UL(0x00100000)
+#define ARM_NS_SHARED_RAM_SIZE		0x00300000
+
 /*
  * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
  * the page reserved for fw_configs) to BL32
@@ -90,10 +93,23 @@
 #define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
 
 /*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE		(ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			2
+#define ARM_BL_REGIONS			3
 #define PLAT_ARM_MMAP_ENTRIES		8
 #define MAX_XLAT_TABLES			5
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +        \
@@ -111,7 +127,13 @@
 #define ARM_SYS_CNTCTL_BASE			UL(0x1a200000)
 #define ARM_SYS_CNTREAD_BASE			UL(0x1a210000)
 #define ARM_SYS_TIMCTL_BASE			UL(0x1a220000)
-#define CORSTONE700_TIMER_BASE_FREQUENCY	UL(24000000)
+
+#ifdef TARGET_PLATFORM_FVP
+#define SYS_COUNTER_FREQ_IN_TICKS	UL(50000000) /* 50MHz */
+#else
+#define SYS_COUNTER_FREQ_IN_TICKS	UL(32000000) /* 32MHz */
+#endif
+
 #define CORSTONE700_IRQ_TZ_WDOG			32
 #define CORSTONE700_IRQ_SEC_SYS_TIMER		34
 
@@ -140,7 +162,7 @@
 #define PLAT_ARM_TRUSTED_MAILBOX_BASE		ARM_TRUSTED_SRAM_BASE
 #define PLAT_ARM_NSTIMER_FRAME_ID		U(1)
 
-#define PLAT_ARM_NS_IMAGE_OFFSET		(ARM_DRAM1_BASE + UL(0x8000000))
+#define PLAT_ARM_NS_IMAGE_BASE			(ARM_NS_SHARED_RAM_BASE)
 
 #define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 32)
@@ -162,7 +184,12 @@
 #define ARM_MAP_SHARED_RAM			MAP_REGION_FLAT(	\
 						ARM_SHARED_RAM_BASE,	\
 						ARM_SHARED_RAM_SIZE,	\
-						MT_DEVICE | MT_RW | MT_SECURE)
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_SHARED_RAM			MAP_REGION_FLAT(	\
+						ARM_NS_SHARED_RAM_BASE,	\
+						ARM_NS_SHARED_RAM_SIZE,	\
+						MT_MEMORY | MT_RW | MT_NS)
 
 #define ARM_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
 						ARM_NS_DRAM1_BASE,	\
@@ -187,6 +214,14 @@
 						MT_DEVICE | MT_RW | MT_SECURE)
 #endif
 
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
 #define CORSTONE700_DEVICE_BASE		(0x1A000000)
 #define CORSTONE700_DEVICE_SIZE		(0x26000000)
 #define CORSTONE700_MAP_DEVICE		MAP_REGION_FLAT(		\
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index a4d4f22..513af3c 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -4,6 +4,11 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Making sure the corstone700 platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+        $(error TARGET_PLATFORM must be fpga or fvp)
+endif
+
 CORSTONE700_CPU_LIBS	+=	lib/cpus/aarch32/cortex_a32.S
 
 BL32_SOURCES		+=	plat/arm/common/aarch32/arm_helpers.S	\
@@ -12,17 +17,18 @@
 				lib/xlat_tables/aarch32/xlat_tables.c	\
 				lib/xlat_tables/xlat_tables_common.c	\
 				${CORSTONE700_CPU_LIBS}	\
-				plat/arm/board/corstone700/drivers/mhu/mhu.c
+				plat/arm/board/corstone700/common/drivers/mhu/mhu.c
 
-PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/include	\
+PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/common/include	\
 				-Iinclude/plat/arm/common	\
-				-Iplat/arm/board/corstone700/drivers/mhu
+				-Iplat/arm/board/corstone700/common/drivers/mhu
 
 NEED_BL32		:=	yes
 
-CORSTONE700_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+CORSTONE700_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
@@ -30,13 +36,14 @@
 override NEED_BL1	:=	no
 override NEED_BL2	:=	no
 override NEED_BL2U	:=	no
+override NEED_BL33	:=	yes
 
 #TFA for Corstone700 starts from BL32
 override RESET_TO_SP_MIN	:=	1
 
 #Device tree
-CORSTONE700_HW_CONFIG_DTS	:=	fdts/corstone700.dts
-CORSTONE700_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+CORSTONE700_HW_CONFIG_DTS	:=	fdts/corstone700_${TARGET_PLATFORM}.dts
+CORSTONE700_HW_CONFIG		:=	${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb
 FDT_SOURCES			+=	${CORSTONE700_HW_CONFIG_DTS}
 $(eval CORSTONE700_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS)))
 
@@ -49,4 +56,8 @@
     $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
   endif
   $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
+# Adding TARGET_PLATFORM as a GCC define (-D option)
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
 include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
index acee6c3..75dc0f1 100644
--- a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -7,17 +7,17 @@
 # SP_MIN source files specific to FVP platform
 BL32_SOURCES	+=	drivers/cfi/v2m/v2m_flash.c				\
 			lib/utils/mem_region.c					\
-			plat/arm/board/corstone700/corstone700_helpers.S	\
-			plat/arm/board/corstone700/corstone700_topology.c	\
-			plat/arm/board/corstone700/corstone700_security.c	\
-			plat/arm/board/corstone700/corstone700_plat.c		\
-			plat/arm/board/corstone700/corstone700_pm.c		\
+			plat/arm/board/corstone700/common/corstone700_helpers.S	\
+			plat/arm/board/corstone700/common/corstone700_topology.c	\
+			plat/arm/board/corstone700/common/corstone700_security.c	\
+			plat/arm/board/corstone700/common/corstone700_plat.c		\
+			plat/arm/board/corstone700/common/corstone700_pm.c		\
 			plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c	\
 			${CORSTONE700_GIC_SOURCES}
 
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 	ifneq (${ENABLE_STACK_PROTECTOR},none)
-		BL32_SOURCES += plat/arm/board/corstone700/corstone700_stack_protector.c
+		BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c
 	endif
 endif
 
diff --git a/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
new file mode 100644
index 0000000..e258015
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+
+#include <libfdt.h>
+#include <fconf_nt_config_getter.h>
+
+#include <plat/common/platform.h>
+
+struct event_log_config_t event_log_config;
+
+int fconf_populate_event_log_config(uintptr_t config)
+{
+	int err;
+	int node;
+
+	/* Necessary to work with libfdt APIs */
+	const void *dtb = (const void *)config;
+
+	/*
+	 * Find the offset of the node containing "arm,tpm_event_log"
+	 * compatible property
+	 */
+	const char *compatible_str = "arm,tpm_event_log";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find '%s' compatible in dtb\n",
+			compatible_str);
+		return node;
+	}
+
+	/* Retrieve Event Log details from the DTB */
+#ifdef SPD_opteed
+	err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2,
+				&event_log_config.tpm_event_log_sm_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n");
+		return err;
+	}
+#endif
+	err = fdtw_read_cells(dtb, node,
+		"tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n");
+		return err;
+	}
+
+	err = fdtw_read_cells(dtb, node,
+		"tpm_event_log_size", 1, &event_log_config.tpm_event_log_size);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n");
+	}
+
+	return err;
+}
+
+FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config,
+				fconf_populate_event_log_config);
diff --git a/plat/arm/board/fvp/fdts/event_log.dtsi b/plat/arm/board/fvp/fdts/event_log.dtsi
new file mode 100644
index 0000000..47af672
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/event_log.dtsi
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* TPM Event Log Config */
+event_log: tpm_event_log {
+	compatible = "arm,tpm_event_log";
+	tpm_event_log_addr = <0x0 0x0>;
+	tpm_event_log_size = <0x0>;
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index 09f2730..9fb566b 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -14,7 +14,7 @@
 
 		tb_fw-config {
 			load-address = <0x0 0x4001300>;
-			max-size = <0x200>;
+			max-size = <0x1800>;
 			id = <TB_FW_CONFIG_ID>;
 		};
 
diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
index 7ab980b..8f32b98 100644
--- a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,5 +7,13 @@
 /dts-v1/;
 
 / {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
 };
+
+#if MEASURED_BOOT && defined(SPD_opteed)
+&event_log {
+	tpm_event_log_sm_addr = <0x0 0x0>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..f5b31b4
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define	AFF	00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define	POST \
+	};
+
+/ {
+	compatible = "arm,ffa-core-manifest-1.0";
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	attribute {
+		spmc_id = <0x8000>;
+		maj_ver = <0x1>;
+		min_ver = <0x0>;
+		exec_state = <0x0>;
+		load_address = <0x0 0x6000000>;
+		entrypoint = <0x0 0x6000000>;
+		binary_size = <0x80000>;
+	};
+
+	chosen {
+		linux,initrd-start = <0>;
+		linux,initrd-end = <0>;
+	};
+
+	hypervisor {
+		compatible = "hafnium,hafnium";
+		vm1 {
+			is_ffa_partition;
+			debug_name = "op-tee";
+			load_address = <0x6280000>;
+			smc_whitelist = <0xbe000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		CPU_0
+
+		/*
+		 * SPMC(Hafnium) requires secondary core nodes are declared
+		 * in descending order.
+		 */
+		CPU_7
+		CPU_6
+		CPU_5
+		CPU_4
+		CPU_3
+		CPU_2
+		CPU_1
+	};
+
+	memory@60000000 {
+		device_type = "memory";
+		reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
+	};
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 9cffad3..280a64a 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -75,6 +75,12 @@
 
 	secure-partitions {
 		compatible = "arm,sp";
+#ifdef OPTEE_SP_FW_CONFIG
+		op-tee {
+			uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
+			load-address = <0x6280000>;
+		};
+#else
 		cactus-primary {
 			uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
 			load-address = <0x7000000>;
@@ -84,5 +90,24 @@
 			uuid = <0x092358d1 0xb94723f0 0x64447c82 0xc88f57f5>;
 			load-address = <0x7100000>;
 		};
+#endif
 	};
+
+#if COT_DESC_IN_DTB
+	#include "cot_descriptors.dtsi"
+#endif
+
 };
+
+#if COT_DESC_IN_DTB
+
+#include "../fvp_def.h"
+
+&trusted_nv_counter {
+	reg = <TFW_NVCTR_BASE>;
+};
+
+&non_trusted_nv_counter {
+	reg = <NTFW_CTR_BASE>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
index 7ab980b..7bed6cb 100644
--- a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,5 +7,7 @@
 /dts-v1/;
 
 / {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
 };
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index d13cc81..0e77c4d 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -70,6 +70,14 @@
 
 #if MEASURED_BOOT
 /*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+	arm_bl1_set_bl2_hash(image_desc);
+}
+
+/*
  * Implementation for bl1_plat_handle_post_image_load(). This function
  * populates the default arguments to BL2. The BL2 memory layout structure
  * is allocated and the calculated layout is populated in arg1 to BL2.
@@ -90,7 +98,7 @@
 	assert(image_desc != NULL);
 
 	/* Calculate BL2 hash and set it in TB_FW_CONFIG */
-	arm_bl1_set_bl2_hash(image_desc);
+	bl1_plat_set_bl2_hash(image_desc);
 
 	/* Get the entry point info */
 	ep_info = &image_desc->ep_info;
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index d5618d9..f2f2143 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -6,8 +6,12 @@
 
 #include <assert.h>
 
+#include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <drivers/arm/sp804_delay_timer.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 
@@ -69,3 +73,45 @@
 
 	return arm_bl_params;
 }
+#if MEASURED_BOOT
+static int fvp_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	const bl_mem_params_node_t *bl_mem_params =
+				get_bl_mem_params_node(image_id);
+
+	assert(bl_mem_params != NULL);
+
+	image_info_t info = bl_mem_params->image_info;
+	int err;
+
+	if ((info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U) {
+		/* Calculate image hash and record data in Event Log */
+		err = tpm_record_measurement(info.image_base,
+					     info.image_size, image_id);
+		if (err != 0) {
+			ERROR("%s%s image id %u (%i)\n",
+				"BL2: Failed to ", "record", image_id, err);
+			return err;
+		}
+	}
+
+	err = arm_bl2_handle_post_image_load(image_id);
+	if (err != 0) {
+		ERROR("%s%s image id %u (%i)\n",
+			"BL2: Failed to ", "handle", image_id, err);
+	}
+
+	return err;
+}
+
+int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = fvp_bl2_plat_handle_post_image_load(image_id);
+
+	if (err != 0) {
+		ERROR("%s() returns %i\n", __func__, err);
+	}
+
+	return err;
+}
+#endif	/* MEASURED_BOOT */
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index c5fae56..cb717e0 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -18,7 +18,10 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
+
+#if SPM_MM
 #include <services/spm_mm_partition.h>
+#endif
 
 #include "fvp_private.h"
 
diff --git a/plat/arm/board/fvp/fvp_measured_boot.c b/plat/arm/board/fvp/fvp_measured_boot.c
new file mode 100644
index 0000000..b145aae
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_measured_boot.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/measured_boot/event_log.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* FVP table with platform specific image IDs, names and PCRs */
+static const image_data_t fvp_images_data[] = {
+	{ BL2_IMAGE_ID, BL2_STRING, PCR_0 },		/* Reserved for BL2 */
+	{ BL31_IMAGE_ID, BL31_STRING, PCR_0 },
+	{ BL32_IMAGE_ID, BL32_STRING, PCR_0 },
+	{ BL32_EXTRA1_IMAGE_ID, BL32_EXTRA1_IMAGE_STRING, PCR_0 },
+	{ BL32_EXTRA2_IMAGE_ID, BL32_EXTRA2_IMAGE_STRING, PCR_0 },
+	{ BL33_IMAGE_ID, BL33_STRING, PCR_0 },
+	{ GPT_IMAGE_ID, GPT_IMAGE_STRING, PCR_0 },
+	{ HW_CONFIG_ID, HW_CONFIG_STRING, PCR_0 },
+	{ NT_FW_CONFIG_ID, NT_FW_CONFIG_STRING, PCR_0 },
+	{ SCP_BL2_IMAGE_ID, SCP_BL2_IMAGE_STRING, PCR_0 },
+	{ SOC_FW_CONFIG_ID, SOC_FW_CONFIG_STRING, PCR_0 },
+	{ STM32_IMAGE_ID, STM32_IMAGE_STRING, PCR_0 },
+	{ TOS_FW_CONFIG_ID, TOS_FW_CONFIG_STRING, PCR_0 },
+	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+};
+
+static const measured_boot_data_t fvp_measured_boot_data = {
+	fvp_images_data,
+	arm_set_nt_fw_info,
+	arm_set_tos_fw_info
+};
+
+/*
+ * Function retuns pointer to FVP plat_measured_boot_data_t structure
+ */
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+	return &fvp_measured_boot_data;
+}
diff --git a/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
new file mode 100644
index 0000000..0824c35
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_NT_CONFIG_GETTER_H
+#define FCONF_NT_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* NT Firmware Config related getter */
+#define nt_config__event_log_config_getter(prop) event_log.prop
+
+struct event_log_config_t {
+#ifdef SPD_opteed
+	void *tpm_event_log_sm_addr;
+#endif
+	void *tpm_event_log_addr;
+	size_t tpm_event_log_size;
+};
+
+int fconf_populate_event_log_config(uintptr_t config);
+
+extern struct event_log_config_t event_log_config;
+
+#endif /* FCONF_NT_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 7222c55..a986017 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -120,7 +120,7 @@
 #if TRUSTED_BOARD_BOOT
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #else
-# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x12000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
 #if RESET_TO_BL31
@@ -243,8 +243,8 @@
 
 /*
  * GIC related constants to cater for both GICv2 and GICv3 instances of an
- * FVP. They could be overriden at runtime in case the FVP implements the legacy
- * VE memory map.
+ * FVP. They could be overridden at runtime in case the FVP implements the
+ * legacy VE memory map.
  */
 #define PLAT_ARM_GICD_BASE		BASE_GICD_BASE
 #define PLAT_ARM_GICR_BASE		BASE_GICR_BASE
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c3b49bb..f75f556 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -72,13 +72,10 @@
 GIC_ENABLE_V4_EXTN	:=	0
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
 
-# No support for extended PPI and SPI range
-GIC_EXT_INTID		:=	0
-$(eval $(call add_define,GIC_EXT_INTID))
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
 
-FVP_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+FVP_GIC_SOURCES		:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
@@ -256,8 +253,13 @@
 endif
 
 ifeq (${SPD},spmd)
-FDT_SOURCES		+=	plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
-FVP_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb
+
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS	:=	plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
+FVP_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
 
 # Add the TOS_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
@@ -357,6 +359,11 @@
 ifeq (${TRUSTED_BOARD_BOOT}, 1)
 BL1_SOURCES		+=	plat/arm/board/fvp/fvp_trusted_boot.c
 BL2_SOURCES		+=	plat/arm/board/fvp/fvp_trusted_boot.c
+
+ifeq (${MEASURED_BOOT},1)
+BL2_SOURCES		+=	plat/arm/board/fvp/fvp_measured_boot.c
+endif
+
 # FVP being a development platform, enable capability to disable Authentication
 # dynamically if TRUSTED_BOARD_BOOT is set.
 DYN_DISABLE_AUTH	:=	1
diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h
index 3591b4d..3f2fcee 100644
--- a/plat/arm/board/fvp_ve/include/platform_def.h
+++ b/plat/arm/board/fvp_ve/include/platform_def.h
@@ -121,10 +121,19 @@
 #endif
 
 /*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -173,7 +182,14 @@
  * and limit. Leave enough space of BL2 meminfo.
  */
 #define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_LIMIT		((ARM_BL_RAM_BASE + PAGE_SIZE) \
+					+ (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
 /*******************************************************************************
  * BL1 specific defines.
@@ -205,6 +221,8 @@
 
 /* Put BL32 below BL2 in NS DRAM.*/
 #define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 #define BL32_BASE			((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
 						- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 62981c5..f8e38ff 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -11,10 +11,11 @@
 BL2_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
 endif
 
-FVP_VE_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
-				plat/common/plat_gicv2.c		\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+FVP_VE_GIC_SOURCES	:=	${GICV2_SOURCES}		\
+				plat/common/plat_gicv2.c	\
 				plat/arm/common/arm_gicv2.c
 
 FVP_VE_SECURITY_SOURCES	:=	plat/arm/board/fvp_ve/fvp_ve_security.c
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 20ed2c7..393a648 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -29,6 +29,8 @@
 fdt     fdt_get_alias_namelen
 fdt     fdt_path_offset
 fdt     fdt_path_offset_namelen
+fdt     fdt_address_cells
+fdt     fdt_size_cells
 fdt     fdt_get_name
 fdt     fdt_get_alias
 fdt     fdt_node_offset_by_phandle
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 8ca7f61..196d3c0 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -4,9 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-JUNO_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+JUNO_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 0bd3a21..4b621e3 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -38,6 +38,8 @@
 				${N1SDP_BASE}/n1sdp_security.c		\
 				drivers/arm/css/sds/sds.c
 
+FDT_SOURCES		+=	fdts/${PLAT}-single-chip.dts	\
+				fdts/${PLAT}-multi-chip.dts
 
 # TF-A not required to load the SCP Images
 override CSS_LOAD_SCP_IMAGES	  	:=	0
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index bdf20ca..81632a5 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -32,6 +32,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+BL2_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
 FDT_SOURCES		+=	${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts	\
 				${RDDANIEL_BASE}/fdts/${PLAT}_tb_fw_config.dts
diff --git a/plat/arm/board/rddaniel/rddaniel_trusted_boot.c b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rddanielxlr/platform.mk
index 1482c81..93967ad 100644
--- a/plat/arm/board/rddanielxlr/platform.mk
+++ b/plat/arm/board/rddanielxlr/platform.mk
@@ -32,6 +32,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+BL2_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+endif
+
 # Enable dynamic addition of MMAP regions in BL31
 BL31_CFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC
 
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc0/tc0_plat.c
index b1ec39b..0546192 100644
--- a/plat/arm/board/tc0/tc0_plat.c
+++ b/plat/arm/board/tc0/tc0_plat.c
@@ -15,7 +15,10 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <drivers/arm/sbsa.h>
+
+#if SPM_MM
 #include <services/spm_mm_partition.h>
+#endif
 
 /*
  * Table of regions for different BL stages to map using the MMU.
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 6b630b9..4b2a062 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -54,6 +54,9 @@
 /* Data structure which holds the extents of the trusted SRAM for BL1*/
 static meminfo_t bl1_tzram_layout;
 
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
 struct meminfo *bl1_plat_sec_mem_layout(void)
 {
 	return &bl1_tzram_layout;
@@ -152,15 +155,15 @@
 	plat_arm_io_setup();
 
 	/* Check if we need FWU before further processing */
-	err = plat_arm_bl1_fwu_needed();
-	if (err) {
+	is_fwu_needed = plat_arm_bl1_fwu_needed();
+	if (is_fwu_needed) {
 		ERROR("Skip platform setup as FWU detected\n");
 		return;
 	}
 
 	/* Set global DTB info for fixed fw_config information */
 	fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
-	set_fw_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size);
+	set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID);
 
 	/* Fill the device tree information struct with the info from the config dtb */
 	err = fconf_load_config(FW_CONFIG_ID);
@@ -247,5 +250,5 @@
  ******************************************************************************/
 unsigned int bl1_plat_get_next_image_id(void)
 {
-	return plat_arm_bl1_fwu_needed() ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
+	return  is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
 }
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index fd60c2b..60d8f6e 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -26,6 +26,9 @@
 /* Data structure which holds the extents of the trusted SRAM for BL2 */
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
+/* Base address of fw_config received from BL1 */
+static uintptr_t fw_config_base;
+
 /*
  * Check that BL2_BASE is above ARM_FW_CONFIG_LIMIT. This reserved page is
  * for `meminfo_t` data structure and fw_configs passed from BL1.
@@ -37,6 +40,9 @@
 #pragma weak bl2_platform_setup
 #pragma weak bl2_plat_arch_setup
 #pragma weak bl2_plat_sec_mem_layout
+#if MEASURED_BOOT
+#pragma weak bl2_plat_get_hash
+#endif
 
 #define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
 					bl2_tzram_layout.total_base,	\
@@ -54,21 +60,13 @@
 void arm_bl2_early_platform_setup(uintptr_t fw_config,
 				  struct meminfo *mem_layout)
 {
-	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
 	/* Initialize the console to provide early debug support */
 	arm_console_boot_init();
 
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
 
-	/* Fill the properties struct with the info from the config dtb */
-	fconf_populate("FW_CONFIG", fw_config);
-
-	/* TB_FW_CONFIG was also loaded by BL1 */
-	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
-	assert(tb_fw_config_info != NULL);
-
-	fconf_populate("TB_FW", tb_fw_config_info->config_addr);
+	fw_config_base = fw_config;
 
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
@@ -132,6 +130,7 @@
 #if ARM_CRYPTOCELL_INTEG
 		ARM_MAP_BL_COHERENT_RAM,
 #endif
+		ARM_MAP_BL_CONFIG_REGION,
 		{0}
 	};
 
@@ -148,7 +147,18 @@
 
 void bl2_plat_arch_setup(void)
 {
+	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+
 	arm_bl2_plat_arch_setup();
+
+	/* Fill the properties struct with the info from the config dtb */
+	fconf_populate("FW_CONFIG", fw_config_base);
+
+	/* TB_FW_CONFIG was also loaded by BL1 */
+	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+	assert(tb_fw_config_info != NULL);
+
+	fconf_populate("TB_FW", tb_fw_config_info->config_addr);
 }
 
 int arm_bl2_handle_post_image_load(unsigned int image_id)
@@ -225,3 +235,11 @@
 {
 	return arm_bl2_plat_handle_post_image_load(image_id);
 }
+
+#if MEASURED_BOOT
+/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
+void bl2_plat_get_hash(void *data)
+{
+	arm_bl2_get_hash(data);
+}
+#endif
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index ded8f89..58ccf0e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -114,6 +114,18 @@
 	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
 	bl32_image_ep_info.pc = BL32_BASE;
 	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+
+#if defined(SPD_spmd)
+	/* SPM (hafnium in secure world) expects SPM Core manifest base address
+	 * in x0, which in !RESET_TO_BL31 case loaded after base of non shared
+	 * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non
+	 * shared SRAM is allocated to BL31, so to avoid overwriting of manifest
+	 * keep it in the last page.
+	 */
+	bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE +
+				PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE;
+#endif
+
 # endif /* BL32_BASE */
 
 	/* Populate entry point information for BL33 */
@@ -130,6 +142,14 @@
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
+#if defined(SPD_spmd) && !(ARM_LINUX_KERNEL_AS_BL33)
+	/*
+	 * Hafnium in normal world expects its manifest address in x0, which
+	 * is loaded at base of DRAM.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE;
+#endif
+
 # if ARM_LINUX_KERNEL_AS_BL33
 	/*
 	 * According to the file ``Documentation/arm64/booting.txt`` of the
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 60c777e..e2b99a3 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -13,7 +13,9 @@
 #include <common/debug.h>
 #include <common/romlib.h>
 #include <lib/mmio.h>
+#include <lib/smccc.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
@@ -235,6 +237,23 @@
 }
 #endif
 
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ *                                     feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
+ * otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+	switch (fid) {
+	case SMCCC_ARCH_SOC_ID:
+	default:
+		return SMC_ARCH_CALL_NOT_SUPPORTED;
+	}
+}
+
 /*
  * Weak function to get ARM platform SOC-ID, Always return SOC-ID=0
  * ToDo: Get proper SOC-ID for every ARM platform and define this
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index a92bf25..96ab2d3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -337,3 +337,9 @@
         $(error "To reclaim init code xlat tables v2 must be used")
     endif
 endif
+
+ifeq (${MEASURED_BOOT},1)
+    MEASURED_BOOT_MK := drivers/measured_boot/measured_boot.mk
+    $(info Including ${MEASURED_BOOT_MK})
+    include ${MEASURED_BOOT_MK}
+endif
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 633445b..6b3a611 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -23,6 +23,7 @@
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/fconf/fconf_tbbr_getter.h>
+
 #include <plat/arm/common/arm_dyn_cfg_helpers.h>
 #include <plat/arm/common/plat_arm.h>
 
@@ -98,13 +99,14 @@
 	tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
 
 	if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) {
-		/* As libfdt use void *, we can't avoid this cast */
+		/* As libfdt uses void *, we can't avoid this cast */
 		void *dtb = (void *)tb_fw_cfg_dtb;
 
 		err = arm_set_dtb_mbedtls_heap_info(dtb,
 			mbedtls_heap_addr, mbedtls_heap_size);
 		if (err < 0) {
-			ERROR("BL1: unable to write shared Mbed TLS heap information to DTB\n");
+			ERROR("%swrite shared Mbed TLS heap information%s",
+				"BL1: unable to ", " to DTB\n");
 			panic();
 		}
 #if !MEASURED_BOOT
@@ -124,13 +126,13 @@
 
 #if MEASURED_BOOT
 /*
- * Puts the BL2 hash data to TB_FW_CONFIG DTB.
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
  * Executed only from BL1.
  */
-void arm_bl1_set_bl2_hash(image_desc_t *image_desc)
+void arm_bl1_set_bl2_hash(const image_desc_t *image_desc)
 {
 	unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
-	image_info_t image_info = image_desc->image_info;
+	const image_info_t image_info = image_desc->image_info;
 	uintptr_t tb_fw_cfg_dtb;
 	int err;
 	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
@@ -154,13 +156,15 @@
 					(void *)image_info.image_base,
 					image_info.image_size, hash_data);
 	if (err != 0) {
-		ERROR("BL1: unable to calculate BL2 hash\n");
+		ERROR("%scalculate%s\n", "BL1: unable to ",
+						" BL2 hash");
 		panic();
 	}
 
 	err = arm_set_bl2_hash_info((void *)tb_fw_cfg_dtb, hash_data);
 	if (err < 0) {
-		ERROR("BL1: unable to write BL2 hash data to DTB\n");
+		ERROR("%swrite%sdata%s\n", "BL1: unable to ",
+					" BL2 hash ", "to DTB\n");
 		panic();
 	}
 
@@ -171,6 +175,21 @@
 	 */
 	flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize((void *)tb_fw_cfg_dtb));
 }
+
+/*
+ * Reads TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB.
+ * Executed only from BL2.
+ */
+void arm_bl2_get_hash(void *data)
+{
+	const void *bl2_hash;
+
+	assert(data != NULL);
+
+	/* Retrieve TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB */
+	bl2_hash = FCONF_GET_PROPERTY(tbbr, dyn_config, bl2_hash_data);
+	(void)memcpy(data, bl2_hash, TCG_DIGEST_SIZE);
+}
 #endif /* MEASURED_BOOT */
 #endif /* TRUSTED_BOARD_BOOT */
 
@@ -184,7 +203,7 @@
 	unsigned int i;
 	bl_mem_params_node_t *cfg_mem_params = NULL;
 	uintptr_t image_base;
-	size_t image_size;
+	uint32_t image_size;
 	const unsigned int config_ids[] = {
 			HW_CONFIG_ID,
 			SOC_FW_CONFIG_ID,
@@ -202,14 +221,15 @@
 		/* Get the config load address and size from TB_FW_CONFIG */
 		cfg_mem_params = get_bl_mem_params_node(config_ids[i]);
 		if (cfg_mem_params == NULL) {
-			VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n");
+			VERBOSE("%sHW_CONFIG in bl_mem_params_node\n",
+				"Couldn't find ");
 			continue;
 		}
 
 		dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]);
 		if (dtb_info == NULL) {
-			VERBOSE("Couldn't find config_id %d load info in TB_FW_CONFIG\n",
-					config_ids[i]);
+			VERBOSE("%sconfig_id %d load info in TB_FW_CONFIG\n",
+				"Couldn't find ", config_ids[i]);
 			continue;
 		}
 
@@ -223,30 +243,32 @@
 		 */
 		if (config_ids[i] != HW_CONFIG_ID) {
 
-			if (check_uptr_overflow(image_base, image_size))
+			if (check_uptr_overflow(image_base, image_size)) {
 				continue;
-
+			}
 #ifdef	BL31_BASE
 			/* Ensure the configs don't overlap with BL31 */
 			if ((image_base >= BL31_BASE) &&
-			    (image_base <= BL31_LIMIT))
+			    (image_base <= BL31_LIMIT)) {
 				continue;
+			}
 #endif
 			/* Ensure the configs are loaded in a valid address */
-			if (image_base < ARM_BL_RAM_BASE)
+			if (image_base < ARM_BL_RAM_BASE) {
 				continue;
+			}
 #ifdef BL32_BASE
 			/*
 			 * If BL32 is present, ensure that the configs don't
 			 * overlap with it.
 			 */
 			if ((image_base >= BL32_BASE) &&
-			    (image_base <= BL32_LIMIT))
+			    (image_base <= BL32_LIMIT)) {
 				continue;
+			}
 #endif
 		}
 
-
 		cfg_mem_params->image_info.image_base = image_base;
 		cfg_mem_params->image_info.image_max_size = (uint32_t)image_size;
 
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index f110e3b..5f20c8d 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -6,9 +6,13 @@
 
 #include <assert.h>
 
+#if MEASURED_BOOT
+#include <common/desc_image_load.h>
+#endif
+#include <common/fdt_wrappers.h>
+
 #include <libfdt.h>
 
-#include <common/fdt_wrappers.h>
 #include <plat/arm/common/arm_dyn_cfg_helpers.h>
 #include <plat/arm/common/plat_arm.h>
 
@@ -17,6 +21,15 @@
 
 #if MEASURED_BOOT
 #define DTB_PROP_BL2_HASH_DATA	"bl2_hash_data"
+#ifdef SPD_opteed
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this property should be removed when this feature is supported.
+ */
+#define DTB_PROP_HW_SM_LOG_ADDR	"tpm_event_log_sm_addr"
+#endif
+#define DTB_PROP_HW_LOG_ADDR	"tpm_event_log_addr"
+#define DTB_PROP_HW_LOG_SIZE    "tpm_event_log_size"
 
 static int dtb_root = -1;
 #endif /* MEASURED_BOOT */
@@ -37,18 +50,19 @@
 
 	/* Check if the pointer to DT is correct */
 	if (fdt_check_header(dtb) != 0) {
-		WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
+		WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG");
 		return -1;
 	}
 
 	/* Assert the node offset point to "arm,tb_fw" compatible property */
 	*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
 	if (*node < 0) {
-		WARN("The compatible property `arm,tb_fw` not found in the config\n");
+		WARN("The compatible property '%s' not%s", "arm,tb_fw",
+			" found in the config\n");
 		return -1;
 	}
 
-	VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
+	VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n");
 	return 0;
 }
 
@@ -76,7 +90,8 @@
 	 */
 	int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
 	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG loaded. Unable to get root node\n");
+		ERROR("Invalid%s loaded. Unable to get root node\n",
+			" TB_FW_CONFIG");
 		return -1;
 	}
 
@@ -90,16 +105,16 @@
 	err = fdtw_write_inplace_cells(dtb, dtb_root,
 		DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
 	if (err < 0) {
-		ERROR("Unable to write DTB property %s\n",
-			DTB_PROP_MBEDTLS_HEAP_ADDR);
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR);
 		return -1;
 	}
 
 	err = fdtw_write_inplace_cells(dtb, dtb_root,
 		DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
 	if (err < 0) {
-		ERROR("Unable to write DTB property %s\n",
-			DTB_PROP_MBEDTLS_HEAP_SIZE);
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE);
 		return -1;
 	}
 
@@ -124,7 +139,165 @@
 	/*
 	 * Write the BL2 hash data in the DTB.
 	 */
-	return fdtw_write_inplace_bytes(dtb, dtb_root, DTB_PROP_BL2_HASH_DATA,
+	return fdtw_write_inplace_bytes(dtb, dtb_root,
+					DTB_PROP_BL2_HASH_DATA,
 					TCG_DIGEST_SIZE, data);
 }
+
+/*
+ * Write the Event Log address and its size in the DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ *	0 = success
+ *    < 0 = error
+ */
+static int arm_set_event_log_info(uintptr_t config_base,
+#ifdef SPD_opteed
+				  uintptr_t sm_log_addr,
+#endif
+				  uintptr_t log_addr, size_t log_size)
+{
+	/* As libfdt uses void *, we can't avoid this cast */
+	void *dtb = (void *)config_base;
+	const char *compatible = "arm,tpm_event_log";
+	int err, node;
+
+	/*
+	 * Verify that the DTB is valid, before attempting to write to it,
+	 * and get the DTB root node.
+	 */
+
+	/* Check if the pointer to DT is correct */
+	err = fdt_check_header(dtb);
+	if (err < 0) {
+		WARN("Invalid DTB file passed\n");
+		return err;
+	}
+
+	/* Assert the node offset point to compatible property */
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible);
+	if (node < 0) {
+		WARN("The compatible property '%s' not%s", compatible,
+			" found in the config\n");
+		return node;
+	}
+
+	VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
+
+#ifdef SPD_opteed
+	if (sm_log_addr != 0UL) {
+		err = fdtw_write_inplace_cells(dtb, node,
+			DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr);
+		if (err < 0) {
+			ERROR("%sDTB property '%s'\n",
+				"Unable to write ", DTB_PROP_HW_SM_LOG_ADDR);
+			return err;
+		}
+	}
+#endif
+	err = fdtw_write_inplace_cells(dtb, node,
+		DTB_PROP_HW_LOG_ADDR, 2, &log_addr);
+	if (err < 0) {
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_HW_LOG_ADDR);
+		return err;
+	}
+
+	err = fdtw_write_inplace_cells(dtb, node,
+		DTB_PROP_HW_LOG_SIZE, 1, &log_size);
+	if (err < 0) {
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_HW_LOG_SIZE);
+	} else {
+		/*
+		 * Ensure that the info written to the DTB is visible
+		 * to other images.
+		 */
+		flush_dcache_range(config_base, fdt_totalsize(dtb));
+	}
+
+	return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TOS_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ *	0 = success
+ *    < 0 = error
+ */
+int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+			size_t log_size)
+{
+	int err;
+
+	assert(config_base != 0UL);
+	assert(log_addr != 0UL);
+
+	/* Write the Event Log address and its size in the DTB */
+	err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+					0UL,
+#endif
+					log_addr, log_size);
+	if (err < 0) {
+		ERROR("%sEvent Log data to TOS_FW_CONFIG\n",
+					"Unable to write ");
+	}
+
+	return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the NT_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ *	0 = success
+ *    < 0 = error
+ */
+int arm_set_nt_fw_info(uintptr_t config_base,
+#ifdef SPD_opteed
+			uintptr_t log_addr,
+#endif
+			size_t log_size, uintptr_t *ns_log_addr)
+{
+	uintptr_t ns_addr;
+	const bl_mem_params_node_t *cfg_mem_params;
+	int err;
+
+	assert(config_base != 0UL);
+	assert(ns_log_addr != NULL);
+
+	/* Get the config load address and size from NT_FW_CONFIG */
+	cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+	assert(cfg_mem_params != NULL);
+
+	/* Calculate Event Log address in Non-secure memory */
+	ns_addr = cfg_mem_params->image_info.image_base +
+			cfg_mem_params->image_info.image_max_size;
+
+	/* Check for memory space */
+	if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) {
+		return -1;
+	}
+
+	/* Write the Event Log address and its size in the DTB */
+	err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+					log_addr,
+#endif
+					ns_addr, log_size);
+
+	/* Return Event Log address in Non-secure memory */
+	*ns_log_addr = (err < 0) ? 0UL : ns_addr;
+	return err;
+}
 #endif /* MEASURED_BOOT */
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 48cc4fe..350ecd1 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -51,7 +51,7 @@
 	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {UUID_TRUSTED_OS_FW_CONTENT_CERT},
 	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {UUID_NON_TRUSTED_FW_CONTENT_CERT},
 #if defined(SPD_spmd)
-	[SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
+	[SIP_SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
 #endif
 #endif /* ARM_IO_IN_DTB */
 #endif /* TRUSTED_BOARD_BOOT */
@@ -184,9 +184,9 @@
 		open_fip
 	},
 #if defined(SPD_spmd)
-	[SP_CONTENT_CERT_ID] = {
+	[SIP_SP_CONTENT_CERT_ID] = {
 		&fip_dev_handle,
-		(uintptr_t)&arm_uuid_spec[SP_CONTENT_CERT_ID],
+		(uintptr_t)&arm_uuid_spec[SIP_SP_CONTENT_CERT_ID],
 		open_fip
 	},
 #endif
@@ -233,7 +233,7 @@
 	{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
 	{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
 #if defined(SPD_spmd)
-	{SP_CONTENT_CERT_ID, "sp_content_cert_uuid"},
+	{SIP_SP_CONTENT_CERT_ID, "sip_sp_content_cert_uuid"},
 #endif
 #endif /* TRUSTED_BOARD_BOOT */
 };
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
index 64e873e..4459264 100644
--- a/plat/arm/common/fconf/arm_fconf_sp.c
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -30,7 +30,7 @@
 	union uuid_helper_t uuid_helper;
 	unsigned int index = 0;
 	uint32_t val32;
-	const unsigned int sp_start_index = SP_CONTENT_CERT_ID + 1;
+	const unsigned int sp_start_index = SP_PKG1_ID;
 
 	/* As libfdt use void *, we can't avoid this cast */
 	const void *dtb = (void *)config;
@@ -45,6 +45,11 @@
 	}
 
 	fdt_for_each_subnode(sp_node, dtb, node) {
+		if (index == MAX_SP_IDS) {
+			ERROR("FCONF: Reached max number of SPs\n");
+			return -1;
+		}
+
 		err = fdt_read_uint32_array(dtb, sp_node, "uuid", 4,
 					    uuid_helper.word);
 		if (err < 0) {
@@ -87,15 +92,10 @@
 		policies[sp_start_index + index].check = open_fip;
 
 		index++;
-
-		if (index >= MAX_SP_IDS) {
-			ERROR("FCONF: reached max number of SPs\n");
-			return -1;
-		}
 	}
 
 	if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
-		ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
+		ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node);
 		return sp_node;
 	}
 
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index b611eaf..a2117f6 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,7 +15,10 @@
 #include <plat/common/platform.h>
 #include <drivers/arm/sbsa.h>
 #include <sgi_base_platform_def.h>
+
+#if SPM_MM
 #include <services/spm_mm_partition.h>
+#endif
 
 #define SGI_MAP_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
 						V2M_FLASH0_SIZE,	\
diff --git a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
index e416540..54b2423 100644
--- a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
+++ b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
@@ -8,7 +8,7 @@
 
 / {
 	/* Platform Config */
-	plat_arm_bl2 {
+	tb_fw-config {
 		compatible = "arm,tb_fw";
 		hw_config_addr = <0x0 0x83000000>;
 		hw_config_max_size = <0x01000000>;
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index 808a107..3069f91 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -133,6 +133,12 @@
 				plat/brcm/board/common/sbl_util.c \
 				drivers/arm/sp805/sp805.c
 
+# Add RNG driver
+DRIVER_RNG_ENABLE := 1
+ifeq (${DRIVER_RNG_ENABLE},1)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/rng.c
+endif
+
 # Add eMMC driver
 ifeq (${DRIVER_EMMC_ENABLE},1)
 $(eval $(call add_define,DRIVER_EMMC_ENABLE))
diff --git a/plat/brcm/board/stingray/include/sr_def.h b/plat/brcm/board/stingray/include/sr_def.h
index ac3ee78..be0dee1 100644
--- a/plat/brcm/board/stingray/include/sr_def.h
+++ b/plat/brcm/board/stingray/include/sr_def.h
@@ -292,6 +292,11 @@
 #define ICFG_PKA_MEM_PWR_CTRL__ISO		BIT(8)
 
 /*******************************************************************************
+ * RNG constants
+ ******************************************************************************/
+#define RNG_BASE_ADDR			0x68b20000
+
+/*******************************************************************************
  * Trusted Watchdog constants
  ******************************************************************************/
 #define ARM_SP805_TWDG_BASE		0x68b30000
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index 5733781..2baa29a 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,7 +27,9 @@
 #pragma weak bl1_plat_fwu_done
 #pragma weak bl1_plat_handle_pre_image_load
 #pragma weak bl1_plat_handle_post_image_load
-
+#if MEASURED_BOOT
+#pragma weak bl1_plat_set_bl2_hash
+#endif
 
 unsigned int bl1_plat_get_next_image_id(void)
 {
@@ -116,3 +118,12 @@
 		(void *) bl2_tzram_layout);
 	return 0;
 }
+
+#if MEASURED_BOOT
+/*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+}
+#endif
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index d38fc6f..89b77ba 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -11,6 +11,7 @@
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
 #include <tools_share/firmware_encrypted.h>
 
@@ -25,6 +26,7 @@
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
 #pragma weak plat_get_enc_key_info
+#pragma weak plat_is_smccc_feature_available
 #pragma weak plat_get_soc_version
 #pragma weak plat_get_soc_revision
 
@@ -38,6 +40,11 @@
 	return SMC_ARCH_CALL_NOT_SUPPORTED;
 }
 
+int32_t plat_is_smccc_feature_available(u_register_t fid __unused)
+{
+	return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
 void bl2_el3_plat_prepare_exit(void)
 {
 }
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index 455b980..e65980b 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -128,7 +128,13 @@
 	 */
 	pm_base = (uintptr_t)pm_addr;
 	pm_base_align = page_align(pm_base, UP);
-	mapped_size = pm_base_align - pm_base;
+
+	if (pm_base == pm_base_align) {
+		/* Page aligned */
+		mapped_size = PAGE_SIZE;
+	} else {
+		mapped_size = pm_base_align - pm_base;
+	}
 
 	/* Check space within the page at least maps the FDT header */
 	if (mapped_size < sizeof(struct fdt_header)) {
diff --git a/plat/imx/common/imx_sip_handler.c b/plat/imx/common/imx_sip_handler.c
index 62048b6..f9f5577 100644
--- a/plat/imx/common/imx_sip_handler.c
+++ b/plat/imx/common/imx_sip_handler.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <services/std_svc.h>
@@ -12,6 +13,7 @@
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <imx_sip_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
 #include <sci/sci.h>
 
 #if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
@@ -185,3 +187,37 @@
 
 	return ret;
 }
+
+int imx_kernel_entry_handler(uint32_t smc_fid,
+		u_register_t x1,
+		u_register_t x2,
+		u_register_t x3,
+		u_register_t x4)
+{
+	static entry_point_info_t bl33_image_ep_info;
+	entry_point_info_t *next_image_info;
+	unsigned int mode;
+
+	if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000))
+		return SMC_UNK;
+
+	mode = MODE32_svc;
+
+	next_image_info = &bl33_image_ep_info;
+
+	next_image_info->pc = x1;
+
+	next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+			(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+
+	next_image_info->args.arg0 = 0;
+	next_image_info->args.arg1 = 0;
+	next_image_info->args.arg2 = x3;
+
+	SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+	cm_init_my_context(next_image_info);
+	cm_prepare_el3_exit(NON_SECURE);
+
+	return 0;
+}
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 4893b9f..20e1479 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -26,6 +26,9 @@
 			u_register_t flags)
 {
 	switch (smc_fid) {
+	case IMX_SIP_AARCH32:
+		SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4));
+		break;
 #if defined(PLAT_imx8mq)
 	case IMX_SIP_GET_SOC_INFO:
 		SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 5898f7a..0a2d750 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -28,6 +28,11 @@
 
 #define IMX_SIP_MISC_SET_TEMP		0xC200000C
 
+#define IMX_SIP_AARCH32			0xC20000FD
+
+int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1,
+			     u_register_t x2, u_register_t x3,
+			     u_register_t x4);
 #if defined(PLAT_imx8mq)
 int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
 			 u_register_t x2, u_register_t x3);
diff --git a/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
new file mode 100644
index 0000000..c697af2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define MIPI_PWR_REQ			BIT(0)
+#define PCIE_PWR_REQ			BIT(1)
+#define OTG1_PWR_REQ			BIT(2)
+#define OTG2_PWR_REQ			BIT(3)
+#define HSIOMIX_PWR_REQ			BIT(4)
+#define DDRMIX_PWR_REQ			BIT(5)
+#define GPU2D_PWR_REQ			BIT(6)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define VPUMIX_PWR_REQ			BIT(8)
+#define GPU3D_PWR_REQ			BIT(9)
+#define DISPMIX_PWR_REQ			BIT(10)
+#define VPU_G1_PWR_REQ			BIT(11)
+#define VPU_G2_PWR_REQ			BIT(12)
+#define VPU_H1_PWR_REQ			BIT(13)
+
+#define DDRMIX_ADB400_SYNC		BIT(2)
+#define HSIOMIX_ADB400_SYNC		(0x3 << 5)
+#define DISPMIX_ADB400_SYNC		BIT(7)
+#define VPUMIX_ADB400_SYNC		BIT(8)
+#define GPU3D_ADB400_SYNC		BIT(9)
+#define GPU2D_ADB400_SYNC		BIT(10)
+#define GPUMIX_ADB400_SYNC		BIT(11)
+#define DDRMIX_ADB400_ACK		BIT(20)
+#define HSIOMIX_ADB400_ACK		(0x3 << 23)
+#define DISPMIX_ADB400_ACK		BIT(25)
+#define VPUMIX_ADB400_ACK		BIT(26)
+#define GPU3D_ADB400_ACK		BIT(27)
+#define GPU2D_ADB400_ACK		BIT(28)
+#define GPUMIX_ADB400_ACK		BIT(29)
+
+#define MIPI_PGC			0xc00
+#define PCIE_PGC			0xc40
+#define OTG1_PGC			0xc80
+#define OTG2_PGC			0xcc0
+#define HSIOMIX_PGC			0xd00
+#define DDRMIX_PGC			0xd40
+#define GPU2D_PGC			0xd80
+#define GPUMIX_PGC			0xdc0
+#define VPUMIX_PGC			0xe00
+#define GPU3D_PGC			0xe40
+#define DISPMIX_PGC			0xe80
+#define VPU_G1_PGC			0xec0
+#define VPU_G2_PGC			0xf00
+#define VPU_H1_PGC			0xf40
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
new file mode 100644
index 0000000..fd10438
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define TMR_TCD2_SHIFT			0
+#define TMC_TMR_SHIFT			10
+#define TRC1_TMC_SHIFT			20
+
+#define MIPI_PWR_REQ			BIT(0)
+#define OTG1_PWR_REQ			BIT(2)
+#define HSIOMIX_PWR_REQ			BIT(4)
+#define DDRMIX_PWR_REQ			BIT(5)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define DISPMIX_PWR_REQ			BIT(10)
+
+#define DDRMIX_ADB400_SYNC		BIT(2)
+#define HSIOMIX_ADB400_SYNC		BIT(5)
+#define DISPMIX_ADB400_SYNC		BIT(7)
+#define GPUMIX_ADB400_SYNC		(0x5 << 9)
+#define DDRMIX_ADB400_ACK		BIT(20)
+#define HSIOMIX_ADB400_ACK		BIT(23)
+#define DISPMIX_ADB400_ACK		BIT(25)
+#define GPUMIX_ADB400_ACK		(0x5 << 27)
+
+#define MIPI_PGC			0xc00
+#define OTG1_PGC			0xc80
+#define HSIOMIX_PGC			0xd00
+#define DDRMIX_PGC			0xd40
+#define GPUMIX_PGC			0xdc0
+#define DISPMIX_PGC			0xe80
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
new file mode 100644
index 0000000..d660e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x)		(0x4000 + (x) * 0x10)
+#define IMR_NUM		U(5)
+
+struct imx_noc_setting {
+	uint32_t domain_id;
+	uint32_t start;
+	uint32_t end;
+	uint32_t prioriy;
+	uint32_t mode;
+	uint32_t socket_qos_en;
+};
+
+enum clk_type {
+	CCM_ROOT_SLICE,
+	CCM_CCGR,
+};
+
+struct clk_setting {
+	uint32_t offset;
+	uint32_t val;
+	enum clk_type type;
+};
+
+enum pu_domain_id {
+	/* hsio ss */
+	HSIOMIX,
+	PCIE_PHY,
+	USB1_PHY,
+	USB2_PHY,
+	MLMIX,
+	AUDIOMIX,
+	/* gpu ss */
+	GPUMIX,
+	GPU2D,
+	GPU3D,
+	/* vpu ss */
+	VPUMIX,
+	VPU_G1,
+	VPU_G2,
+	VPU_H1,
+	/* media ss */
+	MEDIAMIX,
+	MEDIAMIX_ISPDWP,
+	MIPI_PHY1,
+	MIPI_PHY2,
+	/* HDMI ss */
+	HDMIMIX,
+	HDMI_PHY,
+	DDRMIX,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[20] = {
+	[MIPI_PHY1] = IMX_PD_DOMAIN(MIPI_PHY1, false),
+	[PCIE_PHY] = IMX_PD_DOMAIN(PCIE_PHY, false),
+	[USB1_PHY] = IMX_PD_DOMAIN(USB1_PHY, true),
+	[USB2_PHY] = IMX_PD_DOMAIN(USB2_PHY, true),
+	[MLMIX] = IMX_MIX_DOMAIN(MLMIX, false),
+	[AUDIOMIX] = IMX_MIX_DOMAIN(AUDIOMIX, false),
+	[GPU2D] = IMX_PD_DOMAIN(GPU2D, false),
+	[GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+	[VPUMIX] = IMX_MIX_DOMAIN(VPUMIX, false),
+	[GPU3D] = IMX_PD_DOMAIN(GPU3D, false),
+	[MEDIAMIX] = IMX_MIX_DOMAIN(MEDIAMIX, false),
+	[VPU_G1] = IMX_PD_DOMAIN(VPU_G1, false),
+	[VPU_G2] = IMX_PD_DOMAIN(VPU_G2, false),
+	[VPU_H1] = IMX_PD_DOMAIN(VPU_H1, false),
+	[HDMIMIX] = IMX_MIX_DOMAIN(HDMIMIX, false),
+	[HDMI_PHY] = IMX_PD_DOMAIN(HDMI_PHY, false),
+	[MIPI_PHY2] = IMX_PD_DOMAIN(MIPI_PHY2, false),
+	[HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+	[MEDIAMIX_ISPDWP] = IMX_PD_DOMAIN(MEDIAMIX_ISPDWP, false),
+};
+
+static struct imx_noc_setting noc_setting[] = {
+	{MLMIX, 0x180, 0x180, 0x80000303, 0x0, 0x0},
+	{AUDIOMIX, 0x200, 0x200, 0x80000303, 0x0, 0x0},
+	{AUDIOMIX, 0x280, 0x480, 0x80000404, 0x0, 0x0},
+	{GPUMIX, 0x500, 0x580, 0x80000303, 0x0, 0x0},
+	{HDMIMIX, 0x600, 0x680, 0x80000202, 0x0, 0x1},
+	{HDMIMIX, 0x700, 0x700, 0x80000505, 0x0, 0x0},
+	{HSIOMIX, 0x780, 0x900, 0x80000303, 0x0, 0x0},
+	{MEDIAMIX, 0x980, 0xb80, 0x80000202, 0x0, 0x1},
+	{MEDIAMIX_ISPDWP, 0xc00, 0xd00, 0x80000505, 0x0, 0x0},
+	{VPU_G1, 0xd80, 0xd80, 0x80000303, 0x0, 0x0},
+	{VPU_G2, 0xe00, 0xe00, 0x80000303, 0x0, 0x0},
+	{VPU_H1, 0xe80, 0xe80, 0x80000303, 0x0, 0x0}
+};
+
+static struct clk_setting hsiomix_clk[] = {
+	{ 0x8380, 0x0, CCM_ROOT_SLICE },
+	{ 0x44d0, 0x0, CCM_CCGR },
+	{ 0x45c0, 0x0, CCM_CCGR },
+};
+
+static struct aipstz_cfg aipstz5[] = {
+	{IMX_AIPSTZ5, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static unsigned int pu_domain_status;
+
+static void imx_noc_qos(unsigned int domain_id)
+{
+	unsigned int i;
+	uint32_t hurry;
+
+	if (domain_id == HDMIMIX) {
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22018);
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22010);
+
+		/* set GPR to make lcdif read hurry level 0x7 */
+		hurry = mmio_read_32(IMX_HDMI_CTL_BASE + TX_CONTROL0);
+		hurry |= 0x00077000;
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL0, hurry);
+	}
+
+	if (domain_id == MEDIAMIX) {
+		/* handle mediamix special */
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RSTn_CSR, 0x1FFFFFF);
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + CLK_EN_CSR, 0x1FFFFFF);
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RST_DIV, 0x40030000);
+
+		/* set GPR to make lcdif read hurry level 0x7 */
+		hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL);
+		hurry |= 0xfc00;
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL, hurry);
+		/* set GPR to make isi write hurry level 0x7 */
+		hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL);
+		hurry |= 0x1ff00000;
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL, hurry);
+	}
+
+	/* set MIX NoC */
+	for (i = 0; i < ARRAY_SIZE(noc_setting); i++) {
+		if (noc_setting[i].domain_id == domain_id) {
+			udelay(50);
+			uint32_t offset = noc_setting[i].start;
+
+			while (offset <= noc_setting[i].end) {
+				mmio_write_32(IMX_NOC_BASE + offset + 0x8, noc_setting[i].prioriy);
+				mmio_write_32(IMX_NOC_BASE + offset + 0xc, noc_setting[i].mode);
+				mmio_write_32(IMX_NOC_BASE + offset + 0x18, noc_setting[i].socket_qos_en);
+				offset += 0x80;
+			}
+		}
+	}
+}
+
+static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+	unsigned int i;
+
+	if (domain_id == HSIOMIX) {
+		for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+			hsiomix_clk[i].val = mmio_read_32(IMX_CCM_BASE + hsiomix_clk[i].offset);
+			mmio_setbits_32(IMX_CCM_BASE + hsiomix_clk[i].offset,
+					hsiomix_clk[i].type == CCM_ROOT_SLICE ? BIT(28) : 0x3);
+		}
+	}
+
+	if (on) {
+		if (pwr_domain->need_sync) {
+			pu_domain_status |= (1 << domain_id);
+		}
+
+		if (domain_id == HDMIMIX) {
+			/* assert the reset */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0x0);
+			/* enable all th function clock */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+		}
+
+		/* clear the PGC bit */
+		mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+		/* power up the domain */
+		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+		/* wait for power request done */
+		while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req)
+			;
+
+		if (domain_id == HDMIMIX) {
+			/* wait for memory repair done for HDMIMIX */
+			while (!(mmio_read_32(IMX_SRC_BASE + 0x94) & BIT(8)))
+				;
+			/* disable all the function clock */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0x0);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x0);
+			/* deassert the reset */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0xffffffff);
+			/* enable all the clock again */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+		}
+
+		if (domain_id == HSIOMIX) {
+			/* enable HSIOMIX clock */
+			mmio_write_32(IMX_HSIOMIX_CTL_BASE, 0x2);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+				;
+		}
+
+		imx_noc_qos(domain_id);
+
+		/* AIPS5 config is lost when audiomix is off, so need to re-init it */
+		if (domain_id == AUDIOMIX) {
+			imx_aipstz_init(aipstz5);
+		}
+	} else {
+		if (pwr_domain->always_on) {
+			return;
+		}
+
+		if (pwr_domain->need_sync) {
+			pu_domain_status &= ~(1 << domain_id);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+				;
+		}
+
+		/* set the PGC bit */
+		mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+		/*
+		 * leave the G1, G2, H1 power domain on until VPUMIX power off,
+		 * otherwise system will hang due to VPUMIX ACK
+		 */
+		if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) {
+			return;
+		}
+
+		if (domain_id == VPUMIX) {
+			mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ |
+				 VPU_G2_PWR_REQ | VPU_H1_PWR_REQ);
+
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ |
+					VPU_G2_PWR_REQ | VPU_H1_PWR_REQ))
+				;
+		}
+
+		/* power down the domain */
+		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+		/* wait for power request done */
+		while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req)
+			;
+
+		if (domain_id == HDMIMIX) {
+			/* disable all the clocks of HDMIMIX */
+			mmio_write_32(IMX_HDMI_CTL_BASE + 0x40, 0x0);
+			mmio_write_32(IMX_HDMI_CTL_BASE + 0x50, 0x0);
+		}
+	}
+
+	if (domain_id == HSIOMIX) {
+		for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+			mmio_write_32(IMX_CCM_BASE + hsiomix_clk[i].offset, hsiomix_clk[i].val);
+		}
+	}
+}
+
+void imx_gpc_init(void)
+{
+	uint32_t val;
+	unsigned int i;
+
+	/* mask all the wakeup irq by default */
+	for (i = 0; i < IMR_NUM; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
+
+	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+	/* use GIC wake_request to wakeup C0~C3 from LPM */
+	val |= CORE_WKUP_FROM_GIC;
+	/* clear the MASTER0 LPM handshake */
+	val &= ~MASTER0_LPM_HSK;
+	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+	/* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+	mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+		MASTER2_MAPPING));
+
+	/* set all mix/PU in A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0x3fffff);
+
+	/*
+	 * Set the CORE & SCU power up timing:
+	 * SW = 0x1, SW2ISO = 0x1;
+	 * the CPU CORE and SCU power up timming counter
+	 * is drived  by 32K OSC, each domain's power up
+	 * latency is (SW + SW2ISO) / 32768
+	 */
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+		      (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+	/* set DUMMY PDN/PUP ACK by default for A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+		      A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+	/* clear DSM by default */
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~SLPCR_EN_DSM;
+	/* enable the fast wakeup wait/stop mode */
+	val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+	val |= SLPCR_A53_FASTWUP_STOP_MODE;
+	/* clear the RBC */
+	val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+	/* set the STBY_COUNT to 0x5, (128 * 30)us */
+	val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+	val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+	/*
+	 * USB PHY power up needs to make sure RESET bit in SRC is clear,
+	 * otherwise, the PU power up bit in GPC will NOT self-cleared.
+	 * only need to do it once.
+	 */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+	/* enable all the power domain by default */
+	for (i = 0; i < 101; i++) {
+		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
+	}
+
+	for (i = 0; i < 20; i++) {
+		imx_gpc_pm_domain_enable(i, true);
+	}
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
new file mode 100644
index 0000000..22fbd5e
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+static const mmap_region_t imx_mmap[] = {
+	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+	NOC_MAP, {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+	{IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+	/* Master domain assignment */
+	RDC_MDAn(0x1, DID1),
+
+	/* peripherals domain permission */
+
+	/* memory region */
+
+	/* Sentinel */
+	{0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned long mode;
+	uint32_t spsr;
+
+	/* figure out what mode we enter the non-secure world */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+	if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+		return;
+
+	tzc380_init(IMX_TZASC_BASE);
+
+	/*
+	 * Need to substact offset 0x40000000 from CPU address when
+	 * programming tzasc region for i.mx8mp.
+	 */
+
+	/* Enable 1G-5G S/NS RW */
+	tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+		TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+	unsigned int i;
+
+	/* Enable CSU NS access permission */
+	for (i = 0; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+	}
+
+	imx_aipstz_init(aipstz);
+
+	imx_rdc_init(rdc);
+
+	imx8m_caam_init();
+
+	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		IMX_CONSOLE_BAUDRATE, &console);
+	/* This console is only used for boot stage */
+	console_set_scope(&console, CONSOLE_FLAG_BOOT);
+
+	/*
+	 * tell BL3-1 where the non-secure software image is located
+	 * and the entry state information.
+	 */
+	bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+	bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef SPD_opteed
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = 0;
+
+	/* Pass TEE base and size to bl33 */
+	bl33_image_ep_info.args.arg1 = BL32_BASE;
+	bl33_image_ep_info.args.arg2 = BL32_SIZE;
+#endif
+
+	bl31_tzc380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+		MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+		MT_MEMORY | MT_RO | MT_SECURE);
+#if USE_COHERENT_MEM
+	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+		(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE),
+		MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+	mmap_add(imx_mmap);
+
+	init_xlat_tables();
+
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* select the CKIL source to 32K OSC */
+	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+	plat_gic_driver_init();
+	plat_gic_init();
+
+	imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+	if (type == NON_SECURE) {
+		return &bl33_image_ep_info;
+	}
+
+	if (type == SECURE) {
+		return &bl32_image_ep_info;
+	}
+
+	return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
new file mode 100644
index 0000000..bc7b246
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+	.pwr_domain_on = imx_pwr_domain_on,
+	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
+	.pwr_domain_off = imx_pwr_domain_off,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+	.validate_power_state = imx_validate_power_state,
+	.cpu_standby = imx_cpu_standby,
+	.pwr_domain_suspend = imx_domain_suspend,
+	.pwr_domain_suspend_finish = imx_domain_suspend_finish,
+	.pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+	.system_reset = imx_system_reset,
+	.system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	/* sec_entrypoint is used for warm reset */
+	imx_mailbox_init(sec_entrypoint);
+
+	*psci_ops = &imx_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
new file mode 100644
index 0000000..12da6ac
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x180
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x44
+#define IMR1_CORE2_A53			0x194
+#define IMR1_CORE3_A53			0x1A8
+#define IMR1_CORE0_M4			0x58
+
+#define SLT0_CFG			0x200
+#define GPC_PU_PWRHSK			0x190
+#define PGC_CPU_0_1_MAPPING		0x1CC
+#define CPU_PGC_UP_TRG			0xD0
+#define PU_PGC_UP_TRG			0xD8
+#define CPU_PGC_DN_TRG			0xDC
+#define PU_PGC_DN_TRG			0xE4
+#define LPS_CPU1			0xEC
+
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(30)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(8)
+#define A53_PLAT_PUP_ACK		BIT(9)
+
+#define NOC_PDN_SLT_CTRL		BIT(12)
+#define NOC_PUP_SLT_CTRL		BIT(13)
+#define NOC_PGC_PDN_ACK			BIT(12)
+#define NOC_PGC_PUP_ACK			BIT(13)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define TMR_TCD2_SHIFT			0
+#define TMC_TMR_SHIFT			10
+#define TRC1_TMC_SHIFT			20
+
+#define MIPI_PHY1_PWR_REQ		BIT(0)
+#define PCIE_PHY_PWR_REQ		BIT(1)
+#define USB1_PHY_PWR_REQ		BIT(2)
+#define USB2_PHY_PWR_REQ		BIT(3)
+#define MLMIX_PWR_REQ			BIT(4)
+#define AUDIOMIX_PWR_REQ		BIT(5)
+#define GPU2D_PWR_REQ			BIT(6)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define VPUMIX_PWR_REQ			BIT(8)
+#define GPU3D_PWR_REQ			BIT(9)
+#define MEDIAMIX_PWR_REQ		BIT(10)
+#define VPU_G1_PWR_REQ			BIT(11)
+#define VPU_G2_PWR_REQ			BIT(12)
+#define VPU_H1_PWR_REQ			BIT(13)
+#define HDMIMIX_PWR_REQ			BIT(14)
+#define HDMI_PHY_PWR_REQ		BIT(15)
+#define MIPI_PHY2_PWR_REQ		BIT(16)
+#define HSIOMIX_PWR_REQ			BIT(17)
+#define MEDIAMIX_ISPDWP_PWR_REQ		BIT(18)
+#define DDRMIX_PWR_REQ			BIT(19)
+
+#define AUDIOMIX_ADB400_SYNC		(BIT(4) | BIT(15))
+#define MLMIX_ADB400_SYNC		(BIT(7) | BIT(8))
+#define GPUMIX_ADB400_SYNC		BIT(9)
+#define VPUMIX_ADB400_SYNC		BIT(10)
+#define DDRMIX_ADB400_SYNC		BIT(11)
+#define HSIOMIX_ADB400_SYNC		BIT(12)
+#define HDMIMIX_ADB400_SYNC		BIT(13)
+#define MEDIAMIX_ADB400_SYNC		BIT(14)
+
+#define AUDIOMIX_ADB400_ACK		(BIT(20) | BIT(31))
+#define MLMIX_ADB400_ACK		(BIT(23) | BIT(24))
+#define GPUMIX_ADB400_ACK		BIT(25)
+#define VPUMIX_ADB400_ACK		BIT(26)
+#define DDRMIX_ADB400_ACK		BIT(27)
+#define HSIOMIX_ADB400_ACK		BIT(28)
+#define HDMIMIX_ADB400_ACK		BIT(29)
+#define MEDIAMIX_ADB400_ACK		BIT(30)
+
+#define MIPI_PHY1_PGC			0xb00
+#define PCIE_PHY_PGC			0xb40
+#define USB1_PHY_PGC			0xb80
+#define USB2_PHY_PGC			0xbc0
+#define MLMIX_PGC			0xc00
+#define AUDIOMIX_PGC			0xc40
+#define GPU2D_PGC			0xc80
+#define GPUMIX_PGC			0xcc0
+#define VPUMIX_PGC			0xd00
+#define GPU3D_PGC			0xd40
+#define MEDIAMIX_PGC			0xd80
+#define VPU_G1_PGC			0xdc0
+#define VPU_G2_PGC			0xe00
+#define VPU_H1_PGC			0xe40
+#define HDMIMIX_PGC			0xe80
+#define HDMI_PHY_PGC			0xec0
+#define MIPI_PHY2_PGC			0xf00
+#define HSIOMIX_PGC			0xf40
+#define MEDIAMIX_ISPDWP_PGC		0xf80
+#define DDRMIX_PGC			0xfc0
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
new file mode 100644
index 0000000..644adc7
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		0xB00
+#define CACHE_WRITEBACK_GRANULE		64
+
+#define PLAT_PRIMARY_CPU		U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0			MPIDR_AFFLVL0
+#define IMX_PWR_LVL1			MPIDR_AFFLVL1
+#define IMX_PWR_LVL2			MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL		U(1)
+#define PLAT_MAX_PWR_LVL		U(2)
+#define PLAT_MAX_OFF_STATE		U(4)
+#define PLAT_MAX_RET_STATE		U(2)
+
+#define PLAT_WAIT_RET_STATE		U(1)
+#define PLAT_STOP_OFF_STATE		U(3)
+
+#define BL31_BASE			U(0x960000)
+#define BL31_LIMIT			U(0x980000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE			U(0x38800000)
+#define PLAT_GICR_BASE			U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		16
+
+#define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+
+#define IMX_AIPSTZ1			U(0x301f0000)
+#define IMX_AIPSTZ2			U(0x305f0000)
+#define IMX_AIPSTZ3			U(0x309f0000)
+#define IMX_AIPSTZ4			U(0x32df0000)
+#define IMX_AIPSTZ5			U(0x30df0000)
+
+#define IMX_AIPS_BASE			U(0x30000000)
+#define IMX_AIPS_SIZE			U(0x3000000)
+#define IMX_GPV_BASE			U(0x32000000)
+#define IMX_GPV_SIZE			U(0x800000)
+#define IMX_AIPS1_BASE			U(0x30200000)
+#define IMX_AIPS4_BASE			U(0x32c00000)
+#define IMX_ANAMIX_BASE			U(0x30360000)
+#define IMX_CCM_BASE			U(0x30380000)
+#define IMX_SRC_BASE			U(0x30390000)
+#define IMX_GPC_BASE			U(0x303a0000)
+#define IMX_RDC_BASE			U(0x303d0000)
+#define IMX_CSU_BASE			U(0x303e0000)
+#define IMX_WDOG_BASE			U(0x30280000)
+#define IMX_SNVS_BASE			U(0x30370000)
+#define IMX_NOC_BASE			U(0x32700000)
+#define IMX_NOC_SIZE			U(0x100000)
+#define IMX_TZASC_BASE			U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE		U(0x30340000)
+#define IMX_CAAM_BASE			U(0x30900000)
+#define IMX_DDRC_BASE			U(0x3d400000)
+#define IMX_DDRPHY_BASE			U(0x3c000000)
+#define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_DDR_IPS_SIZE		U(0x1800000)
+#define IMX_ROM_BASE			U(0x0)
+
+#define IMX_GIC_BASE			PLAT_GICD_BASE
+#define IMX_GIC_SIZE			U(0x200000)
+
+#define IMX_HSIOMIX_CTL_BASE		U(0x32f10000)
+#define IMX_HDMI_CTL_BASE		U(0x32fc0000)
+#define RTX_RESET_CTL0			U(0x20)
+#define RTX_CLK_CTL0			U(0x40)
+#define RTX_CLK_CTL1			U(0x50)
+#define TX_CONTROL0			U(0x200)
+#define TX_CONTROL1			U(0x220)
+
+#define IMX_MEDIAMIX_CTL_BASE		U(0x32ec0000)
+#define RSTn_CSR			U(0x0)
+#define CLK_EN_CSR			U(0x4)
+#define RST_DIV				U(0x8)
+#define LCDIF_ARCACHE_CTRL		U(0x4c)
+#define ISI_CACHE_CTRL			U(0x50)
+
+#define WDOG_WSR			U(0x2)
+#define WDOG_WCR_WDZST			BIT(0)
+#define WDOG_WCR_WDBG			BIT(1)
+#define WDOG_WCR_WDE			BIT(2)
+#define WDOG_WCR_WDT			BIT(3)
+#define WDOG_WCR_SRS			BIT(4)
+#define WDOG_WCR_WDA			BIT(5)
+#define WDOG_WCR_SRE			BIT(6)
+#define WDOG_WCR_WDW			BIT(7)
+
+#define SRC_A53RCR0			U(0x4)
+#define SRC_A53RCR1			U(0x8)
+#define SRC_OTG1PHY_SCR			U(0x20)
+#define SRC_OTG2PHY_SCR			U(0x24)
+#define SRC_GPR1_OFFSET			U(0x74)
+
+#define SNVS_LPCR			U(0x38)
+#define SNVS_LPCR_SRTC_ENV		BIT(0)
+#define SNVS_LPCR_DP_EN			BIT(5)
+#define SNVS_LPCR_TOP			BIT(6)
+
+#define IOMUXC_GPR10			U(0x28)
+#define GPR_TZASC_EN			BIT(0)
+#define GPR_TZASC_EN_LOCK		BIT(16)
+
+#define ANAMIX_MISC_CTL			U(0x124)
+#define DRAM_PLL_CTRL			(IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM			U(64)
+
+#define OCRAM_S_BASE			U(0x00180000)
+#define OCRAM_S_SIZE			U(0x8000)
+#define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE		OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define GIC_MAP		MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
+#define DDRC_MAP	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define NOC_MAP		MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
new file mode 100644
index 0000000..1d11e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -0,0 +1,56 @@
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
+				-Iplat/imx/imx8m/include		\
+				-Iplat/imx/imx8m/imx8mp/include
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
+				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_aipstz.c			\
+				plat/imx/imx8m/imx_rdc.c			\
+				plat/imx/imx8m/imx8m_caam.c			\
+				plat/imx/imx8m/imx8m_psci_common.c		\
+				plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c	\
+				plat/imx/imx8m/imx8mp/imx8mp_psci.c		\
+				plat/imx/imx8m/imx8mp/gpc.c			\
+				plat/imx/common/imx8_topology.c			\
+				plat/imx/common/imx_sip_handler.c		\
+				plat/imx/common/imx_sip_svc.c			\
+				plat/imx/common/imx_uart_console.S		\
+				lib/cpus/aarch64/cortex_a53.S			\
+				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_GIC_SOURCES}				\
+				${XLAT_TABLES_LIB_SRCS}
+
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
+
+BL32_BASE		?=	0x56000000
+$(eval $(call add_define,BL32_BASE))
+
+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/imx/imx8m/imx8mq/include/gpc_reg.h b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
new file mode 100644
index 0000000..9f472d6
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define DDRMIX_PWR_REQ			BIT(5)
+#define DDRMIX_ADB400_SYNC		BIT(1)
+#define DDRMIX_ADB400_ACK		BIT(18)
+#define DDRMIX_PGC			0xd40
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 6033b0d..89a0b9d 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -7,74 +7,7 @@
 #ifndef IMX8M_GPC_H
 #define IMX8M_GPC_H
 
-#define LPCR_A53_BSC			0x0
-#define LPCR_A53_BSC2			0x108
-#define LPCR_A53_AD			0x4
-#define LPCR_M4				0x8
-#define SLPCR				0x14
-#define MST_CPU_MAPPING			0x18
-#define MLPCR				0x20
-#define PGC_ACK_SEL_A53			0x24
-#define IMR1_CORE0_A53			0x30
-#define IMR1_CORE1_A53			0x40
-#define IMR1_CORE2_A53			0x1C0
-#define IMR1_CORE3_A53			0x1D0
-#define IMR1_CORE0_M4			0x50
-#define SLT0_CFG			0xB0
-#define GPC_PU_PWRHSK			0x1FC
-#define PGC_CPU_0_1_MAPPING		0xEC
-#define CPU_PGC_UP_TRG			0xF0
-#define PU_PGC_UP_TRG			0xF8
-#define CPU_PGC_DN_TRG			0xFC
-#define PU_PGC_DN_TRG			0x104
-#define A53_CORE0_PGC			0x800
-#define A53_PLAT_PGC			0x900
-#define PLAT_PGC_PCR			0x900
-#define PGC_SCU_TIMING			0x910
-
-#define MASK_DSM_TRIGGER_A53		BIT(31)
-#define IRQ_SRC_A53_WUP			BIT(30)
-#define IRQ_SRC_A53_WUP_SHIFT		30
-#define IRQ_SRC_C1			BIT(29)
-#define IRQ_SRC_C0			BIT(28)
-#define IRQ_SRC_C3			BIT(23)
-#define IRQ_SRC_C2			BIT(22)
-#define CORE_WKUP_FROM_GIC		(IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
-#define CPU_CLOCK_ON_LPM		BIT(14)
-#define A53_CLK_ON_LPM			BIT(14)
-#define MASTER0_LPM_HSK			BIT(6)
-
-#define L2PGE				BIT(31)
-#define EN_L2_WFI_PDN			BIT(5)
-#define EN_PLAT_PDN			BIT(4)
-
-#define SLPCR_EN_DSM			BIT(31)
-#define SLPCR_RBC_EN			BIT(30)
-#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
-#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
-#define SLPCR_VSTBY			BIT(2)
-#define SLPCR_SBYOS			BIT(1)
-#define SLPCR_BYPASS_PMIC_READY		BIT(0)
-#define SLPCR_RBC_COUNT_SHIFT		24
-#define SLPCR_STBY_COUNT_SHFT		3
-
-#define A53_DUMMY_PDN_ACK		BIT(15)
-#define A53_DUMMY_PUP_ACK		BIT(31)
-#define A53_PLAT_PDN_ACK		BIT(2)
-#define A53_PLAT_PUP_ACK		BIT(18)
-
-#define PLAT_PUP_SLT_CTRL		BIT(9)
-#define PLAT_PDN_SLT_CTRL		BIT(8)
-
-#define SLT_PLAT_PDN			BIT(8)
-#define SLT_PLAT_PUP			BIT(9)
-
-#define MASTER1_MAPPING			BIT(1)
-#define MASTER2_MAPPING			BIT(2)
-
-#define TMR_TCD2_SHIFT			0
-#define TMC_TMR_SHIFT			10
-#define TRC1_TMC_SHIFT			20
+#include <gpc_reg.h>
 
 /* helper macro */
 #define A53_LPM_MASK	U(0xF)
@@ -83,7 +16,7 @@
 #define LPM_MODE(local_state)		((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP)
 
 #define DSM_MODE_MASK	BIT(31)
-
+#define CORE_WKUP_FROM_GIC		(IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
 #define A53_CORE_WUP_SRC(core_id)	(1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
 #define COREx_PGC_PCR(core_id)		(0x800 + (core_id) * 0x40)
 #define COREx_WFI_PDN(core_id)		(1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
@@ -95,6 +28,33 @@
 #define IRQ_IMR_NUM	4
 #define IMR_MASK_ALL	0xffffffff
 
+#define IMX_PD_DOMAIN(name, on)				\
+	{						\
+		.pwr_req = name##_PWR_REQ,		\
+		.pgc_offset = name##_PGC,		\
+		.need_sync = false,			\
+		.always_on = true,			\
+	}
+
+#define IMX_MIX_DOMAIN(name, on)			\
+	{						\
+		.pwr_req = name##_PWR_REQ,		\
+		.pgc_offset = name##_PGC,		\
+		.adb400_sync = name##_ADB400_SYNC,	\
+		.adb400_ack = name##_ADB400_ACK,	\
+		.need_sync = true,			\
+		.always_on = true,			\
+	}
+
+struct imx_pwr_domain {
+	uint32_t pwr_req;
+	uint32_t adb400_sync;
+	uint32_t adb400_ack;
+	uint32_t pgc_offset;
+	bool need_sync;
+	bool always_on;
+};
+
 /* function declare */
 void imx_gpc_init(void);
 void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
diff --git a/plat/marvell/armada/a3k/common/include/platform_def.h b/plat/marvell/armada/a3k/common/include/platform_def.h
index 7f8f79a..61c7dfe 100644
--- a/plat/marvell/armada/a3k/common/include/platform_def.h
+++ b/plat/marvell/armada/a3k/common/include/platform_def.h
@@ -83,9 +83,11 @@
 #define PLAT_MARVELL_TRUSTED_ROM_BASE		PLAT_MARVELL_ATF_LOAD_ADDR
 /* 4 MB for FIP image */
 #define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x00400000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
+/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE SHMEM follows this region
+ */
 #define PLAT_MARVELL_TRUSTED_RAM_BASE		0x04400000
-#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x01000000	/* 16 MB */
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x00C00000	/* 12 MB DRAM */
 
 /*
  * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
diff --git a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
index 7d30ebe..a409261 100644
--- a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
@@ -103,7 +103,10 @@
 	{0x00000000f2000000,	0x4000000,	IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,	IO_0_TID},
 	{0x00000000c0000000,	0x30000000,	IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
index 7fc33f1..3b68e91 100644
--- a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
@@ -94,7 +94,10 @@
 	{0x00000000f2000000,	0x4000000,	IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,	IO_0_TID},
 	{0x00000000c0000000,    0x30000000,	IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
index 856c07a..4ccda14 100644
--- a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
@@ -132,7 +132,10 @@
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
index 0edc977..75a1b0c 100644
--- a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
@@ -78,12 +78,8 @@
 	/* CP1 (MCI0) internal regs */
 	{0x00000000f4000000,		0x2000000,  MCI_0_TID},
 #ifndef IMAGE_BLE
-	/* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
-	{0x00000000f9000000,		0x2000000,  MCI_0_TID},
-	/* PCIe1 on CP1*/
-	{0x00000000fb000000,		0x1000000,  MCI_0_TID},
-	/* PCIe2 on CP1*/
-	{0x00000000fc000000,		0x1000000,  MCI_0_TID},
+	/* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/
+	{0x00000000f9000000,		0x4000000,  MCI_0_TID},
 	/* MCI 0 indirect window */
 	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,   MCI_0_TID},
 	/* MCI 1 indirect window */
@@ -166,7 +162,10 @@
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
 #if LLC_SRAM
-	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
 #endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
new file mode 100644
index 0000000..46a9a26
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/mentor/mi2cv.h>
+#include <lib/mmio.h>
+
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+#define MVEBU_AP_MPP_CTRL0_7_REG                MVEBU_AP_MPP_REGS(0)
+#define MVEBU_AP_MPP_CTRL4_OFFS                 16
+#define MVEBU_AP_MPP_CTRL5_OFFS                 20
+#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA         0x3
+#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA         0x3
+
+#define MVEBU_CP_MPP_CTRL37_OFFS		20
+#define MVEBU_CP_MPP_CTRL38_OFFS		24
+#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA	0x2
+#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA	0x2
+
+#define MVEBU_MPP_CTRL_MASK			0xf
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+	/* Board with 1CS 8Gb x4 devices of Micron 2400T */
+	DEBUG_LEVEL_ERROR,
+	0x1, /* active interfaces */
+	/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+	{ { { {0x1, 0x0, 0, 0},	/* FIXME: change the cs mask for all 64 bit */
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0},
+	      {0x1, 0x0, 0, 0} },
+	   /* TODO: double check if the speed bin is 2400T */
+	   SPEED_BIN_DDR_2400T,		/* speed_bin */
+	   MV_DDR_DEV_WIDTH_8BIT,	/* sdram device width */
+	   MV_DDR_DIE_CAP_8GBIT,	/* die capacity */
+	   MV_DDR_FREQ_SAR,		/* frequency */
+	   0, 0,			/* cas_l, cas_wl */
+	   MV_DDR_TEMP_LOW} },		/* temperature */
+	   MV_DDR_64BIT_BUS_MASK,	/* subphys mask */
+	   MV_DDR_CFG_SPD,		/* ddr configuration data source */
+	{ {0} },			/* raw spd data */
+	{0},				/* timing parameters */
+	{				/* electrical configuration */
+		{			/* memory electrical configuration */
+			MV_DDR_RTT_NOM_PARK_RZQ_DISABLE,	/* rtt_nom */
+			{
+				MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+				MV_DDR_RTT_NOM_PARK_RZQ_DIV1  /* rtt_park 2cs */
+			},
+			{
+				MV_DDR_RTT_WR_DYN_ODT_OFF,	/* rtt_wr 1cs */
+				MV_DDR_RTT_WR_RZQ_DIV2		/* rtt_wr 2cs */
+			},
+			MV_DDR_DIC_RZQ_DIV7	/* dic */
+		},
+		{			/* phy electrical configuration */
+			MV_DDR_OHM_30,	/* data_drv_p */
+			MV_DDR_OHM_30,	/* data_drv_n */
+			MV_DDR_OHM_30,	/* ctrl_drv_p */
+			MV_DDR_OHM_30,	/* ctrl_drv_n */
+			{
+				MV_DDR_OHM_60,	/* odt_p 1cs */
+				MV_DDR_OHM_120	/* odt_p 2cs */
+			},
+			{
+				MV_DDR_OHM_60,	/* odt_n 1cs */
+				MV_DDR_OHM_120	/* odt_n 2cs */
+			},
+		},
+		{			/* mac electrical configuration */
+			MV_DDR_ODT_CFG_NORMAL,		/* odtcfg_pattern */
+			MV_DDR_ODT_CFG_ALWAYS_ON,	/* odtcfg_write */
+			MV_DDR_ODT_CFG_NORMAL,		/* odtcfg_read */
+		},
+	}
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+	/* Return the board topology as defined in the board code */
+	return &board_topology_map;
+}
+
+static void mpp_config(void)
+{
+	uint32_t val;
+	uintptr_t reg;
+
+       /* configure ap mmps 4, 5 to I2C */
+	reg = MVEBU_AP_MPP_CTRL0_7_REG;
+
+	val = mmio_read_32(reg);
+	val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL4_OFFS) |
+		(MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL5_OFFS));
+	val |= ((MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA << MVEBU_AP_MPP_CTRL4_OFFS) |
+		(MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA << MVEBU_AP_MPP_CTRL5_OFFS));
+
+	mmio_write_32(reg, val);
+}
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+	INFO("Gathering DRAM information\n");
+
+	if (tm->cfg_src == MV_DDR_CFG_SPD) {
+		/* configure MPPs to enable i2c */
+		mpp_config();
+		/* initialize the MVEBU_AP_I2C_BASE I2C bus */
+		i2c_init((void *)MVEBU_AP_I2C_BASE);
+		/* select SPD memory page 0 to access DRAM configuration */
+		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
+		/* read data from spd */
+		i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
+			 sizeof(tm->spd_data.all_bytes));
+	}
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
new file mode 100644
index 0000000..0edc977
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * GPIO Configuration
+ *****************************************************************************
+ */
+#define MPP_CONTROL_REGISTER		0xf2440018
+#define MPP_CONTROL_MPP_SEL_52_MASK	0xf0000
+#define GPIO_DATA_OUT1_REGISTER		0xf2440140
+#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144
+#define GPIO52_MASK			0x100000
+
+/* Reset PCIe via GPIO number 52 */
+int marvell_gpio_config(void)
+{
+	uint32_t reg;
+
+	reg = mmio_read_32(MPP_CONTROL_REGISTER);
+	reg |= MPP_CONTROL_MPP_SEL_52_MASK;
+	mmio_write_32(MPP_CONTROL_REGISTER, reg);
+
+	reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER);
+	reg |= GPIO52_MASK;
+	mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg);
+
+	reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER);
+	reg &= ~GPIO52_MASK;
+	mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg);
+	udelay(100);
+
+	return 0;
+}
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+	/* CP1 SPI1 CS0 Direct Mode access */
+	{0xf900,	0x1000000,	AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+			       uintptr_t base)
+{
+	*win = amb_memory_map;
+	if (*win == NULL)
+		*size = 0;
+	else
+		*size = ARRAY_SIZE(amb_memory_map);
+
+	return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+	/* CP1 (MCI0) internal regs */
+	{0x00000000f4000000,		0x2000000,  MCI_0_TID},
+#ifndef IMAGE_BLE
+	/* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
+	{0x00000000f9000000,		0x2000000,  MCI_0_TID},
+	/* PCIe1 on CP1*/
+	{0x00000000fb000000,		0x1000000,  MCI_0_TID},
+	/* PCIe2 on CP1*/
+	{0x00000000fc000000,		0x1000000,  MCI_0_TID},
+	/* MCI 0 indirect window */
+	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,   MCI_0_TID},
+	/* MCI 1 indirect window */
+	{MVEBU_MCI_REG_BASE_REMAP(1),	0x100000,   MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+	return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+				  uint32_t *size)
+{
+	*win = io_win_memory_map;
+	if (*win == NULL)
+		*size = 0;
+	else
+		*size = ARRAY_SIZE(io_win_memory_map);
+
+	return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+	/* CP0 */
+	/* PEX1_X1 window */
+	{0x00000000f7000000,	0x1000000,	PEX1_TID},
+	/* PEX2_X1 window */
+	{0x00000000f8000000,	0x1000000,	PEX2_TID},
+	/* PEX0_X4 window */
+	{0x00000000f6000000,	0x1000000,	PEX0_TID},
+	{0x00000000c0000000,	0x30000000,	PEX0_TID},
+	{0x0000000800000000,	0x100000000,	PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+	/* CP1 */
+	/* SPI1_CS0 (RUNIT) window */
+	{0x00000000f9000000,	0x1000000,	RUNIT_TID},
+	/* PEX1_X1 window */
+	{0x00000000fb000000,	0x1000000,	PEX1_TID},
+	/* PEX2_X1 window */
+	{0x00000000fc000000,	0x1000000,	PEX2_TID},
+	/* PEX0_X4 window */
+	{0x00000000fa000000,	0x1000000,	PEX0_TID}
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+			       uintptr_t base)
+{
+	switch (base) {
+	case MVEBU_CP_REGS_BASE(0):
+		*win = iob_memory_map_cp0;
+		*size = ARRAY_SIZE(iob_memory_map_cp0);
+		return 0;
+	case MVEBU_CP_REGS_BASE(1):
+		*win = iob_memory_map_cp1;
+		*size = ARRAY_SIZE(iob_memory_map_cp1);
+		return 0;
+	default:
+		*size = 0;
+		*win = 0;
+		return 1;
+	}
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {
+#ifdef IMAGE_BLE
+	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+#endif
+	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
+	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
+	{0x0000000800000000,	0x100000000,  IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+	return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+			       uint32_t *size)
+{
+	*win = ccu_memory_map;
+	*size = ARRAY_SIZE(ccu_memory_map);
+
+	return 0;
+}
+
+/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
+
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_marvell_get_skip_image_data(void)
+{
+	/* No recovery button on A8k-MCBIN board */
+	return NULL;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
new file mode 100644
index 0000000..5147dd5
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Sartura Ltd.
+ * Author: Luka Kovacic <luka.kovacic@sartura.hr>
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <drivers/console.h>
+#include <plat_marvell.h>
+
+/*****************************************************************************
+ * Platform specific power off functions
+ * Power off PSU / Send command to power management MCU / ...
+ *****************************************************************************
+ */
+
+unsigned char add_xor_checksum(unsigned char *buf, unsigned char xor_len)
+{
+	unsigned char xor_sum = 0;
+	unsigned int i;
+
+	for (i = 0; i < xor_len; i++)
+		xor_sum ^= buf[i];
+
+	return xor_sum;
+}
+
+int system_power_off(void)
+{
+	static console_t console;
+
+	/* WT61P803 MCU system_off_now command */
+	unsigned char system_off_now[4] = { '@', 'C', '0' };
+	int i, len;
+
+	len = sizeof(system_off_now);
+	system_off_now[len - 1] = add_xor_checksum(system_off_now, len);
+
+	console_16550_register(PLAT_MARVELL_BOOT_UART_BASE + 0x100,
+		PLAT_MARVELL_BOOT_UART_CLK_IN_HZ, 115200, &console);
+
+	/* Send system_off_now to console */
+	for (i = 0; i < len; i++) {
+		console.putc(system_off_now[i],	&console);
+		udelay(1000);
+	}
+
+	console.flush(&console);
+	(void)console_unregister(&console);
+
+	mdelay(100);
+
+	return 0;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
new file mode 100644
index 0000000..3fa119a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT		2	/* A80x0 has both CP0 & CP1 */
+#define I2C_SPD_ADDR		0x53	/* Access SPD data */
+#define I2C_SPD_P0_ADDR		0x36	/* Select SPD data page 0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
new file mode 100644
index 0000000..3378d53
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier:     BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT		:= 0
+
+CP_NUM			:= 2
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC     	:=	tools/doimage/secure/sec_img_8K.cfg
+
+MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR		:= 	$(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index dcbf9a6..02f1553 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -37,7 +37,7 @@
 DOIMAGE_FLAGS	+= -b $(ROM_BIN_EXT) $(NAND_DOIMAGE_FLAGS) $(DOIMAGE_SEC_FLAGS)
 
 # Check whether to build system_power.c for the platform
-ifneq ("$(wildcard $(PLAT_FAMILY_BASE)/$(PLAT)/board/system_power.c)","")
+ifneq ("$(wildcard $(BOARD_DIR)/board/system_power.c)","")
 SYSTEM_POWER_SUPPORT = 1
 else
 SYSTEM_POWER_SUPPORT = 0
@@ -85,12 +85,13 @@
 				$(MARVELL_DRV_BASE)/ccu.c	\
 				$(MARVELL_DRV_BASE)/cache_llc.c	\
 				$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
-				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c
+				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
+				$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
 
 BL31_PORTING_SOURCES	:=	$(BOARD_DIR)/board/marvell_plat_config.c
 
 ifeq ($(SYSTEM_POWER_SUPPORT),1)
-BL31_PORTING_SOURCES	+=	$(PLAT_FAMILY_BASE)/$(PLAT)/board/system_power.c
+BL31_PORTING_SOURCES	+=	$(BOARD_DIR)/board/system_power.c
 endif
 
 BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a72.S		       \
diff --git a/plat/marvell/armada/a8k/common/include/platform_def.h b/plat/marvell/armada/a8k/common/include/platform_def.h
index b26e3ea..944a151 100644
--- a/plat/marvell/armada/a8k/common/include/platform_def.h
+++ b/plat/marvell/armada/a8k/common/include/platform_def.h
@@ -96,11 +96,13 @@
 #define PLAT_MARVELL_TRUSTED_ROM_BASE		PLAT_MARVELL_ATF_LOAD_ADDR
 /* 4 MB for FIP image */
 #define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x00400000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted RAM */
+/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE 4MB SHMEM follows this region
+ */
 #define PLAT_MARVELL_TRUSTED_RAM_BASE		0x04400000
-#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x01000000	/* 16 MB DRAM */
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x00C00000	/* 12 MB DRAM */
 
-#define PLAT_MARVELL_LLC_SRAM_BASE		PLAT_MARVELL_TRUSTED_RAM_BASE
+#define PLAT_MARVELL_LLC_SRAM_BASE		0x05400000
 #define PLAT_MARVELL_LLC_SRAM_SIZE		0x00100000	/* 1 MB SRAM */
 
 /*
diff --git a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
index 6a8e11c..8d909dc 100644
--- a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
+++ b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
@@ -100,6 +100,45 @@
 
 	    .next_handoff_image_id = BL33_IMAGE_ID,
     },
+
+	/*
+	 * Fill BL32 external 1 related information.
+	 * A typical use for extra1 image is with OP-TEE
+	 * where it is the pager image.
+	 */
+	{
+	    .image_id = BL32_EXTRA1_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+	    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/*
+	 * Fill BL32 external 2 related information.
+	 * A typical use for extra2 image is with OP-TEE,
+	 * where it is the paged image.
+	 */
+	{
+	    .image_id = BL32_EXTRA2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+	    .image_info.image_base = MARVELL_OPTEE_PAGEABLE_LOAD_BASE,
+	    .image_info.image_max_size = MARVELL_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
 # endif /* BL32_BASE */
 
 	/* Fill BL33 related information */
diff --git a/plat/marvell/armada/common/marvell_bl2_setup.c b/plat/marvell/armada/common/marvell_bl2_setup.c
index 3c1c391..3dfa82e 100644
--- a/plat/marvell/armada/common/marvell_bl2_setup.c
+++ b/plat/marvell/armada/common/marvell_bl2_setup.c
@@ -17,6 +17,9 @@
 #include <drivers/console.h>
 #include <lib/utils.h>
 
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
 #include <marvell_def.h>
 #include <plat_marvell.h>
 
@@ -97,9 +100,29 @@
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 
+#ifdef SPD_opteed
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+#endif /* SPD_opteed */
 	assert(bl_mem_params);
 
 	switch (image_id) {
+	case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+					 &pager_mem_params->image_info,
+					 &paged_mem_params->image_info);
+		if (err != 0)
+			WARN("OPTEE header parse error.\n");
+#endif /* SPD_opteed */
+		bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl32_entry();
+		break;
 
 	case BL33_IMAGE_ID:
 		/* BL33 expects to receive the primary CPU MPID (through r0) */
diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
index fcc97ac..2e96e2f 100644
--- a/plat/marvell/armada/common/marvell_common.mk
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -22,15 +22,7 @@
 $(eval $(call add_define,LLC_SRAM))
 
 # Enable/Disable LLC
-ifeq (${LLC_SRAM}, 0)
 LLC_ENABLE			:= 1
-else
-# When LLC_SRAM=1, the entire LLC converted to SRAM and enabled at BL1.
-# All existing cases activating LLC at BL31 stage should be disabled.
-# The below assignment does not allow changing the LLC_ENABLE
-# value in the command line.
-LLC_ENABLE			= 0
-endif
 $(eval $(call add_define,LLC_ENABLE))
 
 include lib/xlat_tables_v2/xlat_tables.mk
@@ -66,6 +58,10 @@
 				$(MARVELL_PLAT_BASE)/common/aarch64/marvell_bl2_mem_params_desc.c	\
 				$(MARVELL_PLAT_BASE)/common/marvell_image_load.c
 
+ifeq (${SPD},opteed)
+PLAT_INCLUDES		+=	-Iinclude/lib
+BL2_SOURCES		+=	lib/optee/optee_utils.c
+endif
 
 BL31_SOURCES		+=	$(MARVELL_PLAT_BASE)/common/marvell_bl31_setup.c	\
 				$(MARVELL_PLAT_BASE)/common/marvell_pm.c		\
@@ -77,6 +73,15 @@
 # PSCI functionality
 $(eval $(call add_define,CONFIG_ARM64))
 
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
 # MSS (SCP) build
 ifeq (${MSS_SUPPORT}, 1)
 include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk
diff --git a/plat/marvell/armada/common/marvell_io_storage.c b/plat/marvell/armada/common/marvell_io_storage.c
index 065f956..2627ba4 100644
--- a/plat/marvell/armada/common/marvell_io_storage.c
+++ b/plat/marvell/armada/common/marvell_io_storage.c
@@ -43,6 +43,15 @@
 static const io_uuid_spec_t bl32_uuid_spec = {
 	.uuid = UUID_SECURE_PAYLOAD_BL32,
 };
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -83,6 +92,16 @@
 		(uintptr_t)&bl32_uuid_spec,
 		open_fip
 	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
index 7150f0a..74dddc6 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
@@ -13,7 +13,6 @@
 #define HEADER_VERSION	0x1
 
 #define MSS_IDRAM_SIZE	0x10000 /* 64KB */
-#define MG_SRAM_SIZE	0x20000 /* 128KB */
 
 /* Types definitions */
 typedef struct file_header {
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
index 4473d81..adf570e 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
@@ -12,6 +12,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
 #include <lib/mmio.h>
 
 #include <plat_pm_trace.h>
@@ -42,8 +43,6 @@
 
 #define MSS_HANDSHAKE_TIMEOUT		50
 
-#define MG_CM3_SRAM_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
-
 static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
 {
 	int timeout = MSS_HANDSHAKE_TIMEOUT;
@@ -61,28 +60,6 @@
 	return 0;
 }
 
-static int mg_image_load(uintptr_t src_addr, uint32_t size, uintptr_t mg_regs)
-{
-	if (size > MG_SRAM_SIZE) {
-		ERROR("image is too big to fit into MG CM3 memory\n");
-		return 1;
-	}
-
-	NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
-	       src_addr, size, mg_regs);
-
-	/* Copy image to MG CM3 SRAM */
-	memcpy((void *)mg_regs, (void *)src_addr, size);
-
-	/*
-	 * Don't release MG CM3 from reset - it will be done by next step
-	 * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
-	 * has enabeld 802.3. auto-neg) will be choosen.
-	 */
-
-	return 0;
-}
-
 static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
 {
 	uint32_t i, loop_num, timeout;
@@ -258,8 +235,7 @@
 			break;
 		}
 		NOTICE("Load image to CP%d MG\n", cp_index);
-		ret = mg_image_load(single_img, image_size,
-				    MG_CM3_SRAM_BASE(cp_index));
+		ret = mg_image_load(single_img, image_size, cp_index);
 		if (ret != 0) {
 			ERROR("SCP Image load failed\n");
 			return -1;
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index 82dd606..f412a80 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.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.
 # Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
@@ -20,9 +20,10 @@
 				plat/common/plat_gicv3.c			\
 				${COMMON_DIR}/tegra_gicv3.c
 
-TEGRA_GICv2_SOURCES	:=	drivers/arm/gic/common/gic_common.c		\
-				drivers/arm/gic/v2/gicv2_main.c			\
-				drivers/arm/gic/v2/gicv2_helpers.c		\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+TEGRA_GICv2_SOURCES	:=	${GICV2_SOURCES}				\
 				plat/common/plat_gicv2.c			\
 				${COMMON_DIR}/tegra_gicv2.c
 
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index e4338b9..0804135 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -8,6 +8,8 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <services/arm_arch_svc.h>
 #include <tegra_def.h>
 #include <tegra_platform.h>
 #include <tegra_private.h>
@@ -286,3 +288,21 @@
 {
 	return (int32_t)((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor());
 }
+
+/*****************************************************************************
+ * plat_smccc_feature_available() - This function checks whether SMCCC feature
+ *                                  is availabile for the platform or not.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_smccc_feature_available(u_register_t fid)
+{
+	switch (fid) {
+	case SMCCC_ARCH_SOC_ID:
+		return SMC_ARCH_CALL_SUCCESS;
+	default:
+		return SMC_ARCH_CALL_NOT_SUPPORTED;
+	}
+}
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index 0a49d81..cfacd1f 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -17,6 +17,7 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
 #include <libfdt.h>
 
 #include <drivers/arm/gicv2.h>
@@ -200,13 +201,6 @@
 	enable_mmu_el3(0);
 }
 
-static uint32_t dtb_size(const void *dtb)
-{
-	const uint32_t *dtb_header = dtb;
-
-	return fdt32_to_cpu(dtb_header[1]);
-}
-
 static void rpi4_prepare_dtb(void)
 {
 	void *dtb = (void *)rpi4_get_dtb_address();
@@ -250,7 +244,7 @@
 	if (ret < 0)
 		ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
 
-	clean_dcache_range((uintptr_t)dtb, dtb_size(dtb));
+	clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
 	INFO("Changed device tree to advertise PSCI.\n");
 }
 
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
index 679f14d..4524610 100644
--- a/plat/socionext/uniphier/uniphier_bl2_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -21,8 +21,8 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_IMAGE_BUF_OFFSET	0x04300000UL
-#define UNIPHIER_IMAGE_BUF_SIZE		0x00100000UL
+#define UNIPHIER_IMAGE_BUF_OFFSET	0x03800000UL
+#define UNIPHIER_IMAGE_BUF_SIZE		0x00800000UL
 
 static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
 static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
diff --git a/plat/socionext/uniphier/uniphier_image_desc.c b/plat/socionext/uniphier/uniphier_image_desc.c
index 8c232ba..dd62d1e 100644
--- a/plat/socionext/uniphier/uniphier_image_desc.c
+++ b/plat/socionext/uniphier/uniphier_image_desc.c
@@ -14,9 +14,9 @@
 #include "uniphier.h"
 
 #define UNIPHIER_BL33_OFFSET		0x04000000UL
-#define UNIPHIER_BL33_MAX_SIZE		0x00100000UL
+#define UNIPHIER_BL33_MAX_SIZE		0x00800000UL
 
-#define UNIPHIER_SCP_OFFSET		0x04100000UL
+#define UNIPHIER_SCP_OFFSET		0x04800000UL
 #define UNIPHIER_SCP_MAX_SIZE		0x00020000UL
 
 static struct bl_mem_params_node uniphier_image_descs[] = {
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 77d1eaf..92e15b0 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -25,8 +25,8 @@
 
 #define UNIPHIER_OCM_REGION_SIZE	0x00040000ULL
 
-#define UNIPHIER_BLOCK_BUF_OFFSET	0x04200000UL
-#define UNIPHIER_BLOCK_BUF_SIZE		0x00100000UL
+#define UNIPHIER_BLOCK_BUF_OFFSET	0x03000000UL
+#define UNIPHIER_BLOCK_BUF_SIZE		0x00800000UL
 
 static const io_dev_connector_t *uniphier_fip_dev_con;
 static uintptr_t uniphier_fip_dev_handle;
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
new file mode 100644
index 0000000..13f4b13
--- /dev/null
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SHARED_RESOURCES_H
+#define STM32MP_SHARED_RESOURCES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef STM32MP_SHARED_RESOURCES
+enum stm32mp_shres;
+
+/* Return true if @clock_id is shared by secure and non-secure worlds */
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
+
+/* Return true if and only if @reset_id relates to a non-secure peripheral */
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
+
+/* Register a shared resource assigned to the secure world */
+void stm32mp_register_secure_periph(enum stm32mp_shres id);
+
+/* Register a shared resource assigned to the non-secure world */
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id);
+
+/* Register a peripheral as secure or non-secure based on IO base address */
+void stm32mp_register_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base);
+
+/* Register a GPIO as secure or non-secure based on its bank and pin numbers */
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
+
+/* Consolidate peripheral states and lock against new peripheral registering */
+void stm32mp_lock_periph_registering(void);
+#else
+static inline void stm32mp_register_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline void stm32mp_register_secure_gpio(unsigned int bank __unused,
+						unsigned int pin __unused)
+{
+}
+
+static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused,
+						    unsigned int pin __unused)
+{
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+#endif /* STM32MP_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 27ba6f7..7076a71 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -196,4 +196,11 @@
  ******************************************************************************/
 #define PLAT_PCPU_DATA_SIZE	2
 
+/*******************************************************************************
+ * Number of parallel entry slots in SMT SCMI server entry context. For this
+ * platform, SCMI server is reached through SMC only, hence the number of
+ * entry slots.
+ ******************************************************************************/
+#define PLAT_SMT_ENTRY_COUNT		PLATFORM_CORE_COUNT
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index 2da64ac..b6cb91e 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -22,4 +22,6 @@
 void stm32mp1_syscfg_disable_io_compensation(void);
 
 uint32_t stm32mp_get_ddr_ns_size(void);
+
+void stm32mp1_init_scmi_server(void);
 #endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..3f6367e
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <stm32mp_shared_resources.h>
+
+#define STM32MP1_SHRES_GPIOZ(i)		(STM32MP1_SHRES_GPIOZ_0 + (i))
+
+enum stm32mp_shres {
+	STM32MP1_SHRES_CRYP1,
+	STM32MP1_SHRES_GPIOZ_0,
+	STM32MP1_SHRES_GPIOZ_1,
+	STM32MP1_SHRES_GPIOZ_2,
+	STM32MP1_SHRES_GPIOZ_3,
+	STM32MP1_SHRES_GPIOZ_4,
+	STM32MP1_SHRES_GPIOZ_5,
+	STM32MP1_SHRES_GPIOZ_6,
+	STM32MP1_SHRES_GPIOZ_7,
+	STM32MP1_SHRES_HASH1,
+	STM32MP1_SHRES_I2C4,
+	STM32MP1_SHRES_I2C6,
+	STM32MP1_SHRES_IWDG1,
+	STM32MP1_SHRES_MCU,
+	STM32MP1_SHRES_MDMA,
+	STM32MP1_SHRES_PLL3,
+	STM32MP1_SHRES_RNG1,
+	STM32MP1_SHRES_RTC,
+	STM32MP1_SHRES_SPI6,
+	STM32MP1_SHRES_USART1,
+
+	STM32MP1_SHRES_COUNT
+};
+#endif /* STM32MP1_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
index b872758..57240bc 100644
--- a/plat/st/stm32mp1/include/stm32mp1_smc.h
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -29,6 +29,16 @@
  */
 #define STM32_SMC_BSEC			0x82001003
 
+/*
+ * STM32_SIP_SMC_SCMI_AGENT0
+ * STM32_SIP_SMC_SCMI_AGENT1
+ * Process SCMI message pending in SCMI shared memory buffer.
+ *
+ * Argument a0: (input) SMCC ID
+ */
+#define STM32_SIP_SMC_SCMI_AGENT0	0x82002000
+#define STM32_SIP_SMC_SCMI_AGENT1	0x82002001
+
 /* SMC function IDs for SiP Service queries */
 #define STM32_SIP_SVC_CALL_COUNT	0x8200ff00
 #define STM32_SIP_SVC_UID		0x8200ff01
@@ -40,7 +50,7 @@
 #define STM32_SIP_SVC_VERSION_MINOR	0x1
 
 /* Number of STM32 SiP Calls implemented */
-#define STM32_COMMON_SIP_NUM_CALLS	4
+#define STM32_COMMON_SIP_NUM_CALLS	3
 
 /* Service for BSEC */
 #define STM32_SMC_READ_SHADOW		0x01
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
index 72af9ff..49375a6 100644
--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -9,6 +9,7 @@
 
 #include <common/debug.h>
 #include <common/runtime_svc.h>
+#include <drivers/st/scmi-msg.h>
 #include <lib/psci/psci.h>
 #include <tools_share/uuid.h>
 
@@ -65,6 +66,13 @@
 		ret2_enabled = true;
 		break;
 
+	case STM32_SIP_SMC_SCMI_AGENT0:
+		scmi_smt_fastcall_smc_entry(0);
+		break;
+	case STM32_SIP_SMC_SCMI_AGENT1:
+		scmi_smt_fastcall_smc_entry(1);
+		break;
+
 	default:
 		WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
 		ret1 = SMC_UNK;
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index de54e09..5d7d495 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -6,10 +6,13 @@
 
 SP_MIN_WITH_SECURE_FIQ	:=	1
 
+BL32_CFLAGS		+=	-DSTM32MP_SHARED_RESOURCES
+
 BL32_SOURCES		+=	drivers/st/etzpc/etzpc.c			\
 				plat/common/aarch32/platform_mp_stack.S		\
 				plat/st/stm32mp1/sp_min/sp_min_setup.c		\
 				plat/st/stm32mp1/stm32mp1_pm.c			\
+				plat/st/stm32mp1/stm32mp1_shared_resources.c	\
 				plat/st/stm32mp1/stm32mp1_topology.c
 
 # Generic GIC v2
@@ -22,9 +25,17 @@
 # Generic PSCI
 BL32_SOURCES		+=	plat/common/plat_psci_common.c
 
+# SCMI server drivers
+BL32_SOURCES		+=	drivers/st/scmi-msg/base.c		\
+				drivers/st/scmi-msg/clock.c		\
+				drivers/st/scmi-msg/entry.c		\
+				drivers/st/scmi-msg/reset_domain.c	\
+				drivers/st/scmi-msg/smt.c
+
 # stm32mp1 specific services
 BL32_SOURCES		+=	plat/st/stm32mp1/services/bsec_svc.c		\
-				plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+				plat/st/stm32mp1/services/stm32mp1_svc_setup.c	\
+				plat/st/stm32mp1/stm32mp1_scmi.c
 
 # Arm Archtecture services
 BL32_SOURCES		+=	services/arm_arch_svc/arm_arch_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 1f96239..b639fcb 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -100,19 +100,12 @@
 
 static void stm32mp1_etzpc_early_setup(void)
 {
-	unsigned int n;
-
 	if (etzpc_init() != 0) {
 		panic();
 	}
 
 	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
 	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
-
-	/* Release security on all shared resources */
-	for (n = 0; n < STM32MP1_ETZPC_SEC_ID_LIMIT; n++) {
-		etzpc_configure_decprot(n, ETZPC_DECPROT_NS_RW);
-	}
 }
 
 /*******************************************************************************
@@ -199,14 +192,13 @@
 
 	stm32mp1_gic_init();
 
-	/* Set GPIO bank Z as non secure */
-	for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) {
-		set_gpio_secure_cfg(GPIO_BANK_Z, pin, false);
-	}
-
 	if (stm32_iwdg_init() < 0) {
 		panic();
 	}
+
+	stm32mp_lock_periph_registering();
+
+	stm32mp1_init_scmi_server();
 }
 
 void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 4fae2d7..ea18a30 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -25,6 +25,7 @@
 #include <stm32mp_shres_helpers.h>
 #include <stm32mp1_dbgmcu.h>
 #include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
 #endif
 
 /*******************************************************************************
@@ -61,6 +62,9 @@
 					 STM32MP_SYSRAM_SIZE - \
 					 STM32MP_NS_SYSRAM_SIZE)
 
+#define STM32MP_SCMI_NS_SHM_BASE	STM32MP_NS_SYSRAM_BASE
+#define STM32MP_SCMI_NS_SHM_SIZE	STM32MP_NS_SYSRAM_SIZE
+
 #define STM32MP_SEC_SYSRAM_BASE		STM32MP_SYSRAM_BASE
 #define STM32MP_SEC_SYSRAM_SIZE		(STM32MP_SYSRAM_SIZE - \
 					 STM32MP_NS_SYSRAM_SIZE)
@@ -493,14 +497,16 @@
 #define IWDG2_BASE			U(0x5A002000)
 
 /*******************************************************************************
- * STM32MP1 I2C4
+ * Miscellaneous STM32MP1 peripherals base address
  ******************************************************************************/
-#define I2C4_BASE			U(0x5C002000)
-
-/*******************************************************************************
- * STM32MP1 DBGMCU
- ******************************************************************************/
+#define CRYP1_BASE			U(0x54001000)
 #define DBGMCU_BASE			U(0x50081000)
+#define HASH1_BASE			U(0x54002000)
+#define I2C4_BASE			U(0x5C002000)
+#define I2C6_BASE			U(0x5c009000)
+#define RNG1_BASE			U(0x54003000)
+#define RTC_BASE			U(0x5c004000)
+#define SPI6_BASE			U(0x5c001000)
 
 /*******************************************************************************
  * Device Tree defines
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
new file mode 100644
index 0000000..80faf0c
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+
+#define TIMEOUT_US_1MS		1000U
+
+#define SCMI_CLOCK_NAME_SIZE	16U
+#define SCMI_RSTD_NAME_SIZE	16U
+
+/*
+ * struct stm32_scmi_clk - Data for the exposed clock
+ * @clock_id: Clock identifier in RCC clock driver
+ * @name: Clock string ID exposed to agent
+ * @enabled: State of the SCMI clock
+ */
+struct stm32_scmi_clk {
+	unsigned long clock_id;
+	const char *name;
+	bool enabled;
+};
+
+/*
+ * struct stm32_scmi_rstd - Data for the exposed reset controller
+ * @reset_id: Reset identifier in RCC reset driver
+ * @name: Reset string ID exposed to agent
+ */
+struct stm32_scmi_rstd {
+	unsigned long reset_id;
+	const char *name;
+};
+
+/* Locate all non-secure SMT message buffers in last page of SYSRAM */
+#define SMT_BUFFER_BASE		STM32MP_SCMI_NS_SHM_BASE
+#define SMT_BUFFER0_BASE	SMT_BUFFER_BASE
+#define SMT_BUFFER1_BASE	(SMT_BUFFER_BASE + 0x200)
+
+CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >=
+	(SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE),
+	assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size);
+
+static struct scmi_msg_channel scmi_channel[] = {
+	[0] = {
+		.shm_addr = SMT_BUFFER0_BASE,
+		.shm_size = SMT_BUF_SLOT_SIZE,
+	},
+	[1] = {
+		.shm_addr = SMT_BUFFER1_BASE,
+		.shm_size = SMT_BUF_SLOT_SIZE,
+	},
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+	assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+	return &scmi_channel[agent_id];
+}
+
+#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
+	[_scmi_id] = { \
+		.clock_id = _id, \
+		.name = _name, \
+		.enabled = _init_enabled, \
+	}
+
+static struct stm32_scmi_clk stm32_scmi0_clock[] = {
+	CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
+	CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
+	CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
+	CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
+	CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
+	CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
+	CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
+	CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
+	CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
+	CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
+	CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
+	CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
+	CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
+	CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
+	CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
+	CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
+	CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
+	CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
+	CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
+	CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
+	CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
+};
+
+static struct stm32_scmi_clk stm32_scmi1_clock[] = {
+	CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
+	CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
+	CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
+};
+
+#define RESET_CELL(_scmi_id, _id, _name) \
+	[_scmi_id] = { \
+		.reset_id = _id, \
+		.name = _name, \
+	}
+
+static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
+	RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
+	RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
+	RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
+	RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
+	RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
+	RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
+	RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
+	RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
+	RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
+	RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
+	RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+};
+
+struct scmi_agent_resources {
+	struct stm32_scmi_clk *clock;
+	size_t clock_count;
+	struct stm32_scmi_rstd *rstd;
+	size_t rstd_count;
+};
+
+static const struct scmi_agent_resources agent_resources[] = {
+	[0] = {
+		.clock = stm32_scmi0_clock,
+		.clock_count = ARRAY_SIZE(stm32_scmi0_clock),
+		.rstd = stm32_scmi0_reset_domain,
+		.rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
+	},
+	[1] = {
+		.clock = stm32_scmi1_clock,
+		.clock_count = ARRAY_SIZE(stm32_scmi1_clock),
+	},
+};
+
+static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
+{
+	assert(agent_id < ARRAY_SIZE(agent_resources));
+
+	return &agent_resources[agent_id];
+}
+
+#if ENABLE_ASSERTIONS
+static size_t plat_scmi_protocol_count_paranoid(void)
+{
+	unsigned int n = 0U;
+	unsigned int count = 0U;
+
+	for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+		if (agent_resources[n].clock_count) {
+			count++;
+			break;
+		}
+	}
+
+	for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+		if (agent_resources[n].rstd_count) {
+			count++;
+			break;
+		}
+	}
+
+	return count;
+}
+#endif
+
+static const char vendor[] = "ST";
+static const char sub_vendor[] = "";
+
+const char *plat_scmi_vendor_name(void)
+{
+	return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+	return sub_vendor;
+}
+
+/* Currently supporting Clocks and Reset Domains */
+static const uint8_t plat_protocol_list[] = {
+	SCMI_PROTOCOL_ID_CLOCK,
+	SCMI_PROTOCOL_ID_RESET_DOMAIN,
+	0U /* Null termination */
+};
+
+size_t plat_scmi_protocol_count(void)
+{
+	const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
+
+	assert(count == plat_scmi_protocol_count_paranoid());
+
+	return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
+{
+	assert(plat_scmi_protocol_count_paranoid() ==
+	       (ARRAY_SIZE(plat_protocol_list) - 1U));
+
+	return plat_protocol_list;
+}
+
+/*
+ * Platform SCMI clocks
+ */
+static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
+					 unsigned int scmi_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+	size_t n = 0U;
+
+	if (resource != NULL) {
+		for (n = 0U; n < resource->clock_count; n++) {
+			if (n == scmi_id) {
+				return &resource->clock[n];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+	if (resource == NULL) {
+		return 0U;
+	}
+
+	return resource->clock_count;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+				     unsigned int scmi_id)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if ((clock == NULL) ||
+	    !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return NULL;
+	}
+
+	return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+				    unsigned long *array, size_t *nb_elts)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if (clock == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return SCMI_DENIED;
+	}
+
+	if (array == NULL) {
+		*nb_elts = 1U;
+	} else if (*nb_elts == 1U) {
+		*array = stm32mp_clk_get_rate(clock->clock_id);
+	} else {
+		return SCMI_GENERIC_ERROR;
+	}
+
+	return SCMI_SUCCESS;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+				       unsigned int scmi_id)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if ((clock == NULL) ||
+	    !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return 0U;
+	}
+
+	return stm32mp_clk_get_rate(clock->clock_id);
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if ((clock == NULL) ||
+	    !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return 0U;
+	}
+
+	return (int32_t)clock->enabled;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+				  bool enable_not_disable)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if (clock == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return SCMI_DENIED;
+	}
+
+	if (enable_not_disable) {
+		if (!clock->enabled) {
+			VERBOSE("SCMI clock %u enable\n", scmi_id);
+			stm32mp_clk_enable(clock->clock_id);
+			clock->enabled = true;
+		}
+	} else {
+		if (clock->enabled) {
+			VERBOSE("SCMI clock %u disable\n", scmi_id);
+			stm32mp_clk_disable(clock->clock_id);
+			clock->enabled = false;
+		}
+	}
+
+	return SCMI_SUCCESS;
+}
+
+/*
+ * Platform SCMI reset domains
+ */
+static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
+					 unsigned int scmi_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+	size_t n;
+
+	if (resource != NULL) {
+		for (n = 0U; n < resource->rstd_count; n++) {
+			if (n == scmi_id) {
+				return &resource->rstd[n];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
+{
+	const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+	if (rstd == NULL) {
+		return NULL;
+	}
+
+	return rstd->name;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+	if (resource == NULL) {
+		return 0U;
+	}
+
+	return resource->rstd_count;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+				uint32_t state)
+{
+	const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+	if (rstd == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+		return SCMI_DENIED;
+	}
+
+	/* Supports only reset with context loss */
+	if (state != 0U) {
+		return SCMI_NOT_SUPPORTED;
+	}
+
+	VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
+
+	if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
+		return SCMI_HARDWARE_ERROR;
+	}
+
+	if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
+		return SCMI_HARDWARE_ERROR;
+	}
+
+	return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+				 bool assert_not_deassert)
+{
+	const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+	if (rstd == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+		return SCMI_DENIED;
+	}
+
+	if (assert_not_deassert) {
+		VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
+		stm32mp_reset_set(rstd->reset_id);
+	} else {
+		VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
+		stm32mp_reset_release(rstd->reset_id);
+	}
+
+	return SCMI_SUCCESS;
+}
+
+/*
+ * Initialize platform SCMI resources
+ */
+void stm32mp1_init_scmi_server(void)
+{
+	size_t i;
+
+	for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
+		scmi_smt_init_agent_channel(&scmi_channel[i]);
+	}
+
+	for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
+		const struct scmi_agent_resources *res = &agent_resources[i];
+		size_t j;
+
+		for (j = 0U; j < res->clock_count; j++) {
+			struct stm32_scmi_clk *clk = &res->clock[j];
+
+			if ((clk->name == NULL) ||
+			    (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
+				ERROR("Invalid SCMI clock name\n");
+				panic();
+			}
+
+			/* Sync SCMI clocks with their targeted initial state */
+			if (clk->enabled &&
+			    stm32mp_nsec_can_access_clock(clk->clock_id)) {
+				stm32mp_clk_enable(clk->clock_id);
+			}
+		}
+
+		for (j = 0U; j < res->rstd_count; j++) {
+			struct stm32_scmi_rstd *rstd = &res->rstd[j];
+
+			if ((rstd->name == NULL) ||
+			    (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
+				ERROR("Invalid SCMI reset domain name\n");
+				panic();
+			}
+		}
+	}
+}
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..208e34a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+
+#include <stm32mp_shared_resources.h>
+
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+	SHRES_UNREGISTERED = 0,
+	SHRES_SECURE,
+	SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
+	[STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+	[STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+	[STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+	[STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+	[STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+	[STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+	[STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+	[STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+	[STM32MP1_SHRES_IWDG1] = "IWDG1",
+	[STM32MP1_SHRES_USART1] = "USART1",
+	[STM32MP1_SHRES_SPI6] = "SPI6",
+	[STM32MP1_SHRES_I2C4] = "I2C4",
+	[STM32MP1_SHRES_RNG1] = "RNG1",
+	[STM32MP1_SHRES_HASH1] = "HASH1",
+	[STM32MP1_SHRES_CRYP1] = "CRYP1",
+	[STM32MP1_SHRES_I2C6] = "I2C6",
+	[STM32MP1_SHRES_RTC] = "RTC",
+	[STM32MP1_SHRES_MCU] = "MCU",
+	[STM32MP1_SHRES_MDMA] = "MDMA",
+	[STM32MP1_SHRES_PLL3] = "PLL3",
+};
+
+static const char __unused *shres2str_id(enum stm32mp_shres id)
+{
+	assert(id < ARRAY_SIZE(shres2str_id_tbl));
+
+	return shres2str_id_tbl[id];
+}
+
+static const char __unused *shres2str_state_tbl[] = {
+	[SHRES_UNREGISTERED] = "unregistered",
+	[SHRES_NON_SECURE] = "non-secure",
+	[SHRES_SECURE] = "secure",
+};
+
+static const char __unused *shres2str_state(unsigned int state)
+{
+	assert(state < ARRAY_SIZE(shres2str_state_tbl));
+
+	return shres2str_state_tbl[state];
+}
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+	registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+	lock_registering();
+
+	return (shres_state[id] == SHRES_NON_SECURE) ||
+	       (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+	return !periph_is_non_secure(id);
+}
+
+/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
+static int8_t gpioz_nbpin = -1;
+
+static unsigned int get_gpio_nbpin(unsigned int bank)
+{
+	if (bank != GPIO_BANK_Z) {
+		int count = fdt_get_gpio_bank_pin_count(bank);
+
+		assert((count >= 0) || (count <= (GPIO_PIN_MAX + 1)));
+
+		return (unsigned int)count;
+	}
+
+	if (gpioz_nbpin < 0) {
+		int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
+
+		assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
+
+		gpioz_nbpin = count;
+	}
+
+	return (unsigned int)gpioz_nbpin;
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+	return get_gpio_nbpin(GPIO_BANK_Z);
+}
+
+static void register_periph(enum stm32mp_shres id, unsigned int state)
+{
+	assert((id < STM32MP1_SHRES_COUNT) &&
+	       ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
+
+	if (registering_locked) {
+		if (shres_state[id] == state) {
+			return;
+		}
+		panic();
+	}
+
+	if ((shres_state[id] != SHRES_UNREGISTERED) &&
+	    (shres_state[id] != state)) {
+		VERBOSE("Cannot change %s from %s to %s\n",
+			shres2str_id(id),
+			shres2str_state(shres_state[id]),
+			shres2str_state(state));
+		panic();
+	}
+
+	if (shres_state[id] == SHRES_UNREGISTERED) {
+		VERBOSE("Register %s as %s\n",
+			shres2str_id(id), shres2str_state(state));
+	}
+
+	if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
+	    (id <= STM32MP1_SHRES_GPIOZ(7)) &&
+	    ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
+		ERROR("Invalid GPIO pin %u, %u pin(s) available\n",
+		      id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin());
+		panic();
+	}
+
+	shres_state[id] = (uint8_t)state;
+
+	/* Explore clock tree to lock dependencies */
+	if (state == SHRES_SECURE) {
+		enum stm32mp_shres clock_res_id;
+
+		switch (id) {
+		case STM32MP1_SHRES_GPIOZ(0):
+		case STM32MP1_SHRES_GPIOZ(1):
+		case STM32MP1_SHRES_GPIOZ(2):
+		case STM32MP1_SHRES_GPIOZ(3):
+		case STM32MP1_SHRES_GPIOZ(4):
+		case STM32MP1_SHRES_GPIOZ(5):
+		case STM32MP1_SHRES_GPIOZ(6):
+		case STM32MP1_SHRES_GPIOZ(7):
+			clock_res_id = GPIOZ;
+			break;
+		case STM32MP1_SHRES_IWDG1:
+			clock_res_id = IWDG1;
+			break;
+		case STM32MP1_SHRES_USART1:
+			clock_res_id = USART1_K;
+			break;
+		case STM32MP1_SHRES_SPI6:
+			clock_res_id = SPI6_K;
+			break;
+		case STM32MP1_SHRES_I2C4:
+			clock_res_id = I2C4_K;
+			break;
+		case STM32MP1_SHRES_RNG1:
+			clock_res_id = RNG1_K;
+			break;
+		case STM32MP1_SHRES_HASH1:
+			clock_res_id = HASH1;
+			break;
+		case STM32MP1_SHRES_CRYP1:
+			clock_res_id = CRYP1;
+			break;
+		case STM32MP1_SHRES_I2C6:
+			clock_res_id = I2C6_K;
+			break;
+		case STM32MP1_SHRES_RTC:
+			clock_res_id = RTC;
+			break;
+		default:
+			/* No clock resource dependency */
+			return;
+		}
+
+		stm32mp1_register_clock_parents_secure(clock_res_id);
+	}
+}
+
+/* Register resource by ID */
+void stm32mp_register_secure_periph(enum stm32mp_shres id)
+{
+	register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
+{
+	register_periph(id, SHRES_NON_SECURE);
+}
+
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+	enum stm32mp_shres id;
+
+	switch (base) {
+	case CRYP1_BASE:
+		id = STM32MP1_SHRES_CRYP1;
+		break;
+	case HASH1_BASE:
+		id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_BASE:
+		id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_BASE:
+		id = STM32MP1_SHRES_I2C6;
+		break;
+	case IWDG1_BASE:
+		id = STM32MP1_SHRES_IWDG1;
+		break;
+	case RNG1_BASE:
+		id = STM32MP1_SHRES_RNG1;
+		break;
+	case RTC_BASE:
+		id = STM32MP1_SHRES_RTC;
+		break;
+	case SPI6_BASE:
+		id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_BASE:
+		id = STM32MP1_SHRES_USART1;
+		break;
+
+	case GPIOA_BASE:
+	case GPIOB_BASE:
+	case GPIOC_BASE:
+	case GPIOD_BASE:
+	case GPIOE_BASE:
+	case GPIOF_BASE:
+	case GPIOG_BASE:
+	case GPIOH_BASE:
+	case GPIOI_BASE:
+	case GPIOJ_BASE:
+	case GPIOK_BASE:
+	case USART2_BASE:
+	case USART3_BASE:
+	case UART4_BASE:
+	case UART5_BASE:
+	case USART6_BASE:
+	case UART7_BASE:
+	case UART8_BASE:
+	case IWDG2_BASE:
+		/* Allow drivers to register some non-secure resources */
+		VERBOSE("IO for non-secure resource 0x%x\n",
+			(unsigned int)base);
+		if (state != SHRES_NON_SECURE) {
+			panic();
+		}
+
+		return;
+
+	default:
+		panic();
+	}
+
+	register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+	register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+	register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+	switch (bank) {
+	case GPIO_BANK_Z:
+		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+		break;
+	default:
+		ERROR("GPIO bank %u cannot be secured\n", bank);
+		panic();
+	}
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+	switch (bank) {
+	case GPIO_BANK_Z:
+		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+	unsigned int non_secure = 0U;
+	unsigned int i;
+
+	lock_registering();
+
+	if (bank != GPIO_BANK_Z) {
+		return true;
+	}
+
+	for (i = 0U; i < get_gpioz_nbpin(); i++) {
+		if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
+			non_secure++;
+		}
+	}
+
+	return non_secure == get_gpioz_nbpin();
+}
+
+static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+	unsigned int secure = 0U;
+	unsigned int i;
+
+	lock_registering();
+
+	if (bank != GPIO_BANK_Z) {
+		return false;
+	}
+
+	for (i = 0U; i < get_gpioz_nbpin(); i++) {
+		if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+			secure++;
+		}
+	}
+
+	return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+	switch (clock_id) {
+	case CK_CSI:
+	case CK_HSE:
+	case CK_HSE_DIV2:
+	case CK_HSI:
+	case CK_LSE:
+	case CK_LSI:
+	case PLL1_P:
+	case PLL1_Q:
+	case PLL1_R:
+	case PLL2_P:
+	case PLL2_Q:
+	case PLL2_R:
+	case PLL3_P:
+	case PLL3_Q:
+	case PLL3_R:
+	case RTCAPB:
+		return true;
+	case GPIOZ:
+		/* Allow clock access if at least one pin is non-secure */
+		return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
+	case CRYP1:
+		shres_id = STM32MP1_SHRES_CRYP1;
+		break;
+	case HASH1:
+		shres_id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_K:
+		shres_id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_K:
+		shres_id = STM32MP1_SHRES_I2C6;
+		break;
+	case IWDG1:
+		shres_id = STM32MP1_SHRES_IWDG1;
+		break;
+	case RNG1_K:
+		shres_id = STM32MP1_SHRES_RNG1;
+		break;
+	case RTC:
+		shres_id = STM32MP1_SHRES_RTC;
+		break;
+	case SPI6_K:
+		shres_id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_K:
+		shres_id = STM32MP1_SHRES_USART1;
+		break;
+	default:
+		return false;
+	}
+
+	return periph_is_non_secure(shres_id);
+}
+
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
+{
+	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+	switch (reset_id) {
+	case CRYP1_R:
+		shres_id = STM32MP1_SHRES_CRYP1;
+		break;
+	case GPIOZ_R:
+		/* GPIOZ reset mandates all pins are non-secure */
+		return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
+	case HASH1_R:
+		shres_id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_R:
+		shres_id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_R:
+		shres_id = STM32MP1_SHRES_I2C6;
+		break;
+	case MCU_R:
+		shres_id = STM32MP1_SHRES_MCU;
+		break;
+	case MDMA_R:
+		shres_id = STM32MP1_SHRES_MDMA;
+		break;
+	case RNG1_R:
+		shres_id = STM32MP1_SHRES_RNG1;
+		break;
+	case SPI6_R:
+		shres_id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_R:
+		shres_id = STM32MP1_SHRES_USART1;
+		break;
+	default:
+		return false;
+	}
+
+	return periph_is_non_secure(shres_id);
+}
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+	switch (id) {
+	case STM32MP1_SHRES_MCU:
+	case STM32MP1_SHRES_PLL3:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+	assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+	       (id > STM32MP1_SHRES_GPIOZ(7)));
+
+	if (periph_is_non_secure(id)) {
+		return ETZPC_DECPROT_NS_RW;
+	}
+
+	return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+	/* Some system peripherals shall be secure */
+	etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+
+	/* Configure ETZPC with peripheral registering */
+	etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_HASH1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C4));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C6));
+	etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_RNG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_USART1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+	uint32_t n;
+	uint32_t error = 0U;
+	bool mckprot = stm32mp1_rcc_is_mckprot();
+	bool secure = stm32mp1_rcc_is_secure();
+
+	for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+		if (shres_state[n] != SHRES_SECURE) {
+			continue;
+		}
+
+		if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+			ERROR("RCC %s MCKPROT %s and %s secure\n",
+			      secure ? "secure" : "non-secure",
+			      mckprot ? "set" : "not set",
+			      shres2str_id(n));
+			error++;
+		}
+	}
+
+	if (error != 0U) {
+		panic();
+	}
+}
+
+static void set_gpio_secure_configuration(void)
+{
+	uint32_t pin;
+
+	for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+		bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+		set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+	}
+}
+
+static void print_shared_resources_state(void)
+{
+	unsigned int id;
+
+	for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+		switch (shres_state[id]) {
+		case SHRES_SECURE:
+			INFO("stm32mp1 %s is secure\n", shres2str_id(id));
+			break;
+		case SHRES_NON_SECURE:
+		case SHRES_UNREGISTERED:
+			VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
+			break;
+		default:
+			VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
+			panic();
+		}
+	}
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+	registering_locked = true;
+
+	print_shared_resources_state();
+
+	check_rcc_secure_configuration();
+	set_etzpc_secure_configuration();
+	set_gpio_secure_configuration();
+}
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 588656d..37bfc62 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -24,8 +24,9 @@
 	switch (arg1) {
 	case SMCCC_VERSION:
 	case SMCCC_ARCH_FEATURES:
+		return SMC_ARCH_CALL_SUCCESS;
 	case SMCCC_ARCH_SOC_ID:
-		return SMC_OK;
+		return plat_is_smccc_feature_available(arg1);
 #if WORKAROUND_CVE_2017_5715
 	case SMCCC_ARCH_WORKAROUND_1:
 		if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 80b498e..8c5b04a 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -24,17 +24,17 @@
 #define OPT_ALIGN 2
 
 static int info_cmd(int argc, char *argv[]);
-static void info_usage(void);
+static void info_usage(int);
 static int create_cmd(int argc, char *argv[]);
-static void create_usage(void);
+static void create_usage(int);
 static int update_cmd(int argc, char *argv[]);
-static void update_usage(void);
+static void update_usage(int);
 static int unpack_cmd(int argc, char *argv[]);
-static void unpack_usage(void);
+static void unpack_usage(int);
 static int remove_cmd(int argc, char *argv[]);
-static void remove_usage(void);
+static void remove_usage(int);
 static int version_cmd(int argc, char *argv[]);
-static void version_usage(void);
+static void version_usage(int);
 static int help_cmd(int argc, char *argv[]);
 static void usage(void);
 
@@ -448,7 +448,7 @@
 	fip_toc_header_t toc_header;
 
 	if (argc != 2)
-		info_usage();
+		info_usage(EXIT_FAILURE);
 	argc--, argv++;
 
 	parse_fip(argv[0], &toc_header);
@@ -487,10 +487,10 @@
 	return 0;
 }
 
-static void info_usage(void)
+static void info_usage(int exit_status)
 {
 	printf("fiptool info FIP_FILENAME\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align)
@@ -669,7 +669,7 @@
 	unsigned long align = 1;
 
 	if (argc < 2)
-		create_usage();
+		create_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument,
@@ -710,7 +710,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				create_usage();
+				create_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -722,7 +722,7 @@
 			break;
 		}
 		default:
-			create_usage();
+			create_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -730,7 +730,7 @@
 	free(opts);
 
 	if (argc == 0)
-		create_usage();
+		create_usage(EXIT_SUCCESS);
 
 	update_fip();
 
@@ -738,7 +738,7 @@
 	return 0;
 }
 
-static void create_usage(void)
+static void create_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -753,7 +753,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int update_cmd(int argc, char *argv[])
@@ -767,7 +767,7 @@
 	int pflag = 0;
 
 	if (argc < 2)
-		update_usage();
+		update_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -807,7 +807,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				update_usage();
+				update_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -825,7 +825,7 @@
 			snprintf(outfile, sizeof(outfile), "%s", optarg);
 			break;
 		default:
-			update_usage();
+			update_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -833,7 +833,7 @@
 	free(opts);
 
 	if (argc == 0)
-		update_usage();
+		update_usage(EXIT_SUCCESS);
 
 	if (outfile[0] == '\0')
 		snprintf(outfile, sizeof(outfile), "%s", argv[0]);
@@ -851,7 +851,7 @@
 	return 0;
 }
 
-static void update_usage(void)
+static void update_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -867,7 +867,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int unpack_cmd(int argc, char *argv[])
@@ -880,7 +880,7 @@
 	int unpack_all = 1;
 
 	if (argc < 2)
-		unpack_usage();
+		unpack_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b');
@@ -915,7 +915,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				unpack_usage();
+				unpack_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -934,7 +934,7 @@
 			snprintf(outdir, sizeof(outdir), "%s", optarg);
 			break;
 		default:
-			unpack_usage();
+			unpack_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -942,7 +942,7 @@
 	free(opts);
 
 	if (argc == 0)
-		unpack_usage();
+		unpack_usage(EXIT_SUCCESS);
 
 	parse_fip(argv[0], NULL);
 
@@ -986,7 +986,7 @@
 	return 0;
 }
 
-static void unpack_usage(void)
+static void unpack_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -1003,7 +1003,7 @@
 		    toc_entry->name);
 	printf("\n");
 	printf("If no options are provided, all images will be unpacked.\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int remove_cmd(int argc, char *argv[])
@@ -1017,7 +1017,7 @@
 	int fflag = 0;
 
 	if (argc < 2)
-		remove_usage();
+		remove_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, no_argument);
 	opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -1053,7 +1053,7 @@
 			    filename, sizeof(filename));
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0)
-				remove_usage();
+				remove_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -1071,7 +1071,7 @@
 			snprintf(outfile, sizeof(outfile), "%s", optarg);
 			break;
 		default:
-			remove_usage();
+			remove_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -1079,7 +1079,7 @@
 	free(opts);
 
 	if (argc == 0)
-		remove_usage();
+		remove_usage(EXIT_SUCCESS);
 
 	if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag)
 		log_errx("File %s already exists, use --force to overwrite it",
@@ -1110,7 +1110,7 @@
 	return 0;
 }
 
-static void remove_usage(void)
+static void remove_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -1126,7 +1126,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int version_cmd(int argc, char *argv[])
@@ -1140,10 +1140,10 @@
 	return 0;
 }
 
-static void version_usage(void)
+static void version_usage(int exit_status)
 {
 	printf("fiptool version\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int help_cmd(int argc, char *argv[])
@@ -1157,7 +1157,7 @@
 	for (i = 0; i < NELEM(cmds); i++) {
 		if (strcmp(cmds[i].name, argv[0]) == 0 &&
 		    cmds[i].usage != NULL)
-			cmds[i].usage();
+			cmds[i].usage(EXIT_SUCCESS);
 	}
 	if (i == NELEM(cmds))
 		printf("No help for subcommand '%s'\n", argv[0]);
@@ -1178,7 +1178,7 @@
 	printf("  remove\tRemove images from FIP.\n");
 	printf("  version\tShow fiptool version.\n");
 	printf("  help\t\tShow help for given command.\n");
-	exit(1);
+	exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h
index af3fcbd..88c4a7e 100644
--- a/tools/fiptool/fiptool.h
+++ b/tools/fiptool/fiptool.h
@@ -48,7 +48,7 @@
 typedef struct cmd {
 	char              *name;
 	int              (*handler)(int, char **);
-	void             (*usage)(void);
+	void             (*usage)(int);
 } cmd_t;
 
 #endif /* FIPTOOL_H */
diff --git a/tools/marvell/doimage/doimage.c b/tools/marvell/doimage/doimage.c
index 82fd375..e08b820 100644
--- a/tools/marvell/doimage/doimage.c
+++ b/tools/marvell/doimage/doimage.c
@@ -51,7 +51,7 @@
 /* Number of address pairs in control array */
 #define CP_CTRL_EL_ARRAY_SZ	32
 
-#define VERSION_STRING		"Marvell(C) doimage utility version 3.2"
+#define VERSION_STRING		"Marvell(C) doimage utility version 3.3"
 
 /* A8K definitions */
 
@@ -303,7 +303,7 @@
 				MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
 
 	/* First compute the SHA256 hash for the input blob */
-	mbedtls_sha256(input, ilen, hash, 0);
+	mbedtls_sha256_ret(input, ilen, hash, 0);
 
 	/* Then calculate the hash signature */
 	rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx),
@@ -354,6 +354,7 @@
 	mbedtls_pk_context		pk_ctx;
 	unsigned char			hash[32];
 	int				rval;
+	unsigned char			*pkey = (unsigned char *)pub_key;
 
 	/* Not sure this is required,
 	 * but it's safer to start with empty buffer
@@ -373,8 +374,7 @@
 	}
 
 	/* Check ability to read the public key */
-	rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key,
-					   MAX_RSA_DER_BYTE_LEN);
+	rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx);
 	if (rval != 0) {
 		fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n",
 			rval);
@@ -387,7 +387,7 @@
 				MBEDTLS_MD_SHA256);
 
 	/* Compute the SHA256 hash for the input buffer */
-	mbedtls_sha256(input, ilen, hash, 0);
+	mbedtls_sha256_ret(input, ilen, hash, 0);
 
 	rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx),
 					     mbedtls_ctr_drbg_random,
@@ -458,7 +458,7 @@
 	/* compute SHA-256 digest of the results
 	 * and use it as the init vector (IV)
 	 */
-	mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0);
+	mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0);
 	memcpy(IV, digest, AES_BLOCK_SZ);
 	mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key,
 			       AES_KEY_BIT_LEN);
@@ -880,11 +880,13 @@
 				fname);
 			return 1;
 		}
+
 		/* Data in the output buffer is aligned to the buffer end */
 		der_buf_start = output_buf + sizeof(output_buf) - output_len;
 		/* In the header DER data is aligned
 		 * to the start of appropriate field
 		 */
+		bzero(out_der_key, MAX_RSA_DER_BYTE_LEN);
 		memcpy(out_der_key, der_buf_start, output_len);
 
 	} /* for every private key file */
@@ -899,8 +901,10 @@
 		fprintf(stderr, "Failed to sign CSK keys block!\n");
 		return 1;
 	}
+
 	/* Check that everything is correct */
-	if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN,
+	if (verify_rsa_signature(sec_ext.kak_key,
+				 MAX_RSA_DER_BYTE_LEN,
 				 &sec_ext.csk_keys[0][0],
 				 sizeof(sec_ext.csk_keys),
 				 opts.sec_opts->kak_key_file,
@@ -1333,7 +1337,7 @@
 					goto error;
 				}
 
-				mbedtls_sha256(sec_entry->kak_key,
+				mbedtls_sha256_ret(sec_entry->kak_key,
 					       MAX_RSA_DER_BYTE_LEN, hash, 0);
 				fprintf(stdout,
 					">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n");
@@ -1559,13 +1563,9 @@
 
 int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd)
 {
-	int aligned_size;
 	int written;
 
-	/* Image size must be aligned to 4 bytes */
-	aligned_size = (image_size + 3) & (~0x3);
-
-	written = fwrite(buf, aligned_size, 1, out_fd);
+	written = fwrite(buf, image_size, 1, out_fd);
 	if (written != 1) {
 		fprintf(stderr, "Error: Failed to write boot image\n");
 		goto error;
@@ -1587,7 +1587,7 @@
 	int ext_cnt = 0;
 	int opt;
 	int ret = 0;
-	int image_size;
+	int image_size, file_size;
 	uint8_t *image_buf = NULL;
 	int read;
 	size_t len;
@@ -1683,16 +1683,18 @@
 		goto main_exit;
 	}
 
-	/* Read the input file to buffer */
-	image_size = get_file_size(in_file);
-	image_buf = calloc((image_size + AES_BLOCK_SZ - 1) &
-			   ~(AES_BLOCK_SZ - 1), 1);
+	/* Read the input file to buffer
+	 * Always align the image to 16 byte boundary
+	 */
+	file_size  = get_file_size(in_file);
+	image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1);
+	image_buf  = calloc(image_size, 1);
 	if (image_buf == NULL) {
 		fprintf(stderr, "Error: failed allocating input buffer\n");
 		return 1;
 	}
 
-	read = fread(image_buf, image_size, 1, in_fd);
+	read = fread(image_buf, file_size, 1, in_fd);
 	if (read != 1) {
 		fprintf(stderr, "Error: failed to read input file\n");
 		goto main_exit;