diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/std_svc/spmd/spmd_main.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index afd0f2ea2..dde162288 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,10 +16,14 @@ #include <bl31/interrupt_mgmt.h> #include <common/debug.h> #include <common/runtime_svc.h> +#include <common/tbbr/tbbr_img_def.h> #include <lib/el3_runtime/context_mgmt.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> #include <lib/smccc.h> #include <lib/spinlock.h> #include <lib/utils.h> +#include <lib/xlat_tables/xlat_tables_v2.h> #include <plat/common/common_def.h> #include <plat/common/platform.h> #include <platform_def.h> @@ -245,6 +249,92 @@ static uint64_t spmd_secure_interrupt_handler(uint32_t id, SMC_RET0(&ctx->cpu_ctx); } +#if ENABLE_RME && SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 +static int spmd_dynamic_map_mem(uintptr_t base_addr, size_t size, + unsigned int attr, uintptr_t *align_addr, + size_t *align_size) +{ + uintptr_t base_addr_align; + size_t mapped_size_align; + int rc; + + /* Page aligned address and size if necessary */ + base_addr_align = page_align(base_addr, DOWN); + mapped_size_align = page_align(size, UP); + + if ((base_addr != base_addr_align) && + (size == mapped_size_align)) { + mapped_size_align += PAGE_SIZE; + } + + /* + * Map dynamically given region with its aligned base address and + * size + */ + rc = mmap_add_dynamic_region((unsigned long long)base_addr_align, + base_addr_align, + mapped_size_align, + attr); + if (rc == 0) { + *align_addr = base_addr_align; + *align_size = mapped_size_align; + } + + return rc; +} + +static void spmd_do_sec_cpy(uintptr_t root_base_addr, uintptr_t sec_base_addr, + size_t size) +{ + uintptr_t root_base_addr_align, sec_base_addr_align; + size_t root_mapped_size_align, sec_mapped_size_align; + int rc; + + assert(root_base_addr != 0UL); + assert(sec_base_addr != 0UL); + assert(size != 0UL); + + /* Map the memory with required attributes */ + rc = spmd_dynamic_map_mem(root_base_addr, size, MT_RO_DATA | MT_ROOT, + &root_base_addr_align, + &root_mapped_size_align); + if (rc != 0) { + ERROR("%s %s %lu (%d)\n", "Error while mapping", "root region", + root_base_addr, rc); + panic(); + } + + rc = spmd_dynamic_map_mem(sec_base_addr, size, MT_RW_DATA | MT_SECURE, + &sec_base_addr_align, &sec_mapped_size_align); + if (rc != 0) { + ERROR("%s %s %lu (%d)\n", "Error while mapping", + "secure region", sec_base_addr, rc); + panic(); + } + + /* Do copy operation */ + (void)memcpy((void *)sec_base_addr, (void *)root_base_addr, size); + + /* Unmap root memory region */ + rc = mmap_remove_dynamic_region(root_base_addr_align, + root_mapped_size_align); + if (rc != 0) { + ERROR("%s %s %lu (%d)\n", "Error while unmapping", + "root region", root_base_addr_align, rc); + panic(); + } + + /* Unmap secure memory region */ + rc = mmap_remove_dynamic_region(sec_base_addr_align, + sec_mapped_size_align); + if (rc != 0) { + ERROR("%s %s %lu (%d)\n", "Error while unmapping", + "secure region", sec_base_addr_align, rc); + panic(); + } +} +#endif /* ENABLE_RME && SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 */ + /******************************************************************************* * Loads SPMC manifest and inits SPMC. ******************************************************************************/ @@ -254,6 +344,7 @@ static int spmd_spmc_init(void *pm_addr) unsigned int core_id; uint32_t ep_attr, flags; int rc; + const struct dyn_cfg_dtb_info_t *image_info __unused; /* Load the SPM Core manifest */ rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr); @@ -344,6 +435,26 @@ static int spmd_spmc_init(void *pm_addr) DISABLE_ALL_EXCEPTIONS); } +#if ENABLE_RME && SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 + image_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TOS_FW_CONFIG_ID); + assert(image_info != NULL); + + if ((image_info->config_addr == 0UL) || + (image_info->secondary_config_addr == 0UL) || + (image_info->config_max_size == 0UL)) { + return -EINVAL; + } + + /* Copy manifest from root->secure region */ + spmd_do_sec_cpy(image_info->config_addr, + image_info->secondary_config_addr, + image_info->config_max_size); + + /* Update ep info of BL32 */ + assert(spmc_ep_info != NULL); + spmc_ep_info->args.arg0 = image_info->secondary_config_addr; +#endif /* ENABLE_RME && SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 */ + /* Set an initial SPMC context state for all cores. */ for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) { spm_core_context[core_id].state = SPMC_STATE_OFF; |