SPM: S-EL0 partitions support build for TC0

Add support for building Ivy for the TC0 platform. To do this
extend the Ivy build system to support building for multiple
platforms.

Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: I47298f00ba91f498826dd3ddd690309df01cc13e
diff --git a/Makefile b/Makefile
index 69d55be..3c1cf53 100644
--- a/Makefile
+++ b/Makefile
@@ -108,16 +108,16 @@
 include fwu/ns_bl1u/ns_bl1u.mk
 include fwu/ns_bl2u/ns_bl2u.mk
 
-# Only platform fvp supports cactus_mm, ivy, quark
+# Only platform fvp supports cactus_mm, quark
 ifeq (${ARCH}-${PLAT},aarch64-fvp)
 include spm/cactus_mm/cactus_mm.mk
-include spm/ivy/ivy.mk
 include spm/quark/quark.mk
 endif
 
-# cactus is supported on platforms: fvp, tc0
+# cactus and ivy are supported on platforms: fvp, tc0
 ifeq (${ARCH}-${PLAT},$(filter ${ARCH}-${PLAT},aarch64-fvp aarch64-tc0))
 include spm/cactus/cactus.mk
+include spm/ivy/ivy.mk
 endif
 
 ################################################################################
@@ -367,11 +367,6 @@
 	@echo "ERROR: $@ is supported only on AArch64 FVP."
 	@exit 1
 
-.PHONY: ivy
-ivy:
-	@echo "ERROR: $@ is supported only on AArch64 FVP."
-	@exit 1
-
 .PHONY: quark
 quark:
 	@echo "ERROR: $@ is supported only on AArch64 FVP."
@@ -383,6 +378,11 @@
 cactus:
 	@echo "ERROR: $@ is supported only on AArch64 FVP or TC0."
 	@exit 1
+
+.PHONY: ivy
+ivy:
+	@echo "ERROR: $@ is supported only on AArch64 FVP or TC0."
+	@exit 1
 endif
 
 MAKE_DEP = -Wp,-MD,$(DEP) -MT $$@
@@ -524,6 +524,7 @@
 
 ifeq (${ARCH}-${PLAT},aarch64-tc0)
   $(eval $(call MAKE_IMG,cactus))
+  $(eval $(call MAKE_IMG,ivy))
 endif
 
 # The EL3 test payload is only supported in AArch64. It has an independent build
diff --git a/spm/common/sp_debug.c b/spm/common/sp_debug.c
index 64ea9c5..396253b 100644
--- a/spm/common/sp_debug.c
+++ b/spm/common/sp_debug.c
@@ -7,6 +7,7 @@
 #include <drivers/arm/pl011.h>
 #include <drivers/console.h>
 #include <sp_debug.h>
+#include <sp_helpers.h>
 #include <spm_helpers.h>
 
 static int (*putc_impl)(int);
@@ -18,6 +19,18 @@
 	return c;
 }
 
+static int putc_svccall(int c)
+{
+	/* TODO svc call */
+	svc_args args = {
+		.fid = SPM_DEBUG_LOG,
+		.arg1 = c
+	};
+	sp_svc(&args);
+
+	return c;
+}
+
 static int putc_uart(int c)
 {
 	console_pl011_putc(c);
@@ -33,6 +46,10 @@
 		putc_impl = putc_hypcall;
 		return;
 
+	case SVC_CALL_AS_STDOUT:
+		putc_impl = putc_svccall;
+		return;
+
 	case PL011_AS_STDOUT:
 	default:
 		break;
diff --git a/spm/common/sp_debug.h b/spm/common/sp_debug.h
index 8b0bec7..e35c602 100644
--- a/spm/common/sp_debug.h
+++ b/spm/common/sp_debug.h
@@ -7,6 +7,7 @@
 enum stdout_route {
 	PL011_AS_STDOUT = 0,
 	HVC_CALL_AS_STDOUT,
+	SVC_CALL_AS_STDOUT,
 };
 
 void set_putc_impl(enum stdout_route);
diff --git a/spm/ivy/app/ivy_main.c b/spm/ivy/app/ivy_main.c
index f51fcb5..28f93ab 100644
--- a/spm/ivy/app/ivy_main.c
+++ b/spm/ivy/app/ivy_main.c
@@ -8,8 +8,7 @@
 #include <debug.h>
 #include <errno.h>
 #include <ffa_helpers.h>
-#include <ivy_def.h>
-#include <platform_def.h>
+#include <sp_debug.h>
 #include <sp_helpers.h>
 
 #include "ivy.h"
@@ -23,6 +22,8 @@
 	u_register_t ret;
 	svc_args args;
 
+	set_putc_impl(SVC_CALL_AS_STDOUT);
+
 	NOTICE("Entering S-EL0 Secure Partition\n");
 	NOTICE("%s\n", build_message);
 	NOTICE("%s\n", version_string);
@@ -30,16 +31,20 @@
 init:
 	args = (svc_args){.fid = FFA_MSG_WAIT};
 	ret = sp_svc(&args);
+
 	while (1) {
 		if (ret != FFA_MSG_SEND_DIRECT_REQ_SMC32) {
 			ERROR("unknown FF-A request %lx\n", ret);
 			goto init;
 		}
+
 		VERBOSE("Received request: %lx\n", args.arg3);
+
 		args.fid = FFA_MSG_SEND_DIRECT_RESP_SMC32;
 		args.arg1 = 0x80020000;
 		args.arg2 = 0;
 		args.arg3 = 0;
+
 		ret = sp_svc(&args);
 	}
 }
diff --git a/spm/ivy/app/ivy.dts b/spm/ivy/app/plat/arm/fvp/fdts/ivy.dts
similarity index 100%
rename from spm/ivy/app/ivy.dts
rename to spm/ivy/app/plat/arm/fvp/fdts/ivy.dts
diff --git a/spm/ivy/app/plat/arm/fvp/include/ivy_platform_def.h b/spm/ivy/app/plat/arm/fvp/include/ivy_platform_def.h
new file mode 100644
index 0000000..3658c83
--- /dev/null
+++ b/spm/ivy/app/plat/arm/fvp/include/ivy_platform_def.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#ifndef CACTUS_PLATFORM_DEF_H
+#define CACTUS_PLATFORM_DEF_H
+
+#define PLAT_ARM_DEVICE0_BASE		DEVICE0_BASE
+#define PLAT_ARM_DEVICE0_SIZE		DEVICE0_SIZE
+
+#define CACTUS_PL011_UART_BASE		PL011_UART2_BASE
+#define CACTUS_PL011_UART_CLK_IN_HZ	PL011_UART2_CLK_IN_HZ
+
+#define PLAT_CACTUS_RX_BASE		ULL(0x7300000)
+
+#define CACTUS_PRIMARY_EC_COUNT		(8U)
+#define CACTUS_SECONDARY_EC_COUNT	(8U)
+#define CACTUS_TERTIARY_EC_COUNT	(8U)
+
+#endif /* CACTUS_PLATFORM_DEF_H */
diff --git a/spm/ivy/app/plat/arm/fvp/platform.mk b/spm/ivy/app/plat/arm/fvp/platform.mk
new file mode 100644
index 0000000..1e9a43b
--- /dev/null
+++ b/spm/ivy/app/plat/arm/fvp/platform.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+FVP_IVY_BASE		= spm/ivy/app/plat/arm/fvp
+
+PLAT_INCLUDES		+= -I${FVP_IVY_BASE}/include/
+
+# Add the FDT source
+IVY_DTS		= ${FVP_IVY_BASE}/fdts/ivy.dts
+
+# List of FDTS to copy
+FDTS_CP_LIST		= ${FVP_IVY_BASE}/fdts/ivy.dts
diff --git a/spm/ivy/app/plat/arm/tc0/fdts/ivy.dts b/spm/ivy/app/plat/arm/tc0/fdts/ivy.dts
new file mode 100644
index 0000000..2a22e20
--- /dev/null
+++ b/spm/ivy/app/plat/arm/tc0/fdts/ivy.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020-2021, 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 = "ivy-1";
+	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+	uuid = <0xeaba83d8 0xbaaf4eaf 0x8144f7fd 0xcbe544a7>;
+	id = <1>;
+	auxiliary-id = <0xae>;
+	stream-endpoint-ids = <0 1 2 3>;
+	execution-ctx-count = <1>;
+	exception-level = <2>; /* S-EL1 */
+	execution-state = <0>; /* AARCH64 */
+	load-address = <0xfe280000>;
+	entrypoint-offset = <0x00001000>;
+	xlat-granule = <0>; /* 4KiB */
+	boot-order = <0>;
+	messaging-method = <0>; /* Direct messaging only */
+	run-time-model = <1>; /* SP pre-emptible */
+
+	/* Boot protocol */
+	gp-register-num = <0x0>;
+};
diff --git a/spm/ivy/app/plat/arm/tc0/include/ivy_platform_def.h b/spm/ivy/app/plat/arm/tc0/include/ivy_platform_def.h
new file mode 100644
index 0000000..3658c83
--- /dev/null
+++ b/spm/ivy/app/plat/arm/tc0/include/ivy_platform_def.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#ifndef CACTUS_PLATFORM_DEF_H
+#define CACTUS_PLATFORM_DEF_H
+
+#define PLAT_ARM_DEVICE0_BASE		DEVICE0_BASE
+#define PLAT_ARM_DEVICE0_SIZE		DEVICE0_SIZE
+
+#define CACTUS_PL011_UART_BASE		PL011_UART2_BASE
+#define CACTUS_PL011_UART_CLK_IN_HZ	PL011_UART2_CLK_IN_HZ
+
+#define PLAT_CACTUS_RX_BASE		ULL(0x7300000)
+
+#define CACTUS_PRIMARY_EC_COUNT		(8U)
+#define CACTUS_SECONDARY_EC_COUNT	(8U)
+#define CACTUS_TERTIARY_EC_COUNT	(8U)
+
+#endif /* CACTUS_PLATFORM_DEF_H */
diff --git a/spm/ivy/app/plat/arm/tc0/platform.mk b/spm/ivy/app/plat/arm/tc0/platform.mk
new file mode 100644
index 0000000..10342d2
--- /dev/null
+++ b/spm/ivy/app/plat/arm/tc0/platform.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TC0_IVY_BASE		= spm/ivy/app/plat/arm/tc0
+
+PLAT_INCLUDES		+= -I${TC0_IVY_BASE}/include/
+
+# Add the FDT source
+IVY_DTS		= ${TC0_IVY_BASE}/fdts/ivy.dts
+
+# List of FDTS to copy
+FDTS_CP_LIST		= ${TC0_IVY_BASE}/fdts/ivy.dts
diff --git a/spm/ivy/ivy.mk b/spm/ivy/ivy.mk
index 7230a45..d184097 100644
--- a/spm/ivy/ivy.mk
+++ b/spm/ivy/ivy.mk
@@ -7,7 +7,13 @@
 include branch_protection.mk
 include lib/xlat_tables_v2/xlat_tables.mk
 
-IVY_DTB		:= $(BUILD_PLAT)/ivy.dtb
+# Include ivy platform Makefile
+IVY_PLAT_PATH	:= $(shell find spm/ivy/app/plat -wholename '*/${PLAT}')
+ifneq (${IVY_PLAT_PATH},)
+	include ${IVY_PLAT_PATH}/platform.mk
+endif
+
+IVY_DTB		:= build/${PLAT}/debug/ivy.dtb
 
 IVY_INCLUDES :=					\
 	-Itftf/framework/include			\
@@ -74,12 +80,31 @@
 $(eval $(call add_define,IVY_DEFINES,PLAT_${PLAT}))
 
 $(IVY_DTB) : $(BUILD_PLAT)/ivy $(BUILD_PLAT)/ivy/ivy.elf
-$(IVY_DTB) : spm/ivy/app/ivy.dts
-	@echo "  DTBGEN  spm/ivy/app/ivy.dts"
+$(IVY_DTB) : $(IVY_DTS)
+	@echo "  DTBGEN  $@"
 	${Q}tools/generate_dtb/generate_dtb.sh \
-		ivy spm/ivy/app/ivy.dts $(BUILD_PLAT)
+		ivy ${IVY_DTS} $(BUILD_PLAT)
+	${Q}tools/generate_json/generate_json.sh \
+		ivy $(BUILD_PLAT)
 	@echo
 	@echo "Built $@ successfully"
 	@echo
 
 ivy: $(IVY_DTB)
+
+# FDTS_CP copies flattened device tree sources
+#   $(1) = output directory
+#   $(2) = flattened device tree source file to copy
+define FDTS_CP
+        $(eval FDTS := $(addprefix $(1)/,$(notdir $(2))))
+FDTS_LIST += $(FDTS)
+$(FDTS): $(2) $(IVY_DTB)
+	@echo "  CP      $$<"
+	${Q}cp $$< $$@
+endef
+
+ifdef FDTS_CP_LIST
+        $(eval files := $(filter %.dts,$(FDTS_CP_LIST)))
+        $(eval $(foreach file,$(files),$(call FDTS_CP,$(BUILD_PLAT),$(file))))
+ivy: $(FDTS_LIST)
+endif
diff --git a/tools/generate_json/generate_json.sh b/tools/generate_json/generate_json.sh
index 30d901e..3a3c04f 100755
--- a/tools/generate_json/generate_json.sh
+++ b/tools/generate_json/generate_json.sh
@@ -28,10 +28,11 @@
 	\t\"pm\": \"$1-secondary.dts\",\n \
 	\t\"owner\": \"Plat\"\n\t},\n\n\t\"$1-tertiary\" : {\n \
 	\t\"image\": \"$1.bin\",\n \
-	\t\"pm\": \"$1-tertiary.dts\" \n \
-	},\n\n\t\"ivy\" : {\n \
+	\t\"pm\": \"$1-tertiary.dts\", \n \
+	\t\"owner\": \"Plat\"\n\t},\n\n\t\"ivy\" : {\n \
 	\t\"image\": \"ivy.bin\",\n \
-	\t\"pm\": \"ivy.dts\" \n \
+	\t\"pm\": \"ivy.dts\", \n \
+	\t\"owner\": \"Plat\"\n \
 	}\n}" \
 	> "$GENERATED_JSON"
 else