Merge "arm_fpga: Add support for unknown MPIDs" into integration
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index b4fe404..40fc5db 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -300,6 +300,10 @@
    handled at EL3, and a panic will result. This is supported only for AArch64
    builds.
 
+-  ``EVENT_LOG_LEVEL``: Chooses the log level to use for Measured Boot when
+   ``MEASURED_BOOT`` is enabled. For a list of valid values, see ``LOG_LEVEL``.
+   Default value is 40 (LOG_LEVEL_INFO).
+
 -  ``FAULT_INJECTION_SUPPORT``: ARMv8.4 extensions introduced support for fault
    injection from lower ELs, and this build option enables lower ELs to use
    Error Records accessed via System Registers to inject faults. This is
diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/measured_boot.mk
index b7aa48b..497fdba 100644
--- a/drivers/measured_boot/measured_boot.mk
+++ b/drivers/measured_boot/measured_boot.mk
@@ -4,6 +4,9 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Default log level to dump the event log (LOG_LEVEL_INFO)
+EVENT_LOG_LEVEL         ?= 40
+
 # TPM hash algorithm
 TPM_HASH_ALG			:=	sha256
 
@@ -31,6 +34,7 @@
         TPM_ALG_ID \
         TCG_DIGEST_SIZE \
         EVENT_LOG_SIZE \
+        EVENT_LOG_LEVEL \
 )))
 
 ifeq (${HASH_ALG}, sha256)
diff --git a/drivers/mtd/nand/raw_nand.c b/drivers/mtd/nand/raw_nand.c
index 48131fc..1fb5fac 100644
--- a/drivers/mtd/nand/raw_nand.c
+++ b/drivers/mtd/nand/raw_nand.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -190,7 +190,7 @@
 	return ret;
 }
 
-int nand_wait_ready(unsigned long delay)
+int nand_wait_ready(unsigned int delay_ms)
 {
 	uint8_t status;
 	int ret;
@@ -204,7 +204,7 @@
 		return ret;
 	}
 
-	timeout = timeout_init_us(delay);
+	timeout = timeout_init_us(delay_ms * 1000U);
 	while (!timeout_elapsed(timeout)) {
 		ret = nand_read_data(&status, 1U, true);
 		if (ret != 0) {
diff --git a/drivers/mtd/nor/spi_nor.c b/drivers/mtd/nor/spi_nor.c
index 22d3ae3..108f893 100644
--- a/drivers/mtd/nor/spi_nor.c
+++ b/drivers/mtd/nor/spi_nor.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -368,7 +368,7 @@
 	if (nor_dev.read_op.data.buswidth == 4U) {
 		switch (id) {
 		case MACRONIX_ID:
-			WARN("Enable Macronix quad support\n");
+			INFO("Enable Macronix quad support\n");
 			ret = spi_nor_macronix_quad_enable();
 			break;
 		case MICRON_ID:
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index d6cd8b1..f8bc5a2 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -653,15 +653,17 @@
 bool stm32mp1_rcc_is_secure(void)
 {
 	uintptr_t rcc_base = stm32mp_rcc_base();
+	uint32_t mask = RCC_TZCR_TZEN;
 
-	return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0;
+	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
 }
 
 bool stm32mp1_rcc_is_mckprot(void)
 {
 	uintptr_t rcc_base = stm32mp_rcc_base();
+	uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT;
 
-	return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0;
+	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
 }
 
 void stm32mp1_clk_rcc_regs_lock(void)
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 515947c..317fd9e 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -252,6 +252,8 @@
 		mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK,
 				   8U * stm32_remain.length);
 		zeromem(&stm32_remain, sizeof(stm32_remain));
+	} else {
+		mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK);
 	}
 
 	mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL);
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index bb77371..7d63262 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -161,13 +161,14 @@
 	const fdt32_t *cuint;
 	int lenp = 0;
 	uint32_t i;
-	uint8_t status = fdt_get_status(node);
+	uint8_t status;
 	void *fdt;
 
 	if (fdt_get_address(&fdt) == 0) {
 		return -FDT_ERR_NOTFOUND;
 	}
 
+	status = fdt_get_status(node);
 	if (status == DT_DISABLED) {
 		return -FDT_ERR_NOTFOUND;
 	}
diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c
index 44b7d19..0ed7154 100644
--- a/drivers/st/io/io_mmc.c
+++ b/drivers/st/io/io_mmc.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
  */
@@ -97,14 +97,21 @@
 static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
 			  size_t length, size_t *length_read)
 {
-	*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
-				       buffer, length);
+	uint8_t retries;
 
-	if (*length_read != length) {
-		return -EIO;
+	for (retries = 0U; retries < 3U; retries++) {
+		*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
+					       buffer, length);
+
+		if (*length_read == length) {
+			return 0;
+		}
+		WARN("%s: length_read = %lu (!= %lu), retry %u\n", __func__,
+		     (unsigned long)*length_read, (unsigned long)length,
+		     retries + 1U);
 	}
 
-	return 0;
+	return -EIO;
 }
 
 /* Close a file on the mmc device */
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 63fbb07..cff3a34 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -258,6 +258,18 @@
 		break;
 	}
 
+	mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+	/*
+	 * Clear the SDMMC_DCTRLR if the command does not await data.
+	 * Skip CMD55 as the next command could be data related, and
+	 * the register could have been set in prepare function.
+	 */
+	if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) &&
+	    (cmd->cmd_idx != MMC_CMD(55))) {
+		mmio_write_32(base + SDMMC_DCTRLR, 0U);
+	}
+
 	if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
 		mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
 	}
@@ -373,15 +385,15 @@
 
 static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
 {
-	int8_t retry;
-	int err = 0;
+	uint8_t retry;
+	int err;
 
 	assert(cmd != NULL);
 
-	for (retry = 0; retry <= 3; retry++) {
+	for (retry = 0U; retry < 3U; retry++) {
 		err = stm32_sdmmc2_send_cmd_req(cmd);
 		if (err == 0) {
-			return err;
+			return 0;
 		}
 
 		if ((cmd->cmd_idx == MMC_CMD(1)) ||
@@ -390,12 +402,12 @@
 		}
 
 		/* Command 8 is expected to fail for eMMC */
-		if (!(cmd->cmd_idx == MMC_CMD(8))) {
-			WARN(" CMD%d, Retry: %d, Error: %d\n",
-			     cmd->cmd_idx, retry, err);
+		if (cmd->cmd_idx != MMC_CMD(8)) {
+			WARN(" CMD%u, Retry: %u, Error: %d\n",
+			     cmd->cmd_idx, retry + 1U, err);
 		}
 
-		udelay(10);
+		udelay(10U);
 	}
 
 	return err;
diff --git a/fdts/tc0.dts b/fdts/tc0.dts
index ac097cd..15c14ca 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc0.dts
@@ -134,7 +134,7 @@
 		clocks = <&soc_refclk100mhz>;
 		clock-names = "apb_pclk";
 		#mbox-cells = <1>;
-		interrupts = <0 316 4>;
+		interrupts = <0 317 4>;
 		interrupt-names = "mhu_rx";
 		mhu-protocol = "doorbell";
 	};
diff --git a/include/drivers/measured_boot/event_log.h b/include/drivers/measured_boot/event_log.h
index 10dfbb3..efde117 100644
--- a/include/drivers/measured_boot/event_log.h
+++ b/include/drivers/measured_boot/event_log.h
@@ -20,8 +20,6 @@
  * 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
diff --git a/include/drivers/raw_nand.h b/include/drivers/raw_nand.h
index 9018f02..7152300 100644
--- a/include/drivers/raw_nand.h
+++ b/include/drivers/raw_nand.h
@@ -169,7 +169,7 @@
 };
 
 int nand_raw_init(unsigned long long *size, unsigned int *erase_size);
-int nand_wait_ready(unsigned long delay);
+int nand_wait_ready(unsigned int delay_ms);
 int nand_read_page_cmd(unsigned int page, unsigned int offset,
 		       uintptr_t buffer, unsigned int len);
 int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer,
diff --git a/include/drivers/st/etzpc.h b/include/drivers/st/etzpc.h
index 6e3fec1..4cd2b4e 100644
--- a/include/drivers/st/etzpc.h
+++ b/include/drivers/st/etzpc.h
@@ -7,6 +7,9 @@
 #ifndef DRIVERS_ST_ETZPC_H
 #define DRIVERS_ST_ETZPC_H
 
+#include <stdbool.h>
+#include <stdint.h>
+
 /* Define security level for each peripheral (DECPROT) */
 enum etzpc_decprot_attributes {
 	ETZPC_DECPROT_S_RW = 0,
diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h
index 91cbafb..9894483 100644
--- a/include/lib/libc/string.h
+++ b/include/lib/libc/string.h
@@ -27,5 +27,6 @@
 char *strrchr(const char *p, int ch);
 size_t strlcpy(char * dst, const char * src, size_t dsize);
 size_t strlcat(char * dst, const char * src, size_t dsize);
+char *strtok_r(char *s, const char *delim, char **last);
 
 #endif /* STRING_H */
diff --git a/lib/libc/aarch32/memset.S b/lib/libc/aarch32/memset.S
new file mode 100644
index 0000000..880ba83
--- /dev/null
+++ b/lib/libc/aarch32/memset.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.syntax unified
+	.global	memset
+
+/* -----------------------------------------------------------------------
+ * void *memset(void *dst, int val, size_t count)
+ *
+ * Copy the value of 'val' (converted to an unsigned char) into
+ * each of the first 'count' characters of the object pointed to by 'dst'.
+ *
+ * Returns the value of 'dst'.
+ * -----------------------------------------------------------------------
+ */
+func memset
+	mov	r12, r0			/* keep r0 */
+	tst	r0, #3
+	beq	aligned			/* 4-bytes aligned */
+
+	/* Unaligned 'dst' */
+unaligned:
+	subs	r2, r2, #1
+	strbhs	r1, [r12], #1
+	bxls	lr			/* return if 0 */
+	tst	r12, #3
+	bne	unaligned		/* continue while unaligned */
+
+	/* 4-bytes aligned */
+aligned:bfi	r1, r1, #8, #8		/* propagate 'val' */
+	bfi	r1, r1, #16, #16
+
+	mov	r3, r1
+
+	cmp	r2, #16
+	blo	less_16			/* < 16 */
+
+	push	{r4, lr}
+	mov	r4, r1
+	mov	lr, r1
+
+write_32:
+	subs	r2, r2, #32
+	stmiahs	r12!, {r1, r3, r4, lr}
+	stmiahs	r12!, {r1, r3, r4, lr}
+	bhi	write_32		/* write 32 bytes in a loop */
+	popeq	{r4, pc}		/* return if 0 */
+	lsls	r2, r2, #28		/* C = r2[4]; N = r2[3]; Z = r2[3:0] */
+	stmiacs	r12!, {r1, r3, r4, lr}	/* write 16 bytes */
+	popeq	{r4, pc}		/* return if 16 */
+	stmiami	r12!, {r1, r3}		/* write 8 bytes */
+	lsls	r2, r2, #2		/* C = r2[2]; N = r2[1]; Z = r2[1:0] */
+	strcs	r1, [r12], #4		/* write 4 bytes */
+	popeq	{r4, pc}		/* return if 8 or 4 */
+	strhmi	r1, [r12], #2		/* write 2 bytes */
+	lsls	r2, r2, #1		/* N = Z = r2[0] */
+	strbmi	r1, [r12]		/* write 1 byte */
+	pop	{r4, pc}
+
+less_16:lsls	r2, r2, #29		/* C = r2[3]; N = r2[2]; Z = r2[2:0] */
+	stmiacs	r12!, {r1, r3}		/* write 8 bytes */
+	bxeq	lr			/* return if 8 */
+	strmi	r1, [r12], #4		/* write 4 bytes */
+	lsls	r2, r2, #2		/* C = r2[1]; N = Z = r2[0] */
+	strhcs	r1, [r12], #2		/* write 2 bytes */
+	strbmi	r1, [r12]		/* write 1 byte */
+	bx	lr
+
+endfunc memset
diff --git a/lib/libc/aarch64/memset.S b/lib/libc/aarch64/memset.S
new file mode 100644
index 0000000..0543704
--- /dev/null
+++ b/lib/libc/aarch64/memset.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.global	memset
+
+/* -----------------------------------------------------------------------
+ * void *memset(void *dst, int val, size_t count)
+ *
+ * Copy the value of 'val' (converted to an unsigned char) into
+ * each of the first 'count' characters of the object pointed to by 'dst'.
+ *
+ * Returns the value of 'dst'.
+ * -----------------------------------------------------------------------
+ */
+func memset
+	cbz	x2, exit		/* exit if 'count' = 0 */
+	mov	x3, x0			/* keep x0 */
+	tst	x0, #7
+	b.eq	aligned			/* 8-bytes aligned */
+
+	/* Unaligned 'dst' */
+unaligned:
+	strb	w1, [x3], #1
+	subs	x2, x2, #1
+	b.eq	exit			/* exit if 0 */
+	tst	x3, #7
+	b.ne	unaligned		/* continue while unaligned */
+
+	/* 8-bytes aligned */
+aligned:cbz	x1, x1_zero
+	bfi	w1, w1, #8, #8		/* propagate 'val' */
+	bfi	w1, w1, #16, #16
+	bfi	x1, x1, #32, #32
+
+x1_zero:ands	x4, x2, #~0x3f
+	b.eq	less_64
+
+write_64:
+	.rept	4
+	stp	x1, x1, [x3], #16	/* write 64 bytes in a loop */
+	.endr
+	subs	x4, x4, #64
+	b.ne	write_64
+less_64:tbz	w2, #5, less_32		/* < 32 bytes */
+	stp	x1, x1, [x3], #16	/* write 32 bytes */
+	stp	x1, x1, [x3], #16
+less_32:tbz	w2, #4, less_16		/* < 16 bytes */
+	stp	x1, x1, [x3], #16	/* write 16 bytes */
+less_16:tbz	w2, #3, less_8		/* < 8 bytes */
+	str	x1, [x3], #8		/* write 8 bytes */
+less_8:	tbz	w2, #2, less_4		/* < 4 bytes */
+	str	w1, [x3], #4		/* write 4 bytes */
+less_4:	tbz	w2, #1, less_2		/* < 2 bytes */
+	strh	w1, [x3], #2		/* write 2 bytes */
+less_2:	tbz	w2, #0, exit
+	strb	w1, [x3]		/* write 1 byte */
+exit:	ret
+
+endfunc	memset
diff --git a/lib/libc/libc_asm.mk b/lib/libc/libc_asm.mk
new file mode 100644
index 0000000..6416a3c
--- /dev/null
+++ b/lib/libc/libc_asm.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LIBC_SRCS	:=	$(addprefix lib/libc/,		\
+			abort.c				\
+			assert.c			\
+			exit.c				\
+			memchr.c			\
+			memcmp.c			\
+			memcpy.c			\
+			memmove.c			\
+			memrchr.c			\
+			printf.c			\
+			putchar.c			\
+			puts.c				\
+			snprintf.c			\
+			strchr.c			\
+			strcmp.c			\
+			strlcpy.c			\
+			strlen.c			\
+			strncmp.c			\
+			strnlen.c			\
+			strrchr.c)
+
+ifeq (${ARCH},aarch64)
+LIBC_SRCS	+=	$(addprefix lib/libc/aarch64/,	\
+			memset.S			\
+			setjmp.S)
+else
+LIBC_SRCS	+=	$(addprefix lib/libc/aarch32/,	\
+			memset.S)
+endif
+
+INCLUDES	+=	-Iinclude/lib/libc		\
+			-Iinclude/lib/libc/$(ARCH)	\
diff --git a/lib/libc/strtok.c b/lib/libc/strtok.c
new file mode 100644
index 0000000..7e1a4d2
--- /dev/null
+++ b/lib/libc/strtok.c
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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
+ *    notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS 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 SOFTWEYR LLC, THE
+ * REGENTS, 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 <string.h>
+
+char *
+strtok_r(char *s, const char *delim, char **last)
+{
+	char *spanp, *tok;
+	int c, sc;
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == 0) {		/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = (char *)delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = '\0';
+				*last = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h
index a8d471e..075c403 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc0/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -191,4 +191,19 @@
  */
 #define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x20000
 
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE		UL(0x25000000)
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET			UL(0x1000000)
+#define TZC400_COUNT			4
+
+#define TZC400_BASE(n)			(PLAT_ARM_TZC_BASE + \
+					 (n * TZC400_OFFSET))
+
+#define TZC_NSAID_DEFAULT		U(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS	\
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT))
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
index 903fabf..05d691e 100644
--- a/plat/arm/board/tc0/platform.mk
+++ b/plat/arm/board/tc0/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -61,6 +61,8 @@
 				${TC0_BASE}/tc0_err.c		\
 				${TC0_BASE}/tc0_trusted_boot.c		\
 				lib/utils/mem_region.c			\
+				drivers/arm/tzc/tzc400.c		\
+				plat/arm/common/arm_tzc400.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
diff --git a/plat/arm/board/tc0/tc0_security.c b/plat/arm/board/tc0/tc0_security.c
index 6aa38c8..5f1cb11 100644
--- a/plat/arm/board/tc0/tc0_security.c
+++ b/plat/arm/board/tc0/tc0_security.c
@@ -1,12 +1,23 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <plat/arm/common/plat_arm.h>
 #include <platform_def.h>
 
+static const arm_tzc_regions_info_t tzc_regions[] = {
+	ARM_TZC_REGIONS_DEF,
+	{}
+};
+
 /* Initialize the secure environment */
 void plat_arm_security_setup(void)
 {
+	unsigned int i;
+
+	for (i = 0U; i < TZC400_COUNT; i++) {
+		arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+	}
 }
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 1832c65..74afc53 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -121,6 +121,12 @@
 ENABLE_PSCI_STAT		:=	1
 ENABLE_PMF			:=	1
 
+# Override the standard libc with optimised libc_asm
+OVERRIDE_LIBC			:=	1
+ifeq (${OVERRIDE_LIBC},1)
+    include lib/libc/libc_asm.mk
+endif
+
 # On ARM platforms, separate the code and read-only data sections to allow
 # mapping the former as executable and the latter as execute-never.
 SEPARATE_CODE_AND_RODATA	:=	1
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 14cdb7e..159084f 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,7 +39,7 @@
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # else
 #  define PLAT_ARM_MMAP_ENTRIES		(5 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
-#  define MAX_XLAT_TABLES		(5 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
+#  define MAX_XLAT_TABLES		(6 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
 # endif
 #elif defined(IMAGE_BL32)
 # define PLAT_ARM_MMAP_ENTRIES		8
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index a2117f6..39eb89e 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -43,6 +43,9 @@
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	SGI_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
 	CSS_SGI_MAP_DEVICE,
 	SOC_CSS_MAP_DEVICE,
 	ARM_MAP_NS_DRAM1,
@@ -63,6 +66,9 @@
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
 	CSS_SGI_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
 	SOC_CSS_MAP_DEVICE,
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,