From be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 19:43:51 +0200 Subject: Adding upstream version 2.10.0+dfsg. Signed-off-by: Daniel Baumann --- plat/arm/board/fvp/aarch32/fvp_helpers.S | 143 +++++ plat/arm/board/fvp/aarch64/fvp_ea.c | 54 ++ plat/arm/board/fvp/aarch64/fvp_helpers.S | 177 ++++++ plat/arm/board/fvp/aarch64/fvp_ras.c | 67 +++ plat/arm/board/fvp/fconf/fconf_hw_config_getter.c | 359 ++++++++++++ plat/arm/board/fvp/fconf/fconf_nt_config_getter.c | 64 +++ plat/arm/board/fvp/fdts/event_log.dtsi | 13 + plat/arm/board/fvp/fdts/fvp_fw_config.dts | 59 ++ plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts | 19 + plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts | 11 + plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts | 102 ++++ .../board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts | 64 +++ plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts | 127 +++++ plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts | 13 + plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts | 34 ++ plat/arm/board/fvp/fdts/optee_sp_manifest.dts | 44 ++ plat/arm/board/fvp/fvp_bl1_measured_boot.c | 80 +++ plat/arm/board/fvp/fvp_bl1_setup.c | 89 +++ plat/arm/board/fvp/fvp_bl2_el3_setup.c | 30 + plat/arm/board/fvp/fvp_bl2_measured_boot.c | 262 +++++++++ plat/arm/board/fvp/fvp_bl2_setup.c | 140 +++++ plat/arm/board/fvp/fvp_bl2u_setup.c | 22 + plat/arm/board/fvp/fvp_bl31_setup.c | 156 ++++++ plat/arm/board/fvp/fvp_common.c | 623 +++++++++++++++++++++ plat/arm/board/fvp/fvp_common_measured_boot.c | 54 ++ plat/arm/board/fvp/fvp_console.c | 54 ++ plat/arm/board/fvp/fvp_cpu_errata.mk | 63 +++ plat/arm/board/fvp/fvp_def.h | 181 ++++++ plat/arm/board/fvp/fvp_drtm_addr.c | 36 ++ plat/arm/board/fvp/fvp_drtm_dma_prot.c | 76 +++ plat/arm/board/fvp/fvp_drtm_err.c | 22 + plat/arm/board/fvp/fvp_drtm_measurement.c | 29 + plat/arm/board/fvp/fvp_drtm_stub.c | 35 ++ plat/arm/board/fvp/fvp_el3_spmc.c | 47 ++ plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c | 66 +++ plat/arm/board/fvp/fvp_err.c | 43 ++ plat/arm/board/fvp/fvp_gicv3.c | 174 ++++++ plat/arm/board/fvp/fvp_io_storage.c | 174 ++++++ plat/arm/board/fvp/fvp_plat_attest_token.c | 118 ++++ plat/arm/board/fvp/fvp_pm.c | 455 +++++++++++++++ plat/arm/board/fvp/fvp_private.h | 24 + plat/arm/board/fvp/fvp_realm_attest_key.c | 36 ++ plat/arm/board/fvp/fvp_security.c | 42 ++ plat/arm/board/fvp/fvp_spmd.c | 17 + plat/arm/board/fvp/fvp_spmd_logical_sp.c | 99 ++++ plat/arm/board/fvp/fvp_stack_protector.c | 24 + plat/arm/board/fvp/fvp_sync_traps.c | 62 ++ plat/arm/board/fvp/fvp_topology.c | 123 ++++ plat/arm/board/fvp/fvp_trusted_boot.c | 116 ++++ .../arm/board/fvp/include/fconf_hw_config_getter.h | 60 ++ .../arm/board/fvp/include/fconf_nt_config_getter.h | 27 + plat/arm/board/fvp/include/fvp_critical_data.h | 23 + plat/arm/board/fvp/include/plat.ld.S | 15 + plat/arm/board/fvp/include/plat_macros.S | 42 ++ plat/arm/board/fvp/include/platform_def.h | 469 ++++++++++++++++ plat/arm/board/fvp/jmptbl.i | 65 +++ plat/arm/board/fvp/platform.mk | 546 ++++++++++++++++++ plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c | 122 ++++ plat/arm/board/fvp/sp_min/sp_min-fvp.mk | 39 ++ plat/arm/board/fvp/trp/trp-fvp.mk | 12 + plat/arm/board/fvp/tsp/fvp_tsp_setup.c | 17 + plat/arm/board/fvp/tsp/tsp-fvp.mk | 14 + 62 files changed, 6373 insertions(+) create mode 100644 plat/arm/board/fvp/aarch32/fvp_helpers.S create mode 100644 plat/arm/board/fvp/aarch64/fvp_ea.c create mode 100644 plat/arm/board/fvp/aarch64/fvp_helpers.S create mode 100644 plat/arm/board/fvp/aarch64/fvp_ras.c create mode 100644 plat/arm/board/fvp/fconf/fconf_hw_config_getter.c create mode 100644 plat/arm/board/fvp/fconf/fconf_nt_config_getter.c create mode 100644 plat/arm/board/fvp/fdts/event_log.dtsi create mode 100644 plat/arm/board/fvp/fdts/fvp_fw_config.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts create mode 100644 plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts create mode 100644 plat/arm/board/fvp/fdts/optee_sp_manifest.dts create mode 100644 plat/arm/board/fvp/fvp_bl1_measured_boot.c create mode 100644 plat/arm/board/fvp/fvp_bl1_setup.c create mode 100644 plat/arm/board/fvp/fvp_bl2_el3_setup.c create mode 100644 plat/arm/board/fvp/fvp_bl2_measured_boot.c create mode 100644 plat/arm/board/fvp/fvp_bl2_setup.c create mode 100644 plat/arm/board/fvp/fvp_bl2u_setup.c create mode 100644 plat/arm/board/fvp/fvp_bl31_setup.c create mode 100644 plat/arm/board/fvp/fvp_common.c create mode 100644 plat/arm/board/fvp/fvp_common_measured_boot.c create mode 100644 plat/arm/board/fvp/fvp_console.c create mode 100644 plat/arm/board/fvp/fvp_cpu_errata.mk create mode 100644 plat/arm/board/fvp/fvp_def.h create mode 100644 plat/arm/board/fvp/fvp_drtm_addr.c create mode 100644 plat/arm/board/fvp/fvp_drtm_dma_prot.c create mode 100644 plat/arm/board/fvp/fvp_drtm_err.c create mode 100644 plat/arm/board/fvp/fvp_drtm_measurement.c create mode 100644 plat/arm/board/fvp/fvp_drtm_stub.c create mode 100644 plat/arm/board/fvp/fvp_el3_spmc.c create mode 100644 plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c create mode 100644 plat/arm/board/fvp/fvp_err.c create mode 100644 plat/arm/board/fvp/fvp_gicv3.c create mode 100644 plat/arm/board/fvp/fvp_io_storage.c create mode 100644 plat/arm/board/fvp/fvp_plat_attest_token.c create mode 100644 plat/arm/board/fvp/fvp_pm.c create mode 100644 plat/arm/board/fvp/fvp_private.h create mode 100644 plat/arm/board/fvp/fvp_realm_attest_key.c create mode 100644 plat/arm/board/fvp/fvp_security.c create mode 100644 plat/arm/board/fvp/fvp_spmd.c create mode 100644 plat/arm/board/fvp/fvp_spmd_logical_sp.c create mode 100644 plat/arm/board/fvp/fvp_stack_protector.c create mode 100644 plat/arm/board/fvp/fvp_sync_traps.c create mode 100644 plat/arm/board/fvp/fvp_topology.c create mode 100644 plat/arm/board/fvp/fvp_trusted_boot.c create mode 100644 plat/arm/board/fvp/include/fconf_hw_config_getter.h create mode 100644 plat/arm/board/fvp/include/fconf_nt_config_getter.h create mode 100644 plat/arm/board/fvp/include/fvp_critical_data.h create mode 100644 plat/arm/board/fvp/include/plat.ld.S create mode 100644 plat/arm/board/fvp/include/plat_macros.S create mode 100644 plat/arm/board/fvp/include/platform_def.h create mode 100644 plat/arm/board/fvp/jmptbl.i create mode 100644 plat/arm/board/fvp/platform.mk create mode 100644 plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c create mode 100644 plat/arm/board/fvp/sp_min/sp_min-fvp.mk create mode 100644 plat/arm/board/fvp/trp/trp-fvp.mk create mode 100644 plat/arm/board/fvp/tsp/fvp_tsp_setup.c create mode 100644 plat/arm/board/fvp/tsp/tsp-fvp.mk (limited to 'plat/arm/board/fvp') 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 +#include +#include +#include + + .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_ea.c b/plat/arm/board/fvp/aarch64/fvp_ea.c new file mode 100644 index 0000000..07053a9 --- /dev/null +++ b/plat/arm/board/fvp/aarch64/fvp_ea.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * This source file with custom plat_ea_handler function is compiled only when + * building TF-A with compile option PLATFORM_TEST_EA_FFH + */ + +/* Test address(non-existent) used in tftf to cause External aborts */ +#define TEST_ADDRESS UL(0x7FFFF000) + +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ +#ifdef PLATFORM_TEST_EA_FFH + u_register_t elr_el3; + u_register_t fault_address; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + el3_state_t *el3_ctx = get_el3state_ctx(ctx); + gp_regs_t *gpregs_ctx = get_gpregs_ctx(ctx); + unsigned int level = (unsigned int)GET_EL(read_spsr_el3()); + + fault_address = read_ctx_reg(gpregs_ctx, CTX_GPREG_X0); + + if ((level < MODE_EL3) && (fault_address == TEST_ADDRESS)) { + if (ea_reason == ERROR_EA_SYNC) { + INFO("Handled sync EA from lower EL at address 0x%lx\n", fault_address); + /* To avoid continuous faults, forward return address */ + elr_el3 = read_ctx_reg(el3_ctx, CTX_ELR_EL3); + elr_el3 += 4; + write_ctx_reg(el3_ctx, CTX_ELR_EL3, elr_el3); + return; + } else if (ea_reason == ERROR_EA_ASYNC) { + INFO("Handled Serror from lower EL at address 0x%lx\n", fault_address); + return; + } + } +#endif + plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags); +} 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 +#include +#include +#include +#include +#include + + .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..f9b9634 --- /dev/null +++ b/plat/arm/board/fvp/aarch64/fvp_ras.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#ifdef PLATFORM_TEST_RAS_FFH +static int injected_fault_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data) +{ + uint64_t status; + int ret; + + /* + * The faulting error record is already selected by the SER probe + * function. + */ + status = read_erxstatus_el1(); + + ERROR("Fault reported by system error record %d on 0x%lx: status=0x%" PRIx64 "\n", + probe_data, read_mpidr_el1(), status); + ERROR(" exception reason=%u syndrome=0x%" PRIx64 "\n", data->ea_reason, + data->flags); + + /* Clear error */ + write_erxstatus_el1(status); + + ret = sdei_dispatch_event(5000); + if (ret < 0) { + ERROR("Can't dispatch event to SDEI\n"); + panic(); + } else { + INFO("SDEI event dispatched\n"); + } + + return 0; +} + +void plat_handle_uncontainable_ea(void) +{ + /* Do not change the string, CI expects it. Wait forever */ + INFO("Injected Uncontainable Error\n"); + while (true) { + wfe(); + } +} +#endif + +struct ras_interrupt fvp_ras_interrupts[] = { +}; + +struct err_record_info fvp_err_records[] = { +#ifdef PLATFORM_TEST_RAS_FFH + /* Record for injected fault */ + ERR_RECORD_SYSREG_V1(0, 2, ras_err_ser_probe_sysreg, + injected_fault_handler, NULL), +#endif +}; + +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..43dc17b --- /dev/null +++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2020-2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +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; +struct ns_dram_layout dram_layout; + +/* + * Each NS DRAM bank entry is 'reg' node property which is + * a sequence of (address, length) pairs of 32-bit values. + */ +#define DRAM_ENTRY_SIZE (4UL * sizeof(uint32_t)) + +CASSERT(ARM_DRAM_NUM_BANKS == 2UL, ARM_DRAM_NUM_BANKS_mismatch); + +#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; +} + +int fconf_populate_dram_layout(uintptr_t config) +{ + int node, len; + const uint32_t *reg; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* Find 'memory' node */ + node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type", + "memory", sizeof("memory")); + if (node < 0) { + WARN("FCONF: Unable to locate 'memory' node\n"); + return node; + } + + reg = fdt_getprop(hw_config_dtb, node, "reg", &len); + if (reg == NULL) { + ERROR("FCONF failed to read 'reg' property\n"); + return len; + } + + switch (len) { + case DRAM_ENTRY_SIZE: + /* 1 DRAM bank */ + dram_layout.num_banks = 1UL; + break; + case 2UL * DRAM_ENTRY_SIZE: + /* 2 DRAM banks */ + dram_layout.num_banks = 2UL; + break; + default: + ERROR("FCONF: Invalid 'memory' node\n"); + return -FDT_ERR_BADLAYOUT; + } + + for (unsigned long i = 0UL; i < dram_layout.num_banks; i++) { + int err = fdt_get_reg_props_by_index( + hw_config_dtb, node, (int)i, + &dram_layout.dram_bank[i].base, + (size_t *)&dram_layout.dram_bank[i].size); + if (err < 0) { + ERROR("FCONF: Failed to read 'reg' property #%lu of 'memory' node\n", i); + return err; + } + } + + 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); +FCONF_REGISTER_POPULATOR(HW_CONFIG, dram_layout, fconf_populate_dram_layout); 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 +#include + +#include +#include + +#include + +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..8e26542 --- /dev/null +++ b/plat/arm/board/fvp/fdts/event_log.dtsi @@ -0,0 +1,13 @@ +/* + * 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>; + tpm_event_log_max_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..4adf5d5 --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019-2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x1800>; + id = ; + }; + + hw-config { + load-address = <0x0 0x07f00000>; + max-size = <0x00100000>; + id = ; + secondary-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 = ; + }; + +/* 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>; +#if ENABLE_RME + secondary-load-address = <0x0 0x7e00000>; +#endif /* ENABLE_RME */ + max-size = <0xB00>; + id = ; + }; +#endif + + nt_fw-config { + load-address = <0x0 0x80000000>; + max-size = <0x200>; + 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..e159248 --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2020-2023, 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 = <2>; + + 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>; + /* + * Platform specific SiP SMC call handled at EL3. Used + * to pend an interrupt for testing purpose. + */ + smc_whitelist = <0x82000100>; + }; + 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@0 { + device_type = "memory"; + reg = <0x0 0xfd000000 0x0 0x2000000>, + <0x0 0x7000000 0x0 0x1000000>, + <0x0 0xff000000 0x0 0x1000000>; + }; + + memory@1 { + device_type = "ns-memory"; + reg = <0x00008800 0x80000000 0x0 0x7f000000>, + <0x0 0x88000000 0x0 0x10000000>; + }; + +#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..6ba76db --- /dev/null +++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020-2023, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/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"; + plat_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 = ; +}; + +&non_trusted_nv_counter { + reg = ; +}; +#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 = ; + 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..dc95ba1 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* 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, + .pk_oid = ZERO_OID, + .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, + .pk_oid = ZERO_OID, + .lock_measurement = true }, + { + .id = BL2_IMAGE_ID, + .slot = U(8), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_BL2_STRING, + .pk_oid = ZERO_OID, + .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(fvp_rss_mboot_metadata); +} + +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, + PLAT_ARM_EVENT_LOG_MAX_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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 + +#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..349e064 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#if defined(ARM_COT_cca) +#include +#else +#include +#endif /* ARM_COT_cca */ +#include + +#include +#include + +#if defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd) +CASSERT(ARM_EVENT_LOG_DRAM1_SIZE >= PLAT_ARM_EVENT_LOG_MAX_SIZE, \ + assert_res_eventlog_mem_insufficient); +#endif /* defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd) */ + +/* 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, + .pk_oid = BL31_IMAGE_KEY_OID, + .lock_measurement = true }, + { + .id = HW_CONFIG_ID, + .slot = U(10), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_HW_CONFIG_STRING, + .pk_oid = HW_CONFIG_KEY_OID, + .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, + .pk_oid = SOC_FW_CONFIG_KEY_OID, + .lock_measurement = true }, +#if ENABLE_RME + { + .id = RMM_IMAGE_ID, + .slot = U(12), + .signer_id_size = SIGNER_ID_MIN_SIZE, + .sw_type = RSS_MBOOT_RMM_STRING, + .pk_oid = RMM_IMAGE_KEY_OID, + .lock_measurement = true }, +#endif /* ENABLE_RME */ + { + .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; + size_t event_log_max_size; + int rc; + + rc = arm_get_tb_fw_info(&event_log_base, &bl1_event_log_size, + &event_log_max_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 + + event_log_max_size); + + event_log_init((uint8_t *)event_log_start, event_log_finish); + + rss_measured_boot_init(fvp_rss_mboot_metadata); +} + +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, + fvp_event_log_metadata); + 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); + +#if defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd) + /* Copy Event Log to TZC secured DRAM memory */ + (void)memcpy((void *)ARM_EVENT_LOG_DRAM1_BASE, + (const void *)event_log_base, + event_log_cur_size); + + /* Ensure that the Event Log is visible in TZC secured DRAM memory */ + flush_dcache_range(ARM_EVENT_LOG_DRAM1_BASE, event_log_cur_size); +#endif /* defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd) */ + + rc = arm_set_nt_fw_info( +#ifdef SPD_opteed + (uintptr_t)ARM_EVENT_LOG_DRAM1_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)ARM_EVENT_LOG_DRAM1_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..ebd5266 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2_setup.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fvp_private.h" + +static struct transfer_list_header *ns_tl __unused; + +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(); + +#if TRANSFER_LIST + ns_tl = transfer_list_init((void *)FW_NS_HANDOFF_BASE, FW_HANDOFF_SIZE); + assert(ns_tl != NULL); +#endif + /* 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; + struct transfer_list_entry *te __unused; + bl_mem_params_node_t *param_node __unused; + + arm_bl_params = arm_get_next_bl_params(); + +#if !RESET_TO_BL2 && !EL3_PAYLOAD_BASE + const struct dyn_cfg_dtb_info_t *fw_config_info; + uintptr_t fw_config_base = 0UL; + +#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); + + /* Update the next image's ep info with the FW config 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); + + param_node->ep_info.args.arg1 = (uint32_t)fw_config_base; + + /* Update BL33's ep info with the NS HW config address */ + param_node = get_bl_mem_params_node(BL33_IMAGE_ID); + assert(param_node != NULL); + +#if TRANSFER_LIST + /* Update BL33's ep info with NS HW config address */ + te = transfer_list_find(ns_tl, TL_TAG_FDT); + assert(te != NULL); + + param_node->ep_info.args.arg1 = TRANSFER_LIST_SIGNATURE | + REGISTER_CONVENTION_VERSION_MASK; + param_node->ep_info.args.arg2 = 0; + param_node->ep_info.args.arg3 = (uintptr_t)ns_tl; + param_node->ep_info.args.arg0 = + te ? (uintptr_t)transfer_list_entry_data(te) : 0; +#else + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + param_node->ep_info.args.arg1 = hw_config_info->secondary_config_addr; +#endif /* TRANSFER_LIST */ +#endif /* !RESET_TO_BL2 && !EL3_PAYLOAD_BASE */ + + return arm_bl_params; +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ +#if !RESET_TO_BL2 && !EL3_PAYLOAD_BASE + if (image_id == HW_CONFIG_ID) { + const struct dyn_cfg_dtb_info_t *hw_config_info; + struct transfer_list_entry *te __unused; + + const bl_mem_params_node_t *param_node = + get_bl_mem_params_node(image_id); + assert(param_node != NULL); + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + +#if TRANSFER_LIST + /* Update BL33's ep info with NS HW config address */ + te = transfer_list_add(ns_tl, TL_TAG_FDT, + param_node->image_info.image_size, + (void *)hw_config_info->config_addr); + assert(te != NULL); +#else + memcpy((void *)hw_config_info->secondary_config_addr, + (void *)hw_config_info->config_addr, + (size_t)param_node->image_info.image_size); + + /* + * Ensure HW-config device tree is committed to memory, as the HW-Config + * might be used without cache and MMU enabled at BL33. + */ + flush_dcache_range(hw_config_info->secondary_config_addr, + param_node->image_info.image_size); +#endif /* TRANSFER_LIST */ + } +#endif /* !RESET_TO_BL2 && !EL3_PAYLOAD_BASE */ + + return arm_bl2_plat_handle_post_image_load(image_id); +} 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 +#include +#include + +#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..e46dbc9 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl31_setup.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 && !RESET_TO_BL2 + 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->secondary_config_addr != 0UL); + arg2 = hw_config_info->secondary_config_addr; +#endif /* !RESET_TO_BL31 && !RESET_TO_BL2 */ + + 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 && !RESET_TO_BL2 && !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 && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1 */ +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + +#if !RESET_TO_BL31 && !RESET_TO_BL2 + /* 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..c40a3ce --- /dev/null +++ b/plat/arm/board/fvp/fvp_common.c @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if SPM_MM +#include +#endif + +#include +#include +#include +#include + +#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) + +#if TRANSFER_LIST +#ifdef FW_NS_HANDOFF_BASE +#define MAP_FW_NS_HANDOFF MAP_REGION_FLAT(FW_NS_HANDOFF_BASE, \ + FW_HANDOFF_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) +#endif +#endif + +/* + * 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, + + /* + * Required to load Event Log in TZC secured memory + */ +#if MEASURED_BOOT && (defined(SPD_tspd) || defined(SPD_opteed) || \ +defined(SPD_spmd)) + ARM_MAP_EVENT_LOG_DRAM1, +#endif /* MEASURED_BOOT && (SPD_tspd || SPD_opteed || SPD_spmd) */ + +#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 && !RESET_TO_BL2 + /* + * To access shared the Mbed TLS heap while booting the + * system with Crypto support + */ + ARM_MAP_BL1_RW, +#endif /* CRYPTO_SUPPORT && !RESET_TO_BL2 */ +#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 +#ifdef MAP_FW_NS_HANDOFF + MAP_FW_NS_HANDOFF, +#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(struct rmm_manifest *manifest) +{ + uint64_t checksum, num_banks; + struct ns_dram_bank *bank_ptr; + + assert(manifest != NULL); + + /* Get number of DRAM banks */ + num_banks = FCONF_GET_PROPERTY(hw_config, dram_layout, num_banks); + assert(num_banks <= ARM_DRAM_NUM_BANKS); + + manifest->version = RMMD_MANIFEST_VERSION; + manifest->padding = 0U; /* RES0 */ + manifest->plat_data = (uintptr_t)NULL; + manifest->plat_dram.num_banks = num_banks; + + /* + * Array ns_dram_banks[] follows ns_dram_info structure: + * + * +-----------------------------------+ + * | offset | field | comment | + * +----------+-----------+------------+ + * | 0 | version | 0x00000002 | + * +----------+-----------+------------+ + * | 4 | padding | 0x00000000 | + * +----------+-----------+------------+ + * | 8 | plat_data | NULL | + * +----------+-----------+------------+ + * | 16 | num_banks | | + * +----------+-----------+ | + * | 24 | banks | plat_dram | + * +----------+-----------+ | + * | 32 | checksum | | + * +----------+-----------+------------+ + * | 40 | base 0 | | + * +----------+-----------+ bank[0] | + * | 48 | size 0 | | + * +----------+-----------+------------+ + * | 56 | base 1 | | + * +----------+-----------+ bank[1] | + * | 64 | size 1 | | + * +----------+-----------+------------+ + */ + bank_ptr = (struct ns_dram_bank *) + ((uintptr_t)&manifest->plat_dram.checksum + + sizeof(manifest->plat_dram.checksum)); + + manifest->plat_dram.banks = bank_ptr; + + /* Calculate checksum of plat_dram structure */ + checksum = num_banks + (uint64_t)bank_ptr; + + /* Store FVP DRAM banks data in Boot Manifest */ + for (unsigned long i = 0UL; i < num_banks; i++) { + uintptr_t base = FCONF_GET_PROPERTY(hw_config, dram_layout, dram_bank[i].base); + uint64_t size = FCONF_GET_PROPERTY(hw_config, dram_layout, dram_bank[i].size); + + bank_ptr[i].base = base; + bank_ptr[i].size = size; + + /* Update checksum */ + checksum += base + size; + } + + /* Checksum must be 0 */ + manifest->plat_dram.checksum = ~checksum + 1UL; + + return 0; +} +#endif /* ENABLE_RME */ 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..0c1d5e7 --- /dev/null +++ b/plat/arm/board/fvp/fvp_common_measured_boot.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +extern event_log_metadata_t fvp_event_log_metadata[]; +extern struct rss_mboot_metadata 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, + fvp_event_log_metadata); + 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(fvp_rss_mboot_metadata, + 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; +} + +int plat_mboot_measure_key(const void *pk_oid, const void *pk_ptr, + size_t pk_len) +{ + return rss_mboot_set_signer_id(fvp_rss_mboot_metadata, pk_oid, pk_ptr, + pk_len); +} diff --git a/plat/arm/board/fvp/fvp_console.c b/plat/arm/board/fvp/fvp_console.c new file mode 100644 index 0000000..3aa454b --- /dev/null +++ b/plat/arm/board/fvp/fvp_console.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +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 + * RESET_TO_BL2 systems. + */ +#if RESET_TO_SP_MIN || RESET_TO_BL31 || RESET_TO_BL2 + 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_cpu_errata.mk b/plat/arm/board/fvp/fvp_cpu_errata.mk new file mode 100644 index 0000000..b8fa4ea --- /dev/null +++ b/plat/arm/board/fvp/fvp_cpu_errata.mk @@ -0,0 +1,63 @@ +# +# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +#/* +# * TODO: below lines of code to be removed +# * after abi and framework are synchronized +# */ + +ifeq (${ERRATA_ABI_SUPPORT}, 1) +# enable the cpu macros for errata abi interface +ifeq (${ARCH}, aarch64) +ifeq (${HW_ASSISTED_COHERENCY}, 0) +CORTEX_A35_H_INC := 1 +CORTEX_A53_H_INC := 1 +CORTEX_A57_H_INC := 1 +CORTEX_A72_H_INC := 1 +CORTEX_A73_H_INC := 1 +$(eval $(call add_define, CORTEX_A35_H_INC)) +$(eval $(call add_define, CORTEX_A53_H_INC)) +$(eval $(call add_define, CORTEX_A57_H_INC)) +$(eval $(call add_define, CORTEX_A72_H_INC)) +$(eval $(call add_define, CORTEX_A73_H_INC)) +else +ifeq (${CTX_INCLUDE_AARCH32_REGS}, 0) +CORTEX_A76_H_INC := 1 +CORTEX_A77_H_INC := 1 +CORTEX_A78_H_INC := 1 +NEOVERSE_N1_H_INC := 1 +NEOVERSE_N2_H_INC := 1 +NEOVERSE_V1_H_INC := 1 +CORTEX_A78_AE_H_INC := 1 +CORTEX_A510_H_INC := 1 +CORTEX_A710_H_INC := 1 +CORTEX_A715_H_INC := 1 +CORTEX_A78C_H_INC := 1 +CORTEX_X2_H_INC := 1 +$(eval $(call add_define, CORTEX_A76_H_INC)) +$(eval $(call add_define, CORTEX_A77_H_INC)) +$(eval $(call add_define, CORTEX_A78_H_INC)) +$(eval $(call add_define, NEOVERSE_N1_H_INC)) +$(eval $(call add_define, NEOVERSE_N2_H_INC)) +$(eval $(call add_define, NEOVERSE_V1_H_INC)) +$(eval $(call add_define, CORTEX_A78_AE_H_INC)) +$(eval $(call add_define, CORTEX_A510_H_INC)) +$(eval $(call add_define, CORTEX_A710_H_INC)) +$(eval $(call add_define, CORTEX_A715_H_INC)) +$(eval $(call add_define, CORTEX_A78C_H_INC)) +$(eval $(call add_define, CORTEX_X2_H_INC)) +endif +CORTEX_A55_H_INC := 1 +CORTEX_A75_H_INC := 1 +$(eval $(call add_define, CORTEX_A55_H_INC)) +$(eval $(call add_define, CORTEX_A75_H_INC)) +endif +else +CORTEX_A32_H_INC := 1 +$(eval $(call add_define, CORTEX_A32_H_INC)) +endif +endif 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 + +#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 + +#include +#include + +/******************************************************************************* + * 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 +#include + +#include +#include +#include +#include + +#include + +/** + * 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 + +#include + +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 +#include +#include + +#include +#include + +#include + +/* 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 + +#include + +/* + * 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..6b44f63 --- /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 + +#include + +/* + * 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..72dfa30 --- /dev/null +++ b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#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; + uint32_t src_dst; + + /* 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("LSP: Received Direct Request from %s world (0x%x)\n", + secure_origin ? "Secure" : "Normal", ffa_endpoint_source(x1)); + + /* Populate the source and destination IDs. */ + src_dst = (uint32_t) LP_PARTITION_ID << FFA_DIRECT_MSG_SOURCE_SHIFT | + ffa_endpoint_source(x1) << FFA_DIRECT_MSG_DESTINATION_SHIFT; + /* + * Logical SP's must always send a direct response so we can populate + * our response directly. + */ + SMC_RET8(handle, ret, src_dst, 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 + +#include +#include +#include +#include +#include +#include + +/* + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +#include +#include +#include +#include +#include +#include +#include + +/* 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..5fb3141 --- /dev/null +++ b/plat/arm/board/fvp/fvp_plat_attest_token.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +static const uint8_t sample_platform_token[] = { + 0xD2, 0x84, 0x44, 0xA1, 0x01, 0x38, 0x22, 0xA0, + 0x59, 0x02, 0x33, 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, + 0xB5, 0x97, 0x3C, 0xB6, 0x8B, 0xAA, 0x9F, 0xC5, + 0x55, 0x58, 0x78, 0x6B, 0x7E, 0xC6, 0x7F, 0x69, + 0xE4, 0x0D, 0xF5, 0xBA, 0x5A, 0xA9, 0x21, 0xCD, + 0x0C, 0x27, 0xF4, 0x05, 0x87, 0xA0, 0x11, 0xEA, + 0x19, 0x09, 0x5C, 0x58, 0x20, 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, 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, 0x74, 0x54, 0x46, 0x2D, 0x4D, 0x5F, 0x53, + 0x48, 0x41, 0x32, 0x35, 0x36, 0x4D, 0x65, 0x6D, + 0x50, 0x72, 0x65, 0x58, 0x49, 0x50, 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, 0x60, + 0xE6, 0xB6, 0x38, 0x4F, 0xAE, 0x3F, 0x6E, 0x67, + 0xF5, 0xD4, 0x97, 0x4B, 0x3F, 0xFD, 0x0A, 0xFA, + 0x1D, 0xF0, 0x2F, 0x73, 0xB8, 0xFF, 0x5F, 0x02, + 0xC0, 0x0F, 0x40, 0xAC, 0xF3, 0xA2, 0x9D, 0xB5, + 0x31, 0x50, 0x16, 0x4F, 0xFA, 0x34, 0x3D, 0x0E, + 0xAF, 0xE0, 0xD0, 0xD1, 0x6C, 0xF0, 0x9D, 0xC1, + 0x01, 0x42, 0xA2, 0x3C, 0xCE, 0xD4, 0x4A, 0x59, + 0xDC, 0x29, 0x0A, 0x30, 0x93, 0x5F, 0xB4, 0x98, + 0x61, 0xBA, 0xE3, 0x91, 0x22, 0x95, 0x24, 0xF4, + 0xAE, 0x47, 0x93, 0xD3, 0x84, 0xA3, 0x76, 0xD0, + 0xC1, 0x26, 0x96, 0x53, 0xA3, 0x60, 0x3F, 0x6C, + 0x75, 0x96, 0x90, 0x6A, 0xF9, 0x4E, 0xDA, 0x30 +}; + +/* + * Get the hardcoded platform attestation token as FVP does not support + * RSS. + */ +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(sample_platform_token)) { + return -EINVAL; + } + + (void)memcpy((void *)buf, (const void *)sample_platform_token, + sizeof(sample_platform_token)); + *len = sizeof(sample_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..51dda9e --- /dev/null +++ b/plat/arm/board/fvp/fvp_pm.c @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(); + + /* + * On power down we need to disable statistical profiling extensions + * before exiting coherency. + */ + if (is_feat_spe_supported()) { + spe_disable(); + } + + /* Disable coherency if this cluster is to be turned off */ + fvp_interconnect_disable(); + + /* 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()); + + return; +} + +/******************************************************************************* + * 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; + +#if PSCI_OS_INIT_MODE + req_state->last_at_pwrlvl = PLAT_MAX_PWR_LVL; +#endif +} +#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 + +/******************************************************************************* + * 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..fe0cde7 --- /dev/null +++ b/plat/arm/board/fvp/fvp_realm_attest_key.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +static const uint8_t sample_delegated_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 +}; + +/* + * Get the hardcoded delegated realm attestation key as FVP + * does not support RSS. + */ +int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len, + unsigned int type) +{ + if (*len < sizeof(sample_delegated_key)) { + return -EINVAL; + } + + (void)memcpy((void *)buf, (const void *)sample_delegated_key, + sizeof(sample_delegated_key)); + *len = sizeof(sample_delegated_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 +#include +#include + +/* + * 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_spmd.c b/plat/arm/board/fvp/fvp_spmd.c new file mode 100644 index 0000000..8213e5e --- /dev/null +++ b/plat/arm/board/fvp/fvp_spmd.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +int plat_spmd_handle_group0_interrupt(uint32_t intid) +{ + /* + * As of now, there are no sources of Group0 secure interrupt enabled + * for FVP. + */ + (void)intid; + return -1; +} diff --git a/plat/arm/board/fvp/fvp_spmd_logical_sp.c b/plat/arm/board/fvp/fvp_spmd_logical_sp.c new file mode 100644 index 0000000..8841fc1 --- /dev/null +++ b/plat/arm/board/fvp/fvp_spmd_logical_sp.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +#define SPMD_LP_PARTITION_ID SPMD_LP_ID_START +#define SPMD_LP_UUID {0xe98e43ad, 0xb7db524f, 0x47a3bf57, 0x1588f4e3} + +/* SPMD Logical SP currently only supports sending direct message. */ +#define SPMD_PARTITION_PROPERTIES FFA_PARTITION_DIRECT_REQ_SEND + +#define SPMD_LP_MAX_SUPPORTED_SP 10 +static void fvp_get_partition_info(void) +{ + struct ffa_value ret = { 0 }; + uint32_t target_uuid[4] = { 0 }; + static struct ffa_partition_info_v1_1 + part_info[SPMD_LP_MAX_SUPPORTED_SP] = { 0 }; + + uint16_t num_partitions = 0; + + if (!spmd_el3_invoke_partition_info_get(target_uuid, 0, 0, &ret)) { + panic(); + } + + if (is_ffa_error(&ret)) { + panic(); + } + + num_partitions = ffa_partition_info_regs_get_last_idx(&ret) + 1; + if (num_partitions > SPMD_LP_MAX_SUPPORTED_SP) { + panic(); + } + + INFO("Number of secure partitions = %d\n", num_partitions); + + for (uint16_t i = 0; i < num_partitions; i++) { + INFO("***Start Partition***\n"); + if (!ffa_partition_info_regs_get_part_info(&ret, i, &part_info[i])) + panic(); + INFO("\tPartition ID: 0x%x\n", part_info[i].ep_id); + INFO("\tvCPU count:0x%x\n", part_info[i].execution_ctx_count); + INFO("\tProperties: 0x%x\n", part_info[i].properties); + INFO("\tUUID: 0x%x 0x%x 0x%x 0x%x\n", part_info[i].uuid[0], + part_info[i].uuid[1], part_info[i].uuid[2], + part_info[i].uuid[3]); + INFO("***End Partition***\n"); + } + +} + +static int32_t fvp_spmd_logical_partition_init(void) +{ + INFO("FVP SPMD LSP: Init function called.\n"); + + fvp_get_partition_info(); + return 0; +} + +/* + * Platform specific SMC handler used to translate SIP SMCs or other platform + * specific SMCs into FF-A direct messages. + */ +uintptr_t plat_spmd_logical_sp_smc_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + struct ffa_value retval = { 0 }; + uint64_t send_recv_id = SPMD_LP_PARTITION_ID << 16 | 0x8001; + + /* + * Forward the SMC as direct request. + */ + if (!spmd_el3_ffa_msg_direct_req(send_recv_id, x2, x3, x4, handle, &retval)) { + panic(); + } + + SMC_RET8(handle, retval.func, retval.arg1, retval.arg2, retval.arg3, + retval.arg4, retval.arg5, retval.arg6, retval.arg7); +} + +/* Register SPMD logical partition */ +DECLARE_SPMD_LOGICAL_PARTITION( + fvp_spmd_logical_partition, + fvp_spmd_logical_partition_init,/* Init Function */ + SPMD_LP_PARTITION_ID, /* FF-A Partition ID */ + SPMD_LP_UUID, /* UUID */ + SPMD_PARTITION_PROPERTIES /* Partition Properties. */ +); 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 + +#include +#include + +#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_sync_traps.c b/plat/arm/board/fvp/fvp_sync_traps.c new file mode 100644 index 0000000..91240f7 --- /dev/null +++ b/plat/arm/board/fvp/fvp_sync_traps.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * This file just contains demonstration code, to "handle" RNG traps. + */ + +#include + +#include +#include +#include +#include + +/* + * SCR_EL3.SCR_TRNDR_BIT also affects execution in EL3, so allow to disable + * the trap temporarily. + */ +static void enable_rng_trap(bool enable) +{ + uint64_t scr_el3 = read_scr_el3(); + + if (enable) { + scr_el3 |= SCR_TRNDR_BIT; + } else { + scr_el3 &= ~SCR_TRNDR_BIT; + } + + write_scr_el3(scr_el3); + isb(); +} + +/* + * This emulation code here is not very meaningful: enabling the RNG + * trap typically happens for a reason, so just calling the actual + * hardware instructions might not be useful or even possible. + */ +int plat_handle_rng_trap(uint64_t esr_el3, cpu_context_t *ctx) +{ + /* extract the target register number from the exception syndrome */ + unsigned int rt = get_sysreg_iss_rt(esr_el3); + + /* ignore XZR accesses and writes to the register */ + if (rt == 31 || is_sysreg_iss_write(esr_el3)) { + return TRAP_RET_CONTINUE; + } + + enable_rng_trap(false); + if ((esr_el3 & ISS_SYSREG_OPCODE_MASK) == ISS_SYSREG_OPCODE_RNDR) { + ctx->gpregs_ctx.ctx_regs[rt] = read_rndr(); + } else { + ctx->gpregs_ctx.ctx_regs[rt] = read_rndrrs(); + } + enable_rng_trap(true); + + /* + * We successfully handled the trap, continue with the next + * instruction. + */ + return TRAP_RET_CONTINUE; +} diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c new file mode 100644 index 0000000..971e35b --- /dev/null +++ b/plat/arm/board/fvp/fvp_topology.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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 + * RESET_TO_BL2 systems. + */ +#if RESET_TO_SP_MIN || RESET_TO_BL31 || RESET_TO_BL2 + 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..4c3201e --- /dev/null +++ b/plat/arm/board/fvp/fvp_trusted_boot.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * 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); +} + +/* + * Return the non-volatile counter address stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +static int plat_get_nv_ctr_addr(void *cookie, uintptr_t *nv_ctr_addr) +{ + const char *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 if (strcmp(oid, CCA_FW_NVCOUNTER_OID) == 0) { + /* FVP does not support the CCA NV Counter so use the Trusted NV */ + *nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + return 0; +} + +/* + * 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) +{ + uintptr_t nv_ctr_addr; + int rc; + + assert(cookie != NULL); + + rc = plat_get_nv_ctr_addr(cookie, &nv_ctr_addr); + if (rc != 0) { + return rc; + } + + 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; +} + +/* + * 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) +{ + uintptr_t nv_ctr_addr; + int rc; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + rc = plat_get_nv_ctr_addr(cookie, &nv_ctr_addr); + if (rc != 0) { + return rc; + } + + *nv_ctr = *((unsigned int *)nv_ctr_addr); + + return 0; +} 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..b7a1247 --- /dev/null +++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020-2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_HW_CONFIG_GETTER_H +#define FCONF_HW_CONFIG_GETTER_H + +#include +#include + +#include + +/* 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 +#define hw_config__dram_layout_getter(prop) dram_layout.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; +}; + +struct ns_dram_layout { + uint64_t num_banks; + struct ns_dram_bank dram_bank[ARM_DRAM_NUM_BANKS]; +}; + +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); +int fconf_populate_dram_layout(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; +extern struct ns_dram_layout dram_layout; + +#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 + +/* 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 +#include +#include + +#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 + +#if RECLAIM_INIT_CODE +#include +#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 +#include + + /* --------------------------------------------- + * 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..aad0417 --- /dev/null +++ b/plat/arm/board/fvp/include/platform_def.h @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +#include "../fvp_def.h" + +#if TRUSTED_BOARD_BOOT +#include MBEDTLS_CONFIG_FILE +#endif + +/* 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 + +#if PSCI_OS_INIT_MODE +#define PLAT_MAX_CPU_SUSPEND_PWR_LVL ARM_PWR_LVL1 +#endif + +/* + * 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 (FVP_TRUSTED_SRAM_SIZE * UL(1024)) + +#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)) + +#if TRANSFER_LIST +#define FW_HANDOFF_SIZE 0x4000 +#define FW_NS_HANDOFF_BASE (PLAT_ARM_NS_IMAGE_BASE - FW_HANDOFF_SIZE) +#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 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 +# if ENABLE_RME && defined(IMAGE_BL2) +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +# else +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +# endif /* (IMAGE_BL2 && ENABLE_RME) */ +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# if (defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd)) && \ +defined(IMAGE_BL2) && MEASURED_BOOT +# define MAX_XLAT_TABLES 7 +# else +# define MAX_XLAT_TABLES 6 +# endif /* (SPD_tspd || SPD_opteed || SPD_spmd) && IMAGE_BL2 && MEASURED_BOOT */ +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + * In case of PSA Crypto API, few algorithms like ECDSA needs bigger BL1 RW + * area. + */ +#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA || PSA_CRYPTO +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xC000) +#else +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) +#endif + +/* + * 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 + +/* + * Set the maximum size of BL2 to be close to half of the Trusted SRAM. + * Maximum size of BL2 increases as Trusted SRAM size increases. + */ +#if CRYPTO_SUPPORT +#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA) || COT_DESC_IN_DTB +# define PLAT_ARM_MAX_BL2_SIZE ((PLAT_ARM_TRUSTED_SRAM_SIZE / 2) - \ + (2 * PAGE_SIZE) - \ + FVP_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE ((PLAT_ARM_TRUSTED_SRAM_SIZE / 2) - \ + (3 * PAGE_SIZE) - \ + FVP_BL2_ROMLIB_OPTIMIZATION) +#endif +#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. + * Size of the BL31 PROGBITS increases as the SRAM size increases. + */ +#define PLAT_ARM_MAX_BL31_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE - \ + ARM_FW_CONFIGS_SIZE - 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 + #if PLATFORM_TEST_RAS_FFH + #define PLAT_ARM_PRIVATE_SDEI_EVENTS \ + ARM_SDEI_PRIVATE_EVENTS, \ + SDEI_EXPLICIT_EVENT(5000, SDEI_MAPF_NORMAL), \ + SDEI_EXPLICIT_EVENT(5001, SDEI_MAPF_NORMAL), \ + SDEI_EXPLICIT_EVENT(5002, SDEI_MAPF_NORMAL), \ + SDEI_EXPLICIT_EVENT(5003, SDEI_MAPF_CRITICAL), \ + SDEI_EXPLICIT_EVENT(5004, SDEI_MAPF_CRITICAL) + #else + #define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS + #endif +#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 0x20 + +/* + * 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 + */ +#if ENABLE_RME && (defined(SPD_tspd) || defined(SPD_opteed) || defined(SPD_spmd)) +/* Account for additional measurements of secure partitions and SPM. */ +#define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x800) +#else +#define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x400) +#endif + +/* + * 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..dc8032f --- /dev/null +++ b/plat/arm/board/fvp/jmptbl.i @@ -0,0 +1,65 @@ +# +# Copyright (c) 2018-2023, 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_node_offset_by_prop_value +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_len +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..2fdff34 --- /dev/null +++ b/plat/arm/board/fvp/platform.mk @@ -0,0 +1,546 @@ +# +# Copyright (c) 2013-2023, 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 + +# Size (in kilobytes) of the Trusted SRAM region to utilize when building for +# the FVP platform. This option defaults to 256. +FVP_TRUSTED_SRAM_SIZE := 256 + +# Macro to enable helpers for running SPM tests. Disabled by default. +PLAT_TEST_SPM := 0 + +# This is a very trickly TEMPORARY fix. Enabling ALL features exceeds BL31's +# progbits limit. We need a way to build all useful configurations while waiting +# on the fvp to increase its SRAM size. The problem is twofild: +# 1. the cleanup that introduced these enables cleaned up tf-a a little too +# well and things that previously (incorrectly) were enabled, no longer are. +# A bunch of CI configs build subtly incorrectly and this combo makes it +# necessary to forcefully and unconditionally enable them here. +# 2. the progbits limit is exceeded only when the tsp is involved. However, +# there are tsp CI configs that run on very high architecture revisions so +# disabling everything isn't an option. +# The fix is to enable everything, as before. When the tsp is included, though, +# we need to slim the size down. In that case, disable all optional features, +# that will not be present in CI when the tsp is. +# Similarly, DRTM support is only tested on v8.0 models. Disable everything just +# for it. +# TODO: make all of this unconditional (or only base the condition on +# ARM_ARCH_* when the makefile supports it). +ifneq (${DRTM_SUPPORT}, 1) +ifneq (${SPD}, tspd) + ENABLE_FEAT_AMU := 2 + ENABLE_FEAT_AMUv1p1 := 2 + ENABLE_FEAT_HCX := 2 + ENABLE_FEAT_RNG := 2 + ENABLE_FEAT_TWED := 2 + ENABLE_FEAT_GCS := 2 +ifeq (${ARCH}, aarch64) +ifneq (${SPD}, spmd) +ifeq (${SPM_MM}, 0) +ifeq (${CTX_INCLUDE_FPREGS}, 0) + ENABLE_SME_FOR_NS := 2 + ENABLE_SME2_FOR_NS := 2 +endif +endif +endif +endif +endif + +# enable unconditionally for all builds +ifeq (${ARCH}, aarch64) + ENABLE_BRBE_FOR_NS := 2 + ENABLE_TRBE_FOR_NS := 2 +endif +ENABLE_SYS_REG_TRACE_FOR_NS := 2 +ENABLE_FEAT_CSV2_2 := 2 +ENABLE_FEAT_DIT := 2 +ENABLE_FEAT_PAN := 2 +ENABLE_FEAT_MTE_PERM := 2 +ENABLE_FEAT_VHE := 2 +CTX_INCLUDE_NEVE_REGS := 2 +ENABLE_FEAT_SEL2 := 2 +ENABLE_TRF_FOR_NS := 2 +ENABLE_FEAT_ECV := 2 +ENABLE_FEAT_FGT := 2 +ENABLE_FEAT_TCR2 := 2 +ENABLE_FEAT_S2PIE := 2 +ENABLE_FEAT_S1PIE := 2 +ENABLE_FEAT_S2POE := 2 +ENABLE_FEAT_S1POE := 2 +endif + +# 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)) + +# Pass FVP_TRUSTED_SRAM_SIZE to the build system. +$(eval $(call add_define,FVP_TRUSTED_SRAM_SIZE)) + +# 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,${RESET_TO_BL2} \ + ${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 \ + -Iinclude/lib/psa + + +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 + # TODO: add all cores to the appropriate lists + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a65.S \ + lib/cpus/aarch64/cortex_a65ae.S \ + 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/cortex_a78_ae.S \ + lib/cpus/aarch64/cortex_a78c.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/neoverse_n_common.S \ + lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_v1.S \ + lib/cpus/aarch64/neoverse_e1.S \ + lib/cpus/aarch64/cortex_x2.S \ + lib/cpus/aarch64/cortex_gelas.S \ + lib/cpus/aarch64/nevis.S \ + lib/cpus/aarch64/travis.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 \ + lib/cpus/aarch32/cortex_a57.S \ + lib/cpus/aarch32/cortex_a53.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 (${ENABLE_FEAT_RNG_TRAP},1) +BL31_SOURCES += plat/arm/board/fvp/fvp_sync_traps.c +endif + +ifeq (${RESET_TO_BL2},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,${RESET_TO_BL2} ${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 (${TRANSFER_LIST}, 1) +include lib/transfer_list/transfer_list.mk +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 dynamic mitigation support by default +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 + +ifneq (${ENABLE_FEAT_AMU},0) +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 (${HANDLE_EA_EL3_FIRST_NS},1) +ifeq (${ENABLE_FEAT_RAS},1) +BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c +else +BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ea.c +endif +endif + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c +endif + +# Enable the dynamic translation tables library. +ifeq ($(filter 1,${RESET_TO_BL2} ${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 (${RESET_TO_BL2}, 0) + override BL1_SOURCES = +endif + +# 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 token/key. +PLAT_RSS_NOT_SUPPORTED := 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) + 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 + +# 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} + + 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 + +ifeq (${SPMC_AT_EL3}, 1) +PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_el3_spmc.c +endif + +PSCI_OS_INIT_MODE := 1 + +ifeq (${SPD},spmd) +BL31_SOURCES += plat/arm/board/fvp/fvp_spmd.c +endif + +# Test specific macros, keep them at bottom of this file +$(eval $(call add_define,PLATFORM_TEST_EA_FFH)) +ifeq (${PLATFORM_TEST_EA_FFH}, 1) + ifeq (${FFH_SUPPORT}, 0) + $(error "PLATFORM_TEST_EA_FFH expects FFH_SUPPORT to be 1") + endif + +endif + +$(eval $(call add_define,PLATFORM_TEST_RAS_FFH)) +ifeq (${PLATFORM_TEST_RAS_FFH}, 1) + ifeq (${ENABLE_FEAT_RAS}, 0) + $(error "PLATFORM_TEST_RAS_FFH expects ENABLE_FEAT_RAS to be 1") + endif + ifeq (${HANDLE_EA_EL3_FIRST_NS}, 0) + $(error "PLATFORM_TEST_RAS_FFH expects HANDLE_EA_EL3_FIRST_NS to be 1") + endif +endif + +ifeq (${ERRATA_ABI_SUPPORT}, 1) +include plat/arm/board/fvp/fvp_cpu_errata.mk +endif + +# Build macro necessary for running SPM tests on FVP platform +$(eval $(call add_define,PLAT_TEST_SPM)) 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..705ec38 --- /dev/null +++ b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#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 && !RESET_TO_BL2 + + 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 && !RESET_TO_BL2 */ + + 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 + * RESET_TO_BL2 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 && !RESET_TO_BL2 && !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); + + /* + * Preferably 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 && !RESET_TO_BL2 && !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..4ddba6f --- /dev/null +++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk @@ -0,0 +1,39 @@ +# +# Copyright (c) 2016-2023, 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,${RESET_TO_BL2} ${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 + +#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 -- cgit v1.2.3