diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
commit | 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 (patch) | |
tree | bcf648efac40ca6139842707f0eba5a4496a6dd2 /plat/arm/board | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-102b0d2daa97dae68d3eed54d8fe37a9cc38a892.tar.xz arm-trusted-firmware-102b0d2daa97dae68d3eed54d8fe37a9cc38a892.zip |
Adding upstream version 2.8.0+dfsg.upstream/2.8.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/arm/board')
302 files changed, 22420 insertions, 0 deletions
diff --git a/plat/arm/board/a5ds/a5ds_bl1_setup.c b/plat/arm/board/a5ds/a5ds_bl1_setup.c new file mode 100644 index 0000000..629c928 --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_bl1_setup.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); +} diff --git a/plat/arm/board/a5ds/a5ds_bl2_setup.c b/plat/arm/board/a5ds/a5ds_bl2_setup.c new file mode 100644 index 0000000..1979c50 --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_bl2_setup.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); +} diff --git a/plat/arm/board/a5ds/a5ds_common.c b/plat/arm/board/a5ds/a5ds_common.c new file mode 100644 index 0000000..a4a0cff --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_common.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <lib/mmio.h> +#include <platform_def.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> + +#define MAP_PERIPHBASE MAP_REGION_FLAT(PERIPHBASE,\ + PERIPH_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_A5_PERIPHERALS MAP_REGION_FLAT(A5_PERIPHERALS_BASE,\ + A5_PERIPHERALS_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MAP_PERIPHBASE, + MAP_A5_PERIPHERALS, + MAP_BOOT_RW, + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MAP_PERIPHBASE, + MAP_A5_PERIPHERALS, + MAP_BOOT_RW, + ARM_MAP_NS_DRAM1, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MAP_PERIPHBASE, + MAP_A5_PERIPHERALS, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +unsigned int plat_get_syscnt_freq2(void) +{ + return A5DS_TIMER_BASE_FREQUENCY; +} diff --git a/plat/arm/board/a5ds/a5ds_err.c b/plat/arm/board/a5ds/a5ds_err.c new file mode 100644 index 0000000..feb9fdf --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * a5ds error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/a5ds/a5ds_pm.c b/plat/arm/board/a5ds/a5ds_pm.c new file mode 100644 index 0000000..7774002 --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_pm.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <assert.h> +#include <drivers/arm/gicv2.h> +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int a5ds_pwr_domain_on(u_register_t mpidr) +{ + unsigned int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE; + + hold_base[pos] = A5DS_HOLD_STATE_GO; + dsbish(); + sev(); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* TODO: This setup is needed only after a cold boot*/ + gicv2_pcpu_distif_init(); + + /* Enable the gic cpu interface */ + gicv2_cpuif_enable(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + * a5ds only has always-on power domain and there is no power control present. + ******************************************************************************/ +void a5ds_pwr_domain_off(const psci_power_state_t *target_state) +{ + ERROR("CPU_OFF not supported on this platform\n"); + assert(false); + panic(); +} + +/******************************************************************************* + * Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t a5ds_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL, + .pwr_domain_on = a5ds_pwr_domain_on, + .pwr_domain_on_finish = a5ds_pwr_domain_on_finish, + .pwr_domain_off = a5ds_pwr_domain_off +}; + +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE; + *mailbox = sec_entrypoint; + + *psci_ops = &a5ds_psci_pm_ops; + + return 0; +} diff --git a/plat/arm/board/a5ds/a5ds_private.h b/plat/arm/board/a5ds/a5ds_private.h new file mode 100644 index 0000000..f577249 --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_private.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef A5DS_PRIVATE_H +#define A5DS_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void a5ds_config_setup(void); + +#endif /* A5DS_PRIVATE_H */ diff --git a/plat/arm/board/a5ds/a5ds_security.c b/plat/arm/board/a5ds/a5ds_security.c new file mode 100644 index 0000000..5593ae0 --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_security.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The platform currently does not have any security setup. + */ +} diff --git a/plat/arm/board/a5ds/a5ds_topology.c b/plat/arm/board/a5ds/a5ds_topology.c new file mode 100644 index 0000000..94fa71f --- /dev/null +++ b/plat/arm/board/a5ds/a5ds_topology.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +/* The A5DS power domain tree descriptor */ +static const unsigned char a5ds_power_domain_tree_desc[] = { + 1, + /* No of children for the root node */ + A5DS_CLUSTER_COUNT, + /* No of children for the first cluster node */ + A5DS_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the topology according to A5DS_CLUSTER_COUNT. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return a5ds_power_domain_tree_desc; +} + +/******************************************************************************* + * Get core position using mpidr + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= A5DS_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= A5DS_MAX_CPUS_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); + +} diff --git a/plat/arm/board/a5ds/aarch32/a5ds_helpers.S b/plat/arm/board/a5ds/aarch32/a5ds_helpers.S new file mode 100644 index 0000000..ed7ad9c --- /dev/null +++ b/plat/arm/board/a5ds/aarch32/a5ds_helpers.S @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT + mov_imm r2, A5DS_HOLD_BASE + /* Clear the value stored in the hold address for the specific core */ + mov_imm r3, A5DS_HOLD_STATE_WAIT + str r3, [r2, r0] + dmb ish + + /* Wait until we have a go */ +poll_mailbox: + ldr r1, [r2, r0] + cmp r1, #A5DS_HOLD_STATE_WAIT + beq 1f + mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE + ldr r1, [r0] + bx r1 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr + +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #0 + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * Loads MPIDR in r0 and calls plat_arm_calc_core_pos + * --------------------------------------------------------------------- + */ +func plat_my_core_pos + ldcopr r0, MPIDR + b plat_arm_calc_core_pos + +endfunc plat_my_core_pos + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on A5DS. + * + * (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) + + * (CPUId * A5DS_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #A5DS_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #A5DS_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts new file mode 100644 index 0000000..b9ff8bf --- /dev/null +++ b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x2001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + hw-config { + load-address = <0x0 0x83000000>; + max-size = <0x01000000>; + id = <HW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts new file mode 100644 index 0000000..c66186f --- /dev/null +++ b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + }; +}; diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h new file mode 100644 index 0000000..9f3df1e --- /dev/null +++ b/plat/arm/board/a5ds/include/platform_def.h @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <common/tbbr/tbbr_img_def.h> +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/smccc_def.h> +#include <plat/common/common_def.h> + +/* Memory location options for TSP */ +#define ARM_DRAM_ID 2 + +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) + +#define SRAM_BASE 0x2000000 +#define SRAM_SIZE 0x200000 + +/* The first 4KB of NS DRAM1 are used as shared memory */ +#define A5DS_SHARED_RAM_BASE SRAM_BASE +#define A5DS_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* The next 252 kB of NS DRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (A5DS_SHARED_RAM_BASE + \ + A5DS_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \ + A5DS_SHARED_RAM_SIZE) + +#define PERIPHBASE 0x1a000000 +#define PERIPH_SIZE 0x00240000 +#define A5_PERIPHERALS_BASE 0x1c000000 +#define A5_PERIPHERALS_SIZE 0x10000 + +#define ARM_CACHE_WRITEBACK_SHIFT 5 + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define A5DS_IRQ_TZ_WDOG 56 +#define A5DS_IRQ_SEC_SYS_TIMER 57 + +/* Default cluster count for A5DS */ +#define A5DS_CLUSTER_COUNT U(1) + +/* Default number of CPUs per cluster on A5DS */ +#define A5DS_MAX_CPUS_PER_CLUSTER U(4) + +/* Default number of threads per CPU on A5DS */ +#define A5DS_MAX_PE_PER_CPU U(1) + +#define A5DS_CORE_COUNT U(4) + +#define A5DS_PRIMARY_CPU 0x0 + +#define BOOT_BASE ARM_DRAM1_BASE +#define BOOT_SIZE UL(0x2800000) + +#define ARM_NS_DRAM1_BASE (ARM_DRAM1_BASE + BOOT_SIZE) +/* + * The last 2MB is meant to be NOLOAD and will not be zero + * initialized. + */ +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + BOOT_SIZE - \ + 0x00200000) + +#define MAP_BOOT_RW MAP_REGION_FLAT( \ + BOOT_BASE, \ + BOOT_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + A5DS_SHARED_RAM_BASE, \ + A5DS_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, \ + ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_SRAM MAP_REGION_FLAT( \ + SRAM_BASE, \ + SRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to + * share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides + * in the BL1 RW region. Hence, BL2 needs access to the BL1 RW region in order + * to be able to access the heap. + */ + +#define ARM_MAP_BL_RO MAP_REGION_FLAT(\ + BL_CODE_BASE,\ + BL_CODE_END - BL_CODE_BASE,\ + MT_CODE | MT_SECURE),\ + MAP_REGION_FLAT(\ + BL_RO_DATA_BASE,\ + BL_RO_DATA_END\ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT(\ + BL_COHERENT_RAM_BASE,\ + BL_COHERENT_RAM_END \ + - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +/* + * Map the region for device tree configuration with read and write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \ + (ARM_FW_CONFIGS_LIMIT \ + - ARM_BL_RAM_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 6 + +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#define A5DS_TIMER_BASE_FREQUENCY UL(7500000) + +#define ARM_CONSOLE_BAUDRATE 115200 + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * To enable FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space of BL2 meminfo. + */ +#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE) + +/* + * Define limit of firmware configuration memory: + * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory + */ +#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2)) + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + ******************************************************************************/ +#define BL1_RO_BASE 0x00000000 +#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE +/* + * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE)) +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ + +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - A5DS_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE + +/* Put BL32 below BL2 in NS DRAM.*/ +#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT +#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \ + + (PAGE_SIZE / 2U)) + +#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\ + - PLAT_ARM_MAX_BL32_SIZE) +#define BL32_PROGBITS_LIMIT BL2_BASE +#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT A5DS_CORE_COUNT +#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + U(1) + +#define PLAT_MAX_PWR_LVL 2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ + +#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x10000 /* 64KB */ + +#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000) + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 6 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000 + +/* + * A5DS_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define A5DS_MAX_BL2_SIZE 0x11000 + +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL32_SIZE 0x3B000 +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* Reserve the last block of flash for PSCI MEM PROTECT flag */ +#define PLAT_ARM_FLASH_IMAGE_BASE BOOT_BASE +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE) + +#define PLAT_ARM_NVM_BASE BOOT_BASE +#define PLAT_ARM_NVM_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE 0x1A200000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ UL(7500000) + +#define PLAT_ARM_RUN_UART_BASE 0x1A210000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ UL(7500000) + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#define A5DS_TIMER_BASE_FREQUENCY UL(7500000) + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 1 + +/* Mailbox base address */ +#define A5DS_TRUSTED_MAILBOX_BASE A5DS_SHARED_RAM_BASE +#define A5DS_TRUSTED_MAILBOX_SIZE (8 + A5DS_HOLD_SIZE) +#define A5DS_HOLD_BASE (A5DS_TRUSTED_MAILBOX_BASE + 8) +#define A5DS_HOLD_SIZE (PLATFORM_CORE_COUNT * \ + A5DS_HOLD_ENTRY_SIZE) +#define A5DS_HOLD_ENTRY_SHIFT 3 +#define A5DS_HOLD_ENTRY_SIZE (1 << A5DS_HOLD_ENTRY_SHIFT) +#define A5DS_HOLD_STATE_WAIT 0 +#define A5DS_HOLD_STATE_GO 1 + +/* Snoop Control Unit base address */ +#define A5DS_SCU_BASE 0x1C000000 + +/* + * GIC related constants to cater for GICv2 + */ +#define PLAT_ARM_GICD_BASE 0x1C001000 +#define PLAT_ARM_GICC_BASE 0x1C000100 + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(A5DS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(A5DS_IRQ_SEC_SYS_TIMER,\ + GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk new file mode 100644 index 0000000..4f87306 --- /dev/null +++ b/plat/arm/board/a5ds/platform.mk @@ -0,0 +1,111 @@ +# +# Copyright (c) 2019-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Firmware Configuration Framework sources +include common/fdt_wrappers.mk +include lib/fconf/fconf.mk + +BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} +BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c + +DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES} + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +A5DS_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +A5DS_SECURITY_SOURCES := plat/arm/board/a5ds/a5ds_security.c + +PLAT_INCLUDES := -Iplat/arm/board/a5ds/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/a5ds/a5ds_common.c \ + plat/arm/common/${ARCH}/arm_helpers.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +A5DS_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/cfi/v2m/v2m_flash.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/a5ds/a5ds_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/arm/board/a5ds/${ARCH}/a5ds_helpers.S \ + plat/arm/board/a5ds/a5ds_bl1_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + ${A5DS_CPU_LIBS} \ + ${DYN_CFG_SOURCES} + +BL2_SOURCES += lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/board/a5ds/a5ds_bl2_setup.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/a5ds/a5ds_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ + plat/arm/common/arm_image_load.c \ + common/desc_image_load.c \ + ${DYN_CFG_SOURCES} \ + ${A5DS_SECURITY_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK + +FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb + +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) + +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \ + fdts/$(notdir ${FVP_HW_CONFIG_DTS}))) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG})) + +FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \ + plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \ + ${FVP_HW_CONFIG_DTS} +endif + +NEED_BL32 := yes + +MULTI_CONSOLE_API := 1 + +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch32/nonlpae_tables.c + +# Use translation tables library v1 when using Cortex-A5 +ARM_XLAT_TABLES_LIB_V1 := 1 +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) diff --git a/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c b/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c new file mode 100644 index 0000000..a951dc7 --- /dev/null +++ b/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/scu.h> +#include <plat/arm/common/plat_arm.h> + + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* enable snoop control unit */ + enable_snoop_ctrl_unit(A5DS_SCU_BASE); +} + +/* + * A5DS will only have one always-on power domain and there + * is no power control present. + */ +void plat_arm_pwrc_setup(void) +{ +} + diff --git a/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk new file mode 100644 index 0000000..4b0c97d --- /dev/null +++ b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2019, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to A5DS platform +BL32_SOURCES += drivers/arm/scu/scu.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + plat/arm/board/a5ds/aarch32/a5ds_helpers.S \ + plat/arm/board/a5ds/a5ds_pm.c \ + plat/arm/board/a5ds/a5ds_topology.c \ + plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c \ + plat/arm/common/sp_min/arm_sp_min_setup.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c \ + ${A5DS_CPU_LIBS} \ + ${A5DS_GIC_SOURCES} \ + ${A5DS_SECURITY_SOURCES} diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S new file mode 100644 index 0000000..20120c9 --- /dev/null +++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/bl_common.h> +#include "../fpga_private.h" + +#include <platform_def.h> + + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl platform_mem_init + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_fpga_calc_core_pos + +/* ----------------------------------------------------------------------- + * Indicate a cold boot for every CPU - warm boot is unsupported for the + * holding pen PSCI implementation. + * ----------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + +/* ----------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * ----------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + + /* + * Wait for the primary processor to initialise the .BSS segment + * to avoid a race condition that would erase fpga_valid_mpids + * if it is populated before the C runtime is ready. + * + * We cannot use the current spin-lock implementation until the + * runtime is up and we should not rely on sevl/wfe instructions as + * it is optional whether they are implemented or not, so we use + * a global variable as lock and wait for the primary processor to + * finish the C runtime bring-up. + */ + + ldr w0, =C_RUNTIME_READY_KEY + adrp x1, secondary_core_spinlock + add x1, x1, :lo12:secondary_core_spinlock +1: + wfe + ldr w2, [x1] + cmp w2, w0 + b.ne 1b + /* Prevent reordering of the store into fpga_valid_mpids below */ + dmb ish + + mov x10, x30 + bl plat_my_core_pos + mov x30, x10 + + adrp x4, fpga_valid_mpids + add x4, x4, :lo12:fpga_valid_mpids + mov x5, #VALID_MPID + strb w5, [x4, x0] + + /* + * Poll the CPU's hold entry until it indicates to jump + * to the entrypoint address. + */ + + adrp x1, hold_base + add x1, x1, :lo12:hold_base +poll_hold_entry: + ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT] + cmp x3, #PLAT_FPGA_HOLD_STATE_GO + b.ne 1f + + adrp x2, fpga_sec_entrypoint + add x2, x2, :lo12:fpga_sec_entrypoint + ldr x3, [x2] + br x3 +1: + wfe + b poll_hold_entry + +endfunc plat_secondary_cold_boot_setup + +/* ----------------------------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary cpu + * ----------------------------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FPGA_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + +func platform_mem_init + ret +endfunc platform_mem_init + +func plat_my_core_pos + ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)) + mrs x0, mpidr_el1 + and x0, x0, x1 + b plat_fpga_calc_core_pos + +endfunc plat_my_core_pos + +/* ----------------------------------------------------------------------- + * unsigned int plat_fpga_calc_core_pos (uint32_t mpid) + * Clobber registers: x0 to x5 + * ----------------------------------------------------------------------- + */ +func plat_fpga_calc_core_pos + /* + * Check for MT bit in MPIDR, which may be either value for images + * running on the FPGA. + * + * If not set, shift MPIDR to left to make it look as if in a + * multi-threaded implementation. + * + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + mov x4, #FPGA_MAX_CPUS_PER_CLUSTER + mov x5, #FPGA_MAX_PE_PER_CPU + + /* Compute linear position */ + madd x1, x2, x4, x1 + madd x0, x1, x5, x0 + + ret +endfunc plat_fpga_calc_core_pos + +func plat_crash_console_init + mov_imm x0, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_init +endfunc plat_crash_console_init + +func plat_crash_console_putc + mov_imm x1, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov_imm x0, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush diff --git a/plat/arm/board/arm_fpga/build_axf.ld.S b/plat/arm/board/arm_fpga/build_axf.ld.S new file mode 100644 index 0000000..d8254e5 --- /dev/null +++ b/plat/arm/board/arm_fpga/build_axf.ld.S @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Linker script for the Arm Ltd. FPGA boards to generate an ELF file that + * contains the ROM trampoline, BL31 and the DTB. + * + * This allows to pass just one file to the uploader tool, and automatically + * provides the correct load addresses. + */ + +#include <platform_def.h> + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +INPUT(./rom_trampoline.o) +INPUT(./kernel_trampoline.o) + +TARGET(binary) +INPUT(./bl31.bin) +INPUT(./fdts/arm_fpga.dtb) + +ENTRY(_start) + +SECTIONS +{ + .rom (0x0): { + *rom_trampoline.o(.text*) + KEEP(*(.rom)) + } + + .bl31 (BL31_BASE): { + ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned"); + *bl31.bin + } + + .dtb (FPGA_PRELOADED_DTB_BASE): { + ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned"); + *arm_fpga.dtb + } + + .kern_tramp (PRELOADED_BL33_BASE): { + *kernel_trampoline.o(.text*) + KEEP(*(.kern_tramp)) + } + + /DISCARD/ : { *(stacks) } + /DISCARD/ : { *(.debug_*) } + /DISCARD/ : { *(.note*) } + /DISCARD/ : { *(.comment*) } +} diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c new file mode 100644 index 0000000..e1b3abb --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <common/fdt_fixup.h> +#include <common/fdt_wrappers.h> +#include <drivers/arm/gicv3.h> +#include <drivers/delay_timer.h> +#include <drivers/generic_delay_timer.h> +#include <lib/extensions/spe.h> +#include <lib/mmio.h> +#include <libfdt.h> + +#include "fpga_private.h" +#include <plat/common/platform.h> +#include <platform_def.h> + +static entry_point_info_t bl33_image_ep_info; +static unsigned int system_freq; +volatile uint32_t secondary_core_spinlock; + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return 0ULL; +#endif +} + +uint32_t fpga_get_spsr_for_bl33_entry(void) +{ + return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Add this core to the VALID mpids list */ + fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID; + + /* + * Notify the secondary CPUs that the C runtime is ready + * so they can announce themselves. + */ + secondary_core_spinlock = C_RUNTIME_READY_KEY; + dsbish(); + sev(); + + fpga_console_init(); + + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* Set x0-x3 for the primary CPU as expected by the kernel */ + bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +} + +void bl31_plat_arch_setup(void) +{ +} + +void bl31_platform_setup(void) +{ + /* Write frequency to CNTCRL and initialize timer */ + generic_delay_timer_init(); + + /* + * Before doing anything else, wait for some time to ensure that + * the secondary CPUs have populated the fpga_valid_mpids array. + * As the number of secondary cores is unknown and can even be 0, + * it is not possible to rely on any signal from them, so use a + * delay instead. + */ + mdelay(5); + + /* + * On the event of a cold reset issued by, for instance, a reset pin + * assertion, we cannot guarantee memory to be initialized to zero. + * In such scenario, if the secondary cores reached + * plat_secondary_cold_boot_setup before the primary one initialized + * .BSS, we could end up having a race condition if the spinlock + * was not cleared before. + * + * Similarly, if there were a reset before the spinlock had been + * cleared, the secondary cores would find the lock opened before + * .BSS is cleared, causing another race condition. + * + * So clean the spinlock as soon as we think it is safe to reduce the + * chances of any race condition on a reset. + */ + secondary_core_spinlock = 0UL; + + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_fpga_gic_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + next_image_info = &bl33_image_ep_info; + + /* Only expecting BL33: the kernel will run in EL2NS */ + assert(type == NON_SECURE); + + /* None of the images can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/* + * Even though we sell the FPGA UART as an SBSA variant, it is actually + * a full fledged PL011. So the baudrate divider registers exist. + */ +#ifndef UARTIBRD +#define UARTIBRD 0x024 +#define UARTFBRD 0x028 +#endif + +/* Round an integer to the closest multiple of a value. */ +static unsigned int round_multiple(unsigned int x, unsigned int multiple) +{ + if (multiple < 2) { + return x; + } + + return ((x + (multiple / 2 - 1)) / multiple) * multiple; +} + +#define PL011_FRAC_SHIFT 6 +#define FPGA_DEFAULT_BAUDRATE 38400 +#define PL011_OVERSAMPLING 16 +static unsigned int pl011_freq_from_divider(unsigned int divider) +{ + unsigned int freq; + + freq = divider * FPGA_DEFAULT_BAUDRATE * PL011_OVERSAMPLING; + + return freq >> PL011_FRAC_SHIFT; +} + +/* + * The FPGAs run most peripherals from one main clock, among them the CPUs, + * the arch timer, and the UART baud base clock. + * The SCP knows this frequency and programs the UART clock divider for a + * 38400 bps baudrate. Recalculate the base input clock from there. + */ +static unsigned int fpga_get_system_frequency(void) +{ + const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + int node, err; + + /* + * If the arch timer DT node has an explicit clock-frequency property + * set, use that, to allow people overriding auto-detection. + */ + node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer"); + if (node >= 0) { + uint32_t freq; + + err = fdt_read_uint32(fdt, node, "clock-frequency", &freq); + if (err >= 0) { + return freq; + } + } + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011"); + if (node >= 0) { + uintptr_t pl011_base; + unsigned int divider; + + err = fdt_get_reg_props_by_index(fdt, node, 0, + &pl011_base, NULL); + if (err >= 0) { + divider = mmio_read_32(pl011_base + UARTIBRD); + divider <<= PL011_FRAC_SHIFT; + divider += mmio_read_32(pl011_base + UARTFBRD); + + /* + * The result won't be exact, due to rounding errors, + * but the input frequency was a multiple of 250 KHz. + */ + return round_multiple(pl011_freq_from_divider(divider), + 250000); + } else { + WARN("Cannot read PL011 MMIO base\n"); + } + } else { + WARN("No PL011 DT node\n"); + } + + /* No PL011 DT node or calculation failed. */ + return FPGA_DEFAULT_TIMER_FREQUENCY; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + if (system_freq == 0U) { + system_freq = fpga_get_system_frequency(); + } + + return system_freq; +} + +static void fpga_dtb_update_clock(void *fdt, unsigned int freq) +{ + uint32_t freq_dtb = fdt32_to_cpu(freq); + uint32_t phandle; + int node, err; + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011"); + if (node < 0) { + WARN("%s(): No PL011 DT node found\n", __func__); + + return; + } + + err = fdt_read_uint32(fdt, node, "clocks", &phandle); + if (err != 0) { + WARN("Cannot find clocks property\n"); + + return; + } + + node = fdt_node_offset_by_phandle(fdt, phandle); + if (node < 0) { + WARN("Cannot get phandle\n"); + + return; + } + + err = fdt_setprop_inplace(fdt, node, + "clock-frequency", + &freq_dtb, + sizeof(freq_dtb)); + if (err < 0) { + WARN("Could not update DT baud clock frequency\n"); + + return; + } +} + +#define CMDLINE_SIGNATURE "CMD:" + +static int fpga_dtb_set_commandline(void *fdt, const char *cmdline) +{ + int chosen; + const char *eol; + char nul = 0; + int slen, err; + + chosen = fdt_add_subnode(fdt, 0, "chosen"); + if (chosen == -FDT_ERR_EXISTS) { + chosen = fdt_path_offset(fdt, "/chosen"); + } + + if (chosen < 0) { + return chosen; + } + + /* + * There is most likely an EOL at the end of the + * command line, make sure we terminate the line there. + * We can't replace the EOL with a NUL byte in the + * source, as this is in read-only memory. So we first + * create the property without any termination, then + * append a single NUL byte. + */ + eol = strchr(cmdline, '\n'); + if (eol == NULL) { + eol = strchr(cmdline, 0); + } + /* Skip the signature and omit the EOL/NUL byte. */ + slen = eol - (cmdline + strlen(CMDLINE_SIGNATURE)); + /* + * Let's limit the size of the property, just in case + * we find the signature by accident. The Linux kernel + * limits to 4096 characters at most (in fact 2048 for + * arm64), so that sounds like a reasonable number. + */ + if (slen > 4095) { + slen = 4095; + } + + err = fdt_setprop(fdt, chosen, "bootargs", + cmdline + strlen(CMDLINE_SIGNATURE), slen); + if (err != 0) { + return err; + } + + return fdt_appendprop(fdt, chosen, "bootargs", &nul, 1); +} + +static void fpga_prepare_dtb(void) +{ + void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE; + int err; + + err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE); + if (err < 0) { + ERROR("cannot open devicetree at %p: %d\n", fdt, err); + panic(); + } + + /* Reserve memory used by Trusted Firmware. */ + if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE, + BL31_LIMIT - BL31_BASE)) { + WARN("Failed to add reserved memory node to DT\n"); + } + + /* Check for the command line signature. */ + if (!strncmp(cmdline, CMDLINE_SIGNATURE, strlen(CMDLINE_SIGNATURE))) { + err = fpga_dtb_set_commandline(fdt, cmdline); + if (err == 0) { + INFO("using command line at 0x%x\n", + FPGA_PRELOADED_CMD_LINE); + } else { + ERROR("failed to put command line into DTB: %d\n", err); + } + } + + if (err < 0) { + ERROR("Error %d extending Device Tree\n", err); + panic(); + } + + err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU, + FPGA_MAX_CPUS_PER_CLUSTER, + FPGA_MAX_CLUSTER_COUNT); + + if (err == -EEXIST) { + WARN("Not overwriting already existing /cpus node in DTB\n"); + } else { + if (err < 0) { + ERROR("Error %d creating the /cpus DT node\n", err); + panic(); + } else { + unsigned int nr_cores = fpga_get_nr_gic_cores(); + + INFO("Adjusting GICR DT region to cover %u cores\n", + nr_cores); + err = fdt_adjust_gic_redist(fdt, nr_cores, + fpga_get_redist_base(), + fpga_get_redist_size()); + if (err < 0) { + ERROR("Error %d fixing up GIC DT node\n", err); + } + } + } + + fpga_dtb_update_clock(fdt, system_freq); + + /* Check whether we support the SPE PMU. Remove the DT node if not. */ + if (!spe_supported()) { + int node = fdt_node_offset_by_compatible(fdt, 0, + "arm,statistical-profiling-extension-v1"); + + if (node >= 0) { + fdt_del_node(fdt, node); + } + } + + /* Check whether we have an ITS. Remove the DT node if not. */ + if (!fpga_has_its()) { + int node = fdt_node_offset_by_compatible(fdt, 0, + "arm,gic-v3-its"); + + if (node >= 0) { + fdt_del_node(fdt, node); + } + } + + err = fdt_pack(fdt); + if (err < 0) { + ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err); + } + + clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt)); +} + +void bl31_plat_runtime_setup(void) +{ + fpga_prepare_dtb(); +} + +void bl31_plat_enable_mmu(uint32_t flags) +{ + /* TODO: determine if MMU needs to be enabled */ +} diff --git a/plat/arm/board/arm_fpga/fpga_console.c b/plat/arm/board/arm_fpga/fpga_console.c new file mode 100644 index 0000000..8c1da62 --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_console.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> +#include <stdint.h> + +#include <common/fdt_wrappers.h> +#include <drivers/arm/pl011.h> +#include <drivers/console.h> + +#include <platform_def.h> + +static console_t console; + +void fpga_console_init(void) +{ + const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + uintptr_t base_addr = PLAT_FPGA_CRASH_UART_BASE; + int node; + + /* + * Try to read the UART base address from the DT, by chasing the + * stdout-path property of the chosen node. + * If this does not work, use the crash console address as a fallback. + */ + node = fdt_get_stdout_node_offset(fdt); + if (node >= 0) { + fdt_get_reg_props_by_index(fdt, node, 0, &base_addr, NULL); + } + + (void)console_pl011_register(base_addr, 0, 0, &console); + + console_set_scope(&console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME); +} diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h new file mode 100644 index 0000000..2884ea6 --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_def.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/utils_def.h> + +#ifndef FPGA_DEF_H +#define FPGA_DEF_H + +/* + * These are set to large values to account for images describing systems with + * larger cluster configurations. + * + * For cases where the number of clusters, cores or threads is smaller than a + * maximum value below, this does not affect the PSCI functionality as any PEs + * that are present will still be indexed appropriately regardless of any empty + * entries in the array used to represent the topology. + */ + +#define FPGA_MAX_CLUSTER_COUNT 4 +#define FPGA_MAX_CPUS_PER_CLUSTER 8 +#define FPGA_MAX_PE_PER_CPU 4 + +#define FPGA_PRIMARY_CPU 0x0 +/******************************************************************************* + * FPGA image memory map related constants + ******************************************************************************/ + +/* + * UART base address, just for the crash console, as a fallback. + * The actual console UART address is taken from the DT. + */ +#define PLAT_FPGA_CRASH_UART_BASE 0x7ff80000 + +#define FPGA_DEFAULT_TIMER_FREQUENCY 10000000 + +#endif diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c new file mode 100644 index 0000000..e06a9da --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_gicv3.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <common/fdt_wrappers.h> +#include <drivers/arm/arm_gicv3_common.h> +#include <drivers/arm/gic_common.h> +#include <drivers/arm/gicv3.h> +#include <lib/mmio.h> +#include <libfdt.h> + +#include <platform_def.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +static const interrupt_prop_t fpga_interrupt_props[] = { + PLATFORM_G1S_PROPS(INTR_GROUP1S), + PLATFORM_G0_PROPS(INTR_GROUP0) +}; + +static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT]; +static int nr_itses; + +static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +static gicv3_driver_data_t fpga_gicv3_driver_data = { + .interrupt_props = fpga_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = fpga_rdistif_base_addrs, + .mpidr_to_core_pos = fpga_mpidr_to_core_pos +}; + +void plat_fpga_gic_init(void) +{ + const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + uintptr_t gicr_base = 0U; + uint32_t iidr; + int node, ret; + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,gic-v3"); + if (node < 0) { + WARN("No \"arm,gic-v3\" compatible node found in DT, no GIC support.\n"); + return; + } + + /* TODO: Assuming only empty "ranges;" properties up the bus path. */ + ret = fdt_get_reg_props_by_index(fdt, node, 0, + &fpga_gicv3_driver_data.gicd_base, NULL); + if (ret < 0) { + WARN("Could not read GIC distributor address from DT.\n"); + return; + } + + iidr = mmio_read_32(fpga_gicv3_driver_data.gicd_base + GICD_IIDR); + if (((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || + ((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)) { + unsigned int frame_id; + + /* + * According to the GIC TRMs, if there are any ITSes, they + * start four 64K pages after the distributor. After all + * the ITSes then follow the redistributors. + */ + gicr_base = fpga_gicv3_driver_data.gicd_base + (4U << 16); + + do { + uint64_t its_typer; + + /* Each GIC component can be identified by its ID. */ + frame_id = gicv3_get_component_partnum(gicr_base); + + if (frame_id == PIDR_COMPONENT_ARM_REDIST) { + INFO("Found %d ITSes, redistributors start at 0x%llx\n", + nr_itses, (unsigned long long)gicr_base); + break; + } + + if (frame_id != PIDR_COMPONENT_ARM_ITS) { + WARN("GICv3: found unexpected frame 0x%x\n", + frame_id); + gicr_base = 0U; + break; + } + + /* + * Found an ITS, now work out if it supports virtual + * SGIs (for direct guest injection). If yes, each + * ITS occupies four 64K pages, otherwise just two. + */ + its_typer = mmio_read_64(gicr_base + GITS_TYPER); + if ((its_typer & GITS_TYPER_VSGI) != 0U) { + gicr_base += 4U << 16; + } else { + gicr_base += 2U << 16; + } + nr_itses++; + } while (true); + } + + /* + * If this is not a GIC-600 or -700, or the autodetection above failed, + * use the base address from the device tree. + */ + if (gicr_base == 0U) { + ret = fdt_get_reg_props_by_index(fdt, node, 1, + &fpga_gicv3_driver_data.gicr_base, + NULL); + if (ret < 0) { + WARN("Could not read GIC redistributor address from DT.\n"); + return; + } + } else { + fpga_gicv3_driver_data.gicr_base = gicr_base; + } + + gicv3_driver_init(&fpga_gicv3_driver_data); + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void fpga_pwr_gic_on_finish(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void fpga_pwr_gic_off(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); + gicv3_rdistif_off(plat_my_core_pos()); +} + +unsigned int fpga_get_nr_gic_cores(void) +{ + return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base); +} + +uintptr_t fpga_get_redist_size(void) +{ + uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base + + GICR_TYPER); + + return gicv3_redist_size(typer_val); +} + +uintptr_t fpga_get_redist_base(void) +{ + return fpga_gicv3_driver_data.gicr_base; +} + +bool fpga_has_its(void) +{ + return nr_itses > 0; +} diff --git a/plat/arm/board/arm_fpga/fpga_pm.c b/plat/arm/board/arm_fpga/fpga_pm.c new file mode 100644 index 0000000..a306a23 --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_pm.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#include "fpga_private.h" +#include <platform_def.h> + +/* + * This is a basic PSCI implementation that allows secondary CPUs to be + * released from their initial state and continue to the warm boot entrypoint. + * + * The secondary CPUs are placed in a holding pen and released by calls + * to fpga_pwr_domain_on(mpidr), which updates the hold entry for the CPU + * specified by the mpidr argument - the (polling) target CPU will then branch + * to the BL31 warm boot sequence at the entrypoint address. + * + * Additionally, the secondary CPUs are kept in a low-power wfe() state + * (placed there at the end of each poll) and woken when necessary through + * calls to sev() in fpga_pwr_domain_on(mpidr), once the hold state for the + * relevant CPU has been updated. + * + * Hotplug is currently implemented using a wfi-loop, which removes the + * dependencies on any power controllers or other mechanism that is specific + * to the running system as specified by the FPGA image. + */ + +uint64_t hold_base[PLATFORM_CORE_COUNT]; +uintptr_t fpga_sec_entrypoint; + +/* + * Calls to the CPU specified by the mpidr will set its hold entry to a value + * indicating that it should stop polling and branch off to the warm entrypoint. + */ +static int fpga_pwr_domain_on(u_register_t mpidr) +{ + int pos = plat_core_pos_by_mpidr(mpidr); + unsigned long current_mpidr = read_mpidr_el1(); + + if (pos < 0) { + panic(); + } + + if (mpidr == current_mpidr) { + return PSCI_E_ALREADY_ON; + } + hold_base[pos] = PLAT_FPGA_HOLD_STATE_GO; + flush_dcache_range((uintptr_t)&hold_base[pos], sizeof(uint64_t)); + sev(); /* Wake any CPUs from wfe */ + + return PSCI_E_SUCCESS; +} + +void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + fpga_pwr_gic_on_finish(); +} + +static void fpga_pwr_domain_off(const psci_power_state_t *target_state) +{ + fpga_pwr_gic_off(); + + while (1) { + wfi(); + } +} + +static void fpga_cpu_standby(plat_local_state_t cpu_state) +{ + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + u_register_t scr = read_scr_el3(); + write_scr_el3(scr|SCR_IRQ_BIT); + dsb(); + wfi(); + write_scr_el3(scr); +} + +plat_psci_ops_t plat_fpga_psci_pm_ops = { + .pwr_domain_on = fpga_pwr_domain_on, + .pwr_domain_on_finish = fpga_pwr_domain_on_finish, + .pwr_domain_off = fpga_pwr_domain_off, + .cpu_standby = fpga_cpu_standby +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + fpga_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&fpga_sec_entrypoint, + sizeof(fpga_sec_entrypoint)); + *psci_ops = &plat_fpga_psci_pm_ops; + return 0; +} diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h new file mode 100644 index 0000000..84d651c --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FPGA_PRIVATE_H +#define FPGA_PRIVATE_H + +#include "../fpga_def.h" +#include <platform_def.h> + +#define C_RUNTIME_READY_KEY (0xaa55aa55) +#define VALID_MPID (1U) +#define FPGA_MAX_DTB_SIZE 0x10000 + +#ifndef __ASSEMBLER__ + +extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT]; + +void fpga_console_init(void); + +void plat_fpga_gic_init(void); +void fpga_pwr_gic_on_finish(void); +void fpga_pwr_gic_off(void); +unsigned int plat_fpga_calc_core_pos(uint32_t mpid); +unsigned int fpga_get_nr_gic_cores(void); +uintptr_t fpga_get_redist_size(void); +uintptr_t fpga_get_redist_base(void); +bool fpga_has_its(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* FPGA_PRIVATE_H */ diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c new file mode 100644 index 0000000..7fead86 --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_topology.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/spinlock.h> + +#include "fpga_private.h" +#include <plat/common/platform.h> +#include <platform_def.h> + +unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2]; +unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT]; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + * + * This description of the power domain topology is aligned with the CPU + * indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos() + * APIs. + * + * A description of the topology tree can be found at + * https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design + */ + + if (fpga_power_domain_tree_desc[0] == 0U) { + /* + * As fpga_power_domain_tree_desc[0] == 0, assume that the + * Power Domain Topology Tree has not been initialized, so + * perform the initialization here. + */ + + fpga_power_domain_tree_desc[0] = 1U; + fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT; + + for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) { + fpga_power_domain_tree_desc[2 + i] = + (FPGA_MAX_CPUS_PER_CLUSTER * + FPGA_MAX_PE_PER_CPU); + } + } + + return fpga_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int core_pos; + + mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)); + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + + if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) || + (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) || + (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) { + ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr); + panic(); + } + + /* Calculate the core position, based on the maximum topology. */ + core_pos = plat_fpga_calc_core_pos(mpidr); + + /* Check whether this core is actually present. */ + if (fpga_valid_mpids[core_pos] != VALID_MPID) { + return -1; + } + + return core_pos; +} diff --git a/plat/arm/board/arm_fpga/include/plat_macros.S b/plat/arm/board/arm_fpga/include/plat_macros.S new file mode 100644 index 0000000..44cddeb --- /dev/null +++ b/plat/arm/board/arm_fpga/include/plat_macros.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +.macro plat_crash_print_regs +.endm + +#endif diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h new file mode 100644 index 0000000..2350d87 --- /dev/null +++ b/plat/arm/board/arm_fpga/include/platform_def.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <plat/common/common_def.h> +#include <platform_def.h> +#include "../fpga_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" + +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE UL(0x800) + +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +#define PLATFORM_CORE_COUNT \ + (FPGA_MAX_CLUSTER_COUNT * \ + FPGA_MAX_CPUS_PER_CLUSTER * \ + FPGA_MAX_PE_PER_CPU) + +#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1) + +#if !ENABLE_PIE +#define BL31_BASE UL(0x80000000) +#define BL31_LIMIT UL(0x80070000) +#else +#define BL31_BASE UL(0x0) +#define BL31_LIMIT UL(0x01000000) +#endif + +#define PLAT_SDEI_NORMAL_PRI 0x70 + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define PLATFORM_G0_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_FPGA_HOLD_ENTRY_SHIFT 3 +#define PLAT_FPGA_HOLD_STATE_WAIT 0 +#define PLAT_FPGA_HOLD_STATE_GO 1 + +#endif diff --git a/plat/arm/board/arm_fpga/kernel_trampoline.S b/plat/arm/board/arm_fpga/kernel_trampoline.S new file mode 100644 index 0000000..f4c08ef --- /dev/null +++ b/plat/arm/board/arm_fpga/kernel_trampoline.S @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The traditional arm64 Linux kernel load address is 512KiB from the + * beginning of DRAM, caused by this having been the default value of the + * kernel's CONFIG_TEXT_OFFSET Kconfig value. + * However kernel version 5.8 changed the default offset (into a 2MB page) + * to 0, so TF-A's default assumption is no longer true. Fortunately the + * kernel got more relaxed about this offset at the same time, so it + * tolerates the wrong offset, but issues a warning: + * [Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader! + * + * We cannot easily change the load address offset in TF-A to be 2MiB, because + * this would break older kernels - and they are not as forgiving in this + * respect. + * + * But we can allow users to load the kernel at the right offset, and + * offer this trampoline here to transition to this new load address. + * Any older kernels, or newer kernels misloaded, will overwrite this code + * here, so it does no harm in this case. + */ + +#include <asm_macros.S> +#include <common/bl_common.ld.h> + +.text +.global _tramp_start + +_tramp_start: + adr x4, _tramp_start + orr x4, x4, #0x1fffff + add x4, x4, #1 /* align up to 2MB */ + br x4 diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk new file mode 100644 index 0000000..a14a0d8 --- /dev/null +++ b/plat/arm/board/arm_fpga/platform.mk @@ -0,0 +1,130 @@ +# +# Copyright (c) 2021-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk +include lib/libfdt/libfdt.mk + +RESET_TO_BL31 := 1 +ifeq (${RESET_TO_BL31}, 0) +$(error "This is a BL31-only port; RESET_TO_BL31 must be enabled") +endif + +ifeq (${ENABLE_PIE}, 1) +override SEPARATE_CODE_AND_RODATA := 1 +endif + +CTX_INCLUDE_AARCH32_REGS := 0 +ifeq (${CTX_INCLUDE_AARCH32_REGS}, 1) +$(error "This is an AArch64-only port; CTX_INCLUDE_AARCH32_REGS must be disabled") +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(error "TRUSTED_BOARD_BOOT must be disabled") +endif + +PRELOADED_BL33_BASE := 0x80080000 + +FPGA_PRELOADED_DTB_BASE := 0x80070000 +$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE)) + +FPGA_PRELOADED_CMD_LINE := 0x1000 +$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE)) + +ENABLE_AMU := 1 + +# Treating this as a memory-constrained port for now +USE_COHERENT_MEM := 0 + +# This can be overridden depending on CPU(s) used in the FPGA image +HW_ASSISTED_COHERENCY := 1 + +PL011_GENERIC_UART := 1 + +SUPPORT_UNKNOWN_MPID ?= 1 + +FPGA_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +# select a different set of CPU files, depending on whether we compile for +# hardware assisted coherency cores or not +ifeq (${HW_ASSISTED_COHERENCY}, 0) +# Cores used without DSU + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S +else +# AArch64-only cores + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \ + lib/cpus/aarch64/cortex_a76ae.S \ + lib/cpus/aarch64/cortex_a77.S \ + lib/cpus/aarch64/cortex_a78.S \ + lib/cpus/aarch64/neoverse_n_common.S \ + lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_e1.S \ + lib/cpus/aarch64/neoverse_v1.S \ + lib/cpus/aarch64/cortex_a78_ae.S \ + lib/cpus/aarch64/cortex_a65.S \ + lib/cpus/aarch64/cortex_a65ae.S \ + lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_a715.S \ + lib/cpus/aarch64/cortex_x3.S \ + lib/cpus/aarch64/cortex_a78c.S + +# AArch64/AArch32 cores + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S +endif + +ifeq (${SUPPORT_UNKNOWN_MPID}, 1) +# Add support for unknown/invalid MPIDs (aarch64 only) +$(eval $(call add_define,SUPPORT_UNKNOWN_MPID)) + FPGA_CPU_LIBS += lib/cpus/aarch64/generic.S +endif + +# Allow detection of GIC-600 +GICV3_SUPPORT_GIC600 := 1 + +GIC_ENABLE_V4_EXTN := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +FPGA_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/board/arm_fpga/fpga_gicv3.c + +FDT_SOURCES := fdts/arm_fpga.dts + +PLAT_INCLUDES := -Iplat/arm/board/arm_fpga/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/arm_fpga/${ARCH}/fpga_helpers.S + +BL31_SOURCES += common/fdt_fixup.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/common/plat_psci_common.c \ + plat/arm/board/arm_fpga/fpga_pm.c \ + plat/arm/board/arm_fpga/fpga_topology.c \ + plat/arm/board/arm_fpga/fpga_console.c \ + plat/arm/board/arm_fpga/fpga_bl31_setup.c \ + ${FPGA_CPU_LIBS} \ + ${FPGA_GIC_SOURCES} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,bl31)) +$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,bl31)) +$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,bl31)) + +bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld + $(ECHO) " LD $@" + $(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf + +all: bl31.axf diff --git a/plat/arm/board/arm_fpga/rom_trampoline.S b/plat/arm/board/arm_fpga/rom_trampoline.S new file mode 100644 index 0000000..cd66c79 --- /dev/null +++ b/plat/arm/board/arm_fpga/rom_trampoline.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The Arm Ltd. FPGA images start execution at address 0x0, which is + * mapped at an (emulated) ROM image. The payload uploader can write to + * this memory, but write access by the CPU cores is prohibited. + * + * Provide a simple trampoline to start BL31 execution at the actual + * load address. We put the DTB address in x0, so any code in DRAM could + * make use of that information (not yet used in BL31 right now). + */ + +#include <asm_macros.S> +#include <common/bl_common.ld.h> + +.text +.global _start + +_start: + mov_imm x1, BL31_BASE /* beginning of DRAM */ + mov_imm x0, FPGA_PRELOADED_DTB_BASE + br x1 diff --git a/plat/arm/board/common/aarch32/board_arm_helpers.S b/plat/arm/board/common/aarch32/board_arm_helpers.S new file mode 100644 index 0000000..8c63693 --- /dev/null +++ b/plat/arm/board/common/aarch32/board_arm_helpers.S @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <common/bl_common.h> +#include <platform_def.h> + + .globl plat_report_exception + + + /* ------------------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On FVP platform, it updates the LEDs + * to indicate where we are. + * SYS_LED[0] - 0x0 + * SYS_LED[2:1] - 0x0 + * SYS_LED[7:3] - Exception Mode. + * Clobbers: r0-r1 + * ------------------------------------------------------- + */ +func plat_report_exception + lsl r0, r0, #V2M_SYS_LED_EC_SHIFT + ldr r1, =V2M_SYSREGS_BASE + add r1, r1, #V2M_SYS_LED + str r0, [r1] + bx lr +endfunc plat_report_exception diff --git a/plat/arm/board/common/aarch64/board_arm_helpers.S b/plat/arm/board/common/aarch64/board_arm_helpers.S new file mode 100644 index 0000000..cde6b00 --- /dev/null +++ b/plat/arm/board/common/aarch64/board_arm_helpers.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <common/bl_common.h> +#include <platform_def.h> + + .globl plat_report_exception + + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On FVP platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mrs x1, CurrentEl + lsr x1, x1, #MODE_EL_SHIFT + lsl x1, x1, #V2M_SYS_LED_EL_SHIFT + lsl x0, x0, #V2M_SYS_LED_EC_SHIFT + mov x2, #(SECURE << V2M_SYS_LED_SS_SHIFT) + orr x0, x0, x2 + orr x0, x0, x1 + mov x1, #V2M_SYSREGS_BASE + add x1, x1, #V2M_SYS_LED + str w0, [x1] + ret +endfunc plat_report_exception diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c new file mode 100644 index 0000000..714c444 --- /dev/null +++ b/plat/arm/board/common/board_arm_trusted_boot.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#include <common/debug.h> +#include <drivers/arm/cryptocell/cc_rotpk.h> +#include <drivers/delay_timer.h> +#include <lib/cassert.h> +#include <lib/fconf/fconf.h> +#include <plat/common/common_def.h> +#include <plat/common/platform.h> +#if defined(ARM_COT_cca) +#include <tools_share/cca_oid.h> +#elif defined(ARM_COT_dualroot) +#include <tools_share/dualroot_oid.h> +#elif defined(ARM_COT_tbbr) +#include <tools_share/tbbr_oid.h> +#endif + +#include <plat/arm/common/fconf_nv_cntr_getter.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +#if !ARM_CRYPTOCELL_INTEG +#if !ARM_ROTPK_LOCATION_ID + #error "ARM_ROTPK_LOCATION_ID not defined" +#endif +#endif + +#if COT_DESC_IN_DTB && defined(IMAGE_BL2) +uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS]; +#else +uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS] = { + TFW_NVCTR_BASE, + NTFW_CTR_BASE +}; +#endif + + +/* Weak definition may be overridden in specific platform */ +#pragma weak plat_get_nv_ctr +#pragma weak plat_set_nv_ctr + +extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) || ARM_CRYPTOCELL_INTEG +static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN]; +#endif + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) +/* + * Return the ROTPK hash stored in dedicated registers. + */ +int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint8_t *dst; + uint32_t *src, tmp; + unsigned int words, i; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + + memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); + dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; + + words = ARM_ROTPK_HASH_LEN >> 2; + + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)(tmp & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + } + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags = ROTPK_IS_HASH; + return 0; +} +#endif + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ + (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) +/* + * Return development ROTPK hash generated from ROT_KEY. + */ +int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = arm_rotpk_header; + *key_len = arm_rotpk_hash_end - arm_rotpk_header; + *flags = ROTPK_IS_HASH; + return 0; +} +#endif + +#if ARM_CRYPTOCELL_INTEG +/* + * Return ROTPK hash from CryptoCell. + */ +int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + unsigned char *dst; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); + dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; + *key_ptr = rotpk_hash_der; + *key_len = sizeof(rotpk_hash_der); + return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags); +} +#endif + +/* + * Wrapper function for most Arm platforms to get ROTPK hash. + */ +static int get_rotpk_info(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ +#if ARM_CRYPTOCELL_INTEG + return arm_get_rotpk_info_cc(key_ptr, key_len, flags); +#else + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ + (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) + return arm_get_rotpk_info_dev(key_ptr, key_len, flags); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + return arm_get_rotpk_info_regs(key_ptr, key_len, flags); +#else + return 1; +#endif +#endif /* ARM_CRYPTOCELL_INTEG */ +} + +#if defined(ARM_COT_tbbr) + +int arm_get_rotpk_info(void *cookie __unused, void **key_ptr, + unsigned int *key_len, unsigned int *flags) +{ + return get_rotpk_info(key_ptr, key_len, flags); +} + +#elif defined(ARM_COT_dualroot) + +int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + /* + * Return the right root of trust key hash based on the cookie value: + * - NULL means the primary ROTPK. + * - Otherwise, interpret cookie as the OID of the certificate + * extension containing the key. + */ + if (cookie == NULL) { + return get_rotpk_info(key_ptr, key_len, flags); + } else if (strcmp(cookie, PROT_PK_OID) == 0) { + extern unsigned char arm_protpk_hash[]; + extern unsigned char arm_protpk_hash_end[]; + *key_ptr = arm_protpk_hash; + *key_len = arm_protpk_hash_end - arm_protpk_hash; + *flags = ROTPK_IS_HASH; + return 0; + } else { + /* Invalid key ID. */ + return 1; + } +} + +#elif defined(ARM_COT_cca) + +int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + /* + * Return the right root of trust key hash based on the cookie value: + * - NULL means the primary ROTPK. + * - Otherwise, interpret cookie as the OID of the certificate + * extension containing the key. + */ + if (cookie == NULL) { + return get_rotpk_info(key_ptr, key_len, flags); + } else if (strcmp(cookie, PROT_PK_OID) == 0) { + extern unsigned char arm_protpk_hash[]; + extern unsigned char arm_protpk_hash_end[]; + *key_ptr = arm_protpk_hash; + *key_len = arm_protpk_hash_end - arm_protpk_hash; + *flags = ROTPK_IS_HASH; + return 0; + } else if (strcmp(cookie, SWD_ROT_PK_OID) == 0) { + extern unsigned char arm_swd_rotpk_hash[]; + extern unsigned char arm_swd_rotpk_hash_end[]; + *key_ptr = arm_swd_rotpk_hash; + *key_len = arm_swd_rotpk_hash_end - arm_swd_rotpk_hash; + *flags = ROTPK_IS_HASH; + return 0; + } else { + /* Invalid key ID. */ + return 1; + } +} + +#endif + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + const char *oid; + uint32_t *nv_ctr_addr; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr, + NON_TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + *nv_ctr = (unsigned int)(*nv_ctr_addr); + + return 0; +} + +/* + * Store a new non-volatile counter value. By default on ARM development + * platforms, the non-volatile counters are RO and cannot be modified. We expect + * the values in the certificates to always match the RO values so that this + * function is never called. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk new file mode 100644 index 0000000..1d0eb13 --- /dev/null +++ b/plat/arm/board/common/board_common.mk @@ -0,0 +1,120 @@ +# +# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +BL1_SOURCES += drivers/cfi/v2m/v2m_flash.c + +BL2_SOURCES += drivers/cfi/v2m/v2m_flash.c + +ifneq (${TRUSTED_BOARD_BOOT},0) +ifneq (${ARM_CRYPTOCELL_INTEG}, 1) +# ROTPK hash location +ifeq (${ARM_ROTPK_LOCATION}, regs) + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID +else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa) + CRYPTO_ALG=rsa + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID + ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin +$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"')) +$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH) +$(warning Development keys support for FVP is deprecated. Use `regs` \ +option instead) +else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa) + CRYPTO_ALG=ec + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID + ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin +$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"')) +$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH) +$(warning Development keys support for FVP is deprecated. Use `regs` \ +option instead) +else +$(error "Unsupported ARM_ROTPK_LOCATION value") +endif + +$(eval $(call add_define,ARM_ROTPK_LOCATION_ID)) + +ifeq (${ENABLE_RME}, 1) +COT := cca +endif + +# Force generation of the new hash if ROT_KEY is specified +ifdef ROT_KEY + HASH_PREREQUISITES = $(ROT_KEY) FORCE +else + HASH_PREREQUISITES = $(ROT_KEY) +endif + +$(ARM_ROTPK_HASH) : $(HASH_PREREQUISITES) +ifndef ROT_KEY + $(error Cannot generate hash: no ROT_KEY defined) +endif + ${OPENSSL_BIN_PATH}/openssl ${CRYPTO_ALG} -in $< -pubout -outform DER | \ + ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ + +# Certificate NV-Counters. Use values corresponding to tied off values in +# ARM development platforms +TFW_NVCTR_VAL ?= 31 +NTFW_NVCTR_VAL ?= 223 +else +# Certificate NV-Counters when CryptoCell is integrated. For development +# platforms we set the counter to first valid value. +TFW_NVCTR_VAL ?= 0 +NTFW_NVCTR_VAL ?= 0 +endif +BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \ + plat/arm/board/common/rotpk/arm_dev_rotpk.S +BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \ + plat/arm/board/common/rotpk/arm_dev_rotpk.S + +# Allows platform code to provide implementation variants depending on the +# selected chain of trust. +$(eval $(call add_define,ARM_COT_${COT})) + +ifeq (${COT},dualroot) +# Platform Root of Trust key files. +ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem +ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin + +# Provide the private key to cert_create tool. It needs it to sign the images. +PROT_KEY := ${ARM_PROT_KEY} + +$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"')) + +BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S +BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S + +$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH) +$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH) +endif + +ifeq (${COT},cca) +# Platform and Secure World Root of Trust key files. +ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem +ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin +ARM_SWD_ROT_KEY := plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem +ARM_SWD_ROTPK_HASH := plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin + +# Provide the private keys to cert_create tool. It needs them to sign the images. +PROT_KEY := ${ARM_PROT_KEY} +SWD_ROT_KEY := ${ARM_SWD_ROT_KEY} + +$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"')) +$(eval $(call add_define_val,ARM_SWD_ROTPK_HASH,'"$(ARM_SWD_ROTPK_HASH)"')) + +BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S \ + plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S +BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S \ + plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S + +$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH) +$(BUILD_PLAT)/bl1/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK_HASH) +$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH) +$(BUILD_PLAT)/bl2/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK_HASH) +endif + +endif diff --git a/plat/arm/board/common/protpk/README b/plat/arm/board/common/protpk/README new file mode 100644 index 0000000..3aca180 --- /dev/null +++ b/plat/arm/board/common/protpk/README @@ -0,0 +1,14 @@ +This directory contains some development keys to be used as the platform +root-of-trust key. + +* arm_protprivk_rsa.pem is a 2K RSA private key in PEM format. It has been + generated using the openssl command line tool: + + openssl genrsa 2048 > arm_protprivk_rsa.pem + +* arm_protpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key + associated with the above private key. It has been generated using the openssl + command line tool: + + openssl rsa -in arm_protprivk_rsa.pem -pubout -outform DER | \ + openssl dgst -sha256 -binary > arm_protpk_rsa_sha256.bin diff --git a/plat/arm/board/common/protpk/arm_dev_protpk.S b/plat/arm/board/common/protpk/arm_dev_protpk.S new file mode 100644 index 0000000..2688cbb --- /dev/null +++ b/plat/arm/board/common/protpk/arm_dev_protpk.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global arm_protpk_hash + .global arm_protpk_hash_end + + .section .rodata.arm_protpk_hash, "a" + +arm_protpk_hash: + /* DER header. */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* Key hash. */ + .incbin ARM_PROTPK_HASH +arm_protpk_hash_end: diff --git a/plat/arm/board/common/protpk/arm_protprivk_rsa.pem b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem new file mode 100644 index 0000000..eeaad9e --- /dev/null +++ b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAzR0h/Z4Up17wfuRlYrUWseGDmlGKpl1PflGiYbyVmI7PwTTp +y/T77EiljGp52suLWntHsc0lee50pW16DU2c5bVfmyofau3GjJ1Yqw5XFAahr6eM +/0mkN8utrevvcRT9CP07D+zdhb/WlRUAnedqr/AUHU8BXS+Bxe8P0Z0Z7+DKjYZp +thzXxsjKM02BFFzNwyVrlyBFDkW/53A4M+dpmuWDjAGCJH88W/u0LdmLcii11IzD +/Ofz8Jxc/ZhqL+9FFK4qU+AJp8yXAnACSB46DlNltJrode0y5tmPhtS37ZF7EFb8 +UZWwZVgtuQyuyz9RYUS6jtiGuq6s8GlRwjTe7wIDAQABAoIBAFoWIYeyln+sQxR4 +W88umfkmgxaUGcFX2kIwuJEUst9+WeERzF24C62LeqphWYOvQlVLMAH3iC41fSXr +H2AYZoC9WHBd386nAD1iHj+C3Nv+zaTIgjTdszKOUonAxjl0bm40SmyELAdCaoyv +3MV9jm4Xk74LpR24b9bvWJNH3MxttH9hiYS+n0IzeTXDfO8GrNvHh92zx+jo8yMm +Khhu+TDC9jA2pHpJcF/0EXxYMhwYiQT16nnHb+xMgS4JpalQhvVK01s4VYGHRoFk +K6xh4TIS336LDLyalrGsPlfNfEdx+DimShDIfBUx9Jp3Pp11TUQUz4rhIHB9WdfG +b6bV4wECgYEA+cgPS2TQ7XQ1RJq1S7OGePtBXvnoH226KwGS6Fey8838tLxbblim +MU+EOYs3O66V6U2YpzmIakXo8030k8thY+jKbZl3l0m/hMuPOG66hfE5i7dYsiP4 +atok5wFiNeNYYjHMEayzk53MhG8EOh36msAO7ohKmenONUBA7pk6yTkCgYEA0jhk +HPshwi+wKkx+JLTnuoEgx40tkRgSF2xBqKssMTasaQmX8qG+w9CEs0R8nZCI70Vc +tXSFcidjdkHUVE2WsygIFuS1tbsAnpaxtn3E6rjie30X/Z280+TV0HjR0EMETmwl +ShC5lZ0oP3LpEZfjbR5qs2kFW4MOxA7tjQVaMWcCgYEA5ZbVMBifzdMl70RA5i9C +qEtSQAl3KgRCvar5rKSHsX+iC0Kiy9+iCusq/3WONEZ6NvMDIJpKYFyYDaOW7o5f +m2TrRChu+1lnN5mfsGBfBCTBH0JMvZlAin6ussLb0eqBX+ijyY8zlLjTttsQSJcr +tThZwTj3UVfOGbZQuL+RgEkCgYBXO3U3nXI9vUIx2zoBC1yZRNoQVGITMlTXiWGZ +lyYoadKTZ5q44Sti4BUguounaoGYIEU/OtHhM70PJnPwY53kS/lHXrKUbbvtEwU9 +f+UFraC1s4wP/rOLjgq3jlsqO5T+4dt7Z4NLNUKtSYazeT6zWgrW1f6WIcUv0C38 +9bqegwKBgFCK3Oa5ibL5sPaPQ/1UfdeW4JVuu6A4JhHS7r+cVLsmcrvE1Qv7Wcvw +B5aqXeqLu2dtIN8/f++3tzccs9LXKY/fh72D4TVjfrqOSSZoGTH9l4U5NXbqWM3I +skkAYb2bMST/d1qSyYesgXVNAlaQHRh3vEz8x853nJ3v9OFj8/rW +-----END RSA PRIVATE KEY----- diff --git a/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/plat/arm/board/common/rotpk/arm_dev_rotpk.S new file mode 100644 index 0000000..06e2a06 --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_dev_rotpk.S @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* corstone1000 platform provides custom values for the macros defined in + * arm_def.h , so only platform_def.h needs to be included + */ +#if !defined(TARGET_PLATFORM_FVP) && !defined(TARGET_PLATFORM_FPGA) +#include "plat/arm/common/arm_def.h" +#else +#include <platform_def.h> +#endif + + .global arm_rotpk_header + .global arm_rotpk_header_end + .section .rodata.arm_rotpk_hash, "a" + +arm_rotpk_header: + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +arm_rotpk_header_len: + +#ifdef ARM_ROTPK_HASH + .global arm_rotpk_hash_end + .incbin ARM_ROTPK_HASH +arm_rotpk_hash_end: +#endif + +.if ARM_ROTPK_HEADER_LEN != arm_rotpk_header_len - arm_rotpk_header +.error "Invalid ROTPK header length." +.endif diff --git a/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der Binary files differnew file mode 100644 index 0000000..2547877 --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der diff --git a/plat/arm/board/common/rotpk/arm_rotpk_rsa.der b/plat/arm/board/common/rotpk/arm_rotpk_rsa.der Binary files differnew file mode 100644 index 0000000..661f899 --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotpk_rsa.der diff --git a/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem b/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem new file mode 100644 index 0000000..fb328e3 --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINSaX6nvzS3teiBJA7WlTLRKJOajpy29o2cArLbUXoZBoAoGCCqGSM49 +AwEHoUQDQgAEm+ZIvTQ44aKk83DhVLsvsFpKDP/Ch9vA+4Hp+fmVfX6gDH8K1OBi +SpRf7FJ9RGPIn2H6xst+a1OtLMWUDRqGkQ== +-----END EC PRIVATE KEY----- diff --git a/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem b/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem new file mode 100644 index 0000000..71410ec --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLLGDVjWPUB3l+ +xxaWvU0kTqyG5rdx48VUC+cUHL0pGsE/erYCqqs2xNk2aWziZcObsb89qFYmy/0E +AbqsPlQyynleu7IF6gZY8nS64fSHwBkKH2YHd4SDoRzv/yhZ58NofSYgQ+tWY/M5 +MdgrUam8T9D23pXcX1vB7ZBv7CiRfhfteJD0YKfEx09Q7V0TOiErcMVhewghZTrN +glaMekesieilSEgx2R1G5YWGmKDlwKZqvQfkkldhB499Wk3Krja5VgQQ8my+9jts +gD6+DqNNx9R+p0nU8tK8zzCo53SPZN+8XEdozEBM+IPMy0A1BGDKs6QXnwPKHVr6 +0a8hVxDTAgMBAAECggEAfwsc8ewbhDW4TwIGqfNtDUr0rtYN13VpqohW0ki2L8G/ +HQaKUViO/wxQFqoNn/OqQO0AfHmKhXAAokTCiXngBHJ/OjF7vB7+IRhazZEE6u2/ +uoivr/OYNQbFpXyTqsQ1eFzpPju6KKcPK7BzT4Mc89ek/vloFAi8w6LdMl8lbvOg +LBWqX+5A+UQoenPUTvYM4U22YNcEAWubkpsYAmViiWiac+a+uPRk39aKyfOedDNu ++ty9MtCwekivoUTfP/1+O+jFlDnPMJUOEkBmcBqxseYYAHu7blBpdHxYpAItC2pv +YwJJSvsE+HLBLPk177Jahg7sOUqcP0F/X+T65yuvIQKBgQDxdjXdJT5K8j7rG2fv +2bvF2H1GPaHaTYRk0EGI2Ql6Nn+ddfeCE6gaT7aPPgg87wAhNu93coFuYHw0p/sc +ZkXMJ+BmlstPV555cWXmwcxZLsni0fOXrt4YxwWkZwmh74m0NVM/cSFw56PU0oj1 +yDNeq3fgmsJocmuNTe1eG9qA7QKBgQDXaAGrNA5Xel5mqqMYTHHQWI6l2uzdNtt7 +eDn3K9+Eh3ywTqrwP845MAjKDU2Lq61I6t2H89dEifHq823VIcLCHd9BF04MrAH7 +qDPzrmPP2iB9g+YFmGBKe+K0HFE1t1KrTlo9VV6ZAC6RJNLAgwD4kvfIVYNkCGwe ++hoZBdhgvwKBgBrOsPQ4ak4PzwRzKnrqhXpVqrLdrNZ7vLMkm+IBlpfG7SwiKLR8 +UjF5oB8PGAML1cvaOYPdZplGhQOjkrF4eU9NLhC1tSS96Y46FMIlyfYsx6UzAgRZ +GbdOgUXbWqpr2bH0KaXlfXz3eqzqIuKGs41TJB//jo3iBibN/AhytzORAoGAeGov +5KDpE4XYl9Pz8HVremjG9Xh4yQENmOwQm1fvT4rd7UFM1ZkVk2qCv1DIdLe32vdQ +d9ucDzh+ADWsxGRnF1TTpPN+Mh9FzISu5h4qtdreJsxBHgecbIbsqHrb+wdMM29N +itPaWfV8Eq9fETcqp8qgsWD8XkNHDdoKFMrrtskCgYAoSt/Je1D3ZE/3HEjez7bq +fenS3J6KG2SEn2PNFn+R0R5vBo4DaV/cQysKh44GD2+sh0QDyh6nuWJufyhPzROP +DU6DCLbwNePj/yaGuzi36oLt6bBgfPWCiJY7jIdK8DmTLW25m7fRtCC5pxZlSzgl +KBf7R6cbaTvaFe05Y2FJXA== +-----END PRIVATE KEY----- diff --git a/plat/arm/board/common/swd_rotpk/README b/plat/arm/board/common/swd_rotpk/README new file mode 100644 index 0000000..b628a5f --- /dev/null +++ b/plat/arm/board/common/swd_rotpk/README @@ -0,0 +1,14 @@ +This directory contains some development keys to be used as the secure world +root-of-trust key used in the CCA chain of trust. + +* swd_rotprivk_rsa.pem is a 2K RSA private key in PEM format. It has been + generated using the openssl command line tool: + + openssl genrsa 2048 > arm_swd_rotprivk_rsa.pem + +* swd_rotpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key + associated with the above private key. It has been generated using the openssl + command line tool: + + openssl rsa -in arm_swd_rotprivk_rsa.pem -pubout -outform DER | \ + openssl dgst -sha256 -binary > arm_swd_rotpk_rsa_sha256.bin diff --git a/plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S b/plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S new file mode 100644 index 0000000..ae4f9d2 --- /dev/null +++ b/plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global arm_swd_rotpk_hash + .global arm_swd_rotpk_hash_end + + .section .rodata.arm_swd_rotpk_hash, "a" + +arm_swd_rotpk_hash: + /* DER header. */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* Key hash. */ + .incbin ARM_SWD_ROTPK_HASH +arm_swd_rotpk_hash_end: diff --git a/plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin b/plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin new file mode 100644 index 0000000..b2f3e60 --- /dev/null +++ b/plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin @@ -0,0 +1 @@ +0¾âÃ’æœÈË“(ì¨0ŠwIÓÕéã¡gk
\ No newline at end of file diff --git a/plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem b/plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem new file mode 100644 index 0000000..0de655d --- /dev/null +++ b/plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA8igTd5QdZd181kz9vINr7Au34Rr/pQ1jpesfLlc1ZXCNAI9y +/rhQlpw00y8rwOfgZsf18gPwGWWGhDJMsXI7OPem7BEUr8xKumuJuCiOdJh1STcR +/JoFvz8wJPyycj/DOERRGsz+RvFBs6cLjSZHNQdzKDW+DE5vVJpmNWBVkoK7MCRD +Wh/PMZVSoq9PeJOzayYcsipKvifT1+Wo9y2MG5zTDxi28rLr/FBm0CpTepBcRe8L +pmgS7XJKhCQYxdDSzxi/0t/qXAwWuME4jv2HbNxsUZjahiBYpA0BafXanSuxVHly +qpD0BmKAu7PpgKrEnUcPuHpZ2W+a05lNk6zjewIDAQABAoIBAG3twYCcTYgrtvs1 +8k38vyZl33CiKAGOhXkRtpL75fKJ2IizljmKBJOKj/R6ynsFCHrANadLIFj3HMyw +ZN59A+OFkVJDIsf3jsj3/ooKZzkI6N120YSBizBZiAqSaJOy3HWTldn7y0b7SJ88 +quLFyLeLDTzowMCnbqTSfqmmdNJQAn+Q+7RX5sZGyBQUF2pRAA67cOYzc3a5MZ5E +zBOs2u8VboC3ulEq876XWQbcXpRh/ap3eplQ1kAdyy64IPp2WbxqyXW0IQAQqaqh +6oj19ME6mVD5wtELcYscJCDb7pA6WJtPp6nz/og2ifCJE/75T5RJ6fc6eBFMcofQ +STIClGECgYEA/ZC0GX1HTKEKK3c1TiS3Zy0DS5ZoN5KFK7Sp1ZAjPE63iAr1a3z9 +Kepb+L8TBSw50tVD74MF5ChEid/ghF5BrVC3/YJkiiNpM1F51SMLGFeiDPRzJcx5 +KJkSflX7Q36BAXqj85Yz5AjgTPKcBqQRVZ6pNZN1HY99MloMg22WPRECgYEA9HtU +FXmnTplXaNnihdq+vL5Z4/KDM+1f1E95y1PB8vkLI+o1szVNFP+BYz+w42lKtHW+ +c+z40AhFBGZQ0QCx83NOyObCReFjEbP8Nz71BsHe6GyMk9tSPIpzu9XB49Rs+9EO +DAvFM5y2j5bH+lXE0pSyS3oBf51L9ZCPhp/vB8sCgYEAydwB1Gzsbu+hFfs/v2bx +brzh67HgY6VMSP/5WF/3/RG5gB8hQ6HsNQsyjrMmZC7SFarb+3e2H+2CqrREm3wi +EuS4pKPCgEoyfL03HVtZgNZ61o9gf83pAk3h8Bto/VFfSBsnHEsOIlKCph9Z4NuK +RTwa/uDWEmNhyszvO03pldECgYEA2zB7GWnhc1mNgabfLY0JtuSeaPzzXqnyYcID +eyUT3QglUcTY8lvWSP4ufdILgEfVP2fVIdAS30iawDAPQuLxqEf4Gayx/r7s+GE6 +vjlGqxFEDXPMsX9QApFK49voop/AOiCbDHe9DOHy11ei4TDmbrn8BClVkJlxEa/S +ziszvfMCgYEA2V0zXziooI0toaOJEWZlAYhEONS5SG2z28HMLNgbdMcueGNhseaR +NBGgPcu3EQhbL/hD0tBs09u6gjy1WD1i0HYnm1K1YQ1flzfbjUa3BqZETMbNhugd +CM9yv0GEL/udZyOmO401aYl+QGXZX/WwlLQOe7WqQXOXJvW73oSqy7M= +-----END RSA PRIVATE KEY----- diff --git a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c new file mode 100644 index 0000000..fe521a9 --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/desc_image_load.h> + +#include <platform_def.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + .ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + + .next_handoff_image_id = BL32_IMAGE_ID, + }, + + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + .ep_info.args.arg0 = CORSTONE1000_TOS_FW_CONFIG_BASE, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* Fill TOS_FW_CONFIG related information */ + { + .image_id = TOS_FW_CONFIG_ID, + .image_info.image_base = CORSTONE1000_TOS_FW_CONFIG_BASE, + .image_info.image_max_size = (CORSTONE1000_TOS_FW_CONFIG_LIMIT - + CORSTONE1000_TOS_FW_CONFIG_BASE), + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL33_BASE, + .image_info.image_max_size = BL33_LIMIT - BL33_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/arm/board/corstone1000/common/corstone1000_err.c b/plat/arm/board/corstone1000/common/corstone1000_err.c new file mode 100644 index 0000000..376799f --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * corstone1000 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/plat/arm/board/corstone1000/common/corstone1000_helpers.S new file mode 100644 index 0000000..cbe27c3 --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_helpers.S @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On corstone1000, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, Not yet supported. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current CPU is the primary + * CPU. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #CORSTONE1000_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c new file mode 100644 index 0000000..0235f8b --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/bl_common.h> + +#include <drivers/generic_delay_timer.h> +#include <drivers/io/io_storage.h> +#include <plat/common/platform.h> +#include <plat/arm/common/arm_fconf_getter.h> +#include <plat/arm/common/arm_fconf_io_storage.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + ARM_MAP_NS_SHARED_RAM, + ARM_MAP_NS_DRAM1, + CORSTONE1000_MAP_DEVICE, + CORSTONE1000_EXTERNAL_FLASH, + {0} +}; + +static void set_fip_image_source(void) +{ + const struct plat_io_policy *policy; + /* + * metadata for firmware update is written at 0x0000 offset of the flash. + * PLAT_ARM_BOOT_BANK_FLAG contains the boot bank that TF-M is booted. + * As per firmware update spec, at a given point of time, only one bank + * is active. This means, TF-A should boot from the same bank as TF-M. + */ + volatile uint32_t *boot_bank_flag = (uint32_t *)(PLAT_ARM_BOOT_BANK_FLAG); + + if (*boot_bank_flag > 1) { + VERBOSE("Boot_bank is set higher than possible values"); + } + + VERBOSE("Boot bank flag = %u.\n\r", *boot_bank_flag); + + policy = FCONF_GET_PROPERTY(arm, io_policies, FIP_IMAGE_ID); + + assert(policy != NULL); + assert(policy->image_spec != 0UL); + + io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec; + + if ((*boot_bank_flag) == 0) { + VERBOSE("Booting from bank 0: fip offset = 0x%lx\n\r", + PLAT_ARM_FIP_BASE_BANK0); + spec->offset = PLAT_ARM_FIP_BASE_BANK0; + } else { + VERBOSE("Booting from bank 1: fip offset = 0x%lx\n\r", + PLAT_ARM_FIP_BASE_BANK1); + spec->offset = PLAT_ARM_FIP_BASE_BANK1; + } +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + /* + * Identify the start address of the FIP by reading the boot + * index flag from the flash. + */ + set_fip_image_source(); +} + +/* corstone1000 only has one always-on power domain and there + * is no power control present + */ +void __init plat_arm_pwrc_setup(void) +{ +} + +unsigned int plat_get_syscnt_freq2(void) +{ + /* Returning the Generic Timer Frequency */ + return SYS_COUNTER_FREQ_IN_TICKS; +} + + +/* + * Helper function to initialize ARM interconnect driver. + */ +void plat_arm_interconnect_init(void) +{ +} + +/* + * Helper function to place current master into coherency + */ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/* + * Helper function to remove current master from coherency + */ +void plat_arm_interconnect_exit_coherency(void) +{ +} + +/* + * This function is invoked during Mbed TLS library initialisation to get a heap + * The function simply returns the default allocated heap. + */ + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c new file mode 100644 index 0000000..4b0a791 --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ + +static void __dead2 corstone1000_system_reset(void) +{ + + uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG; + uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG; + + *(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL; + *watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE; + while (1) { + wfi(); + } +} + +plat_psci_ops_t plat_arm_psci_pm_ops = { + .system_reset = corstone1000_system_reset, + .validate_ns_entrypoint = NULL +}; + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + ops = &plat_arm_psci_pm_ops; + return ops; +} diff --git a/plat/arm/board/corstone1000/common/corstone1000_security.c b/plat/arm/board/corstone1000/common/corstone1000_security.c new file mode 100644 index 0000000..c88201b --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_security.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ +} diff --git a/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c b/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c new file mode 100644 index 0000000..393235e --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include <plat/common/platform.h> + +static uint32_t plat_generate_random_number(void) +{ + uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U); + uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U); + uint64_t cntpct = read_cntpct_el0(); + + /* Generate 32-bit pattern: saving the 2 least significant bytes + * in random_lo and random_hi + */ + uint16_t random_lo = (uint16_t)( + (((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct + ); + + uint16_t random_hi = (uint16_t)( + (((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct + ); + + return (((uint32_t)random_hi) << 16) | random_lo; +} + +u_register_t plat_get_stack_protector_canary(void) +{ + return plat_generate_random_number(); /* a 32-bit pattern returned */ +} diff --git a/plat/arm/board/corstone1000/common/corstone1000_topology.c b/plat/arm/board/corstone1000/common/corstone1000_topology.c new file mode 100644 index 0000000..5351896 --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_topology.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +/* The corstone1000 power domain tree descriptor */ +static unsigned char corstone1000_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT + + 2]; +/******************************************************************************* + * This function dynamically constructs the topology according to + * CLUSTER_COUNT and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + corstone1000_power_domain_tree_desc[0] = 1; + corstone1000_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT; + + for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++) + corstone1000_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT; + + return corstone1000_power_domain_tree_desc; +} + +/****************************************************************************** + * This function implements a part of the critical interface between the PSCI + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is + * returned in case the MPIDR is invalid. + *****************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return plat_arm_calc_core_pos(mpidr); +} diff --git a/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c b/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c new file mode 100644 index 0000000..7e8fbb2 --- /dev/null +++ b/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * The function returns 0 on success. Any other value is treated as error by the + * Trusted Board Boot. The function also reports extra information related + * to the ROTPK in the flags parameter: ROTPK_IS_HASH, ROTPK_NOT_DEPLOYED. + * + * Refer to the TF-A porting-guide document for more details. + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + +/* + * STUB overriding the non-volatile counter reading. + * NV counters are not implemented at this stage of development. + * Return: 0 = success + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = CORSTONE1000_FW_NVCTR_VAL; + return 0; +} + +/* + * STUB overriding the non-volatile counter updating. + * NV counters are not implemented at this stage of development. + * Return: 0 = success + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 0; +} diff --git a/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts b/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts new file mode 100644 index 0000000..8e49ab8 --- /dev/null +++ b/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + /* + * BL32 image details needed by SPMC + * + * Note: + * binary_size: size of BL32 + TOS_FW_CONFIG + */ + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0x2002000>; + entrypoint = <0x0 0x2002000>; + binary_size = <0xae000>; + }; + +}; diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h new file mode 100644 index 0000000..584d485 --- /dev/null +++ b/plat/arm/board/corstone1000/common/include/platform_def.h @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <common/tbbr/tbbr_img_def.h> +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_spm_def.h> +#include <plat/arm/common/smccc_def.h> +#include <plat/common/common_def.h> +#include <plat/arm/soc/common/soc_css_def.h> + +#define ARM_ROTPK_HEADER_LEN 19 +#define ARM_ROTPK_HASH_LEN 32 + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define ARM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978) + +/* PL011 UART related constants */ +#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ +#undef V2M_IOFPGA_UART0_CLK_IN_HZ +#endif + +#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ +#undef V2M_IOFPGA_UART1_CLK_IN_HZ +#endif + +#define V2M_IOFPGA_UART0_CLK_IN_HZ 50000000 +#define V2M_IOFPGA_UART1_CLK_IN_HZ 50000000 + +/* Core/Cluster/Thread counts for corstone1000 */ +#define CORSTONE1000_CLUSTER_COUNT U(1) +#define CORSTONE1000_MAX_CPUS_PER_CLUSTER U(4) +#define CORSTONE1000_MAX_PE_PER_CPU U(1) +#define CORSTONE1000_PRIMARY_CPU U(0) + +#define PLAT_ARM_CLUSTER_COUNT CORSTONE1000_CLUSTER_COUNT + +#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \ + CORSTONE1000_MAX_CPUS_PER_CLUSTER * \ + CORSTONE1000_MAX_PE_PER_CPU) + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x1a510000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ +#define PLAT_ARM_RUN_UART_BASE 0x1a520000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ +#define ARM_CONSOLE_BAUDRATE 115200 +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +/* Memory related constants */ + +/* SRAM (CVM) memory layout + * + * <ARM_TRUSTED_SRAM_BASE> + * partition size: sizeof(meminfo_t) = 16 bytes + * content: memory info area used by the next BL + * + * <ARM_FW_CONFIG_BASE> + * partition size: 4080 bytes + * + * <ARM_BL2_MEM_DESC_BASE> + * partition size: 4 KB + * content: Area where BL2 copies the images descriptors + * + * <ARM_BL_RAM_BASE> = <BL32_BASE> + * partition size: 688 KB + * content: BL32 (optee-os) + * + * <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x20ae000 + * partition size: 8 KB + * content: BL32 config (TOS_FW_CONFIG) + * + * <BL31_BASE> + * partition size: 140 KB + * content: BL31 + * + * <BL2_SIGNATURE_BASE> + * partition size: 4 KB + * content: MCUBOOT data needed to verify TF-A BL2 + * + * <BL2_BASE> + * partition size: 176 KB + * content: BL2 + * + * <ARM_NS_SHARED_RAM_BASE> = <ARM_TRUSTED_SRAM_BASE> + 1 MB + * partition size: 512 KB + * content: BL33 (u-boot) + */ + +/* DDR memory */ +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE (SZ_2G) /* 2GB*/ +#define ARM_DRAM1_END (ARM_DRAM1_BASE + ARM_DRAM1_SIZE - 1) + +/* DRAM1 and DRAM2 are the same for corstone1000 */ +#define ARM_DRAM2_BASE ARM_DRAM1_BASE +#define ARM_DRAM2_SIZE ARM_DRAM1_SIZE +#define ARM_DRAM2_END ARM_DRAM1_END + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE - 1) + +/* The first 8 KB of Trusted SRAM are used as shared memory */ +#define ARM_TRUSTED_SRAM_BASE UL(0x02000000) +#define ARM_SHARED_RAM_SIZE (SZ_8K) /* 8 KB */ +#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + +/* The remaining Trusted SRAM is used to load the BL images */ +#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */ + +/* Last 512KB of CVM is allocated for shared RAM as an example openAMP */ +#define ARM_NS_SHARED_RAM_SIZE (512 * SZ_1K) + +#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \ + ARM_NS_SHARED_RAM_SIZE - \ + ARM_SHARED_RAM_SIZE) + +#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */ + +#define PLAT_ARM_MAX_BL31_SIZE (140 * SZ_1K) /* 140 KB */ + +#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE) + +#define BL2_SIGNATURE_SIZE (SZ_4K) /* 4 KB */ + +#define BL2_SIGNATURE_BASE (BL2_LIMIT - PLAT_ARM_MAX_BL2_SIZE) +#define BL2_BASE (BL2_LIMIT - \ + PLAT_ARM_MAX_BL2_SIZE + \ + BL2_SIGNATURE_SIZE) +#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +#define BL31_BASE (BL2_SIGNATURE_BASE - PLAT_ARM_MAX_BL31_SIZE) +#define BL31_LIMIT BL2_SIGNATURE_BASE + +#define CORSTONE1000_TOS_FW_CONFIG_BASE (BL31_BASE - \ + CORSTONE1000_TOS_FW_CONFIG_SIZE) +#define CORSTONE1000_TOS_FW_CONFIG_SIZE (SZ_8K) /* 8 KB */ +#define CORSTONE1000_TOS_FW_CONFIG_LIMIT BL31_BASE + +#define BL32_BASE ARM_BL_RAM_BASE +#define PLAT_ARM_MAX_BL32_SIZE (CORSTONE1000_TOS_FW_CONFIG_BASE - BL32_BASE) + +#define BL32_LIMIT (BL32_BASE + PLAT_ARM_MAX_BL32_SIZE) + +/* SPD_spmd settings */ + +#define PLAT_ARM_SPMC_BASE BL32_BASE +#define PLAT_ARM_SPMC_SIZE PLAT_ARM_MAX_BL32_SIZE + +/* NS memory */ + +/* The last 512KB of the SRAM is allocated as shared memory */ +#define ARM_NS_SHARED_RAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SRAM_SIZE - \ + (PLAT_ARM_MAX_BL31_SIZE + \ + PLAT_ARM_MAX_BL32_SIZE)) + +#define BL33_BASE ARM_DRAM1_BASE +#define PLAT_ARM_MAX_BL33_SIZE (12 * SZ_1M) /* 12 MB*/ +#define BL33_LIMIT (ARM_DRAM1_BASE + PLAT_ARM_MAX_BL33_SIZE) + +/* end of the definition of SRAM memory layout */ + +/* NOR Flash */ + +#define PLAT_ARM_BOOT_BANK_FLAG UL(0x08002000) +#define PLAT_ARM_FIP_BASE_BANK0 UL(0x081EF000) +#define PLAT_ARM_FIP_BASE_BANK1 UL(0x0916F000) +#define PLAT_ARM_FIP_MAX_SIZE UL(0x1ff000) /* 1.996 MB */ + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (SZ_32M) /* 32 MB */ + +#define PLAT_ARM_FLASH_IMAGE_BASE PLAT_ARM_FIP_BASE_BANK0 +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE PLAT_ARM_FIP_MAX_SIZE + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * Define FW_CONFIG area base and limit. Leave enough space for BL2 meminfo. + * FW_CONFIG is intended to host the device tree. Currently, This area is not + * used because corstone1000 platform doesn't use a device tree at TF-A level. + */ +#define ARM_FW_CONFIG_BASE (ARM_SHARED_RAM_BASE + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT (ARM_SHARED_RAM_BASE + \ + (ARM_SHARED_RAM_SIZE >> 1)) + +/* + * Boot parameters passed from BL2 to BL31/BL32 are stored here + */ +#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT +#define ARM_BL2_MEM_DESC_LIMIT ARM_BL_RAM_BASE + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 3 +#define PLAT_ARM_MMAP_ENTRIES 8 +#define MAX_XLAT_TABLES 5 +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS) +#define MAX_IO_DEVICES 2 +#define MAX_IO_HANDLES 3 +#define MAX_IO_BLOCK_DEVICES 1 + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x1C010000 +#define PLAT_ARM_GICC_BASE 0x1C02F000 + +/* MHUv2 Secure Channel receiver and sender */ +#define PLAT_SDK700_MHU0_SEND 0x1B800000 +#define PLAT_SDK700_MHU0_RECV 0x1B810000 + +/* Timer/watchdog related constants */ +#define ARM_SYS_CNTCTL_BASE UL(0x1a200000) +#define ARM_SYS_CNTREAD_BASE UL(0x1a210000) +#define ARM_SYS_TIMCTL_BASE UL(0x1a220000) + +#define SECURE_WATCHDOG_ADDR_CTRL_REG 0x1A320000 +#define SECURE_WATCHDOG_ADDR_VAL_REG 0x1A320008 +#define SECURE_WATCHDOG_MASK_ENABLE 0x01 +#define SECURE_WATCHDOG_COUNTDOWN_VAL 0x1000 + +#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */ + +#define CORSTONE1000_IRQ_TZ_WDOG 32 +#define CORSTONE1000_IRQ_SEC_SYS_TIMER 34 + +#define PLAT_MAX_PWR_LVL 2 +/* + * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The + * power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define ARM_PWR_LVL0 MPIDR_AFFLVL0 +#define ARM_PWR_LVL1 MPIDR_AFFLVL1 +#define ARM_PWR_LVL2 MPIDR_AFFLVL2 + +/* + * Macros for local power states in ARM platforms encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define ARM_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define ARM_LOCAL_STATE_RET U(1) +/* Local power state for OFF/power-down. Valid for CPU and cluster + * power domains + */ +#define ARM_LOCAL_STATE_OFF U(2) + +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * This macro defines the deepest retention state possible. A higher state + * ID will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +#define PLATFORM_STACK_SIZE UL(0x440) + +#define CORSTONE1000_EXTERNAL_FLASH MAP_REGION_FLAT( \ + PLAT_ARM_NVM_BASE, \ + PLAT_ARM_NVM_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \ + ARM_NS_SHARED_RAM_BASE, \ + ARM_NS_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, \ + ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + (BL_CODE_END - BL_CODE_BASE), \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + (BL_RO_DATA_END - BL_RO_DATA_BASE), \ + MT_RO_DATA | MT_SECURE) +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \ + BL_COHERENT_RAM_BASE, \ + (BL_COHERENT_RAM_END \ + - BL_COHERENT_RAM_BASE), \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +/* + * Map the region for the optional device tree configuration with read and + * write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \ + ARM_FW_CONFIG_BASE, \ + (ARM_FW_CONFIG_LIMIT \ + - ARM_FW_CONFIG_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define CORSTONE1000_DEVICE_BASE (0x1A000000) +#define CORSTONE1000_DEVICE_SIZE (0x26000000) +#define CORSTONE1000_MAP_DEVICE MAP_REGION_FLAT( \ + CORSTONE1000_DEVICE_BASE, \ + CORSTONE1000_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(CORSTONE1000_IRQ_TZ_WDOG, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CORSTONE1000_IRQ_SEC_SYS_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/corstone1000/include/plat_macros.S b/plat/arm/board/corstone1000/include/plat_macros.S new file mode 100644 index 0000000..9334201 --- /dev/null +++ b/plat/arm/board/corstone1000/include/plat_macros.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <css_macros.S> + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + css_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk new file mode 100644 index 0000000..d891691 --- /dev/null +++ b/plat/arm/board/corstone1000/platform.mk @@ -0,0 +1,83 @@ +# +# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Making sure the corstone1000 platform type is specified +ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),) + $(error TARGET_PLATFORM must be fpga or fvp) +endif + +CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S + +PLAT_INCLUDES := -Iplat/arm/board/corstone1000/common/include \ + -Iplat/arm/board/corstone1000/include \ + -Iinclude/plat/arm/common \ + -Iinclude/plat/arm/css/common/aarch64 + + +CORSTONE1000_FW_NVCTR_VAL := 255 +TFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL} +NTFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL} + +override NEED_BL1 := no + +override NEED_BL2 := yes +FIP_BL2_ARGS := tb-fw + +override NEED_BL2U := no +override NEED_BL31 := yes +NEED_BL32 := yes +override NEED_BL33 := yes + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +CORSTONE1000_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + + +BL2_SOURCES += plat/arm/board/corstone1000/common/corstone1000_security.c \ + plat/arm/board/corstone1000/common/corstone1000_err.c \ + plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c \ + lib/utils/mem_region.c \ + plat/arm/board/corstone1000/common/corstone1000_helpers.S \ + plat/arm/board/corstone1000/common/corstone1000_plat.c \ + plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c \ + ${CORSTONE1000_CPU_LIBS} \ + + +BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/corstone1000/common/corstone1000_helpers.S \ + plat/arm/board/corstone1000/common/corstone1000_topology.c \ + plat/arm/board/corstone1000/common/corstone1000_security.c \ + plat/arm/board/corstone1000/common/corstone1000_plat.c \ + plat/arm/board/corstone1000/common/corstone1000_pm.c \ + ${CORSTONE1000_CPU_LIBS} \ + ${CORSTONE1000_GIC_SOURCES} + +ifneq (${ENABLE_STACK_PROTECTOR},0) + ifneq (${ENABLE_STACK_PROTECTOR},none) + CORSTONE1000_SECURITY_SOURCES := plat/arm/board/corstone1000/common/corstone1000_stack_protector.c + BL2_SOURCES += ${CORSTONE1000_SECURITY_SOURCES} + BL31_SOURCES += ${CORSTONE1000_SECURITY_SOURCES} + endif +endif + +FDT_SOURCES += plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts +CORSTONE1000_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/corstone1000_spmc_manifest.dtb + +# Add the SPMC manifest to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE1000_TOS_FW_CONFIG},--tos-fw-config,${CORSTONE1000_TOS_FW_CONFIG})) + +# Adding TARGET_PLATFORM as a GCC define (-D option) +$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM}))) + +# Adding CORSTONE1000_FW_NVCTR_VAL as a GCC define (-D option) +$(eval $(call add_define,CORSTONE1000_FW_NVCTR_VAL)) + +include plat/arm/common/arm_common.mk +include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/corstone700/common/corstone700_helpers.S b/plat/arm/board/corstone700/common/corstone700_helpers.S new file mode 100644 index 0000000..c713f4f --- /dev/null +++ b/plat/arm/board/corstone700/common/corstone700_helpers.S @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On Corstone700, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, Not yet supported. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current CPU is the primary + * CPU. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #0 + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on Corstone700. + * + * (ClusterId * MAX_CPUS_PER_CLUSTER * MAX_PE_PER_CPU) + + * (CPUId * MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * MAX_CPUS_PER_CLUSTER + CPUId) * MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #CORSTONE700_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #CORSTONE700_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/corstone700/common/corstone700_plat.c b/plat/arm/board/corstone700/common/corstone700_plat.c new file mode 100644 index 0000000..dd7531d --- /dev/null +++ b/plat/arm/board/corstone700/common/corstone700_plat.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/bl_common.h> + +#include <corstone700_mhu.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + ARM_MAP_NS_SHARED_RAM, + ARM_MAP_NS_DRAM1, + CORSTONE700_MAP_DEVICE, + {0} +}; + +/* Corstone700 only has one always-on power domain and there + * is no power control present + */ +void __init plat_arm_pwrc_setup(void) +{ + mhu_secure_init(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + /* Returning the Generic Timer Frequency */ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/plat/arm/board/corstone700/common/corstone700_pm.c b/plat/arm/board/corstone700/common/corstone700_pm.c new file mode 100644 index 0000000..4884ea5 --- /dev/null +++ b/plat/arm/board/corstone700/common/corstone700_pm.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t plat_arm_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL +}; + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return ops; +} diff --git a/plat/arm/board/corstone700/common/corstone700_security.c b/plat/arm/board/corstone700/common/corstone700_security.c new file mode 100644 index 0000000..39b2fc9 --- /dev/null +++ b/plat/arm/board/corstone700/common/corstone700_security.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ +} diff --git a/plat/arm/board/corstone700/common/corstone700_stack_protector.c b/plat/arm/board/corstone700/common/corstone700_stack_protector.c new file mode 100644 index 0000000..6fd09da --- /dev/null +++ b/plat/arm/board/corstone700/common/corstone700_stack_protector.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include <plat/common/platform.h> + +static uint32_t plat_generate_random_number(void) +{ + uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U); + uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U); + uint64_t cntpct = read_cntpct_el0(); + + /* Generate 32-bit pattern: saving the 2 least significant bytes + * in random_lo and random_hi + */ + uint16_t random_lo = (uint16_t)( + (((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct + ); + + uint16_t random_hi = (uint16_t)( + (((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct + ); + + return (((uint32_t)random_hi) << 16) | random_lo; +} + +u_register_t plat_get_stack_protector_canary(void) +{ + return plat_generate_random_number(); /* a 32-bit pattern is returned */ +} diff --git a/plat/arm/board/corstone700/common/corstone700_topology.c b/plat/arm/board/corstone700/common/corstone700_topology.c new file mode 100644 index 0000000..904f5ab --- /dev/null +++ b/plat/arm/board/corstone700/common/corstone700_topology.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +/* The Corstone700 power domain tree descriptor */ +static unsigned char corstone700_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT + + 2]; +/******************************************************************************* + * This function dynamically constructs the topology according to + * CLUSTER_COUNT and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + corstone700_power_domain_tree_desc[0] = 1; + corstone700_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT; + + for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++) + corstone700_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT; + + return corstone700_power_domain_tree_desc; +} + +/****************************************************************************** + * This function implements a part of the critical interface between the PSCI + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is + * returned in case the MPIDR is invalid. + *****************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return plat_arm_calc_core_pos(mpidr); +} diff --git a/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c new file mode 100644 index 0000000..832cfb7 --- /dev/null +++ b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/bakery_lock.h> +#include <lib/mmio.h> + +#include "corstone700_mhu.h" +#include <plat_arm.h> +#include <platform_def.h> + +ARM_INSTANTIATE_LOCK; + +#pragma weak plat_arm_pwrc_setup + +/* + * Slot 31 is reserved because the MHU hardware uses this register bit to + * indicate a non-secure access attempt. The total number of available slots is + * therefore 31 [30:0]. + */ +#define MHU_MAX_SLOT_ID 30 + +void mhu_secure_message_start(uintptr_t address, unsigned int slot_id) +{ + unsigned int intr_stat_check; + uint64_t timeout_cnt; + volatile uint8_t expiration; + + assert(slot_id <= MHU_MAX_SLOT_ID); + arm_lock_get(); + + /* + * Make sure any previous command has finished + * and polling timeout not expired + */ + + timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT); + + do { + intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) & + (1 << slot_id)); + + expiration = timeout_elapsed(timeout_cnt); + + } while ((intr_stat_check != 0U) && (expiration == 0U)); + + /* + * Note: No risk of timer overflows while waiting + * for the timeout expiration. + * According to Armv8 TRM: System counter roll-over + * time of not less than 40 years + */ +} + +void mhu_secure_message_send(uintptr_t address, + unsigned int slot_id, + unsigned int message) +{ + unsigned char access_ready; + uint64_t timeout_cnt; + volatile uint8_t expiration; + + assert(slot_id <= MHU_MAX_SLOT_ID); + assert((mmio_read_32(address + CPU_INTR_S_STAT) & + (1 << slot_id)) == 0U); + + MHU_V2_ACCESS_REQUEST(address); + + timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT); + + do { + access_ready = MHU_V2_IS_ACCESS_READY(address); + expiration = timeout_elapsed(timeout_cnt); + + } while ((access_ready == 0U) && (expiration == 0U)); + + /* + * Note: No risk of timer overflows while waiting + * for the timeout expiration. + * According to Armv8 TRM: System counter roll-over + * time of not less than 40 years + */ + + mmio_write_32(address + CPU_INTR_S_SET, message); +} + +void mhu_secure_message_end(uintptr_t address, unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + /* + * Clear any response we got by writing one in the relevant slot bit to + * the CLEAR register + */ + MHU_V2_CLEAR_REQUEST(address); + + arm_lock_release(); +} + +void __init mhu_secure_init(void) +{ + arm_lock_init(); + + /* + * The STAT register resets to zero. Ensure it is in the expected state, + * as a stale or garbage value would make us think it's a message we've + * already sent. + */ + + assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0); +} diff --git a/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h new file mode 100644 index 0000000..7f14ca5 --- /dev/null +++ b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORSTONE700_MHU_H +#define CORSTONE700_MHU_H + +#define MHU_POLL_INTR_STAT_TIMEOUT 50000 /*timeout value in us*/ + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT 0x00 +#define CPU_INTR_S_SET 0x0C + +/* MHUv2 Control Registers Offsets */ +#define MHU_V2_MSG_CFG_OFFSET 0xF80 +#define MHU_V2_ACCESS_REQ_OFFSET 0xF88 +#define MHU_V2_ACCESS_READY_OFFSET 0xF8C + +#define MHU_V2_ACCESS_REQUEST(addr) \ + mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1) + +#define MHU_V2_CLEAR_REQUEST(addr) \ + mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0) + +#define MHU_V2_IS_ACCESS_READY(addr) \ + (mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1) + +void mhu_secure_message_start(uintptr_t address, unsigned int slot_id); +void mhu_secure_message_send(uintptr_t address, + unsigned int slot_id, + unsigned int message); +void mhu_secure_message_end(uintptr_t address, unsigned int slot_id); +void mhu_secure_init(void); + +#endif /* CORSTONE700_MHU_H */ diff --git a/plat/arm/board/corstone700/common/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h new file mode 100644 index 0000000..57b0551 --- /dev/null +++ b/plat/arm/board/corstone700/common/include/platform_def.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_spm_def.h> +#include <plat/arm/common/smccc_def.h> +#include <plat/common/common_def.h> + +/* PL011 UART related constants */ +#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ +#undef V2M_IOFPGA_UART0_CLK_IN_HZ +#endif + +#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ +#undef V2M_IOFPGA_UART1_CLK_IN_HZ +#endif + +#define V2M_IOFPGA_UART0_CLK_IN_HZ 32000000 +#define V2M_IOFPGA_UART1_CLK_IN_HZ 32000000 + +/* Core/Cluster/Thread counts for Corstone700 */ +#define CORSTONE700_CLUSTER_COUNT U(1) +#define CORSTONE700_MAX_CPUS_PER_CLUSTER U(4) +#define CORSTONE700_MAX_PE_PER_CPU U(1) + +#define PLAT_ARM_CLUSTER_COUNT CORSTONE700_CLUSTER_COUNT + +#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \ + CORSTONE700_MAX_CPUS_PER_CLUSTER * \ + CORSTONE700_MAX_PE_PER_CPU) + + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x1a510000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ +#define PLAT_ARM_RUN_UART_BASE 0x1a520000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ +#define ARM_CONSOLE_BAUDRATE 115200 +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +/* Memory related constants */ +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \ + ARM_NS_DRAM1_SIZE - 1) +#define ARM_TRUSTED_SRAM_BASE UL(0x02000000) +#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE +#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */ + +/* The remaining Trusted SRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + \ + ARM_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE) + +#define ARM_NS_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + UL(0x00100000) +#define ARM_NS_SHARED_RAM_SIZE 0x00300000 + +/* + * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding + * the page reserved for fw_configs) to BL32 + */ +#define BL32_BASE (ARM_BL_RAM_BASE + PAGE_SIZE) +#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * To enable FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space for BL2 meminfo. + */ +#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE / 2U)) + +/* + * Boot parameters passed from BL2 to BL31/BL32 are stored here + */ +#define ARM_BL2_MEM_DESC_BASE (ARM_FW_CONFIG_LIMIT) +#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \ + + (PAGE_SIZE / 2U)) + +/* + * Define limit of firmware configuration memory: + * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory + */ +#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2)) + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 3 +#define PLAT_ARM_MMAP_ENTRIES 8 +#define MAX_XLAT_TABLES 5 +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x1C010000 +#define PLAT_ARM_GICC_BASE 0x1C02F000 + +/* MHUv2 Secure Channel receiver and sender */ +#define PLAT_SDK700_MHU0_SEND 0x1B800000 +#define PLAT_SDK700_MHU0_RECV 0x1B810000 + +/* Timer/watchdog related constants */ +#define ARM_SYS_CNTCTL_BASE UL(0x1a200000) +#define ARM_SYS_CNTREAD_BASE UL(0x1a210000) +#define ARM_SYS_TIMCTL_BASE UL(0x1a220000) + +#ifdef TARGET_PLATFORM_FVP +#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */ +#else +#define SYS_COUNTER_FREQ_IN_TICKS UL(32000000) /* 32MHz */ +#endif + +#define CORSTONE700_IRQ_TZ_WDOG 32 +#define CORSTONE700_IRQ_SEC_SYS_TIMER 34 + +#define PLAT_MAX_PWR_LVL 2 +/* + * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The + * power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define ARM_PWR_LVL0 MPIDR_AFFLVL0 +#define ARM_PWR_LVL1 MPIDR_AFFLVL1 +#define ARM_PWR_LVL2 MPIDR_AFFLVL2 + +/* + * Macros for local power states in ARM platforms encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define ARM_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define ARM_LOCAL_STATE_RET U(1) +/* Local power state for OFF/power-down. Valid for CPU and cluster + * power domains + */ +#define ARM_LOCAL_STATE_OFF U(2) + +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * This macro defines the deepest retention state possible. A higher state + * ID will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +#define PLATFORM_STACK_SIZE UL(0x440) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \ + ARM_NS_SHARED_RAM_BASE, \ + ARM_NS_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, \ + ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END \ + - BL_CODE_BASE, \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + BL_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \ + BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END \ + - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +/* + * Map the region for device tree configuration with read and write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \ + (ARM_FW_CONFIGS_LIMIT \ + - ARM_BL_RAM_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define CORSTONE700_DEVICE_BASE (0x1A000000) +#define CORSTONE700_DEVICE_SIZE (0x26000000) +#define CORSTONE700_MAP_DEVICE MAP_REGION_FLAT( \ + CORSTONE700_DEVICE_BASE,\ + CORSTONE700_DEVICE_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk new file mode 100644 index 0000000..75833f6 --- /dev/null +++ b/plat/arm/board/corstone700/platform.mk @@ -0,0 +1,63 @@ +# +# Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Making sure the corstone700 platform type is specified +ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),) + $(error TARGET_PLATFORM must be fpga or fvp) +endif + +CORSTONE700_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S + +BL32_SOURCES += plat/arm/common/aarch32/arm_helpers.S \ + plat/arm/common/arm_console.c \ + plat/arm/common/arm_common.c \ + lib/xlat_tables/aarch32/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + ${CORSTONE700_CPU_LIBS} \ + plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c + +PLAT_INCLUDES := -Iplat/arm/board/corstone700/common/include \ + -Iinclude/plat/arm/common \ + -Iplat/arm/board/corstone700/common/drivers/mhu + +NEED_BL32 := yes + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +CORSTONE700_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +# BL1/BL2 Image not a part of the capsule Image for Corstone700 +override NEED_BL1 := no +override NEED_BL2 := no +override NEED_BL2U := no +override NEED_BL33 := yes + +#TFA for Corstone700 starts from BL32 +override RESET_TO_SP_MIN := 1 + +#Device tree +CORSTONE700_HW_CONFIG_DTS := fdts/corstone700_${TARGET_PLATFORM}.dts +CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb +FDT_SOURCES += ${CORSTONE700_HW_CONFIG_DTS} +$(eval CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS))) + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE700_HW_CONFIG},--hw-config,${CORSTONE700_HW_CONFIG})) + +# Check for Linux kernel as a BL33 image by default +$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) + ifndef ARM_PRELOADED_DTB_BASE + $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.") + endif + $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) + +# Adding TARGET_PLATFORM as a GCC define (-D option) +$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM}))) + +include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c b/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c new file mode 100644 index 0000000..2fc0e0d --- /dev/null +++ b/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk new file mode 100644 index 0000000..75dc0f1 --- /dev/null +++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/corstone700/common/corstone700_helpers.S \ + plat/arm/board/corstone700/common/corstone700_topology.c \ + plat/arm/board/corstone700/common/corstone700_security.c \ + plat/arm/board/corstone700/common/corstone700_plat.c \ + plat/arm/board/corstone700/common/corstone700_pm.c \ + plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c \ + ${CORSTONE700_GIC_SOURCES} + +ifneq (${ENABLE_STACK_PROTECTOR},0) + ifneq (${ENABLE_STACK_PROTECTOR},none) + BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c + endif +endif + +include plat/arm/common/sp_min/arm_sp_min.mk diff --git a/plat/arm/board/fvp/aarch32/fvp_helpers.S b/plat/arm/board/fvp/aarch32/fvp_helpers.S new file mode 100644 index 0000000..9985c1d --- /dev/null +++ b/plat/arm/board/fvp/aarch32/fvp_helpers.S @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + ldcopr r2, MPIDR + ldr r1, =PWRC_BASE + str r2, [r1, #PSYSR_OFF] + ldr r2, [r1, #PSYSR_OFF] + ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp r2, #WKUP_PPONR + beq warm_reset + cmp r2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov r0, #0 + bx lr + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr r0, [r0] + cmp r0, #0 + beq _panic + bx lr + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic: + b _panic +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #FVP_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #FVP_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #FVP_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S new file mode 100644 index 0000000..8efc238 --- /dev/null +++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/gicv3.h> +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +#ifndef EL3_PAYLOAD_BASE + /* --------------------------------------------- + * Power down this cpu. + * TODO: Do we need to worry about powering the + * cluster down as well here. That will need + * locks which we won't have unless an elf- + * loader zeroes out the zi section. + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + mov_imm x1, PWRC_BASE + str w0, [x1, #PPOFFR_OFF] + + /* --------------------------------------------- + * There is no sane reason to come out of this + * wfi so panic if we do. This cpu will be pow- + * ered on and reset by the cpu_on pm api + * --------------------------------------------- + */ + dsb sy + wfi + no_ret plat_panic_handler +#else + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + + /* Wait until the entrypoint gets populated */ +poll_mailbox: + ldr x1, [x0] + cbz x1, 1f + br x1 +1: + wfe + b poll_mailbox +#endif /* EL3_PAYLOAD_BASE */ +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + mrs x2, mpidr_el1 + mov_imm x1, PWRC_BASE + str w2, [x1, #PSYSR_OFF] + ldr w2, [x1, #PSYSR_OFF] + ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp w2, #WKUP_PPONR + beq warm_reset + cmp w2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov x0, #0 + ret + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + cbz x0, _panic_handler + ret + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic_handler: + no_ret plat_panic_handler +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FVP_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #FVP_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x5, #FVP_MAX_PE_PER_CPU + madd x0, x1, x5, x0 + ret +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/fvp/aarch64/fvp_ras.c b/plat/arm/board/fvp/aarch64/fvp_ras.c new file mode 100644 index 0000000..759f6d0 --- /dev/null +++ b/plat/arm/board/fvp/aarch64/fvp_ras.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/extensions/ras.h> + +struct ras_interrupt fvp_ras_interrupts[] = { +}; + +struct err_record_info fvp_err_records[] = { +}; + +REGISTER_ERR_RECORD_INFO(fvp_err_records); +REGISTER_RAS_INTERRUPTS(fvp_ras_interrupts); diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c new file mode 100644 index 0000000..45e3b7e --- /dev/null +++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <inttypes.h> +#include <stdint.h> + +#include <common/debug.h> +#include <common/fdt_wrappers.h> +#include <fconf_hw_config_getter.h> +#include <libfdt.h> +#include <plat/common/platform.h> + +struct gicv3_config_t gicv3_config; +struct hw_topology_t soc_topology; +struct uart_serial_config_t uart_serial_config; +struct cpu_timer_t cpu_timer; + +#define ILLEGAL_ADDR ULL(~0) + +int fconf_populate_gicv3_config(uintptr_t config) +{ + int err; + int node; + uintptr_t addr; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* + * Find the offset of the node containing "arm,gic-v3" compatible property. + * Populating fconf strucutures dynamically is not supported for legacy + * systems which use GICv2 IP. Simply skip extracting GIC properties. + */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3"); + if (node < 0) { + WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n"); + return 0; + } + /* The GICv3 DT binding holds at least two address/size pairs, + * the first describing the distributor, the second the redistributors. + * See: bindings/interrupt-controller/arm,gic-v3.yaml + */ + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL); + if (err < 0) { + ERROR("FCONF: Failed to read GICD reg property of GIC node\n"); + return err; + } + gicv3_config.gicd_base = addr; + + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL); + if (err < 0) { + ERROR("FCONF: Failed to read GICR reg property of GIC node\n"); + } else { + gicv3_config.gicr_base = addr; + } + + return err; +} + +int fconf_populate_topology(uintptr_t config) +{ + int err, node, cluster_node, core_node, thread_node; + uint32_t cluster_count = 0, max_cpu_per_cluster = 0, total_cpu_count = 0; + uint32_t max_pwr_lvl = 0; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* Find the offset of the node containing "arm,psci-1.0" compatible property */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,psci-1.0"); + if (node < 0) { + ERROR("FCONF: Unable to locate node with arm,psci-1.0 compatible property\n"); + return node; + } + + err = fdt_read_uint32(hw_config_dtb, node, "max-pwr-lvl", &max_pwr_lvl); + if (err < 0) { + /* + * Some legacy FVP dts may not have this property. Assign the default + * value. + */ + WARN("FCONF: Could not locate max-pwr-lvl property\n"); + max_pwr_lvl = 2; + } + + assert(max_pwr_lvl <= MPIDR_AFFLVL2); + + /* Find the offset of the "cpus" node */ + node = fdt_path_offset(hw_config_dtb, "/cpus"); + if (node < 0) { + ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpus"); + return node; + } + + /* A typical cpu-map node in a device tree is shown here for reference + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + + cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + }; + }; + */ + + /* Locate the cpu-map child node */ + node = fdt_subnode_offset(hw_config_dtb, node, "cpu-map"); + if (node < 0) { + ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpu-map"); + return node; + } + + uint32_t cpus_per_cluster[PLAT_ARM_CLUSTER_COUNT] = {0}; + + /* Iterate through cluster nodes */ + fdt_for_each_subnode(cluster_node, hw_config_dtb, node) { + assert(cluster_count < PLAT_ARM_CLUSTER_COUNT); + + /* Iterate through core nodes */ + fdt_for_each_subnode(core_node, hw_config_dtb, cluster_node) { + /* core nodes may have child nodes i.e., "thread" nodes */ + if (fdt_first_subnode(hw_config_dtb, core_node) < 0) { + cpus_per_cluster[cluster_count]++; + } else { + /* Multi-threaded CPU description is found in dtb */ + fdt_for_each_subnode(thread_node, hw_config_dtb, core_node) { + cpus_per_cluster[cluster_count]++; + } + + /* Since in some dtbs, core nodes may not have thread node, + * no need to error if even one child node is not found. + */ + } + } + + /* Ensure every cluster node has at least 1 child node */ + if (cpus_per_cluster[cluster_count] < 1U) { + ERROR("FCONF: Unable to locate the core node in cluster %d\n", cluster_count); + return -1; + } + + VERBOSE("CLUSTER ID: %d cpu-count: %d\n", cluster_count, + cpus_per_cluster[cluster_count]); + + /* Find the maximum number of cpus in any cluster */ + max_cpu_per_cluster = MAX(max_cpu_per_cluster, cpus_per_cluster[cluster_count]); + total_cpu_count += cpus_per_cluster[cluster_count]; + cluster_count++; + } + + + /* At least one cluster node is expected in hardware configuration dtb */ + if (cluster_count < 1U) { + ERROR("FCONF: Unable to locate the cluster node in cpu-map node\n"); + return -1; + } + + soc_topology.plat_max_pwr_level = max_pwr_lvl; + soc_topology.plat_cluster_count = cluster_count; + soc_topology.cluster_cpu_count = max_cpu_per_cluster; + soc_topology.plat_cpu_count = total_cpu_count; + + return 0; +} + +int fconf_populate_uart_config(uintptr_t config) +{ + int uart_node, node, err; + uintptr_t addr; + const char *path; + uint32_t phandle; + uint64_t translated_addr; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* + * uart child node is indirectly referenced through its path which is + * specified in the `serial1` property of the "aliases" node. + * Note that TF-A boot console is mapped to serial0 while runtime + * console is mapped to serial1. + */ + + path = fdt_get_alias(hw_config_dtb, "serial1"); + if (path == NULL) { + ERROR("FCONF: Could not read serial1 property in aliases node\n"); + return -1; + } + + /* Find the offset of the uart serial node */ + uart_node = fdt_path_offset(hw_config_dtb, path); + if (uart_node < 0) { + ERROR("FCONF: Failed to locate uart serial node using its path\n"); + return -1; + } + + /* uart serial node has its offset and size of address in reg property */ + err = fdt_get_reg_props_by_index(hw_config_dtb, uart_node, 0, &addr, + NULL); + if (err < 0) { + ERROR("FCONF: Failed to read reg property of '%s' node\n", + "uart serial"); + return err; + } + VERBOSE("FCONF: UART node address: %lx\n", addr); + + /* + * Perform address translation of local device address to CPU address + * domain. + */ + translated_addr = fdtw_translate_address(hw_config_dtb, + uart_node, (uint64_t)addr); + if (translated_addr == ILLEGAL_ADDR) { + ERROR("FCONF: failed to translate UART node base address"); + return -1; + } + + uart_serial_config.uart_base = translated_addr; + + VERBOSE("FCONF: UART serial device base address: %" PRIx64 "\n", + uart_serial_config.uart_base); + + /* + * The phandle of the DT node which captures the clock info of uart + * serial node is specified in the "clocks" property. + */ + err = fdt_read_uint32(hw_config_dtb, uart_node, "clocks", &phandle); + if (err < 0) { + ERROR("FCONF: Could not read clocks property in uart serial node\n"); + return err; + } + + node = fdt_node_offset_by_phandle(hw_config_dtb, phandle); + if (node < 0) { + ERROR("FCONF: Failed to locate clk node using its path\n"); + return node; + } + + /* + * Retrieve clock frequency. We assume clock provider generates a fixed + * clock. + */ + err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", + &uart_serial_config.uart_clk); + if (err < 0) { + ERROR("FCONF: Could not read clock-frequency property in clk node\n"); + return err; + } + + VERBOSE("FCONF: UART serial device clk frequency: %x\n", + uart_serial_config.uart_clk); + + return 0; +} + +int fconf_populate_cpu_timer(uintptr_t config) +{ + int err, node; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* Find the node offset point to "arm,armv8-timer" compatible property, + * a per-core architected timer attached to a GIC to deliver its per-processor + * interrupts via PPIs */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,armv8-timer"); + if (node < 0) { + ERROR("FCONF: Unrecognized hardware configuration dtb (%d)\n", node); + return node; + } + + /* Locate the cell holding the clock-frequency, an optional field */ + err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", &cpu_timer.clock_freq); + if (err < 0) { + WARN("FCONF failed to read clock-frequency property\n"); + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config); +FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology); +FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config); +FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer); diff --git a/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c new file mode 100644 index 0000000..e258015 --- /dev/null +++ b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <common/fdt_wrappers.h> + +#include <libfdt.h> +#include <fconf_nt_config_getter.h> + +#include <plat/common/platform.h> + +struct event_log_config_t event_log_config; + +int fconf_populate_event_log_config(uintptr_t config) +{ + int err; + int node; + + /* Necessary to work with libfdt APIs */ + const void *dtb = (const void *)config; + + /* + * Find the offset of the node containing "arm,tpm_event_log" + * compatible property + */ + const char *compatible_str = "arm,tpm_event_log"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find '%s' compatible in dtb\n", + compatible_str); + return node; + } + + /* Retrieve Event Log details from the DTB */ +#ifdef SPD_opteed + err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2, + &event_log_config.tpm_event_log_sm_addr); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n"); + return err; + } +#endif + err = fdtw_read_cells(dtb, node, + "tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n"); + return err; + } + + err = fdtw_read_cells(dtb, node, + "tpm_event_log_size", 1, &event_log_config.tpm_event_log_size); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n"); + } + + return err; +} + +FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config, + fconf_populate_event_log_config); diff --git a/plat/arm/board/fvp/fdts/event_log.dtsi b/plat/arm/board/fvp/fdts/event_log.dtsi new file mode 100644 index 0000000..47af672 --- /dev/null +++ b/plat/arm/board/fvp/fdts/event_log.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* TPM Event Log Config */ +event_log: tpm_event_log { + compatible = "arm,tpm_event_log"; + tpm_event_log_addr = <0x0 0x0>; + tpm_event_log_size = <0x0>; +}; diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts new file mode 100644 index 0000000..577ac74 --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x1800>; + id = <TB_FW_CONFIG_ID>; + }; + + hw-config { + load-address = <0x0 0x07f00000>; + max-size = <0x00100000>; + id = <HW_CONFIG_ID>; + ns-load-address = <0x0 0x82000000>; + }; + + /* + * Load SoC and TOS firmware configs at the base of + * non shared SRAM. The runtime checks ensure we don't + * overlap BL2, BL31 or BL32. The NT firmware config + * is loaded at base of DRAM. + */ + soc_fw-config { + load-address = <0x0 0x04001300>; + max-size = <0x200>; + id = <SOC_FW_CONFIG_ID>; + }; + +/* If required, SPD should enable loading of trusted OS fw config */ +#if defined(SPD_tspd) || defined(SPD_spmd) + tos_fw-config { + load-address = <0x0 0x04001500>; + max-size = <0xB00>; + id = <TOS_FW_CONFIG_ID>; + }; +#endif + + nt_fw-config { + load-address = <0x0 0x80000000>; + max-size = <0x200>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts new file mode 100644 index 0000000..8f32b98 --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { +#if MEASURED_BOOT +#include "event_log.dtsi" +#endif +}; + +#if MEASURED_BOOT && defined(SPD_opteed) +&event_log { + tpm_event_log_sm_addr = <0x0 0x0>; +}; +#endif diff --git a/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts new file mode 100644 index 0000000..7ab980b --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts new file mode 100644 index 0000000..4543671 --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#undef POST +#define POST \ + }; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0x6000000>; + entrypoint = <0x0 0x6000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "cactus-primary"; + load_address = <0x7000000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm2 { + is_ffa_partition; + debug_name = "cactus-secondary"; + load_address = <0x7100000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm3 { + is_ffa_partition; + debug_name = "cactus-tertiary"; + load_address = <0x7200000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + vm4 { + is_ffa_partition; + debug_name = "ivy"; + load_address = <0x7600000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU_0 + + /* + * SPMC (Hafnium) requires secondary core nodes are declared + * in descending order. + */ + CPU_7 + CPU_6 + CPU_5 + CPU_4 + CPU_3 + CPU_2 + CPU_1 + }; + + memory@6000000 { + device_type = "memory"; + reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */ + }; + +#if MEASURED_BOOT +#include "event_log.dtsi" +#endif +}; diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000..041dade --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#undef POST +#define POST \ + }; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0x6000000>; + entrypoint = <0x0 0x6000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "op-tee"; + load_address = <0x6280000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU_0 + + /* + * SPMC (Hafnium) requires secondary core nodes are declared + * in descending order. + */ + CPU_7 + CPU_6 + CPU_5 + CPU_4 + CPU_3 + CPU_2 + CPU_1 + }; + + memory@6000000 { + device_type = "memory"; + reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */ + }; +}; diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts new file mode 100644 index 0000000..6fd334d --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/libc/cdefs.h> + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; + + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) + */ + +#if ARM_IO_IN_DTB + arm-io_policies { + fip-handles { + compatible = "arm,io-fip-handle"; + scp_bl2_uuid = "9766fd3d-89be-e849-ae5d-78a140608213"; + bl31_uuid = "47d4086d-4cfe-9846-9b95-2950cbbd5a00"; + bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38"; + bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288"; + bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9"; + bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4"; + hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc"; + soc_fw_cfg_uuid = "9979814b-0376-fb46-8c8e-8d267f7859e0"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; + cca_cert_uuid = "36d83d85-761d-4daf-96f1-cd99d6569b00"; + core_swd_cert_uuid = "52222d31-820f-494d-8bbc-ea6825d3c35a"; + plat_cert_uuid = "d43cd902-5b9f-412e-8ac6-92b6d18be60d"; + t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c"; + scp_fw_key_uuid = "024221a1-f860-e411-8d9b-f33c0e15a014"; + soc_fw_key_uuid = "8ab8becc-f960-e411-9ad0-eb4822d8dcf8"; + tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04"; + nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859"; + scp_fw_content_cert_uuid = "44be6f04-5e63-e411-b28b-73d8eaae9656"; + soc_fw_content_cert_uuid = "e2b20c20-5e63-e411-9ce8-abccf92bb666"; + tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d"; + nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7"; + sp_content_cert_uuid = "776dfd44-8697-4c3b-91eb-c13e025a2a6f"; + }; + }; +#endif /* ARM_IO_IN_DTB */ + + secure-partitions { + compatible = "arm,sp"; + +#ifdef ARM_BL2_SP_LIST_DTS + #include __XSTRING(ARM_BL2_SP_LIST_DTS) +#else +#ifdef OPTEE_SP_FW_CONFIG + op-tee { + uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b"; + load-address = <0x6280000>; + }; +#else + cactus-primary { + uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb"; + load-address = <0x7000000>; + owner = "SiP"; + }; + + cactus-secondary { + uuid = "d1582309-f023-47b9-827c-4464f5578fc8"; + load-address = <0x7100000>; + owner = "Plat"; + }; + + cactus-tertiary { + uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2"; + load-address = <0x7200000>; + owner = "Plat"; + }; + + ivy { + uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7"; + load-address = <0x7600000>; + owner = "Plat"; + }; +#endif +#endif /* ARM_BL2_SP_LIST_DTS */ + }; + +#if COT_DESC_IN_DTB + #include "cot_descriptors.dtsi" +#endif + +#if MEASURED_BOOT + #include "event_log.dtsi" +#endif + +}; + +#if COT_DESC_IN_DTB + +#include "../fvp_def.h" + +&trusted_nv_counter { + reg = <TFW_NVCTR_BASE>; +}; + +&non_trusted_nv_counter { + reg = <NTFW_CTR_BASE>; +}; +#endif diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts new file mode 100644 index 0000000..7bed6cb --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { +#if MEASURED_BOOT +#include "event_log.dtsi" +#endif +}; diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts new file mode 100644 index 0000000..1587c72 --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#undef POST +#define POST \ + }; + +#define S_EL0 (0x1) +#define S_EL1 (0x2) + +/* For consumption by EL3 SPMC. */ +/ { + compatible = "arm,ffa-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + ffa-version = <0x00010001>; /* 31:16 - Major, 15:0 - Minor */ + id = <0x8001>; + uuid = <0x6b43b460 0x74a24b78 0xade24502 0x40682886>; + messaging-method = <0x3>; /* Direct Messaging Only */ + exception-level = <S_EL1>; + execution-state = <0>; + execution-ctx-count = <8>; + gp-register-num = <0>; + /* Subscribe to CPU_OFF, CPU_SUSPEND and CPU_SUSPEND_RESUME PM Msgs */ + power-management-messages = <0x7>; +}; diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts new file mode 100644 index 0000000..27f4724 --- /dev/null +++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP) + * that has additional optional properties defined. + * + */ + +/dts-v1/; + +/ { + compatible = "arm,ffa-manifest-1.0"; + + /* Properties */ + description = "op-tee"; + ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ + uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>; + id = <1>; + execution-ctx-count = <8>; + exception-level = <2>; /* S-EL1 */ + execution-state = <0>; /* AARCH64 */ + load-address = <0x6280000>; + entrypoint-offset = <0x4000>; + xlat-granule = <0>; /* 4KiB */ + boot-order = <0>; + messaging-method = <0x3>; /* Direct request/response supported. */ + managed-exit; + run-time-model = <1>; /* SP pre-emptible. */ + + /* Boot protocol */ + gp-register-num = <0x0>; + + device-regions { + compatible = "arm,ffa-manifest-device-regions"; + + uart1 { + base-address = <0x00000000 0x1c0a0000>; + pages-count = <1>; + attributes = <0x3>; /* read-write */ + }; + }; +}; diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c new file mode 100644 index 0000000..76cd918 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <drivers/measured_boot/event_log/event_log.h> +#include <drivers/measured_boot/rss/rss_measured_boot.h> +#include <plat/arm/common/plat_arm.h> + +/* Event Log data */ +static uint8_t event_log[PLAT_ARM_EVENT_LOG_MAX_SIZE]; + +/* FVP table with platform specific image IDs, names and PCRs */ +const event_log_metadata_t fvp_event_log_metadata[] = { + { FW_CONFIG_ID, EVLOG_FW_CONFIG_STRING, PCR_0 }, + { TB_FW_CONFIG_ID, EVLOG_TB_FW_CONFIG_STRING, PCR_0 }, + { BL2_IMAGE_ID, EVLOG_BL2_STRING, PCR_0 }, + + { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */ +}; + +/* FVP table with platform specific image IDs and metadata. Intentionally not a + * const struct, some members might set by bootloaders during trusted boot. + */ +struct rss_mboot_metadata fvp_rss_mboot_metadata[] = { + { + .id = FW_CONFIG_ID, + .slot = U(6), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_FW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = TB_FW_CONFIG_ID, + .slot = U(7), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = BL2_IMAGE_ID, + .slot = U(8), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_BL2_STRING, + .lock_measurement = true }, + + { + .id = RSS_MBOOT_INVALID_ID } +}; + +void bl1_plat_mboot_init(void) +{ + event_log_init(event_log, event_log + sizeof(event_log)); + event_log_write_header(); + + rss_measured_boot_init(); +} + +void bl1_plat_mboot_finish(void) +{ + size_t event_log_cur_size; + + event_log_cur_size = event_log_get_cur_size(event_log); + int rc = arm_set_tb_fw_info((uintptr_t)event_log, + event_log_cur_size); + if (rc != 0) { + /* + * It is a fatal error because on FVP platform, BL2 software + * assumes that a valid Event Log buffer exist and it will use + * same Event Log buffer to append image measurements. + */ + panic(); + } +} diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c new file mode 100644 index 0000000..59fc0f3 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl1_setup.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <bl1/bl1.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/arm/smmu_v3.h> +#include <drivers/arm/sp805.h> +#include <lib/mmio.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/common/arm_def.h> +#include <plat/common/platform.h> +#include "fvp_private.h" + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); + + /* On FVP RevC, initialize SMMUv3 */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) + smmuv3_security_init(PLAT_FVP_SMMUV3_BASE); +} + +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* Clear the NV flags register. */ + mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR), + nv_flags); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) + wfi(); +} + +/******************************************************************************* + * The following function checks if Firmware update is needed by checking error + * reported in NV flag. + ******************************************************************************/ +bool plat_arm_bl1_fwu_needed(void) +{ + int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* if image load/authentication failed */ + return ((nv_flags == -EAUTH) || (nv_flags == -ENOENT)); +} diff --git a/plat/arm/board/fvp/fvp_bl2_el3_setup.c b/plat/arm/board/fvp/fvp_bl2_el3_setup.c new file mode 100644 index 0000000..7def56a --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2_el3_setup.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +#include "fvp_private.h" + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + arm_bl2_el3_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c new file mode 100644 index 0000000..e938e24 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/measured_boot/event_log/event_log.h> +#include <drivers/measured_boot/rss/rss_measured_boot.h> +#include <tools_share/tbbr_oid.h> +#include <fvp_critical_data.h> + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/common_def.h> + +/* Event Log data */ +static uint64_t event_log_base; + +/* FVP table with platform specific image IDs, names and PCRs */ +const event_log_metadata_t fvp_event_log_metadata[] = { + { BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 }, + { BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 }, + { BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 }, + { BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 }, + { BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 }, + { HW_CONFIG_ID, EVLOG_HW_CONFIG_STRING, PCR_0 }, + { NT_FW_CONFIG_ID, EVLOG_NT_FW_CONFIG_STRING, PCR_0 }, + { SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 }, + { SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 }, + { TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 }, + { RMM_IMAGE_ID, EVLOG_RMM_STRING, PCR_0}, + +#if defined(SPD_spmd) + { SP_PKG1_ID, EVLOG_SP1_STRING, PCR_0 }, + { SP_PKG2_ID, EVLOG_SP2_STRING, PCR_0 }, + { SP_PKG3_ID, EVLOG_SP3_STRING, PCR_0 }, + { SP_PKG4_ID, EVLOG_SP4_STRING, PCR_0 }, + { SP_PKG5_ID, EVLOG_SP5_STRING, PCR_0 }, + { SP_PKG6_ID, EVLOG_SP6_STRING, PCR_0 }, + { SP_PKG7_ID, EVLOG_SP7_STRING, PCR_0 }, + { SP_PKG8_ID, EVLOG_SP8_STRING, PCR_0 }, +#endif + + { CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 }, + + { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */ +}; + +/* FVP table with platform specific image IDs and metadata. Intentionally not a + * const struct, some members might set by bootloaders during trusted boot. + */ +struct rss_mboot_metadata fvp_rss_mboot_metadata[] = { + { + .id = BL31_IMAGE_ID, + .slot = U(9), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_BL31_STRING, + .lock_measurement = true }, + { + .id = HW_CONFIG_ID, + .slot = U(10), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_HW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = SOC_FW_CONFIG_ID, + .slot = U(11), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = RMM_IMAGE_ID, + .slot = U(12), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_RMM_STRING, + .lock_measurement = true }, + { + .id = RSS_MBOOT_INVALID_ID } +}; + +void bl2_plat_mboot_init(void) +{ + uint8_t *event_log_start; + uint8_t *event_log_finish; + size_t bl1_event_log_size; + int rc; + + rc = arm_get_tb_fw_info(&event_log_base, &bl1_event_log_size); + if (rc != 0) { + ERROR("%s(): Unable to get Event Log info from TB_FW_CONFIG\n", + __func__); + /* + * It is a fatal error because on FVP platform, BL2 software + * assumes that a valid Event Log buffer exist and it will use + * same Event Log buffer to append image measurements. + */ + panic(); + } + + /* + * BL1 and BL2 share the same Event Log buffer and that BL2 will + * append its measurements after BL1's + */ + event_log_start = (uint8_t *)((uintptr_t)event_log_base + + bl1_event_log_size); + event_log_finish = (uint8_t *)((uintptr_t)event_log_base + + PLAT_ARM_EVENT_LOG_MAX_SIZE); + + event_log_init((uint8_t *)event_log_start, event_log_finish); + + rss_measured_boot_init(); +} + +int plat_mboot_measure_critical_data(unsigned int critical_data_id, + const void *base, size_t size) +{ + /* + * It is very unlikely that the critical data size would be + * bigger than 2^32 bytes + */ + assert(size < UINT32_MAX); + assert(base != NULL); + + /* Calculate image hash and record data in Event Log */ + int err = event_log_measure_and_record((uintptr_t)base, (uint32_t)size, + critical_data_id); + if (err != 0) { + ERROR("%s%s critical data (%i)\n", + "Failed to ", "record", err); + return err; + } + + return 0; +} + +#if TRUSTED_BOARD_BOOT +static int fvp_populate_critical_data(struct fvp_critical_data *critical_data) +{ + char *nv_ctr_oids[MAX_NV_CTR_IDS] = { + [TRUSTED_NV_CTR_ID] = TRUSTED_FW_NVCOUNTER_OID, + [NON_TRUSTED_NV_CTR_ID] = NON_TRUSTED_FW_NVCOUNTER_OID, + }; + + for (int i = 0; i < MAX_NV_CTR_IDS; i++) { + int rc = plat_get_nv_ctr(nv_ctr_oids[i], + &critical_data->nv_ctr[i]); + if (rc != 0) { + return rc; + } + } + + return 0; +} +#endif /* TRUSTED_BOARD_BOOT */ + +static int fvp_populate_and_measure_critical_data(void) +{ + int rc = 0; + +/* + * FVP platform only measures 'platform NV-counter' and hence its + * measurement makes sense during Trusted-Boot flow only. + */ +#if TRUSTED_BOARD_BOOT + struct fvp_critical_data populate_critical_data; + + rc = fvp_populate_critical_data(&populate_critical_data); + if (rc == 0) { + rc = plat_mboot_measure_critical_data(CRITICAL_DATA_ID, + &populate_critical_data, + sizeof(populate_critical_data)); + } +#endif /* TRUSTED_BOARD_BOOT */ + + return rc; +} + +void bl2_plat_mboot_finish(void) +{ + int rc; + + /* Event Log address in Non-Secure memory */ + uintptr_t ns_log_addr; + + /* Event Log filled size */ + size_t event_log_cur_size; + + rc = fvp_populate_and_measure_critical_data(); + if (rc != 0) { + panic(); + } + + event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base); + + rc = arm_set_nt_fw_info( +#ifdef SPD_opteed + (uintptr_t)event_log_base, +#endif + event_log_cur_size, &ns_log_addr); + if (rc != 0) { + ERROR("%s(): Unable to update %s_FW_CONFIG\n", + __func__, "NT"); + /* + * It is a fatal error because on FVP secure world software + * assumes that a valid event log exists and will use it to + * record the measurements into the fTPM. + * Note: In FVP platform, OP-TEE uses nt_fw_config to get the + * secure Event Log buffer address. + */ + panic(); + } + + /* Copy Event Log to Non-secure memory */ + (void)memcpy((void *)ns_log_addr, (const void *)event_log_base, + event_log_cur_size); + + /* Ensure that the Event Log is visible in Non-secure memory */ + flush_dcache_range(ns_log_addr, event_log_cur_size); + +#if defined(SPD_tspd) || defined(SPD_spmd) + /* Set Event Log data in TOS_FW_CONFIG */ + rc = arm_set_tos_fw_info((uintptr_t)event_log_base, + event_log_cur_size); + if (rc != 0) { + ERROR("%s(): Unable to update %s_FW_CONFIG\n", + __func__, "TOS"); + panic(); + } +#endif /* defined(SPD_tspd) || defined(SPD_spmd) */ + + dump_event_log((uint8_t *)event_log_base, event_log_cur_size); +} diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c new file mode 100644 index 0000000..74e5d72 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2_setup.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/arm/sp804_delay_timer.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#include "fvp_private.h" + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); +} + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params; + const struct dyn_cfg_dtb_info_t *hw_config_info __unused; + bl_mem_params_node_t *param_node __unused; + + arm_bl_params = arm_get_next_bl_params(); + +#if !BL2_AT_EL3 && !EL3_PAYLOAD_BASE + const struct dyn_cfg_dtb_info_t *fw_config_info; + uintptr_t fw_config_base = 0UL; + entry_point_info_t *ep_info; + +#if __aarch64__ + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); +#else /* aarch32 */ + /* Get SP_MIN image node */ + param_node = get_bl_mem_params_node(BL32_IMAGE_ID); +#endif /* __aarch64__ */ + assert(param_node != NULL); + + /* get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0UL); + + /* + * Get the entry point info of next executable image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; + + /* grab NS HW config address */ + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + /* To retrieve actual size of the HW_CONFIG */ + param_node = get_bl_mem_params_node(HW_CONFIG_ID); + assert(param_node != NULL); + + /* Copy HW config from Secure address to NS address */ + memcpy((void *)hw_config_info->ns_config_addr, + (void *)hw_config_info->config_addr, + (size_t)param_node->image_info.image_size); + + /* + * Ensure HW-config device tree committed to memory, as there is + * a possibility to use HW-config without cache and MMU enabled + * at BL33 + */ + flush_dcache_range(hw_config_info->ns_config_addr, + param_node->image_info.image_size); + + param_node = get_bl_mem_params_node(BL33_IMAGE_ID); + assert(param_node != NULL); + + /* Update BL33's ep info with NS HW config address */ + param_node->ep_info.args.arg1 = hw_config_info->ns_config_addr; +#endif /* !BL2_AT_EL3 && !EL3_PAYLOAD_BASE */ + + return arm_bl_params; +} diff --git a/plat/arm/board/fvp/fvp_bl2u_setup.c b/plat/arm/board/fvp/fvp_bl2u_setup.c new file mode 100644 index 0000000..fd73767 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2u_setup.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#include "fvp_private.h" + +void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) +{ + arm_bl2u_early_platform_setup(mem_layout, plat_info); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c new file mode 100644 index 0000000..dd90965 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl31_setup.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <common/debug.h> +#include <drivers/arm/smmu_v3.h> +#include <fconf_hw_config_getter.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> +#include <lib/mmio.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#include "fvp_private.h" + +static const struct dyn_cfg_dtb_info_t *hw_config_info __unused; + +void __init bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + +#if !RESET_TO_BL31 && !BL2_AT_EL3 + const struct dyn_cfg_dtb_info_t *soc_fw_config_info; + + INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); + + soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); + if (soc_fw_config_info != NULL) { + arg1 = soc_fw_config_info->config_addr; + } + + /* + * arg2 is currently holding the 'secure' address of HW_CONFIG. + * But arm_bl31_early_platform_setup() below expects the 'non-secure' + * address of HW_CONFIG (which it will pass to BL33). + * This why we need to override arg2 here. + */ + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + assert(hw_config_info->ns_config_addr != 0UL); + arg2 = hw_config_info->ns_config_addr; +#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 */ + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize the correct interconnect for this cluster during cold + * boot. No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * FVP PSCI code will enable coherency for other clusters. + */ + fvp_interconnect_enable(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); + + /* On FVP RevC, initialize SMMUv3 */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) + smmuv3_init(PLAT_FVP_SMMUV3_BASE); +} + +void __init bl31_plat_arch_setup(void) +{ + int rc __unused; + uintptr_t hw_config_base_align __unused; + size_t mapped_size_align __unused; + + arm_bl31_plat_arch_setup(); + + /* + * For RESET_TO_BL31 systems, BL31 is the first bootloader to run. + * So there is no BL2 to load the HW_CONFIG dtb into memory before + * control is passed to BL31. The code below relies on dynamic mapping + * capability, which is not supported by xlat tables lib V1. + * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support + * gets deprecated. + */ +#if !RESET_TO_BL31 && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 + assert(hw_config_info != NULL); + assert(hw_config_info->config_addr != 0UL); + + /* Page aligned address and size if necessary */ + hw_config_base_align = page_align(hw_config_info->config_addr, DOWN); + mapped_size_align = page_align(hw_config_info->config_max_size, UP); + + if ((hw_config_info->config_addr != hw_config_base_align) && + (hw_config_info->config_max_size == mapped_size_align)) { + mapped_size_align += PAGE_SIZE; + } + + /* + * map dynamically HW config region with its aligned base address and + * size + */ + rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align, + hw_config_base_align, + mapped_size_align, + MT_RO_DATA); + if (rc != 0) { + ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc); + panic(); + } + + /* Populate HW_CONFIG device tree with the mapped address */ + fconf_populate("HW_CONFIG", hw_config_info->config_addr); + + /* unmap the HW_CONFIG memory region */ + rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align); + if (rc != 0) { + ERROR("Error while unmapping HW_CONFIG device tree (%d).\n", + rc); + panic(); + } +#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 */ +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + +#if !RESET_TO_BL31 && !BL2_AT_EL3 + /* Get the frequency through FCONF API for HW_CONFIG */ + counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq); + if (counter_base_frequency > 0U) { + return counter_base_frequency; + } +#endif + + /* Read the frequency from Frequency modes table */ + counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); + + /* The first entry of the frequency modes table must not be 0 */ + if (counter_base_frequency == 0U) { + panic(); + } + + return counter_base_frequency; +} diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c new file mode 100644 index 0000000..f8463f1 --- /dev/null +++ b/plat/arm/board/fvp/fvp_common.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <drivers/arm/cci.h> +#include <drivers/arm/ccn.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/sp804_delay_timer.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <lib/smccc.h> +#include <lib/xlat_tables/xlat_tables_compat.h> +#include <platform_def.h> +#include <services/arm_arch_svc.h> +#if ENABLE_RME +#include <services/rmm_core_manifest.h> +#endif +#if SPM_MM +#include <services/spm_mm_partition.h> +#endif + +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#include "fvp_private.h" + +/* Defines for GIC Driver build time selection */ +#define FVP_GICV2 1 +#define FVP_GICV3 2 + +/******************************************************************************* + * arm_config holds the characteristics of the differences between the three FVP + * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot + * at each boot stage by the primary before enabling the MMU (to allow + * interconnect configuration) & used thereafter. Each BL will have its own copy + * to allow independent operation. + ******************************************************************************/ +arm_config_t arm_config; + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#if FVP_GICR_REGION_PROTECTION +#define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \ + BASE_GICD_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Map all core's redistributor memory as read-only. After boots up, + * per-core map its redistributor memory as read-write */ +#define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \ + (BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\ + MT_DEVICE | MT_RO | MT_SECURE) +#endif /* FVP_GICR_REGION_PROTECTION */ + +/* + * Need to be mapped with write permissions in order to set a new non-volatile + * counter value. + */ +#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ + DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of memory regions for various BL stages to map using the MMU. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. + */ +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RO, + V2M_MAP_IOFPGA, + MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + MAP_DEVICE1, +#endif +#if TRUSTED_BOARD_BOOT + /* To access the Root of Trust Public Key registers. */ + MAP_DEVICE2, + /* Map DRAM to authenticate NS_BL2U image. */ + ARM_MAP_NS_DRAM1, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, + V2M_MAP_IOFPGA, + MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + MAP_DEVICE1, +#endif + ARM_MAP_NS_DRAM1, +#ifdef __aarch64__ + ARM_MAP_DRAM2, +#endif + /* + * Required to load HW_CONFIG, SPMC and SPs to trusted DRAM. + */ + ARM_MAP_TRUSTED_DRAM, +#if ENABLE_RME + ARM_MAP_RMM_DRAM, + ARM_MAP_GPT_L1_DRAM, +#endif /* ENABLE_RME */ +#ifdef SPD_tspd + ARM_MAP_TSP_SEC_MEM, +#endif +#if TRUSTED_BOARD_BOOT + /* To access the Root of Trust Public Key registers. */ + MAP_DEVICE2, +#endif /* TRUSTED_BOARD_BOOT */ + +#if CRYPTO_SUPPORT && !BL2_AT_EL3 + /* + * To access shared the Mbed TLS heap while booting the + * system with Crypto support + */ + ARM_MAP_BL1_RW, +#endif /* CRYPTO_SUPPORT && !BL2_AT_EL3 */ +#if SPM_MM || SPMC_AT_EL3 + ARM_SP_IMAGE_MMAP, +#endif +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2U +const mmap_region_t plat_arm_mmap[] = { + MAP_DEVICE0, + V2M_MAP_IOFPGA, + {0} +}; +#endif +#ifdef IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, +#if USE_DEBUGFS + /* Required by devfip, can be removed if devfip is not used */ + V2M_MAP_FLASH0_RW, +#endif /* USE_DEBUGFS */ + ARM_MAP_EL3_TZC_DRAM, + V2M_MAP_IOFPGA, + MAP_DEVICE0, +#if FVP_GICR_REGION_PROTECTION + MAP_GICD_MEM, + MAP_GICR_MEM, +#else + MAP_DEVICE1, +#endif /* FVP_GICR_REGION_PROTECTION */ + ARM_V2M_MAP_MEM_PROTECT, +#if SPM_MM + ARM_SPM_BUF_EL3_MMAP, +#endif +#if ENABLE_RME + ARM_MAP_GPT_L1_DRAM, + ARM_MAP_EL3_RMM_SHARED_MEM, +#endif + {0} +}; + +#if defined(IMAGE_BL31) && SPM_MM +const mmap_region_t plat_arm_secure_partition_mmap[] = { + V2M_MAP_IOFPGA_EL0, /* for the UART */ + MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE | MT_USER), + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { +#ifndef __aarch64__ + ARM_MAP_SHARED_RAM, + ARM_V2M_MAP_MEM_PROTECT, +#endif + V2M_MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif + +#ifdef IMAGE_RMM +const mmap_region_t plat_arm_mmap[] = { + V2M_MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +#if FVP_INTERCONNECT_DRIVER != FVP_CCN +static const int fvp_cci400_map[] = { + PLAT_FVP_CCI400_CLUS0_SL_PORT, + PLAT_FVP_CCI400_CLUS1_SL_PORT, +}; + +static const int fvp_cci5xx_map[] = { + PLAT_FVP_CCI5XX_CLUS0_SL_PORT, + PLAT_FVP_CCI5XX_CLUS1_SL_PORT, +}; + +static unsigned int get_interconnect_master(void) +{ + unsigned int master; + u_register_t mpidr; + + mpidr = read_mpidr_el1(); + master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ? + MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); + + assert(master < FVP_CLUSTER_COUNT); + return master; +} +#endif + +#if defined(IMAGE_BL31) && SPM_MM +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x80000000, 0}, + [1] = {0x80000001, 0}, + [2] = {0x80000002, 0}, + [3] = {0x80000003, 0}, + [4] = {0x80000100, 0}, + [5] = {0x80000101, 0}, + [6] = {0x80000102, 0}, + [7] = {0x80000103, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} +#endif + +/******************************************************************************* + * A single boot loader stack is expected to work on both the Foundation FVP + * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The + * SYS_ID register provides a mechanism for detecting the differences between + * these platforms. This information is stored in a per-BL array to allow the + * code to take the correct path.Per BL platform configuration. + ******************************************************************************/ +void __init fvp_config_setup(void) +{ + unsigned int rev, hbi, bld, arch, sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK; + hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK; + bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK; + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL) { + ERROR("This firmware is for FVP models\n"); + panic(); + } + + /* + * The build field in the SYS_ID tells which variant of the GIC + * memory is implemented by the model. + */ + switch (bld) { + case BLD_GIC_VE_MMAP: + ERROR("Legacy Versatile Express memory map for GIC peripheral" + " is not supported\n"); + panic(); + break; + case BLD_GIC_A53A57_MMAP: + break; + default: + ERROR("Unsupported board build %x\n", bld); + panic(); + } + + /* + * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010 + * for the Foundation FVP. + */ + switch (hbi) { + case HBI_FOUNDATION_FVP: + arm_config.flags = 0; + + /* + * Check for supported revisions of Foundation FVP + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_FOUNDATION_FVP_V2_0: + case REV_FOUNDATION_FVP_V2_1: + case REV_FOUNDATION_FVP_v9_1: + case REV_FOUNDATION_FVP_v9_6: + break; + default: + WARN("Unrecognized Foundation FVP revision %x\n", rev); + break; + } + break; + case HBI_BASE_FVP: + arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); + + /* + * Check for supported revisions + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_BASE_FVP_V0: + arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; + break; + case REV_BASE_FVP_REVC: + arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 | + ARM_CONFIG_FVP_HAS_CCI5XX); + break; + default: + WARN("Unrecognized Base FVP revision %x\n", rev); + break; + } + break; + default: + ERROR("Unsupported board HBI number 0x%x\n", hbi); + panic(); + } + + /* + * We assume that the presence of MT bit, and therefore shifted + * affinities, is uniform across the platform: either all CPUs, or no + * CPUs implement it. + */ + if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) + arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF; +} + + +void __init fvp_interconnect_init(void) +{ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) { + ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported"); + panic(); + } + + plat_arm_interconnect_init(); +#else + uintptr_t cci_base = 0U; + const int *cci_map = NULL; + unsigned int map_size = 0U; + + /* Initialize the right interconnect */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) { + cci_base = PLAT_FVP_CCI5XX_BASE; + cci_map = fvp_cci5xx_map; + map_size = ARRAY_SIZE(fvp_cci5xx_map); + } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) { + cci_base = PLAT_FVP_CCI400_BASE; + cci_map = fvp_cci400_map; + map_size = ARRAY_SIZE(fvp_cci400_map); + } else { + return; + } + + assert(cci_base != 0U); + assert(cci_map != NULL); + cci_init(cci_base, cci_map, map_size); +#endif +} + +void fvp_interconnect_enable(void) +{ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + plat_arm_interconnect_enter_coherency(); +#else + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_enable_snoop_dvm_reqs(master); + } +#endif +} + +void fvp_interconnect_disable(void) +{ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + plat_arm_interconnect_exit_coherency(); +#else + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_disable_snoop_dvm_reqs(master); + } +#endif +} + +#if CRYPTO_SUPPORT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif /* CRYPTO_SUPPORT */ + +void fvp_timer_init(void) +{ +#if USE_SP804_TIMER + /* Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35MHz) clock will be used. + */ + mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); + + /* Enable System level generic timer */ + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); +#endif /* USE_SP804_TIMER */ +} + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + return (int32_t) + (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE, + ARM_SOC_IDENTIFICATION_CODE) | + (FVP_SOC_ID & SOC_ID_IMPL_DEF_MASK)); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + unsigned int sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) & + V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK); +} + +#if ENABLE_RME +/* + * Get a pointer to the RMM-EL3 Shared buffer and return it + * through the pointer passed as parameter. + * + * This function returns the size of the shared buffer. + */ +size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared) +{ + *shared = (uintptr_t)RMM_SHARED_BASE; + + return (size_t)RMM_SHARED_SIZE; +} + +int plat_rmmd_load_manifest(rmm_manifest_t *manifest) +{ + assert(manifest != NULL); + + manifest->version = RMMD_MANIFEST_VERSION; + manifest->plat_data = (uintptr_t)NULL; + + return 0; +} + +#endif diff --git a/plat/arm/board/fvp/fvp_common_measured_boot.c b/plat/arm/board/fvp/fvp_common_measured_boot.c new file mode 100644 index 0000000..93aa055 --- /dev/null +++ b/plat/arm/board/fvp/fvp_common_measured_boot.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> + +#include <common/desc_image_load.h> +#include <drivers/measured_boot/event_log/event_log.h> +#include <drivers/measured_boot/rss/rss_measured_boot.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +extern event_log_metadata_t fvp_event_log_metadata[]; +extern struct rss_mboot_metadata fvp_rss_mboot_metadata[]; + +const event_log_metadata_t *plat_event_log_get_metadata(void) +{ + return fvp_event_log_metadata; +} + +struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void) +{ + return fvp_rss_mboot_metadata; +} + +int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data) +{ + int err; + int rc = 0; + + /* Calculate image hash and record data in Event Log */ + err = event_log_measure_and_record(image_data->image_base, + image_data->image_size, + image_id); + if (err != 0) { + ERROR("%s%s image id %u (%i)\n", + "Failed to ", "record in event log", image_id, err); + rc = err; + } + + /* Calculate image hash and record data in RSS */ + err = rss_mboot_measure_and_record(image_data->image_base, + image_data->image_size, + image_id); + if (err != 0) { + ERROR("%s%s image id %u (%i)\n", + "Failed to ", "record in RSS", image_id, err); + rc = (rc == 0) ? err : -1; + } + + return rc; +} diff --git a/plat/arm/board/fvp/fvp_console.c b/plat/arm/board/fvp/fvp_console.c new file mode 100644 index 0000000..1a6cd42 --- /dev/null +++ b/plat/arm/board/fvp/fvp_console.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <common/debug.h> +#include <drivers/arm/pl011.h> +#include <drivers/console.h> +#include <fconf_hw_config_getter.h> +#include <plat/arm/common/plat_arm.h> + +static console_t fvp_runtime_console; + +/* Initialize the runtime console */ +void arm_console_runtime_init(void) +{ + uintptr_t uart_base; + uint32_t uart_clk; + + /* + * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and + * BL2_AT_EL3 systems. + */ +#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3 + uart_base = PLAT_ARM_RUN_UART_BASE; + uart_clk = PLAT_ARM_RUN_UART_CLK_IN_HZ; +#else + uart_base = FCONF_GET_PROPERTY(hw_config, uart_serial_config, + uart_base); + uart_clk = FCONF_GET_PROPERTY(hw_config, uart_serial_config, + uart_clk); +#endif + + int rc = console_pl011_register(uart_base, uart_clk, + ARM_CONSOLE_BAUDRATE, + &fvp_runtime_console); + + if (rc == 0) { + panic(); + } + + console_set_scope(&fvp_runtime_console, CONSOLE_FLAG_RUNTIME); +} + +void arm_console_runtime_end(void) +{ + console_flush(); + (void)console_unregister(&fvp_runtime_console); +} diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h new file mode 100644 index 0000000..831eb35 --- /dev/null +++ b/plat/arm/board/fvp/fvp_def.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_DEF_H +#define FVP_DEF_H + +#include <lib/utils_def.h> + +#ifndef FVP_CLUSTER_COUNT +#error "FVP_CLUSTER_COUNT is not set in makefile" +#endif + +#ifndef FVP_MAX_CPUS_PER_CLUSTER +#error "FVP_MAX_CPUS_PER_CLUSTER is not set in makefile" +#endif + +#ifndef FVP_MAX_PE_PER_CPU +#error "FVP_MAX_PE_PER_CPU is not set in makefile" +#endif + +#define FVP_PRIMARY_CPU 0x0 + +/* Defines for the Interconnect build selection */ +#define FVP_CCI 1 +#define FVP_CCN 2 + +/****************************************************************************** + * Definition of platform soc id + *****************************************************************************/ +#define FVP_SOC_ID 0 + +/******************************************************************************* + * FVP memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE UL(0x0c000000) +#define FLASH1_SIZE UL(0x04000000) + +#define PSRAM_BASE UL(0x14000000) +#define PSRAM_SIZE UL(0x04000000) + +#define VRAM_BASE UL(0x18000000) +#define VRAM_SIZE UL(0x02000000) + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE UL(0x20000000) +#define DEVICE0_SIZE UL(0x0c200000) + +/* + * In case of FVP models with CCN, the CCN register space overlaps into + * the NSRAM area. + */ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN +#define DEVICE1_BASE UL(0x2e000000) +#define DEVICE1_SIZE UL(0x1A00000) +#else +#define DEVICE1_BASE BASE_GICD_BASE + +#if GIC_ENABLE_V4_EXTN +/* GICv4 mapping: GICD + CORE_COUNT * 256KB */ +#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \ + (PLATFORM_CORE_COUNT * 0x40000)) +#else +/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */ +#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \ + (PLATFORM_CORE_COUNT * 0x20000)) +#endif /* GIC_ENABLE_V4_EXTN */ + +#define NSRAM_BASE UL(0x2e000000) +#define NSRAM_SIZE UL(0x10000) +#endif +/* Devices in the second GB */ +#define DEVICE2_BASE UL(0x7fe00000) +#define DEVICE2_SIZE UL(0x00200000) + +#define PCIE_EXP_BASE UL(0x40000000) +#define TZRNG_BASE UL(0x7fe60000) + +/* Non-volatile counters */ +#define TRUSTED_NVCTR_BASE UL(0x7fe70000) +#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000)) +#define TFW_NVCTR_SIZE UL(4) +#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004)) +#define NTFW_CTR_SIZE UL(4) + +/* Keys */ +#define SOC_KEYS_BASE UL(0x7fe80000) +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000)) +#define TZ_PUB_KEY_HASH_SIZE UL(32) +#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020)) +#define HU_KEY_SIZE UL(16) +#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044)) +#define END_KEY_SIZE UL(32) + +/* Constants to distinguish FVP type */ +#define HBI_BASE_FVP U(0x020) +#define REV_BASE_FVP_V0 U(0x0) +#define REV_BASE_FVP_REVC U(0x2) + +#define HBI_FOUNDATION_FVP U(0x010) +#define REV_FOUNDATION_FVP_V2_0 U(0x0) +#define REV_FOUNDATION_FVP_V2_1 U(0x1) +#define REV_FOUNDATION_FVP_v9_1 U(0x2) +#define REV_FOUNDATION_FVP_v9_6 U(0x3) + +#define BLD_GIC_VE_MMAP U(0x0) +#define BLD_GIC_A53A57_MMAP U(0x1) + +#define ARCH_MODEL U(0x1) + +/* FVP Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP specific flags */ +#define FVP_SP810_CTRL_TIM0_OV BIT_32(16) +#define FVP_SP810_CTRL_TIM1_OV BIT_32(18) +#define FVP_SP810_CTRL_TIM2_OV BIT_32(20) +#define FVP_SP810_CTRL_TIM3_OV BIT_32(22) + +/******************************************************************************* + * GIC & interrupt handling related constants + ******************************************************************************/ +/* VE compatible GIC memory map */ +#define VE_GICD_BASE UL(0x2c001000) +#define VE_GICC_BASE UL(0x2c002000) +#define VE_GICH_BASE UL(0x2c004000) +#define VE_GICV_BASE UL(0x2c006000) + +/* Base FVP compatible GIC memory map */ +#define BASE_GICD_BASE UL(0x2f000000) +#define BASE_GICD_SIZE UL(0x10000) +#define BASE_GICR_BASE UL(0x2f100000) + +#if GIC_ENABLE_V4_EXTN +/* GICv4 redistributor size: 256KB */ +#define BASE_GICR_SIZE UL(0x40000) +#else +#define BASE_GICR_SIZE UL(0x20000) +#endif /* GIC_ENABLE_V4_EXTN */ + +#define BASE_GICC_BASE UL(0x2c000000) +#define BASE_GICH_BASE UL(0x2c010000) +#define BASE_GICV_BASE UL(0x2c02f000) + +#define FVP_IRQ_TZ_WDOG 56 +#define FVP_IRQ_SEC_SYS_TIMER 57 + +/******************************************************************************* + * TrustZone address space controller related constants + ******************************************************************************/ + +/* NSAIDs used by devices in TZC filter 0 on FVP */ +#define FVP_NSAID_DEFAULT 0 +#define FVP_NSAID_PCI 1 +#define FVP_NSAID_VIRTIO 8 /* from FVP v5.6 onwards */ +#define FVP_NSAID_AP 9 /* Application Processors */ +#define FVP_NSAID_VIRTIO_OLD 15 /* until FVP v5.5 */ + +/* NSAIDs used by devices in TZC filter 2 on FVP */ +#define FVP_NSAID_HDLCD0 2 +#define FVP_NSAID_CLCD 7 + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#endif /* FVP_DEF_H */ diff --git a/plat/arm/board/fvp/fvp_drtm_addr.c b/plat/arm/board/fvp/fvp_drtm_addr.c new file mode 100644 index 0000000..eeaa342 --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_addr.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <stdint.h> + +#include <plat/common/platform.h> +#include <platform_def.h> + +/******************************************************************************* + * Check passed region is within Non-Secure region of DRAM + ******************************************************************************/ +int plat_drtm_validate_ns_region(uintptr_t region_start, + size_t region_size) +{ + uintptr_t region_end = region_start + region_size - 1; + + if (region_start >= region_end) { + return -1; + } else if ((region_start >= ARM_NS_DRAM1_BASE) && + (region_start < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE)) && + (region_end >= ARM_NS_DRAM1_BASE) && + (region_end < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { + return 0; + } else if ((region_start >= ARM_DRAM2_BASE) && + (region_start < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE)) && + (region_end >= ARM_DRAM2_BASE) && + (region_end < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { + return 0; + } + + return -1; +} diff --git a/plat/arm/board/fvp/fvp_drtm_dma_prot.c b/plat/arm/board/fvp/fvp_drtm_dma_prot.c new file mode 100644 index 0000000..38ff7fe --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_dma_prot.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdbool.h> +#include <stddef.h> + +#include <drivers/arm/smmu_v3.h> +#include <lib/utils_def.h> +#include <plat/arm/common/arm_config.h> +#include <plat/common/platform.h> + +#include <platform_def.h> + +/** + * Array mentioning number of SMMUs supported by FVP + */ +static const uintptr_t fvp_smmus[] = { + PLAT_FVP_SMMUV3_BASE, +}; + +bool plat_has_non_host_platforms(void) +{ + /* FVP base platforms typically have GPU, as per FVP Reference guide */ + return true; +} + +bool plat_has_unmanaged_dma_peripherals(void) +{ + /* + * FVP Reference guide does not show devices that are described as + * DMA-capable but not managed by an SMMU in the FVP documentation. + * However, the SMMU seems to have only been introduced in the RevC + * revision. + */ + return (arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) == 0; +} + +unsigned int plat_get_total_smmus(void) +{ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) { + return ARRAY_SIZE(fvp_smmus); + } else { + return 0; + } +} + +void plat_enumerate_smmus(const uintptr_t **smmus_out, + size_t *smmu_count_out) +{ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) { + *smmus_out = fvp_smmus; + *smmu_count_out = ARRAY_SIZE(fvp_smmus); + } else { + *smmus_out = NULL; + *smmu_count_out = 0; + } +} + +/* DRTM DMA Protection Features */ +static const plat_drtm_dma_prot_features_t dma_prot_features = { + .max_num_mem_prot_regions = 0, /* No protection regions are present */ + .dma_protection_support = 0x1 /* Complete DMA protection only */ +}; + +const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void) +{ + return &dma_prot_features; +} + +uint64_t plat_drtm_dma_prot_get_max_table_bytes(void) +{ + return 0U; +} diff --git a/plat/arm/board/fvp/fvp_drtm_err.c b/plat/arm/board/fvp/fvp_drtm_err.c new file mode 100644 index 0000000..95259fa --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_err.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <plat/common/platform.h> + +int plat_set_drtm_error(uint64_t error_code) +{ + /* TODO: Set DRTM error in NV-storage */ + return 0; +} + +int plat_get_drtm_error(uint64_t *error_code) +{ + /* TODO: Get DRTM error from NV-storage */ + *error_code = 0; + return 0; +} diff --git a/plat/arm/board/fvp/fvp_drtm_measurement.c b/plat/arm/board/fvp/fvp_drtm_measurement.c new file mode 100644 index 0000000..4fbedd8 --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_measurement.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <drivers/measured_boot/event_log/event_log.h> +#include <plat/common/platform.h> + +#include <platform_def.h> + +/* DRTM TPM Features */ +static const plat_drtm_tpm_features_t tpm_features = { + /* No TPM-based hashing supported. */ + .tpm_based_hash_support = false, + + /* Set to decided algorithm by Event Log driver */ + .firmware_hash_algorithm = TPM_ALG_ID + +}; + +const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void) +{ + return &tpm_features; +} diff --git a/plat/arm/board/fvp/fvp_drtm_stub.c b/plat/arm/board/fvp/fvp_drtm_stub.c new file mode 100644 index 0000000..e2bc516 --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_stub.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include <stdint.h> + +#include <services/drtm_svc.h> + +/* + * This file contains DRTM platform functions which don't really do anything on + * FVP but are needed for DRTM to function. + */ + +uint64_t plat_drtm_get_min_size_normal_world_dce(void) +{ + return 0ULL; +} + +uint64_t plat_drtm_get_imp_def_dlme_region_size(void) +{ + return 0ULL; +} + +uint64_t plat_drtm_get_tcb_hash_features(void) +{ + return 0ULL; +} + +uint64_t plat_drtm_get_tcb_hash_table_size(void) +{ + return 0ULL; +} diff --git a/plat/arm/board/fvp/fvp_el3_spmc.c b/plat/arm/board/fvp/fvp_el3_spmc.c new file mode 100644 index 0000000..2b347ed --- /dev/null +++ b/plat/arm/board/fvp/fvp_el3_spmc.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <services/el3_spmc_ffa_memory.h> + +#include <platform_def.h> + +/* + * On the FVP platform when using the EL3 SPMC implementation allocate the + * datastore for tracking shared memory descriptors in the TZC DRAM section + * to ensure sufficient storage can be allocated. + * Provide an implementation of the accessor method to allow the datastore + * details to be retrieved by the SPMC. + * The SPMC will take care of initializing the memory region. + */ + +#define PLAT_SPMC_SHMEM_DATASTORE_SIZE 512 * 1024 + +__section("arm_el3_tzc_dram") static uint8_t +plat_spmc_shmem_datastore[PLAT_SPMC_SHMEM_DATASTORE_SIZE]; + +int plat_spmc_shmem_datastore_get(uint8_t **datastore, size_t *size) +{ + *datastore = plat_spmc_shmem_datastore; + *size = PLAT_SPMC_SHMEM_DATASTORE_SIZE; + return 0; +} + +/* + * Add dummy implementations of memory management related platform hooks. + * These can be used to implement platform specific functionality to support + * a memory sharing/lending operation. + * + * Note: The hooks must be located as part of the initial share request and + * final reclaim to prevent order dependencies with operations that may take + * place in the normal world without visibility of the SPMC. + */ +int plat_spmc_shmem_begin(struct ffa_mtd *desc) +{ + return 0; +} +int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) +{ + return 0; +} diff --git a/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c new file mode 100644 index 0000000..b9e4f86 --- /dev/null +++ b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <services/el3_spmc_logical_sp.h> +#include <services/ffa_svc.h> +#include <smccc_helpers.h> + +#define LP_PARTITION_ID 0xC001 +#define LP_UUID {0x47a3bf57, 0xe98e43ad, 0xb7db524f, 0x1588f4e3} + +/* Our Logical SP currently only supports receipt of direct messaging. */ +#define PARTITION_PROPERTIES FFA_PARTITION_DIRECT_REQ_RECV + +static int32_t sp_init(void) +{ + INFO("LSP: Init function called.\n"); + return 0; +} + +static uint64_t handle_ffa_direct_request(uint32_t smc_fid, bool secure_origin, + uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + uint64_t ret; + + /* Determine if we have a 64 or 32 direct request. */ + if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC32) { + ret = FFA_MSG_SEND_DIRECT_RESP_SMC32; + } else if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC64) { + ret = FFA_MSG_SEND_DIRECT_RESP_SMC64; + } else { + panic(); /* Unknown SMC. */ + } + /* + * Handle the incoming request. For testing purposes we echo the + * incoming message. + */ + INFO("Logical Partition: Received Direct Request from %s world!\n", + secure_origin ? "Secure" : "Normal"); + + /* + * Logical SP's must always send a direct response so we can populate + * our response directly. + */ + SMC_RET8(handle, ret, 0, 0, x4, 0, 0, 0, 0); +} + +/* Register logical partition */ +DECLARE_LOGICAL_PARTITION( + my_logical_partition, + sp_init, /* Init Function */ + LP_PARTITION_ID, /* FF-A Partition ID */ + LP_UUID, /* UUID */ + PARTITION_PROPERTIES, /* Partition Properties. */ + handle_ffa_direct_request /* Callback for direct requests. */ +); diff --git a/plat/arm/board/fvp/fvp_err.c b/plat/arm/board/fvp/fvp_err.c new file mode 100644 index 0000000..244659a --- /dev/null +++ b/plat/arm/board/fvp/fvp_err.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <common/debug.h> +#include <drivers/arm/sp805.h> +#include <drivers/cfi/v2m_flash.h> +#include <lib/mmio.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* + * FVP error handler + */ +__dead2 void plat_arm_error_handler(int err) +{ + /* Propagate the err code in the NV-flags register */ + mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err); + + console_flush(); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + for (;;) + wfi(); +} + +void __dead2 plat_arm_system_reset(void) +{ + /* Write the System Configuration Control Register */ + mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, + V2M_CFGCTRL_START | + V2M_CFGCTRL_RW | + V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT)); + wfi(); + ERROR("FVP System Reset: operation not handled.\n"); + panic(); +} diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c new file mode 100644 index 0000000..e780f21 --- /dev/null +++ b/plat/arm/board/fvp/fvp_gicv3.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <platform_def.h> + +#include <common/debug.h> +#include <common/interrupt_props.h> +#include <drivers/arm/gicv3.h> +#include <fconf_hw_config_getter.h> +#include <lib/utils.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/common/fconf_sec_intr_config.h> +#include <plat/common/platform.h> + +#if FVP_GICR_REGION_PROTECTION +/* To indicate GICR region of the core initialized as Read-Write */ +static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false}; +#endif /* FVP_GICR_REGION_PROTECTION */ + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +/* Default GICR base address to be used for GICR probe. */ +static uint64_t fvp_gicr_base_addrs[2] = { 0U }; + +/* List of zero terminated GICR frame addresses which CPUs will probe */ +static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; + +#if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)))) +static const interrupt_prop_t fvp_interrupt_props[] = { + PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) +}; +#endif + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) +{ + u_register_t temp_mpidr = mpidr; + + temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return plat_arm_calc_core_pos(temp_mpidr); +} + + +static gicv3_driver_data_t fvp_gic_data = { + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = fvp_rdistif_base_addrs, + .mpidr_to_core_pos = fvp_gicv3_mpidr_hash +}; + +/****************************************************************************** + * This function gets called per core to make its redistributor frame rw + *****************************************************************************/ +static void fvp_gicv3_make_rdistrif_rw(void) +{ +#if FVP_GICR_REGION_PROTECTION + unsigned int core_pos = plat_my_core_pos(); + + /* Make the redistributor frame RW if it is not done previously */ + if (fvp_gicr_rw_region_init[core_pos] != true) { + int ret = xlat_change_mem_attributes(BASE_GICR_BASE + + (core_pos * BASE_GICR_SIZE), + BASE_GICR_SIZE, + MT_EXECUTE_NEVER | + MT_DEVICE | MT_RW | + MT_SECURE); + + if (ret != 0) { + ERROR("Failed to make redistributor frame \ + read write = %d\n", ret); + panic(); + } else { + fvp_gicr_rw_region_init[core_pos] = true; + } + } +#else + return; +#endif /* FVP_GICR_REGION_PROTECTION */ +} + +void plat_arm_gic_driver_init(void) +{ + fvp_gicv3_make_rdistrif_rw(); + /* + * Get GICD and GICR base addressed through FCONF APIs. + * FCONF is not supported in BL32 for FVP. + */ +#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)) + fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, + gicv3_config, + gicd_base); + fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, + gicr_base); +#if SEC_INT_DESC_IN_FCONF + fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config, + sec_intr_prop, descriptor); + fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config, + sec_intr_prop, count); +#else + fvp_gic_data.interrupt_props = fvp_interrupt_props; + fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); +#endif +#else + fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; + fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; + fvp_gic_data.interrupt_props = fvp_interrupt_props; + fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); +#endif + + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ + +#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)) + gicv3_driver_init(&fvp_gic_data); + if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { + ERROR("No GICR base frame found for Primary CPU\n"); + panic(); + } +#endif +} + +/****************************************************************************** + * Function to iterate over all GICR frames and discover the corresponding + * per-cpu redistributor frame as well as initialize the corresponding + * interface in GICv3. + *****************************************************************************/ +void plat_arm_gic_pcpu_init(void) +{ + int result; + const uint64_t *plat_gicr_frames = fvp_gicr_frames; + + fvp_gicv3_make_rdistrif_rw(); + + do { + result = gicv3_rdistif_probe(*plat_gicr_frames); + + /* If the probe is successful, no need to proceed further */ + if (result == 0) + break; + + plat_gicr_frames++; + } while (*plat_gicr_frames != 0U); + + if (result == -1) { + ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); + panic(); + } + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c new file mode 100644 index 0000000..4eef51c --- /dev/null +++ b/plat/arm/board/fvp/fvp_io_storage.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_semihosting.h> +#include <drivers/io/io_storage.h> +#include <lib/semihosting.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/common_def.h> + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL33_IMAGE_NAME "bl33.bin" +#define TB_FW_CONFIG_NAME "fvp_tb_fw_config.dtb" +#define SOC_FW_CONFIG_NAME "fvp_soc_fw_config.dtb" +#define TOS_FW_CONFIG_NAME "fvp_tsp_fw_config.dtb" +#define NT_FW_CONFIG_NAME "fvp_nt_fw_config.dtb" +#define FW_CONFIG_NAME "fvp_fw_config.dtb" +#define HW_CONFIG_NAME "hw_config.dtb" + +#if TRUSTED_BOARD_BOOT +#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt" +#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt" +#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt" +#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt" +#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt" +#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *sh_dev_con; +static uintptr_t sh_dev_handle; + +static const io_file_spec_t sh_file_spec[] = { + [BL2_IMAGE_ID] = { + .path = BL2_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL31_IMAGE_ID] = { + .path = BL31_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_IMAGE_ID] = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL33_IMAGE_ID] = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [TB_FW_CONFIG_ID] = { + .path = TB_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_CONFIG_ID] = { + .path = SOC_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [TOS_FW_CONFIG_ID] = { + .path = TOS_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [NT_FW_CONFIG_ID] = { + .path = NT_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [FW_CONFIG_ID] = { + .path = FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [HW_CONFIG_ID] = { + .path = HW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + .path = TRUSTED_BOOT_FW_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_KEY_CERT_ID] = { + .path = TRUSTED_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_KEY_CERT_ID] = { + .path = SOC_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + .path = TOS_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + .path = NT_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_CONTENT_CERT_ID] = { + .path = SOC_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + .path = TOS_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + .path = NT_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + + +static int open_semihosting(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if the file exists on semi-hosting.*/ + result = io_dev_init(sh_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(sh_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Semi-hosting IO\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_arm_io_setup(void) +{ + int io_result; + + io_result = arm_io_setup(); + if (io_result < 0) { + panic(); + } + + /* Register the additional IO devices on this platform */ + io_result = register_io_dev_sh(&sh_dev_con); + if (io_result < 0) { + panic(); + } + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle); + if (io_result < 0) { + panic(); + } +} + +/* + * FVP provides semihosting as an alternative to load images + */ +int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); + if (result == 0) { + *dev_handle = sh_dev_handle; + *image_spec = (uintptr_t)&sh_file_spec[image_id]; + } + + return result; +} diff --git a/plat/arm/board/fvp/fvp_plat_attest_token.c b/plat/arm/board/fvp/fvp_plat_attest_token.c new file mode 100644 index 0000000..4dd37a4 --- /dev/null +++ b/plat/arm/board/fvp/fvp_plat_attest_token.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> +#include <stdint.h> +#include <string.h> + +/* Using hardcoded token values for AEM FVP */ +static uint8_t platform_token[] = { + 0xD2, 0x84, 0x40, 0xA0, 0x59, 0x02, 0x46, 0xA9, + 0x19, 0x01, 0x09, 0x78, 0x1C, 0x68, 0x74, 0x74, + 0x70, 0x3A, 0x2F, 0x2F, 0x61, 0x72, 0x6D, 0x2E, + 0x63, 0x6F, 0x6D, 0x2F, 0x43, 0x43, 0x41, 0x2D, + 0x53, 0x53, 0x44, 0x2F, 0x31, 0x2E, 0x30, 0x2E, + 0x30, 0x0A, 0x58, 0x20, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, + 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, 0x14, + 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, 0x1C, + 0x1B, 0x1A, 0x19, 0x18, 0x19, 0x09, 0x5C, 0x58, + 0x40, 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x50, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xA0, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, + 0x00, 0x09, 0x00, 0x40, 0x00, 0x1C, 0x00, 0x1B, + 0x00, 0x19, 0x01, 0x00, 0x58, 0x21, 0x01, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, + 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, + 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x19, + 0x09, 0x61, 0x58, 0x21, 0x01, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, + 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, + 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x19, 0x09, 0x5B, + 0x19, 0x30, 0x03, 0x19, 0x09, 0x62, 0x67, 0x73, + 0x68, 0x61, 0x2D, 0x32, 0x35, 0x36, 0x19, 0x09, + 0x5F, 0x84, 0xA5, 0x01, 0x62, 0x42, 0x4C, 0x05, + 0x58, 0x20, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, + 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, + 0x09, 0x08, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, + 0x19, 0x18, 0x04, 0x65, 0x33, 0x2E, 0x34, 0x2E, + 0x32, 0x02, 0x58, 0x20, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, + 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, 0x14, + 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, 0x1C, + 0x1B, 0x1A, 0x19, 0x18, 0x06, 0x67, 0x73, 0x68, + 0x61, 0x2D, 0x32, 0x35, 0x36, 0xA4, 0x01, 0x62, + 0x4D, 0x31, 0x05, 0x58, 0x20, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, + 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, + 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x04, 0x63, 0x31, + 0x2E, 0x32, 0x02, 0x58, 0x20, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, + 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, + 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0xA4, 0x01, 0x62, + 0x4D, 0x32, 0x05, 0x58, 0x20, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, + 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, + 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x04, 0x65, 0x31, + 0x2E, 0x32, 0x2E, 0x33, 0x02, 0x58, 0x20, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, + 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, + 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0xA4, + 0x01, 0x62, 0x4D, 0x33, 0x05, 0x58, 0x20, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, + 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, + 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x04, + 0x61, 0x31, 0x02, 0x58, 0x20, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, + 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, + 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x19, 0x09, 0x60, + 0x6C, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65, + 0x72, 0x2E, 0x63, 0x6F, 0x6D, 0x58, 0x40, 0x84, + 0x32, 0x12, 0x5B, 0x92, 0x6B, 0x20, 0xD8, 0x14, + 0xC1, 0xC1, 0x8C, 0x3C, 0x73, 0xB8, 0x29, 0x0F, + 0x42, 0xBC, 0x0B, 0x25, 0x87, 0x5C, 0x4F, 0xA4, + 0xFA, 0xD9, 0xDE, 0xC1, 0x2B, 0x20, 0xED, 0xDF, + 0x1C, 0xDD, 0x1A, 0x09, 0xBD, 0xA0, 0x25, 0x48, + 0xC6, 0xBB, 0x99, 0xA1, 0x30, 0x4F, 0x2C, 0xDC, + 0x89, 0xE8, 0xB7, 0xFF, 0x32, 0xE9, 0x3F, 0xBB, + 0xC6, 0xBF, 0x9D, 0x38, 0x68, 0xE1, 0xB2, +}; + +int plat_rmmd_get_cca_attest_token(uintptr_t buf, size_t *len, + uintptr_t hash, size_t hash_size) +{ + (void)hash; + (void)hash_size; + + if (*len < sizeof(platform_token)) { + return -EINVAL; + } + + (void)memcpy((void *)buf, platform_token, sizeof(platform_token)); + *len = sizeof(platform_token); + + return 0; +} diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c new file mode 100644 index 0000000..6b9d618 --- /dev/null +++ b/plat/arm/board/fvp/fvp_pm.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/gicv3.h> +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <lib/extensions/spe.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +#include "fvp_private.h" +#include "../drivers/arm/gic/v3/gicv3_private.h" + + +#if ARM_RECOM_STATE_ID_ENC +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int arm_pm_idle_states[] = { + /* State-id - 0x01 */ + arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET, + ARM_PWR_LVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF, + ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, + ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x222 */ + arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, + ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN), + 0, +}; +#endif + +/******************************************************************************* + * Function which implements the common FVP specific operations to power down a + * cluster in response to a CPU_OFF or CPU_SUSPEND request. + ******************************************************************************/ +static void fvp_cluster_pwrdwn_common(void) +{ + uint64_t mpidr = read_mpidr_el1(); + +#if ENABLE_SPE_FOR_LOWER_ELS + /* + * On power down we need to disable statistical profiling extensions + * before exiting coherency. + */ + spe_disable(); +#endif + + /* Disable coherency if this cluster is to be turned off */ + fvp_interconnect_disable(); + +#if HW_ASSISTED_COHERENCY + uint32_t reg; + + /* + * If we have determined this core to be the last man standing and we + * intend to power down the cluster proactively, we provide a hint to + * the power controller that cluster power is not required when all + * cores are powered down. + * Note that this is only an advisory to power controller and is supported + * by SoCs with DynamIQ Shared Units only. + */ + reg = read_clusterpwrdn(); + + /* Clear and set bit 0 : Cluster power not required */ + reg &= ~DSU_CLUSTER_PWR_MASK; + reg |= DSU_CLUSTER_PWR_OFF; + write_clusterpwrdn(reg); +#endif + + /* Program the power controller to turn the cluster off */ + fvp_pwrc_write_pcoffr(mpidr); +} + +/* + * Empty implementation of these hooks avoid setting the GICR_WAKER.Sleep bit + * on ARM GICv3 implementations on FVP. This is required, because FVP does not + * support SYSTEM_SUSPEND and it is `faked` in firmware. Hence, for wake up + * from `fake` system suspend the GIC must not be powered off. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{} + +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{} + +static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* Get the mpidr for this cpu */ + mpidr = read_mpidr_el1(); + + /* Perform the common cluster specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL1] == + ARM_LOCAL_STATE_OFF) { + /* + * This CPU might have woken up whilst the cluster was + * attempting to power down. In this case the FVP power + * controller will have a pending cluster power off request + * which needs to be cleared by writing to the PPONR register. + * This prevents the power controller from interpreting a + * subsequent entry of this cpu into a simple wfi as a power + * down request. + */ + fvp_pwrc_write_pponr(mpidr); + + /* Enable coherency if this cluster was off */ + fvp_interconnect_enable(); + } + /* Perform the common system specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL2] == + ARM_LOCAL_STATE_OFF) + arm_system_pwr_domain_resume(); + + /* + * Clear PWKUPR.WEN bit to ensure interrupts do not interfere + * with a cpu power down unless the bit is set again + */ + fvp_pwrc_clr_wen(mpidr); +} + +/******************************************************************************* + * FVP handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void fvp_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr = read_scr_el3(); + + assert(cpu_state == ARM_LOCAL_STATE_RET); + + /* + * Enable the Non-secure interrupt to wake the CPU. + * In GICv3 affinity routing mode, the Non-secure Group 1 interrupts + * use Physical FIQ at EL3 whereas in GICv2, Physical IRQ is used. + * Enabling both the bits works for both GICv2 mode and GICv3 affinity + * routing mode. + */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + isb(); + + /* + * Enter standby state. + * dsb is good practice before using wfi to enter low power states. + */ + dsb(); + wfi(); + + /* + * Restore SCR_EL3 to the original value, synchronisation of SCR_EL3 + * is done by eret in el3_exit() to save some execution cycles. + */ + write_scr_el3(scr); +} + +/******************************************************************************* + * FVP handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int fvp_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned int psysr; + + /* + * Ensure that we do not cancel an inflight power off request for the + * target cpu. That would leave it in a zombie wfi. Wait for it to power + * off and then program the power controller to turn that CPU on. + */ + do { + psysr = fvp_pwrc_read_psysr(mpidr); + } while ((psysr & PSYSR_AFF_L0) != 0U); + + fvp_pwrc_write_pponr(mpidr); + return rc; +} + +/******************************************************************************* + * FVP handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void fvp_pwr_domain_off(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* + * If execution reaches this stage then this power domain will be + * suspended. Perform at least the cpu specific actions followed + * by the cluster specific operations if applicable. + */ + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_arm_gic_cpuif_disable(); + + /* Turn redistributor off */ + plat_arm_gic_redistif_off(); + + /* Program the power controller to power off this cpu. */ + fvp_pwrc_write_ppoffr(read_mpidr_el1()); + + if (target_state->pwr_domain_state[ARM_PWR_LVL1] == + ARM_LOCAL_STATE_OFF) + fvp_cluster_pwrdwn_common(); + +} + +/******************************************************************************* + * FVP handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void fvp_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + + /* + * FVP has retention only at cpu level. Just return + * as nothing is to be done for retention. + */ + if (target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_RET) + return; + + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* Get the mpidr for this cpu */ + mpidr = read_mpidr_el1(); + + /* Program the power controller to enable wakeup interrupts. */ + fvp_pwrc_set_wen(mpidr); + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_arm_gic_cpuif_disable(); + + /* + * The Redistributor is not powered off as it can potentially prevent + * wake up events reaching the CPUIF and/or might lead to losing + * register context. + */ + + /* Perform the common cluster specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL1] == + ARM_LOCAL_STATE_OFF) + fvp_cluster_pwrdwn_common(); + + /* Perform the common system specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL2] == + ARM_LOCAL_STATE_OFF) + arm_system_pwr_domain_save(); + + /* Program the power controller to power off this cpu. */ + fvp_pwrc_write_ppoffr(read_mpidr_el1()); +} + +/******************************************************************************* + * FVP handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +static void fvp_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + fvp_power_domain_on_finish_common(target_state); + +} + +/******************************************************************************* + * FVP handler called when a power domain has just been powered on and the cpu + * and its cluster are fully participating in coherent transaction on the + * interconnect. Data cache must be enabled for CPU at this point. + ******************************************************************************/ +static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state) +{ + /* Program GIC per-cpu distributor or re-distributor interface */ + plat_arm_gic_pcpu_init(); + + /* Enable GIC CPU interface */ + plat_arm_gic_cpuif_enable(); +} + +/******************************************************************************* + * FVP handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +static void fvp_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + /* + * Nothing to be done on waking up from retention from CPU level. + */ + if (target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_RET) + return; + + fvp_power_domain_on_finish_common(target_state); + + /* Enable GIC CPU interface */ + plat_arm_gic_cpuif_enable(); +} + +/******************************************************************************* + * FVP handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 fvp_system_off(void) +{ + /* Write the System Configuration Control Register */ + mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, + V2M_CFGCTRL_START | + V2M_CFGCTRL_RW | + V2M_CFGCTRL_FUNC(V2M_FUNC_SHUTDOWN)); + wfi(); + ERROR("FVP System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 fvp_system_reset(void) +{ + /* Write the System Configuration Control Register */ + mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, + V2M_CFGCTRL_START | + V2M_CFGCTRL_RW | + V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT)); + wfi(); + ERROR("FVP System Reset: operation not handled.\n"); + panic(); +} + +static int fvp_node_hw_state(u_register_t target_cpu, + unsigned int power_level) +{ + unsigned int psysr; + int ret; + + /* + * The format of 'power_level' is implementation-defined, but 0 must + * mean a CPU. We also allow 1 to denote the cluster + */ + if ((power_level != ARM_PWR_LVL0) && (power_level != ARM_PWR_LVL1)) + return PSCI_E_INVALID_PARAMS; + + /* + * Read the status of the given MPDIR from FVP power controller. The + * power controller only gives us on/off status, so map that to expected + * return values of the PSCI call + */ + psysr = fvp_pwrc_read_psysr(target_cpu); + if (psysr == PSYSR_INVALID) + return PSCI_E_INVALID_PARAMS; + + if (power_level == ARM_PWR_LVL0) { + ret = ((psysr & PSYSR_AFF_L0) != 0U) ? HW_ON : HW_OFF; + } else { + /* power_level == ARM_PWR_LVL1 */ + ret = ((psysr & PSYSR_AFF_L1) != 0U) ? HW_ON : HW_OFF; + } + + return ret; +} + +/* + * The FVP doesn't truly support power management at SYSTEM power domain. The + * SYSTEM_SUSPEND will be down-graded to the cluster level within the platform + * layer. The `fake` SYSTEM_SUSPEND allows us to validate some of the driver + * save and restore sequences on FVP. + */ +#if !ARM_BL31_IN_DRAM +static void fvp_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF; +} +#endif + +/******************************************************************************* + * Handler to filter PSCI requests. + ******************************************************************************/ +/* + * The system power domain suspend is only supported only via + * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain + * will be downgraded to the lower level. + */ +static int fvp_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int rc; + rc = arm_validate_power_state(power_state, req_state); + + /* + * Ensure that the system power domain level is never suspended + * via PSCI CPU SUSPEND API. Currently system suspend is only + * supported via PSCI SYSTEM SUSPEND API. + */ + req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN; + return rc; +} + +/* + * Custom `translate_power_state_by_mpidr` handler for FVP. Unlike in the + * `fvp_validate_power_state`, we do not downgrade the system power + * domain level request in `power_state` as it will be used to query the + * PSCI_STAT_COUNT/RESIDENCY at the system power domain level. + */ +static int fvp_translate_power_state_by_mpidr(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state) +{ + return arm_validate_power_state(power_state, output_state); +} + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t plat_arm_psci_pm_ops = { + .cpu_standby = fvp_cpu_standby, + .pwr_domain_on = fvp_pwr_domain_on, + .pwr_domain_off = fvp_pwr_domain_off, + .pwr_domain_suspend = fvp_pwr_domain_suspend, + .pwr_domain_on_finish = fvp_pwr_domain_on_finish, + .pwr_domain_on_finish_late = fvp_pwr_domain_on_finish_late, + .pwr_domain_suspend_finish = fvp_pwr_domain_suspend_finish, + .system_off = fvp_system_off, + .system_reset = fvp_system_reset, + .validate_power_state = fvp_validate_power_state, + .validate_ns_entrypoint = arm_validate_psci_entrypoint, + .translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr, + .get_node_hw_state = fvp_node_hw_state, +#if !ARM_BL31_IN_DRAM + /* + * The TrustZone Controller is set up during the warmboot sequence after + * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM + * this is not a problem but, if it is in TZC-secured DRAM, it tries to + * reconfigure the same memory it is running on, causing an exception. + */ + .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, +#endif + .mem_protect_chk = arm_psci_mem_protect_chk, + .read_mem_protect = arm_psci_read_mem_protect, + .write_mem_protect = arm_nor_psci_write_mem_protect, +}; + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return ops; +} diff --git a/plat/arm/board/fvp/fvp_private.h b/plat/arm/board/fvp/fvp_private.h new file mode 100644 index 0000000..3590370 --- /dev/null +++ b/plat/arm/board/fvp/fvp_private.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_PRIVATE_H +#define FVP_PRIVATE_H + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_config_setup(void); + +void fvp_interconnect_init(void); +void fvp_interconnect_enable(void); +void fvp_interconnect_disable(void); +void fvp_timer_init(void); +void tsp_early_platform_setup(void); + +#endif /* FVP_PRIVATE_H */ diff --git a/plat/arm/board/fvp/fvp_realm_attest_key.c b/plat/arm/board/fvp/fvp_realm_attest_key.c new file mode 100644 index 0000000..1af1f0d --- /dev/null +++ b/plat/arm/board/fvp/fvp_realm_attest_key.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <services/rmmd_svc.h> + +static uint8_t sample_attest_priv_key[] = { + 0x20, 0x11, 0xC7, 0xF0, 0x3C, 0xEE, 0x43, 0x25, 0x17, 0x6E, + 0x52, 0x4F, 0x03, 0x3C, 0x0C, 0xE1, 0xE2, 0x1A, 0x76, 0xE6, + 0xC1, 0xA4, 0xF0, 0xB8, 0x39, 0xAA, 0x1D, 0xF6, 0x1E, 0x0E, + 0x8A, 0x5C, 0x8A, 0x05, 0x74, 0x0F, 0x9B, 0x69, 0xEF, 0xA7, + 0xEB, 0x1A, 0x41, 0x85, 0xBD, 0x11, 0x7F, 0x68 +}; + +int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len, + unsigned int type) +{ + assert(type == ATTEST_KEY_CURVE_ECC_SECP384R1); + + if (*len < sizeof(sample_attest_priv_key)) { + return -EINVAL; + } + + (void)memcpy((void *)buf, sample_attest_priv_key, + sizeof(sample_attest_priv_key)); + *len = sizeof(sample_attest_priv_key); + + return 0; +} diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c new file mode 100644 index 0000000..573d92e --- /dev/null +++ b/plat/arm/board/fvp/fvp_security.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The Base FVP has a TrustZone address space controller, the Foundation + * FVP does not. Trying to program the device on the foundation FVP will + * cause an abort. + * + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ + + const arm_tzc_regions_info_t fvp_tzc_regions[] = { + ARM_TZC_REGIONS_DEF, +#if !SPM_MM && !ENABLE_RME + {FVP_DRAM3_BASE, FVP_DRAM3_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, + {FVP_DRAM4_BASE, FVP_DRAM4_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, + {FVP_DRAM5_BASE, FVP_DRAM5_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, + {FVP_DRAM6_BASE, FVP_DRAM6_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, +#endif + {0} + }; + + if ((get_arm_config()->flags & ARM_CONFIG_HAS_TZC) != 0U) + arm_tzc400_setup(PLAT_ARM_TZC_BASE, fvp_tzc_regions); +} diff --git a/plat/arm/board/fvp/fvp_stack_protector.c b/plat/arm/board/fvp/fvp_stack_protector.c new file mode 100644 index 0000000..e940a12 --- /dev/null +++ b/plat/arm/board/fvp/fvp_stack_protector.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include <plat/common/platform.h> + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. As the + * FVP does not have any random number generator, this is better than + * nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c new file mode 100644 index 0000000..80cfbd5 --- /dev/null +++ b/plat/arm/board/fvp/fvp_topology.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <fconf_hw_config_getter.h> +#include <lib/cassert.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#include <platform_def.h> + +/* The FVP power domain tree descriptor */ +static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2]; + + +CASSERT(((FVP_CLUSTER_COUNT > 0) && (FVP_CLUSTER_COUNT <= 256)), + assert_invalid_fvp_cluster_count); + +/******************************************************************************* + * This function dynamically constructs the topology according to cpu-map node + * in HW_CONFIG dtb and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + uint32_t cluster_count, cpus_per_cluster; + + /* + * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and + * BL2_AT_EL3 systems. + */ +#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3 + cluster_count = FVP_CLUSTER_COUNT; + cpus_per_cluster = FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU; +#else + cluster_count = FCONF_GET_PROPERTY(hw_config, topology, plat_cluster_count); + cpus_per_cluster = FCONF_GET_PROPERTY(hw_config, topology, cluster_cpu_count); + /* Several FVP Models use the same blanket dts. Ex: FVP_Base_Cortex-A65x4 + * and FVP_Base_Cortex-A65AEx8 both use same dts but have different number of + * CPUs in the cluster, as reflected by build flags FVP_MAX_CPUS_PER_CLUSTER. + * Take the minimum of two to ensure PSCI functions do not exceed the size of + * the PSCI data structures allocated at build time. + */ + cpus_per_cluster = MIN(cpus_per_cluster, + (uint32_t)(FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU)); + +#endif + + assert(cluster_count > 0U); + assert(cpus_per_cluster > 0U); + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + fvp_power_domain_tree_desc[0] = 1; + fvp_power_domain_tree_desc[1] = (unsigned char)cluster_count; + + for (i = 0; i < cluster_count; i++) + fvp_power_domain_tree_desc[i + 2] = (unsigned char)cpus_per_cluster; + + return fvp_power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return FVP_MAX_CPUS_PER_CLUSTER; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int clus_id, cpu_id, thread_id; + + /* Validate affinity fields */ + if ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) { + thread_id = MPIDR_AFFLVL0_VAL(mpidr); + cpu_id = MPIDR_AFFLVL1_VAL(mpidr); + clus_id = MPIDR_AFFLVL2_VAL(mpidr); + } else { + thread_id = 0; + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + clus_id = MPIDR_AFFLVL1_VAL(mpidr); + } + + if (clus_id >= FVP_CLUSTER_COUNT) + return -1; + if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER) + return -1; + if (thread_id >= FVP_MAX_PE_PER_CPU) + return -1; + + if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID) + return -1; + + /* + * Core position calculation for FVP platform depends on the MT bit in + * MPIDR. This function cannot assume that the supplied MPIDR has the MT + * bit set even if the implementation has. For example, PSCI clients + * might supply MPIDR values without the MT bit set. Therefore, we + * inject the current PE's MT bit so as to get the calculation correct. + * This of course assumes that none or all CPUs on the platform has MT + * bit set. + */ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return (int) plat_arm_calc_core_pos(mpidr); +} diff --git a/plat/arm/board/fvp/fvp_trusted_boot.c b/plat/arm/board/fvp/fvp_trusted_boot.c new file mode 100644 index 0000000..1ea37f7 --- /dev/null +++ b/plat/arm/board/fvp/fvp_trusted_boot.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#include <lib/mmio.h> +#include <lib/fconf/fconf.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/common/fconf_nv_cntr_getter.h> +#include <plat/common/platform.h> +#include <platform_def.h> +#include <tools_share/tbbr_oid.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + +/* + * Store a new non-volatile counter value. + * + * On some FVP versions, the non-volatile counters are read-only so this + * function will always fail. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + uintptr_t nv_ctr_addr; + + assert(cookie != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + NON_TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + mmio_write_32(nv_ctr_addr, nv_ctr); + + /* + * If the FVP models a locked counter then its value cannot be updated + * and the above write operation has been silently ignored. + */ + return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1; +} diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h new file mode 100644 index 0000000..ca85f7a --- /dev/null +++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_HW_CONFIG_GETTER_H +#define FCONF_HW_CONFIG_GETTER_H + +#include <lib/fconf/fconf.h> + +/* Hardware Config related getter */ +#define hw_config__gicv3_config_getter(prop) gicv3_config.prop +#define hw_config__topology_getter(prop) soc_topology.prop +#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop +#define hw_config__cpu_timer_getter(prop) cpu_timer.prop + +struct gicv3_config_t { + uint64_t gicd_base; + uint64_t gicr_base; +}; + +struct hw_topology_t { + uint32_t plat_cluster_count; + uint32_t cluster_cpu_count; + uint32_t plat_cpu_count; + uint32_t plat_max_pwr_level; +}; + +struct uart_serial_config_t { + uint64_t uart_base; + uint32_t uart_clk; +}; + +struct cpu_timer_t { + uint32_t clock_freq; +}; + +int fconf_populate_gicv3_config(uintptr_t config); +int fconf_populate_topology(uintptr_t config); +int fconf_populate_uart_config(uintptr_t config); +int fconf_populate_cpu_timer(uintptr_t config); + +extern struct gicv3_config_t gicv3_config; +extern struct hw_topology_t soc_topology; +extern struct uart_serial_config_t uart_serial_config; +extern struct cpu_timer_t cpu_timer; +#endif /* FCONF_HW_CONFIG_GETTER_H */ diff --git a/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/plat/arm/board/fvp/include/fconf_nt_config_getter.h new file mode 100644 index 0000000..0824c35 --- /dev/null +++ b/plat/arm/board/fvp/include/fconf_nt_config_getter.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_NT_CONFIG_GETTER_H +#define FCONF_NT_CONFIG_GETTER_H + +#include <lib/fconf/fconf.h> + +/* NT Firmware Config related getter */ +#define nt_config__event_log_config_getter(prop) event_log.prop + +struct event_log_config_t { +#ifdef SPD_opteed + void *tpm_event_log_sm_addr; +#endif + void *tpm_event_log_addr; + size_t tpm_event_log_size; +}; + +int fconf_populate_event_log_config(uintptr_t config); + +extern struct event_log_config_t event_log_config; + +#endif /* FCONF_NT_CONFIG_GETTER_H */ diff --git a/plat/arm/board/fvp/include/fvp_critical_data.h b/plat/arm/board/fvp/include/fvp_critical_data.h new file mode 100644 index 0000000..04bd5b2 --- /dev/null +++ b/plat/arm/board/fvp/include/fvp_critical_data.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef FVP_CRITICAL_DATA_H +#define FVP_CRITICAL_DATA_H + +#include <common/nv_cntr_ids.h> +#include <lib/utils_def.h> +#include <plat/common/platform.h> + +#define EVLOG_CRITICAL_DATA_STRING "CRITICAL DATA" + +#define CRITICAL_DATA_ID CRITICAL_DATA_ID_BASE + +struct fvp_critical_data { + + /* platform NV counters */ + unsigned int nv_ctr[MAX_NV_CTR_IDS]; +}; + +#endif /* FVP_CRITICAL_DATA_H */ diff --git a/plat/arm/board/fvp/include/plat.ld.S b/plat/arm/board/fvp/include/plat.ld.S new file mode 100644 index 0000000..7c8bf06 --- /dev/null +++ b/plat/arm/board/fvp/include/plat.ld.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_LD_S +#define PLAT_LD_S + +#include <plat/arm/common/arm_tzc_dram.ld.S> + +#if RECLAIM_INIT_CODE +#include <plat/arm/common/arm_reclaim_init.ld.S> +#endif /* RECLAIM_INIT_CODE */ + +#endif /* PLAT_LD_S */ diff --git a/plat/arm/board/fvp/include/plat_macros.S b/plat/arm/board/fvp/include/plat_macros.S new file mode 100644 index 0000000..57f5924 --- /dev/null +++ b/plat/arm/board/fvp/include/plat_macros.S @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <arm_macros.S> +#include <platform_def.h> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* + * Detect if we're using the base memory map or + * the legacy VE memory map + */ + mov_imm x0, (V2M_SYSREGS_BASE + V2M_SYS_ID) + ldr w16, [x0] + /* Extract BLD (12th - 15th bits) from the SYS_ID */ + ubfx x16, x16, #V2M_SYS_ID_BLD_SHIFT, #4 + /* Check if VE mmap */ + cmp w16, #BLD_GIC_VE_MMAP + b.eq use_ve_mmap + /* Assume Base Cortex mmap */ + mov_imm x17, BASE_GICC_BASE + mov_imm x16, BASE_GICD_BASE + b print_gic_regs +use_ve_mmap: + mov_imm x17, VE_GICC_BASE + mov_imm x16, VE_GICD_BASE +print_gic_regs: + arm_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h new file mode 100644 index 0000000..1ef6c87 --- /dev/null +++ b/plat/arm/board/fvp/include/platform_def.h @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <drivers/arm/tzc400.h> +#include <lib/utils_def.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_def.h> +#include <plat/arm/common/arm_spm_def.h> +#include <plat/common/common_def.h> + +#include "../fvp_def.h" + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT (U(FVP_CLUSTER_COUNT) * \ + U(FVP_MAX_CPUS_PER_CLUSTER) * \ + U(FVP_MAX_PE_PER_CPU)) + +#define PLAT_NUM_PWR_DOMAINS (U(FVP_CLUSTER_COUNT) + \ + PLATFORM_CORE_COUNT + U(1)) + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT U(FVP_CLUSTER_COUNT) + +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x00000000) +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */ + +#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x06000000) +#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */ + +#if ENABLE_RME +#define PLAT_ARM_RMM_BASE (RMM_BASE) +#define PLAT_ARM_RMM_SIZE (RMM_LIMIT - RMM_BASE) +#endif + +/* + * Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to + * max size of BL32 image. + */ +#if defined(SPD_spmd) +#define PLAT_ARM_SPMC_BASE PLAT_ARM_TRUSTED_DRAM_BASE +#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */ +#endif + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* No SCP in FVP */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0) + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) /* 36-bit range */ +#define PLAT_ARM_DRAM2_SIZE ULL(0x780000000) /* 30 GB */ + +#define FVP_DRAM3_BASE ULL(0x8800000000) /* 40-bit range */ +#define FVP_DRAM3_SIZE ULL(0x7800000000) /* 480 GB */ +#define FVP_DRAM3_END (FVP_DRAM3_BASE + FVP_DRAM3_SIZE - 1U) + +#define FVP_DRAM4_BASE ULL(0x88000000000) /* 44-bit range */ +#define FVP_DRAM4_SIZE ULL(0x78000000000) /* 7.5 TB */ +#define FVP_DRAM4_END (FVP_DRAM4_BASE + FVP_DRAM4_SIZE - 1U) + +#define FVP_DRAM5_BASE ULL(0x880000000000) /* 48-bit range */ +#define FVP_DRAM5_SIZE ULL(0x780000000000) /* 120 TB */ +#define FVP_DRAM5_END (FVP_DRAM5_BASE + FVP_DRAM5_SIZE - 1U) + +#define FVP_DRAM6_BASE ULL(0x8800000000000) /* 52-bit range */ +#define FVP_DRAM6_SIZE ULL(0x7800000000000) /* 1920 TB */ +#define FVP_DRAM6_END (FVP_DRAM6_BASE + FVP_DRAM6_SIZE - 1U) + +/* Range of kernel DTB load address */ +#define FVP_DTB_DRAM_MAP_START ULL(0x82000000) +#define FVP_DTB_DRAM_MAP_SIZE ULL(0x02000000) /* 32 MB */ + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + FVP_DTB_DRAM_MAP_START, \ + FVP_DTB_DRAM_MAP_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +#if SPMC_AT_EL3 +/* + * Number of Secure Partitions supported. + * SPMC at EL3, uses this count to configure the maximum number of supported + * secure partitions. + */ +#define SECURE_PARTITION_COUNT 1 + +/* + * Number of Normal World Partitions supported. + * SPMC at EL3, uses this count to configure the maximum number of supported + * NWd partitions. + */ +#define NS_PARTITION_COUNT 1 + +/* + * Number of Logical Partitions supported. + * SPMC at EL3, uses this count to configure the maximum number of supported + * logical partitions. + */ +#define MAX_EL3_LP_DESCS_COUNT 1 + +#endif /* SPMC_AT_EL3 */ + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + UL(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL31) +# if SPM_MM +# define PLAT_ARM_MMAP_ENTRIES 10 +# define MAX_XLAT_TABLES 9 +# define PLAT_SP_IMAGE_MMAP_REGIONS 30 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 +# elif SPMC_AT_EL3 +# define PLAT_ARM_MMAP_ENTRIES 13 +# define MAX_XLAT_TABLES 11 +# else +# define PLAT_ARM_MMAP_ENTRIES 9 +# if USE_DEBUGFS +# if ENABLE_RME +# define MAX_XLAT_TABLES 9 +# else +# define MAX_XLAT_TABLES 8 +# endif +# else +# if ENABLE_RME +# define MAX_XLAT_TABLES 8 +# elif DRTM_SUPPORT +# define MAX_XLAT_TABLES 8 +# else +# define MAX_XLAT_TABLES 7 +# endif +# endif +# endif +#elif defined(IMAGE_BL32) +# if SPMC_AT_EL3 +# define PLAT_ARM_MMAP_ENTRIES 270 +# define MAX_XLAT_TABLES 10 +# else +# define PLAT_ARM_MMAP_ENTRIES 9 +# define MAX_XLAT_TABLES 6 +# endif +#elif !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0x5000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT && COT_DESC_IN_DTB +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#elif CRYPTO_SUPPORT +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#elif ARM_BL31_IN_DRAM +/* When ARM_BL31_IN_DRAM is set, BL2 can use almost all of Trusted SRAM. */ +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1F000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#endif + +#if RESET_TO_BL31 +/* Size of Trusted SRAM - the first 4KB of shared memory - GPT L0 Tables */ +#define PLAT_ARM_MAX_BL31_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE - \ + ARM_L0_GPT_SIZE) +#else +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE (UL(0x3D000) - ARM_L0_GPT_SIZE) +#endif /* RESET_TO_BL31 */ + +#ifndef __aarch64__ +#if RESET_TO_SP_MIN +/* Size of Trusted SRAM - the first 4KB of shared memory */ +#define PLAT_ARM_MAX_BL32_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE) +#else +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +# define PLAT_ARM_MAX_BL32_SIZE UL(0x3B000) +#endif /* RESET_TO_SP_MIN */ +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if CRYPTO_SUPPORT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x500) +# endif /* CRYPTO_SUPPORT */ +#elif defined(IMAGE_BL2) +# if CRYPTO_SUPPORT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x600) +# endif /* CRYPTO_SUPPORT */ +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE UL(0x400) +#elif defined(IMAGE_BL31) +# if DRTM_SUPPORT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x800) +# endif /* DRTM_SUPPORT */ +#elif defined(IMAGE_BL32) +# if SPMC_AT_EL3 +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x440) +# endif /* SPMC_AT_EL3 */ +#elif defined(IMAGE_RMM) +# define PLATFORM_STACK_SIZE UL(0x440) +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* Reserve the last block of flash for PSCI MEM PROTECT flag */ +#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH0_BASE +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#if ARM_GPT_SUPPORT +/* + * Offset of the FIP in the GPT image. BL1 component uses this option + * as it does not load the partition table to get the FIP base + * address. At sector 34 by default (i.e. after reserved sectors 0-33) + * Offset = 34 * 512(sector size) = 17408 i.e. 0x4400 + */ +#define PLAT_ARM_FIP_OFFSET_IN_GPT 0x4400 +#endif /* ARM_GPT_SUPPORT */ + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE +#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ + +#define PLAT_ARM_TRP_UART_BASE V2M_IOFPGA_UART3_BASE +#define PLAT_ARM_TRP_UART_CLK_IN_HZ V2M_IOFPGA_UART3_CLK_IN_HZ + +#define PLAT_FVP_SMMUV3_BASE UL(0x2b400000) +#define PLAT_ARM_SMMUV3_ROOT_REG_OFFSET UL(0x20000) + +/* CCI related constants */ +#define PLAT_FVP_CCI400_BASE UL(0x2c090000) +#define PLAT_FVP_CCI400_CLUS0_SL_PORT 3 +#define PLAT_FVP_CCI400_CLUS1_SL_PORT 4 + +/* CCI-500/CCI-550 on Base platform */ +#define PLAT_FVP_CCI5XX_BASE UL(0x2a000000) +#define PLAT_FVP_CCI5XX_CLUS0_SL_PORT 5 +#define PLAT_FVP_CCI5XX_CLUS1_SL_PORT 6 + +/* CCN related constants. Only CCN 502 is currently supported */ +#define PLAT_ARM_CCN_BASE UL(0x2e000000) +#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP 1, 5, 7, 11 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* Mailbox base address */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE + + +/* TrustZone controller related constants + * + * Currently only filters 0 and 2 are connected on Base FVP. + * Filter 0 : CPU clusters (no access to DRAM by default) + * Filter 1 : not connected + * Filter 2 : LCDs (access to VRAM allowed by default) + * Filter 3 : not connected + * Programming unconnected filters will have no effect at the + * moment. These filter could, however, be connected in future. + * So care should be taken not to configure the unused filters. + * + * Allow only non-secure access to all DRAM to supported devices. + * Give access to the CPUs and Virtio. Some devices + * would normally use the default ID so allow that too. + */ +#define PLAT_ARM_TZC_BASE UL(0x2a4a0000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD)) + +/* + * GIC related constants to cater for both GICv2 and GICv3 instances of an + * FVP. They could be overridden at runtime in case the FVP implements the + * legacy VE memory map. + */ +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICR_BASE BASE_GICR_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(FVP_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(FVP_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#if SDEI_IN_FCONF +#define PLAT_SDEI_DP_EVENT_MAX_CNT ARM_SDEI_DP_EVENT_MAX_CNT +#define PLAT_SDEI_DS_EVENT_MAX_CNT ARM_SDEI_DS_EVENT_MAX_CNT +#else +#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS +#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS +#endif + +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) + +#define PLAT_SP_PRI PLAT_RAS_PRI + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* + * Maximum size of Event Log buffer used in Measured Boot Event Log driver + */ +#define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x400) + +/* + * Maximum size of Event Log buffer used for DRTM + */ +#define PLAT_DRTM_EVENT_LOG_MAX_SIZE UL(0x300) + +/* + * Number of MMAP entries used by DRTM implementation + */ +#define PLAT_DRTM_MMAP_ENTRIES PLAT_ARM_MMAP_ENTRIES + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i new file mode 100644 index 0000000..85e6e3a --- /dev/null +++ b/plat/arm/board/fvp/jmptbl.i @@ -0,0 +1,63 @@ +# +# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Platform specific romlib functions can be added or included here. +# The index in the output file will be generated cumulatively in the same +# order as it is given in this file. +# Output file can be found at: $BUILD_DIR/jmptbl.i +# +# Format: +# lib function [patch] +# Example: +# rom rom_lib_init +# fdt fdt_getprop_namelen patch + +rom rom_lib_init +fdt fdt_getprop +fdt fdt_get_property +fdt fdt_getprop_namelen +fdt fdt_setprop_inplace +fdt fdt_check_header +fdt fdt_node_offset_by_compatible +fdt fdt_setprop_inplace_namelen_partial +fdt fdt_first_subnode +fdt fdt_next_subnode +fdt fdt_path_offset +fdt fdt_path_offset_namelen +fdt fdt_subnode_offset +fdt fdt_address_cells +fdt fdt_size_cells +fdt fdt_parent_offset +fdt fdt_stringlist_search +fdt fdt_get_alias_namelen +fdt fdt_get_name +fdt fdt_get_alias +fdt fdt_node_offset_by_phandle +fdt fdt_subnode_offset +fdt fdt_add_subnode +mbedtls mbedtls_asn1_get_alg +mbedtls mbedtls_asn1_get_alg_null +mbedtls mbedtls_asn1_get_bitstring_null +mbedtls mbedtls_asn1_get_bool +mbedtls mbedtls_asn1_get_int +mbedtls mbedtls_asn1_get_tag +mbedtls mbedtls_free +mbedtls mbedtls_md +mbedtls mbedtls_md_get_size +mbedtls mbedtls_memory_buffer_alloc_init +mbedtls mbedtls_oid_get_md_alg +mbedtls mbedtls_oid_get_numeric_string +mbedtls mbedtls_oid_get_pk_alg +mbedtls mbedtls_oid_get_sig_alg +mbedtls mbedtls_pk_free +mbedtls mbedtls_pk_init +mbedtls mbedtls_pk_parse_subpubkey +mbedtls mbedtls_pk_verify_ext +mbedtls mbedtls_platform_set_snprintf +mbedtls mbedtls_x509_get_rsassa_pss_params +mbedtls mbedtls_x509_get_sig_alg +mbedtls mbedtls_md_info_from_type +c exit +c atexit diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk new file mode 100644 index 0000000..51ba035 --- /dev/null +++ b/plat/arm/board/fvp/platform.mk @@ -0,0 +1,464 @@ +# +# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# Use the GICv3 driver on the FVP by default +FVP_USE_GIC_DRIVER := FVP_GICV3 + +# Default cluster count for FVP +FVP_CLUSTER_COUNT := 2 + +# Default number of CPUs per cluster on FVP +FVP_MAX_CPUS_PER_CLUSTER := 4 + +# Default number of threads per CPU on FVP +FVP_MAX_PE_PER_CPU := 1 + +# Disable redistributor frame of inactive/fused CPU cores by marking it as read +# only; enable redistributor frames of all CPU cores by default. +FVP_GICR_REGION_PROTECTION := 0 + +FVP_DT_PREFIX := fvp-base-gicv3-psci + +# The FVP platform depends on this macro to build with correct GIC driver. +$(eval $(call add_define,FVP_USE_GIC_DRIVER)) + +# Pass FVP_CLUSTER_COUNT to the build system. +$(eval $(call add_define,FVP_CLUSTER_COUNT)) + +# Pass FVP_MAX_CPUS_PER_CLUSTER to the build system. +$(eval $(call add_define,FVP_MAX_CPUS_PER_CLUSTER)) + +# Pass FVP_MAX_PE_PER_CPU to the build system. +$(eval $(call add_define,FVP_MAX_PE_PER_CPU)) + +# Pass FVP_GICR_REGION_PROTECTION to the build system. +$(eval $(call add_define,FVP_GICR_REGION_PROTECTION)) + +# Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2, +# choose the CCI driver , else the CCN driver +ifeq ($(FVP_CLUSTER_COUNT), 0) +$(error "Incorrect cluster count specified for FVP port") +else ifeq ($(FVP_CLUSTER_COUNT),$(filter $(FVP_CLUSTER_COUNT),1 2)) +FVP_INTERCONNECT_DRIVER := FVP_CCI +else +FVP_INTERCONNECT_DRIVER := FVP_CCN +endif + +$(eval $(call add_define,FVP_INTERCONNECT_DRIVER)) + +# Choose the GIC sources depending upon the how the FVP will be invoked +ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3) + +# The GIC model (GIC-600 or GIC-500) will be detected at runtime +GICV3_SUPPORT_GIC600 := 1 +GICV3_OVERRIDE_DISTIF_PWR_OPS := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +FVP_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + + ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31} ${RESET_TO_SP_MIN}),) + FVP_GIC_SOURCES += plat/arm/board/fvp/fvp_gicv3.c + endif + +else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2) + +# No GICv4 extension +GIC_ENABLE_V4_EXTN := 0 +$(eval $(call add_define,GIC_ENABLE_V4_EXTN)) + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +FVP_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +FVP_DT_PREFIX := fvp-base-gicv2-psci +else +$(error "Incorrect GIC driver chosen on FVP port") +endif + +ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCI) +FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c +else ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCN) +FVP_INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \ + plat/arm/common/arm_ccn.c +else +$(error "Incorrect CCN driver chosen on FVP port") +endif + +FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \ + plat/arm/board/fvp/fvp_security.c \ + plat/arm/common/arm_tzc400.c + + +PLAT_INCLUDES := -Iplat/arm/board/fvp/include + + +PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp/fvp_common.c + +FVP_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +ifeq (${ARCH}, aarch64) + +# select a different set of CPU files, depending on whether we compile for +# hardware assisted coherency cores or not +ifeq (${HW_ASSISTED_COHERENCY}, 0) +# Cores used without DSU + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S +else +# Cores used with DSU only + ifeq (${CTX_INCLUDE_AARCH32_REGS}, 0) + # AArch64-only cores + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \ + lib/cpus/aarch64/cortex_a76ae.S \ + lib/cpus/aarch64/cortex_a77.S \ + lib/cpus/aarch64/cortex_a78.S \ + lib/cpus/aarch64/neoverse_n_common.S \ + lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_e1.S \ + lib/cpus/aarch64/neoverse_v1.S \ + lib/cpus/aarch64/neoverse_v2.S \ + lib/cpus/aarch64/cortex_a78_ae.S \ + lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_a715.S \ + lib/cpus/aarch64/cortex_x3.S \ + lib/cpus/aarch64/cortex_a65.S \ + lib/cpus/aarch64/cortex_a65ae.S \ + lib/cpus/aarch64/cortex_a78c.S \ + lib/cpus/aarch64/cortex_hayes.S \ + lib/cpus/aarch64/cortex_hunter.S \ + lib/cpus/aarch64/cortex_hunter_elp_arm.S \ + lib/cpus/aarch64/cortex_x2.S \ + lib/cpus/aarch64/neoverse_poseidon.S + endif + # AArch64/AArch32 cores + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S +endif + +else +FVP_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S +endif + +BL1_SOURCES += drivers/arm/smmu/smmu_v3.c \ + drivers/arm/sp805/sp805.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_semihosting.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/board/fvp/${ARCH}/fvp_helpers.S \ + plat/arm/board/fvp/fvp_bl1_setup.c \ + plat/arm/board/fvp/fvp_err.c \ + plat/arm/board/fvp/fvp_io_storage.c \ + ${FVP_CPU_LIBS} \ + ${FVP_INTERCONNECT_SOURCES} + +ifeq (${USE_SP804_TIMER},1) +BL1_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +else +BL1_SOURCES += drivers/delay_timer/generic_delay_timer.c +endif + + +BL2_SOURCES += drivers/arm/sp805/sp805.c \ + drivers/io/io_semihosting.c \ + lib/utils/mem_region.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/board/fvp/fvp_bl2_setup.c \ + plat/arm/board/fvp/fvp_err.c \ + plat/arm/board/fvp/fvp_io_storage.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${FVP_SECURITY_SOURCES} + + +ifeq (${COT_DESC_IN_DTB},1) +BL2_SOURCES += plat/arm/common/fconf/fconf_nv_cntr_getter.c +endif + +ifeq (${ENABLE_RME},1) +BL2_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S +BL31_SOURCES += plat/arm/board/fvp/fvp_plat_attest_token.c \ + plat/arm/board/fvp/fvp_realm_attest_key.c +endif + +ifeq (${BL2_AT_EL3},1) +BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \ + plat/arm/board/fvp/fvp_bl2_el3_setup.c \ + ${FVP_CPU_LIBS} \ + ${FVP_INTERCONNECT_SOURCES} +endif + +ifeq (${USE_SP804_TIMER},1) +BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \ + ${FVP_SECURITY_SOURCES} + +ifeq (${USE_SP804_TIMER},1) +BL2U_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +BL31_SOURCES += drivers/arm/fvp/fvp_pwrc.c \ + drivers/arm/smmu/smmu_v3.c \ + drivers/delay_timer/delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp/fvp_bl31_setup.c \ + plat/arm/board/fvp/fvp_console.c \ + plat/arm/board/fvp/fvp_pm.c \ + plat/arm/board/fvp/fvp_topology.c \ + plat/arm/board/fvp/aarch64/fvp_helpers.S \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${FVP_CPU_LIBS} \ + ${FVP_GIC_SOURCES} \ + ${FVP_INTERCONNECT_SOURCES} \ + ${FVP_SECURITY_SOURCES} + +# Support for fconf in BL31 +# Added separately from the above list for better readability +ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),) +BL31_SOURCES += lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + plat/arm/board/fvp/fconf/fconf_hw_config_getter.c + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${SEC_INT_DESC_IN_FCONF},1) +BL31_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c +endif + +endif + +ifeq (${USE_SP804_TIMER},1) +BL31_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +else +BL31_SOURCES += drivers/delay_timer/generic_delay_timer.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK +FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts +FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \ + ${PLAT}_fw_config.dts \ + ${PLAT}_tb_fw_config.dts \ + ${PLAT}_soc_fw_config.dts \ + ${PLAT}_nt_fw_config.dts \ + ) + +FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb +FVP_SOC_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb +FVP_NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +ifeq (${SPD},tspd) +FDT_SOURCES += plat/arm/board/fvp/fdts/${PLAT}_tsp_fw_config.dts +FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tsp_fw_config.dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config,${FVP_TOS_FW_CONFIG})) +endif + +ifeq (${SPD},spmd) + +ifeq ($(ARM_SPMC_MANIFEST_DTS),) +ARM_SPMC_MANIFEST_DTS := plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts +endif + +FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS} +FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config,${FVP_TOS_FW_CONFIG})) +endif + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config,${FVP_FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CONFIG})) +# Add the SOC_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_SOC_FW_CONFIG},--soc-fw-config,${FVP_SOC_FW_CONFIG})) +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_NT_FW_CONFIG},--nt-fw-config,${FVP_NT_FW_CONFIG})) + +FDT_SOURCES += ${FVP_HW_CONFIG_DTS} +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS))) + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG})) +endif + +# Enable Activity Monitor Unit extensions by default +ENABLE_AMU := 1 + +# Enable dynamic mitigation support by default +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 + +ifeq (${ENABLE_AMU},1) +BL31_SOURCES += lib/cpus/aarch64/cpuamu.c \ + lib/cpus/aarch64/cpuamu_helpers.S + +ifeq (${HW_ASSISTED_COHERENCY}, 1) +BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ + lib/cpus/aarch64/neoverse_n1_pubsub.c +endif +endif + +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c +endif + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c +endif + +ifeq (${ARCH},aarch32) + NEED_BL32 := yes +endif + +# Enable the dynamic translation tables library. +ifeq ($(filter 1,${BL2_AT_EL3} ${ARM_XLAT_TABLES_LIB_V1}),) + ifeq (${ARCH},aarch32) + BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + else # AArch64 + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +endif + +ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + ifeq (${ARCH},aarch32) + BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + else # AArch64 + BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + ifeq (${SPD},tspd) + BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + endif + endif +endif + +ifeq (${USE_DEBUGFS},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC +endif + +# Add support for platform supplied linker script for BL31 build +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +ifneq (${BL2_AT_EL3}, 0) + override BL1_SOURCES = +endif + +# Include Measured Boot makefile before any Crypto library makefile. +# Crypto library makefile may need default definitions of Measured Boot build +# flags present in Measured Boot makefile. +ifeq (${MEASURED_BOOT},1) + RSS_MEASURED_BOOT_MK := drivers/measured_boot/rss/rss_measured_boot.mk + $(info Including ${RSS_MEASURED_BOOT_MK}) + include ${RSS_MEASURED_BOOT_MK} + + ifneq (${MBOOT_RSS_HASH_ALG}, sha256) + $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512)) + endif + + BL1_SOURCES += ${MEASURED_BOOT_SOURCES} + BL2_SOURCES += ${MEASURED_BOOT_SOURCES} +endif + +include plat/arm/board/common/board_common.mk +include plat/arm/common/arm_common.mk + +ifeq (${MEASURED_BOOT},1) +BL1_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \ + plat/arm/board/fvp/fvp_bl1_measured_boot.c \ + lib/psa/measured_boot.c + +BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \ + plat/arm/board/fvp/fvp_bl2_measured_boot.c \ + lib/psa/measured_boot.c + +# Note that attestation code does not depend on measured boot interfaces per se, +# but the two features go together - attestation without boot measurements is +# pretty much pointless... +BL31_SOURCES += lib/psa/delegated_attestation.c + +PLAT_INCLUDES += -Iinclude/lib/psa + +# RSS is not supported on FVP right now. Thus, we use the mocked version +# of the provided PSA APIs. They return with success and hard-coded data. +PLAT_RSS_NOT_SUPPORTED := 1 + +# Even though RSS is not supported on FVP (see above), we support overriding +# PLAT_RSS_NOT_SUPPORTED from the command line, just for the purpose of building +# the code to detect any build regressions. The resulting firmware will not be +# functional. +ifneq (${PLAT_RSS_NOT_SUPPORTED},1) + $(warning "RSS is not supported on FVP. The firmware will not be functional.") + include drivers/arm/rss/rss_comms.mk + BL1_SOURCES += ${RSS_COMMS_SOURCES} + BL2_SOURCES += ${RSS_COMMS_SOURCES} + BL31_SOURCES += ${RSS_COMMS_SOURCES} \ + lib/psa/delegated_attestation.c + + BL1_CFLAGS += -DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0 + BL2_CFLAGS += -DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0 + BL31_CFLAGS += -DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0 +endif + +endif + +ifeq (${DRTM_SUPPORT}, 1) +BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_addr.c \ + plat/arm/board/fvp/fvp_drtm_dma_prot.c \ + plat/arm/board/fvp/fvp_drtm_err.c \ + plat/arm/board/fvp/fvp_drtm_measurement.c \ + plat/arm/board/fvp/fvp_drtm_stub.c \ + plat/arm/common/arm_dyn_cfg.c \ + plat/arm/board/fvp/fvp_err.c +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c +BL2_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c + +# FVP being a development platform, enable capability to disable Authentication +# dynamically if TRUSTED_BOARD_BOOT is set. +DYN_DISABLE_AUTH := 1 +endif + +# enable trace buffer control registers access to NS by default +ENABLE_TRBE_FOR_NS := 1 + +# enable branch record buffer control registers access in NS by default +# only enable for aarch64 +# do not enable when ENABLE_RME=1 +ifeq (${ARCH}, aarch64) +ifeq (${ENABLE_RME},0) + ENABLE_BRBE_FOR_NS := 1 +endif +endif + +# enable trace system registers access to NS by default +ENABLE_SYS_REG_TRACE_FOR_NS := 1 + +# enable trace filter control registers access to NS by default +ENABLE_TRF_FOR_NS := 1 + +ifeq (${SPMC_AT_EL3}, 1) +PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_el3_spmc.c +endif diff --git a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c new file mode 100644 index 0000000..9ab36a6 --- /dev/null +++ b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <bl32/sp_min/platform_sp_min.h> +#include <common/debug.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> +#include <plat/arm/common/plat_arm.h> + +#include "../fvp_private.h" + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + const struct dyn_cfg_dtb_info_t *tos_fw_config_info __unused; + + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + +#if !RESET_TO_SP_MIN && !BL2_AT_EL3 + + INFO("SP_MIN FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); + + tos_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TOS_FW_CONFIG_ID); + if (tos_fw_config_info != NULL) { + arg1 = tos_fw_config_info->config_addr; + } +#endif /* !RESET_TO_SP_MIN && !BL2_AT_EL3 */ + + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize the correct interconnect for this cluster during cold + * boot. No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * FVP PSCI code will enable coherency for other clusters. + */ + fvp_interconnect_enable(); +} + +void sp_min_plat_arch_setup(void) +{ + int rc __unused; + const struct dyn_cfg_dtb_info_t *hw_config_info __unused; + uintptr_t hw_config_base_align __unused; + size_t mapped_size_align __unused; + + arm_sp_min_plat_arch_setup(); + + /* + * For RESET_TO_SP_MIN systems, SP_MIN(BL32) is the first bootloader + * to run. So there is no BL2 to load the HW_CONFIG dtb into memory + * before control is passed to SP_MIN. + * Also, BL2 skips loading HW_CONFIG dtb for BL2_AT_EL3 builds. + * The code below relies on dynamic mapping capability, which is not + * supported by xlat tables lib V1. + * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support + * gets deprecated. + */ +#if !RESET_TO_SP_MIN && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + assert(hw_config_info->config_addr != 0UL); + + INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", + (void *)hw_config_info->config_addr); + + /* + * Preferrably we expect this address and size are page aligned, + * but if they are not then align it. + */ + hw_config_base_align = page_align(hw_config_info->config_addr, DOWN); + mapped_size_align = page_align(hw_config_info->config_max_size, UP); + + if ((hw_config_info->config_addr != hw_config_base_align) && + (hw_config_info->config_max_size == mapped_size_align)) { + mapped_size_align += PAGE_SIZE; + } + + /* + * map dynamically HW config region with its aligned base address and + * size + */ + rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align, + hw_config_base_align, + mapped_size_align, + MT_RO_DATA); + if (rc != 0) { + ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc); + panic(); + } + + /* Populate HW_CONFIG device tree with the mapped address */ + fconf_populate("HW_CONFIG", hw_config_info->config_addr); + + /* unmap the HW_CONFIG memory region */ + rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align); + if (rc != 0) { + ERROR("Error while unmapping HW_CONFIG device tree (%d).\n", + rc); + panic(); + } +#endif /* !RESET_TO_SP_MIN && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 */ +} diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk new file mode 100644 index 0000000..183d802 --- /dev/null +++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk @@ -0,0 +1,39 @@ +# +# Copyright (c) 2016-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp/aarch32/fvp_helpers.S \ + plat/arm/board/fvp/fvp_pm.c \ + plat/arm/board/fvp/fvp_console.c \ + plat/arm/board/fvp/fvp_topology.c \ + plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${FVP_CPU_LIBS} \ + ${FVP_GIC_SOURCES} \ + ${FVP_INTERCONNECT_SOURCES} \ + ${FVP_SECURITY_SOURCES} + +# Support for fconf in SP_MIN(BL32) +# Added separately from the above list for better readability +ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),) +BL32_SOURCES += lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + plat/arm/board/fvp/fconf/fconf_hw_config_getter.c \ + +BL32_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${SEC_INT_DESC_IN_FCONF},1) +BL32_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c +endif + +endif + +include plat/arm/common/sp_min/arm_sp_min.mk diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk new file mode 100644 index 0000000..a450541 --- /dev/null +++ b/plat/arm/board/fvp/trp/trp-fvp.mk @@ -0,0 +1,12 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# TRP source files specific to FVP platform + +RMM_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S + +include plat/arm/common/trp/arm_trp.mk + diff --git a/plat/arm/board/fvp/tsp/fvp_tsp_setup.c b/plat/arm/board/fvp/tsp/fvp_tsp_setup.c new file mode 100644 index 0000000..3c8a963 --- /dev/null +++ b/plat/arm/board/fvp/tsp/fvp_tsp_setup.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +#include "../fvp_private.h" + +void tsp_early_platform_setup(void) +{ + arm_tsp_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} diff --git a/plat/arm/board/fvp/tsp/tsp-fvp.mk b/plat/arm/board/fvp/tsp/tsp-fvp.mk new file mode 100644 index 0000000..ab3f225 --- /dev/null +++ b/plat/arm/board/fvp/tsp/tsp-fvp.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# TSP source files specific to FVP platform +BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \ + plat/arm/board/fvp/aarch64/fvp_helpers.S \ + plat/arm/board/fvp/fvp_topology.c \ + plat/arm/board/fvp/tsp/fvp_tsp_setup.c \ + ${FVP_GIC_SOURCES} + +include plat/arm/common/tsp/arm_tsp.mk diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c new file mode 100644 index 0000000..ae6af6c --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../../../../bl1/bl1_private.h" +#include <arch.h> + +#include <fvp_r_arch_helpers.h> + +/******************************************************************************* + * Function that does the first bit of architectural setup that affects + * execution in the non-secure address space. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + /* v8-R64 does not include SCRs. */ +} + +/******************************************************************************* + * Set the Secure EL1 required architectural state + ******************************************************************************/ +void bl1_arch_next_el_setup(void) +{ + u_register_t next_sctlr; + + /* Use the same endianness than the current BL */ + next_sctlr = (read_sctlr_el2() & SCTLR_EE_BIT); + + /* Set SCTLR Secure EL1 */ + next_sctlr |= SCTLR_EL1_RES1; + + write_sctlr_el1(next_sctlr); +} diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S new file mode 100644 index 0000000..15f4c43 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/bl_common.h> +#include <el2_common_macros.S> +#include <lib/xlat_mpu/xlat_mpu.h> + + .globl bl1_entrypoint + .globl bl1_run_next_image + + + /* ----------------------------------------------------- + * bl1_entrypoint() is the entry point into the trusted + * firmware code when a cpu is released from warm or + * cold reset. + * ----------------------------------------------------- + */ + +func bl1_entrypoint + /* --------------------------------------------------------------------- + * If the reset address is programmable then bl1_entrypoint() is + * executed only on the cold boot path. Therefore, we can skip the warm + * boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + el2_entrypoint_common \ + _init_sctlr=1 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=bl1_exceptions \ + _pie_fixup_size=0 + + /* -------------------------------------------------------------------- + * Perform BL1 setup + * -------------------------------------------------------------------- + */ + bl bl1_setup + + /* -------------------------------------------------------------------- + * Initialize platform and jump to our c-entry point + * for this type of reset. + * -------------------------------------------------------------------- + */ + bl bl1_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl1_entrypoint + +func bl1_run_next_image + mov x20,x0 + + /* --------------------------------------------- + * MPU needs to be disabled because both BL1 and BL33 execute + * in EL2, and therefore share the same address space. + * BL33 will initialize the address space according to its + * own requirement. + * --------------------------------------------- + */ + bl disable_mpu_icache_el2 + + /* --------------------------------------------- + * Wipe clean and disable all MPU regions. This function expects + * that the MPU has already been turned off, and caching concerns + * addressed, but it also explicitly turns off the MPU. + * --------------------------------------------- + */ + bl clear_all_mpu_regions + + /* -------------------------------------------------- + * Do the transition to next boot image. + * -------------------------------------------------- + */ + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el2, x0 + msr spsr_el2, x1 + + ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)] + ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)] + ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)] + ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)] + exception_return +endfunc bl1_run_next_image diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S new file mode 100644 index 0000000..43c2e01 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <bl1/bl1.h> +#include <common/bl_common.h> +#include <context.h> + +/* ----------------------------------------------------------------------------- + * File contains an EL2 equivalent of the EL3 vector table from: + * .../bl1/aarch64/bl1_exceptions.S + * ----------------------------------------------------------------------------- + */ + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL1. + * ----------------------------------------------------------------------------- + */ + .globl bl1_exceptions + +vector_base bl1_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0 + mov x0, #SYNC_EXCEPTION_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionSP0 + +vector_entry IrqSP0 + mov x0, #IRQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSP0 + +vector_entry FiqSP0 + mov x0, #FIQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSP0 + +vector_entry SErrorSP0 + mov x0, #SERROR_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx + mov x0, #SYNC_EXCEPTION_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionSPx + +vector_entry IrqSPx + mov x0, #IRQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSPx + +vector_entry FiqSPx + mov x0, #FIQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSPx + +vector_entry SErrorSPx + mov x0, #SERROR_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64 + /* The current v8-R64 implementation does not support conduit calls */ + b el2_panic +end_vector_entry SynchronousExceptionA64 + +vector_entry IrqA64 + mov x0, #IRQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA64 + +vector_entry FiqA64 + mov x0, #FIQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA64 + +vector_entry SErrorA64 + mov x0, #SERROR_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA64 + + +unexpected_sync_exception: + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/plat/arm/board/fvp_r/fvp_r_bl1_main.c new file mode 100644 index 0000000..841a176 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_bl1_main.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include "../../../../bl1/bl1_private.h" +#include <arch.h> +#include <arch_features.h> +#include <arch_helpers.h> +#include <bl1/bl1.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/auth/auth_mod.h> +#include <drivers/console.h> +#include <lib/cpus/errata_report.h> +#include <lib/utils.h> +#include <smccc_helpers.h> +#include <tools_share/uuid.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#include <platform_def.h> + + +void cm_prepare_el2_exit(void); + +void bl1_run_next_image(const struct entry_point_info *bl_ep_info); + +/******************************************************************************* + * Function to perform late architectural and platform specific initialization. + * It also queries the platform to load and run next BL image. Only called + * by the primary cpu after a cold boot. + ******************************************************************************/ +void bl1_transfer_bl33(void) +{ + unsigned int image_id; + + /* Get the image id of next image to load and run. */ + image_id = bl1_plat_get_next_image_id(); + +#if !ARM_DISABLE_TRUSTED_WDOG + /* Disable watchdog before leaving BL1 */ + plat_arm_secure_wdt_stop(); +#endif + + bl1_run_next_image(&bl1_plat_get_image_desc(image_id)->ep_info); +} + +/******************************************************************************* + * This function locates and loads the BL33 raw binary image in the trusted SRAM. + * Called by the primary cpu after a cold boot. + * TODO: Add support for alternative image load mechanism e.g using virtio/elf + * loader etc. + ******************************************************************************/ +void bl1_load_bl33(void) +{ + image_desc_t *desc; + image_info_t *info; + int err; + + /* Get the image descriptor */ + desc = bl1_plat_get_image_desc(BL33_IMAGE_ID); + assert(desc != NULL); + + /* Get the image info */ + info = &desc->image_info; + INFO("BL1: Loading BL33\n"); + + err = bl1_plat_handle_pre_image_load(BL33_IMAGE_ID); + if (err != 0) { + ERROR("Failure in pre image load handling of BL33 (%d)\n", err); + plat_error_handler(err); + } + + err = load_auth_image(BL33_IMAGE_ID, info); + if (err != 0) { + ERROR("Failed to load BL33 firmware.\n"); + plat_error_handler(err); + } + + /* Allow platform to handle image information. */ + err = bl1_plat_handle_post_image_load(BL33_IMAGE_ID); + if (err != 0) { + ERROR("Failure in post image load handling of BL33 (%d)\n", err); + plat_error_handler(err); + } + + NOTICE("BL1: Booting BL33\n"); +} + +/******************************************************************************* + * Helper utility to calculate the BL2 memory layout taking into consideration + * the BL1 RW data assuming that it is at the top of the memory layout. + ******************************************************************************/ +void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, + meminfo_t *bl2_mem_layout) +{ + assert(bl1_mem_layout != NULL); + assert(bl2_mem_layout != NULL); + + /* + * Remove BL1 RW data from the scope of memory visible to BL2. + * This is assuming BL1 RW data is at the top of bl1_mem_layout. + */ + assert(bl1_mem_layout->total_base < BL1_RW_BASE); + bl2_mem_layout->total_base = bl1_mem_layout->total_base; + bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base; + + flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t)); +} + +/******************************************************************************* + * This function prepares for entry to BL33 + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + unsigned int mode = MODE_EL1; + image_desc_t *desc; + entry_point_info_t *next_bl_ep; + +#if CTX_INCLUDE_AARCH32_REGS + /* + * Ensure that the build flag to save AArch32 system registers in CPU + * context is not set for AArch64-only platforms. + */ + if (el_implemented(1) == EL_IMPL_A64ONLY) { + ERROR("EL1 supports AArch64-only. Please set build flag %s", + "CTX_INCLUDE_AARCH32_REGS = 0\n"); + panic(); + } +#endif + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + assert(desc != NULL); + + /* Get the entry point info. */ + next_bl_ep = &desc->ep_info; + + /* FVP-R is only secure */ + assert(GET_SECURITY_STATE(next_bl_ep->h.attr) == SECURE); + + /* Prepare the SPSR for the next BL image. */ + next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode, + (uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare context for the next EL */ + cm_prepare_el2_exit(); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} + +/******************************************************************************* + * Setup function for BL1. + ******************************************************************************/ +void bl1_setup(void) +{ + /* Perform early platform-specific setup */ + bl1_early_platform_setup(); + + /* Perform late platform-specific setup */ + bl1_plat_arch_setup(); +} + +/******************************************************************************* + * Function to perform late architectural and platform specific initialization. + * It also queries the platform to load and run next BL image. Only called + * by the primary cpu after a cold boot. + ******************************************************************************/ +void bl1_main(void) +{ + unsigned int image_id; + + /* Announce our arrival */ + NOTICE(FIRMWARE_WELCOME_STR); + NOTICE("BL1: %s\n", version_string); + NOTICE("BL1: %s\n", build_message); + + INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT); + + print_errata_status(); + +#if ENABLE_ASSERTIONS + u_register_t val; + /* + * Ensure that MMU/Caches and coherency are turned on + */ + val = read_sctlr_el2(); + + assert((val & SCTLR_M_BIT) != 0U); + assert((val & SCTLR_C_BIT) != 0U); + assert((val & SCTLR_I_BIT) != 0U); + /* + * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the + * provided platform value + */ + val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK; + /* + * If CWG is zero, then no CWG information is available but we can + * at least check the platform value is less than the architectural + * maximum. + */ + if (val != 0) { + assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE); + } else { + assert(MAX_CACHE_LINE_SIZE >= CACHE_WRITEBACK_GRANULE); + } +#endif /* ENABLE_ASSERTIONS */ + + /* Perform remaining generic architectural setup from ELmax */ + bl1_arch_setup(); + +#if TRUSTED_BOARD_BOOT + /* Initialize authentication module */ + auth_mod_init(); +#endif /* TRUSTED_BOARD_BOOT */ + + /* Perform platform setup in BL1. */ + bl1_platform_setup(); + + /* Get the image id of next image to load and run. */ + image_id = bl1_plat_get_next_image_id(); + + /* + * We currently interpret any image id other than + * BL2_IMAGE_ID as the start of firmware update. + */ + if (image_id == BL33_IMAGE_ID) { + bl1_load_bl33(); + } else { + NOTICE("BL1-FWU: *******FWU Process Started*******\n"); + } + + bl1_prepare_next_image(image_id); + + console_flush(); + + bl1_transfer_bl33(); +} + +/******************************************************************************* + * Function called just before handing over to the next BL to inform the user + * about the boot progress. In debug mode, also print details about the BL + * image's execution context. + ******************************************************************************/ +void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info) +{ + NOTICE("BL1: Booting BL31\n"); + print_entry_point_info(bl_ep_info); +} + +#if SPIN_ON_BL1_EXIT +void print_debug_loop_message(void) +{ + NOTICE("BL1: Debug loop, spinning forever\n"); + NOTICE("BL1: Please connect the debugger to continue\n"); +} +#endif + diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c new file mode 100644 index 0000000..1ac0a9c --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Use the xlat_tables_v2 data structures: */ +#define XLAT_TABLES_LIB_V2 1 + +#include <assert.h> + +#include <bl1/bl1.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/arm/sp805.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> +#include <lib/xlat_mpu/xlat_mpu.h> + +#include "fvp_r_private.h" +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/arm_def.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#define MAP_BL1_TOTAL MAP_REGION_FLAT( \ + bl1_tzram_layout.total_base, \ + bl1_tzram_layout.total_size, \ + MT_MEMORY | MT_RW | MT_SECURE) +/* + * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section + * otherwise one region is defined containing both + */ +#if SEPARATE_CODE_AND_RODATA +#define MAP_BL1_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL1_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL1_RO_DATA_BASE, \ + BL1_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) +#else +#define MAP_BL1_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL1_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) +#endif + +/* Data structure which holds the extents of the trusted SRAM for BL1*/ +static meminfo_t bl1_tzram_layout; + +struct meminfo *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +void arm_bl1_early_platform_setup(void) +{ + +#if !ARM_DISABLE_TRUSTED_WDOG + /* Enable watchdog */ + plat_arm_secure_wdt_start(); +#endif + + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = ARM_BL_RAM_BASE; + bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE; +} + +/* Boolean variable to hold condition whether firmware update needed or not */ +static bool is_fwu_needed; + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} + +void arm_bl1_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_BL1_TOTAL, + MAP_BL1_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif +#if ARM_CRYPTOCELL_INTEG + ARM_MAP_BL_COHERENT_RAM, +#endif + /* DRAM1_region: */ + MAP_REGION_FLAT( \ + PLAT_ARM_DRAM1_BASE, \ + PLAT_ARM_DRAM1_SIZE, \ + MT_MEMORY | MT_SECURE | MT_EXECUTE \ + | MT_RW | MT_NON_CACHEABLE), + /* NULL terminator: */ + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + enable_mpu_el2(0); + + arm_setup_romlib(); +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} + +/* + * Perform the platform specific architecture setup shared between + * ARM standard platforms. + */ +void arm_bl1_platform_setup(void) +{ + uint32_t fw_config_max_size; + + /* Initialise the IO layer and register platform IO devices */ + plat_arm_io_setup(); + + /* Check if we need FWU before further processing */ + is_fwu_needed = plat_arm_bl1_fwu_needed(); + if (is_fwu_needed) { + ERROR("Skip platform setup as FWU detected\n"); + return; + } + + /* Set global DTB info for fixed fw_config information */ + fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE; + set_config_info(ARM_FW_CONFIG_BASE, ~0UL, fw_config_max_size, + FW_CONFIG_ID); + + assert(bl1_plat_get_image_desc(BL33_IMAGE_ID) != NULL); + + /* + * Allow access to the System counter timer module and program + * counter frequency for non secure images during FWU + */ +#ifdef ARM_SYS_TIMCTL_BASE + arm_configure_sys_timer(); +#endif +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) + write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); +} + +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) { + wfi(); + } +} + +unsigned int bl1_plat_get_next_image_id(void) +{ + return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL33_IMAGE_ID; +} + +/* + * Returns BL33 image details. + */ +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id) +{ + static image_desc_t bl33_img_desc = BL33_IMAGE_DESC; + + return &bl33_img_desc; +} + +/* + * This function populates the default arguments to BL33. + * The BL33 memory layout structure is allocated and the + * calculated layout is populated in arg1 to BL33. + */ +int bl1_plat_handle_post_image_load(unsigned int image_id) +{ + meminfo_t *bl33_secram_layout; + meminfo_t *bl1_secram_layout; + image_desc_t *image_desc; + entry_point_info_t *ep_info; + + if (image_id != BL33_IMAGE_ID) { + return 0; + } + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL33_IMAGE_ID); + assert(image_desc != NULL); + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; + + /* Find out how much free trusted ram remains after BL1 load */ + bl1_secram_layout = bl1_plat_sec_mem_layout(); + + /* + * Create a new layout of memory for BL33 as seen by BL1 i.e. + * tell it the amount of total and free memory available. + * This layout is created at the first free address visible + * to BL33. BL33 will read the memory layout before using its + * memory for other purposes. + */ + bl33_secram_layout = (meminfo_t *) bl1_secram_layout->total_base; + + bl1_calc_bl2_mem_layout(bl1_secram_layout, bl33_secram_layout); + + ep_info->args.arg1 = (uintptr_t)bl33_secram_layout; + + VERBOSE("BL1: BL3 memory layout address = %p\n", + (void *) bl33_secram_layout); + return 0; +} diff --git a/plat/arm/board/fvp_r/fvp_r_common.c b/plat/arm/board/fvp_r/fvp_r_common.c new file mode 100644 index 0000000..edcf658 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_common.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */ +#define XLAT_TABLES_LIB_V2 1 + +#include <assert.h> +#include <common/debug.h> + +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/sp804_delay_timer.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <lib/smccc.h> +#include <lib/xlat_tables/xlat_tables_compat.h> +#include <services/arm_arch_svc.h> + +#include "fvp_r_private.h" +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + + +/* Defines for GIC Driver build time selection */ +#define FVP_R_GICV3 2 + +/******************************************************************************* + * arm_config holds the characteristics of the differences between the FVP_R + * platforms. It will be populated during cold boot at each boot stage by the + * primary before enabling the MPU (to allow interconnect configuration) & + * used thereafter. Each BL will have its own copy to allow independent + * operation. + ******************************************************************************/ +arm_config_t arm_config; + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Need to be mapped with write permissions in order to set a new non-volatile + * counter value. + */ +#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ + DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of memory regions for various BL stages to map using the MPU. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. + * + * The flash needs to be mapped as writable in order to erase the FIP's Table of + * Contents in case of unrecoverable error (see plat_error_handler()). + */ +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, + V2M_MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, +#if TRUSTED_BOARD_BOOT + /* To access the Root of Trust Public Key registers. */ + MAP_DEVICE2, +#endif + {0} +}; +#endif + +ARM_CASSERT_MMAP + +static const int fvp_cci400_map[] = { + PLAT_FVP_R_CCI400_CLUS0_SL_PORT, + PLAT_FVP_R_CCI400_CLUS1_SL_PORT, +}; + +static const int fvp_cci5xx_map[] = { + PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT, + PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT, +}; + +static unsigned int get_interconnect_master(void) +{ + unsigned int master; + u_register_t mpidr; + + mpidr = read_mpidr_el1(); + master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ? + MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); + + assert(master < FVP_R_CLUSTER_COUNT); + return master; +} + +/******************************************************************************* + * Initialize the platform config for future decision making + ******************************************************************************/ +void __init fvp_config_setup(void) +{ + unsigned int rev, hbi, bld, arch, sys_id; + + arm_config.flags |= ARM_CONFIG_BASE_MMAP; + sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID); + rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK; + hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK; + bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK; + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL) { + ERROR("This firmware is for FVP_R models\n"); + panic(); + } + + /* + * The build field in the SYS_ID tells which variant of the GIC + * memory is implemented by the model. + */ + switch (bld) { + case BLD_GIC_VE_MMAP: + ERROR("Legacy Versatile Express memory map for GIC %s", + "peripheral is not supported\n"); + panic(); + break; + case BLD_GIC_A53A57_MMAP: + break; + default: + ERROR("Unsupported board build %x\n", bld); + panic(); + } + + /* + * The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010 + * for the Foundation FVP_R. + */ + switch (hbi) { + case HBI_FOUNDATION_FVP_R: + arm_config.flags = 0; + + /* + * Check for supported revisions of Foundation FVP_R + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_FOUNDATION_FVP_R_V2_0: + case REV_FOUNDATION_FVP_R_V2_1: + case REV_FOUNDATION_FVP_R_v9_1: + case REV_FOUNDATION_FVP_R_v9_6: + break; + default: + WARN("Unrecognized Foundation FVP_R revision %x\n", rev); + break; + } + break; + case HBI_BASE_FVP_R: + arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); + + /* + * Check for supported revisions + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_BASE_FVP_R_V0: + arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; + break; + default: + WARN("Unrecognized Base FVP_R revision %x\n", rev); + break; + } + break; + default: + ERROR("Unsupported board HBI number 0x%x\n", hbi); + panic(); + } + + /* + * We assume that the presence of MT bit, and therefore shifted + * affinities, is uniform across the platform: either all CPUs, or no + * CPUs implement it. + */ + if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) { + arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF; + } +} + + +void __init fvp_interconnect_init(void) +{ + uintptr_t cci_base = 0U; + const int *cci_map = NULL; + unsigned int map_size = 0U; + + /* Initialize the right interconnect */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) { + cci_base = PLAT_FVP_R_CCI5XX_BASE; + cci_map = fvp_cci5xx_map; + map_size = ARRAY_SIZE(fvp_cci5xx_map); + } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) { + cci_base = PLAT_FVP_R_CCI400_BASE; + cci_map = fvp_cci400_map; + map_size = ARRAY_SIZE(fvp_cci400_map); + } else { + return; + } + + assert(cci_base != 0U); + assert(cci_map != NULL); + cci_init(cci_base, cci_map, map_size); +} + +void fvp_interconnect_enable(void) +{ + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_enable_snoop_dvm_reqs(master); + } +} + +void fvp_interconnect_disable(void) +{ + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_disable_snoop_dvm_reqs(master); + } +} + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void fvp_timer_init(void) +{ +#if USE_SP804_TIMER + /* Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35MHz) clock will be used. + */ + mmio_write_32(V2M_SP810_BASE, FVP_R_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); + + /* Enable System level generic timer */ + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); +#endif /* USE_SP804_TIMER */ +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + return (int32_t) + ((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT) + | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT) + | FVP_R_SOC_ID); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + unsigned int sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) & + V2M_SYS_ID_REV_MASK); +} diff --git a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c new file mode 100644 index 0000000..d172d2d --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> + +/************************************************************ + * For R-class everything is in secure world. + * Prepare the CPU system registers for first entry into EL1 + ************************************************************/ +void cm_prepare_el2_exit(void) +{ + uint64_t hcr_el2 = 0U; + + /* + * The use of ARMv8.3 pointer authentication (PAuth) is governed + * by fields in HCR_EL2, which trigger a 'trap to EL2' if not + * enabled. This register initialized at boot up, update PAuth + * bits. + * + * HCR_API_BIT: Set to one to disable traps to EL2 if lower ELs + * access PAuth registers + * + * HCR_APK_BIT: Set to one to disable traps to EL2 if lower ELs + * access PAuth instructions + */ + hcr_el2 = read_hcr_el2(); + write_hcr_el2(hcr_el2 | HCR_API_BIT | HCR_APK_BIT); + + /* + * Initialise CNTHCTL_EL2. All fields are architecturally UNKNOWN + * on reset and are set to zero except for field(s) listed below. + * + * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to EL2 + * if lower ELs accesses to the physical timer registers. + * + * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to EL2 + * if lower ELs access to the physical counter registers. + */ + write_cnthctl_el2(CNTHCTL_RESET_VAL | EL1PCEN_BIT | EL1PCTEN_BIT); + + /* + * On Armv8-R, the EL1&0 memory system architecture is configurable + * as a VMSA or PMSA. All the fields architecturally UNKNOWN on reset + * and are set to zero except for field listed below. + * + * VCTR_EL2.MSA: Set to one to ensure the VMSA is enabled so that + * rich OS can boot. + */ + write_vtcr_el2(VTCR_RESET_VAL | VTCR_EL2_MSA); +} diff --git a/plat/arm/board/fvp_r/fvp_r_debug.S b/plat/arm/board/fvp_r/fvp_r_debug.S new file mode 100644 index 0000000..88f0a29 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_debug.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/debug.h> + + .globl el2_panic + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + +/* + * el2_panic will be redefined by the + * crash reporting mechanism (if enabled) + */ +el2_panic: + mov x6, x30 + bl plat_crash_console_init + + /* Check if the console is initialized */ + cbz x0, _panic_handler + + /* The console is initialized */ + adr x4, panic_msg + bl asm_print_str + mov x4, x6 + + /* The panic location is lr -4 */ + sub x4, x4, #4 + bl asm_print_hex + + bl plat_crash_console_flush + +_panic_handler: + /* Pass to plat_panic_handler the address from where el2_panic was + * called, not the address of the call from el2_panic. + */ + mov x30, x6 + b plat_panic_handler diff --git a/plat/arm/board/fvp_r/fvp_r_def.h b/plat/arm/board/fvp_r/fvp_r_def.h new file mode 100644 index 0000000..eda39cf --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_def.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_DEF_H +#define FVP_R_DEF_H + +#include <lib/utils_def.h> + +/****************************************************************************** + * FVP-R topology constants + *****************************************************************************/ +#define FVP_R_CLUSTER_COUNT 2 +#define FVP_R_MAX_CPUS_PER_CLUSTER 4 +#define FVP_R_MAX_PE_PER_CPU 1 +#define FVP_R_PRIMARY_CPU 0x0 + +/****************************************************************************** + * Definition of platform soc id + *****************************************************************************/ +#define FVP_R_SOC_ID 0 + +/******************************************************************************* + * FVP_R memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE UL(0x8c000000) +#define FLASH1_SIZE UL(0x04000000) + +#define PSRAM_BASE UL(0x94000000) +#define PSRAM_SIZE UL(0x04000000) + +#define VRAM_BASE UL(0x98000000) +#define VRAM_SIZE UL(0x02000000) + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE UL(0xa0000000) +#define DEVICE0_SIZE UL(0x0c200000) + +/* + * In case of FVP_R models with CCN, the CCN register space overlaps into + * the NSRAM area. + */ +#define DEVICE1_BASE UL(0xae000000) +#define DEVICE1_SIZE UL(0x1A00000) + +#define NSRAM_BASE UL(0xae000000) +#define NSRAM_SIZE UL(0x10000) +/* Devices in the second GB */ +#define DEVICE2_BASE UL(0xffe00000) +#define DEVICE2_SIZE UL(0x00200000) + +#define PCIE_EXP_BASE UL(0xc0000000) +#define TZRNG_BASE UL(0x7fe60000) + +/* Non-volatile counters */ +#define TRUSTED_NVCTR_BASE UL(0xffe70000) +#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000)) +#define TFW_NVCTR_SIZE UL(4) +#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004)) +#define NTFW_CTR_SIZE UL(4) + +/* Keys */ +#define SOC_KEYS_BASE UL(0xffe80000) +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000)) +#define TZ_PUB_KEY_HASH_SIZE UL(32) +#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020)) +#define HU_KEY_SIZE UL(16) +#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044)) +#define END_KEY_SIZE UL(32) + +/* Constants to distinguish FVP_R type */ +#define HBI_BASE_FVP_R U(0x020) +#define REV_BASE_FVP_R_V0 U(0x0) +#define REV_BASE_FVP_R_REVC U(0x2) + +#define HBI_FOUNDATION_FVP_R U(0x010) +#define REV_FOUNDATION_FVP_R_V2_0 U(0x0) +#define REV_FOUNDATION_FVP_R_V2_1 U(0x1) +#define REV_FOUNDATION_FVP_R_v9_1 U(0x2) +#define REV_FOUNDATION_FVP_R_v9_6 U(0x3) + +#define BLD_GIC_VE_MMAP U(0x0) +#define BLD_GIC_A53A57_MMAP U(0x1) + +#define ARCH_MODEL U(0x1) + +/* FVP_R Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP_R SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP_R specific flags */ +#define FVP_R_SP810_CTRL_TIM0_OV BIT_32(16) +#define FVP_R_SP810_CTRL_TIM1_OV BIT_32(18) +#define FVP_R_SP810_CTRL_TIM2_OV BIT_32(20) +#define FVP_R_SP810_CTRL_TIM3_OV BIT_32(22) + +#endif /* FVP_R_DEF_H */ diff --git a/plat/arm/board/fvp_r/fvp_r_err.c b/plat/arm/board/fvp_r/fvp_r_err.c new file mode 100644 index 0000000..7ee752b --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_err.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <common/debug.h> +#include <drivers/arm/sp805.h> +#include <drivers/cfi/v2m_flash.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* + * FVP_R error handler + */ +__dead2 void plat_arm_error_handler(int err) +{ + int ret; + + switch (err) { + case -ENOENT: + case -EAUTH: + /* Image load or authentication error. Erase the ToC */ + INFO("Erasing FIP ToC from flash...\n"); + (void)nor_unlock(PLAT_ARM_FLASH_IMAGE_BASE); + ret = nor_word_program(PLAT_ARM_FLASH_IMAGE_BASE, 0); + if (ret != 0) { + ERROR("Cannot erase ToC\n"); + } else { + INFO("Done\n"); + } + break; + default: + /* Unexpected error */ + break; + } + + (void)console_flush(); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/fvp_r/fvp_r_helpers.S b/plat/arm/board/fvp_r/fvp_r_helpers.S new file mode 100644 index 0000000..ba85777 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_helpers.S @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/gicv3.h> + +#include <platform_def.h> + + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* --------------------------------------------- + * Power down this cpu. + * TODO: Do we need to worry about powering the + * cluster down as well here? That will need + * locks which we won't have unless an elf- + * loader zeroes out the zi section. + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + mov_imm x1, PWRC_BASE + str w0, [x1, #PPOFFR_OFF] + + /* --------------------------------------------- + * There is no sane reason to come out of this + * wfi so panic if we do. This cpu will be pow- + * ered on and reset by the cpu_on pm api + * --------------------------------------------- + */ + dsb sy + wfi + no_ret plat_panic_handler +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP_R, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + mrs x2, mpidr_el1 + mov_imm x1, PWRC_BASE + str w2, [x1, #PSYSR_OFF] + ldr w2, [x1, #PSYSR_OFF] + ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp w2, #WKUP_PPONR + beq warm_reset + cmp w2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov x0, #0 + ret + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + cbz x0, _panic_handler + ret + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic_handler: + no_ret plat_panic_handler +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FVP_R_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/plat/arm/board/fvp_r/fvp_r_io_storage.c b/plat/arm/board/fvp_r/fvp_r_io_storage.c new file mode 100644 index 0000000..3b44828 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_io_storage.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_semihosting.h> +#include <drivers/io/io_storage.h> +#include <lib/semihosting.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/common_def.h> + +/* Semihosting filenames */ +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt" +#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *sh_dev_con; +static uintptr_t sh_dev_handle; + +static const io_file_spec_t sh_file_spec[] = { + [BL33_IMAGE_ID] = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + .path = TRUSTED_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + .path = NT_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + .path = NT_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + + +static int open_semihosting(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if the file exists on semi-hosting.*/ + result = io_dev_init(sh_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(sh_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Semi-hosting IO\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_arm_io_setup(void) +{ + int io_result; + + io_result = arm_io_setup(); + if (io_result < 0) { + panic(); + } + + /* Register the additional IO devices on this platform */ + io_result = register_io_dev_sh(&sh_dev_con); + if (io_result < 0) { + panic(); + } + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle); + if (io_result < 0) { + panic(); + } +} + +/* + * FVP_R provides semihosting as an alternative to load images + */ +int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); + + if (result == 0) { + *dev_handle = sh_dev_handle; + *image_spec = (uintptr_t)&sh_file_spec[image_id]; + } + + return result; +} diff --git a/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S new file mode 100644 index 0000000..67ad164 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> + + .globl disable_mpu_el2 + .globl disable_mpu_icache_el2 + +/* --------------------------------------------------------------------------- + * Disable the MPU at EL2. + * --------------------------------------------------------------------------- + */ + +func disable_mpu_el2 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mpu_el2: + mrs x0, sctlr_el2 + bic x0, x0, x1 + msr sctlr_el2, x0 + isb /* ensure MMU is off */ + dsb sy + ret +endfunc disable_mpu_el2 + + +func disable_mpu_icache_el2 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mpu_el2 +endfunc disable_mpu_icache_el2 diff --git a/plat/arm/board/fvp_r/fvp_r_private.h b/plat/arm/board/fvp_r/fvp_r_private.h new file mode 100644 index 0000000..48f6e89 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_private.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_PRIVATE_H +#define FVP_R_PRIVATE_H + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_config_setup(void); + +void fvp_interconnect_init(void); +void fvp_interconnect_enable(void); +void fvp_interconnect_disable(void); +void fvp_timer_init(void); + +#endif /* FVP_R_PRIVATE_H */ diff --git a/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/plat/arm/board/fvp_r/fvp_r_stack_protector.c new file mode 100644 index 0000000..69b6312 --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_stack_protector.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <fvp_r_arch_helpers.h> +#include <plat/common/platform.h> + +#define RANDOM_CANARY_VALUE ((u_register_t) 8092347823957523895ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. As the + * FVP_R does not have any random number generator, this is better than + * nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c new file mode 100644 index 0000000..de0b28f --- /dev/null +++ b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#include <lib/fconf/fconf.h> +#include <lib/mmio.h> +#include <tools_share/tbbr_oid.h> + +#include <plat/arm/common/fconf_nv_cntr_getter.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + +/* + * Store a new non-volatile counter value. + * + * On some FVP_R versions, the non-volatile counters are read-only so this + * function will always fail. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + uintptr_t nv_ctr_addr; + + assert(cookie != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + NON_TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + mmio_write_32(nv_ctr_addr, nv_ctr); + + /* + * If the FVP_R models a locked counter then its value cannot be updated + * and the above write operation has been silently ignored. + */ + return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1; +} diff --git a/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h new file mode 100644 index 0000000..92bf484 --- /dev/null +++ b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_ARCH_HELPERS_H +#define FVP_R_ARCH_HELPERS_H + +#include <arch_helpers.h> + +/******************************************************************************* + * MPU register definitions + ******************************************************************************/ +#define MPUIR_EL2 S3_4_C0_C0_4 +#define PRBAR_EL2 S3_4_C6_C8_0 +#define PRLAR_EL2 S3_4_C6_C8_1 +#define PRSELR_EL2 S3_4_C6_C2_1 +#define PRENR_EL2 S3_4_C6_C1_1 + +/* v8-R64 MPU registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2) + +#endif /* FVP_R_ARCH_HELPERS_H */ diff --git a/plat/arm/board/fvp_r/include/platform_def.h b/plat/arm/board/fvp_r/include/platform_def.h new file mode 100644 index 0000000..ea3a258 --- /dev/null +++ b/plat/arm/board/fvp_r/include/platform_def.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_PLATFORM_DEF_H +#define FVP_R_PLATFORM_DEF_H + +#define PLAT_V2M_OFFSET 0x80000000 + +#define BL33_IMAGE_DESC { \ + .image_id = BL33_IMAGE_ID, \ + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \ + VERSION_2, image_info_t, 0), \ + .image_info.image_base = PLAT_ARM_DRAM1_BASE + 0x1000, \ + .image_info.image_max_size = UL(0x3ffff000), \ + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \ + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\ + .ep_info.pc = PLAT_ARM_DRAM1_BASE + 0x1000, \ + .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), \ +} + +#include "../fvp_r_def.h" +#include <drivers/arm/tzc400.h> +#include <lib/utils_def.h> +#include <plat/arm/board/common/v2m_def.h> + +/* These are referenced by arm_def.h #included next, so #define first. */ +#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x80000000) +#define PLAT_ARM_TRUSTED_SRAM_BASE UL(0x84000000) +#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x86000000) +#define PLAT_ARM_DRAM1_BASE ULL(0x0) +#define PLAT_ARM_DRAM2_BASE ULL(0x080000000) + +#define PLAT_HW_CONFIG_DTB_BASE ULL(0x12000000) +#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000) +#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000) +#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000) +#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000) +#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000) +#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000) + +#include <plat/arm/common/arm_def.h> +#include <plat/common/common_def.h> + + +/* Required to create plat_regions: */ +#define MIN_LVL_BLOCK_DESC U(1) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT (U(FVP_R_CLUSTER_COUNT) * \ + U(FVP_R_MAX_CPUS_PER_CLUSTER) * \ + U(FVP_R_MAX_PE_PER_CPU)) + +#define PLAT_NUM_PWR_DOMAINS (U(FVP_R_CLUSTER_COUNT) + \ + PLATFORM_CORE_COUNT + U(1)) + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT U(FVP_R_CLUSTER_COUNT) +#define PLAT_ARM_DRAM1_SIZE ULL(0x7fffffff) +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */ +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */ +#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */ + +/* These two are defined thus in arm_def.h, but doesn't seem to see it... */ +#define PLAT_BL1_RO_LIMIT (BL1_RO_BASE \ + + PLAT_ARM_TRUSTED_ROM_SIZE) + +#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000) +#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000) +#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000) +#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000) +#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000) +#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000) + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* No SCP in FVP_R */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0) + +#define PLAT_ARM_DRAM2_SIZE UL(0x80000000) + +#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000) + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + PLAT_HW_CONFIG_DTB_BASE, \ + PLAT_HW_CONFIG_DTB_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +#define V2M_FVP_R_SYSREGS_BASE UL(0x9c010000) + +/* + * Load address of BL33 for this platform port, + * U-Boot specifically must be loaded at a 4K aligned address. + */ +#define PLAT_ARM_NS_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + 0x1000) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif +# define N_MPU_REGIONS 16 /* number of MPU regions */ +# define ALL_MPU_EL2_REGIONS_USED 0xffffffff + /* this is the PRENR_EL2 value if all MPU regions are in use */ + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0x6000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +#if COT_DESC_IN_DTB +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_R_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_R_BL2_ROMLIB_OPTIMIZATION) +#endif +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_R_BL2_ROMLIB_OPTIMIZATION) +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000) + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x500) +# endif +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* + * These nominally reserve the last block of flash for PSCI MEM PROTECT flag, + * but no PSCI in FVP_R platform, so reserve nothing: + */ +#define PLAT_ARM_FLASH_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + UL(0x40000000)) +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (PLAT_ARM_DRAM1_SIZE - UL(0x40000000)) + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE +#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ + +/* CCI related constants */ +#define PLAT_FVP_R_CCI400_BASE UL(0xac090000) +#define PLAT_FVP_R_CCI400_CLUS0_SL_PORT 3 +#define PLAT_FVP_R_CCI400_CLUS1_SL_PORT 4 + +/* CCI-500/CCI-550 on Base platform */ +#define PLAT_FVP_R_CCI5XX_BASE UL(0xaa000000) +#define PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT 5 +#define PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT 6 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* Mailbox base address */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE + + +/* TrustZone controller related constants + * + * Currently only filters 0 and 2 are connected on Base FVP_R. + * Filter 0 : CPU clusters (no access to DRAM by default) + * Filter 1 : not connected + * Filter 2 : LCDs (access to VRAM allowed by default) + * Filter 3 : not connected + * Programming unconnected filters will have no effect at the + * moment. These filter could, however, be connected in future. + * So care should be taken not to configure the unused filters. + * + * Allow only non-secure access to all DRAM to supported devices. + * Give access to the CPUs and Virtio. Some devices + * would normally use the default ID so allow that too. + */ +#define PLAT_ARM_TZC_BASE UL(0xaa4a0000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_DEFAULT) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_PCI) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_AP) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO_OLD)) + +/* + * GIC related constants to cater for both GICv2 and GICv3 instances of an + * FVP_R. They could be overridden at runtime in case the FVP_R implements the + * legacy VE memory map. + */ +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICR_BASE BASE_GICR_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) + +#define PLAT_SP_PRI PLAT_RAS_PRI + +/* + * Physical and virtual address space limits for MPU in AARCH64 & AARCH32 modes + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) + +#define ARM_SOC_CONTINUATION_SHIFT U(24) +#define ARM_SOC_IDENTIFICATION_SHIFT U(16) + +#endif /* FVP_R_PLATFORM_DEF_H */ diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk new file mode 100644 index 0000000..93b5cf2 --- /dev/null +++ b/plat/arm/board/fvp_r/platform.mk @@ -0,0 +1,99 @@ +# +# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Only aarch64 ARCH supported for FVP_R +ARCH := aarch64 + +# Override to exclude BL2, BL2U, BL31, and BL33 for FVP_R +override NEED_BL2 := no +override NEED_BL2U := no +override NEED_BL31 := no +NEED_BL32 := no + +override CTX_INCLUDE_AARCH32_REGS := 0 + +# Use MPU-based memory management: +XLAT_MPU_LIB_V1 := 1 + +# FVP R will not have more than 2 clusters so just use CCI interconnect +FVP_R_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c + + +include plat/arm/board/common/board_common.mk +include plat/arm/common/arm_common.mk + +PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include + +FVP_R_BL_COMMON_SOURCES := plat/arm/board/fvp_r/fvp_r_common.c \ + plat/arm/board/fvp_r/fvp_r_context_mgmt.c \ + plat/arm/board/fvp_r/fvp_r_debug.S \ + plat/arm/board/fvp_r/fvp_r_err.c \ + plat/arm/board/fvp_r/fvp_r_helpers.S \ + plat/arm/board/fvp_r/fvp_r_misc_helpers.S + +FVP_R_BL1_SOURCES := plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c \ + plat/arm/board/fvp_r/fvp_r_bl1_setup.c \ + plat/arm/board/fvp_r/fvp_r_io_storage.c \ + plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S \ + plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S \ + plat/arm/board/fvp_r/fvp_r_bl1_main.c + +FVP_R_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +FVP_R_DYNC_CFG_SOURCES := common/fdt_wrappers.c \ + plat/arm/common/arm_dyn_cfg.c + +ifeq (${TRUSTED_BOARD_BOOT},1) +FVP_R_AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + lib/fconf/fconf_tbbr_getter.c \ + plat/common/tbbr/plat_tbbr.c \ + drivers/auth/tbbr/tbbr_cot_bl1_r64.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + plat/arm/board/common/board_arm_trusted_boot.c \ + plat/arm/board/common/rotpk/arm_dev_rotpk.S \ + plat/arm/board/fvp_r/fvp_r_trusted_boot.c + +FVP_R_BL1_SOURCES += ${MBEDTLS_SOURCES} \ + ${FVP_R_AUTH_SOURCES} +endif + +ifeq (${USE_SP804_TIMER},1) +FVP_R_BL_COMMON_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +else +FVP_R_BL_COMMON_SOURCES += drivers/delay_timer/generic_delay_timer.c +endif + +# Enable Activity Monitor Unit extensions by default +ENABLE_AMU := 1 + +ifneq (${ENABLE_STACK_PROTECTOR},0) +FVP_R_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c +endif + +override BL1_SOURCES := drivers/arm/sp805/sp805.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/io/io_semihosting.c \ + lib/cpus/aarch64/cpu_helpers.S \ + lib/fconf/fconf_dyn_cfg_getter.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/common/plat_bl1_common.c \ + plat/common/aarch64/platform_up_stack.S \ + ${FVP_R_BL1_SOURCES} \ + ${FVP_R_BL_COMMON_SOURCES} \ + ${FVP_R_CPU_LIBS} \ + ${FVP_R_DYNC_CFG_SOURCES} \ + ${FVP_R_INTERCONNECT_SOURCES} diff --git a/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S b/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S new file mode 100644 index 0000000..78f6c68 --- /dev/null +++ b/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr + +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Currently configured for a sigle CPU + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mov r0, #1 + bx lr +endfunc plat_is_my_cpu_primary diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts new file mode 100644 index 0000000..6e5691b --- /dev/null +++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x80001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x01000000>; + id = <HW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts new file mode 100644 index 0000000..c66186f --- /dev/null +++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + }; +}; diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c new file mode 100644 index 0000000..736cf42 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/sp805.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c new file mode 100644 index 0000000..4ccae27 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/sp804_delay_timer.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#include "fvp_ve_private.h" + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + /* Initialize the platform config for future decision making */ + fvp_ve_config_setup(); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + +#if USE_SP804_TIMER + /* + * Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35 MHz) clock will be used + */ + mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); +#endif /* USE_SP804_TIMER */ +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_common.c b/plat/arm/board/fvp_ve/fvp_ve_common.c new file mode 100644 index 0000000..768dad5 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_common.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <lib/mmio.h> +#include <platform_def.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH1_RW, + V2M_MAP_IOFPGA, + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH1_RW, + V2M_MAP_IOFPGA, + ARM_MAP_NS_DRAM1, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + MAP_DEVICE0, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +void __init fvp_ve_config_setup(void) +{ + unsigned int sys_id, arch; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL_VE) { + ERROR("This firmware is for FVP VE models\n"); + panic(); + } +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return FVP_VE_TIMER_BASE_FREQUENCY; +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_def.h b/plat/arm/board/fvp_ve/fvp_ve_def.h new file mode 100644 index 0000000..98de5f6 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_def.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_VE_DEF_H +#define FVP_VE_DEF_H + +#include <lib/utils_def.h> + +/* Default cluster count for FVP VE */ +#define FVP_VE_CLUSTER_COUNT U(1) + +/* Default number of CPUs per cluster on FVP VE */ +#define FVP_VE_MAX_CPUS_PER_CLUSTER U(1) + +/* Default number of threads per CPU on FVP VE */ +#define FVP_VE_MAX_PE_PER_CPU U(1) + +#define FVP_VE_CORE_COUNT U(1) + +#define FVP_VE_PRIMARY_CPU 0x0 + +/******************************************************************************* + * FVP memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE 0x0c000000 +#define FLASH1_SIZE 0x04000000 + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE 0x20000000 +#define DEVICE0_SIZE 0x0c200000 + +#define NSRAM_BASE 0x2e000000 +#define NSRAM_SIZE 0x10000 + +#define PCIE_EXP_BASE 0x40000000 +#define TZRNG_BASE 0x7fe60000 + +#define ARCH_MODEL_VE 0x5 + +/* FVP Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP specific flags */ +#define FVP_SP810_CTRL_TIM0_OV (1 << 16) +#define FVP_SP810_CTRL_TIM1_OV (1 << 18) +#define FVP_SP810_CTRL_TIM2_OV (1 << 20) +#define FVP_SP810_CTRL_TIM3_OV (1 << 22) + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ +/* VE compatible GIC memory map */ +#define VE_GICD_BASE 0x2c001000 +#ifdef ARM_CORTEX_A5 +#define VE_GICC_BASE 0x2c000100 +#else +#define VE_GICC_BASE 0x2c002000 +#endif +#define VE_GICH_BASE 0x2c004000 +#define VE_GICV_BASE 0x2c006000 + +#define FVP_VE_IRQ_TZ_WDOG 56 +#define FVP_VE_IRQ_SEC_SYS_TIMER 57 + +#define V2M_FLASH1_BASE UL(0x0C000000) +#define V2M_FLASH1_SIZE UL(0x04000000) + +#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\ + V2M_FLASH1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\ + V2M_FLASH1_SIZE, \ + MT_RO_DATA | MT_SECURE) + +#endif /* FVP_VE_DEF_H */ diff --git a/plat/arm/board/fvp_ve/fvp_ve_err.c b/plat/arm/board/fvp_ve/fvp_ve_err.c new file mode 100644 index 0000000..8d35688 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * FVP VE error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_pm.c b/plat/arm/board/fvp_ve/fvp_ve_pm.c new file mode 100644 index 0000000..a4d627b --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_pm.c @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2019, Arm Limited. All rights reserved. +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Export the platform handlers via fvp_ve_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t fvp_ve_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL, +}; + +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &fvp_ve_psci_pm_ops; + + return 0; +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_private.h b/plat/arm/board/fvp_ve/fvp_ve_private.h new file mode 100644 index 0000000..5d396bc --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_VE_PRIVATE_H +#define FVP_VE_PRIVATE_H + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_ve_config_setup(void); + +#endif /* FVP_VE_PRIVATE_H */ diff --git a/plat/arm/board/fvp_ve/fvp_ve_security.c b/plat/arm/board/fvp_ve/fvp_ve_security.c new file mode 100644 index 0000000..24465cb --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_security.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The Base FVP has a TrustZone address space controller, the Foundation + * FVP does not. Trying to program the device on the foundation FVP will + * cause an abort. + * + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ + + return; +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_topology.c b/plat/arm/board/fvp_ve/fvp_ve_topology.c new file mode 100644 index 0000000..51cc9da --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_topology.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +/* The FVP VE power domain tree descriptor */ +static const unsigned char fvp_ve_power_domain_tree_desc[] = { + 1, + /* No of children for the root node */ + FVP_VE_CLUSTER_COUNT, + /* No of children for the first cluster node */ + FVP_VE_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the topology according to FVP_VE_CLUSTER_COUNT. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return fvp_ve_power_domain_tree_desc; +} + +/******************************************************************************* + * Currently FVP VE has only been tested with one core, therefore 0 is returned. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return 0; +} diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h new file mode 100644 index 0000000..bd8ef6a --- /dev/null +++ b/plat/arm/board/fvp_ve/include/platform_def.h @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <common/tbbr/tbbr_img_def.h> +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/smccc_def.h> +#include <plat/common/common_def.h> + +#include "../fvp_ve_def.h" + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* Memory location options for TSP */ +#define ARM_DRAM_ID 2 + +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) + +#define ARM_DRAM2_BASE PLAT_ARM_DRAM2_BASE +#define ARM_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE +#define ARM_DRAM2_END (ARM_DRAM2_BASE + \ + ARM_DRAM2_SIZE - 1) + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +/* + * The last 2MB is meant to be NOLOAD and will not be zero + * initialized. + */ +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + 0x00200000) + + +/* The first 4KB of NS DRAM1 are used as shared memory */ +#define FVP_VE_SHARED_RAM_BASE ARM_NS_DRAM1_BASE +#define FVP_VE_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* The next 252 kB of NS DRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (FVP_VE_SHARED_RAM_BASE + \ + FVP_VE_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \ + FVP_VE_SHARED_RAM_SIZE) + + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + FVP_VE_SHARED_RAM_BASE, \ + FVP_VE_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, \ + ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \ + ARM_DRAM2_BASE, \ + ARM_DRAM2_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + BL_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \ + BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END \ + - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +/* + * Map the region for device tree configuration with read and write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \ + (ARM_FW_CONFIGS_LIMIT \ + - ARM_BL_RAM_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 6 + +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#define FVP_VE_TIMER_BASE_FREQUENCY UL(24000000) +#define ARM_SYS_CNTREAD_BASE UL(0x2a800000) +#define ARM_SYS_CNT_BASE_S UL(0x2a820000) +#define ARM_SYS_CNT_BASE_NS UL(0x2a830000) + +#define ARM_CONSOLE_BAUDRATE 115200 + +/* Trusted Watchdog constants */ +#define ARM_SP805_TWDG_BASE UL(0x1C0F0000) +#define ARM_SP805_TWDG_CLK_HZ 32768 +/* The TBBR document specifies a watchdog timeout of 256 seconds. SP805 + * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */ +#define ARM_TWDG_TIMEOUT_SEC 128 +#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \ + ARM_TWDG_TIMEOUT_SEC) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * To enable FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space of BL2 meminfo. + */ +#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT ((ARM_BL_RAM_BASE + PAGE_SIZE) \ + + (PAGE_SIZE / 2U)) + +/* + * Define limit of firmware configuration memory: + * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory + */ +#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2)) + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + ******************************************************************************/ +#define BL1_RO_BASE 0x00000000 +#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE +/* + * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE)) + + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ + +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - FVP_VE_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE + + +/* Put BL32 below BL2 in NS DRAM.*/ +#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT +#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \ + + (PAGE_SIZE / 2U)) + +#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\ + - PLAT_ARM_MAX_BL32_SIZE) +#define BL32_PROGBITS_LIMIT BL2_BASE +#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT FVP_VE_CLUSTER_COUNT +#define PLAT_NUM_PWR_DOMAINS ((FVP_VE_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + U(1)) + +#define PLAT_MAX_PWR_LVL 2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ + +#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x04000000 /* 64 MB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000) + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 6 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000 + +/* + * FVP_VE_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define FVP_VE_MAX_BL2_SIZE 0x11000 + +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL32_SIZE 0x3B000 +/* + + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* Reserve the last block of flash for PSCI MEM PROTECT flag */ +#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH1_BASE +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE) + +#define PLAT_ARM_NVM_BASE V2M_FLASH1_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 1 + +/* Mailbox base address */ +#define FVP_VE_TRUSTED_MAILBOX_BASE FVP_VE_SHARED_RAM_BASE + +/* + * GIC related constants to cater for GICv2 + */ +#define PLAT_ARM_GICD_BASE VE_GICD_BASE +#define PLAT_ARM_GICC_BASE VE_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(FVP_VE_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(FVP_VE_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +#endif /* PLATFORM_H */ diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk new file mode 100644 index 0000000..f7eace8 --- /dev/null +++ b/plat/arm/board/fvp_ve/platform.mk @@ -0,0 +1,139 @@ +# +# Copyright (c) 2019-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +ifdef ARM_CORTEX_A5 +# Use the SP804 timer instead of the generic one +USE_SP804_TIMER := 1 +BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +FVP_VE_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +FVP_VE_SECURITY_SOURCES := plat/arm/board/fvp_ve/fvp_ve_security.c + +PLAT_INCLUDES := -Iplat/arm/board/fvp_ve/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp_ve/fvp_ve_common.c \ + plat/arm/common/${ARCH}/arm_helpers.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +ifdef ARM_CORTEX_A5 +FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S +else +FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a7.S +endif + +BL1_SOURCES += drivers/arm/sp805/sp805.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/fvp_ve/fvp_ve_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + drivers/cfi/v2m/v2m_flash.c \ + plat/arm/board/fvp_ve/${ARCH}/fvp_ve_helpers.S \ + plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + ${FVP_VE_CPU_LIBS} \ + ${DYN_CFG_SOURCES} + +BL2_SOURCES += plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/fvp_ve/fvp_ve_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ + plat/arm/common/arm_image_load.c \ + common/desc_image_load.c \ + ${DYN_CFG_SOURCES} \ + ${FVP_VE_SECURITY_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK + +FDT_SOURCES += plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts \ + plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts + +FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb +FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config,${FVP_FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CONFIG})) + +FDT_SOURCES += ${FVP_HW_CONFIG_DTS} +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \ + fdts/$(notdir ${FVP_HW_CONFIG_DTS}))) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG})) +endif + +NEED_BL32 := yes + +# Modification of arm_common.mk + +# Process ARM_DISABLE_TRUSTED_WDOG flag +# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set +ARM_DISABLE_TRUSTED_WDOG := 0 +ifeq (${SPIN_ON_BL1_EXIT}, 1) +ARM_DISABLE_TRUSTED_WDOG := 1 +endif +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) + +# Use translation tables library v1 if using Cortex-A5 +ifdef ARM_CORTEX_A5 +ARM_XLAT_TABLES_LIB_V1 := 1 +else +ARM_XLAT_TABLES_LIB_V1 := 0 +endif +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + # Only use nonlpae version of xlatv1 otherwise use xlat v2 + PLAT_BL_COMMON_SOURCES += lib/xlat_tables/${ARCH}/nonlpae_tables.c +else + include lib/xlat_tables_v2/xlat_tables.mk + PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} +endif + +# Firmware Configuration Framework sources +include lib/fconf/fconf.mk + +BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} +BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c + +DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES} diff --git a/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c b/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c new file mode 100644 index 0000000..e6a1bbe --- /dev/null +++ b/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <plat/arm/common/plat_arm.h> + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} diff --git a/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk new file mode 100644 index 0000000..4ca810d --- /dev/null +++ b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S \ + drivers/arm/fvp/fvp_pwrc.c \ + plat/arm/board/fvp_ve/fvp_ve_pm.c \ + plat/arm/board/fvp_ve/fvp_ve_topology.c \ + plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + plat/arm/common/sp_min/arm_sp_min_setup.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c \ + ${FVP_VE_CPU_LIBS} \ + ${FVP_VE_GIC_SOURCES} \ + ${FVP_VE_SECURITY_SOURCES} diff --git a/plat/arm/board/juno/aarch32/juno_helpers.S b/plat/arm/board/juno/aarch32/juno_helpers.S new file mode 100644 index 0000000..8f9561c --- /dev/null +++ b/plat/arm/board/juno/aarch32/juno_helpers.S @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/bl_common.h> +#include <cortex_a53.h> +#include <cortex_a57.h> +#include <cortex_a72.h> +#include <cpu_macros.S> +#include <platform_def.h> + + .globl plat_reset_handler + .globl plat_arm_calc_core_pos + +#define JUNO_REVISION(rev) REV_JUNO_R##rev +#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev +#define JUMP_TO_HANDLER_IF_JUNO_R(revision) \ + jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision) + + /* -------------------------------------------------------------------- + * Helper macro to jump to the given handler if the board revision + * matches. + * Expects the Juno board revision in x0. + * -------------------------------------------------------------------- + */ + .macro jump_to_handler _revision, _handler + cmp r0, #\_revision + beq \_handler + .endm + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R0. + * + * Juno R0 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Implement workaround for defect id 831273 by enabling an event + * stream every 65536 cycles. + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(0) + /* -------------------------------------------------------------------- + * Enable the event stream every 65536 cycles + * -------------------------------------------------------------------- + */ + mov r0, #(0xf << EVNTI_SHIFT) + orr r0, r0, #EVNTEN_BIT + stcopr r0, CNTKCTL + + /* -------------------------------------------------------------------- + * Nothing else to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A53_MIDR, 1f + + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov r0, #((CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + stcopr r0, CORTEX_A57_L2CTLR +1: + isb + bx lr +endfunc JUNO_HANDLER(0) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R1. + * + * Juno R1 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * + * Note that: + * - The default value for the L2 Tag RAM latency for Cortex-A57 is + * suitable. + * - Defect #831273 doesn't affect Juno R1. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(1) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A57_MIDR, A57 + bx lr + +A57: + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov r0, #(CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) + stcopr r0, CORTEX_A57_L2CTLR + isb + bx lr +endfunc JUNO_HANDLER(1) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R2. + * + * Juno R2 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A72 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72 + * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72 + * + * Note that: + * - Defect #831273 doesn't affect Juno R2. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(2) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A72_MIDR, A72 + bx lr + +A72: + /* -------------------------------------------------------------------- + * Cortex-A72 specific settings + * -------------------------------------------------------------------- + */ + mov r0, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES << CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + stcopr r0, CORTEX_A72_L2CTLR + isb + bx lr +endfunc JUNO_HANDLER(2) + + /* -------------------------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the Juno board revision and call the appropriate reset + * handler. + * -------------------------------------------------------------------- + */ +func plat_reset_handler + /* Read the V2M SYS_ID register */ + ldr r0, =(V2M_SYSREGS_BASE + V2M_SYS_ID) + ldr r1, [r0] + /* Extract board revision from the SYS_ID */ + ubfx r0, r1, #V2M_SYS_ID_REV_SHIFT, #4 + + JUMP_TO_HANDLER_IF_JUNO_R(0) + JUMP_TO_HANDLER_IF_JUNO_R(1) + JUMP_TO_HANDLER_IF_JUNO_R(2) + + /* Board revision is not supported */ + no_ret plat_panic_handler + +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + b css_calc_core_pos_swap_cluster +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S new file mode 100644 index 0000000..c94fa3e --- /dev/null +++ b/plat/arm/board/juno/aarch64/juno_helpers.S @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/bl_common.h> +#include <cortex_a53.h> +#include <cortex_a57.h> +#include <cortex_a72.h> +#include <cpu_macros.S> +#include <platform_def.h> + + .globl plat_reset_handler + .globl plat_arm_calc_core_pos +#if JUNO_AARCH32_EL3_RUNTIME + .globl plat_get_my_entrypoint + .globl juno_reset_to_aarch32_state +#endif + +#define JUNO_REVISION(rev) REV_JUNO_R##rev +#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev +#define JUMP_TO_HANDLER_IF_JUNO_R(revision) \ + jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision) + + /* -------------------------------------------------------------------- + * Helper macro to jump to the given handler if the board revision + * matches. + * Expects the Juno board revision in x0. + * -------------------------------------------------------------------- + */ + .macro jump_to_handler _revision, _handler + cmp x0, #\_revision + b.eq \_handler + .endm + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R0. + * + * Juno R0 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Implement workaround for defect id 831273 by enabling an event + * stream every 65536 cycles. + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(0) + /* -------------------------------------------------------------------- + * Enable the event stream every 65536 cycles + * -------------------------------------------------------------------- + */ + mov x0, #(0xf << EVNTI_SHIFT) + orr x0, x0, #EVNTEN_BIT + msr CNTKCTL_EL1, x0 + + /* -------------------------------------------------------------------- + * Nothing else to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A53_MIDR, 1f + + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov x0, #((CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + msr CORTEX_A57_L2CTLR_EL1, x0 +1: + isb + ret +endfunc JUNO_HANDLER(0) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R1. + * + * Juno R1 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * + * Note that: + * - The default value for the L2 Tag RAM latency for Cortex-A57 is + * suitable. + * - Defect #831273 doesn't affect Juno R1. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(1) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A57_MIDR, A57 + ret + +A57: + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov x0, #(CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) + msr CORTEX_A57_L2CTLR_EL1, x0 + isb + ret +endfunc JUNO_HANDLER(1) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R2. + * + * Juno R2 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A72 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72 + * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72 + * + * Note that: + * - Defect #831273 doesn't affect Juno R2. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(2) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A72_MIDR, A72 + ret + +A72: + /* -------------------------------------------------------------------- + * Cortex-A72 specific settings + * -------------------------------------------------------------------- + */ + mov x0, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES << CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + msr CORTEX_A57_L2CTLR_EL1, x0 + isb + ret +endfunc JUNO_HANDLER(2) + + /* -------------------------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the Juno board revision and call the appropriate reset + * handler. + * -------------------------------------------------------------------- + */ +func plat_reset_handler + /* Read the V2M SYS_ID register */ + mov_imm x0, (V2M_SYSREGS_BASE + V2M_SYS_ID) + ldr w1, [x0] + /* Extract board revision from the SYS_ID */ + ubfx x0, x1, #V2M_SYS_ID_REV_SHIFT, #4 + + JUMP_TO_HANDLER_IF_JUNO_R(0) + JUMP_TO_HANDLER_IF_JUNO_R(1) + JUMP_TO_HANDLER_IF_JUNO_R(2) + + /* Board revision is not supported */ + no_ret plat_panic_handler + +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * void juno_do_reset_to_aarch32_state(void); + * + * Request warm reset to AArch32 mode. + * ----------------------------------------------------- + */ +func juno_do_reset_to_aarch32_state + mov x0, #RMR_EL3_RR_BIT + dsb sy + msr rmr_el3, x0 + isb + wfi + b plat_panic_handler +endfunc juno_do_reset_to_aarch32_state + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + b css_calc_core_pos_swap_cluster +endfunc plat_arm_calc_core_pos + +#if JUNO_AARCH32_EL3_RUNTIME + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. On JUNO platform, this distinction is based on the contents of + * the Trusted Mailbox. It is initialised to zero by the SCP before the + * AP cores are released from reset. Therefore, a zero mailbox means + * it's a cold reset. If it is a warm boot then a request to reset to + * AArch32 state is issued. This is the only way to reset to AArch32 + * in EL3 on Juno. A trampoline located at the high vector address + * has already been prepared by BL1. + * + * This functions returns the contents of the mailbox, i.e.: + * - 0 for a cold boot; + * - request warm reset in AArch32 state for warm boot case; + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + cbz x0, return + b juno_do_reset_to_aarch32_state +return: + ret +endfunc plat_get_my_entrypoint + +/* + * Emit a "movw r0, #imm16" which moves the lower + * 16 bits of `_val` into r0. + */ +.macro emit_movw _reg_d, _val + mov_imm \_reg_d, (0xe3000000 | \ + ((\_val & 0xfff) | \ + ((\_val & 0xf000) << 4))) +.endm + +/* + * Emit a "movt r0, #imm16" which moves the upper + * 16 bits of `_val` into r0. + */ +.macro emit_movt _reg_d, _val + mov_imm \_reg_d, (0xe3400000 | \ + (((\_val & 0x0fff0000) >> 16) | \ + ((\_val & 0xf0000000) >> 12))) +.endm + +/* + * This function writes the trampoline code at HI-VEC (0xFFFF0000) + * address which loads r0 with the entrypoint address for + * BL32 (a.k.a SP_MIN) when EL3 is in AArch32 mode. A warm reset + * to AArch32 mode is then requested by writing into RMR_EL3. + */ +func juno_reset_to_aarch32_state + /* + * Invalidate all caches before the warm reset to AArch32 state. + * This is required on the Juno AArch32 boot flow because the L2 + * unified cache may contain code and data from when the processor + * was still executing in AArch64 state. This code only runs on + * the primary core, all other cores are powered down. + */ + mov x0, #DCISW + bl dcsw_op_all + + emit_movw w0, BL32_BASE + emit_movt w1, BL32_BASE + /* opcode "bx r0" to branch using r0 in AArch32 mode */ + mov_imm w2, 0xe12fff10 + + /* Write the above opcodes at HI-VECTOR location */ + mov_imm x3, HI_VECTOR_BASE + str w0, [x3], #4 + str w1, [x3], #4 + str w2, [x3] + + b juno_do_reset_to_aarch32_state +endfunc juno_reset_to_aarch32_state + +#endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts new file mode 100644 index 0000000..4b88efe --- /dev/null +++ b/plat/arm/board/juno/fdts/juno_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x8000>; + id = <HW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts new file mode 100644 index 0000000..80cfa3e --- /dev/null +++ b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + /* Disable authentication for development */ + disable_auth = <0x0>; + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/juno/include/plat_macros.S b/plat/arm/board/juno/include/plat_macros.S new file mode 100644 index 0000000..ec94a4f --- /dev/null +++ b/plat/arm/board/juno/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <cci_macros.S> +#include <css_macros.S> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + css_print_gic_regs + print_cci_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h new file mode 100644 index 0000000..409d7a6 --- /dev/null +++ b/plat/arm/board/juno/include/platform_def.h @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <drivers/arm/tzc400.h> +#if TRUSTED_BOARD_BOOT +#include MBEDTLS_CONFIG_FILE +#endif +#include <plat/arm/board/common/board_css_def.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_def.h> +#include <plat/arm/css/common/css_def.h> +#include <plat/arm/soc/common/soc_css_def.h> +#include <plat/common/common_def.h> + +#include "../juno_def.h" + +/* Required platform porting definitions */ +/* Juno supports system power domain */ +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 +#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \ + JUNO_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLATFORM_CORE_COUNT (JUNO_CLUSTER0_CORE_COUNT + \ + JUNO_CLUSTER1_CORE_COUNT) + +/* Cryptocell HW Base address */ +#define PLAT_CRYPTOCELL_BASE UL(0x60050000) + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT JUNO_CLUSTER_COUNT + +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */ + +/* Use the bypass address */ +#define PLAT_ARM_TRUSTED_ROM_BASE (V2M_FLASH0_BASE + \ + BL1_ROM_BYPASS_OFFSET) + +#define NSRAM_BASE UL(0x2e000000) +#define NSRAM_SIZE UL(0x00008000) /* 32KB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) + +/* Range of kernel DTB load address */ +#define JUNO_DTB_DRAM_MAP_START ULL(0x82000000) +#define JUNO_DTB_DRAM_MAP_SIZE ULL(0x00008000) /* 32KB */ + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + JUNO_DTB_DRAM_MAP_START, \ + JUNO_DTB_DRAM_MAP_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define JUNO_BL2_ROMLIB_OPTIMIZATION UL(0x8000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define JUNO_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif + +/* + * Actual ROM size on Juno is 64 KB, but TBB currently requires at least 80 KB + * in debug mode. We can test TBB on Juno bypassing the ROM and using 128 KB of + * flash + */ + +#if TRUSTED_BOARD_BOOT +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00020000) +#else +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00010000) +#endif /* TRUSTED_BOARD_BOOT */ + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#ifdef IMAGE_BL1 +# define PLAT_ARM_MMAP_ENTRIES 7 +# define MAX_XLAT_TABLES 4 +#endif + +#ifdef IMAGE_BL2 +#ifdef SPD_opteed +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 10 +# define MAX_XLAT_TABLES 4 +#endif +#endif + +#ifdef IMAGE_BL2U +# define PLAT_ARM_MMAP_ENTRIES 5 +# define MAX_XLAT_TABLES 3 +#endif + +#ifdef IMAGE_BL31 +# define PLAT_ARM_MMAP_ENTRIES 7 +# define MAX_XLAT_TABLES 5 +#endif + +#ifdef IMAGE_BL32 +# define PLAT_ARM_MMAP_ENTRIES 6 +# define MAX_XLAT_TABLES 4 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) +#else +# define PLAT_ARM_MAX_BL1_RW_SIZE UL(0x6000) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1F000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#elif TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#endif +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL31 -> BL2_BASE. + * Hence the BL31 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE. + */ +#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000) + +#if JUNO_AARCH32_EL3_RUNTIME +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current BL32 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL32 -> BL2_BASE. + * Hence the BL32 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE. + */ +#define PLAT_ARM_MAX_BL32_SIZE UL(0x3D000) +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x440) +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE UL(0x400) +#elif defined(IMAGE_BL31) +# if PLAT_XLAT_TABLES_DYNAMIC +# define PLATFORM_STACK_SIZE UL(0x800) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE UL(0x440) +#endif + +/* CCI related constants */ +#define PLAT_ARM_CCI_BASE UL(0x2c090000) +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 3 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* TZC related constants */ +#define PLAT_ARM_TZC_BASE UL(0x2a4a0000) +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT)) + +/* TZC related constants */ +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL + +/* + * Required ARM CSS based platform porting definitions + */ + +/* GIC related constants (no GICR in GIC-400) */ +#define PLAT_ARM_GICD_BASE UL(0x2c010000) +#define PLAT_ARM_GICC_BASE UL(0x2c02f000) +#define PLAT_ARM_GICH_BASE UL(0x2c04f000) +#define PLAT_ARM_GICV_BASE UL(0x2c06f000) + +/* MHU related constants */ +#define PLAT_CSS_MHU_BASE UL(0x2b1f0000) + +/* + * Base address of the first memory region used for communication between AP + * and SCP. Used by the BOM and SCPI protocols. + */ +#if !CSS_USE_SCMI_SDS_DRIVER +/* + * Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which + * means the SCP/AP configuration data gets overwritten when the AP initiates + * communication with the SCP. The configuration data is expected to be a + * 32-bit word on all CSS platforms. On Juno, part of this configuration is + * which CPU is the primary, according to the shift and mask definitions below. + */ +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE (ARM_TRUSTED_SRAM_BASE + UL(0x80)) +#define PLAT_CSS_PRIMARY_CPU_SHIFT 8 +#define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH 4 +#endif + +/* + * SCP_BL2 uses up whatever remaining space is available as it is loaded before + * anything else in this memory region and is handed over to the SCP before + * BL31 is loaded over the top. + */ +#define PLAT_CSS_MAX_SCP_BL2_SIZE \ + ((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK) + +#define PLAT_CSS_MAX_SCP_BL2U_SIZE PLAT_CSS_MAX_SCP_BL2_SIZE + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + CSS_G1S_IRQ_PROPS(grp), \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(JUNO_IRQ_DMA_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_HDLCD0_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_HDLCD1_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_USB_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_THIN_LINKS_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_SEC_I2C, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_GPU_SMMU_1, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_ETR_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +/* + * Required ARM CSS SoC based platform porting definitions + */ + +/* CSS SoC NIC-400 Global Programmers View (GPV) */ +#define PLAT_SOC_CSS_NIC400_BASE UL(0x2a000000) + +#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS +#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i new file mode 100644 index 0000000..8932aa0 --- /dev/null +++ b/plat/arm/board/juno/jmptbl.i @@ -0,0 +1,62 @@ +# +# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Platform specific romlib functions can be added or included here. +# The index in the output file will be generated cumulatively in the same +# order as it is given in this file. +# Output file can be found at: $BUILD_DIR/jmptbl.i +# +# Format: +# lib function [patch] +# Example: +# rom rom_lib_init +# fdt fdt_getprop_namelen patch + +rom rom_lib_init +fdt fdt_getprop +fdt fdt_get_property +fdt fdt_getprop_namelen +fdt fdt_setprop_inplace +fdt fdt_check_header +fdt fdt_node_offset_by_compatible +fdt fdt_setprop_inplace_namelen_partial +fdt fdt_first_subnode +fdt fdt_next_subnode +fdt fdt_parent_offset +fdt fdt_stringlist_search +fdt fdt_get_alias_namelen +fdt fdt_path_offset +fdt fdt_path_offset_namelen +fdt fdt_address_cells +fdt fdt_size_cells +fdt fdt_get_name +fdt fdt_get_alias +fdt fdt_node_offset_by_phandle +fdt fdt_subnode_offset +fdt fdt_add_subnode +mbedtls mbedtls_asn1_get_alg +mbedtls mbedtls_asn1_get_alg_null +mbedtls mbedtls_asn1_get_bitstring_null +mbedtls mbedtls_asn1_get_bool +mbedtls mbedtls_asn1_get_int +mbedtls mbedtls_asn1_get_tag +mbedtls mbedtls_free +mbedtls mbedtls_md +mbedtls mbedtls_md_get_size +mbedtls mbedtls_memory_buffer_alloc_init +mbedtls mbedtls_oid_get_md_alg +mbedtls mbedtls_oid_get_numeric_string +mbedtls mbedtls_oid_get_pk_alg +mbedtls mbedtls_oid_get_sig_alg +mbedtls mbedtls_pk_free +mbedtls mbedtls_pk_init +mbedtls mbedtls_pk_parse_subpubkey +mbedtls mbedtls_pk_verify_ext +mbedtls mbedtls_platform_set_snprintf +mbedtls mbedtls_x509_get_rsassa_pss_params +mbedtls mbedtls_x509_get_sig_alg +mbedtls mbedtls_md_info_from_type +c exit +c atexit diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c new file mode 100644 index 0000000..a9d5cc3 --- /dev/null +++ b/plat/arm/board/juno/juno_bl1_setup.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/arm/css/sds.h> +#include <drivers/arm/sp805.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/common/arm_def.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +void juno_reset_to_aarch32_state(void); + +static int is_watchdog_reset(void) +{ +#if !CSS_USE_SCMI_SDS_DRIVER + #define RESET_REASON_WDOG_RESET (0x2) + const uint32_t *reset_flags_ptr = (const uint32_t *)SSC_GPRETN; + + if ((*reset_flags_ptr & RESET_REASON_WDOG_RESET) != 0) + return 1; + + return 0; +#else + int ret; + uint32_t scp_reset_synd_flags; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SCP SDS initialization failed\n"); + panic(); + } + + ret = sds_struct_read(SDS_RESET_SYNDROME_STRUCT_ID, + SDS_RESET_SYNDROME_OFFSET, + &scp_reset_synd_flags, + SDS_RESET_SYNDROME_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Getting reset reason from SDS failed\n"); + panic(); + } + + /* Check if the WATCHDOG_RESET_BIT is set in the reset syndrome */ + if (scp_reset_synd_flags & SDS_RESET_SYNDROME_AP_WD_RESET_BIT) + return 1; + + return 0; +#endif +} + +/******************************************************************************* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or watchdog reset happened. + ******************************************************************************/ +bool plat_arm_bl1_fwu_needed(void) +{ + int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* Check if TOC is invalid or watchdog reset happened. */ + return (!arm_io_is_toc_valid() || (((nv_flags == -EAUTH) || + (nv_flags == -ENOENT)) && is_watchdog_reset())); +} + +/******************************************************************************* + * On JUNO update the arg2 with address of SCP_BL2U image info. + ******************************************************************************/ +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + if (image_id == BL2U_IMAGE_ID) { + image_desc_t *image_desc = bl1_plat_get_image_desc(SCP_BL2U_IMAGE_ID); + ep_info->args.arg2 = (unsigned long)&image_desc->image_info; + } +} + +/******************************************************************************* + * On Juno clear SYS_NVFLAGS and wait for watchdog reset. + ******************************************************************************/ +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* Clear the NV flags register. */ + mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR), + nv_flags); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) + wfi(); +} + +#if JUNO_AARCH32_EL3_RUNTIME +void bl1_plat_prepare_exit(entry_point_info_t *ep_info) +{ +#if !ARM_DISABLE_TRUSTED_WDOG + /* Disable watchdog before leaving BL1 */ + sp805_stop(ARM_SP805_TWDG_BASE); +#endif + + juno_reset_to_aarch32_state(); +} +#endif /* JUNO_AARCH32_EL3_RUNTIME */ + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c new file mode 100644 index 0000000..849acd6 --- /dev/null +++ b/plat/arm/board/juno/juno_bl2_setup.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-2017,2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> + +#include <plat/arm/common/plat_arm.h> + +#if JUNO_AARCH32_EL3_RUNTIME +/******************************************************************************* + * This function changes the spsr for BL32 image to bypass + * the check in BL1 AArch64 exception handler. This is needed in the aarch32 + * boot flow as the core comes up in aarch64 and to enter the BL32 image a warm + * reset in aarch32 state is required. + ******************************************************************************/ +int arm_bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = arm_bl2_handle_post_image_load(image_id); + + if (!err && (image_id == BL32_IMAGE_ID)) { + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + assert(bl_mem_params); + bl_mem_params->ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + + return err; +} + +#else + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params = arm_get_next_bl_params(); + +#if __aarch64__ + const struct dyn_cfg_dtb_info_t *fw_config_info; + bl_mem_params_node_t *param_node; + uintptr_t fw_config_base = 0U; + entry_point_info_t *ep_info; + + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); + assert(param_node != NULL); + + /* Get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0U); + + /* + * Get the entry point info of BL31 image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; +#endif /* __aarch64__ */ + + return arm_bl_params; +} +#endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/plat/arm/board/juno/juno_bl31_setup.c b/plat/arm/board/juno/juno_bl31_setup.c new file mode 100644 index 0000000..7a0a6d9 --- /dev/null +++ b/plat/arm/board/juno/juno_bl31_setup.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> + +#include <plat/arm/common/plat_arm.h> + +void __init bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + const struct dyn_cfg_dtb_info_t *soc_fw_config_info; + + INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); + + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); + + soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); + if (soc_fw_config_info != NULL) { + arg1 = soc_fw_config_info->config_addr; + } + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_arm_interconnect_enter_coherency(); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); + + /* HW_CONFIG was also loaded by BL2 */ + const struct dyn_cfg_dtb_info_t *hw_config_info; + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + fconf_populate("HW_CONFIG", hw_config_info->config_addr); +} diff --git a/plat/arm/board/juno/juno_common.c b/plat/arm/board/juno/juno_common.c new file mode 100644 index 0000000..038f604 --- /dev/null +++ b/plat/arm/board/juno/juno_common.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/smccc.h> +#include <platform_def.h> +#include <services/arm_arch_svc.h> + +#include <plat/arm/common/plat_arm.h> + +/* + * Table of memory regions for different BL stages to map using the MMU. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. + */ +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, +#if TRUSTED_BOARD_BOOT + /* Map DRAM to authenticate NS_BL2U image. */ + ARM_MAP_NS_DRAM1, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#ifdef __aarch64__ + ARM_MAP_DRAM2, +#endif +#ifdef SPD_tspd + ARM_MAP_TSP_SEC_MEM, +#endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2U +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + CSS_MAP_DEVICE, + CSS_MAP_SCP_BL2U, + V2M_MAP_IOFPGA, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#ifdef IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + SOC_CSS_MAP_DEVICE, + ARM_DTB_DRAM_NS, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { +#ifndef __aarch64__ + ARM_MAP_SHARED_RAM, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif +#endif + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + return (int32_t) + (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE, + ARM_SOC_IDENTIFICATION_CODE) | + (JUNO_SOC_ID & SOC_ID_IMPL_DEF_MASK)); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + unsigned int sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) & + V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK); +} diff --git a/plat/arm/board/juno/juno_def.h b/plat/arm/board/juno/juno_def.h new file mode 100644 index 0000000..ddf99dc --- /dev/null +++ b/plat/arm/board/juno/juno_def.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef JUNO_DEF_H +#define JUNO_DEF_H + +#include <lib/utils_def.h> + +/****************************************************************************** + * Definition of platform soc id + *****************************************************************************/ +#define JUNO_SOC_ID 1 + +/******************************************************************************* + * Juno memory map related constants + ******************************************************************************/ + +/* Board revisions */ +#define REV_JUNO_R0 U(0x1) /* Rev B */ +#define REV_JUNO_R1 U(0x2) /* Rev C */ +#define REV_JUNO_R2 U(0x3) /* Rev D */ + +/* Bypass offset from start of NOR flash */ +#define BL1_ROM_BYPASS_OFFSET UL(0x03EC0000) + +#define EMMC_BASE UL(0x0c000000) +#define EMMC_SIZE UL(0x04000000) + +#define PSRAM_BASE UL(0x14000000) +#define PSRAM_SIZE UL(0x02000000) + +#define JUNO_SSC_VER_PART_NUM U(0x030) + +/******************************************************************************* + * Juno topology related constants + ******************************************************************************/ +#define JUNO_CLUSTER_COUNT U(2) +#define JUNO_CLUSTER0_CORE_COUNT U(2) +#define JUNO_CLUSTER1_CORE_COUNT U(4) + +/******************************************************************************* + * TZC-400 related constants + ******************************************************************************/ +#define TZC400_NSAID_CCI400 0 /* Note: Same as default NSAID!! */ +#define TZC400_NSAID_PCIE 1 +#define TZC400_NSAID_HDLCD0 2 +#define TZC400_NSAID_HDLCD1 3 +#define TZC400_NSAID_USB 4 +#define TZC400_NSAID_DMA330 5 +#define TZC400_NSAID_THINLINKS 6 +#define TZC400_NSAID_AP 9 +#define TZC400_NSAID_GPU 10 +#define TZC400_NSAID_SCP 11 +#define TZC400_NSAID_CORESIGHT 12 + +/******************************************************************************* + * TRNG related constants + ******************************************************************************/ +#define TRNG_BASE UL(0x7FE60000) +#define TRNG_NOUTPUTS 4 +#define TRNG_STATUS UL(0x10) +#define TRNG_INTMASK UL(0x14) +#define TRNG_CONFIG UL(0x18) +#define TRNG_CONTROL UL(0x1C) +#define TRNG_NBYTES 16 /* Number of bytes generated per round. */ + +/******************************************************************************* + * MMU-401 related constants + ******************************************************************************/ +#define MMU401_SSD_OFFSET UL(0x4000) +#define MMU401_DMA330_BASE UL(0x7fb00000) + +/******************************************************************************* + * Interrupt handling constants + ******************************************************************************/ +#define JUNO_IRQ_DMA_SMMU 126 +#define JUNO_IRQ_HDLCD0_SMMU 128 +#define JUNO_IRQ_HDLCD1_SMMU 130 +#define JUNO_IRQ_USB_SMMU 132 +#define JUNO_IRQ_THIN_LINKS_SMMU 134 +#define JUNO_IRQ_SEC_I2C 137 +#define JUNO_IRQ_GPU_SMMU_1 73 +#define JUNO_IRQ_ETR_SMMU 75 + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#endif /* JUNO_DEF_H */ diff --git a/plat/arm/board/juno/juno_err.c b/plat/arm/board/juno/juno_err.c new file mode 100644 index 0000000..02d751e --- /dev/null +++ b/plat/arm/board/juno/juno_err.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <arch_helpers.h> +#include <drivers/arm/sp805.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* + * Juno error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + /* Propagate the err code in the NV-flags register */ + mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + for (;;) + wfi(); +} diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c new file mode 100644 index 0000000..cc80651 --- /dev/null +++ b/plat/arm/board/juno/juno_pm.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/css/scmi.h> +#include <plat/arm/common/plat_arm.h> + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ +#if CSS_USE_SCMI_SDS_DRIVER + return css_scmi_override_pm_ops(ops); +#else + return ops; +#endif /* CSS_USE_SCMI_SDS_DRIVER */ +} diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c new file mode 100644 index 0000000..654a7f1 --- /dev/null +++ b/plat/arm/board/juno/juno_security.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <assert.h> + +#include <common/debug.h> +#include <drivers/arm/nic_400.h> +#include <lib/mmio.h> +#include <platform_def.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/soc/common/soc_css.h> +#include <plat/common/platform.h> + +#include "juno_tzmp1_def.h" + +#ifdef JUNO_TZMP1 +/* + * Protect buffer for VPU/GPU/DPU memory usage with hardware protection + * enabled. Propose 224MB video output, 96 MB video input and 32MB video + * private. + * + * Ind Memory Range Caption S_ATTR NS_ATTR + * 1 0x080000000 - 0x0E7FFFFFF ARM_NS_DRAM1 NONE RDWR | MEDIA_RW + * 2 0x0E8000000 - 0x0F5FFFFFF JUNO_MEDIA_TZC_PROT_DRAM1 NONE MEDIA_RW | AP_WR + * 3 0x0F6000000 - 0x0FBFFFFFF JUNO_VPU_TZC_PROT_DRAM1 RDWR VPU_PROT_RW + * 4 0x0FC000000 - 0x0FDFFFFFF JUNO_VPU_TZC_PRIV_DRAM1 RDWR VPU_PRIV_RW + * 5 0x0FE000000 - 0x0FEFFFFFF JUNO_AP_TZC_SHARE_DRAM1 NONE RDWR | MEDIA_RW + * 6 0x0FF000000 - 0x0FFFFFFFF ARM_AP_TZC_DRAM1 RDWR NONE + * 7 0x880000000 - 0x9FFFFFFFF ARM_DRAM2 NONE RDWR | MEDIA_RW + * + * Memory regions are neighbored to save limited TZC regions. Calculation + * started from ARM_TZC_SHARE_DRAM1 since it is known and fixed for both + * protected-enabled and protected-disabled settings. + * + * Video private buffer aheads of ARM_TZC_SHARE_DRAM1 + */ + +static const arm_tzc_regions_info_t juno_tzmp1_tzc_regions[] = { + {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0}, + {JUNO_NS_DRAM1_PT1_BASE, JUNO_NS_DRAM1_PT1_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS}, + {JUNO_MEDIA_TZC_PROT_DRAM1_BASE, JUNO_MEDIA_TZC_PROT_DRAM1_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_PROT_ACCESS}, + {JUNO_VPU_TZC_PROT_DRAM1_BASE, JUNO_VPU_TZC_PROT_DRAM1_END, + TZC_REGION_S_RDWR, JUNO_VPU_TZC_PROT_ACCESS}, + {JUNO_VPU_TZC_PRIV_DRAM1_BASE, JUNO_VPU_TZC_PRIV_DRAM1_END, + TZC_REGION_S_RDWR, JUNO_VPU_TZC_PRIV_ACCESS}, + {JUNO_AP_TZC_SHARE_DRAM1_BASE, JUNO_AP_TZC_SHARE_DRAM1_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS}, + {ARM_DRAM2_BASE, ARM_DRAM2_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS}, + {}, +}; + +/******************************************************************************* + * Program dp650 to configure NSAID value for protected mode. + ******************************************************************************/ +static void init_dp650(void) +{ + mmio_write_32(DP650_BASE + DP650_PROT_NSAID_OFFSET, + DP650_PROT_NSAID_CONFIG); +} + +/******************************************************************************* + * Program v550 to configure NSAID value for protected mode. + ******************************************************************************/ +static void init_v550(void) +{ + /* + * bits[31:28] is for PRIVATE, + * bits[27:24] is for OUTBUF, + * bits[23:20] is for PROTECTED. + */ + mmio_write_32(V550_BASE + V550_PROTCTRL_OFFSET, V550_PROTCTRL_CONFIG); +} + +#endif /* JUNO_TZMP1 */ + +/******************************************************************************* + * Set up the MMU-401 SSD tables. The power-on configuration has all stream IDs + * assigned to Non-Secure except some for the DMA-330. Assign those back to the + * Non-Secure world as well, otherwise EL1 may end up erroneously generating + * (untranslated) Secure transactions if it turns the SMMU on. + ******************************************************************************/ +static void init_mmu401(void) +{ + uint32_t reg = mmio_read_32(MMU401_DMA330_BASE + MMU401_SSD_OFFSET); + reg |= 0x1FF; + mmio_write_32(MMU401_DMA330_BASE + MMU401_SSD_OFFSET, reg); +} + +/******************************************************************************* + * Program CSS-NIC400 to allow non-secure access to some CSS regions. + ******************************************************************************/ +static void css_init_nic400(void) +{ + /* Note: This is the NIC-400 device on the CSS */ + mmio_write_32(PLAT_SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(CSS_NIC400_SLAVE_BOOTSECURE), + ~0); +} + +/******************************************************************************* + * Initialize debug configuration. + ******************************************************************************/ +static void init_debug_cfg(void) +{ +#if !DEBUG + /* Set internal drive selection for SPIDEN. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_SET, + 1U << SPIDEN_SEL_SET_SHIFT); + + /* Drive SPIDEN LOW to disable invasive debug of secure state. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_CLR, + 1U << SPIDEN_INT_CLR_SHIFT); + + /* Set internal drive selection for SPNIDEN. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_SET, + 1U << SPNIDEN_SEL_SET_SHIFT); + + /* Drive SPNIDEN LOW to disable non-invasive debug of secure state. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_CLR, + 1U << SPNIDEN_INT_CLR_SHIFT); +#endif +} + +/******************************************************************************* + * Initialize the secure environment. + ******************************************************************************/ +void plat_arm_security_setup(void) +{ + /* Initialize debug configuration */ + init_debug_cfg(); + /* Initialize the TrustZone Controller */ +#ifdef JUNO_TZMP1 + arm_tzc400_setup(PLAT_ARM_TZC_BASE, juno_tzmp1_tzc_regions); + INFO("TZC protected shared memory base address for TZMP usecase: %p\n", + (void *)JUNO_AP_TZC_SHARE_DRAM1_BASE); + INFO("TZC protected shared memory end address for TZMP usecase: %p\n", + (void *)JUNO_AP_TZC_SHARE_DRAM1_END); +#else + arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL); +#endif + /* Do ARM CSS internal NIC setup */ + css_init_nic400(); + /* Do ARM CSS SoC security setup */ + soc_css_security_setup(); + /* Initialize the SMMU SSD tables */ + init_mmu401(); +#ifdef JUNO_TZMP1 + init_dp650(); + init_v550(); +#endif +} + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif diff --git a/plat/arm/board/juno/juno_stack_protector.c b/plat/arm/board/juno/juno_stack_protector.c new file mode 100644 index 0000000..3924af8 --- /dev/null +++ b/plat/arm/board/juno/juno_stack_protector.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/utils.h> +#include <plat/common/plat_trng.h> +#include <platform_def.h> + +u_register_t plat_get_stack_protector_canary(void) +{ + uint64_t entropy; + + if (!plat_get_entropy(&entropy)) { + ERROR("Not enough entropy to initialize canary value\n"); + panic(); + } + + if (sizeof(entropy) == sizeof(u_register_t)) { + return entropy; + } + + return (entropy & 0xffffffffULL) ^ (entropy >> 32); +} diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c new file mode 100644 index 0000000..075f512 --- /dev/null +++ b/plat/arm/board/juno/juno_topology.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/css/css_mhu_doorbell.h> +#include <drivers/arm/css/scmi.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#if CSS_USE_SCMI_SDS_DRIVER +static scmi_channel_plat_info_t juno_scmi_plat_info = { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell, +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &juno_scmi_plat_info; +} + +#endif +/* + * On Juno, the system power level is the highest power level. + * The first entry in the power domain descriptor specifies the + * number of system power domains i.e. 1. + */ +#define JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT + +/* + * The Juno power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr() + * i.e. CLUSTER1 CPUs are allocated indices from 0 to 3 and the higher + * indices for CLUSTER0 CPUs. + */ +static const unsigned char juno_power_domain_tree_desc[] = { + /* No of root nodes */ + JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL, + /* No of children for the root node */ + JUNO_CLUSTER_COUNT, + /* No of children for the first cluster node */ + JUNO_CLUSTER1_CORE_COUNT, + /* No of children for the second cluster node */ + JUNO_CLUSTER0_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the Juno topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return juno_power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return (((mpidr & (u_register_t) 0x100) != 0U) ? + JUNO_CLUSTER1_CORE_COUNT : JUNO_CLUSTER0_CORE_COUNT); +} + +/* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + */ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 2, 3, 4, 5, 0, 1 }; diff --git a/plat/arm/board/juno/juno_trng.c b/plat/arm/board/juno/juno_trng.c new file mode 100644 index 0000000..09552a6 --- /dev/null +++ b/plat/arm/board/juno/juno_trng.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arm_acle.h> +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include <lib/mmio.h> +#include <lib/utils_def.h> +#include <platform_def.h> + +#include <lib/smccc.h> +#include <services/trng_svc.h> +#include <smccc_helpers.h> + +#include <plat/common/platform.h> + +#define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ +#define NRETRIES 5 + +/* initialised to false */ +static bool juno_trng_initialized; + +static bool output_valid(void) +{ + int i; + + for (i = 0; i < NRETRIES; i++) { + uint32_t val; + + val = mmio_read_32(TRNG_BASE + TRNG_STATUS); + if (val & 1U) + return true; + } + return false; /* No output data available. */ +} + +DEFINE_SVC_UUID2(_plat_trng_uuid, + 0x23523c58, 0x7448, 0x4083, 0x9d, 0x16, + 0xe3, 0xfa, 0xb9, 0xf1, 0x73, 0xbc +); +uuid_t plat_trng_uuid; + +static uint32_t crc_value = ~0U; + +/* + * Uses the Trusted Entropy Source peripheral on Juno to return 8 bytes of + * entropy. Returns 'true' when done successfully, 'false' otherwise. + */ +bool plat_get_entropy(uint64_t *out) +{ + uint64_t ret; + + assert(out); + assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out))); + + if (!juno_trng_initialized) { + /* Disable interrupt mode. */ + mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); + /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ + mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); + /* Abort any potentially pending sampling. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 2); + /* Reset TRNG outputs. */ + mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); + + juno_trng_initialized = true; + } + + if (!output_valid()) { + /* Start TRNG. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); + + if (!output_valid()) + return false; + } + + /* CRC each two 32-bit registers together, combine the pairs */ + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 0)); + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 4)); + ret = (uint64_t)crc_value << 32; + + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 8)); + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 12)); + *out = ret | crc_value; + + /* Acknowledge current cycle, clear output registers. */ + mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); + /* Trigger next TRNG cycle. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); + + return true; +} + +void plat_entropy_setup(void) +{ + uint64_t dummy; + + plat_trng_uuid = _plat_trng_uuid; + + /* Initialise the entropy source and trigger RNG generation */ + plat_get_entropy(&dummy); +} diff --git a/plat/arm/board/juno/juno_trusted_boot.c b/plat/arm/board/juno/juno_trusted_boot.c new file mode 100644 index 0000000..25a7470 --- /dev/null +++ b/plat/arm/board/juno/juno_trusted_boot.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#include <drivers/arm/cryptocell/cc_rotpk.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/common_def.h> +#include <plat/common/platform.h> + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + +static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN]; + +extern unsigned char arm_rotpk_header[]; + +/* + * Return the ROTPK hash stored in the registers of Juno board. + */ +static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint8_t *dst; + uint32_t *src, tmp; + unsigned int words, i; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); + dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; + + + /* + * Append the hash from Trusted Root-Key Storage registers. The hash has + * not been written linearly into the registers, so we have to do a bit + * of byte swapping: + * + * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C + * +---------------------------------------------------------------+ + * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | + * +---------------------------------------------------------------+ + * | ... ... | | ... ... | + * | +--------------------+ | +-------+ + * | | | | + * +----------------------------+ +----------------------------+ + * | | | | + * +-------+ | +--------------------+ | + * | | | | + * v v v v + * +---------------------------------------------------------------+ + * | | | + * +---------------------------------------------------------------+ + * 0 15 16 31 + * + * Additionally, we have to access the registers in 32-bit words + */ + words = ARM_ROTPK_HASH_LEN >> 3; + + /* Swap bytes 0-15 (first four registers) */ + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + /* Swap bytes 16-31 (last four registers) */ + src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2); + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags = ROTPK_IS_HASH; + return 0; +} + +#endif + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ +#if ARM_CRYPTOCELL_INTEG + return arm_get_rotpk_info_cc(key_ptr, key_len, flags); +#else + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ + (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) + return arm_get_rotpk_info_dev(key_ptr, key_len, flags); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + return juno_get_rotpk_info_regs(key_ptr, key_len, flags); +#else + return 1; +#endif + +#endif /* ARM_CRYPTOCELL_INTEG */ +} diff --git a/plat/arm/board/juno/juno_tzmp1_def.h b/plat/arm/board/juno/juno_tzmp1_def.h new file mode 100644 index 0000000..4186d02 --- /dev/null +++ b/plat/arm/board/juno/juno_tzmp1_def.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef JUNO_TZMP1_DEF_H +#define JUNO_TZMP1_DEF_H + +/* + * Public memory regions for both protected and non-protected mode + * + * OPTEE shared memory 0xFEE00000 - 0xFEFFFFFF + */ +#define JUNO_AP_TZC_SHARE_DRAM1_SIZE ULL(0x02000000) +#define JUNO_AP_TZC_SHARE_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \ + JUNO_AP_TZC_SHARE_DRAM1_SIZE) +#define JUNO_AP_TZC_SHARE_DRAM1_END (ARM_AP_TZC_DRAM1_BASE - 1) + +/* ARM_MEDIA_FEATURES for MEDIA GPU Protect Mode Test */ +#define JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE 8 /* GPU/DPU protected, VPU outbuf */ +#define JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED 7 /* VPU protected */ +#define JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE 10 /* VPU private (firmware) */ + +#define JUNO_VPU_TZC_PRIV_DRAM1_SIZE ULL(0x02000000) +#define JUNO_VPU_TZC_PRIV_DRAM1_BASE (JUNO_AP_TZC_SHARE_DRAM1_BASE - \ + JUNO_VPU_TZC_PRIV_DRAM1_SIZE) +#define JUNO_VPU_TZC_PRIV_DRAM1_END (JUNO_AP_TZC_SHARE_DRAM1_BASE - 1) + +/* Video input protected buffer follows upper item */ +#define JUNO_VPU_TZC_PROT_DRAM1_SIZE ULL(0x06000000) +#define JUNO_VPU_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PRIV_DRAM1_BASE - \ + JUNO_VPU_TZC_PROT_DRAM1_SIZE) +#define JUNO_VPU_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PRIV_DRAM1_BASE - 1) + +/* Video, graphics and display shares same NSAID and same protected buffer */ +#define JUNO_MEDIA_TZC_PROT_DRAM1_SIZE ULL(0x0e000000) +#define JUNO_MEDIA_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PROT_DRAM1_BASE - \ + JUNO_MEDIA_TZC_PROT_DRAM1_SIZE) +#define JUNO_MEDIA_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PROT_DRAM1_BASE - 1) + +/* Rest of DRAM1 are Non-Secure public buffer */ +#define JUNO_NS_DRAM1_PT1_BASE ARM_DRAM1_BASE +#define JUNO_NS_DRAM1_PT1_END (JUNO_MEDIA_TZC_PROT_DRAM1_BASE - 1) +#define JUNO_NS_DRAM1_PT1_SIZE (JUNO_NS_DRAM1_PT1_END - \ + JUNO_NS_DRAM1_PT1_BASE + 1) + +/* TZC filter flags */ +#define JUNO_MEDIA_TZC_NS_DEV_ACCESS (PLAT_ARM_TZC_NS_DEV_ACCESS | \ + TZC_REGION_ACCESS_RD(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE)) + +/* VPU / GPU /DPU protected access */ +#define JUNO_MEDIA_TZC_PROT_ACCESS \ + (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE) | \ + TZC_REGION_ACCESS_WR(TZC400_NSAID_AP)) + +#define JUNO_VPU_TZC_PROT_ACCESS \ + (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED)) + +#define JUNO_VPU_TZC_PRIV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE)) + +/******************************************************************************* + * Mali-DP650 related constants + ******************************************************************************/ +/* Base address of DP650 */ +#define DP650_BASE 0x6f200000 +/* offset to PROT_NSAID register */ +#define DP650_PROT_NSAID_OFFSET 0x10004 +/* config to PROT_NSAID register */ +#define DP650_PROT_NSAID_CONFIG 0x08008888 + +/******************************************************************************* + * Mali-V550 related constants + ******************************************************************************/ +/* Base address of V550 */ +#define V550_BASE 0x6f030000 +/* offset to PROTCTRL register */ +#define V550_PROTCTRL_OFFSET 0x0040 +/* config to PROTCTRL register */ +#define V550_PROTCTRL_CONFIG 0xa8700000 + +#endif /* JUNO_TZMP1_DEF_H */ diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk new file mode 100644 index 0000000..2c84eb3 --- /dev/null +++ b/plat/arm/board/juno/platform.mk @@ -0,0 +1,201 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +JUNO_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \ + plat/arm/common/arm_cci.c + +JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \ + plat/arm/board/juno/juno_security.c \ + plat/arm/board/juno/juno_trng.c \ + plat/arm/common/arm_tzc400.c + +ifneq (${ENABLE_STACK_PROTECTOR}, 0) +JUNO_SECURITY_SOURCES += plat/arm/board/juno/juno_stack_protector.c +endif + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +PLAT_INCLUDES := -Iplat/arm/board/juno/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/${ARCH}/juno_helpers.S \ + plat/arm/board/juno/juno_common.c + +# Flag to enable support for AArch32 state on JUNO +JUNO_AARCH32_EL3_RUNTIME := 0 +$(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME)) +$(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME)) + +# Flag to enable support for TZMP1 on JUNO +JUNO_TZMP1 := 0 +$(eval $(call assert_boolean,JUNO_TZMP1)) +ifeq (${JUNO_TZMP1}, 1) +$(eval $(call add_define,JUNO_TZMP1)) +endif + +TRNG_SUPPORT := 1 + +ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1) +# Include BL32 in FIP +NEED_BL32 := yes +# BL31 is not required +override BL31_SOURCES = + +# The BL32 needs to be built separately invoking the AARCH32 compiler and +# be specifed via `BL32` build option. + ifneq (${ARCH}, aarch32) + override BL32_SOURCES = + endif +endif + +ifeq (${ARCH},aarch64) +BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + plat/arm/board/juno/juno_err.c \ + plat/arm/board/juno/juno_bl1_setup.c \ + drivers/arm/sp805/sp805.c \ + ${JUNO_INTERCONNECT_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +BL2_SOURCES += drivers/arm/sp805/sp805.c \ + lib/utils/mem_region.c \ + plat/arm/board/juno/juno_err.c \ + plat/arm/board/juno/juno_bl2_setup.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${JUNO_SECURITY_SOURCES} + +BL2U_SOURCES += ${JUNO_SECURITY_SOURCES} + +BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/utils/mem_region.c \ + lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + plat/arm/board/juno/juno_bl31_setup.c \ + plat/arm/board/juno/juno_pm.c \ + plat/arm/board/juno/juno_topology.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${JUNO_GIC_SOURCES} \ + ${JUNO_INTERCONNECT_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${CSS_USE_SCMI_SDS_DRIVER},1) +BL1_SOURCES += drivers/arm/css/sds/sds.c +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += plat/arm/board/juno/juno_trusted_boot.c +BL2_SOURCES += plat/arm/board/juno/juno_trusted_boot.c +endif + +endif + +ifneq (${RESET_TO_BL31},0) + $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \ + Please set RESET_TO_BL31 to 0.") +endif + +ifeq ($(USE_ROMLIB),1) +all : bl1_romlib.bin +endif + +bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin romlib.bin + @echo "Building combined BL1 and ROMLIB binary for Juno $@" + ./lib/romlib/gen_combined_bl1_romlib.sh -o bl1_romlib.bin $(BUILD_PLAT) + +# Errata workarounds for Cortex-A53: +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_826319 := 1 +ERRATA_A53_827319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +# Errata workarounds for Cortex-A57: +ERRATA_A57_806969 := 0 +ERRATA_A57_813419 := 1 +ERRATA_A57_813420 := 1 +ERRATA_A57_814670 := 1 +ERRATA_A57_817169 := 1 +ERRATA_A57_826974 := 1 +ERRATA_A57_826977 := 1 +ERRATA_A57_828024 := 1 +ERRATA_A57_829520 := 1 +ERRATA_A57_833471 := 1 +ERRATA_A57_859972 := 0 + +# Errata workarounds for Cortex-A72: +ERRATA_A72_859971 := 0 + +# Enable option to skip L1 data cache flush during the Cortex-A57 cluster +# power down sequence +SKIP_A57_L1_FLUSH_PWR_DWN := 1 + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +# Enable the dynamic translation tables library. +ifeq (${ARCH},aarch32) + ifeq (${RESET_TO_SP_MIN},1) + BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +else + ifeq (${RESET_TO_BL31},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +endif + +ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1) + BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + else + BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + endif +endif + +BL1_CPPFLAGS += -march=armv8-a+crc +BL2_CPPFLAGS += -march=armv8-a+crc +BL2U_CPPFLAGS += -march=armv8-a+crc +BL31_CPPFLAGS += -march=armv8-a+crc +BL32_CPPFLAGS += -march=armv8-a+crc + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts \ + plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts \ + fdts/${PLAT}.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb +HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config,${HW_CONFIG})) + +include plat/arm/board/common/board_common.mk +include plat/arm/common/arm_common.mk +include plat/arm/soc/common/soc_css.mk +include plat/arm/css/common/css_common.mk diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk new file mode 100644 index 0000000..b3471c1 --- /dev/null +++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to JUNO platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/cpus/aarch32/cortex_a53.S \ + lib/cpus/aarch32/cortex_a57.S \ + lib/cpus/aarch32/cortex_a72.S \ + lib/utils/mem_region.c \ + plat/arm/board/juno/juno_pm.c \ + plat/arm/board/juno/juno_topology.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + plat/arm/soc/common/soc_css_security.c \ + ${JUNO_GIC_SOURCES} \ + ${JUNO_INTERCONNECT_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +include plat/arm/common/sp_min/arm_sp_min.mk +include plat/arm/css/common/sp_min/css_sp_min.mk diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk new file mode 100644 index 0000000..be75c4d --- /dev/null +++ b/plat/arm/board/juno/tsp/tsp-juno.mk @@ -0,0 +1,12 @@ +# +# Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/arm/board/juno/juno_topology.c \ + plat/arm/css/common/css_topology.c \ + ${JUNO_GIC_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +include plat/arm/common/tsp/arm_tsp.mk diff --git a/plat/arm/board/morello/aarch64/morello_helper.S b/plat/arm/board/morello/aarch64/morello_helper.S new file mode 100644 index 0000000..60470a8 --- /dev/null +++ b/plat/arm/board/morello/aarch64/morello_helper.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <cpu_macros.S> +#include <rainier.h> + +#include <platform_def.h> + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Helper function to calculate the core position. + * ((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * MORELLO_MAX_CPUS_PER_CLUSTER * MORELLO_MAX_PE_PER_CPU) + + * (CPUId * MORELLO_MAX_PE_PER_CPU) + ThreadId + * + * which can be simplified as: + * + * (((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * MORELLO_MAX_CPUS_PER_CLUSTER + CPUId) * MORELLO_MAX_PE_PER_CPU) + + * ThreadId + * ------------------------------------------------------ + */ + +func plat_arm_calc_core_pos + mov x4, x0 + + /* + * The MT bit in MPIDR is always set for morello and the + * affinity level 0 corresponds to thread affinity level. + */ + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #MORELLO_MAX_CLUSTERS_PER_CHIP + madd x2, x3, x4, x2 + mov x4, #MORELLO_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x4, #MORELLO_MAX_PE_PER_CPU + madd x0, x1, x4, x0 + ret +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/morello/fdts/morello_fw_config.dts b/plat/arm/board/morello/fdts/morello_fw_config.dts new file mode 100644 index 0000000..c47bae5 --- /dev/null +++ b/plat/arm/board/morello/fdts/morello_fw_config.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/morello/fdts/morello_nt_fw_config.dts b/plat/arm/board/morello/fdts/morello_nt_fw_config.dts new file mode 100644 index 0000000..e730d34 --- /dev/null +++ b/plat/arm/board/morello/fdts/morello_nt_fw_config.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,morello"; + + /* + * Place holder for platform-info node with default values. + * The values will be set to the correct values during + * the BL2 stage of boot. + */ + platform-info { + local-ddr-size = <0x0 0x0>; +#ifdef TARGET_PLATFORM_SOC + remote-ddr-size = <0x0 0x0>; + remote-chip-count = <0x0>; + multichip-mode = <0x0>; + scc-config = <0x0>; +#endif + }; +}; diff --git a/plat/arm/board/morello/fdts/morello_tb_fw_config.dts b/plat/arm/board/morello/fdts/morello_tb_fw_config.dts new file mode 100644 index 0000000..305a818 --- /dev/null +++ b/plat/arm/board/morello/fdts/morello_tb_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/morello/include/plat_macros.S b/plat/arm/board/morello/include/plat_macros.S new file mode 100644 index 0000000..195be84 --- /dev/null +++ b/plat/arm/board/morello/include/plat_macros.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <css_macros.S> + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/arm/board/morello/include/platform_def.h b/plat/arm/board/morello/include/platform_def.h new file mode 100644 index 0000000..08e2d60 --- /dev/null +++ b/plat/arm/board/morello/include/platform_def.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_def.h> +#include <plat/arm/css/common/css_def.h> + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE ULL(0x2A400000) +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ U(50000000) + +/* IOFPGA UART0 */ +#define PLAT_ARM_RUN_UART_BASE ULL(0x1C090000) +#define PLAT_ARM_RUN_UART_CLK_IN_HZ U(24000000) + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000) + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +#define PLAT_ARM_FLASH_IMAGE_BASE ULL(0x1A000000) +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE ULL(0x01000000) + +#define PLAT_ARM_NVM_BASE ULL(0x1A000000) +#define PLAT_ARM_NVM_SIZE ULL(0x01000000) + +#if defined NS_BL1U_BASE +#undef NS_BL1U_BASE +#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x00800000)) +#endif + +/* + * There are no non-volatile counters in morello, these macros points + * to unused addresses. + */ +#define SOC_TRUSTED_NVCTR_BASE ULL(0x7FE70000) +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + U(0x0000)) +#define TFW_NVCTR_SIZE U(4) +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + U(0x0004)) +#define NTFW_CTR_SIZE U(4) + +/* + * To access the complete DDR memory along with remote chip's DDR memory, + * which is at 4 TB offset, physical and virtual address space limits are + * extended to 43-bits. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43) + +#if CSS_USE_SCMI_SDS_DRIVER +#define MORELLO_SCMI_PAYLOAD_BASE ULL(0x45400000) +#else +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE ULL(0x45400000) +#endif + +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00080000) + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xC000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xE000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE U(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE U(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE UL(0x1D000) +#else +# define PLAT_ARM_MAX_BL2_SIZE UL(0x14000) +#endif + +#define PLAT_ARM_MAX_BL31_SIZE UL(0x3B000) + +/******************************************************************************* + * MORELLO topology related constants + ******************************************************************************/ +#define MORELLO_MAX_CPUS_PER_CLUSTER U(2) +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define PLAT_MORELLO_CHIP_COUNT U(1) +#define MORELLO_MAX_CLUSTERS_PER_CHIP U(2) +#define MORELLO_MAX_PE_PER_CPU U(1) + +#define PLATFORM_CORE_COUNT (PLAT_MORELLO_CHIP_COUNT * \ + PLAT_ARM_CLUSTER_COUNT * \ + MORELLO_MAX_CPUS_PER_CLUSTER * \ + MORELLO_MAX_PE_PER_CPU) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3 + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if IMAGE_BL1 || IMAGE_BL31 +# define PLAT_ARM_MMAP_ENTRIES U(6) +# define MAX_XLAT_TABLES U(7) +#else +# define PLAT_ARM_MMAP_ENTRIES U(5) +# define MAX_XLAT_TABLES U(6) +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x440) +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE UL(0x400) +#elif defined(IMAGE_BL31) +# if SPM_MM +# define PLATFORM_STACK_SIZE UL(0x500) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE UL(0x440) +#endif + +#define PLAT_ARM_NSTIMER_FRAME_ID U(0) + +#define PLAT_ARM_TRUSTED_ROM_BASE U(0x0) +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00020000) /* 128KB */ + +#define PLAT_ARM_NSRAM_BASE ULL(0x06000000) +#define PLAT_ARM_NSRAM_SIZE UL(0x00010000) /* 64KB */ + +#define PLAT_CSS_MHU_BASE UL(0x45000000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE +#define PLAT_MAX_PWR_LVL U(2) + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#define MORELLO_DEVICE_BASE ULL(0x08000000) +#define MORELLO_DEVICE_SIZE ULL(0x48000000) + +/*Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(1000) + +#define MORELLO_MAP_DEVICE MAP_REGION_FLAT( \ + MORELLO_DEVICE_BASE, \ + MORELLO_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \ + ARM_DRAM1_BASE, \ + ARM_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/morello/morello_bl1_setup.c b/plat/arm/board/morello/morello_bl1_setup.c new file mode 100644 index 0000000..9155542 --- /dev/null +++ b/plat/arm/board/morello/morello_bl1_setup.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ + +void soc_css_init_nic400(void) +{ +} + +void soc_css_init_pcie(void) +{ +} diff --git a/plat/arm/board/morello/morello_bl2_setup.c b/plat/arm/board/morello/morello_bl2_setup.c new file mode 100644 index 0000000..da1f7ae --- /dev/null +++ b/plat/arm/board/morello/morello_bl2_setup.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/css/sds.h> +#include <lib/mmio.h> +#include <lib/utils.h> +#include <plat/arm/common/plat_arm.h> + +#include "morello_def.h" +#include <platform_def.h> + +#ifdef TARGET_PLATFORM_FVP +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size + * - Local DDR size in bytes, DDR memory in main board + */ +struct morello_plat_info { + uint64_t local_ddr_size; +} __packed; +#else +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which is an information about multichip setup + * - Local DDR size in bytes, DDR memory in main board + * - Remote DDR size in bytes, DDR memory in remote board + * - remote_chip_count + * - multichip mode + * - scc configuration + */ +struct morello_plat_info { + uint64_t local_ddr_size; + uint64_t remote_ddr_size; + uint8_t remote_chip_count; + bool multichip_mode; + uint32_t scc_config; +} __packed; +#endif + +/* Compile time assertion to ensure the size of structure is 18 bytes */ +CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE, + assert_invalid_plat_info_size); + +#ifdef TARGET_PLATFORM_SOC +/* + * Morello platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC-Bing. Zeroing out several gigabytes of + * memory from SCP is quite time consuming so the following function + * is added to zero out the DDR memory from application processor which is + * much faster compared to SCP. + */ + +static void dmc_ecc_setup(struct morello_plat_info *plat_info) +{ + uint64_t dram2_size; + uint32_t val; + uint64_t tag_mem_base; + uint64_t usable_mem_size; + + INFO("Total DIMM size: %uGB\n", + (uint32_t)(plat_info->local_ddr_size / 0x40000000)); + + assert(plat_info->local_ddr_size > ARM_DRAM1_SIZE); + dram2_size = plat_info->local_ddr_size - ARM_DRAM1_SIZE; + + INFO("Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF\n"); + zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + + INFO("Zeroing DDR memory range 0x%llx - 0x%llx\n", + ARM_DRAM2_BASE, ARM_DRAM2_BASE + dram2_size); + zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); + flush_dcache_range(ARM_DRAM2_BASE, dram2_size); + + /* Clear previous ECC errors while zeroing out the memory */ + val = mmio_read_32(MORELLO_DMC0_ERR2STATUS_REG); + mmio_write_32(MORELLO_DMC0_ERR2STATUS_REG, val); + + val = mmio_read_32(MORELLO_DMC1_ERR2STATUS_REG); + mmio_write_32(MORELLO_DMC1_ERR2STATUS_REG, val); + + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); + mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); + + while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_CONFIG) { + continue; + } + + while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_CONFIG) { + continue; + } + + /* Configure Bing client/server mode based on SCC configuration */ + if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) { + INFO("Configuring DMC Bing in client mode\n"); + usable_mem_size = plat_info->local_ddr_size - + (plat_info->local_ddr_size / 128ULL); + + /* Linear DDR address */ + tag_mem_base = usable_mem_size; + tag_mem_base = tag_mem_base / 4; + + /* Reverse translation */ + if (tag_mem_base < ARM_DRAM1_BASE) { + tag_mem_base += ARM_DRAM1_BASE; + } else { + tag_mem_base = tag_mem_base - ARM_DRAM1_BASE + + ARM_DRAM2_BASE; + } + + mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x1); + mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x1); + mmio_write_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x1); + mmio_write_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x1); + + if (plat_info->scc_config & MORELLO_SCC_C1_TAG_CACHE_EN_MASK) { + mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x2); + mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x2); + INFO("C1 Tag Cache Enabled\n"); + } + + if (plat_info->scc_config & MORELLO_SCC_C2_TAG_CACHE_EN_MASK) { + mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x4); + mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x4); + INFO("C2 Tag Cache Enabled\n"); + } + + mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL, + (uint32_t)tag_mem_base); + mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL, + (uint32_t)tag_mem_base); + mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL2, + (uint32_t)(tag_mem_base >> 32)); + mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL2, + (uint32_t)(tag_mem_base >> 32)); + + mmio_setbits_32(MORELLO_DMC0_MEM_ACCESS_CTL, + MORELLO_DMC_MEM_ACCESS_DIS); + mmio_setbits_32(MORELLO_DMC1_MEM_ACCESS_CTL, + MORELLO_DMC_MEM_ACCESS_DIS); + + INFO("Tag base set to 0x%lx\n", tag_mem_base); + plat_info->local_ddr_size = usable_mem_size; + } else { + INFO("Configuring DMC Bing in server mode\n"); + mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x0); + mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x0); + } + + INFO("Enabling ECC on DMCs\n"); + /* Enable ECC in DMCs */ + mmio_setbits_32(MORELLO_DMC0_ERR0CTLR0_REG, + MORELLO_DMC_ERR0CTLR0_ECC_EN); + mmio_setbits_32(MORELLO_DMC1_ERR0CTLR0_REG, + MORELLO_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); + mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); + + while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_READY) { + continue; + } + + while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_READY) { + continue; + } +} +#endif + +void bl2_platform_setup(void) +{ + int ret; + struct morello_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed. ret:%d\n", ret); + panic(); + } + + ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID, + MORELLO_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + MORELLO_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS. ret:%d\n", ret); + panic(); + } + + /* Validate plat_info SDS */ +#ifdef TARGET_PLATFORM_FVP + if (plat_info.local_ddr_size == 0U) { +#else + if ((plat_info.local_ddr_size == 0U) + || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT) + ) { +#endif + ERROR("platform info SDS is corrupted\n"); + panic(); + } + +#ifdef TARGET_PLATFORM_SOC + dmc_ecc_setup(&plat_info); +#endif + arm_bl2_platform_setup(); +} diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c new file mode 100644 index 0000000..a044212 --- /dev/null +++ b/plat/arm/board/morello/morello_bl31_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/css/css_mhu_doorbell.h> +#include <drivers/arm/css/scmi.h> +#include <plat/arm/common/plat_arm.h> + +#include "morello_def.h" +#include <platform_def.h> + +static scmi_channel_plat_info_t morello_scmi_plat_info = { + .scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &morello_scmi_plat_info; +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} + +void bl31_platform_setup(void) +{ + arm_bl31_platform_setup(); +} diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h new file mode 100644 index 0000000..f154924 --- /dev/null +++ b/plat/arm/board/morello/morello_def.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MORELLO_DEF_H +#define MORELLO_DEF_H + +/* Non-secure SRAM MMU mapping */ +#define MORELLO_NS_SRAM_BASE UL(0x06000000) +#define MORELLO_NS_SRAM_SIZE UL(0x00010000) +#define MORELLO_MAP_NS_SRAM MAP_REGION_FLAT( \ + MORELLO_NS_SRAM_BASE, \ + MORELLO_NS_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* SDS Platform information defines */ +#define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID U(8) +#define MORELLO_SDS_PLATFORM_INFO_OFFSET U(0) +#ifdef TARGET_PLATFORM_FVP +# define MORELLO_SDS_PLATFORM_INFO_SIZE U(8) +#else +# define MORELLO_SDS_PLATFORM_INFO_SIZE U(22) +#endif +#define MORELLO_MAX_DDR_CAPACITY U(0x1000000000) +#define MORELLO_MAX_REMOTE_CHIP_COUNT U(16) + +#define MORELLO_SCC_SERVER_MODE U(0) +#define MORELLO_SCC_CLIENT_MODE_MASK U(1) +#define MORELLO_SCC_C1_TAG_CACHE_EN_MASK U(4) +#define MORELLO_SCC_C2_TAG_CACHE_EN_MASK U(8) + +/* Base address of non-secure SRAM where Platform information will be filled */ +#define MORELLO_PLATFORM_INFO_BASE UL(0x06000000) + +/* DMC memory status registers */ +#define MORELLO_DMC0_MEMC_STATUS_REG UL(0x4E000000) +#define MORELLO_DMC1_MEMC_STATUS_REG UL(0x4E100000) + +#define MORELLO_DMC_MEMC_STATUS_MASK U(7) + +/* DMC memory command registers */ +#define MORELLO_DMC0_MEMC_CMD_REG UL(0x4E000008) +#define MORELLO_DMC1_MEMC_CMD_REG UL(0x4E100008) + +/* DMC capability control register */ +#define MORELLO_DMC0_CAP_CTRL_REG UL(0x4E000D00) +#define MORELLO_DMC1_CAP_CTRL_REG UL(0x4E100D00) + +/* DMC tag cache control register */ +#define MORELLO_DMC0_TAG_CACHE_CTL UL(0x4E000D04) +#define MORELLO_DMC1_TAG_CACHE_CTL UL(0x4E100D04) + +/* DMC tag cache config register */ +#define MORELLO_DMC0_TAG_CACHE_CFG UL(0x4E000D08) +#define MORELLO_DMC1_TAG_CACHE_CFG UL(0x4E100D08) + +/* DMC memory access control register */ +#define MORELLO_DMC0_MEM_ACCESS_CTL UL(0x4E000D0C) +#define MORELLO_DMC1_MEM_ACCESS_CTL UL(0x4E100D0C) + +#define MORELLO_DMC_MEM_ACCESS_DIS (1UL << 16) + +/* DMC memory address control register */ +#define MORELLO_DMC0_MEM_ADDR_CTL UL(0x4E000D10) +#define MORELLO_DMC1_MEM_ADDR_CTL UL(0x4E100D10) + +/* DMC memory address control 2 register */ +#define MORELLO_DMC0_MEM_ADDR_CTL2 UL(0x4E000D14) +#define MORELLO_DMC1_MEM_ADDR_CTL2 UL(0x4E100D14) + +/* DMC special control register */ +#define MORELLO_DMC0_SPL_CTL_REG UL(0x4E000D18) +#define MORELLO_DMC1_SPL_CTL_REG UL(0x4E100D18) + +/* DMC ERR0CTLR0 registers */ +#define MORELLO_DMC0_ERR0CTLR0_REG UL(0x4E000708) +#define MORELLO_DMC1_ERR0CTLR0_REG UL(0x4E100708) + +/* DMC ECC in ERR0CTLR0 register */ +#define MORELLO_DMC_ERR0CTLR0_ECC_EN U(9) + +/* DMC ERR2STATUS register */ +#define MORELLO_DMC0_ERR2STATUS_REG UL(0x4E000790) +#define MORELLO_DMC1_ERR2STATUS_REG UL(0x4E100790) + +/* DMC memory commands */ +#define MORELLO_DMC_MEMC_CMD_CONFIG U(0) +#define MORELLO_DMC_MEMC_CMD_READY U(3) + +#endif /* MORELLO_DEF_H */ diff --git a/plat/arm/board/morello/morello_err.c b/plat/arm/board/morello/morello_err.c new file mode 100644 index 0000000..4d20a09 --- /dev/null +++ b/plat/arm/board/morello/morello_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * morello error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/morello/morello_image_load.c b/plat/arm/board/morello/morello_image_load.c new file mode 100644 index 0000000..52d46f3 --- /dev/null +++ b/plat/arm/board/morello/morello_image_load.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/arm/css/sds.h> +#include <libfdt.h> + +#include "morello_def.h" +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#ifdef TARGET_PLATFORM_FVP +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which is an information about multichip setup + * - Local DDR size in bytes, DDR memory in main board + */ +struct morello_plat_info { + uint64_t local_ddr_size; +} __packed; +#else +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which is an information about multichip setup + * - Local DDR size in bytes, DDR memory in main board + * - Remote DDR size in bytes, DDR memory in remote board + * - remote_chip_count + * - multichip mode + * - scc configuration + */ +struct morello_plat_info { + uint64_t local_ddr_size; + uint64_t remote_ddr_size; + uint8_t remote_chip_count; + bool multichip_mode; + uint32_t scc_config; +} __packed; +#endif + +/* In client mode, a part of the DDR memory is reserved for Tag bits. + * Calculate the usable memory size after subtracting the Tag memory. + */ +static inline uint64_t get_mem_client_mode(uint64_t size) +{ + return (size - (size / 128ULL)); +} + +/******************************************************************************* + * This function inserts Platform information via device tree nodes as, + * platform-info { + * local-ddr-size = <0x0 0x0>; + *#ifdef TARGET_PLATFORM_SOC + * remote-ddr-size = <0x0 0x0>; + * remote-chip-count = <0x0>; + * multichip-mode = <0x0>; + * scc-config = <0x0>; + *#endif + * }; + ******************************************************************************/ +static int plat_morello_append_config_node(struct morello_plat_info *plat_info) +{ + bl_mem_params_node_t *mem_params; + void *fdt; + int nodeoffset, err; + uint64_t usable_mem_size; + + usable_mem_size = plat_info->local_ddr_size; + + mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); + if (mem_params == NULL) { + ERROR("NT_FW CONFIG base address is NULL\n"); + return -1; + } + + fdt = (void *)(mem_params->image_info.image_base); + + /* Check the validity of the fdt */ + if (fdt_check_header(fdt) != 0) { + ERROR("Invalid NT_FW_CONFIG DTB passed\n"); + return -1; + } + + nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info"); + if (nodeoffset < 0) { + ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n"); + return -1; + } + +#ifdef TARGET_PLATFORM_SOC + err = fdt_setprop_u64(fdt, nodeoffset, "remote-ddr-size", + plat_info->remote_ddr_size); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "remote-chip-count", + plat_info->remote_chip_count); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set remote-chip-count\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode", + plat_info->multichip_mode); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "scc-config", + plat_info->scc_config); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set scc-config\n"); + return -1; + } + + if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) { + usable_mem_size = get_mem_client_mode(plat_info->local_ddr_size); + } +#endif + err = fdt_setprop_u64(fdt, nodeoffset, "local-ddr-size", + usable_mem_size); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n"); + return -1; + } + + flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size); + + return 0; +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + int ret; + struct morello_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed. ret:%d\n", ret); + panic(); + } + + ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID, + MORELLO_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + MORELLO_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS. ret:%d\n", ret); + panic(); + } + + /* Validate plat_info SDS */ +#ifdef TARGET_PLATFORM_FVP + if (plat_info.local_ddr_size == 0U) { +#else + if ((plat_info.local_ddr_size == 0U) + || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT) + ){ +#endif + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + ret = plat_morello_append_config_node(&plat_info); + if (ret != 0) { + panic(); + } + + return arm_get_next_bl_params(); +} diff --git a/plat/arm/board/morello/morello_interconnect.c b/plat/arm/board/morello/morello_interconnect.c new file mode 100644 index 0000000..d941bfe --- /dev/null +++ b/plat/arm/board/morello/morello_interconnect.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/* + * For MORELLO which supports FCM (with automatic interconnect enter/exit), + * we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/plat/arm/board/morello/morello_plat.c b/plat/arm/board/morello/morello_plat.c new file mode 100644 index 0000000..1da0ff9 --- /dev/null +++ b/plat/arm/board/morello/morello_plat.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <drivers/arm/sbsa.h> +#include <plat/arm/common/plat_arm.h> + +#include "morello_def.h" + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MORELLO_MAP_DEVICE, + MORELLO_MAP_NS_SRAM, + ARM_MAP_DRAM1, + ARM_MAP_DRAM2, + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MORELLO_MAP_DEVICE, + MORELLO_MAP_NS_SRAM, + {0} +}; +#endif + +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MORELLO_MAP_DEVICE, + MORELLO_MAP_NS_SRAM, + ARM_MAP_DRAM1, + ARM_MAP_DRAM2, +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/plat/arm/board/morello/morello_security.c b/plat/arm/board/morello/morello_security.c new file mode 100644 index 0000000..a388a80 --- /dev/null +++ b/plat/arm/board/morello/morello_security.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * TZC programming is currently not done. + */ +void plat_arm_security_setup(void) +{ +} diff --git a/plat/arm/board/morello/morello_topology.c b/plat/arm/board/morello/morello_topology.c new file mode 100644 index 0000000..ef2f753 --- /dev/null +++ b/plat/arm/board/morello/morello_topology.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/cassert.h> +#include <plat/arm/common/plat_arm.h> + +/* Compile time assertion to ensure the core count is 4 */ +CASSERT(PLATFORM_CORE_COUNT == 4U, assert_invalid_platform_core_count); + +/* Topology */ +typedef struct morello_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} morello_topology_t; + +/* + * The power domain tree descriptor. The cluster power domains are + * arranged so that when the PSCI generic code creates the power domain tree, + * the indices of the CPU power domain nodes it allocates match the linear + * indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char morello_pd_tree_desc[] = { + PLAT_MORELLO_CHIP_COUNT, + PLAT_ARM_CLUSTER_COUNT, + MORELLO_MAX_CPUS_PER_CLUSTER, + MORELLO_MAX_CPUS_PER_CLUSTER, +}; + +/* Topology configuration for morello */ +const morello_topology_t morello_topology = { + .power_tree = morello_pd_tree_desc, + .plat_cluster_core_count = MORELLO_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return morello_topology.power_tree; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return morello_topology.plat_cluster_core_count; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3}; diff --git a/plat/arm/board/morello/morello_trusted_boot.c b/plat/arm/board/morello/morello_trusted_boot.c new file mode 100644 index 0000000..f9bc009 --- /dev/null +++ b/plat/arm/board/morello/morello_trusted_boot.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = MORELLO_FW_NVCTR_VAL; + + return 0; +} + +/* + * Store a new non-volatile counter value. By default on ARM development + * platforms, the non-volatile counters are RO and cannot be modified. We expect + * the values in the certificates to always match the RO values so that this + * function is never called. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk new file mode 100644 index 0000000..156b7ea --- /dev/null +++ b/plat/arm/board/morello/platform.mk @@ -0,0 +1,110 @@ +# +# Copyright (c) 2020-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Making sure the Morello platform type is specified +ifeq ($(filter ${TARGET_PLATFORM}, fvp soc),) + $(error TARGET_PLATFORM must be fvp or soc) +endif + +MORELLO_BASE := plat/arm/board/morello + +INTERCONNECT_SOURCES := ${MORELLO_BASE}/morello_interconnect.c + +PLAT_INCLUDES := -I${MORELLO_BASE}/include + +MORELLO_CPU_SOURCES := lib/cpus/aarch64/rainier.S + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +MORELLO_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c \ + +PLAT_BL_COMMON_SOURCES := ${MORELLO_BASE}/morello_plat.c \ + ${MORELLO_BASE}/aarch64/morello_helper.S + +BL1_SOURCES := ${MORELLO_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${MORELLO_BASE}/morello_err.c \ + ${MORELLO_BASE}/morello_trusted_boot.c \ + ${MORELLO_BASE}/morello_bl1_setup.c \ + drivers/arm/sbsa/sbsa.c + +BL2_SOURCES := ${MORELLO_BASE}/morello_security.c \ + ${MORELLO_BASE}/morello_err.c \ + ${MORELLO_BASE}/morello_trusted_boot.c \ + ${MORELLO_BASE}/morello_bl2_setup.c \ + ${MORELLO_BASE}/morello_image_load.c \ + lib/utils/mem_region.c \ + drivers/arm/css/sds/sds.c + +BL31_SOURCES := ${MORELLO_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${MORELLO_GIC_SOURCES} \ + ${MORELLO_BASE}/morello_bl31_setup.c \ + ${MORELLO_BASE}/morello_topology.c \ + ${MORELLO_BASE}/morello_security.c \ + drivers/arm/css/sds/sds.c + +FDT_SOURCES += fdts/morello-${TARGET_PLATFORM}.dts \ + ${MORELLO_BASE}/fdts/morello_fw_config.dts \ + ${MORELLO_BASE}/fdts/morello_tb_fw_config.dts \ + ${MORELLO_BASE}/fdts/morello_nt_fw_config.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/morello_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/morello_tb_fw_config.dtb +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/morello_nt_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +MORELLO_FW_NVCTR_VAL := 0 +TFW_NVCTR_VAL := ${MORELLO_FW_NVCTR_VAL} +NTFW_NVCTR_VAL := ${MORELLO_FW_NVCTR_VAL} + +# TF-A not required to load the SCP Images +override CSS_LOAD_SCP_IMAGES := 0 + +override NEED_BL2U := no + +# 32 bit mode not supported +override CTX_INCLUDE_AARCH32_REGS := 0 + +override ARM_PLAT_MT := 1 + +override ARM_BL31_IN_DRAM := 1 + +# Errata workarounds: +ERRATA_N1_1868343 := 1 + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# When building for systems with hardware-assisted coherency, there's no need to +# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too. +USE_COHERENT_MEM := 0 + +# Add TARGET_PLATFORM to differentiate between Morello FVP and Morello SoC platform +$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM}))) + +# Add MORELLO_FW_NVCTR_VAL +$(eval $(call add_define,MORELLO_FW_NVCTR_VAL)) + +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S new file mode 100644 index 0000000..3da55b6 --- /dev/null +++ b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <neoverse_n1.h> +#include <cpu_macros.S> +#include <platform_def.h> + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Helper function to calculate the core position. + * ((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) + + * (CPUId * N1SDP_MAX_PE_PER_CPU) + ThreadId + * + * which can be simplified as: + * + * (((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) * N1SDP_MAX_PE_PER_CPU) + + * ThreadId + * ------------------------------------------------------ + */ + +func plat_arm_calc_core_pos + mov x4, x0 + + /* + * The MT bit in MPIDR is always set for n1sdp and the + * affinity level 0 corresponds to thread affinity level. + */ + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #N1SDP_MAX_CLUSTERS_PER_CHIP + madd x2, x3, x4, x2 + mov x4, #N1SDP_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x4, #N1SDP_MAX_PE_PER_CPU + madd x0, x1, x4, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ + +func plat_reset_handler + jump_if_cpu_midr NEOVERSE_N1_MIDR, N1 + ret + + /* ----------------------------------------------------- + * Disable CPU power down bit in power control register + * ----------------------------------------------------- + */ +N1: + mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1 + bic x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK + msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts new file mode 100644 index 0000000..700b900 --- /dev/null +++ b/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + tos_fw-config { + load-address = <0x0 0x4001600>; + max-size = <0x1000>; + id = <TOS_FW_CONFIG_ID>; + }; + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts new file mode 100644 index 0000000..da5e04d --- /dev/null +++ b/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,n1sdp"; + + /* + * Place holder for platform-info node with default values. + * The values will be set to the correct values during + * the BL2 stage of boot. + */ + platform-info { + multichip-mode = <0x0>; + secondary-chip-count = <0x0>; + local-ddr-size = <0x0>; + remote-ddr-size = <0x0>; + }; +};
\ No newline at end of file diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts b/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts new file mode 100644 index 0000000..ed87080 --- /dev/null +++ b/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + /* + * BL32 image details needed by SPMC + * + * Note: + * binary_size: size of BL32 + TOS_FW_CONFIG + */ + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x0>; + exec_state = <0x0>; + load_address = <0x0 0x08000000>; + entrypoint = <0x0 0x08000000>; + binary_size = <0x2000000>; + }; + +}; diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts new file mode 100644 index 0000000..e5ffba3 --- /dev/null +++ b/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/n1sdp/include/plat_macros.S b/plat/arm/board/n1sdp/include/plat_macros.S new file mode 100644 index 0000000..521bcc3 --- /dev/null +++ b/plat/arm/board/n1sdp/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <css_macros.S> + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h new file mode 100644 index 0000000..b3799a7 --- /dev/null +++ b/plat/arm/board/n1sdp/include/platform_def.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_def.h> +#include <plat/arm/css/common/css_def.h> + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x2A400000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ 50000000 + +/* IOFPGA UART0 */ +#define PLAT_ARM_RUN_UART_BASE 0x1C090000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ 24000000 + +#define PLAT_ARM_SP_MIN_RUN_UART_BASE 0x2A410000 +#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ 50000000 + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000) + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +#define PLAT_ARM_FLASH_IMAGE_BASE 0x18200000 +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE 0x00800000 + +#define PLAT_ARM_NVM_BASE 0x18200000 +#define PLAT_ARM_NVM_SIZE 0x00800000 + +#if defined NS_BL1U_BASE +# undef NS_BL1U_BASE +# define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x00800000)) +#endif + +/* Non-volatile counters */ +#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000 +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE) +#define TFW_NVCTR_SIZE U(4) +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004) +#define NTFW_CTR_SIZE U(4) + +/* N1SDP remote chip at 4 TB offset */ +#define PLAT_ARM_REMOTE_CHIP_OFFSET (ULL(1) << 42) + +#define N1SDP_REMOTE_DRAM1_BASE ARM_DRAM1_BASE + \ + PLAT_ARM_REMOTE_CHIP_OFFSET +#define N1SDP_REMOTE_DRAM1_SIZE ARM_DRAM1_SIZE + +#define N1SDP_REMOTE_DRAM2_BASE PLAT_ARM_DRAM2_BASE + \ + PLAT_ARM_REMOTE_CHIP_OFFSET +#define N1SDP_REMOTE_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE + +/* + * N1SDP platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC620. To access the complete DDR memory + * along with remote chip's DDR memory, which is at 4 TB offset, physical + * and virtual address space limits are extended to 43-bits. + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +#if CSS_USE_SCMI_SDS_DRIVER +#define N1SDP_SCMI_PAYLOAD_BASE 0x45400000 +#else +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE 0x45400000 +#endif + +/* + * Trusted SRAM in N1SDP is 512 KB but only the bottom 384 KB + * is used for trusted board boot flow. The top 128 KB is used + * to load AP-BL1 image. + */ +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00060000 /* 384 KB */ + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xC000 + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +# define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000 +# define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000 +#else +# define PLAT_ARM_MAX_ROMLIB_RW_SIZE U(0) +# define PLAT_ARM_MAX_ROMLIB_RO_SIZE U(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x22000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0x14000 +#endif + +#define PLAT_ARM_MAX_BL31_SIZE UL(0x40000) + +#define PLAT_ARM_SPMC_BASE U(0x08000000) +#define PLAT_ARM_SPMC_SIZE UL(0x02000000) /* 32 MB */ + + +/******************************************************************************* + * N1SDP topology related constants + ******************************************************************************/ +#define N1SDP_MAX_CPUS_PER_CLUSTER U(2) +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define PLAT_N1SDP_CHIP_COUNT U(2) +#define N1SDP_MAX_CLUSTERS_PER_CHIP U(2) +#define N1SDP_MAX_PE_PER_CPU U(1) + +#define PLATFORM_CORE_COUNT (PLAT_N1SDP_CHIP_COUNT * \ + PLAT_ARM_CLUSTER_COUNT * \ + N1SDP_MAX_CPUS_PER_CLUSTER * \ + N1SDP_MAX_PE_PER_CPU) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3 + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ + +#ifdef IMAGE_BL1 +# define PLAT_ARM_MMAP_ENTRIES U(6) +# define MAX_XLAT_TABLES U(5) +#endif + +#ifdef IMAGE_BL2 +# define PLAT_ARM_MMAP_ENTRIES U(11) +# define MAX_XLAT_TABLES U(10) +#endif + +#ifdef IMAGE_BL31 +# define PLAT_ARM_MMAP_ENTRIES U(12) +# define MAX_XLAT_TABLES U(12) +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x440 +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +# if SPM_MM +# define PLATFORM_STACK_SIZE 0x500 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +#define PLAT_ARM_NSTIMER_FRAME_ID 0 +#define PLAT_CSS_MHU_BASE 0x45000000 +#define PLAT_MAX_PWR_LVL 2 + +#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \ + CSS_IRQ_MHU +#define PLAT_ARM_G0_IRQS ARM_G0_IRQS + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + + +#define N1SDP_DEVICE_BASE ULL(0x08000000) +#define N1SDP_DEVICE_SIZE ULL(0x48000000) +#define N1SDP_REMOTE_DEVICE_BASE N1SDP_DEVICE_BASE + \ + PLAT_ARM_REMOTE_CHIP_OFFSET +#define N1SDP_REMOTE_DEVICE_SIZE N1SDP_DEVICE_SIZE + +/* Real base is 0x0. Changed to load BL1 at this address */ +# define PLAT_ARM_TRUSTED_ROM_BASE 0x04060000 +# define PLAT_ARM_TRUSTED_ROM_SIZE 0x00020000 /* 128KB */ + +#define N1SDP_MAP_DEVICE MAP_REGION_FLAT( \ + N1SDP_DEVICE_BASE, \ + N1SDP_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \ + ARM_DRAM1_BASE, \ + ARM_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define N1SDP_MAP_REMOTE_DEVICE MAP_REGION_FLAT( \ + N1SDP_REMOTE_DEVICE_BASE, \ + N1SDP_REMOTE_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define N1SDP_MAP_REMOTE_DRAM1 MAP_REGION_FLAT( \ + N1SDP_REMOTE_DRAM1_BASE, \ + N1SDP_REMOTE_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define N1SDP_MAP_REMOTE_DRAM2 MAP_REGION_FLAT( \ + N1SDP_REMOTE_DRAM2_BASE, \ + N1SDP_REMOTE_DRAM2_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x30000000 +#define PLAT_ARM_GICC_BASE 0x2C000000 +#define PLAT_ARM_GICR_BASE 0x300C0000 + +/* Platform ID address */ +#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET) + +/* Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(100) + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/n1sdp/n1sdp_bl1_setup.c b/plat/arm/board/n1sdp/n1sdp_bl1_setup.c new file mode 100644 index 0000000..ed93222 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_bl1_setup.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ + +void soc_css_init_nic400(void) +{ +} + +void soc_css_init_pcie(void) +{ +} diff --git a/plat/arm/board/n1sdp/n1sdp_bl2_setup.c b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c new file mode 100644 index 0000000..5f8af9f --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/css/sds.h> +#include <lib/mmio.h> +#include <lib/utils.h> + +#include "n1sdp_def.h" +#include <plat/arm/common/plat_arm.h> + +struct n1sdp_plat_info { + bool multichip_mode; + uint8_t secondary_count; + uint8_t local_ddr_size; + uint8_t remote_ddr_size; +} __packed; + +/* + * N1SDP platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC620. Zeroing out several gigabytes of + * memory from SCP is quite time consuming so the following function + * is added to zero out the DDR memory from application processor which is + * much faster compared to SCP. + */ + +void dmc_ecc_setup(uint8_t ddr_size_gb) +{ + uint64_t dram2_size; + + dram2_size = (ddr_size_gb * 1024UL * 1024UL * 1024UL) - + ARM_DRAM1_SIZE; + + INFO("Zeroing DDR memories\n"); + zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); + flush_dcache_range(ARM_DRAM2_BASE, dram2_size); + + INFO("Enabling ECC on DMCs\n"); + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); + mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); + + /* Enable ECC in DMCs */ + mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); + mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); + mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); +} + +void bl2_platform_setup(void) +{ + int ret; + struct n1sdp_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed\n"); + panic(); + } + + ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, + N1SDP_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + N1SDP_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS\n"); + panic(); + } + /* Validate plat_info SDS */ + if ((plat_info.local_ddr_size == 0) + || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) { + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + dmc_ecc_setup(plat_info.local_ddr_size); + arm_bl2_platform_setup(); +} diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c new file mode 100644 index 0000000..5e897fe --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/css/css_mhu_doorbell.h> +#include <drivers/arm/css/scmi.h> +#include <drivers/arm/css/sds.h> +#include <drivers/arm/gic600_multichip.h> +#include <lib/mmio.h> +#include <lib/utils.h> +#include <plat/arm/common/plat_arm.h> + +#include "n1sdp_def.h" +#include <platform_def.h> + +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which will be used to zero out the memory before + * enabling the ECC capability as well as information + * about multichip setup + * - multichip mode + * - secondary_count + * - Local DDR size in GB, DDR memory in master board + * - Remote DDR size in GB, DDR memory in secondary board + */ +struct n1sdp_plat_info { + bool multichip_mode; + uint8_t secondary_count; + uint8_t local_ddr_size; + uint8_t remote_ddr_size; +} __packed; + +static scmi_channel_plat_info_t n1sdp_scmi_plat_info = { + .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell +}; + +static struct gic600_multichip_data n1sdp_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = 1, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, + PLAT_ARM_GICD_BASE >> 16 + }, + .spi_ids = { + {32, 479}, + {512, 959} + } +}; + +static uintptr_t n1sdp_multichip_gicr_frames[3] = { + PLAT_ARM_GICR_BASE, + PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET, + 0 +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &n1sdp_scmi_plat_info; +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} + +/* + * N1SDP platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC620. Zeroing out several gigabytes of + * memory from SCP is quite time consuming so the following function + * is added to zero out the DDR memory from application processor which is + * much faster compared to SCP. Local DDR memory is zeroed out during BL2 + * stage. If remote chip is connected, it's DDR memory is zeroed out here. + */ + +void remote_dmc_ecc_setup(uint8_t remote_ddr_size) +{ + uint64_t remote_dram2_size; + + remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) - + N1SDP_REMOTE_DRAM1_SIZE; + /* multichip setup */ + INFO("Zeroing remote DDR memories\n"); + zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE, + N1SDP_REMOTE_DRAM1_SIZE); + flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE); + zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); + flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); + + INFO("Enabling ECC on remote DMCs\n"); + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, + N1SDP_DMC_MEMC_CMD_CONFIG); + mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, + N1SDP_DMC_MEMC_CMD_CONFIG); + + /* Enable ECC in DMCs */ + mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG, + N1SDP_DMC_ERR0CTLR0_ECC_EN); + mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG, + N1SDP_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); + mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); +} + +void n1sdp_bl31_multichip_setup(void) +{ + plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames); + gic600_multichip_init(&n1sdp_multichip_data); +} + +void bl31_platform_setup(void) +{ + int ret; + struct n1sdp_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed\n"); + panic(); + } + + ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, + N1SDP_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + N1SDP_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS\n"); + panic(); + } + /* Validate plat_info SDS */ + if ((plat_info.local_ddr_size == 0) + || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) { + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + if (plat_info.multichip_mode) { + n1sdp_multichip_data.chip_count = plat_info.secondary_count + 1; + n1sdp_bl31_multichip_setup(); + } + arm_bl31_platform_setup(); + + /* Check if remote memory is present */ + if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0)) + remote_dmc_ecc_setup(plat_info.remote_ddr_size); +} diff --git a/plat/arm/board/n1sdp/n1sdp_def.h b/plat/arm/board/n1sdp/n1sdp_def.h new file mode 100644 index 0000000..ffa6a03 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_def.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef N1SDP_DEF_H +#define N1SDP_DEF_H + +/* Non-secure SRAM MMU mapping */ +#define N1SDP_NS_SRAM_BASE (0x06000000) +#define N1SDP_NS_SRAM_SIZE (0x00010000) +#define N1SDP_MAP_NS_SRAM MAP_REGION_FLAT( \ + N1SDP_NS_SRAM_BASE, \ + N1SDP_NS_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* SDS Platform information defines */ +#define N1SDP_SDS_PLATFORM_INFO_STRUCT_ID 8 +#define N1SDP_SDS_PLATFORM_INFO_OFFSET 0 +#define N1SDP_SDS_PLATFORM_INFO_SIZE 4 +#define N1SDP_MAX_DDR_CAPACITY_GB 64 +#define N1SDP_MAX_SECONDARY_COUNT 16 + +/* DMC memory command registers */ +#define N1SDP_DMC0_MEMC_CMD_REG 0x4E000008 +#define N1SDP_DMC1_MEMC_CMD_REG 0x4E100008 + +/* DMC ERR0CTLR0 registers */ +#define N1SDP_DMC0_ERR0CTLR0_REG 0x4E000708 +#define N1SDP_DMC1_ERR0CTLR0_REG 0x4E100708 + +/* Remote DMC memory command registers */ +#define N1SDP_REMOTE_DMC0_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC0_MEMC_CMD_REG +#define N1SDP_REMOTE_DMC1_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC1_MEMC_CMD_REG + +/* Remote DMC ERR0CTLR0 registers */ +#define N1SDP_REMOTE_DMC0_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC0_ERR0CTLR0_REG +#define N1SDP_REMOTE_DMC1_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC1_ERR0CTLR0_REG + +/* DMC memory commands */ +#define N1SDP_DMC_MEMC_CMD_CONFIG 0 +#define N1SDP_DMC_MEMC_CMD_READY 3 + +/* DMC ECC enable bit in ERR0CTLR0 register */ +#define N1SDP_DMC_ERR0CTLR0_ECC_EN 0x1 + +#endif /* N1SDP_DEF_H */ diff --git a/plat/arm/board/n1sdp/n1sdp_err.c b/plat/arm/board/n1sdp/n1sdp_err.c new file mode 100644 index 0000000..629e76a --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * n1sdp error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/n1sdp/n1sdp_image_load.c b/plat/arm/board/n1sdp/n1sdp_image_load.c new file mode 100644 index 0000000..6c3528c --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_image_load.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/arm/css/sds.h> +#include <libfdt.h> +#include <plat/common/platform.h> + +#include "n1sdp_def.h" +#include <plat/arm/common/plat_arm.h> + +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which will be used to zero out the memory before + * enabling the ECC capability as well as information + * about multichip setup + * - multichip mode + * - secondary_count + * - Local DDR size in GB, DDR memory in master board + * - Remote DDR size in GB, DDR memory in secondary board + */ +struct n1sdp_plat_info { + bool multichip_mode; + uint8_t secondary_count; + uint8_t local_ddr_size; + uint8_t remote_ddr_size; +} __packed; + +/******************************************************************************* + * This function inserts Platform information via device tree nodes as, + * platform-info { + * multichip-mode = <0x0>; + * secondary-chip-count = <0x0>; + * local-ddr-size = <0x0>; + * remote-ddr-size = <0x0>; + * }; + ******************************************************************************/ +static int plat_n1sdp_append_config_node(struct n1sdp_plat_info *plat_info) +{ + bl_mem_params_node_t *mem_params; + void *fdt; + int nodeoffset, err; + + mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); + if (mem_params == NULL) { + ERROR("NT_FW CONFIG base address is NULL\n"); + return -1; + } + + fdt = (void *)(mem_params->image_info.image_base); + + /* Check the validity of the fdt */ + if (fdt_check_header(fdt) != 0) { + ERROR("Invalid NT_FW_CONFIG DTB passed\n"); + return -1; + } + + nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info"); + if (nodeoffset < 0) { + ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode", + plat_info->multichip_mode); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "secondary-chip-count", + plat_info->secondary_count); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set secondary-chip-count\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "local-ddr-size", + plat_info->local_ddr_size); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "remote-ddr-size", + plat_info->remote_ddr_size); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n"); + return -1; + } + + flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size); + + return 0; +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + int ret; + struct n1sdp_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed. ret:%d\n", ret); + panic(); + } + + ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, + N1SDP_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + N1SDP_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS. ret:%d\n", ret); + panic(); + } + + /* Validate plat_info SDS */ + if ((plat_info.local_ddr_size == 0U) + || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT) + ){ + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + ret = plat_n1sdp_append_config_node(&plat_info); + if (ret != 0) { + panic(); + } + + return arm_get_next_bl_params(); +} diff --git a/plat/arm/board/n1sdp/n1sdp_interconnect.c b/plat/arm/board/n1sdp/n1sdp_interconnect.c new file mode 100644 index 0000000..908f41c --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_interconnect.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/* + * For N1SDP which support FCM (with automatic interconnect enter/exit), + * we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c new file mode 100644 index 0000000..502268c --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_plat.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <drivers/arm/sbsa.h> +#include <plat/arm/common/plat_arm.h> + +#include "n1sdp_def.h" + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + N1SDP_MAP_DEVICE, + N1SDP_MAP_NS_SRAM, + ARM_MAP_DRAM1, + {0} +}; +#endif + +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + N1SDP_MAP_DEVICE, + N1SDP_MAP_NS_SRAM, + ARM_MAP_DRAM1, + ARM_MAP_DRAM2, +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + N1SDP_MAP_DEVICE, + N1SDP_MAP_NS_SRAM, + N1SDP_MAP_REMOTE_DEVICE, + N1SDP_MAP_REMOTE_DRAM1, + N1SDP_MAP_REMOTE_DRAM2, + {0} +}; +#endif + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/plat/arm/board/n1sdp/n1sdp_security.c b/plat/arm/board/n1sdp/n1sdp_security.c new file mode 100644 index 0000000..d2a187b --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_security.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * TZC programming is currently not done. + */ +void plat_arm_security_setup(void) +{ +} diff --git a/plat/arm/board/n1sdp/n1sdp_topology.c b/plat/arm/board/n1sdp/n1sdp_topology.c new file mode 100644 index 0000000..5c2db71 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_topology.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* Topology */ +typedef struct n1sdp_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} n1sdp_topology_t; + +/* + * The power domain tree descriptor. The cluster power domains are + * arranged so that when the PSCI generic code creates the power domain tree, + * the indices of the CPU power domain nodes it allocates match the linear + * indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char n1sdp_pd_tree_desc[] = { + PLAT_N1SDP_CHIP_COUNT, + PLAT_ARM_CLUSTER_COUNT, + PLAT_ARM_CLUSTER_COUNT, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER +}; + +/* Topology configuration for n1sdp */ +const n1sdp_topology_t n1sdp_topology = { + .power_tree = n1sdp_pd_tree_desc, + .plat_cluster_core_count = N1SDP_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return n1sdp_topology.power_tree; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return n1sdp_topology.plat_cluster_core_count; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3, 4, 5, 6, 7}; diff --git a/plat/arm/board/n1sdp/n1sdp_trusted_boot.c b/plat/arm/board/n1sdp/n1sdp_trusted_boot.c new file mode 100644 index 0000000..c7dc47f --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_trusted_boot.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = N1SDP_FW_NVCTR_VAL; + return 0; +} + +/* + * Store a new non-volatile counter value. By default on ARM development + * platforms, the non-volatile counters are RO and cannot be modified. We expect + * the values in the certificates to always match the RO values so that this + * function is never called. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk new file mode 100644 index 0000000..9c0cc02 --- /dev/null +++ b/plat/arm/board/n1sdp/platform.mk @@ -0,0 +1,111 @@ +# +# Copyright (c) 2018-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +N1SDP_BASE := plat/arm/board/n1sdp + +INTERCONNECT_SOURCES := ${N1SDP_BASE}/n1sdp_interconnect.c + +PLAT_INCLUDES := -I${N1SDP_BASE}/include + + +N1SDP_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 +GICV3_IMPL_GIC600_MULTICHIP := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +N1SDP_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c \ + +PLAT_BL_COMMON_SOURCES := ${N1SDP_BASE}/n1sdp_plat.c \ + ${N1SDP_BASE}/aarch64/n1sdp_helper.S + +BL1_SOURCES := ${N1SDP_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${N1SDP_BASE}/n1sdp_err.c \ + ${N1SDP_BASE}/n1sdp_trusted_boot.c \ + ${N1SDP_BASE}/n1sdp_bl1_setup.c \ + drivers/arm/sbsa/sbsa.c + +BL2_SOURCES := ${N1SDP_BASE}/n1sdp_security.c \ + ${N1SDP_BASE}/n1sdp_err.c \ + ${N1SDP_BASE}/n1sdp_trusted_boot.c \ + lib/utils/mem_region.c \ + ${N1SDP_BASE}/n1sdp_bl2_setup.c \ + ${N1SDP_BASE}/n1sdp_image_load.c \ + drivers/arm/css/sds/sds.c + +BL31_SOURCES := ${N1SDP_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${N1SDP_GIC_SOURCES} \ + ${N1SDP_BASE}/n1sdp_bl31_setup.c \ + ${N1SDP_BASE}/n1sdp_topology.c \ + ${N1SDP_BASE}/n1sdp_security.c \ + drivers/arm/css/sds/sds.c + +FDT_SOURCES += fdts/${PLAT}-single-chip.dts \ + fdts/${PLAT}-multi-chip.dts \ + ${N1SDP_BASE}/fdts/n1sdp_fw_config.dts \ + ${N1SDP_BASE}/fdts/n1sdp_tb_fw_config.dts \ + ${N1SDP_BASE}/fdts/n1sdp_nt_fw_config.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_tb_fw_config.dtb +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_nt_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +N1SDP_SPMC_MANIFEST_DTS := ${N1SDP_BASE}/fdts/${PLAT}_optee_spmc_manifest.dts +FDT_SOURCES += ${N1SDP_SPMC_MANIFEST_DTS} +N1SDP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_optee_spmc_manifest.dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${N1SDP_TOS_FW_CONFIG},--tos-fw-config,${N1SDP_TOS_FW_CONFIG})) + +# Setting to 0 as no NVCTR in N1SDP +N1SDP_FW_NVCTR_VAL := 0 +TFW_NVCTR_VAL := ${N1SDP_FW_NVCTR_VAL} +NTFW_NVCTR_VAL := ${N1SDP_FW_NVCTR_VAL} + +# Add N1SDP_FW_NVCTR_VAL +$(eval $(call add_define,N1SDP_FW_NVCTR_VAL)) + +# TF-A not required to load the SCP Images +override CSS_LOAD_SCP_IMAGES := 0 + +override NEED_BL2U := no + +# 32 bit mode not supported +override CTX_INCLUDE_AARCH32_REGS := 0 + +override ARM_PLAT_MT := 1 + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# When building for systems with hardware-assisted coherency, there's no need to +# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too. +USE_COHERENT_MEM := 0 + +# Enable the flag since N1SDP has a system level cache +NEOVERSE_Nx_EXTERNAL_LLC := 1 +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts new file mode 100644 index 0000000..69fb0d4 --- /dev/null +++ b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts new file mode 100644 index 0000000..0af821e --- /dev/null +++ b/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-e1edge"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; + +}; diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts new file mode 100644 index 0000000..dba91e5 --- /dev/null +++ b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h new file mode 100644 index 0000000..69bfd7b --- /dev/null +++ b/plat/arm/board/rde1edge/include/platform_def.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> + +#include <sgi_sdei.h> +#include <sgi_soc_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(8) +#define CSS_SGI_MAX_PE_PER_CPU U(2) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) + +/* Base address of DMC-620 instances */ +#define RDE1EDGE_DMC620_BASE0 UL(0x4e000000) +#define RDE1EDGE_DMC620_BASE1 UL(0x4e100000) + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3 + +/* Maximum number of address bits used per chip */ +#define CSS_SGI_ADDR_BITS_PER_CHIP U(36) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk new file mode 100644 index 0000000..0f9dd49 --- /dev/null +++ b/plat/arm/board/rde1edge/platform.mk @@ -0,0 +1,66 @@ +# +# Copyright (c) 2018-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/arm/css/sgi/sgi-common.mk + +RDE1EDGE_BASE = plat/arm/board/rde1edge + +PLAT_INCLUDES += -I${RDE1EDGE_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_e1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDE1EDGE_BASE}/rde1edge_err.c + +BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_plat.c \ + ${RDE1EDGE_BASE}/rde1edge_security.c \ + ${RDE1EDGE_BASE}/rde1edge_err.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDE1EDGE_BASE}/rde1edge_plat.c \ + ${RDE1EDGE_BASE}/rde1edge_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDE1EDGE_BASE}/rde1edge_trusted_boot.c +BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +ifneq ($(CSS_SGI_CHIP_COUNT),1) + $(error "Chip count for RDE1Edge should be 1, currently set to \ + ${CSS_SGI_CHIP_COUNT}.") +endif + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-E1-Edge should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif + +override CTX_INCLUDE_AARCH32_REGS := 0 diff --git a/plat/arm/board/rde1edge/rde1edge_err.c b/plat/arm/board/rde1edge/rde1edge_err.c new file mode 100644 index 0000000..c72c18c --- /dev/null +++ b/plat/arm/board/rde1edge/rde1edge_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rde1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/rde1edge/rde1edge_plat.c b/plat/arm/board/rde1edge/rde1edge_plat.c new file mode 100644 index 0000000..44d818a --- /dev/null +++ b/plat/arm/board/rde1edge/rde1edge_plat.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> +#include <sgi_plat.h> + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return 0; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/plat/arm/board/rde1edge/rde1edge_security.c b/plat/arm/board/rde1edge/rde1edge_security.c new file mode 100644 index 0000000..35f81d1 --- /dev/null +++ b/plat/arm/board/rde1edge/rde1edge_security.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <common/debug.h> +#include <sgi_dmc620_tzc_regions.h> + +uintptr_t rde1edge_dmc_base[] = { + RDE1EDGE_DMC620_BASE0, + RDE1EDGE_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t rde1edge_plat_driver_data = { + .dmc_base = rde1edge_dmc_base, + .dmc_count = ARRAY_SIZE(rde1edge_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t rde1edge_acc_addr_data[] = { + CSS_SGI_DMC620_TZC_REGIONS_DEF +}; + +static const tzc_dmc620_config_data_t rde1edge_plat_config_data = { + .plat_drv_data = &rde1edge_plat_driver_data, + .plat_acc_addr_data = rde1edge_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(rde1edge_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&rde1edge_plat_config_data); +} diff --git a/plat/arm/board/rde1edge/rde1edge_topology.c b/plat/arm/board/rde1edge/rde1edge_topology.c new file mode 100644 index 0000000..a16283e --- /dev/null +++ b/plat/arm/board/rde1edge/rde1edge_topology.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/****************************************************************************** + * The power domain tree descriptor. RD-E1-Edge platform consists of two + * clusters with eight CPUs in each cluster. The CPUs are multi-threaded with + * two threads per CPU. + ******************************************************************************/ +static const unsigned char rde1edge_pd_tree_desc[] = { + CSS_SGI_CHIP_COUNT, + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU, + CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU +}; + +/****************************************************************************** + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rde1edge_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; diff --git a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts new file mode 100644 index 0000000..d3b7fba --- /dev/null +++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; + diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts new file mode 100644 index 0000000..68366c5 --- /dev/null +++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-n1edge"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts new file mode 100644 index 0000000..257ef4a --- /dev/null +++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h new file mode 100644 index 0000000..de01902 --- /dev/null +++ b/plat/arm/board/rdn1edge/include/platform_def.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> + +#include <sgi_sdei.h> +#include <sgi_soc_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) + +/* Base address of DMC-620 instances */ +#define RDN1EDGE_DMC620_BASE0 UL(0x4e000000) +#define RDN1EDGE_DMC620_BASE1 UL(0x4e100000) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* Virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* Maximum number of address bits used per chip */ +#define CSS_SGI_ADDR_BITS_PER_CHIP U(42) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk new file mode 100644 index 0000000..95753aa --- /dev/null +++ b/plat/arm/board/rdn1edge/platform.mk @@ -0,0 +1,75 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +$(warning Platform ${PLAT} is deprecated. Some of the features might not work as expected) + +# GIC-600 configuration +GICV3_IMPL_GIC600_MULTICHIP := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDN1EDGE_BASE = plat/arm/board/rdn1edge + +PLAT_INCLUDES += -I${RDN1EDGE_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN1EDGE_BASE}/rdn1edge_err.c + +BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_plat.c \ + ${RDN1EDGE_BASE}/rdn1edge_security.c \ + ${RDN1EDGE_BASE}/rdn1edge_err.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN1EDGE_BASE}/rdn1edge_plat.c \ + ${RDN1EDGE_BASE}/rdn1edge_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c +BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c +endif + +# Enable dynamic addition of MMAP regions in BL31 +BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +$(eval $(call CREATE_SEQ,SEQ,2)) +ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) + $(error "Chip count for RDN1Edge platform should be one of $(SEQ), currently \ + set to ${CSS_SGI_CHIP_COUNT}.") +endif + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-N1-Edge should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif + +override CTX_INCLUDE_AARCH32_REGS := 0 diff --git a/plat/arm/board/rdn1edge/rdn1edge_err.c b/plat/arm/board/rdn1edge/rdn1edge_err.c new file mode 100644 index 0000000..46d318c --- /dev/null +++ b/plat/arm/board/rdn1edge/rdn1edge_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rdn1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/rdn1edge/rdn1edge_plat.c b/plat/arm/board/rdn1edge/rdn1edge_plat.c new file mode 100644 index 0000000..1dbbf26 --- /dev/null +++ b/plat/arm/board/rdn1edge/rdn1edge_plat.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/gic600_multichip.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <sgi_soc_platform_def.h> +#include <sgi_plat.h> + +#if defined(IMAGE_BL31) +static const mmap_region_t rdn1edge_dynamic_mmap[] = { + ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1) +}; + +static struct gic600_multichip_data rdn1e1_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = CSS_SGI_CHIP_COUNT, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16 + }, + .spi_ids = { + {32, 255}, + {0, 0} + } +}; + +static uintptr_t rdn1e1_multichip_gicr_frames[] = { + PLAT_ARM_GICR_BASE, /* Chip 0's GICR Base */ + PLAT_ARM_GICR_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), /* Chip 1's GICR BASE */ + UL(0) /* Zero Termination */ +}; +#endif /* IMAGE_BL31 */ + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT; +} + +/* + * IMAGE_BL31 macro is added to build bl31_platform_setup function only for BL31 + * because PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not + * for other stages. + */ +#if defined(IMAGE_BL31) +void bl31_platform_setup(void) +{ + int i, ret; + + if (plat_arm_sgi_get_multi_chip_mode() == 0 && CSS_SGI_CHIP_COUNT > 1) { + ERROR("Chip Count is set to %d but multi-chip mode not enabled\n", + CSS_SGI_CHIP_COUNT); + panic(); + } else if (plat_arm_sgi_get_multi_chip_mode() == 1 && + CSS_SGI_CHIP_COUNT > 1) { + INFO("Enabling support for multi-chip in RD-N1-Edge\n"); + + for (i = 0; i < ARRAY_SIZE(rdn1edge_dynamic_mmap); i++) { + ret = mmap_add_dynamic_region( + rdn1edge_dynamic_mmap[i].base_pa, + rdn1edge_dynamic_mmap[i].base_va, + rdn1edge_dynamic_mmap[i].size, + rdn1edge_dynamic_mmap[i].attr + ); + if (ret != 0) { + ERROR("Failed to add dynamic mmap entry\n"); + panic(); + } + } + + plat_arm_override_gicr_frames(rdn1e1_multichip_gicr_frames); + gic600_multichip_init(&rdn1e1_multichip_data); + } + + sgi_bl31_common_platform_setup(); +} +#endif /* IMAGE_BL31 */ diff --git a/plat/arm/board/rdn1edge/rdn1edge_security.c b/plat/arm/board/rdn1edge/rdn1edge_security.c new file mode 100644 index 0000000..4943532 --- /dev/null +++ b/plat/arm/board/rdn1edge/rdn1edge_security.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <common/debug.h> +#include <sgi_dmc620_tzc_regions.h> + +uintptr_t rdn1edge_dmc_base[] = { + RDN1EDGE_DMC620_BASE0, + RDN1EDGE_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t rdn1edge_plat_driver_data = { + .dmc_base = rdn1edge_dmc_base, + .dmc_count = ARRAY_SIZE(rdn1edge_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t rdn1edge_acc_addr_data[] = { + CSS_SGI_DMC620_TZC_REGIONS_DEF +}; + +static const tzc_dmc620_config_data_t rdn1edge_plat_config_data = { + .plat_drv_data = &rdn1edge_plat_driver_data, + .plat_acc_addr_data = rdn1edge_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(rdn1edge_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&rdn1edge_plat_config_data); +} diff --git a/plat/arm/board/rdn1edge/rdn1edge_topology.c b/plat/arm/board/rdn1edge/rdn1edge_topology.c new file mode 100644 index 0000000..5bbea69 --- /dev/null +++ b/plat/arm/board/rdn1edge/rdn1edge_topology.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +static const unsigned char rdn1edge_pd_tree_desc[] = { + (PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT), + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#if (CSS_SGI_CHIP_COUNT > 1) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +#endif +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rdn1edge_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), +#if (CSS_SGI_CHIP_COUNT > 1) + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x7)), +#endif +}; diff --git a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts new file mode 100644 index 0000000..dd70141 --- /dev/null +++ b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 - 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-n2"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + /* + * First cell pair: Count of isolated CPUs in the list. + * Rest of the cells: MPID list of the isolated CPUs. + */ + isolated-cpu-list = <0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0>; + }; +}; diff --git a/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h new file mode 100644 index 0000000..3474016 --- /dev/null +++ b/plat/arm/board/rdn2/include/platform_def.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> + +#include <sgi_soc_platform_def_v2.h> + +#if (CSS_SGI_PLATFORM_VARIANT == 1) +#define PLAT_ARM_CLUSTER_COUNT U(8) +#elif (CSS_SGI_PLATFORM_VARIANT == 2) +#define PLAT_ARM_CLUSTER_COUNT U(4) +#else +#define PLAT_ARM_CLUSTER_COUNT U(16) +#endif + +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x2A920000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x10720000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) + +#if (CSS_SGI_PLATFORM_VARIANT == 1) +#define TZC400_COUNT U(2) +#elif (CSS_SGI_PLATFORM_VARIANT == 2) +#define TZC400_COUNT U(4) +#else +#define TZC400_COUNT U(8) +#endif + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_DMA U(5) +#define TZC_NSAID_DMA2 U(8) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA2)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#if (CSS_SGI_PLATFORM_VARIANT == 2) +#define CSS_SGI_ADDR_BITS_PER_CHIP U(46) /* 64TB */ +#else +#define CSS_SGI_ADDR_BITS_PER_CHIP U(42) /* 4TB */ +#endif + +#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) + +/* Virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xC0000000) + +#if (CSS_SGI_PLATFORM_VARIANT == 1) +#define PLAT_ARM_GICR_BASE UL(0x30100000) +#else +#define PLAT_ARM_GICR_BASE UL(0x301C0000) +#endif + +/* Interrupt priority level for shutdown/reboot */ +#define PLAT_REBOOT_PRI GIC_HIGHEST_SEC_PRIORITY +#define PLAT_EHF_DESC EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_REBOOT_PRI) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk new file mode 100644 index 0000000..7492fe5 --- /dev/null +++ b/plat/arm/board/rdn2/platform.mk @@ -0,0 +1,90 @@ +# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RD_N2_VARIANTS := 0 1 2 +ifneq ($(CSS_SGI_PLATFORM_VARIANT),\ + $(filter $(CSS_SGI_PLATFORM_VARIANT),$(RD_N2_VARIANTS))) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-N2 should be 0, 1 or 2, currently set \ + to ${CSS_SGI_PLATFORM_VARIANT}.") +endif + +$(eval $(call CREATE_SEQ,SEQ,4)) +ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) + $(error "Chip count for RD-N2-MC should be either $(SEQ) \ + currently it is set to ${CSS_SGI_CHIP_COUNT}.") +endif + +# RD-N2 platform uses GIC-700 which is based on GICv4.1 +GIC_ENABLE_V4_EXTN := 1 +GIC_EXT_INTID := 1 + +#Enable GIC Multichip Extension only for Multichip Platforms +ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2) +GICV3_IMPL_GIC600_MULTICHIP := 1 +endif + +override CSS_SYSTEM_GRACEFUL_RESET := 1 +override EL3_EXCEPTION_HANDLING := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDN2_BASE = plat/arm/board/rdn2 + +PLAT_INCLUDES += -I${RDN2_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_v2.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat_v2.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN2_BASE}/rdn2_err.c + +BL2_SOURCES += ${RDN2_BASE}/rdn2_plat.c \ + ${RDN2_BASE}/rdn2_security.c \ + ${RDN2_BASE}/rdn2_err.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN2_BASE}/rdn2_plat.c \ + ${RDN2_BASE}/rdn2_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c +BL2_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c +endif + +ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2) +BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c + +# Enable dynamic addition of MMAP regions in BL31 +BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDN2_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config)) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 diff --git a/plat/arm/board/rdn2/rdn2_err.c b/plat/arm/board/rdn2/rdn2_err.c new file mode 100644 index 0000000..802ac21 --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rdn2 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/rdn2/rdn2_plat.c b/plat/arm/board/rdn2/rdn2_plat.c new file mode 100644 index 0000000..2506f9d --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_plat.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/gic600_multichip.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <sgi_soc_platform_def_v2.h> +#include <sgi_plat.h> + +#if defined(IMAGE_BL31) +#if (CSS_SGI_PLATFORM_VARIANT == 2) +static const mmap_region_t rdn2mc_dynamic_mmap[] = { +#if CSS_SGI_CHIP_COUNT > 1 + ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), +#endif +#if CSS_SGI_CHIP_COUNT > 2 + ARM_MAP_SHARED_RAM_REMOTE_CHIP(2), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2), +#endif +#if CSS_SGI_CHIP_COUNT > 3 + ARM_MAP_SHARED_RAM_REMOTE_CHIP(3), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3), +#endif +}; +#endif + +#if (CSS_SGI_PLATFORM_VARIANT == 2) +static struct gic600_multichip_data rdn2mc_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = CSS_SGI_CHIP_COUNT, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, +#if CSS_SGI_CHIP_COUNT > 1 + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16, +#endif +#if CSS_SGI_CHIP_COUNT > 2 + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16, +#endif +#if CSS_SGI_CHIP_COUNT > 3 + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16, +#endif + }, + .spi_ids = { + {32, 511}, + #if CSS_SGI_CHIP_COUNT > 1 + {512, 991}, + #endif + #if CSS_SGI_CHIP_COUNT > 2 + {4096, 4575}, + #endif + #if CSS_SGI_CHIP_COUNT > 3 + {4576, 5055}, + #endif + } +}; +#endif + +#if (CSS_SGI_PLATFORM_VARIANT == 2) +static uintptr_t rdn2mc_multichip_gicr_frames[] = { + /* Chip 0's GICR Base */ + PLAT_ARM_GICR_BASE, +#if CSS_SGI_CHIP_COUNT > 1 + /* Chip 1's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), +#endif +#if CSS_SGI_CHIP_COUNT > 2 + /* Chip 2's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2), +#endif +#if CSS_SGI_CHIP_COUNT > 3 + /* Chip 3's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3), +#endif + UL(0) /* Zero Termination */ +}; +#endif +#endif /* IMAGE_BL31 */ + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> + SID_MULTI_CHIP_MODE_SHIFT; +} + +#if defined(IMAGE_BL31) +void bl31_platform_setup(void) +{ +#if (CSS_SGI_PLATFORM_VARIANT == 2) + int ret; + unsigned int i; + + if (plat_arm_sgi_get_multi_chip_mode() == 0) { + ERROR("Chip Count is set to %u but multi-chip mode is not " + "enabled\n", CSS_SGI_CHIP_COUNT); + panic(); + } else { + INFO("Enabling multi-chip support for RD-N2 variant\n"); + + for (i = 0; i < ARRAY_SIZE(rdn2mc_dynamic_mmap); i++) { + ret = mmap_add_dynamic_region( + rdn2mc_dynamic_mmap[i].base_pa, + rdn2mc_dynamic_mmap[i].base_va, + rdn2mc_dynamic_mmap[i].size, + rdn2mc_dynamic_mmap[i].attr); + if (ret != 0) { + ERROR("Failed to add dynamic mmap entry for" + " i: %d " "(ret=%d)\n", i, ret); + panic(); + } + } + + plat_arm_override_gicr_frames( + rdn2mc_multichip_gicr_frames); + gic600_multichip_init(&rdn2mc_multichip_data); + } +#endif + + sgi_bl31_common_platform_setup(); +} +#endif /* IMAGE_BL31 */ diff --git a/plat/arm/board/rdn2/rdn2_security.c b/plat/arm/board/rdn2/rdn2_security.c new file mode 100644 index 0000000..dff6a19 --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_security.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +#if (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1) +static const arm_tzc_regions_info_t tzc_regions_mc[][CSS_SGI_CHIP_COUNT - 1] = { + { + /* TZC memory regions for second chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(1), + {} + }, +#if CSS_SGI_CHIP_COUNT > 2 + { + /* TZC memory regions for third chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(2), + {} + }, +#endif +#if CSS_SGI_CHIP_COUNT > 3 + { + /* TZC memory regions for fourth chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(3), + {} + }, +#endif +}; +#endif /* CSS_SGI_PLATFORM_VARIANT && CSS_SGI_CHIP_COUNT */ + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + unsigned int i; + + INFO("Configuring TrustZone Controller for Chip 0\n"); + + for (i = 0; i < TZC400_COUNT; i++) { + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + } + +#if (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1) + unsigned int j; + + for (i = 1; i < CSS_SGI_CHIP_COUNT; i++) { + INFO("Configuring TrustZone Controller for Chip %u\n", i); + + for (j = 0; j < TZC400_COUNT; j++) { + arm_tzc400_setup(CSS_SGI_REMOTE_CHIP_MEM_OFFSET(i) + + TZC400_BASE(j), tzc_regions_mc[i-1]); + } + } +#endif +} diff --git a/plat/arm/board/rdn2/rdn2_topology.c b/plat/arm/board/rdn2/rdn2_topology.c new file mode 100644 index 0000000..89300f8 --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_topology.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_n2_pd_tree_desc[] = { + (PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT), + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#if (CSS_SGI_PLATFORM_VARIANT != 2 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1)) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_PLATFORM_VARIANT == 0 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 2)) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_PLATFORM_VARIANT == 0 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 3)) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rd_n2_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +#if (CSS_SGI_PLATFORM_VARIANT == 2) +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), +#if (CSS_SGI_CHIP_COUNT > 1) + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 2) + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +}; +#else +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), +#if (CSS_SGI_PLATFORM_VARIANT == 0) + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)), +#endif +}; +#endif diff --git a/plat/arm/board/rdn2/rdn2_trusted_boot.c b/plat/arm/board/rdn2/rdn2_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts new file mode 100644 index 0000000..62ba2c3 --- /dev/null +++ b/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-v1"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/rdv1/include/platform_def.h b/plat/arm/board/rdv1/include/platform_def.h new file mode 100644 index 0000000..620fa3e --- /dev/null +++ b/plat/arm/board/rdv1/include/platform_def.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> + +#include <sgi_soc_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT U(16) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x21830000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT 4 + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* Maximum number of address bits used per chip */ +#define CSS_SGI_ADDR_BITS_PER_CHIP U(42) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x30140000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk new file mode 100644 index 0000000..11f5212 --- /dev/null +++ b/plat/arm/board/rdv1/platform.mk @@ -0,0 +1,65 @@ +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# RD-V1 platform uses GIC-700 which is based on GICv4.1 +GIC_ENABLE_V4_EXTN := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDV1_BASE = plat/arm/board/rdv1 + +PLAT_INCLUDES += -I${RDV1_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1_BASE}/rdv1_err.c + +BL2_SOURCES += ${RDV1_BASE}/rdv1_plat.c \ + ${RDV1_BASE}/rdv1_security.c \ + ${RDV1_BASE}/rdv1_err.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1_BASE}/rdv1_plat.c \ + ${RDV1_BASE}/rdv1_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c +BL2_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDV1_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-V1 should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif diff --git a/plat/arm/board/rdv1/rdv1_err.c b/plat/arm/board/rdv1/rdv1_err.c new file mode 100644 index 0000000..68f9a3e --- /dev/null +++ b/plat/arm/board/rdv1/rdv1_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rdv1 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/rdv1/rdv1_plat.c b/plat/arm/board/rdv1/rdv1_plat.c new file mode 100644 index 0000000..ab5251e --- /dev/null +++ b/plat/arm/board/rdv1/rdv1_plat.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> +#include <sgi_plat.h> + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/plat/arm/board/rdv1/rdv1_security.c b/plat/arm/board/rdv1/rdv1_security.c new file mode 100644 index 0000000..1247db8 --- /dev/null +++ b/plat/arm/board/rdv1/rdv1_security.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + int i; + + for (i = 0; i < TZC400_COUNT; i++) + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); +} diff --git a/plat/arm/board/rdv1/rdv1_topology.c b/plat/arm/board/rdv1/rdv1_topology.c new file mode 100644 index 0000000..ab64fd8 --- /dev/null +++ b/plat/arm/board/rdv1/rdv1_topology.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_v1_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rd_v1_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)) +}; diff --git a/plat/arm/board/rdv1/rdv1_trusted_boot.c b/plat/arm/board/rdv1/rdv1_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/plat/arm/board/rdv1/rdv1_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts new file mode 100644 index 0000000..71c7db3 --- /dev/null +++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-v1-mc"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/rdv1mc/include/platform_def.h b/plat/arm/board/rdv1mc/include/platform_def.h new file mode 100644 index 0000000..3670904 --- /dev/null +++ b/plat/arm/board/rdv1mc/include/platform_def.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> +#include <sgi_soc_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT U(4) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x21830000) +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT U(8) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* Virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xC0000000) + +/* Remote chip address offset (4TB per chip) */ +#define CSS_SGI_ADDR_BITS_PER_CHIP U(42) + +/* Physical and virtual address space limits for MMU in AARCH64 mode */ +#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x30140000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/rdv1mc/platform.mk b/plat/arm/board/rdv1mc/platform.mk new file mode 100644 index 0000000..df0b09a --- /dev/null +++ b/plat/arm/board/rdv1mc/platform.mk @@ -0,0 +1,76 @@ +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable GICv4 extension with multichip driver +GIC_ENABLE_V4_EXTN := 1 +GICV3_IMPL_GIC600_MULTICHIP := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDV1MC_BASE = plat/arm/board/rdv1mc + +PLAT_INCLUDES += -I${RDV1MC_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1MC_BASE}/rdv1mc_err.c + +BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_plat.c \ + ${RDV1MC_BASE}/rdv1mc_security.c \ + ${RDV1MC_BASE}/rdv1mc_err.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1MC_BASE}/rdv1mc_plat.c \ + ${RDV1MC_BASE}/rdv1mc_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/arm/gic/v3/gic600_multichip.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c +BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c +endif + +# Enable dynamic addition of MMAP regions in BL31 +BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDV1MC_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +$(eval $(call CREATE_SEQ,SEQ,4)) +ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) + $(error "Chip count for RD-V1-MC should be either $(SEQ) \ + currently it is set to ${CSS_SGI_CHIP_COUNT}.") +endif + +FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-V1-MC should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif diff --git a/plat/arm/board/rdv1mc/rdv1mc_err.c b/plat/arm/board/rdv1mc/rdv1mc_err.c new file mode 100644 index 0000000..755a503 --- /dev/null +++ b/plat/arm/board/rdv1mc/rdv1mc_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rdv1mc error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/rdv1mc/rdv1mc_plat.c b/plat/arm/board/rdv1mc/rdv1mc_plat.c new file mode 100644 index 0000000..d859400 --- /dev/null +++ b/plat/arm/board/rdv1mc/rdv1mc_plat.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/gic600_multichip.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <sgi_soc_platform_def.h> +#include <sgi_plat.h> + +#if defined(IMAGE_BL31) +static const mmap_region_t rdv1mc_dynamic_mmap[] = { + ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1), +#if (CSS_SGI_CHIP_COUNT > 2) + ARM_MAP_SHARED_RAM_REMOTE_CHIP(2), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(2), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + ARM_MAP_SHARED_RAM_REMOTE_CHIP(3), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(3) +#endif +}; + +static struct gic600_multichip_data rdv1mc_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = CSS_SGI_CHIP_COUNT, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16, +#if (CSS_SGI_CHIP_COUNT > 2) + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16, +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16, +#endif + }, + .spi_ids = { + {32, 255}, + {0, 0}, +#if (CSS_SGI_CHIP_COUNT > 2) + {0, 0}, +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + {0, 0}, +#endif + } +}; + +static uintptr_t rdv1mc_multichip_gicr_frames[] = { + /* Chip 0's GICR Base */ + PLAT_ARM_GICR_BASE, + /* Chip 1's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), +#if (CSS_SGI_CHIP_COUNT > 2) + /* Chip 2's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + /* Chip 3's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3), +#endif + UL(0) /* Zero Termination */ +}; +#endif /* IMAGE_BL31 */ + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT; +} + +/* + * bl31_platform_setup_function is guarded by IMAGE_BL31 macro because + * PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not + * for other stages. + */ +#if defined(IMAGE_BL31) +void bl31_platform_setup(void) +{ + int ret; + unsigned int i; + + if ((plat_arm_sgi_get_multi_chip_mode() == 0) && + (CSS_SGI_CHIP_COUNT > 1)) { + ERROR("Chip Count is set to %u but multi-chip mode is not " + "enabled\n", CSS_SGI_CHIP_COUNT); + panic(); + } else if ((plat_arm_sgi_get_multi_chip_mode() == 1) && + (CSS_SGI_CHIP_COUNT > 1)) { + INFO("Enabling support for multi-chip in RD-V1-MC\n"); + + for (i = 0; i < ARRAY_SIZE(rdv1mc_dynamic_mmap); i++) { + ret = mmap_add_dynamic_region( + rdv1mc_dynamic_mmap[i].base_pa, + rdv1mc_dynamic_mmap[i].base_va, + rdv1mc_dynamic_mmap[i].size, + rdv1mc_dynamic_mmap[i].attr); + if (ret != 0) { + ERROR("Failed to add dynamic mmap entry " + "(ret=%d)\n", ret); + panic(); + } + } + + plat_arm_override_gicr_frames( + rdv1mc_multichip_gicr_frames); + gic600_multichip_init(&rdv1mc_multichip_data); + } + + sgi_bl31_common_platform_setup(); +} +#endif /* IMAGE_BL31 */ diff --git a/plat/arm/board/rdv1mc/rdv1mc_security.c b/plat/arm/board/rdv1mc/rdv1mc_security.c new file mode 100644 index 0000000..adc0bf8 --- /dev/null +++ b/plat/arm/board/rdv1mc/rdv1mc_security.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* TZC memory regions for the first chip */ +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +#if CSS_SGI_CHIP_COUNT > 1 +static const arm_tzc_regions_info_t tzc_regions_mc[][CSS_SGI_CHIP_COUNT - 1] = { + { + /* TZC memory regions for second chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(1), + {} + }, +#if CSS_SGI_CHIP_COUNT > 2 + { + /* TZC memory regions for third chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(2), + {} + }, +#endif +#if CSS_SGI_CHIP_COUNT > 3 + { + /* TZC memory regions for fourth chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(3), + {} + }, +#endif +}; +#endif /* CSS_SGI_CHIP_COUNT */ + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + unsigned int i; + + INFO("Configuring TrustZone Controller for Chip 0\n"); + + for (i = 0; i < TZC400_COUNT; i++) { + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + } + +#if CSS_SGI_CHIP_COUNT > 1 + unsigned int j; + + for (i = 1; i < CSS_SGI_CHIP_COUNT; i++) { + INFO("Configuring TrustZone Controller for Chip %u\n", i); + + for (j = 0; j < TZC400_COUNT; j++) { + arm_tzc400_setup(CSS_SGI_REMOTE_CHIP_MEM_OFFSET(i) + + TZC400_BASE(j), tzc_regions_mc[i-1]); + } + } +#endif +} diff --git a/plat/arm/board/rdv1mc/rdv1mc_topology.c b/plat/arm/board/rdv1mc/rdv1mc_topology.c new file mode 100644 index 0000000..4486e5c --- /dev/null +++ b/plat/arm/board/rdv1mc/rdv1mc_topology.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> +#include <sgi_variant.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_v1_mc_pd_tree_desc_multi_chip[] = { + ((PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT)), + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#if (CSS_SGI_CHIP_COUNT > 1) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_CHIP_COUNT > 2) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +#endif +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + if (plat_arm_sgi_get_multi_chip_mode() == 1) + return rd_v1_mc_pd_tree_desc_multi_chip; + panic(); +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), +#if (CSS_SGI_CHIP_COUNT > 1) + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 2) + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3)) +#endif +}; diff --git a/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c b/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts new file mode 100644 index 0000000..84fc1ad --- /dev/null +++ b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts new file mode 100644 index 0000000..260247a --- /dev/null +++ b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,sgi575"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h new file mode 100644 index 0000000..82a38c5 --- /dev/null +++ b/plat/arm/board/sgi575/include/platform_def.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> + +#include <sgi_sdei.h> +#include <sgi_soc_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45000000) + +/* Base address of DMC-620 instances */ +#define SGI575_DMC620_BASE0 UL(0x4e000000) +#define SGI575_DMC620_BASE1 UL(0x4e100000) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* Maximum number of address bits used per chip */ +#define CSS_SGI_ADDR_BITS_PER_CHIP U(36) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk new file mode 100644 index 0000000..2f2bf73 --- /dev/null +++ b/plat/arm/board/sgi575/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +$(warning Platform ${PLAT} is deprecated. Some of the features might not work as expected) + +include plat/arm/css/sgi/sgi-common.mk + +SGI575_BASE = plat/arm/board/sgi575 + +PLAT_INCLUDES += -I${SGI575_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${SGI575_BASE}/sgi575_err.c + +BL2_SOURCES += ${SGI575_BASE}/sgi575_plat.c \ + ${SGI575_BASE}/sgi575_security.c \ + ${SGI575_BASE}/sgi575_err.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${SGI575_BASE}/sgi575_plat.c \ + ${SGI575_BASE}/sgi575_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${SGI575_BASE}/sgi575_trusted_boot.c +BL2_SOURCES += ${SGI575_BASE}/sgi575_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_fw_config.dts \ + ${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +ifneq ($(CSS_SGI_CHIP_COUNT),1) + $(error "Chip count for SGI575 should be 1, currently set to \ + ${CSS_SGI_CHIP_COUNT}.") +endif + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for SGI575 should always be 0,\ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif diff --git a/plat/arm/board/sgi575/sgi575_err.c b/plat/arm/board/sgi575/sgi575_err.c new file mode 100644 index 0000000..21bfcb7 --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * sgi575 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/sgi575/sgi575_plat.c b/plat/arm/board/sgi575/sgi575_plat.c new file mode 100644 index 0000000..dc294e6 --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_plat.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> +#include <sgi_plat.h> +#include <sgi_variant.h> + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT) + & SSC_VERSION_CONFIG_MASK; +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return 0; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/plat/arm/board/sgi575/sgi575_security.c b/plat/arm/board/sgi575/sgi575_security.c new file mode 100644 index 0000000..17d07d1 --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_security.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <common/debug.h> +#include <sgi_dmc620_tzc_regions.h> + +uintptr_t sgi575_dmc_base[] = { + SGI575_DMC620_BASE0, + SGI575_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t sgi575_plat_driver_data = { + .dmc_base = sgi575_dmc_base, + .dmc_count = ARRAY_SIZE(sgi575_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t sgi575_acc_addr_data[] = { + CSS_SGI_DMC620_TZC_REGIONS_DEF +}; + +static const tzc_dmc620_config_data_t sgi575_plat_config_data = { + .plat_drv_data = &sgi575_plat_driver_data, + .plat_acc_addr_data = sgi575_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(sgi575_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&sgi575_plat_config_data); +} diff --git a/plat/arm/board/sgi575/sgi575_topology.c b/plat/arm/board/sgi575/sgi575_topology.c new file mode 100644 index 0000000..f7c3856 --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_topology.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +static const unsigned char sgi575_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return sgi575_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + 0, 1, 2, 3, 4, 5, 6, 7 +}; diff --git a/plat/arm/board/sgi575/sgi575_trusted_boot.c b/plat/arm/board/sgi575/sgi575_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/plat/arm/board/sgi575/sgi575_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/tc/fdts/tc_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts new file mode 100644 index 0000000..a84c7f8 --- /dev/null +++ b/plat/arm/board/tc/fdts/tc_fw_config.dts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x400>; + id = <TB_FW_CONFIG_ID>; + }; + + tos_fw-config { + load-address = <0x0 0x04001700>; + max-size = <0x1000>; + id = <TOS_FW_CONFIG_ID>; + }; + + hw-config { + load-address = <0x0 0x83000000>; + max-size = <0x8000>; + id = <HW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts new file mode 100644 index 0000000..d3a5e1a --- /dev/null +++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0xfd000000>; + entrypoint = <0x0 0xfd000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "cactus-primary"; + load_address = <0xfe000000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm2 { + is_ffa_partition; + debug_name = "cactus-secondary"; + load_address = <0xfe100000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm3 { + is_ffa_partition; + debug_name = "cactus-tertiary"; + load_address = <0xfe200000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + vm4 { + is_ffa_partition; + debug_name = "ivy"; + load_address = <0xfe600000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + /* + * SPMC (Hafnium) requires secondary cpu nodes are declared in + * descending order + */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + }; + + /* 32MB of TC_TZC_DRAM1_BASE */ + memory@fd000000 { + device_type = "memory"; + reg = <0x0 0xfd000000 0x2000000>; + }; +}; diff --git a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000..92e2ddd --- /dev/null +++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0xfd000000>; + entrypoint = <0x0 0xfd000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "op-tee"; + load_address = <0xfd280000>; + vcpu_count = <8>; +#ifdef TS_SP_FW_CONFIG + mem_size = <26738688>; /* 25MB TZC DRAM */ +#else + mem_size = <30928896>; /* 29MB TZC DRAM */ +#endif + }; +#ifdef TS_SP_FW_CONFIG + vm2 { + is_ffa_partition; + debug_name = "internal-trusted-storage"; + load_address = <0xfee00000>; + vcpu_count = <1>; + mem_size = <2097152>; /* 2MB TZC DRAM */ + }; + vm3 { + is_ffa_partition; + debug_name = "crypto"; + load_address = <0xfec00000>; + vcpu_count = <1>; + mem_size = <2097152>; /* 2MB TZC DRAM */ + }; +#endif + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + /* + * SPMC (Hafnium) requires secondary cpu nodes are declared in + * descending order + */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + }; + + /* 32MB of TC_TZC_DRAM1_BASE */ + memory@fd000000 { + device_type = "memory"; + reg = <0x0 0xfd000000 0x2000000>; + }; +}; diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts new file mode 100644 index 0000000..4c6ccef --- /dev/null +++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/libc/cdefs.h> + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; + + secure-partitions { + compatible = "arm,sp"; +#ifdef ARM_BL2_SP_LIST_DTS + #include __XSTRING(ARM_BL2_SP_LIST_DTS) +#else +#ifdef TS_SP_FW_CONFIG + internal-trusted-storage { + uuid = "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14"; + load-address = <0xfee00000>; + }; + crypto { + uuid = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0"; + load-address = <0xfec00000>; + }; +#endif +#if OPTEE_SP_FW_CONFIG + op-tee { + uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b"; + load-address = <0xfd280000>; + }; +#else + cactus-primary { + uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb"; + load-address = <0xfe000000>; + owner = "SiP"; + }; + + cactus-secondary { + uuid = "d1582309-f023-47b9-827c-4464f5578fc8"; + load-address = <0xfe100000>; + owner = "Plat"; + }; + + cactus-tertiary { + uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2"; + load-address = <0xfe200000>; + }; + + ivy { + uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7"; + load-address = <0xfe600000>; + owner = "Plat"; + }; +#endif +#endif /* ARM_BL2_SP_LIST_DTS */ + }; +}; diff --git a/plat/arm/board/tc/include/plat_macros.S b/plat/arm/board/tc/include/plat_macros.S new file mode 100644 index 0000000..6006fa5 --- /dev/null +++ b/plat/arm/board/tc/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <arm_macros.S> + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h new file mode 100644 index 0000000..bc4f254 --- /dev/null +++ b/plat/arm/board/tc/include/platform_def.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <plat/arm/board/common/board_css_def.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/common/arm_def.h> +#include <plat/arm/common/arm_spm_def.h> +#include <plat/arm/css/common/css_def.h> +#include <plat/arm/soc/common/soc_css_def.h> +#include <plat/common/common_def.h> + +#define PLATFORM_CORE_COUNT 8 + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ + +/* + * The top 16MB of ARM_DRAM1 is configured as secure access only using the TZC, + * its base is ARM_AP_TZC_DRAM1_BASE. + * + * Reserve 32MB below ARM_AP_TZC_DRAM1_BASE for: + * - BL32_BASE when SPD_spmd is enabled + * - Region to load Trusted OS + */ +#define TC_TZC_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \ + TC_TZC_DRAM1_SIZE) +#define TC_TZC_DRAM1_SIZE UL(0x02000000) /* 32 MB */ +#define TC_TZC_DRAM1_END (TC_TZC_DRAM1_BASE + \ + TC_TZC_DRAM1_SIZE - 1) + +#define TC_NS_DRAM1_BASE ARM_DRAM1_BASE +#define TC_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE - \ + TC_TZC_DRAM1_SIZE) +#define TC_NS_DRAM1_END (TC_NS_DRAM1_BASE + \ + TC_NS_DRAM1_SIZE - 1) + +/* + * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure) + */ +#define TC_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + TC_NS_DRAM1_BASE, \ + TC_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + + +#define TC_MAP_TZC_DRAM1 MAP_REGION_FLAT( \ + TC_TZC_DRAM1_BASE, \ + TC_TZC_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define PLAT_HW_CONFIG_DTB_BASE ULL(0x83000000) +#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000) + +#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT( \ + PLAT_HW_CONFIG_DTB_BASE, \ + PLAT_HW_CONFIG_DTB_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) +/* + * Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to + * max size of BL32 image. + */ +#if defined(SPD_spmd) +#define PLAT_ARM_SPMC_BASE TC_TZC_DRAM1_BASE +#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */ +#endif + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL31) +# if SPM_MM +# define PLAT_ARM_MMAP_ENTRIES 9 +# define MAX_XLAT_TABLES 7 +# define PLAT_SP_IMAGE_MMAP_REGIONS 7 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 +# else +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 8 +# endif +#elif defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 5 +#elif !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 7 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xD000 + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000 +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0 +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. Current size is considering that TRUSTED_BOARD_BOOT + * and MEASURED_BOOT is enabled. + */ +# define PLAT_ARM_MAX_BL2_SIZE 0x26000 + + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW. Current size is considering that TRUSTED_BOARD_BOOT and + * MEASURED_BOOT is enabled. + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x47000 + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x440 +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +# if SPM_MM +# define PLATFORM_STACK_SIZE 0x500 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/* + * In the current implementation the RoT Service request that requires the + * biggest message buffer is the RSS_DELEGATED_ATTEST_GET_PLATFORM_TOKEN. The + * maximum required buffer size is calculated based on the platform-specific + * needs of this request. + */ +#define PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE 0x500 + +#define TC_DEVICE_BASE 0x21000000 +#define TC_DEVICE_SIZE 0x5f000000 + +// TC_MAP_DEVICE covers different peripherals +// available to the platform +#define TC_MAP_DEVICE MAP_REGION_FLAT( \ + TC_DEVICE_BASE, \ + TC_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + + +#define TC_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + +#define PLAT_ARM_NSTIMER_FRAME_ID 0 + +#if (TARGET_PLATFORM >= 2) +#define PLAT_ARM_TRUSTED_ROM_BASE 0x1000 +#else +#define PLAT_ARM_TRUSTED_ROM_BASE 0x0 +#endif + +/* PLAT_ARM_TRUSTED_ROM_SIZE 512KB minus ROM base. */ +#define PLAT_ARM_TRUSTED_ROM_SIZE (0x00080000 - PLAT_ARM_TRUSTED_ROM_BASE) + +#define PLAT_ARM_NSRAM_BASE 0x06000000 +#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) +#define PLAT_ARM_DRAM2_END (PLAT_ARM_DRAM2_BASE + PLAT_ARM_DRAM2_SIZE - 1ULL) + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/*Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(100) + +#define PLAT_ARM_SCMI_CHANNEL_COUNT 1 + +#define PLAT_ARM_CLUSTER_COUNT U(1) +#define PLAT_MAX_CPUS_PER_CLUSTER U(8) +#define PLAT_MAX_PE_PER_CPU U(1) + +/* Message Handling Unit (MHU) base addresses */ +#define PLAT_CSS_MHU_BASE UL(0x45400000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +/* TC2: AP<->RSS MHUs */ +#define PLAT_RSS_AP_SND_MHU_BASE UL(0x2A840000) +#define PLAT_RSS_AP_RCV_MHU_BASE UL(0x2A850000) + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* + * Physical and virtual address space limits for MMU in AARCH64 + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x30080000) + +/* + * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current + * SCP_BL2 size plus a little space for growth. + */ +#define PLAT_CSS_MAX_SCP_BL2_SIZE 0x20000 + +/* + * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current + * SCP_BL2U size plus a little space for growth. + */ +#define PLAT_CSS_MAX_SCP_BL2U_SIZE 0x20000 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x25000000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT 4 + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_DEFAULT U(0) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT)) + +/* + * The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to + * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as + * secure. The second and third regions gives non secure access to rest of DRAM. + */ +#define TC_TZC_REGIONS_DEF \ + {TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END, \ + TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {PLAT_ARM_DRAM2_BASE, PLAT_ARM_DRAM2_END, \ + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS} + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S new file mode 100644 index 0000000..5f54856 --- /dev/null +++ b/plat/arm/board/tc/include/tc_helpers.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> +#include <cpu_macros.S> + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on TC. + * + * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) + + * (CPUId * PLAT_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * PLAT_MAX_CPUS_PER_CLUSTER + CPUId) * PLAT_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #PLAT_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x5, #PLAT_MAX_PE_PER_CPU + madd x0, x1, x5, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler diff --git a/plat/arm/board/tc/include/tc_plat.h b/plat/arm/board/tc/include/tc_plat.h new file mode 100644 index 0000000..28c0308 --- /dev/null +++ b/plat/arm/board/tc/include/tc_plat.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TC_PLAT_H +#define TC_PLAT_H + +void tc_bl31_common_platform_setup(void); + +#endif /* TC_PLAT_H */ diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk new file mode 100644 index 0000000..37ba229 --- /dev/null +++ b/plat/arm/board/tc/platform.mk @@ -0,0 +1,199 @@ +# Copyright (c) 2021-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +ifeq ($(TARGET_PLATFORM), 0) +$(warning Platform ${PLAT}$(TARGET_PLATFORM) is deprecated. \ +Some of the features might not work as expected) +endif + +ifeq ($(shell expr $(TARGET_PLATFORM) \<= 2), 0) + $(error TARGET_PLATFORM must be less than or equal to 2) +endif + +$(eval $(call add_define,TARGET_PLATFORM)) + +CSS_LOAD_SCP_IMAGES := 1 + +CSS_USE_SCMI_SDS_DRIVER := 1 + +RAS_EXTENSION := 0 + +SDEI_SUPPORT := 0 + +EL3_EXCEPTION_HANDLING := 0 + +HANDLE_EA_EL3_FIRST_NS := 0 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# When building for systems with hardware-assisted coherency, there's no need to +# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too. +USE_COHERENT_MEM := 0 + +GIC_ENABLE_V4_EXTN := 1 + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Enable SVE +ENABLE_SVE_FOR_NS := 1 +ENABLE_SVE_FOR_SWD := 1 + +# enable trace buffer control registers access to NS by default +ENABLE_TRBE_FOR_NS := 1 + +# enable trace system registers access to NS by default +ENABLE_SYS_REG_TRACE_FOR_NS := 1 + +# enable trace filter control registers access to NS by default +ENABLE_TRF_FOR_NS := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +ENT_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + +override NEED_BL2U := no + +override ARM_PLAT_MT := 1 + +TC_BASE = plat/arm/board/tc + +PLAT_INCLUDES += -I${TC_BASE}/include/ + +# CPU libraries for TARGET_PLATFORM=0 +ifeq (${TARGET_PLATFORM}, 0) +TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_x2.S +endif + +# CPU libraries for TARGET_PLATFORM=1 +ifeq (${TARGET_PLATFORM}, 1) +TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a715.S \ + lib/cpus/aarch64/cortex_x3.S +endif + +# CPU libraries for TARGET_PLATFORM=2 +ifeq (${TARGET_PLATFORM}, 2) +TC_CPU_SOURCES += lib/cpus/aarch64/cortex_hayes.S \ + lib/cpus/aarch64/cortex_hunter.S \ + lib/cpus/aarch64/cortex_hunter_elp_arm.S +endif + +INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c + +PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \ + ${TC_BASE}/include/tc_helpers.S + +BL1_SOURCES += ${INTERCONNECT_SOURCES} \ + ${TC_CPU_SOURCES} \ + ${TC_BASE}/tc_trusted_boot.c \ + ${TC_BASE}/tc_err.c \ + drivers/arm/sbsa/sbsa.c + +BL2_SOURCES += ${TC_BASE}/tc_security.c \ + ${TC_BASE}/tc_err.c \ + ${TC_BASE}/tc_trusted_boot.c \ + ${TC_BASE}/tc_bl2_setup.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${INTERCONNECT_SOURCES} \ + ${TC_CPU_SOURCES} \ + ${ENT_GIC_SOURCES} \ + ${TC_BASE}/tc_bl31_setup.c \ + ${TC_BASE}/tc_topology.c \ + lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${TC_BASE}/fdts/${PLAT}_fw_config.dts \ + ${TC_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +ifeq (${SPD},spmd) +ifeq ($(ARM_SPMC_MANIFEST_DTS),) +ARM_SPMC_MANIFEST_DTS := ${TC_BASE}/fdts/${PLAT}_spmc_manifest.dts +endif + +FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS} +TC_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TC_TOS_FW_CONFIG},--tos-fw-config,${TC_TOS_FW_CONFIG})) +endif + +#Device tree +TC_HW_CONFIG_DTS := fdts/tc.dts +TC_HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb +FDT_SOURCES += ${TC_HW_CONFIG_DTS} +$(eval TC_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC_HW_CONFIG_DTS))) + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TC_HW_CONFIG},--hw-config,${TC_HW_CONFIG})) + +override CTX_INCLUDE_AARCH32_REGS := 0 + +override CTX_INCLUDE_PAUTH_REGS := 1 + +override ENABLE_SPE_FOR_LOWER_ELS := 0 + +override ENABLE_AMU := 1 +override ENABLE_AMU_AUXILIARY_COUNTERS := 1 +override ENABLE_AMU_FCONF := 1 + +override ENABLE_MPMM := 1 +override ENABLE_MPMM_FCONF := 1 + +# Include Measured Boot makefile before any Crypto library makefile. +# Crypto library makefile may need default definitions of Measured Boot build +# flags present in Measured Boot makefile. +ifeq (${MEASURED_BOOT},1) + MEASURED_BOOT_MK := drivers/measured_boot/rss/rss_measured_boot.mk + $(info Including ${MEASURED_BOOT_MK}) + include ${MEASURED_BOOT_MK} + $(info Including rss_comms.mk) + include drivers/arm/rss/rss_comms.mk + + BL1_SOURCES += ${MEASURED_BOOT_SOURCES} \ + plat/arm/board/tc/tc_common_measured_boot.c \ + plat/arm/board/tc/tc_bl1_measured_boot.c \ + lib/psa/measured_boot.c \ + ${RSS_COMMS_SOURCES} + + BL2_SOURCES += ${MEASURED_BOOT_SOURCES} \ + plat/arm/board/tc/tc_common_measured_boot.c \ + plat/arm/board/tc/tc_bl2_measured_boot.c \ + lib/psa/measured_boot.c \ + ${RSS_COMMS_SOURCES} + +PLAT_INCLUDES += -Iinclude/lib/psa + +endif + +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/soc/common/soc_css.mk +include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/tc/tc_bl1_measured_boot.c b/plat/arm/board/tc/tc_bl1_measured_boot.c new file mode 100644 index 0000000..0d29c51 --- /dev/null +++ b/plat/arm/board/tc/tc_bl1_measured_boot.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <drivers/arm/rss_comms.h> +#include <drivers/measured_boot/rss/rss_measured_boot.h> +#include <lib/psa/measured_boot.h> + +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +/* Table with platform specific image IDs and metadata. Intentionally not a + * const struct, some members might set by bootloaders during trusted boot. + */ +struct rss_mboot_metadata tc_rss_mboot_metadata[] = { + { + .id = FW_CONFIG_ID, + .slot = U(6), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_FW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = TB_FW_CONFIG_ID, + .slot = U(7), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = BL2_IMAGE_ID, + .slot = U(8), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_BL2_STRING, + .lock_measurement = true }, + + { + .id = RSS_MBOOT_INVALID_ID } +}; + +void bl1_plat_mboot_init(void) +{ + /* Initialize the communication channel between AP and RSS */ + (void)rss_comms_init(PLAT_RSS_AP_SND_MHU_BASE, + PLAT_RSS_AP_RCV_MHU_BASE); + + rss_measured_boot_init(); +} + +void bl1_plat_mboot_finish(void) +{ + /* Nothing to do. */ +} diff --git a/plat/arm/board/tc/tc_bl2_measured_boot.c b/plat/arm/board/tc/tc_bl2_measured_boot.c new file mode 100644 index 0000000..7ea2c2e --- /dev/null +++ b/plat/arm/board/tc/tc_bl2_measured_boot.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <drivers/arm/rss_comms.h> +#include <drivers/measured_boot/rss/rss_measured_boot.h> +#include <lib/psa/measured_boot.h> + +#include <plat/common/common_def.h> +#include <platform_def.h> + +/* TC specific table with image IDs and metadata. Intentionally not a + * const struct, some members might set by bootloaders during trusted boot. + */ +struct rss_mboot_metadata tc_rss_mboot_metadata[] = { + { + .id = BL31_IMAGE_ID, + .slot = U(9), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_BL31_STRING, + .lock_measurement = true }, + { + .id = HW_CONFIG_ID, + .slot = U(10), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_HW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = SOC_FW_CONFIG_ID, + .slot = U(11), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING, + .lock_measurement = true }, + { + .id = RSS_MBOOT_INVALID_ID } +}; + +void bl2_plat_mboot_init(void) +{ + /* Initialize the communication channel between AP and RSS */ + (void)rss_comms_init(PLAT_RSS_AP_SND_MHU_BASE, + PLAT_RSS_AP_RCV_MHU_BASE); + + rss_measured_boot_init(); +} + +void bl2_plat_mboot_finish(void) +{ + /* Nothing to do. */ +} diff --git a/plat/arm/board/tc/tc_bl2_setup.c b/plat/arm/board/tc/tc_bl2_setup.c new file mode 100644 index 0000000..74ef569 --- /dev/null +++ b/plat/arm/board/tc/tc_bl2_setup.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params = arm_get_next_bl_params(); + + const struct dyn_cfg_dtb_info_t *fw_config_info; + bl_mem_params_node_t *param_node; + uintptr_t fw_config_base = 0U; + entry_point_info_t *ep_info; + + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); + assert(param_node != NULL); + + /* Get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0U); + + /* + * Get the entry point info of BL31 image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; + + return arm_bl_params; +} diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c new file mode 100644 index 0000000..0523ef8 --- /dev/null +++ b/plat/arm/board/tc/tc_bl31_setup.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <libfdt.h> +#include <tc_plat.h> + +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/arm/css/css_mhu_doorbell.h> +#include <drivers/arm/css/scmi.h> +#include <lib/fconf/fconf.h> +#include <lib/fconf/fconf_dyn_cfg_getter.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +static scmi_channel_plat_info_t tc_scmi_plat_info[] = { + { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, + } +}; + +void bl31_platform_setup(void) +{ + tc_bl31_common_platform_setup(); +} + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + + return &tc_scmi_plat_info[channel_id]; + +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); +} + +void tc_bl31_common_platform_setup(void) +{ + arm_bl31_platform_setup(); +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); + + /* HW_CONFIG was also loaded by BL2 */ + const struct dyn_cfg_dtb_info_t *hw_config_info; + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + fconf_populate("HW_CONFIG", hw_config_info->config_addr); +} diff --git a/plat/arm/board/tc/tc_common_measured_boot.c b/plat/arm/board/tc/tc_common_measured_boot.c new file mode 100644 index 0000000..fe71899 --- /dev/null +++ b/plat/arm/board/tc/tc_common_measured_boot.c @@ -0,0 +1,35 @@ + +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> + +#include <common/desc_image_load.h> +#include <drivers/measured_boot/rss/rss_measured_boot.h> + +extern struct rss_mboot_metadata tc_rss_mboot_metadata[]; + +struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void) +{ + return tc_rss_mboot_metadata; +} + +int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data) +{ + int err; + + /* Calculate image hash and record data in RSS */ + err = rss_mboot_measure_and_record(image_data->image_base, + image_data->image_size, + image_id); + if (err != 0) { + ERROR("%s%s image id %u (%i)\n", + "Failed to ", "record in RSS", image_id, err); + } + + return err; +} diff --git a/plat/arm/board/tc/tc_err.c b/plat/arm/board/tc/tc_err.c new file mode 100644 index 0000000..9ed7e92 --- /dev/null +++ b/plat/arm/board/tc/tc_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * tc error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/plat/arm/board/tc/tc_interconnect.c b/plat/arm/board/tc/tc_interconnect.c new file mode 100644 index 0000000..e2fc4e1 --- /dev/null +++ b/plat/arm/board/tc/tc_interconnect.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <plat/arm/common/plat_arm.h> + +/* + * For Total Compute we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void __init plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/plat/arm/board/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c new file mode 100644 index 0000000..77db023 --- /dev/null +++ b/plat/arm/board/tc/tc_plat.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <plat/common/platform.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/arm/ccn.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <drivers/arm/sbsa.h> + +#if SPM_MM +#include <services/spm_mm_partition.h> +#endif + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * arm_configure_mmu_elx() will give the available subset of that. + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + TC_FLASH0_RO, + TC_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + TC_FLASH0_RO, + TC_MAP_DEVICE, + TC_MAP_NS_DRAM1, +#if defined(SPD_spmd) + TC_MAP_TZC_DRAM1, +#endif +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#if SPM_MM + ARM_SP_IMAGE_MMAP, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + TC_MAP_DEVICE, + PLAT_DTB_DRAM_NS, +#if SPM_MM + ARM_SPM_BUF_EL3_MMAP, +#endif + {0} +}; + +#if SPM_MM && defined(IMAGE_BL31) +const mmap_region_t plat_arm_secure_partition_mmap[] = { + PLAT_ARM_SECURE_MAP_DEVICE, + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_CPER_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif /* SPM_MM && defined(IMAGE_BL31) */ +#endif + +ARM_CASSERT_MMAP + +#if SPM_MM && defined(IMAGE_BL31) +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x81000000, 0}, + [1] = {0x81000100, 0}, + [2] = {0x81000200, 0}, + [3] = {0x81000300, 0}, + [4] = {0x81010000, 0}, + [5] = {0x81010100, 0}, + [6] = {0x81010200, 0}, + [7] = {0x81010300, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} +#endif /* SPM_MM && defined(IMAGE_BL31) */ + +#if TRUSTED_BOARD_BOOT || MEASURED_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/plat/arm/board/tc/tc_security.c b/plat/arm/board/tc/tc_security.c new file mode 100644 index 0000000..6a34501 --- /dev/null +++ b/plat/arm/board/tc/tc_security.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + +static const arm_tzc_regions_info_t tzc_regions[] = { + TC_TZC_REGIONS_DEF, + {} +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + unsigned int i; + + for (i = 0U; i < TZC400_COUNT; i++) { + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + } +} diff --git a/plat/arm/board/tc/tc_topology.c b/plat/arm/board/tc/tc_topology.c new file mode 100644 index 0000000..9e18da6 --- /dev/null +++ b/plat/arm/board/tc/tc_topology.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char tc_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + PLAT_MAX_CPUS_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return tc_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), +}; + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return PLAT_MAX_CPUS_PER_CLUSTER; +} + +#if ARM_PLAT_MT +/****************************************************************************** + * Return the number of PE's supported by the CPU. + *****************************************************************************/ +unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr) +{ + return PLAT_MAX_PE_PER_CPU; +} +#endif diff --git a/plat/arm/board/tc/tc_trusted_boot.c b/plat/arm/board/tc/tc_trusted_boot.c new file mode 100644 index 0000000..614f7e2 --- /dev/null +++ b/plat/arm/board/tc/tc_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} |