Merge "qemu: define ARMV7_SUPPORTS_VFP" into integration
diff --git a/docs/design/trusted-board-boot-build.rst b/docs/design/trusted-board-boot-build.rst
index 2025243..f5c8bc9 100644
--- a/docs/design/trusted-board-boot-build.rst
+++ b/docs/design/trusted-board-boot-build.rst
@@ -33,7 +33,7 @@
    -  ``GENERATE_COT=1``
 
    In the case of Arm platforms, the location of the ROTPK hash must also be
-   specified at build time. Two locations are currently supported (see
+   specified at build time. The following locations are currently supported (see
    ``ARM_ROTPK_LOCATION`` build option):
 
    -  ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted
@@ -41,17 +41,16 @@
       registers are read-only. On FVP Base and Cortex models, the registers
       are read-only, but the value can be specified using the command line
       option ``bp.trusted_key_storage.public_key`` when launching the model.
-      On both Juno and FVP models, the default value corresponds to an
-      ECDSA-SECP256R1 public key hash, whose private part is not currently
-      available.
+      On Juno board, the default value corresponds to an ECDSA-SECP256R1 public
+      key hash, whose private part is not currently available.
 
-   -  ``ARM_ROTPK_LOCATION=devel_rsa``: use the ROTPK hash that is hardcoded
-      in the Arm platform port. The private/public RSA key pair may be
-      found in ``plat/arm/board/common/rotpk``.
+   -  ``ARM_ROTPK_LOCATION=devel_rsa``: use the default hash located in
+      plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin. Enforce generation
+      of the new hash if ROT_KEY is specified.
 
-   -  ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the ROTPK hash that is hardcoded
-      in the Arm platform port. The private/public ECDSA key pair may be
-      found in ``plat/arm/board/common/rotpk``.
+   -  ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the default hash located in
+      plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin. Enforce generation
+      of the new hash if ROT_KEY is specified.
 
    Example of command line using RSA development keys:
 
@@ -108,7 +107,7 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
 
 .. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git
 .. _mbed TLS Security Center: https://tls.mbed.org/security
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index e9747af..ca30535 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -468,7 +468,8 @@
    entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0.
 
 -  ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the ROT private key in PEM format. If ``SAVE_KEYS=1``, this
+   file that contains the ROT private key in PEM format and enforces public key
+   hash generation. If ``SAVE_KEYS=1``, this
    file name will be used to save the key.
 
 -  ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index d24ad23..9622de6 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -57,8 +57,7 @@
    ``ARM_ROTPK_LOCATION`` are:
 
    -  ``regs`` : return the ROTPK hash stored in the Trusted root-key storage
-      registers. The private key corresponding to this ROTPK hash is not
-      currently available.
+      registers.
    -  ``devel_rsa`` : return a development public key hash embedded in the BL1
       and BL2 binaries. This hash has been obtained from the RSA public key
       ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use
@@ -70,6 +69,12 @@
       use this option, ``arm_rotprivk_ecdsa.pem`` must be specified as
       ``ROT_KEY`` when creating the certificates.
 
+-  ``ARM_ROTPK_HASH``: used when ``ARM_ROTPK_LOCATION=devel_*``. Specifies the
+   location of the ROTPK hash. Not expected to be a build option. This defaults to
+   ``plat/arm/board/common/rotpk/*_sha256.bin`` depending on the specified algorithm.
+   Providing ``ROT_KEY`` enforces generation of the hash from the ``ROT_KEY`` and
+   overwrites the default hash file.
+
 -  ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options:
 
    -  ``tsram`` : Trusted SRAM (default option when TBB is not enabled)
@@ -109,6 +114,11 @@
    management operations and for SCP RAM Firmware transfer. If this option
    is set to 1, then SCMI/SDS drivers will be used. Default is 0.
 
+ - ``CSS_SGI_CHIP_COUNT``: Configures the number of chips on a SGI/RD platform
+   which supports multi-chip operation. If ``CSS_SGI_CHIP_COUNT`` is set to any
+   valid value greater than 1, the platform code performs required configuration
+   to support multi-chip operation.
+
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 5bd53f3..c825bf4 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -18,6 +18,12 @@
  * Definitions common to all ARM standard platforms
  *****************************************************************************/
 
+/*
+ * Root of trust key hash lengths
+ */
+#define ARM_ROTPK_HEADER_LEN		19
+#define ARM_ROTPK_HASH_LEN		32
+
 /* Special value used to verify platform parameters from BL2 to BL31 */
 #define ARM_BL31_PLAT_PARAM_VAL		ULL(0x0f1e2d3c4b5a6978)
 
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 02feec7..32dc9f9 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -142,6 +142,11 @@
 #define STATE_SW_E_PARAM		(-2)
 #define STATE_SW_E_DENIED		(-3)
 
+/* plat_get_rotpk_info() flags */
+#define ARM_ROTPK_REGS_ID		1
+#define ARM_ROTPK_DEVEL_RSA_ID		2
+#define ARM_ROTPK_DEVEL_ECDSA_ID	3
+
 /* IO storage utility functions */
 void arm_io_setup(void);
 
@@ -255,9 +260,17 @@
 __dead2 void plat_arm_error_handler(int err);
 
 /*
- * Optional function in ARM standard platforms
+ * Optional functions in ARM standard platforms
  */
 void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames);
+int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
+int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
+int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
+int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
 
 #if ARM_PLAT_MT
 unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr);
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index c71e932..3c19230 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,130 +8,61 @@
 #include <stdint.h>
 #include <string.h>
 
+#include <common/debug.h>
+#include <drivers/arm/cryptocell/cc_rotpk.h>
+#include <drivers/delay_timer.h>
 #include <lib/cassert.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
 #include <plat/common/platform.h>
-#include <tools_share/tbbr_oid.h>
 #include <platform_def.h>
-
-/* SHA256 algorithm */
-#define SHA256_BYTES			32
-
-/* ROTPK locations */
-#define ARM_ROTPK_REGS_ID		1
-#define ARM_ROTPK_DEVEL_RSA_ID		2
-#define ARM_ROTPK_DEVEL_ECDSA_ID	3
+#include <tools_share/tbbr_oid.h>
 
-static const unsigned char rotpk_hash_hdr[] =		\
-		"\x30\x31\x30\x0D\x06\x09\x60\x86\x48"	\
-		"\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
-static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1;
-static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES];
 
-/* Use the cryptocell variants if Cryptocell is present */
 #if !ARM_CRYPTOCELL_INTEG
 #if !ARM_ROTPK_LOCATION_ID
   #error "ARM_ROTPK_LOCATION_ID not defined"
 #endif
+#endif
 
 /* Weak definition may be overridden in specific platform */
 #pragma weak plat_get_nv_ctr
 #pragma weak plat_set_nv_ctr
 
-#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
-static const unsigned char arm_devel_rotpk_hash[] =	\
-		"\xB0\xF3\x82\x09\x12\x97\xD8\x3A"	\
-		"\x37\x7A\x72\x47\x1B\xEC\x32\x73"	\
-		"\xE9\x92\x32\xE2\x49\x59\xF6\x5E"	\
-		"\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
-#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
-static const unsigned char arm_devel_rotpk_hash[] =	\
-		"\x2E\x40\xBF\x6E\xF9\x12\xBB\x98"	\
-		"\x31\x71\x09\x0E\x1E\x15\x3D\x0B"	\
-		"\xFD\xD1\xCC\x69\x4A\x98\xEB\x8B"	\
-		"\xA0\xB0\x20\x86\x4E\x6C\x07\x17";
-#endif
+extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[];
+
+static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
 
 /*
- * 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
- * }
+ * Return the ROTPK hash stored in dedicated registers.
  */
-int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
 	uint8_t *dst;
+	uint32_t *src, tmp;
+	unsigned int words, i;
 
 	assert(key_ptr != NULL);
 	assert(key_len != NULL);
 	assert(flags != NULL);
 
 	/* Copy the DER header */
-	memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
-	dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
 
-#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
-	|| (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
-	memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
-#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
-	uint32_t *src, tmp;
-	unsigned int words, i;
+	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+	dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
 
-	/*
-	 * Append the hash from Trusted Root-Key Storage registers. The hash has
-	 * not been written linearly into the registers, so we have to do a bit
-	 * of byte swapping:
-	 *
-	 *     0x00    0x04    0x08    0x0C    0x10    0x14    0x18    0x1C
-	 * +---------------------------------------------------------------+
-	 * | Reg0  | Reg1  | Reg2  | Reg3  | Reg4  | Reg5  | Reg6  | Reg7  |
-	 * +---------------------------------------------------------------+
-	 *  | ...                    ... |   | ...                   ...  |
-	 *  |       +--------------------+   |                    +-------+
-	 *  |       |                        |                    |
-	 *  +----------------------------+   +----------------------------+
-	 *          |                    |                        |       |
-	 *  +-------+                    |   +--------------------+       |
-	 *  |                            |   |                            |
-	 *  v                            v   v                            v
-	 * +---------------------------------------------------------------+
-	 * |                               |                               |
-	 * +---------------------------------------------------------------+
-	 *  0                           15  16                           31
-	 *
-	 * Additionally, we have to access the registers in 32-bit words
-	 */
-	words = SHA256_BYTES >> 3;
+	words = ARM_ROTPK_HASH_LEN >> 2;
 
-	/* Swap bytes 0-15 (first four registers) */
 	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
 	for (i = 0 ; i < words ; i++) {
 		tmp = src[words - 1 - i];
 		/* Words are read in little endian */
-		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
-		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
-		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
 		*dst++ = (uint8_t)(tmp & 0xFF);
-	}
-
-	/* Swap bytes 16-31 (last four registers) */
-	src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2);
-	for (i = 0 ; i < words ; i++) {
-		tmp = src[words - 1 - i];
-		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
-		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
 		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
-		*dst++ = (uint8_t)(tmp & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
 	}
-#endif /* (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
-		  || (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) */
 
 	*key_ptr = (void *)rotpk_hash_der;
 	*key_len = (unsigned int)sizeof(rotpk_hash_der);
@@ -139,6 +70,65 @@
 	return 0;
 }
 
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+    (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+/*
+ * Return development ROTPK hash generated from ROT_KEY.
+ */
+int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	*key_ptr = arm_rotpk_header;
+	*key_len = arm_rotpk_hash_end - arm_rotpk_header;
+	*flags = ROTPK_IS_HASH;
+	return 0;
+}
+#endif
+
+#if ARM_CRYPTOCELL_INTEG
+/*
+ * Return ROTPK hash from CryptoCell.
+ */
+int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	unsigned char *dst;
+
+	assert(key_ptr != NULL);
+	assert(key_len != NULL);
+	assert(flags != NULL);
+
+	/* Copy the DER header */
+	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+	dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+	*key_ptr = rotpk_hash_der;
+	*key_len = sizeof(rotpk_hash_der);
+	return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags);
+}
+#endif
+
+/*
+ * Wraper function for most Arm platforms to get ROTPK hash.
+ */
+int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+#if ARM_CRYPTOCELL_INTEG
+	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
+#else
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+    (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+	return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+	return arm_get_rotpk_info_regs(key_ptr, key_len, flags);
+#else
+	return 1;
+#endif
+
+#endif /* ARM_CRYPTOCELL_INTEG */
+}
+
 /*
  * Return the non-volatile counter value stored in the platform. The cookie
  * will contain the OID of the counter in the certificate.
@@ -179,37 +169,3 @@
 {
 	return 1;
 }
-#else /* ARM_CRYPTOCELL_INTEG */
-
-#include <drivers/arm/cryptocell/cc_rotpk.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)
-{
-	unsigned char *dst;
-
-	assert(key_ptr != NULL);
-	assert(key_len != NULL);
-	assert(flags != NULL);
-
-	/* Copy the DER header */
-	memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
-	dst = &rotpk_hash_der[rotpk_hash_hdr_len];
-	*key_ptr = rotpk_hash_der;
-	*key_len = sizeof(rotpk_hash_der);
-	return cc_get_rotpk_hash(dst, SHA256_BYTES, flags);
-}
-#endif /* ARM_CRYPTOCELL_INTEG */
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index b98dfd4..da63430 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -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
 #
@@ -12,31 +12,60 @@
 BL2_SOURCES		+=	drivers/cfi/v2m/v2m_flash.c
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
-  ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
-    # ROTPK hash location
-    ifeq (${ARM_ROTPK_LOCATION}, regs)
-        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
-    else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
-        KEY_ALG := rsa
-        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
-    else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
-        KEY_ALG := ecdsa
-        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
-    else
-        $(error "Unsupported ARM_ROTPK_LOCATION value")
-    endif
-    $(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
+# ROTPK hash location
+ifeq (${ARM_ROTPK_LOCATION}, regs)
+	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
+else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
+	KEY_ALG := rsa
+	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
+	ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin
+$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
+$(warning Development keys support for FVP is deprecated. Use `regs` \
+option instead)
+else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
+	KEY_ALG := ecdsa
+	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
+	ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
+$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
+$(warning Development keys support for FVP is deprecated. Use `regs` \
+option instead)
+else
+	$(error "Unsupported ARM_ROTPK_LOCATION value")
+endif
+
+$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+
+# Force generation of the new hash if ROT_KEY is specified
+ifdef ROT_KEY
+	HASH_PREREQUISITES = $(ROT_KEY) FORCE
+FORCE:
+else
+	HASH_PREREQUISITES = $(ROT_KEY)
+endif
+
+$(ARM_ROTPK_HASH) : $(HASH_PREREQUISITES)
+ifndef ROT_KEY
+	$(error Cannot generate hash: no ROT_KEY defined)
+endif
+	openssl rsa -in $< -pubout -outform DER | openssl dgst \
+		-sha256 -binary > $@
+
+# Certificate NV-Counters. Use values corresponding to tied off values in
+# ARM development platforms
+TFW_NVCTR_VAL	?=	31
+NTFW_NVCTR_VAL	?=	223
+else
+# Certificate NV-Counters when CryptoCell is integrated. For development
+# platforms we set the counter to first valid value.
+TFW_NVCTR_VAL	?=	0
+NTFW_NVCTR_VAL	?=	0
+endif
+BL1_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c \
+				plat/arm/board/common/rotpk/arm_dev_rotpk.S
+BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c \
+				plat/arm/board/common/rotpk/arm_dev_rotpk.S
 
-    # Certificate NV-Counters. Use values corresponding to tied off values in
-    # ARM development platforms
-    TFW_NVCTR_VAL	?=	31
-    NTFW_NVCTR_VAL	?=	223
-  else
-    # Certificate NV-Counters when CryptoCell is integrated. For development
-    # platforms we set the counter to first valid value.
-    TFW_NVCTR_VAL	?=	0
-    NTFW_NVCTR_VAL	?=	0
-  endif
-    BL1_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c
-    BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c
 endif
diff --git a/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
new file mode 100644
index 0000000..80f2192
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "plat/arm/common/arm_def.h"
+
+	.global arm_rotpk_header
+	.global arm_rotpk_header_end
+	.section .rodata.arm_rotpk_hash, "a"
+
+arm_rotpk_header:
+	.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+	.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+arm_rotpk_header_len:
+
+#ifdef ARM_ROTPK_HASH
+	.global arm_rotpk_hash_end
+	.incbin ARM_ROTPK_HASH
+arm_rotpk_hash_end:
+#endif
+
+.if ARM_ROTPK_HEADER_LEN != arm_rotpk_header_len - arm_rotpk_header
+.error "Invalid ROTPK header length."
+.endif
diff --git a/plat/arm/board/fvp/fvp_trusted_boot.c b/plat/arm/board/fvp/fvp_trusted_boot.c
index dc50764..a09b80e 100644
--- a/plat/arm/board/fvp/fvp_trusted_boot.c
+++ b/plat/arm/board/fvp/fvp_trusted_boot.c
@@ -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
  */
@@ -9,12 +9,31 @@
 #include <string.h>
 
 #include <lib/mmio.h>
-
+#include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
 #include <tools_share/tbbr_oid.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(key_ptr, key_len, flags);
+}
+
+/*
  * Store a new non-volatile counter value.
  *
  * On some FVP versions, the non-volatile counters are read-only so this
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 97a326c..6fb34c4 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -139,7 +139,6 @@
 				plat/arm/board/fvp/fvp_bl1_setup.c		\
 				plat/arm/board/fvp/fvp_err.c			\
 				plat/arm/board/fvp/fvp_io_storage.c		\
-				plat/arm/board/fvp/fvp_trusted_boot.c		\
 				${FVP_CPU_LIBS}					\
 				${FVP_INTERCONNECT_SOURCES}
 
@@ -158,7 +157,6 @@
 				plat/arm/board/fvp/fvp_bl2_setup.c		\
 				plat/arm/board/fvp/fvp_err.c			\
 				plat/arm/board/fvp/fvp_io_storage.c		\
-				plat/arm/board/fvp/fvp_trusted_boot.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c	\
 				${FVP_SECURITY_SOURCES}
 
@@ -302,8 +300,10 @@
 include plat/arm/board/common/board_common.mk
 include plat/arm/common/arm_common.mk
 
+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
 # FVP being a development platform, enable capability to disable Authentication
 # dynamically if TRUSTED_BOARD_BOOT is set.
-ifeq (${TRUSTED_BOARD_BOOT}, 1)
-        DYN_DISABLE_AUTH	:=	1
+DYN_DISABLE_AUTH	:=	1
 endif
diff --git a/plat/arm/board/juno/juno_trusted_boot.c b/plat/arm/board/juno/juno_trusted_boot.c
new file mode 100644
index 0000000..25a7470
--- /dev/null
+++ b/plat/arm/board/juno/juno_trusted_boot.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/arm/cryptocell/cc_rotpk.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+
+static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
+
+extern unsigned char arm_rotpk_header[];
+
+/*
+ * Return the ROTPK hash stored in the registers of Juno board.
+ */
+static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	uint8_t *dst;
+	uint32_t *src, tmp;
+	unsigned int words, i;
+
+	assert(key_ptr != NULL);
+	assert(key_len != NULL);
+	assert(flags != NULL);
+
+	/* Copy the DER header */
+	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+	dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+
+
+	/*
+	 * Append the hash from Trusted Root-Key Storage registers. The hash has
+	 * not been written linearly into the registers, so we have to do a bit
+	 * of byte swapping:
+	 *
+	 *     0x00    0x04    0x08    0x0C    0x10    0x14    0x18    0x1C
+	 * +---------------------------------------------------------------+
+	 * | Reg0  | Reg1  | Reg2  | Reg3  | Reg4  | Reg5  | Reg6  | Reg7  |
+	 * +---------------------------------------------------------------+
+	 *  | ...                    ... |   | ...                   ...  |
+	 *  |       +--------------------+   |                    +-------+
+	 *  |       |                        |                    |
+	 *  +----------------------------+   +----------------------------+
+	 *          |                    |                        |       |
+	 *  +-------+                    |   +--------------------+       |
+	 *  |                            |   |                            |
+	 *  v                            v   v                            v
+	 * +---------------------------------------------------------------+
+	 * |                               |                               |
+	 * +---------------------------------------------------------------+
+	 *  0                           15  16                           31
+	 *
+	 * Additionally, we have to access the registers in 32-bit words
+	 */
+	words = ARM_ROTPK_HASH_LEN >> 3;
+
+	/* Swap bytes 0-15 (first four registers) */
+	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
+	for (i = 0 ; i < words ; i++) {
+		tmp = src[words - 1 - i];
+		/* Words are read in little endian */
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+		*dst++ = (uint8_t)(tmp & 0xFF);
+	}
+
+	/* Swap bytes 16-31 (last four registers) */
+	src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2);
+	for (i = 0 ; i < words ; i++) {
+		tmp = src[words - 1 - i];
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+		*dst++ = (uint8_t)(tmp & 0xFF);
+	}
+
+	*key_ptr = (void *)rotpk_hash_der;
+	*key_len = (unsigned int)sizeof(rotpk_hash_der);
+	*flags = ROTPK_IS_HASH;
+	return 0;
+}
+
+#endif
+
+/*
+ * 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)
+{
+#if ARM_CRYPTOCELL_INTEG
+	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
+#else
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+    (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+	return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+	return juno_get_rotpk_info_regs(key_ptr, key_len, flags);
+#else
+	return 1;
+#endif
+
+#endif /* ARM_CRYPTOCELL_INTEG */
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index bd6bae5..a85ad53 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -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
 #
@@ -91,6 +91,11 @@
 BL1_SOURCES		+=	drivers/arm/css/sds/sds.c
 endif
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	plat/arm/board/juno/juno_trusted_boot.c
+BL2_SOURCES		+=	plat/arm/board/juno/juno_trusted_boot.c
+endif
+
 endif
 
 ifneq (${RESET_TO_BL31},0)
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index 43c37ff..88aa634 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -29,6 +29,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDE1EDGE_BASE}/rde1edge_trusted_boot.c
+BL2_SOURCES		+=	${RDE1EDGE_BASE}/rde1edge_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
 FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
 TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
@@ -42,4 +47,9 @@
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
 
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error  "Chip count for RDE1Edge should be 1, currently set to \
+   ${CSS_SGI_CHIP_COUNT}.")
+endif
+
 override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rde1edge/rde1edge_topology.c b/plat/arm/board/rde1edge/rde1edge_topology.c
index 0b56f20..a16283e 100644
--- a/plat/arm/board/rde1edge/rde1edge_topology.c
+++ b/plat/arm/board/rde1edge/rde1edge_topology.c
@@ -7,12 +7,15 @@
 #include <plat/arm/common/plat_arm.h>
 
 /******************************************************************************
- * The power domain tree descriptor.
+ * The power domain tree descriptor. RD-E1-Edge platform consists of two
+ * clusters with eight CPUs in each cluster. The CPUs are multi-threaded with
+ * two threads per CPU.
  ******************************************************************************/
 static const unsigned char rde1edge_pd_tree_desc[] = {
+	CSS_SGI_CHIP_COUNT,
 	PLAT_ARM_CLUSTER_COUNT,
-	CSS_SGI_MAX_CPUS_PER_CLUSTER,
-	CSS_SGI_MAX_CPUS_PER_CLUSTER
+	CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU
 };
 
 /******************************************************************************
diff --git a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_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(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index ca1e95e..90e9338 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -29,6 +29,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c
+BL2_SOURCES		+=	${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
 FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
 TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
@@ -42,4 +47,9 @@
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
 
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error  "Chip count for RDN1Edge should be 1, currently set to \
+   ${CSS_SGI_CHIP_COUNT}.")
+endif
+
 override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_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(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index ce2717f..76cc4e2 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -29,6 +29,11 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${SGI575_BASE}/sgi575_trusted_boot.c
+BL2_SOURCES		+=	${SGI575_BASE}/sgi575_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
 FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
 TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
@@ -41,3 +46,8 @@
 
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error  "Chip count for SGI575 should be 1, currently set to \
+   ${CSS_SGI_CHIP_COUNT}.")
+endif
diff --git a/plat/arm/board/sgi575/sgi575_trusted_boot.c b/plat/arm/board/sgi575/sgi575_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_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(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/sgm775/platform.mk b/plat/arm/board/sgm775/platform.mk
index 7a843c3..f096ca5 100644
--- a/plat/arm/board/sgm775/platform.mk
+++ b/plat/arm/board/sgm775/platform.mk
@@ -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
 #
@@ -21,3 +21,8 @@
 BL31_SOURCES		+=	drivers/cfi/v2m/v2m_flash.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${SGM775_BASE}/sgm775_trusted_boot.c
+BL2_SOURCES		+=	${SGM775_BASE}/sgm775_trusted_boot.c
+endif
diff --git a/plat/arm/board/sgm775/sgm775_trusted_boot.c b/plat/arm/board/sgm775/sgm775_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/sgm775/sgm775_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(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 7160111..40a7fd8 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -16,6 +16,8 @@
 
 HANDLE_EA_EL3_FIRST		:=	0
 
+CSS_SGI_CHIP_COUNT		:=	1
+
 INTERCONNECT_SOURCES	:=	${CSS_ENT_BASE}/sgi_interconnect.c
 
 PLAT_INCLUDES		+=	-I${CSS_ENT_BASE}/include
@@ -52,6 +54,8 @@
 
 $(eval $(call add_define,SGI_PLAT))
 
+$(eval $(call add_define,CSS_SGI_CHIP_COUNT))
+
 override CSS_LOAD_SCP_IMAGES	:=	0
 override NEED_BL2U		:=	no
 override ARM_BL31_IN_DRAM	:=	1
diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c
index 13099b4..4b11440 100644
--- a/plat/intel/soc/agilex/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex/bl31_plat_setup.c
@@ -14,6 +14,7 @@
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables.h>
 
+#include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 
 static entry_point_info_t bl32_image_ep_info;
@@ -107,6 +108,8 @@
 	/* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
 	mmio_write_64(PLAT_CPU_RELEASE_ADDR,
 		(uint64_t)plat_secondary_cpus_bl31_entry);
+
+	mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
 }
 
 const mmap_region_t plat_agilex_mmap[] = {
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index c4b9e59..38f4696 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -73,6 +73,29 @@
 /* Mailbox REBOOT commands */
 #define MBOX_CMD_REBOOT_HPS		71
 
+/* Mailbox RSU commands */
+#define MBOX_GET_SUBPARTITION_TABLE	90
+#define MBOX_RSU_STATUS			91
+#define MBOX_RSU_UPDATE			92
+
+/* Mailbox RSU macros */
+#define RSU_VERSION_ACMF		BIT(8)
+#define RSU_VERSION_ACMF_MASK		0xff00
+
+/* HPS stage notify command */
+#define MBOX_HPS_STAGE_NOTIFY		93
+
+/* Execution states for HPS_STAGE_NOTIFY */
+#define HPS_EXECUTION_STATE_FSBL	0
+#define HPS_EXECUTION_STATE_SSBL	1
+#define HPS_EXECUTION_STATE_OS		2
+
+/* Mailbox reconfiguration commands */
+#define MBOX_CONFIG_STATUS		4
+#define MBOX_RECONFIG			6
+#define MBOX_RECONFIG_DATA		8
+#define MBOX_RECONFIG_STATUS		9
+
 /* Generic error handling */
 #define MBOX_TIMEOUT			-2047
 #define MBOX_NO_RESPONSE		-2
@@ -98,13 +121,6 @@
 #define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO		0xf0000007
 #define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR		0xf0000008
 
-/* Mailbox reconfiguration commands */
-#define MBOX_CONFIG_STATUS	4
-#define MBOX_RECONFIG		6
-#define MBOX_RECONFIG_DATA	8
-#define MBOX_RECONFIG_STATUS	9
-
-
 void mailbox_set_int(int interrupt_input);
 int mailbox_init(void);
 void mailbox_set_qspi_close(void);
@@ -122,4 +138,9 @@
 uint32_t intel_mailbox_get_config_status(uint32_t cmd);
 int intel_mailbox_is_fpga_not_ready(void);
 
+int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_update(uint32_t *flash_offset);
+int mailbox_hps_stage_notify(uint32_t execution_stage);
+
 #endif /* SOCFPGA_MBOX_H */
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 6bb41f3..2b1d983 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -28,6 +28,7 @@
 #define INTEL_SIP_LEGACY_SMC_ECC_DBE			0xC200000D
 #define INTEL_SIP_SMC_RSU_NOTIFY			0xC200000E
 #define INTEL_SIP_SMC_RSU_RETRY_COUNTER			0xC200000F
+#define INTEL_SIP_SMC_MBOX_SEND_CMD			0xC200001E
 
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR			0x400000
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index 8d7c1d6..673c2d5 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -267,6 +267,55 @@
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0, 0, 0, NULL, 0);
 }
 
+int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len)
+{
+	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE,
+				NULL, 0, 0, (uint32_t *)resp_buf,
+				resp_buf_len);
+}
+
+struct rsu_status_info {
+	uint64_t current_image;
+	uint64_t fail_image;
+	uint32_t state;
+	uint32_t version;
+	uint32_t error_location;
+	uint32_t error_details;
+	uint32_t retry_counter;
+};
+
+int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len)
+{
+	int ret;
+	struct rsu_status_info *info = (struct rsu_status_info *)resp_buf;
+
+	info->retry_counter = ~0;
+
+	ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0, 0,
+			       (uint32_t *)resp_buf, resp_buf_len);
+
+	if (ret < 0)
+		return ret;
+
+	if (info->retry_counter != ~0)
+		if (!(info->version & RSU_VERSION_ACMF_MASK))
+			info->version |= RSU_VERSION_ACMF;
+
+	return ret;
+}
+
+int mailbox_rsu_update(uint32_t *flash_offset)
+{
+	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
+				(uint32_t *)flash_offset, 2, 0, NULL, 0);
+}
+
+int mailbox_hps_stage_notify(uint32_t execution_stage)
+{
+	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
+				&execution_stage, 1, 0, NULL, 0);
+}
+
 int mailbox_init(void)
 {
 	int status = 0;
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index d8a6c19..d27ab9f 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -130,9 +130,14 @@
 	panic();
 }
 
+extern uint64_t intel_rsu_update_address;
+
 static void __dead2 socfpga_system_reset(void)
 {
-	mailbox_reset_cold();
+	if (intel_rsu_update_address)
+		mailbox_rsu_update((uint32_t *)&intel_rsu_update_address);
+	else
+		mailbox_reset_cold();
 
 	while (1)
 		wfi();
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 41dae9e..b4fe6d6 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -365,6 +365,61 @@
 	return INTEL_SIP_SMC_STATUS_ERROR;
 }
 
+/* Intel Remote System Update (RSU) services */
+uint64_t intel_rsu_update_address;
+
+static uint32_t intel_rsu_status(uint64_t *respbuf, uint32_t respbuf_sz)
+{
+	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
+		return INTEL_SIP_SMC_STATUS_ERROR;
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_update(uint64_t update_address)
+{
+	intel_rsu_update_address = update_address;
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_notify(uint64_t execution_stage)
+{
+	if (mailbox_hps_stage_notify((uint32_t)execution_stage) < 0)
+		return INTEL_SIP_SMC_STATUS_ERROR;
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_retry_counter(uint32_t *respbuf, uint32_t respbuf_sz,
+					uint32_t *ret_stat)
+{
+	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
+		return INTEL_SIP_SMC_STATUS_ERROR;
+
+	*ret_stat = respbuf[8];
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+/* Mailbox services */
+static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, int len,
+				    int urgent, uint32_t *response,
+				    int resp_len, int *mbox_status,
+				    int *len_in_resp)
+{
+	int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent,
+				      response, resp_len);
+
+	if (status < 0) {
+		*len_in_resp = 0;
+		*mbox_status = -status;
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	*mbox_status = 0;
+	*len_in_resp = status;
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
 /*
  * This function is responsible for handling all SiP calls from the NS world
  */
@@ -381,7 +436,10 @@
 	uint32_t val = 0;
 	uint32_t status = INTEL_SIP_SMC_STATUS_OK;
 	uint32_t completed_addr[3];
+	uint64_t rsu_respbuf[9];
 	uint32_t count = 0;
+	u_register_t x5, x6;
+	int mbox_status, len_in_resp;
 
 	switch (smc_fid) {
 	case SIP_SVC_UID:
@@ -446,6 +504,41 @@
 						 (uint32_t)x3, &val);
 		SMC_RET3(handle, status, val, x1);
 
+	case INTEL_SIP_SMC_RSU_STATUS:
+		status = intel_rsu_status(rsu_respbuf,
+					ARRAY_SIZE(rsu_respbuf));
+		if (status) {
+			SMC_RET1(handle, status);
+		} else {
+			SMC_RET4(handle, rsu_respbuf[0], rsu_respbuf[1],
+					rsu_respbuf[2], rsu_respbuf[3]);
+		}
+
+	case INTEL_SIP_SMC_RSU_UPDATE:
+		status = intel_rsu_update(x1);
+		SMC_RET1(handle, status);
+
+	case INTEL_SIP_SMC_RSU_NOTIFY:
+		status = intel_rsu_notify(x1);
+		SMC_RET1(handle, status);
+
+	case INTEL_SIP_SMC_RSU_RETRY_COUNTER:
+		status = intel_rsu_retry_counter((uint32_t *)rsu_respbuf,
+						ARRAY_SIZE(rsu_respbuf), &val);
+		if (status) {
+			SMC_RET1(handle, status);
+		} else {
+			SMC_RET2(handle, status, val);
+		}
+
+	case INTEL_SIP_SMC_MBOX_SEND_CMD:
+		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+		status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4,
+					     (uint32_t *)x5, x6, &mbox_status,
+					     &len_in_resp);
+		SMC_RET4(handle, status, mbox_status, x5, len_in_resp);
+
 	default:
 		return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
 			cookie, handle, flags);
diff --git a/plat/intel/soc/stratix10/bl31_plat_setup.c b/plat/intel/soc/stratix10/bl31_plat_setup.c
index 29f57c4..4c31238 100644
--- a/plat/intel/soc/stratix10/bl31_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl31_plat_setup.c
@@ -16,6 +16,7 @@
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
+#include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 #include "socfpga_reset_manager.h"
 #include "socfpga_system_manager.h"
@@ -115,6 +116,8 @@
 	/* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
 	mmio_write_64(PLAT_CPU_RELEASE_ADDR,
 		(uint64_t)plat_secondary_cpus_bl31_entry);
+
+	mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
 }
 
 const mmap_region_t plat_stratix10_mmap[] = {