diff options
Diffstat (limited to 'plat/common')
-rw-r--r-- | plat/common/aarch64/plat_common.c | 43 | ||||
-rw-r--r-- | plat/common/aarch64/plat_ehf.c | 37 | ||||
-rw-r--r-- | plat/common/aarch64/platform_mp_stack.S | 10 | ||||
-rw-r--r-- | plat/common/plat_bl1_common.c | 31 | ||||
-rw-r--r-- | plat/common/plat_bl_common.c | 50 | ||||
-rw-r--r-- | plat/common/plat_psci_common.c | 13 | ||||
-rw-r--r-- | plat/common/plat_spmd_manifest.c | 192 |
7 files changed, 347 insertions, 29 deletions
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c index f8d312952..ba4c366a9 100644 --- a/plat/common/aarch64/plat_common.c +++ b/plat/common/aarch64/plat_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,6 +11,7 @@ #if RAS_EXTENSION #include <lib/extensions/ras.h> #endif +#include <lib/extensions/twed.h> #include <lib/xlat_tables/xlat_mmu_helpers.h> #include <plat/common/platform.h> @@ -20,6 +21,7 @@ * platforms but may also be overridden by a platform if required. */ #pragma weak bl31_plat_runtime_setup +#pragma weak plat_arm_set_twedel_scr_el3 #if SDEI_SUPPORT #pragma weak plat_sdei_handle_masked_trigger @@ -64,6 +66,18 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) } #endif +#if !ENABLE_BACKTRACE +static const char *get_el_str(unsigned int el) +{ + if (el == MODE_EL3) { + return "EL3"; + } else if (el == MODE_EL2) { + return "EL2"; + } + return "S-EL1"; +} +#endif /* !ENABLE_BACKTRACE */ + /* RAS functions common to AArch64 ARM platforms */ void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, void *handle, uint64_t flags) @@ -74,9 +88,30 @@ void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, if (handled != 0) return; #endif + unsigned int level = (unsigned int)GET_EL(read_spsr_el3()); - ERROR("Unhandled External Abort received on 0x%lx at EL3!\n", - read_mpidr_el1()); - ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome); + ERROR("Unhandled External Abort received on 0x%lx from %s\n", + read_mpidr_el1(), get_el_str(level)); + ERROR("exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome); +#if HANDLE_EA_EL3_FIRST + /* Skip backtrace for lower EL */ + if (level != MODE_EL3) { + console_flush(); + do_panic(); + } +#endif panic(); } + +/******************************************************************************* + * In v8.6+ platforms with delayed trapping of WFE this hook sets the delay. It + * is a weak function definition so can be overridden depending on the + * requirements of a platform. The only hook provided is for the TWED fields + * in SCR_EL3, the TWED fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 should be + * configured as needed in lower exception levels. + ******************************************************************************/ + +uint32_t plat_arm_set_twedel_scr_el3(void) +{ + return TWED_DISABLED; +} diff --git a/plat/common/aarch64/plat_ehf.c b/plat/common/aarch64/plat_ehf.c new file mode 100644 index 000000000..da768843e --- /dev/null +++ b/plat/common/aarch64/plat_ehf.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Broadcom + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl31/ehf.h> + +#include <platform_def.h> + +/* + * Enumeration of priority levels on ARM platforms. + */ +ehf_pri_desc_t plat_exceptions[] = { +#if RAS_EXTENSION + /* RAS Priority */ + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_RAS_PRI), +#endif + +#if SDEI_SUPPORT + /* Critical priority SDEI */ + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI), + + /* Normal priority SDEI */ + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI), +#endif +#if SPM_MM + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI), +#endif + /* Plaform specific exceptions description */ +#ifdef PLAT_EHF_DESC + PLAT_EHF_DESC, +#endif +}; + +/* Plug in ARM exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), PLAT_PRI_BITS); diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S index f9780e80c..c0668ea78 100644 --- a/plat/common/aarch64/platform_mp_stack.S +++ b/plat/common/aarch64/platform_mp_stack.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,7 +14,7 @@ .weak plat_set_my_stack /* --------------------------------------------------------------------- - * When the compatility layer is disabled, the platform APIs + * When the compatibility layer is disabled, the platform APIs * plat_get_my_stack() and plat_set_my_stack() are supported by the * platform and the previous APIs platform_get_stack() and * platform_set_stack() are defined in terms of new APIs making use of @@ -32,7 +32,7 @@ * ----------------------------------------------------- */ func plat_get_my_stack - mov x10, x30 // lr + mov x10, x30 get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE ret x10 endfunc plat_get_my_stack @@ -45,14 +45,14 @@ endfunc plat_get_my_stack * ----------------------------------------------------- */ func plat_set_my_stack - mov x9, x30 // lr + mov x9, x30 bl plat_get_my_stack mov sp, x0 ret x9 endfunc plat_set_my_stack /* ----------------------------------------------------- - * Per-cpu stacks in normal memory. Each cpu gets a + * Per-CPU stacks in normal memory. Each CPU gets a * stack of PLATFORM_STACK_SIZE bytes. * ----------------------------------------------------- */ diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c index 5733781ac..1c6d68b2b 100644 --- a/plat/common/plat_bl1_common.c +++ b/plat/common/plat_bl1_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -27,7 +27,9 @@ #pragma weak bl1_plat_fwu_done #pragma weak bl1_plat_handle_pre_image_load #pragma weak bl1_plat_handle_post_image_load - +#if MEASURED_BOOT +#pragma weak bl1_plat_set_bl2_hash +#endif unsigned int bl1_plat_get_next_image_id(void) { @@ -58,7 +60,7 @@ struct image_desc *bl1_plat_get_image_desc(unsigned int image_id) __dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) { - while (1) + while (true) wfi(); } @@ -81,8 +83,8 @@ int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size, */ int bl1_plat_handle_post_image_load(unsigned int image_id) { - meminfo_t *bl2_tzram_layout; - meminfo_t *bl1_tzram_layout; + meminfo_t *bl2_secram_layout; + meminfo_t *bl1_secram_layout; image_desc_t *image_desc; entry_point_info_t *ep_info; @@ -97,7 +99,7 @@ int bl1_plat_handle_post_image_load(unsigned int image_id) ep_info = &image_desc->ep_info; /* Find out how much free trusted ram remains after BL1 load */ - bl1_tzram_layout = bl1_plat_sec_mem_layout(); + bl1_secram_layout = bl1_plat_sec_mem_layout(); /* * Create a new layout of memory for BL2 as seen by BL1 i.e. @@ -106,13 +108,22 @@ int bl1_plat_handle_post_image_load(unsigned int image_id) * to BL2. BL2 will read the memory layout before using its * memory for other purposes. */ - bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->total_base; + bl2_secram_layout = (meminfo_t *) bl1_secram_layout->total_base; - bl1_calc_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout); + bl1_calc_bl2_mem_layout(bl1_secram_layout, bl2_secram_layout); - ep_info->args.arg1 = (uintptr_t)bl2_tzram_layout; + ep_info->args.arg1 = (uintptr_t)bl2_secram_layout; VERBOSE("BL1: BL2 memory layout address = %p\n", - (void *) bl2_tzram_layout); + (void *) bl2_secram_layout); return 0; } + +#if MEASURED_BOOT +/* + * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB. + */ +void bl1_plat_set_bl2_hash(const image_desc_t *image_desc) +{ +} +#endif diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c index b46656c7a..89b77ba6c 100644 --- a/plat/common/plat_bl_common.c +++ b/plat/common/plat_bl_common.c @@ -1,17 +1,19 @@ /* - * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <assert.h> -#include <errno.h> #include <arch_helpers.h> #include <common/bl_common.h> #include <common/debug.h> #include <lib/xlat_tables/xlat_tables_compat.h> #include <plat/common/platform.h> +#include <services/arm_arch_svc.h> +#include <smccc_helpers.h> +#include <tools_share/firmware_encrypted.h> /* * The following platform functions are weakly defined. The Platforms @@ -23,6 +25,25 @@ #pragma weak bl2_plat_handle_pre_image_load #pragma weak bl2_plat_handle_post_image_load #pragma weak plat_try_next_boot_source +#pragma weak plat_get_enc_key_info +#pragma weak plat_is_smccc_feature_available +#pragma weak plat_get_soc_version +#pragma weak plat_get_soc_revision + +int32_t plat_get_soc_version(void) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} + +int32_t plat_get_soc_revision(void) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} + +int32_t plat_is_smccc_feature_available(u_register_t fid __unused) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} void bl2_el3_plat_prepare_exit(void) { @@ -54,6 +75,31 @@ int plat_try_next_boot_source(void) } /* + * Weak implementation to provide dummy decryption key only for test purposes, + * platforms must override this API for any real world firmware encryption + * use-case. + */ +int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key, + size_t *key_len, unsigned int *flags, + const uint8_t *img_id, size_t img_id_len) +{ +#define DUMMY_FIP_ENC_KEY { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef } + + const uint8_t dummy_key[] = DUMMY_FIP_ENC_KEY; + + assert(*key_len >= sizeof(dummy_key)); + + *key_len = sizeof(dummy_key); + memcpy(key, dummy_key, *key_len); + *flags = 0; + + return 0; +} + +/* * Set up the page tables for the generic and platform-specific memory regions. * The size of the Trusted SRAM seen by the BL image must be specified as well * as an array specifying the generic memory regions which can be; diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c index 80ed8198b..c32e59f9c 100644 --- a/plat/common/plat_psci_common.c +++ b/plat/common/plat_psci_common.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,6 +10,7 @@ #include <arch.h> #include <lib/pmf/pmf.h> #include <lib/psci/psci.h> +#include <lib/utils_def.h> #include <plat/common/platform.h> #if ENABLE_PSCI_STAT && ENABLE_PMF @@ -16,9 +18,6 @@ #pragma weak plat_psci_stat_accounting_stop #pragma weak plat_psci_stat_get_residency -/* Ticks elapsed in one second by a signal of 1 MHz */ -#define MHZ_TICKS_PER_SEC 1000000U - /* Maximum time-stamp value read from architectural counters */ #ifdef __aarch64__ #define MAX_TS UINT64_MAX @@ -64,7 +63,6 @@ static u_register_t calc_stat_residency(unsigned long long pwrupts, /* * Capture timestamp before entering a low power state. - * No cache maintenance is required when capturing the timestamp. * Cache maintenance may be needed when reading these timestamps. */ void plat_psci_stat_accounting_start( @@ -72,12 +70,11 @@ void plat_psci_stat_accounting_start( { assert(state_info != NULL); PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR, - PMF_NO_CACHE_MAINT); + PMF_CACHE_MAINT); } /* * Capture timestamp after exiting a low power state. - * No cache maintenance is required when capturing the timestamp. * Cache maintenance may be needed when reading these timestamps. */ void plat_psci_stat_accounting_stop( @@ -85,7 +82,7 @@ void plat_psci_stat_accounting_stop( { assert(state_info != NULL); PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR, - PMF_NO_CACHE_MAINT); + PMF_CACHE_MAINT); } /* diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c new file mode 100644 index 000000000..8f4018c7c --- /dev/null +++ b/plat/common/plat_spmd_manifest.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <libfdt.h> + +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/fdt_wrappers.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <platform_def.h> +#include <services/spm_core_manifest.h> + +#define ATTRIBUTE_ROOT_NODE_STR "attribute" + +/******************************************************************************* + * SPMC attribute node parser + ******************************************************************************/ +static int manifest_parse_attribute(spmc_manifest_attribute_t *attr, + const void *fdt, + int node) +{ + uint32_t val32; + int rc; + + assert((attr != NULL) && (fdt != NULL)); + + rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version); + if (rc != 0) { + ERROR("Missing FFA %s version in SPM Core manifest.\n", + "major"); + return rc; + } + + rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version); + if (rc != 0) { + ERROR("Missing FFA %s version in SPM Core manifest.\n", + "minor"); + return rc; + } + + rc = fdt_read_uint32(fdt, node, "spmc_id", &val32); + if (rc != 0) { + ERROR("Missing SPMC ID in manifest.\n"); + return rc; + } + + attr->spmc_id = val32 & 0xffff; + + rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Execution state"); + } + + rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Binary size"); + } + + rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Load address"); + } + + rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Entry point"); + } + + VERBOSE("SPM Core manifest attribute section:\n"); + VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version); + VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id); + VERBOSE(" binary_size: 0x%x\n", attr->binary_size); + VERBOSE(" load_address: 0x%llx\n", attr->load_address); + VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint); + + return 0; +} + +/******************************************************************************* + * Root node handler + ******************************************************************************/ +static int manifest_parse_root(spmc_manifest_attribute_t *manifest, + const void *fdt, + int root) +{ + int node; + + assert(manifest != NULL); + + node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR, + sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1); + if (node < 0) { + ERROR("Root node doesn't contain subnode '%s'\n", + ATTRIBUTE_ROOT_NODE_STR); + return node; + } + + return manifest_parse_attribute(manifest, fdt, node); +} + +/******************************************************************************* + * Platform handler to parse a SPM Core manifest. + ******************************************************************************/ +int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, + const void *pm_addr) +{ + int rc, unmap_ret; + uintptr_t pm_base, pm_base_align; + size_t mapped_size; + + assert(manifest != NULL); + assert(pm_addr != NULL); + + /* + * Assume TOS_FW_CONFIG is not necessarily aligned to a page + * boundary, thus calculate the remaining space between SPMC + * manifest start address and upper page limit. + * + */ + pm_base = (uintptr_t)pm_addr; + pm_base_align = page_align(pm_base, UP); + + if (pm_base == pm_base_align) { + /* Page aligned */ + mapped_size = PAGE_SIZE; + } else { + mapped_size = pm_base_align - pm_base; + } + + /* Check space within the page at least maps the FDT header */ + if (mapped_size < sizeof(struct fdt_header)) { + ERROR("Error while mapping SPM Core manifest.\n"); + return -EINVAL; + } + + /* Map first SPMC manifest page in the SPMD translation regime */ + pm_base_align = page_align(pm_base, DOWN); + rc = mmap_add_dynamic_region((unsigned long long)pm_base_align, + pm_base_align, + PAGE_SIZE, + MT_RO_DATA); + if (rc != 0) { + ERROR("Error while mapping SPM Core manifest (%d).\n", rc); + return rc; + } + + rc = fdt_check_header(pm_addr); + if (rc != 0) { + ERROR("Wrong format for SPM Core manifest (%d).\n", rc); + goto exit_unmap; + } + + /* Check SPMC manifest fits within the upper mapped page boundary */ + if (mapped_size < fdt_totalsize(pm_addr)) { + ERROR("SPM Core manifest too large.\n"); + rc = -EINVAL; + goto exit_unmap; + } + + VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr); + + rc = fdt_node_offset_by_compatible(pm_addr, -1, + "arm,ffa-core-manifest-1.0"); + if (rc < 0) { + ERROR("Unrecognized SPM Core manifest\n"); + goto exit_unmap; + } + + rc = manifest_parse_root(manifest, pm_addr, rc); + +exit_unmap: + unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE); + if (unmap_ret != 0) { + ERROR("Error while unmapping SPM Core manifest (%d).\n", + unmap_ret); + if (rc == 0) { + rc = unmap_ret; + } + } + + return rc; +} |