SPM: Load image and RD from SP package

Load SP and RD from package instead of relying on RD being already
loaded in memory and the SP being loaded as a BL32 image.

Change-Id: I18d4fbf4597656c6a7e878e1d7c01a8a324f3f8a
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h
index 6fa5615..8d17b90 100644
--- a/include/plat/arm/common/arm_spm_def.h
+++ b/include/plat/arm/common/arm_spm_def.h
@@ -11,6 +11,31 @@
 #include <xlat_tables_defs.h>
 
 /*
+ * Reserve 4 MiB for binaries of Secure Partitions and Resource Description
+ * blobs.
+ */
+#define PLAT_SP_PACKAGE_BASE	BL32_BASE
+#define PLAT_SP_PACKAGE_SIZE	ULL(0x400000)
+
+#define PLAT_MAP_SP_PACKAGE_MEM_RO	MAP_REGION_FLAT(		\
+						PLAT_SP_PACKAGE_BASE,	\
+						PLAT_SP_PACKAGE_SIZE,	\
+						MT_MEMORY | MT_RO | MT_SECURE)
+#define PLAT_MAP_SP_PACKAGE_MEM_RW	MAP_REGION_FLAT(		\
+						PLAT_SP_PACKAGE_BASE,	\
+						PLAT_SP_PACKAGE_SIZE,	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * The rest of the memory reserved for BL32 is free for SPM to use it as memory
+ * pool to allocate memory regions requested in the resource description.
+ */
+#define PLAT_SPM_HEAP_BASE	(PLAT_SP_PACKAGE_BASE + PLAT_SP_PACKAGE_SIZE)
+#define PLAT_SPM_HEAP_SIZE	(BL32_LIMIT - BL32_BASE - PLAT_SP_PACKAGE_SIZE)
+
+#if SPM_DEPRECATED
+
+/*
  * If BL31 is placed in DRAM, place the Secure Partition in DRAM right after the
  * region used by BL31. If BL31 it is placed in SRAM, put the Secure Partition
  * at the base of DRAM.
@@ -28,8 +53,6 @@
 						MT_MEMORY | MT_RW | MT_SECURE)
 #endif
 
-#if SPM_DEPRECATED
-
 #ifdef IMAGE_BL31
 /* SPM Payload memory. Mapped as code in S-EL1 */
 #define ARM_SP_IMAGE_MMAP		MAP_REGION2(				\
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 79d069a..04272b1 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -268,6 +268,8 @@
 const struct secure_partition_boot_info *plat_get_secure_partition_boot_info(
 		void *cookie);
 int plat_spm_sp_rd_load(struct sp_res_desc *rd, const void *ptr, size_t size);
+int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size,
+				 void **rd_base, size_t *rd_size);
 
 /*******************************************************************************
  * Mandatory BL image load functions(may be overridden).
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 66650ee..f36b637 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -96,9 +96,12 @@
 	ARM_MAP_BL1_RW,
 #endif
 #endif /* TRUSTED_BOARD_BOOT */
-#if ENABLE_SPM
+#if ENABLE_SPM && SPM_DEPRECATED
 	ARM_SP_IMAGE_MMAP,
 #endif
+#if ENABLE_SPM && !SPM_DEPRECATED
+	PLAT_MAP_SP_PACKAGE_MEM_RW,
+#endif
 #if ARM_BL31_IN_DRAM
 	ARM_MAP_BL31_SEC_DRAM,
 #endif
@@ -127,6 +130,9 @@
 #if ENABLE_SPM && SPM_DEPRECATED
 	ARM_SPM_BUF_EL3_MMAP,
 #endif
+#if ENABLE_SPM && !SPM_DEPRECATED
+	PLAT_MAP_SP_PACKAGE_MEM_RO,
+#endif
 	{0}
 };
 
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 31c5fdf..70e51fd 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -72,8 +72,8 @@
 #if defined(IMAGE_BL31)
 # if ENABLE_SPM
 #  define PLAT_ARM_MMAP_ENTRIES		9
-#  define MAX_XLAT_TABLES		7
-#  define PLAT_SP_IMAGE_MMAP_REGIONS	7
+#  define MAX_XLAT_TABLES		9
+#  define PLAT_SP_IMAGE_MMAP_REGIONS	30
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # else
 #  define PLAT_ARM_MMAP_ENTRIES		8
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 9f39d71..24b61e8 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -249,6 +249,7 @@
 ifeq (${ENABLE_SPM},1)
 BL31_SOURCES		+=	common/fdt_wrappers.c			\
 				plat/common/plat_spm_rd.c		\
+				plat/common/plat_spm_sp.c		\
 				${LIBFDT_SRCS}
 endif
 endif
diff --git a/plat/common/plat_spm_sp.c b/plat/common/plat_spm_sp.c
new file mode 100644
index 0000000..7b7fbd9
--- /dev/null
+++ b/plat/common/plat_spm_sp.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <sptool.h>
+
+static unsigned int sp_next;
+
+/*******************************************************************************
+ * Platform handler get the address of a Secure Partition and its resource
+ * description blob. It iterates through all SPs detected by the platform. If
+ * there is information for another SP, it returns 0. If there are no more SPs,
+ * it returns -1.
+ ******************************************************************************/
+int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size,
+				 void **rd_base, size_t *rd_size)
+{
+	assert((sp_base != NULL) && (sp_size != NULL));
+	assert((rd_base != NULL) && (rd_base != NULL));
+
+	const uint64_t *pkg_base = (uint64_t *)PLAT_SP_PACKAGE_BASE;
+
+	struct sp_pkg_header *pkg_header = (struct sp_pkg_header *)pkg_base;
+
+	if (sp_next == 0) {
+		if (pkg_header->version != 0x1) {
+			ERROR("SP package has an unsupported version 0x%llx\n",
+			      pkg_header->version);
+			panic();
+		}
+	}
+
+	if (sp_next >= pkg_header->number_of_sp) {
+		/* No more partitions in the package */
+		return -1;
+	}
+
+	const struct sp_pkg_entry *entry_list =
+		(const struct sp_pkg_entry *)((uintptr_t)pkg_base
+					       + sizeof(struct sp_pkg_header));
+
+	const struct sp_pkg_entry *entry = &(entry_list[sp_next]);
+
+	uint64_t sp_offset = entry->sp_offset;
+	uint64_t rd_offset = entry->rd_offset;
+
+	uintptr_t pkg_sp_base = ((uintptr_t)PLAT_SP_PACKAGE_BASE + sp_offset);
+	uintptr_t pkg_rd_base = ((uintptr_t)PLAT_SP_PACKAGE_BASE + rd_offset);
+
+	uint64_t pkg_sp_size = entry->sp_size;
+	uint64_t pkg_rd_size = entry->rd_size;
+
+	uintptr_t pkg_end = (uintptr_t)PLAT_SP_PACKAGE_BASE
+			  + (uintptr_t)PLAT_SP_PACKAGE_SIZE - 1U;
+
+	/*
+	 * Check for overflows. The package header isn't trusted, so assert()
+	 * can't be used here.
+	 */
+
+	uintptr_t pkg_sp_end = pkg_sp_base + pkg_sp_size - 1U;
+	uintptr_t pkg_rd_end = pkg_rd_base + pkg_rd_size - 1U;
+
+	if ((pkg_sp_end > pkg_end) || (pkg_sp_end < pkg_sp_base)) {
+		ERROR("Invalid Secure Partition size (0x%llx)\n", pkg_sp_size);
+		panic();
+	}
+
+	if ((pkg_rd_end > pkg_end) || (pkg_rd_end < pkg_rd_base)) {
+		ERROR("Invalid Resource Description blob size (0x%llx)\n",
+		      pkg_rd_size);
+		panic();
+	}
+
+	/* Return location of the binaries. */
+
+	*sp_base = (void *)pkg_sp_base;
+	*sp_size = pkg_sp_size;
+	*rd_base = (void *)pkg_rd_base;
+	*rd_size = pkg_rd_size;
+
+	sp_next++;
+
+	return 0;
+}
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index ad1262c..6de4858 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -157,7 +157,10 @@
  ******************************************************************************/
 int32_t spm_setup(void)
 {
+	int rc;
 	sp_context_t *ctx;
+	void *sp_base, *rd_base;
+	size_t sp_size, rd_size;
 
 	/* Disable MMU at EL1 (initialized by BL2) */
 	disable_mmu_icache_el1();
@@ -167,9 +170,26 @@
 
 	ctx = &sp_ctx;
 
+	rc = plat_spm_sp_get_next_address(&sp_base, &sp_size,
+					  &rd_base, &rd_size);
+	if (rc != 0) {
+		ERROR("No Secure Partition found.\n");
+		panic();
+	}
+
 	/* Assign translation tables context. */
 	ctx->xlat_ctx_handle = spm_get_sp_xlat_context();
 
+	/* Save location of the image in physical memory */
+	ctx->image_base = (uintptr_t)sp_base;
+	ctx->image_size = sp_size;
+
+	rc = plat_spm_sp_rd_load(&ctx->rd, rd_base, rd_size);
+	if (rc < 0) {
+		ERROR("Error while loading RD blob.\n");
+		panic();
+	}
+
 	spm_sp_setup(ctx);
 
 	/* Register init function for deferred init.  */
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index ec3f48e..ee13e94 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -32,6 +32,7 @@
 #ifndef __ASSEMBLY__
 
 #include <spinlock.h>
+#include <sp_res_desc.h>
 #include <stdint.h>
 #include <xlat_tables_v2.h>
 
@@ -42,9 +43,14 @@
 } sp_state_t;
 
 typedef struct sp_context {
+	/* Location of the image in physical memory */
+	unsigned long long image_base;
+	size_t image_size;
+
 	uint64_t c_rt_ctx;
 	cpu_context_t cpu_ctx;
 	xlat_ctx_t *xlat_ctx_handle;
+	struct sp_res_desc rd;
 
 	sp_state_t state;
 	spinlock_t state_lock;