diff options
author | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2018-11-27 08:36:02 +0000 |
---|---|---|
committer | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2018-12-11 13:45:41 +0000 |
commit | 680389a65a004d2af007abccf0a0352f2c0eb529 (patch) | |
tree | 84d1f5adf7382cb8899978d7106bd49ee690b7da /plat/common/plat_spm_sp.c | |
parent | 26010da11629f27ddf013ba6127198b33edcd574 (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/plat_spm_sp.c')
-rw-r--r-- | plat/common/plat_spm_sp.c | 90 |
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; +} |