summaryrefslogtreecommitdiff
path: root/plat/common
diff options
context:
space:
mode:
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-11-27 08:36:02 +0000
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-12-11 13:45:41 +0000
commit680389a65a004d2af007abccf0a0352f2c0eb529 (patch)
tree84d1f5adf7382cb8899978d7106bd49ee690b7da /plat/common
parent26010da11629f27ddf013ba6127198b33edcd574 (diff)
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>
Diffstat (limited to 'plat/common')
-rw-r--r--plat/common/plat_spm_sp.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/plat/common/plat_spm_sp.c b/plat/common/plat_spm_sp.c
new file mode 100644
index 00000000..7b7fbd98
--- /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;
+}