aboutsummaryrefslogtreecommitdiffstats
path: root/plat/common
diff options
context:
space:
mode:
Diffstat (limited to 'plat/common')
-rw-r--r--plat/common/aarch64/plat_common.c43
-rw-r--r--plat/common/aarch64/plat_ehf.c37
-rw-r--r--plat/common/aarch64/platform_mp_stack.S10
-rw-r--r--plat/common/plat_bl1_common.c31
-rw-r--r--plat/common/plat_bl_common.c50
-rw-r--r--plat/common/plat_psci_common.c13
-rw-r--r--plat/common/plat_spmd_manifest.c192
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;
+}