GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL1 specific platform actions.
|
||||
******************************************************************************/
|
||||
void bl1_early_platform_setup(void)
|
||||
{
|
||||
arm_bl1_early_platform_setup();
|
||||
}
|
||||
|
||||
void bl1_platform_setup(void)
|
||||
{
|
||||
arm_bl1_platform_setup();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
arm_bl2_platform_setup();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <plat/arm/common/arm_config.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
#define MAP_PERIPHBASE MAP_REGION_FLAT(PERIPHBASE,\
|
||||
PERIPH_SIZE,\
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_A5_PERIPHERALS MAP_REGION_FLAT(A5_PERIPHERALS_BASE,\
|
||||
A5_PERIPHERALS_SIZE,\
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#ifdef IMAGE_BL1
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
MAP_PERIPHBASE,
|
||||
MAP_A5_PERIPHERALS,
|
||||
MAP_BOOT_RW,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL2
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
MAP_PERIPHBASE,
|
||||
MAP_A5_PERIPHERALS,
|
||||
MAP_BOOT_RW,
|
||||
ARM_MAP_NS_DRAM1,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL32
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
MAP_PERIPHBASE,
|
||||
MAP_A5_PERIPHERALS,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
ARM_CASSERT_MMAP
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return A5DS_TIMER_BASE_FREQUENCY;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*
|
||||
* a5ds error handler
|
||||
*/
|
||||
void __dead2 plat_arm_error_handler(int err)
|
||||
{
|
||||
while (true) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a power domain is about to be turned on. The
|
||||
* mpidr determines the CPU to be turned on.
|
||||
******************************************************************************/
|
||||
static int a5ds_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int pos = plat_core_pos_by_mpidr(mpidr);
|
||||
uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE;
|
||||
|
||||
hold_base[pos] = A5DS_HOLD_STATE_GO;
|
||||
dsbish();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a power domain has just been powered on after
|
||||
* being turned off earlier. The target_state encodes the low power state that
|
||||
* each level has woken up from.
|
||||
******************************************************************************/
|
||||
void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* TODO: This setup is needed only after a cold boot*/
|
||||
gicv2_pcpu_distif_init();
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a power domain is about to be turned off. The
|
||||
* target_state encodes the power state that each level should transition to.
|
||||
* a5ds only has always-on power domain and there is no power control present.
|
||||
******************************************************************************/
|
||||
void a5ds_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
ERROR("CPU_OFF not supported on this platform\n");
|
||||
assert(false);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard
|
||||
* platform layer will take care of registering the handlers with PSCI.
|
||||
******************************************************************************/
|
||||
plat_psci_ops_t a5ds_psci_pm_ops = {
|
||||
/* dummy struct */
|
||||
.validate_ns_entrypoint = NULL,
|
||||
.pwr_domain_on = a5ds_pwr_domain_on,
|
||||
.pwr_domain_on_finish = a5ds_pwr_domain_on_finish,
|
||||
.pwr_domain_off = a5ds_pwr_domain_off
|
||||
};
|
||||
|
||||
int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE;
|
||||
*mailbox = sec_entrypoint;
|
||||
|
||||
*psci_ops = &a5ds_psci_pm_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef A5DS_PRIVATE_H
|
||||
#define A5DS_PRIVATE_H
|
||||
|
||||
/*******************************************************************************
|
||||
* Function and variable prototypes
|
||||
******************************************************************************/
|
||||
void a5ds_config_setup(void);
|
||||
|
||||
#endif /* A5DS_PRIVATE_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*
|
||||
* We assume that all security programming is done by the primary core.
|
||||
*/
|
||||
void plat_arm_security_setup(void)
|
||||
{
|
||||
/*
|
||||
* The platform currently does not have any security setup.
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* The A5DS power domain tree descriptor */
|
||||
static const unsigned char a5ds_power_domain_tree_desc[] = {
|
||||
1,
|
||||
/* No of children for the root node */
|
||||
A5DS_CLUSTER_COUNT,
|
||||
/* No of children for the first cluster node */
|
||||
A5DS_CORE_COUNT,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the topology according to A5DS_CLUSTER_COUNT.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return a5ds_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Get core position using mpidr
|
||||
******************************************************************************/
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster_id, cpu_id;
|
||||
|
||||
mpidr &= MPIDR_AFFINITY_MASK;
|
||||
|
||||
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
|
||||
return -1;
|
||||
|
||||
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
|
||||
if (cluster_id >= A5DS_CLUSTER_COUNT)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Validate cpu_id by checking whether it represents a CPU in
|
||||
* one of the two clusters present on the platform.
|
||||
*/
|
||||
if (cpu_id >= A5DS_MAX_CPUS_PER_CLUSTER)
|
||||
return -1;
|
||||
|
||||
return (cpu_id + (cluster_id * 4));
|
||||
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset e.g
|
||||
* mark the cpu's presence, mechanism to place it in a
|
||||
* holding pen etc.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
/* Calculate address of our hold entry */
|
||||
bl plat_my_core_pos
|
||||
lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT
|
||||
mov_imm r2, A5DS_HOLD_BASE
|
||||
/* Clear the value stored in the hold address for the specific core */
|
||||
mov_imm r3, A5DS_HOLD_STATE_WAIT
|
||||
str r3, [r2, r0]
|
||||
dmb ish
|
||||
|
||||
/* Wait until we have a go */
|
||||
poll_mailbox:
|
||||
ldr r1, [r2, r0]
|
||||
cmp r1, #A5DS_HOLD_STATE_WAIT
|
||||
beq 1f
|
||||
mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE
|
||||
ldr r1, [r0]
|
||||
bx r1
|
||||
1:
|
||||
wfe
|
||||
b poll_mailbox
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and warm
|
||||
* boot.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* TODO support warm boot */
|
||||
/* Cold reset */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
ldcopr r0, MPIDR
|
||||
ldr r1, =MPIDR_AFFINITY_MASK
|
||||
and r0, r1
|
||||
cmp r0, #0
|
||||
moveq r0, #1
|
||||
movne r0, #0
|
||||
bx lr
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Loads MPIDR in r0 and calls plat_arm_calc_core_pos
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_my_core_pos
|
||||
ldcopr r0, MPIDR
|
||||
b plat_arm_calc_core_pos
|
||||
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
|
||||
*
|
||||
* Function to calculate the core position on A5DS.
|
||||
*
|
||||
* (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) +
|
||||
* (CPUId * A5DS_MAX_PE_PER_CPU) +
|
||||
* ThreadId
|
||||
*
|
||||
* which can be simplified as:
|
||||
*
|
||||
* ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU)
|
||||
* + ThreadId
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_arm_calc_core_pos
|
||||
mov r3, r0
|
||||
|
||||
/*
|
||||
* Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
|
||||
* look as if in a multi-threaded implementation
|
||||
*/
|
||||
tst r0, #MPIDR_MT_MASK
|
||||
lsleq r3, r0, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Compute linear position */
|
||||
mov r3, #A5DS_MAX_CPUS_PER_CLUSTER
|
||||
mla r1, r2, r3, r1
|
||||
mov r3, #A5DS_MAX_PE_PER_CPU
|
||||
mla r0, r1, r3, r0
|
||||
|
||||
bx lr
|
||||
endfunc plat_arm_calc_core_pos
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
dtb-registry {
|
||||
compatible = "fconf,dyn_cfg-dtb_registry";
|
||||
|
||||
tb_fw-config {
|
||||
load-address = <0x0 0x2001300>;
|
||||
max-size = <0x200>;
|
||||
id = <TB_FW_CONFIG_ID>;
|
||||
};
|
||||
|
||||
hw-config {
|
||||
load-address = <0x0 0x83000000>;
|
||||
max-size = <0x01000000>;
|
||||
id = <HW_CONFIG_ID>;
|
||||
};
|
||||
};
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
tb_fw-config {
|
||||
compatible = "arm,tb_fw";
|
||||
|
||||
/* Disable authentication for development */
|
||||
disable_auth = <0x0>;
|
||||
};
|
||||
};
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <plat/arm/board/common/v2m_def.h>
|
||||
#include <plat/arm/common/smccc_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* Memory location options for TSP */
|
||||
#define ARM_DRAM_ID 2
|
||||
|
||||
#define ARM_DRAM1_BASE UL(0x80000000)
|
||||
#define ARM_DRAM1_SIZE UL(0x80000000)
|
||||
#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
|
||||
ARM_DRAM1_SIZE - 1)
|
||||
|
||||
#define SRAM_BASE 0x2000000
|
||||
#define SRAM_SIZE 0x200000
|
||||
|
||||
/* The first 4KB of NS DRAM1 are used as shared memory */
|
||||
#define A5DS_SHARED_RAM_BASE SRAM_BASE
|
||||
#define A5DS_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
|
||||
|
||||
/* The next 252 kB of NS DRAM is used to load the BL images */
|
||||
#define ARM_BL_RAM_BASE (A5DS_SHARED_RAM_BASE + \
|
||||
A5DS_SHARED_RAM_SIZE)
|
||||
#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \
|
||||
A5DS_SHARED_RAM_SIZE)
|
||||
|
||||
#define PERIPHBASE 0x1a000000
|
||||
#define PERIPH_SIZE 0x00240000
|
||||
#define A5_PERIPHERALS_BASE 0x1c000000
|
||||
#define A5_PERIPHERALS_SIZE 0x10000
|
||||
|
||||
#define ARM_CACHE_WRITEBACK_SHIFT 5
|
||||
|
||||
#define ARM_IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define ARM_IRQ_SEC_SGI_0 8
|
||||
#define ARM_IRQ_SEC_SGI_1 9
|
||||
#define ARM_IRQ_SEC_SGI_2 10
|
||||
#define ARM_IRQ_SEC_SGI_3 11
|
||||
#define ARM_IRQ_SEC_SGI_4 12
|
||||
#define ARM_IRQ_SEC_SGI_5 13
|
||||
#define ARM_IRQ_SEC_SGI_6 14
|
||||
#define ARM_IRQ_SEC_SGI_7 15
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define ARM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define ARM_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define A5DS_IRQ_TZ_WDOG 56
|
||||
#define A5DS_IRQ_SEC_SYS_TIMER 57
|
||||
|
||||
/* Default cluster count for A5DS */
|
||||
#define A5DS_CLUSTER_COUNT U(1)
|
||||
|
||||
/* Default number of CPUs per cluster on A5DS */
|
||||
#define A5DS_MAX_CPUS_PER_CLUSTER U(4)
|
||||
|
||||
/* Default number of threads per CPU on A5DS */
|
||||
#define A5DS_MAX_PE_PER_CPU U(1)
|
||||
|
||||
#define A5DS_CORE_COUNT U(4)
|
||||
|
||||
#define A5DS_PRIMARY_CPU 0x0
|
||||
|
||||
#define BOOT_BASE ARM_DRAM1_BASE
|
||||
#define BOOT_SIZE UL(0x2800000)
|
||||
|
||||
#define ARM_NS_DRAM1_BASE (ARM_DRAM1_BASE + BOOT_SIZE)
|
||||
/*
|
||||
* The last 2MB is meant to be NOLOAD and will not be zero
|
||||
* initialized.
|
||||
*/
|
||||
#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
|
||||
BOOT_SIZE - \
|
||||
0x00200000)
|
||||
|
||||
#define MAP_BOOT_RW MAP_REGION_FLAT( \
|
||||
BOOT_BASE, \
|
||||
BOOT_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
|
||||
A5DS_SHARED_RAM_BASE, \
|
||||
A5DS_SHARED_RAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
|
||||
ARM_NS_DRAM1_BASE, \
|
||||
ARM_NS_DRAM1_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define ARM_MAP_SRAM MAP_REGION_FLAT( \
|
||||
SRAM_BASE, \
|
||||
SRAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
/*
|
||||
* Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
|
||||
* share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides
|
||||
* in the BL1 RW region. Hence, BL2 needs access to the BL1 RW region in order
|
||||
* to be able to access the heap.
|
||||
*/
|
||||
|
||||
#define ARM_MAP_BL_RO MAP_REGION_FLAT(\
|
||||
BL_CODE_BASE,\
|
||||
BL_CODE_END - BL_CODE_BASE,\
|
||||
MT_CODE | MT_SECURE),\
|
||||
MAP_REGION_FLAT(\
|
||||
BL_RO_DATA_BASE,\
|
||||
BL_RO_DATA_END\
|
||||
- BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT(\
|
||||
BL_COHERENT_RAM_BASE,\
|
||||
BL_COHERENT_RAM_END \
|
||||
- BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map the region for device tree configuration with read and write permissions
|
||||
*/
|
||||
#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
|
||||
(ARM_FW_CONFIGS_LIMIT \
|
||||
- ARM_BL_RAM_BASE), \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
/*
|
||||
* The max number of regions like RO(code), coherent and data required by
|
||||
* different BL stages which need to be mapped in the MMU.
|
||||
*/
|
||||
#define ARM_BL_REGIONS 6
|
||||
|
||||
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
|
||||
ARM_BL_REGIONS)
|
||||
|
||||
/* Memory mapped Generic timer interfaces */
|
||||
#define A5DS_TIMER_BASE_FREQUENCY UL(7500000)
|
||||
|
||||
#define ARM_CONSOLE_BAUDRATE 115200
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
/*
|
||||
* This macro defines the deepest retention state possible. A higher state
|
||||
* id will represent an invalid or a power down state.
|
||||
*/
|
||||
#define PLAT_MAX_RET_STATE 1
|
||||
|
||||
/*
|
||||
* This macro defines the deepest power down states possible. Any state ID
|
||||
* higher than this is invalid.
|
||||
*/
|
||||
#define PLAT_MAX_OFF_STATE 2
|
||||
|
||||
/*
|
||||
* Some data must be aligned on the biggest cache line size in the platform.
|
||||
* This is known only to the platform as it might have a combination of
|
||||
* integrated and external caches.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/*
|
||||
* To enable FW_CONFIG to be loaded by BL1, define the corresponding base
|
||||
* and limit. Leave enough space of BL2 meminfo.
|
||||
*/
|
||||
#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
|
||||
#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Define limit of firmware configuration memory:
|
||||
* ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
|
||||
*/
|
||||
#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
|
||||
|
||||
/*******************************************************************************
|
||||
* BL1 specific defines.
|
||||
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
|
||||
* addresses.
|
||||
******************************************************************************/
|
||||
#define BL1_RO_BASE 0x00000000
|
||||
#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE
|
||||
/*
|
||||
* Put BL1 RW at the top of the memory allocated for BL images in NS DRAM.
|
||||
*/
|
||||
#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
|
||||
ARM_BL_RAM_SIZE - \
|
||||
(PLAT_ARM_MAX_BL1_RW_SIZE))
|
||||
#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \
|
||||
(ARM_BL_RAM_SIZE))
|
||||
/*******************************************************************************
|
||||
* BL2 specific defines.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Put BL2 just below BL1.
|
||||
*/
|
||||
#define BL2_BASE (BL1_RW_BASE - A5DS_MAX_BL2_SIZE)
|
||||
#define BL2_LIMIT BL1_RW_BASE
|
||||
|
||||
/* Put BL32 below BL2 in NS DRAM.*/
|
||||
#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
|
||||
#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
|
||||
+ (PAGE_SIZE / 2U))
|
||||
|
||||
#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
|
||||
- PLAT_ARM_MAX_BL32_SIZE)
|
||||
#define BL32_PROGBITS_LIMIT BL2_BASE
|
||||
#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
|
||||
|
||||
/* Required platform porting definitions */
|
||||
#define PLATFORM_CORE_COUNT A5DS_CORE_COUNT
|
||||
#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT) + U(1)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL 2
|
||||
|
||||
/*
|
||||
* Other platform porting definitions are provided by included headers
|
||||
*/
|
||||
|
||||
/*
|
||||
* Required ARM standard platform porting definitions
|
||||
*/
|
||||
|
||||
#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */
|
||||
|
||||
#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000
|
||||
#define PLAT_ARM_TRUSTED_ROM_SIZE 0x10000 /* 64KB */
|
||||
|
||||
#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000)
|
||||
|
||||
/*
|
||||
* Load address of BL33 for this platform port
|
||||
*/
|
||||
#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000))
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
|
||||
* plat_arm_mmap array defined for each BL stage.
|
||||
*/
|
||||
#if defined(IMAGE_BL32)
|
||||
# define PLAT_ARM_MMAP_ENTRIES 8
|
||||
# define MAX_XLAT_TABLES 6
|
||||
#else
|
||||
# define PLAT_ARM_MMAP_ENTRIES 12
|
||||
# define MAX_XLAT_TABLES 6
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
|
||||
* plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000
|
||||
|
||||
/*
|
||||
* A5DS_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
|
||||
* little space for growth.
|
||||
*/
|
||||
#define A5DS_MAX_BL2_SIZE 0x11000
|
||||
|
||||
/*
|
||||
* Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
|
||||
* calculated using the current SP_MIN PROGBITS debug size plus the sizes of
|
||||
* BL2 and BL1-RW
|
||||
*/
|
||||
#define PLAT_ARM_MAX_BL32_SIZE 0x3B000
|
||||
/*
|
||||
* Size of cacheable stacks
|
||||
*/
|
||||
#if defined(IMAGE_BL1)
|
||||
# define PLATFORM_STACK_SIZE 0x440
|
||||
#elif defined(IMAGE_BL2)
|
||||
# define PLATFORM_STACK_SIZE 0x400
|
||||
#elif defined(IMAGE_BL32)
|
||||
# define PLATFORM_STACK_SIZE 0x440
|
||||
#endif
|
||||
|
||||
#define MAX_IO_DEVICES 3
|
||||
#define MAX_IO_HANDLES 4
|
||||
|
||||
/* Reserve the last block of flash for PSCI MEM PROTECT flag */
|
||||
#define PLAT_ARM_FLASH_IMAGE_BASE BOOT_BASE
|
||||
#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE)
|
||||
|
||||
#define PLAT_ARM_NVM_BASE BOOT_BASE
|
||||
#define PLAT_ARM_NVM_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE)
|
||||
|
||||
/*
|
||||
* PL011 related constants
|
||||
*/
|
||||
#define PLAT_ARM_BOOT_UART_BASE 0x1A200000
|
||||
#define PLAT_ARM_BOOT_UART_CLK_IN_HZ UL(7500000)
|
||||
|
||||
#define PLAT_ARM_RUN_UART_BASE 0x1A210000
|
||||
#define PLAT_ARM_RUN_UART_CLK_IN_HZ UL(7500000)
|
||||
|
||||
#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
|
||||
#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
|
||||
|
||||
#define A5DS_TIMER_BASE_FREQUENCY UL(7500000)
|
||||
|
||||
/* System timer related constants */
|
||||
#define PLAT_ARM_NSTIMER_FRAME_ID 1
|
||||
|
||||
/* Mailbox base address */
|
||||
#define A5DS_TRUSTED_MAILBOX_BASE A5DS_SHARED_RAM_BASE
|
||||
#define A5DS_TRUSTED_MAILBOX_SIZE (8 + A5DS_HOLD_SIZE)
|
||||
#define A5DS_HOLD_BASE (A5DS_TRUSTED_MAILBOX_BASE + 8)
|
||||
#define A5DS_HOLD_SIZE (PLATFORM_CORE_COUNT * \
|
||||
A5DS_HOLD_ENTRY_SIZE)
|
||||
#define A5DS_HOLD_ENTRY_SHIFT 3
|
||||
#define A5DS_HOLD_ENTRY_SIZE (1 << A5DS_HOLD_ENTRY_SHIFT)
|
||||
#define A5DS_HOLD_STATE_WAIT 0
|
||||
#define A5DS_HOLD_STATE_GO 1
|
||||
|
||||
/* Snoop Control Unit base address */
|
||||
#define A5DS_SCU_BASE 0x1C000000
|
||||
|
||||
/*
|
||||
* GIC related constants to cater for GICv2
|
||||
*/
|
||||
#define PLAT_ARM_GICD_BASE 0x1C001000
|
||||
#define PLAT_ARM_GICC_BASE 0x1C000100
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||
ARM_G1S_IRQ_PROPS(grp), \
|
||||
INTR_PROP_DESC(A5DS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(A5DS_IRQ_SEC_SYS_TIMER,\
|
||||
GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,111 @@
|
||||
#
|
||||
# Copyright (c) 2019-2021, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Firmware Configuration Framework sources
|
||||
include common/fdt_wrappers.mk
|
||||
include lib/fconf/fconf.mk
|
||||
|
||||
BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
|
||||
BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
|
||||
|
||||
# Add `libfdt` and Arm common helpers required for Dynamic Config
|
||||
include lib/libfdt/libfdt.mk
|
||||
|
||||
DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \
|
||||
plat/arm/common/arm_dyn_cfg_helpers.c
|
||||
|
||||
DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
# Include GICv2 driver files
|
||||
include drivers/arm/gic/v2/gicv2.mk
|
||||
|
||||
A5DS_GIC_SOURCES := ${GICV2_SOURCES} \
|
||||
plat/common/plat_gicv2.c \
|
||||
plat/arm/common/arm_gicv2.c
|
||||
|
||||
A5DS_SECURITY_SOURCES := plat/arm/board/a5ds/a5ds_security.c
|
||||
|
||||
PLAT_INCLUDES := -Iplat/arm/board/a5ds/include
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/${ARCH}/pl011_console.S \
|
||||
plat/arm/board/a5ds/a5ds_common.c \
|
||||
plat/arm/common/${ARCH}/arm_helpers.S \
|
||||
plat/arm/common/arm_common.c \
|
||||
plat/arm/common/arm_console.c \
|
||||
plat/arm/board/common/${ARCH}/board_arm_helpers.S
|
||||
|
||||
A5DS_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S
|
||||
|
||||
BL1_SOURCES += drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
drivers/cfi/v2m/v2m_flash.c \
|
||||
plat/arm/common/arm_bl1_setup.c \
|
||||
plat/arm/common/arm_err.c \
|
||||
plat/arm/board/a5ds/a5ds_err.c \
|
||||
plat/arm/common/arm_io_storage.c \
|
||||
plat/arm/common/fconf/arm_fconf_io.c \
|
||||
plat/arm/board/a5ds/${ARCH}/a5ds_helpers.S \
|
||||
plat/arm/board/a5ds/a5ds_bl1_setup.c \
|
||||
lib/aarch32/arm32_aeabi_divmod.c \
|
||||
lib/aarch32/arm32_aeabi_divmod_a32.S \
|
||||
${A5DS_CPU_LIBS} \
|
||||
${DYN_CFG_SOURCES}
|
||||
|
||||
BL2_SOURCES += lib/aarch32/arm32_aeabi_divmod.c \
|
||||
lib/aarch32/arm32_aeabi_divmod_a32.S \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/delay_timer/generic_delay_timer.c \
|
||||
drivers/cfi/v2m/v2m_flash.c \
|
||||
drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
plat/arm/board/a5ds/a5ds_bl2_setup.c \
|
||||
plat/arm/common/arm_bl2_setup.c \
|
||||
plat/arm/common/arm_err.c \
|
||||
plat/arm/board/a5ds/a5ds_err.c \
|
||||
plat/arm/common/arm_io_storage.c \
|
||||
plat/arm/common/fconf/arm_fconf_io.c \
|
||||
plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \
|
||||
plat/arm/common/arm_image_load.c \
|
||||
common/desc_image_load.c \
|
||||
${DYN_CFG_SOURCES} \
|
||||
${A5DS_SECURITY_SOURCES}
|
||||
|
||||
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
|
||||
ifdef UNIX_MK
|
||||
|
||||
FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
|
||||
TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
|
||||
|
||||
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
|
||||
# Add the FW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
|
||||
|
||||
$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \
|
||||
fdts/$(notdir ${FVP_HW_CONFIG_DTS})))
|
||||
# Add the HW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
|
||||
|
||||
FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
|
||||
plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
|
||||
${FVP_HW_CONFIG_DTS}
|
||||
endif
|
||||
|
||||
NEED_BL32 := yes
|
||||
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch32/nonlpae_tables.c
|
||||
|
||||
# Use translation tables library v1 when using Cortex-A5
|
||||
ARM_XLAT_TABLES_LIB_V1 := 1
|
||||
$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
|
||||
$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
|
||||
|
||||
$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
|
||||
$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG))
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/arm/scu.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
|
||||
void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
|
||||
|
||||
/* enable snoop control unit */
|
||||
enable_snoop_ctrl_unit(A5DS_SCU_BASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* A5DS will only have one always-on power domain and there
|
||||
* is no power control present.
|
||||
*/
|
||||
void plat_arm_pwrc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2019, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# SP_MIN source files specific to A5DS platform
|
||||
BL32_SOURCES += drivers/arm/scu/scu.c \
|
||||
drivers/cfi/v2m/v2m_flash.c \
|
||||
lib/utils/mem_region.c \
|
||||
lib/aarch32/arm32_aeabi_divmod.c \
|
||||
lib/aarch32/arm32_aeabi_divmod_a32.S \
|
||||
plat/arm/board/a5ds/aarch32/a5ds_helpers.S \
|
||||
plat/arm/board/a5ds/a5ds_pm.c \
|
||||
plat/arm/board/a5ds/a5ds_topology.c \
|
||||
plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c \
|
||||
plat/arm/common/sp_min/arm_sp_min_setup.c \
|
||||
plat/common/aarch32/platform_mp_stack.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
${A5DS_CPU_LIBS} \
|
||||
${A5DS_GIC_SOURCES} \
|
||||
${A5DS_SECURITY_SOURCES}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.h>
|
||||
#include "../fpga_private.h"
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl platform_mem_init
|
||||
.globl plat_my_core_pos
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_crash_console_flush
|
||||
.globl plat_fpga_calc_core_pos
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* Indicate a cold boot for every CPU - warm boot is unsupported for the
|
||||
* holding pen PSCI implementation.
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
|
||||
/*
|
||||
* Wait for the primary processor to initialise the .BSS segment
|
||||
* to avoid a race condition that would erase fpga_valid_mpids
|
||||
* if it is populated before the C runtime is ready.
|
||||
*
|
||||
* We cannot use the current spin-lock implementation until the
|
||||
* runtime is up and we should not rely on sevl/wfe instructions as
|
||||
* it is optional whether they are implemented or not, so we use
|
||||
* a global variable as lock and wait for the primary processor to
|
||||
* finish the C runtime bring-up.
|
||||
*/
|
||||
|
||||
ldr w0, =C_RUNTIME_READY_KEY
|
||||
adrp x1, secondary_core_spinlock
|
||||
add x1, x1, :lo12:secondary_core_spinlock
|
||||
1:
|
||||
wfe
|
||||
ldr w2, [x1]
|
||||
cmp w2, w0
|
||||
b.ne 1b
|
||||
/* Prevent reordering of the store into fpga_valid_mpids below */
|
||||
dmb ish
|
||||
|
||||
mov x10, x30
|
||||
bl plat_my_core_pos
|
||||
mov x30, x10
|
||||
|
||||
adrp x4, fpga_valid_mpids
|
||||
add x4, x4, :lo12:fpga_valid_mpids
|
||||
mov x5, #VALID_MPID
|
||||
strb w5, [x4, x0]
|
||||
|
||||
/*
|
||||
* Poll the CPU's hold entry until it indicates to jump
|
||||
* to the entrypoint address.
|
||||
*/
|
||||
|
||||
adrp x1, hold_base
|
||||
add x1, x1, :lo12:hold_base
|
||||
poll_hold_entry:
|
||||
ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
|
||||
cmp x3, #PLAT_FPGA_HOLD_STATE_GO
|
||||
b.ne 1f
|
||||
|
||||
adrp x2, fpga_sec_entrypoint
|
||||
add x2, x2, :lo12:fpga_sec_entrypoint
|
||||
ldr x3, [x2]
|
||||
br x3
|
||||
1:
|
||||
wfe
|
||||
b poll_hold_entry
|
||||
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary cpu
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
mov_imm x1, MPIDR_AFFINITY_MASK
|
||||
and x0, x0, x1
|
||||
cmp x0, #FPGA_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
func plat_my_core_pos
|
||||
ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, x1
|
||||
b plat_fpga_calc_core_pos
|
||||
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
|
||||
* Clobber registers: x0 to x5
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_fpga_calc_core_pos
|
||||
/*
|
||||
* Check for MT bit in MPIDR, which may be either value for images
|
||||
* running on the FPGA.
|
||||
*
|
||||
* If not set, shift MPIDR to left to make it look as if in a
|
||||
* multi-threaded implementation.
|
||||
*
|
||||
*/
|
||||
tst x0, #MPIDR_MT_MASK
|
||||
lsl x3, x0, #MPIDR_AFFINITY_BITS
|
||||
csel x3, x3, x0, eq
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
mov x4, #FPGA_MAX_CPUS_PER_CLUSTER
|
||||
mov x5, #FPGA_MAX_PE_PER_CPU
|
||||
|
||||
/* Compute linear position */
|
||||
madd x1, x2, x4, x1
|
||||
madd x0, x1, x5, x0
|
||||
|
||||
ret
|
||||
endfunc plat_fpga_calc_core_pos
|
||||
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
|
||||
b console_pl011_core_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, PLAT_FPGA_CRASH_UART_BASE
|
||||
b console_pl011_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
func plat_crash_console_flush
|
||||
mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
|
||||
b console_pl011_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Linker script for the Arm Ltd. FPGA boards to generate an ELF file that
|
||||
* contains the ROM trampoline, BL31 and the DTB.
|
||||
*
|
||||
* This allows to pass just one file to the uploader tool, and automatically
|
||||
* provides the correct load addresses.
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
OUTPUT_FORMAT("elf64-littleaarch64")
|
||||
OUTPUT_ARCH(aarch64)
|
||||
|
||||
INPUT(./rom_trampoline.o)
|
||||
INPUT(./kernel_trampoline.o)
|
||||
|
||||
TARGET(binary)
|
||||
INPUT(./bl31.bin)
|
||||
INPUT(./fdts/arm_fpga.dtb)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.rom (0x0): {
|
||||
*rom_trampoline.o(.text*)
|
||||
KEEP(*(.rom))
|
||||
}
|
||||
|
||||
.bl31 (BL31_BASE): {
|
||||
ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned");
|
||||
*bl31.bin
|
||||
}
|
||||
|
||||
.dtb (FPGA_PRELOADED_DTB_BASE): {
|
||||
ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned");
|
||||
*arm_fpga.dtb
|
||||
}
|
||||
|
||||
.kern_tramp (PRELOADED_BL33_BASE): {
|
||||
*kernel_trampoline.o(.text*)
|
||||
KEEP(*(.kern_tramp))
|
||||
}
|
||||
|
||||
/DISCARD/ : { *(stacks) }
|
||||
/DISCARD/ : { *(.debug_*) }
|
||||
/DISCARD/ : { *(.note*) }
|
||||
/DISCARD/ : { *(.comment*) }
|
||||
}
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <lib/extensions/spe.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include "fpga_private.h"
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
static unsigned int system_freq;
|
||||
volatile uint32_t secondary_core_spinlock;
|
||||
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
return PRELOADED_BL33_BASE;
|
||||
#else
|
||||
return 0ULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t fpga_get_spsr_for_bl33_entry(void)
|
||||
{
|
||||
return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
}
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* Add this core to the VALID mpids list */
|
||||
fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
|
||||
|
||||
/*
|
||||
* Notify the secondary CPUs that the C runtime is ready
|
||||
* so they can announce themselves.
|
||||
*/
|
||||
secondary_core_spinlock = C_RUNTIME_READY_KEY;
|
||||
dsbish();
|
||||
sev();
|
||||
|
||||
fpga_console_init();
|
||||
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
/* Set x0-x3 for the primary CPU as expected by the kernel */
|
||||
bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE;
|
||||
bl33_image_ep_info.args.arg1 = 0U;
|
||||
bl33_image_ep_info.args.arg2 = 0U;
|
||||
bl33_image_ep_info.args.arg3 = 0U;
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
/* Write frequency to CNTCRL and initialize timer */
|
||||
generic_delay_timer_init();
|
||||
|
||||
/*
|
||||
* Before doing anything else, wait for some time to ensure that
|
||||
* the secondary CPUs have populated the fpga_valid_mpids array.
|
||||
* As the number of secondary cores is unknown and can even be 0,
|
||||
* it is not possible to rely on any signal from them, so use a
|
||||
* delay instead.
|
||||
*/
|
||||
mdelay(5);
|
||||
|
||||
/*
|
||||
* On the event of a cold reset issued by, for instance, a reset pin
|
||||
* assertion, we cannot guarantee memory to be initialized to zero.
|
||||
* In such scenario, if the secondary cores reached
|
||||
* plat_secondary_cold_boot_setup before the primary one initialized
|
||||
* .BSS, we could end up having a race condition if the spinlock
|
||||
* was not cleared before.
|
||||
*
|
||||
* Similarly, if there were a reset before the spinlock had been
|
||||
* cleared, the secondary cores would find the lock opened before
|
||||
* .BSS is cleared, causing another race condition.
|
||||
*
|
||||
* So clean the spinlock as soon as we think it is safe to reduce the
|
||||
* chances of any race condition on a reset.
|
||||
*/
|
||||
secondary_core_spinlock = 0UL;
|
||||
|
||||
/* Initialize the GIC driver, cpu and distributor interfaces */
|
||||
plat_fpga_gic_init();
|
||||
}
|
||||
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
next_image_info = &bl33_image_ep_info;
|
||||
|
||||
/* Only expecting BL33: the kernel will run in EL2NS */
|
||||
assert(type == NON_SECURE);
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint */
|
||||
if (next_image_info->pc) {
|
||||
return next_image_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Even though we sell the FPGA UART as an SBSA variant, it is actually
|
||||
* a full fledged PL011. So the baudrate divider registers exist.
|
||||
*/
|
||||
#ifndef UARTIBRD
|
||||
#define UARTIBRD 0x024
|
||||
#define UARTFBRD 0x028
|
||||
#endif
|
||||
|
||||
/* Round an integer to the closest multiple of a value. */
|
||||
static unsigned int round_multiple(unsigned int x, unsigned int multiple)
|
||||
{
|
||||
if (multiple < 2) {
|
||||
return x;
|
||||
}
|
||||
|
||||
return ((x + (multiple / 2 - 1)) / multiple) * multiple;
|
||||
}
|
||||
|
||||
#define PL011_FRAC_SHIFT 6
|
||||
#define FPGA_DEFAULT_BAUDRATE 38400
|
||||
#define PL011_OVERSAMPLING 16
|
||||
static unsigned int pl011_freq_from_divider(unsigned int divider)
|
||||
{
|
||||
unsigned int freq;
|
||||
|
||||
freq = divider * FPGA_DEFAULT_BAUDRATE * PL011_OVERSAMPLING;
|
||||
|
||||
return freq >> PL011_FRAC_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* The FPGAs run most peripherals from one main clock, among them the CPUs,
|
||||
* the arch timer, and the UART baud base clock.
|
||||
* The SCP knows this frequency and programs the UART clock divider for a
|
||||
* 38400 bps baudrate. Recalculate the base input clock from there.
|
||||
*/
|
||||
static unsigned int fpga_get_system_frequency(void)
|
||||
{
|
||||
const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
int node, err;
|
||||
|
||||
/*
|
||||
* If the arch timer DT node has an explicit clock-frequency property
|
||||
* set, use that, to allow people overriding auto-detection.
|
||||
*/
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer");
|
||||
if (node >= 0) {
|
||||
uint32_t freq;
|
||||
|
||||
err = fdt_read_uint32(fdt, node, "clock-frequency", &freq);
|
||||
if (err >= 0) {
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011");
|
||||
if (node >= 0) {
|
||||
uintptr_t pl011_base;
|
||||
unsigned int divider;
|
||||
|
||||
err = fdt_get_reg_props_by_index(fdt, node, 0,
|
||||
&pl011_base, NULL);
|
||||
if (err >= 0) {
|
||||
divider = mmio_read_32(pl011_base + UARTIBRD);
|
||||
divider <<= PL011_FRAC_SHIFT;
|
||||
divider += mmio_read_32(pl011_base + UARTFBRD);
|
||||
|
||||
/*
|
||||
* The result won't be exact, due to rounding errors,
|
||||
* but the input frequency was a multiple of 250 KHz.
|
||||
*/
|
||||
return round_multiple(pl011_freq_from_divider(divider),
|
||||
250000);
|
||||
} else {
|
||||
WARN("Cannot read PL011 MMIO base\n");
|
||||
}
|
||||
} else {
|
||||
WARN("No PL011 DT node\n");
|
||||
}
|
||||
|
||||
/* No PL011 DT node or calculation failed. */
|
||||
return FPGA_DEFAULT_TIMER_FREQUENCY;
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
if (system_freq == 0U) {
|
||||
system_freq = fpga_get_system_frequency();
|
||||
}
|
||||
|
||||
return system_freq;
|
||||
}
|
||||
|
||||
static void fpga_dtb_update_clock(void *fdt, unsigned int freq)
|
||||
{
|
||||
uint32_t freq_dtb = fdt32_to_cpu(freq);
|
||||
uint32_t phandle;
|
||||
int node, err;
|
||||
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011");
|
||||
if (node < 0) {
|
||||
WARN("%s(): No PL011 DT node found\n", __func__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err = fdt_read_uint32(fdt, node, "clocks", &phandle);
|
||||
if (err != 0) {
|
||||
WARN("Cannot find clocks property\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_phandle(fdt, phandle);
|
||||
if (node < 0) {
|
||||
WARN("Cannot get phandle\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err = fdt_setprop_inplace(fdt, node,
|
||||
"clock-frequency",
|
||||
&freq_dtb,
|
||||
sizeof(freq_dtb));
|
||||
if (err < 0) {
|
||||
WARN("Could not update DT baud clock frequency\n");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#define CMDLINE_SIGNATURE "CMD:"
|
||||
|
||||
static int fpga_dtb_set_commandline(void *fdt, const char *cmdline)
|
||||
{
|
||||
int chosen;
|
||||
const char *eol;
|
||||
char nul = 0;
|
||||
int slen, err;
|
||||
|
||||
chosen = fdt_add_subnode(fdt, 0, "chosen");
|
||||
if (chosen == -FDT_ERR_EXISTS) {
|
||||
chosen = fdt_path_offset(fdt, "/chosen");
|
||||
}
|
||||
|
||||
if (chosen < 0) {
|
||||
return chosen;
|
||||
}
|
||||
|
||||
/*
|
||||
* There is most likely an EOL at the end of the
|
||||
* command line, make sure we terminate the line there.
|
||||
* We can't replace the EOL with a NUL byte in the
|
||||
* source, as this is in read-only memory. So we first
|
||||
* create the property without any termination, then
|
||||
* append a single NUL byte.
|
||||
*/
|
||||
eol = strchr(cmdline, '\n');
|
||||
if (eol == NULL) {
|
||||
eol = strchr(cmdline, 0);
|
||||
}
|
||||
/* Skip the signature and omit the EOL/NUL byte. */
|
||||
slen = eol - (cmdline + strlen(CMDLINE_SIGNATURE));
|
||||
/*
|
||||
* Let's limit the size of the property, just in case
|
||||
* we find the signature by accident. The Linux kernel
|
||||
* limits to 4096 characters at most (in fact 2048 for
|
||||
* arm64), so that sounds like a reasonable number.
|
||||
*/
|
||||
if (slen > 4095) {
|
||||
slen = 4095;
|
||||
}
|
||||
|
||||
err = fdt_setprop(fdt, chosen, "bootargs",
|
||||
cmdline + strlen(CMDLINE_SIGNATURE), slen);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return fdt_appendprop(fdt, chosen, "bootargs", &nul, 1);
|
||||
}
|
||||
|
||||
static void fpga_prepare_dtb(void)
|
||||
{
|
||||
void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE;
|
||||
int err;
|
||||
|
||||
err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE);
|
||||
if (err < 0) {
|
||||
ERROR("cannot open devicetree at %p: %d\n", fdt, err);
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Reserve memory used by Trusted Firmware. */
|
||||
if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE,
|
||||
BL31_LIMIT - BL31_BASE)) {
|
||||
WARN("Failed to add reserved memory node to DT\n");
|
||||
}
|
||||
|
||||
/* Check for the command line signature. */
|
||||
if (!strncmp(cmdline, CMDLINE_SIGNATURE, strlen(CMDLINE_SIGNATURE))) {
|
||||
err = fpga_dtb_set_commandline(fdt, cmdline);
|
||||
if (err == 0) {
|
||||
INFO("using command line at 0x%x\n",
|
||||
FPGA_PRELOADED_CMD_LINE);
|
||||
} else {
|
||||
ERROR("failed to put command line into DTB: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
ERROR("Error %d extending Device Tree\n", err);
|
||||
panic();
|
||||
}
|
||||
|
||||
err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU,
|
||||
FPGA_MAX_CPUS_PER_CLUSTER,
|
||||
FPGA_MAX_CLUSTER_COUNT);
|
||||
|
||||
if (err == -EEXIST) {
|
||||
WARN("Not overwriting already existing /cpus node in DTB\n");
|
||||
} else {
|
||||
if (err < 0) {
|
||||
ERROR("Error %d creating the /cpus DT node\n", err);
|
||||
panic();
|
||||
} else {
|
||||
unsigned int nr_cores = fpga_get_nr_gic_cores();
|
||||
|
||||
INFO("Adjusting GICR DT region to cover %u cores\n",
|
||||
nr_cores);
|
||||
err = fdt_adjust_gic_redist(fdt, nr_cores,
|
||||
fpga_get_redist_base(),
|
||||
fpga_get_redist_size());
|
||||
if (err < 0) {
|
||||
ERROR("Error %d fixing up GIC DT node\n", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fpga_dtb_update_clock(fdt, system_freq);
|
||||
|
||||
/* Check whether we support the SPE PMU. Remove the DT node if not. */
|
||||
if (!spe_supported()) {
|
||||
int node = fdt_node_offset_by_compatible(fdt, 0,
|
||||
"arm,statistical-profiling-extension-v1");
|
||||
|
||||
if (node >= 0) {
|
||||
fdt_del_node(fdt, node);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether we have an ITS. Remove the DT node if not. */
|
||||
if (!fpga_has_its()) {
|
||||
int node = fdt_node_offset_by_compatible(fdt, 0,
|
||||
"arm,gic-v3-its");
|
||||
|
||||
if (node >= 0) {
|
||||
fdt_del_node(fdt, node);
|
||||
}
|
||||
}
|
||||
|
||||
err = fdt_pack(fdt);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err);
|
||||
}
|
||||
|
||||
clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
|
||||
}
|
||||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
fpga_prepare_dtb();
|
||||
}
|
||||
|
||||
void bl31_plat_enable_mmu(uint32_t flags)
|
||||
{
|
||||
/* TODO: determine if MMU needs to be enabled */
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/arm/pl011.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
static console_t console;
|
||||
|
||||
void fpga_console_init(void)
|
||||
{
|
||||
const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
uintptr_t base_addr = PLAT_FPGA_CRASH_UART_BASE;
|
||||
int node;
|
||||
|
||||
/*
|
||||
* Try to read the UART base address from the DT, by chasing the
|
||||
* stdout-path property of the chosen node.
|
||||
* If this does not work, use the crash console address as a fallback.
|
||||
*/
|
||||
node = fdt_get_stdout_node_offset(fdt);
|
||||
if (node >= 0) {
|
||||
fdt_get_reg_props_by_index(fdt, node, 0, &base_addr, NULL);
|
||||
}
|
||||
|
||||
(void)console_pl011_register(base_addr, 0, 0, &console);
|
||||
|
||||
console_set_scope(&console, CONSOLE_FLAG_BOOT |
|
||||
CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#ifndef FPGA_DEF_H
|
||||
#define FPGA_DEF_H
|
||||
|
||||
/*
|
||||
* These are set to large values to account for images describing systems with
|
||||
* larger cluster configurations.
|
||||
*
|
||||
* For cases where the number of clusters, cores or threads is smaller than a
|
||||
* maximum value below, this does not affect the PSCI functionality as any PEs
|
||||
* that are present will still be indexed appropriately regardless of any empty
|
||||
* entries in the array used to represent the topology.
|
||||
*/
|
||||
|
||||
#define FPGA_MAX_CLUSTER_COUNT 4
|
||||
#define FPGA_MAX_CPUS_PER_CLUSTER 8
|
||||
#define FPGA_MAX_PE_PER_CPU 4
|
||||
|
||||
#define FPGA_PRIMARY_CPU 0x0
|
||||
/*******************************************************************************
|
||||
* FPGA image memory map related constants
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* UART base address, just for the crash console, as a fallback.
|
||||
* The actual console UART address is taken from the DT.
|
||||
*/
|
||||
#define PLAT_FPGA_CRASH_UART_BASE 0x7ff80000
|
||||
|
||||
#define FPGA_DEFAULT_TIMER_FREQUENCY 10000000
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/arm/arm_gicv3_common.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static const interrupt_prop_t fpga_interrupt_props[] = {
|
||||
PLATFORM_G1S_PROPS(INTR_GROUP1S),
|
||||
PLATFORM_G0_PROPS(INTR_GROUP0)
|
||||
};
|
||||
|
||||
static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
||||
static int nr_itses;
|
||||
|
||||
static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr)
|
||||
{
|
||||
return (unsigned int)plat_core_pos_by_mpidr(mpidr);
|
||||
}
|
||||
|
||||
static gicv3_driver_data_t fpga_gicv3_driver_data = {
|
||||
.interrupt_props = fpga_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props),
|
||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
||||
.rdistif_base_addrs = fpga_rdistif_base_addrs,
|
||||
.mpidr_to_core_pos = fpga_mpidr_to_core_pos
|
||||
};
|
||||
|
||||
void plat_fpga_gic_init(void)
|
||||
{
|
||||
const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
uintptr_t gicr_base = 0U;
|
||||
uint32_t iidr;
|
||||
int node, ret;
|
||||
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,gic-v3");
|
||||
if (node < 0) {
|
||||
WARN("No \"arm,gic-v3\" compatible node found in DT, no GIC support.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Assuming only empty "ranges;" properties up the bus path. */
|
||||
ret = fdt_get_reg_props_by_index(fdt, node, 0,
|
||||
&fpga_gicv3_driver_data.gicd_base, NULL);
|
||||
if (ret < 0) {
|
||||
WARN("Could not read GIC distributor address from DT.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
iidr = mmio_read_32(fpga_gicv3_driver_data.gicd_base + GICD_IIDR);
|
||||
if (((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
|
||||
((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)) {
|
||||
unsigned int frame_id;
|
||||
|
||||
/*
|
||||
* According to the GIC TRMs, if there are any ITSes, they
|
||||
* start four 64K pages after the distributor. After all
|
||||
* the ITSes then follow the redistributors.
|
||||
*/
|
||||
gicr_base = fpga_gicv3_driver_data.gicd_base + (4U << 16);
|
||||
|
||||
do {
|
||||
uint64_t its_typer;
|
||||
|
||||
/* Each GIC component can be identified by its ID. */
|
||||
frame_id = gicv3_get_component_partnum(gicr_base);
|
||||
|
||||
if (frame_id == PIDR_COMPONENT_ARM_REDIST) {
|
||||
INFO("Found %d ITSes, redistributors start at 0x%llx\n",
|
||||
nr_itses, (unsigned long long)gicr_base);
|
||||
break;
|
||||
}
|
||||
|
||||
if (frame_id != PIDR_COMPONENT_ARM_ITS) {
|
||||
WARN("GICv3: found unexpected frame 0x%x\n",
|
||||
frame_id);
|
||||
gicr_base = 0U;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found an ITS, now work out if it supports virtual
|
||||
* SGIs (for direct guest injection). If yes, each
|
||||
* ITS occupies four 64K pages, otherwise just two.
|
||||
*/
|
||||
its_typer = mmio_read_64(gicr_base + GITS_TYPER);
|
||||
if ((its_typer & GITS_TYPER_VSGI) != 0U) {
|
||||
gicr_base += 4U << 16;
|
||||
} else {
|
||||
gicr_base += 2U << 16;
|
||||
}
|
||||
nr_itses++;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not a GIC-600 or -700, or the autodetection above failed,
|
||||
* use the base address from the device tree.
|
||||
*/
|
||||
if (gicr_base == 0U) {
|
||||
ret = fdt_get_reg_props_by_index(fdt, node, 1,
|
||||
&fpga_gicv3_driver_data.gicr_base,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
WARN("Could not read GIC redistributor address from DT.\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fpga_gicv3_driver_data.gicr_base = gicr_base;
|
||||
}
|
||||
|
||||
gicv3_driver_init(&fpga_gicv3_driver_data);
|
||||
gicv3_distif_init();
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void fpga_pwr_gic_on_finish(void)
|
||||
{
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void fpga_pwr_gic_off(void)
|
||||
{
|
||||
gicv3_cpuif_disable(plat_my_core_pos());
|
||||
gicv3_rdistif_off(plat_my_core_pos());
|
||||
}
|
||||
|
||||
unsigned int fpga_get_nr_gic_cores(void)
|
||||
{
|
||||
return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base);
|
||||
}
|
||||
|
||||
uintptr_t fpga_get_redist_size(void)
|
||||
{
|
||||
uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base +
|
||||
GICR_TYPER);
|
||||
|
||||
return gicv3_redist_size(typer_val);
|
||||
}
|
||||
|
||||
uintptr_t fpga_get_redist_base(void)
|
||||
{
|
||||
return fpga_gicv3_driver_data.gicr_base;
|
||||
}
|
||||
|
||||
bool fpga_has_its(void)
|
||||
{
|
||||
return nr_itses > 0;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "fpga_private.h"
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* This is a basic PSCI implementation that allows secondary CPUs to be
|
||||
* released from their initial state and continue to the warm boot entrypoint.
|
||||
*
|
||||
* The secondary CPUs are placed in a holding pen and released by calls
|
||||
* to fpga_pwr_domain_on(mpidr), which updates the hold entry for the CPU
|
||||
* specified by the mpidr argument - the (polling) target CPU will then branch
|
||||
* to the BL31 warm boot sequence at the entrypoint address.
|
||||
*
|
||||
* Additionally, the secondary CPUs are kept in a low-power wfe() state
|
||||
* (placed there at the end of each poll) and woken when necessary through
|
||||
* calls to sev() in fpga_pwr_domain_on(mpidr), once the hold state for the
|
||||
* relevant CPU has been updated.
|
||||
*
|
||||
* Hotplug is currently implemented using a wfi-loop, which removes the
|
||||
* dependencies on any power controllers or other mechanism that is specific
|
||||
* to the running system as specified by the FPGA image.
|
||||
*/
|
||||
|
||||
uint64_t hold_base[PLATFORM_CORE_COUNT];
|
||||
uintptr_t fpga_sec_entrypoint;
|
||||
|
||||
/*
|
||||
* Calls to the CPU specified by the mpidr will set its hold entry to a value
|
||||
* indicating that it should stop polling and branch off to the warm entrypoint.
|
||||
*/
|
||||
static int fpga_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
int pos = plat_core_pos_by_mpidr(mpidr);
|
||||
unsigned long current_mpidr = read_mpidr_el1();
|
||||
|
||||
if (pos < 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
if (mpidr == current_mpidr) {
|
||||
return PSCI_E_ALREADY_ON;
|
||||
}
|
||||
hold_base[pos] = PLAT_FPGA_HOLD_STATE_GO;
|
||||
flush_dcache_range((uintptr_t)&hold_base[pos], sizeof(uint64_t));
|
||||
sev(); /* Wake any CPUs from wfe */
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
fpga_pwr_gic_on_finish();
|
||||
}
|
||||
|
||||
static void fpga_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
fpga_pwr_gic_off();
|
||||
|
||||
while (1) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
|
||||
static void fpga_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
/*
|
||||
* Enter standby state
|
||||
* dsb is good practice before using wfi to enter low power states
|
||||
*/
|
||||
u_register_t scr = read_scr_el3();
|
||||
write_scr_el3(scr|SCR_IRQ_BIT);
|
||||
dsb();
|
||||
wfi();
|
||||
write_scr_el3(scr);
|
||||
}
|
||||
|
||||
plat_psci_ops_t plat_fpga_psci_pm_ops = {
|
||||
.pwr_domain_on = fpga_pwr_domain_on,
|
||||
.pwr_domain_on_finish = fpga_pwr_domain_on_finish,
|
||||
.pwr_domain_off = fpga_pwr_domain_off,
|
||||
.cpu_standby = fpga_cpu_standby
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
fpga_sec_entrypoint = sec_entrypoint;
|
||||
flush_dcache_range((uint64_t)&fpga_sec_entrypoint,
|
||||
sizeof(fpga_sec_entrypoint));
|
||||
*psci_ops = &plat_fpga_psci_pm_ops;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef FPGA_PRIVATE_H
|
||||
#define FPGA_PRIVATE_H
|
||||
|
||||
#include "../fpga_def.h"
|
||||
#include <platform_def.h>
|
||||
|
||||
#define C_RUNTIME_READY_KEY (0xaa55aa55)
|
||||
#define VALID_MPID (1U)
|
||||
#define FPGA_MAX_DTB_SIZE 0x10000
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
|
||||
|
||||
void fpga_console_init(void);
|
||||
|
||||
void plat_fpga_gic_init(void);
|
||||
void fpga_pwr_gic_on_finish(void);
|
||||
void fpga_pwr_gic_off(void);
|
||||
unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
|
||||
unsigned int fpga_get_nr_gic_cores(void);
|
||||
uintptr_t fpga_get_redist_size(void);
|
||||
uintptr_t fpga_get_redist_base(void);
|
||||
bool fpga_has_its(void);
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* FPGA_PRIVATE_H */
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/spinlock.h>
|
||||
|
||||
#include "fpga_private.h"
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
|
||||
unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
|
||||
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* The highest level is the system level. The next level is constituted
|
||||
* by clusters and then cores in clusters.
|
||||
*
|
||||
* This description of the power domain topology is aligned with the CPU
|
||||
* indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
|
||||
* APIs.
|
||||
*
|
||||
* A description of the topology tree can be found at
|
||||
* https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
|
||||
*/
|
||||
|
||||
if (fpga_power_domain_tree_desc[0] == 0U) {
|
||||
/*
|
||||
* As fpga_power_domain_tree_desc[0] == 0, assume that the
|
||||
* Power Domain Topology Tree has not been initialized, so
|
||||
* perform the initialization here.
|
||||
*/
|
||||
|
||||
fpga_power_domain_tree_desc[0] = 1U;
|
||||
fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
|
||||
|
||||
for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
|
||||
fpga_power_domain_tree_desc[2 + i] =
|
||||
(FPGA_MAX_CPUS_PER_CLUSTER *
|
||||
FPGA_MAX_PE_PER_CPU);
|
||||
}
|
||||
}
|
||||
|
||||
return fpga_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int core_pos;
|
||||
|
||||
mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
|
||||
mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
|
||||
|
||||
if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
|
||||
(MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
|
||||
(MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
|
||||
ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Calculate the core position, based on the maximum topology. */
|
||||
core_pos = plat_fpga_calc_core_pos(mpidr);
|
||||
|
||||
/* Check whether this core is actually present. */
|
||||
if (fpga_valid_mpids[core_pos] != VALID_MPID) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return core_pos;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
.macro plat_crash_print_regs
|
||||
.endm
|
||||
|
||||
#endif
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <plat/common/common_def.h>
|
||||
#include <platform_def.h>
|
||||
#include "../fpga_def.h"
|
||||
|
||||
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
||||
|
||||
#define PLATFORM_LINKER_ARCH aarch64
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x800)
|
||||
|
||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
#define PLATFORM_CORE_COUNT \
|
||||
(FPGA_MAX_CLUSTER_COUNT * \
|
||||
FPGA_MAX_CPUS_PER_CLUSTER * \
|
||||
FPGA_MAX_PE_PER_CPU)
|
||||
|
||||
#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1)
|
||||
|
||||
#if !ENABLE_PIE
|
||||
#define BL31_BASE UL(0x80000000)
|
||||
#define BL31_LIMIT UL(0x80070000)
|
||||
#else
|
||||
#define BL31_BASE UL(0x0)
|
||||
#define BL31_LIMIT UL(0x01000000)
|
||||
#endif
|
||||
|
||||
#define PLAT_SDEI_NORMAL_PRI 0x70
|
||||
|
||||
#define ARM_IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define ARM_IRQ_SEC_SGI_0 8
|
||||
#define ARM_IRQ_SEC_SGI_1 9
|
||||
#define ARM_IRQ_SEC_SGI_2 10
|
||||
#define ARM_IRQ_SEC_SGI_3 11
|
||||
#define ARM_IRQ_SEC_SGI_4 12
|
||||
#define ARM_IRQ_SEC_SGI_5 13
|
||||
#define ARM_IRQ_SEC_SGI_6 14
|
||||
#define ARM_IRQ_SEC_SGI_7 15
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define PLATFORM_G1S_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define PLATFORM_G0_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define PLAT_MAX_RET_STATE 1
|
||||
#define PLAT_MAX_OFF_STATE 2
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
|
||||
|
||||
#define PLAT_FPGA_HOLD_ENTRY_SHIFT 3
|
||||
#define PLAT_FPGA_HOLD_STATE_WAIT 0
|
||||
#define PLAT_FPGA_HOLD_STATE_GO 1
|
||||
|
||||
#endif
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2021, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* The traditional arm64 Linux kernel load address is 512KiB from the
|
||||
* beginning of DRAM, caused by this having been the default value of the
|
||||
* kernel's CONFIG_TEXT_OFFSET Kconfig value.
|
||||
* However kernel version 5.8 changed the default offset (into a 2MB page)
|
||||
* to 0, so TF-A's default assumption is no longer true. Fortunately the
|
||||
* kernel got more relaxed about this offset at the same time, so it
|
||||
* tolerates the wrong offset, but issues a warning:
|
||||
* [Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!
|
||||
*
|
||||
* We cannot easily change the load address offset in TF-A to be 2MiB, because
|
||||
* this would break older kernels - and they are not as forgiving in this
|
||||
* respect.
|
||||
*
|
||||
* But we can allow users to load the kernel at the right offset, and
|
||||
* offer this trampoline here to transition to this new load address.
|
||||
* Any older kernels, or newer kernels misloaded, will overwrite this code
|
||||
* here, so it does no harm in this case.
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.ld.h>
|
||||
|
||||
.text
|
||||
.global _tramp_start
|
||||
|
||||
_tramp_start:
|
||||
adr x4, _tramp_start
|
||||
orr x4, x4, #0x1fffff
|
||||
add x4, x4, #1 /* align up to 2MB */
|
||||
br x4
|
||||
@@ -0,0 +1,130 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include common/fdt_wrappers.mk
|
||||
include lib/libfdt/libfdt.mk
|
||||
|
||||
RESET_TO_BL31 := 1
|
||||
ifeq (${RESET_TO_BL31}, 0)
|
||||
$(error "This is a BL31-only port; RESET_TO_BL31 must be enabled")
|
||||
endif
|
||||
|
||||
ifeq (${ENABLE_PIE}, 1)
|
||||
override SEPARATE_CODE_AND_RODATA := 1
|
||||
endif
|
||||
|
||||
CTX_INCLUDE_AARCH32_REGS := 0
|
||||
ifeq (${CTX_INCLUDE_AARCH32_REGS}, 1)
|
||||
$(error "This is an AArch64-only port; CTX_INCLUDE_AARCH32_REGS must be disabled")
|
||||
endif
|
||||
|
||||
ifeq (${TRUSTED_BOARD_BOOT}, 1)
|
||||
$(error "TRUSTED_BOARD_BOOT must be disabled")
|
||||
endif
|
||||
|
||||
PRELOADED_BL33_BASE := 0x80080000
|
||||
|
||||
FPGA_PRELOADED_DTB_BASE := 0x80070000
|
||||
$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
|
||||
|
||||
FPGA_PRELOADED_CMD_LINE := 0x1000
|
||||
$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
|
||||
|
||||
ENABLE_AMU := 1
|
||||
|
||||
# Treating this as a memory-constrained port for now
|
||||
USE_COHERENT_MEM := 0
|
||||
|
||||
# This can be overridden depending on CPU(s) used in the FPGA image
|
||||
HW_ASSISTED_COHERENCY := 1
|
||||
|
||||
PL011_GENERIC_UART := 1
|
||||
|
||||
SUPPORT_UNKNOWN_MPID ?= 1
|
||||
|
||||
FPGA_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
|
||||
|
||||
# select a different set of CPU files, depending on whether we compile for
|
||||
# hardware assisted coherency cores or not
|
||||
ifeq (${HW_ASSISTED_COHERENCY}, 0)
|
||||
# Cores used without DSU
|
||||
FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
lib/cpus/aarch64/cortex_a57.S \
|
||||
lib/cpus/aarch64/cortex_a72.S \
|
||||
lib/cpus/aarch64/cortex_a73.S
|
||||
else
|
||||
# AArch64-only cores
|
||||
FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \
|
||||
lib/cpus/aarch64/cortex_a76ae.S \
|
||||
lib/cpus/aarch64/cortex_a77.S \
|
||||
lib/cpus/aarch64/cortex_a78.S \
|
||||
lib/cpus/aarch64/neoverse_n_common.S \
|
||||
lib/cpus/aarch64/neoverse_n1.S \
|
||||
lib/cpus/aarch64/neoverse_n2.S \
|
||||
lib/cpus/aarch64/neoverse_e1.S \
|
||||
lib/cpus/aarch64/neoverse_v1.S \
|
||||
lib/cpus/aarch64/cortex_a78_ae.S \
|
||||
lib/cpus/aarch64/cortex_a65.S \
|
||||
lib/cpus/aarch64/cortex_a65ae.S \
|
||||
lib/cpus/aarch64/cortex_a510.S \
|
||||
lib/cpus/aarch64/cortex_a710.S \
|
||||
lib/cpus/aarch64/cortex_a715.S \
|
||||
lib/cpus/aarch64/cortex_x3.S \
|
||||
lib/cpus/aarch64/cortex_a78c.S
|
||||
|
||||
# AArch64/AArch32 cores
|
||||
FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \
|
||||
lib/cpus/aarch64/cortex_a75.S
|
||||
endif
|
||||
|
||||
ifeq (${SUPPORT_UNKNOWN_MPID}, 1)
|
||||
# Add support for unknown/invalid MPIDs (aarch64 only)
|
||||
$(eval $(call add_define,SUPPORT_UNKNOWN_MPID))
|
||||
FPGA_CPU_LIBS += lib/cpus/aarch64/generic.S
|
||||
endif
|
||||
|
||||
# Allow detection of GIC-600
|
||||
GICV3_SUPPORT_GIC600 := 1
|
||||
|
||||
GIC_ENABLE_V4_EXTN := 1
|
||||
|
||||
# Include GICv3 driver files
|
||||
include drivers/arm/gic/v3/gicv3.mk
|
||||
|
||||
FPGA_GIC_SOURCES := ${GICV3_SOURCES} \
|
||||
plat/common/plat_gicv3.c \
|
||||
plat/arm/board/arm_fpga/fpga_gicv3.c
|
||||
|
||||
FDT_SOURCES := fdts/arm_fpga.dts
|
||||
|
||||
PLAT_INCLUDES := -Iplat/arm/board/arm_fpga/include
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := plat/arm/board/arm_fpga/${ARCH}/fpga_helpers.S
|
||||
|
||||
BL31_SOURCES += common/fdt_fixup.c \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/delay_timer/generic_delay_timer.c \
|
||||
drivers/arm/pl011/${ARCH}/pl011_console.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
plat/arm/board/arm_fpga/fpga_pm.c \
|
||||
plat/arm/board/arm_fpga/fpga_topology.c \
|
||||
plat/arm/board/arm_fpga/fpga_console.c \
|
||||
plat/arm/board/arm_fpga/fpga_bl31_setup.c \
|
||||
${FPGA_CPU_LIBS} \
|
||||
${FPGA_GIC_SOURCES}
|
||||
|
||||
BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,bl31))
|
||||
$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,bl31))
|
||||
$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,bl31))
|
||||
|
||||
bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld
|
||||
$(ECHO) " LD $@"
|
||||
$(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf
|
||||
|
||||
all: bl31.axf
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* The Arm Ltd. FPGA images start execution at address 0x0, which is
|
||||
* mapped at an (emulated) ROM image. The payload uploader can write to
|
||||
* this memory, but write access by the CPU cores is prohibited.
|
||||
*
|
||||
* Provide a simple trampoline to start BL31 execution at the actual
|
||||
* load address. We put the DTB address in x0, so any code in DRAM could
|
||||
* make use of that information (not yet used in BL31 right now).
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.ld.h>
|
||||
|
||||
.text
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
mov_imm x1, BL31_BASE /* beginning of DRAM */
|
||||
mov_imm x0, FPGA_PRELOADED_DTB_BASE
|
||||
br x1
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_report_exception
|
||||
|
||||
|
||||
/* -------------------------------------------------------
|
||||
* void plat_report_exception(unsigned int type)
|
||||
* Function to report an unhandled exception
|
||||
* with platform-specific means.
|
||||
* On FVP platform, it updates the LEDs
|
||||
* to indicate where we are.
|
||||
* SYS_LED[0] - 0x0
|
||||
* SYS_LED[2:1] - 0x0
|
||||
* SYS_LED[7:3] - Exception Mode.
|
||||
* Clobbers: r0-r1
|
||||
* -------------------------------------------------------
|
||||
*/
|
||||
func plat_report_exception
|
||||
lsl r0, r0, #V2M_SYS_LED_EC_SHIFT
|
||||
ldr r1, =V2M_SYSREGS_BASE
|
||||
add r1, r1, #V2M_SYS_LED
|
||||
str r0, [r1]
|
||||
bx lr
|
||||
endfunc plat_report_exception
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_report_exception
|
||||
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_report_exception(unsigned int type)
|
||||
* Function to report an unhandled exception
|
||||
* with platform-specific means.
|
||||
* On FVP platform, it updates the LEDs
|
||||
* to indicate where we are
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_report_exception
|
||||
mrs x1, CurrentEl
|
||||
lsr x1, x1, #MODE_EL_SHIFT
|
||||
lsl x1, x1, #V2M_SYS_LED_EL_SHIFT
|
||||
lsl x0, x0, #V2M_SYS_LED_EC_SHIFT
|
||||
mov x2, #(SECURE << V2M_SYS_LED_SS_SHIFT)
|
||||
orr x0, x0, x2
|
||||
orr x0, x0, x1
|
||||
mov x1, #V2M_SYSREGS_BASE
|
||||
add x1, x1, #V2M_SYS_LED
|
||||
str w0, [x1]
|
||||
ret
|
||||
endfunc plat_report_exception
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/cryptocell/cc_rotpk.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/cassert.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <plat/common/common_def.h>
|
||||
#include <plat/common/platform.h>
|
||||
#if defined(ARM_COT_cca)
|
||||
#include <tools_share/cca_oid.h>
|
||||
#elif defined(ARM_COT_dualroot)
|
||||
#include <tools_share/dualroot_oid.h>
|
||||
#elif defined(ARM_COT_tbbr)
|
||||
#include <tools_share/tbbr_oid.h>
|
||||
#endif
|
||||
|
||||
#include <plat/arm/common/fconf_nv_cntr_getter.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#if !ARM_CRYPTOCELL_INTEG
|
||||
#if !ARM_ROTPK_LOCATION_ID
|
||||
#error "ARM_ROTPK_LOCATION_ID not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if COT_DESC_IN_DTB && defined(IMAGE_BL2)
|
||||
uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS];
|
||||
#else
|
||||
uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS] = {
|
||||
TFW_NVCTR_BASE,
|
||||
NTFW_CTR_BASE
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* Weak definition may be overridden in specific platform */
|
||||
#pragma weak plat_get_nv_ctr
|
||||
#pragma weak plat_set_nv_ctr
|
||||
|
||||
extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[];
|
||||
|
||||
#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) || ARM_CRYPTOCELL_INTEG
|
||||
static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
|
||||
#endif
|
||||
|
||||
#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
|
||||
/*
|
||||
* Return the ROTPK hash stored in dedicated registers.
|
||||
*/
|
||||
int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
uint8_t *dst;
|
||||
uint32_t *src, tmp;
|
||||
unsigned int words, i;
|
||||
|
||||
assert(key_ptr != NULL);
|
||||
assert(key_len != NULL);
|
||||
assert(flags != NULL);
|
||||
|
||||
/* Copy the DER header */
|
||||
|
||||
memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
|
||||
dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
|
||||
|
||||
words = ARM_ROTPK_HASH_LEN >> 2;
|
||||
|
||||
src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
|
||||
for (i = 0 ; i < words ; i++) {
|
||||
tmp = src[words - 1 - i];
|
||||
/* Words are read in little endian */
|
||||
*dst++ = (uint8_t)(tmp & 0xFF);
|
||||
*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
|
||||
*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
|
||||
*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
*key_ptr = (void *)rotpk_hash_der;
|
||||
*key_len = (unsigned int)sizeof(rotpk_hash_der);
|
||||
*flags = ROTPK_IS_HASH;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
|
||||
(ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
|
||||
/*
|
||||
* Return development ROTPK hash generated from ROT_KEY.
|
||||
*/
|
||||
int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
*key_ptr = arm_rotpk_header;
|
||||
*key_len = arm_rotpk_hash_end - arm_rotpk_header;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ARM_CRYPTOCELL_INTEG
|
||||
/*
|
||||
* Return ROTPK hash from CryptoCell.
|
||||
*/
|
||||
int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
unsigned char *dst;
|
||||
|
||||
assert(key_ptr != NULL);
|
||||
assert(key_len != NULL);
|
||||
assert(flags != NULL);
|
||||
|
||||
/* Copy the DER header */
|
||||
memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
|
||||
dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
|
||||
*key_ptr = rotpk_hash_der;
|
||||
*key_len = sizeof(rotpk_hash_der);
|
||||
return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wrapper function for most Arm platforms to get ROTPK hash.
|
||||
*/
|
||||
static int get_rotpk_info(void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
#if ARM_CRYPTOCELL_INTEG
|
||||
return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
|
||||
#else
|
||||
|
||||
#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
|
||||
(ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
|
||||
return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
|
||||
#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
|
||||
return arm_get_rotpk_info_regs(key_ptr, key_len, flags);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
#endif /* ARM_CRYPTOCELL_INTEG */
|
||||
}
|
||||
|
||||
#if defined(ARM_COT_tbbr)
|
||||
|
||||
int arm_get_rotpk_info(void *cookie __unused, void **key_ptr,
|
||||
unsigned int *key_len, unsigned int *flags)
|
||||
{
|
||||
return get_rotpk_info(key_ptr, key_len, flags);
|
||||
}
|
||||
|
||||
#elif defined(ARM_COT_dualroot)
|
||||
|
||||
int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
/*
|
||||
* Return the right root of trust key hash based on the cookie value:
|
||||
* - NULL means the primary ROTPK.
|
||||
* - Otherwise, interpret cookie as the OID of the certificate
|
||||
* extension containing the key.
|
||||
*/
|
||||
if (cookie == NULL) {
|
||||
return get_rotpk_info(key_ptr, key_len, flags);
|
||||
} else if (strcmp(cookie, PROT_PK_OID) == 0) {
|
||||
extern unsigned char arm_protpk_hash[];
|
||||
extern unsigned char arm_protpk_hash_end[];
|
||||
*key_ptr = arm_protpk_hash;
|
||||
*key_len = arm_protpk_hash_end - arm_protpk_hash;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
return 0;
|
||||
} else {
|
||||
/* Invalid key ID. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(ARM_COT_cca)
|
||||
|
||||
int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
/*
|
||||
* Return the right root of trust key hash based on the cookie value:
|
||||
* - NULL means the primary ROTPK.
|
||||
* - Otherwise, interpret cookie as the OID of the certificate
|
||||
* extension containing the key.
|
||||
*/
|
||||
if (cookie == NULL) {
|
||||
return get_rotpk_info(key_ptr, key_len, flags);
|
||||
} else if (strcmp(cookie, PROT_PK_OID) == 0) {
|
||||
extern unsigned char arm_protpk_hash[];
|
||||
extern unsigned char arm_protpk_hash_end[];
|
||||
*key_ptr = arm_protpk_hash;
|
||||
*key_len = arm_protpk_hash_end - arm_protpk_hash;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
return 0;
|
||||
} else if (strcmp(cookie, SWD_ROT_PK_OID) == 0) {
|
||||
extern unsigned char arm_swd_rotpk_hash[];
|
||||
extern unsigned char arm_swd_rotpk_hash_end[];
|
||||
*key_ptr = arm_swd_rotpk_hash;
|
||||
*key_len = arm_swd_rotpk_hash_end - arm_swd_rotpk_hash;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
return 0;
|
||||
} else {
|
||||
/* Invalid key ID. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the non-volatile counter value stored in the platform. The cookie
|
||||
* will contain the OID of the counter in the certificate.
|
||||
*
|
||||
* Return: 0 = success, Otherwise = error
|
||||
*/
|
||||
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
|
||||
{
|
||||
const char *oid;
|
||||
uint32_t *nv_ctr_addr;
|
||||
|
||||
assert(cookie != NULL);
|
||||
assert(nv_ctr != NULL);
|
||||
|
||||
oid = (const char *)cookie;
|
||||
if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
|
||||
nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr,
|
||||
TRUSTED_NV_CTR_ID);
|
||||
} else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
|
||||
nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr,
|
||||
NON_TRUSTED_NV_CTR_ID);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
*nv_ctr = (unsigned int)(*nv_ctr_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a new non-volatile counter value. By default on ARM development
|
||||
* platforms, the non-volatile counters are RO and cannot be modified. We expect
|
||||
* the values in the certificates to always match the RO values so that this
|
||||
* function is never called.
|
||||
*
|
||||
* Return: 0 = success, Otherwise = error
|
||||
*/
|
||||
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#
|
||||
# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \
|
||||
plat/arm/board/common/${ARCH}/board_arm_helpers.S
|
||||
|
||||
BL1_SOURCES += drivers/cfi/v2m/v2m_flash.c
|
||||
|
||||
BL2_SOURCES += drivers/cfi/v2m/v2m_flash.c
|
||||
|
||||
ifneq (${TRUSTED_BOARD_BOOT},0)
|
||||
ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
|
||||
# ROTPK hash location
|
||||
ifeq (${ARM_ROTPK_LOCATION}, regs)
|
||||
ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
|
||||
else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
|
||||
CRYPTO_ALG=rsa
|
||||
ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
|
||||
ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin
|
||||
$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
|
||||
$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
|
||||
$(warning Development keys support for FVP is deprecated. Use `regs` \
|
||||
option instead)
|
||||
else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
|
||||
CRYPTO_ALG=ec
|
||||
ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
|
||||
ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
|
||||
$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
|
||||
$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
|
||||
$(warning Development keys support for FVP is deprecated. Use `regs` \
|
||||
option instead)
|
||||
else
|
||||
$(error "Unsupported ARM_ROTPK_LOCATION value")
|
||||
endif
|
||||
|
||||
$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
|
||||
|
||||
ifeq (${ENABLE_RME}, 1)
|
||||
COT := cca
|
||||
endif
|
||||
|
||||
# Force generation of the new hash if ROT_KEY is specified
|
||||
ifdef ROT_KEY
|
||||
HASH_PREREQUISITES = $(ROT_KEY) FORCE
|
||||
else
|
||||
HASH_PREREQUISITES = $(ROT_KEY)
|
||||
endif
|
||||
|
||||
$(ARM_ROTPK_HASH) : $(HASH_PREREQUISITES)
|
||||
ifndef ROT_KEY
|
||||
$(error Cannot generate hash: no ROT_KEY defined)
|
||||
endif
|
||||
${OPENSSL_BIN_PATH}/openssl ${CRYPTO_ALG} -in $< -pubout -outform DER | \
|
||||
${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@
|
||||
|
||||
# Certificate NV-Counters. Use values corresponding to tied off values in
|
||||
# ARM development platforms
|
||||
TFW_NVCTR_VAL ?= 31
|
||||
NTFW_NVCTR_VAL ?= 223
|
||||
else
|
||||
# Certificate NV-Counters when CryptoCell is integrated. For development
|
||||
# platforms we set the counter to first valid value.
|
||||
TFW_NVCTR_VAL ?= 0
|
||||
NTFW_NVCTR_VAL ?= 0
|
||||
endif
|
||||
BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \
|
||||
plat/arm/board/common/rotpk/arm_dev_rotpk.S
|
||||
BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \
|
||||
plat/arm/board/common/rotpk/arm_dev_rotpk.S
|
||||
|
||||
# Allows platform code to provide implementation variants depending on the
|
||||
# selected chain of trust.
|
||||
$(eval $(call add_define,ARM_COT_${COT}))
|
||||
|
||||
ifeq (${COT},dualroot)
|
||||
# Platform Root of Trust key files.
|
||||
ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem
|
||||
ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
|
||||
|
||||
# Provide the private key to cert_create tool. It needs it to sign the images.
|
||||
PROT_KEY := ${ARM_PROT_KEY}
|
||||
|
||||
$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"'))
|
||||
|
||||
BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S
|
||||
BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S
|
||||
|
||||
$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
|
||||
$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
|
||||
endif
|
||||
|
||||
ifeq (${COT},cca)
|
||||
# Platform and Secure World Root of Trust key files.
|
||||
ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem
|
||||
ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
|
||||
ARM_SWD_ROT_KEY := plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem
|
||||
ARM_SWD_ROTPK_HASH := plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin
|
||||
|
||||
# Provide the private keys to cert_create tool. It needs them to sign the images.
|
||||
PROT_KEY := ${ARM_PROT_KEY}
|
||||
SWD_ROT_KEY := ${ARM_SWD_ROT_KEY}
|
||||
|
||||
$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"'))
|
||||
$(eval $(call add_define_val,ARM_SWD_ROTPK_HASH,'"$(ARM_SWD_ROTPK_HASH)"'))
|
||||
|
||||
BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S \
|
||||
plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S
|
||||
BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S \
|
||||
plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S
|
||||
|
||||
$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
|
||||
$(BUILD_PLAT)/bl1/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK_HASH)
|
||||
$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
|
||||
$(BUILD_PLAT)/bl2/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK_HASH)
|
||||
endif
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,14 @@
|
||||
This directory contains some development keys to be used as the platform
|
||||
root-of-trust key.
|
||||
|
||||
* arm_protprivk_rsa.pem is a 2K RSA private key in PEM format. It has been
|
||||
generated using the openssl command line tool:
|
||||
|
||||
openssl genrsa 2048 > arm_protprivk_rsa.pem
|
||||
|
||||
* arm_protpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key
|
||||
associated with the above private key. It has been generated using the openssl
|
||||
command line tool:
|
||||
|
||||
openssl rsa -in arm_protprivk_rsa.pem -pubout -outform DER | \
|
||||
openssl dgst -sha256 -binary > arm_protpk_rsa_sha256.bin
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
.global arm_protpk_hash
|
||||
.global arm_protpk_hash_end
|
||||
|
||||
.section .rodata.arm_protpk_hash, "a"
|
||||
|
||||
arm_protpk_hash:
|
||||
/* DER header. */
|
||||
.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
|
||||
.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
/* Key hash. */
|
||||
.incbin ARM_PROTPK_HASH
|
||||
arm_protpk_hash_end:
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAzR0h/Z4Up17wfuRlYrUWseGDmlGKpl1PflGiYbyVmI7PwTTp
|
||||
y/T77EiljGp52suLWntHsc0lee50pW16DU2c5bVfmyofau3GjJ1Yqw5XFAahr6eM
|
||||
/0mkN8utrevvcRT9CP07D+zdhb/WlRUAnedqr/AUHU8BXS+Bxe8P0Z0Z7+DKjYZp
|
||||
thzXxsjKM02BFFzNwyVrlyBFDkW/53A4M+dpmuWDjAGCJH88W/u0LdmLcii11IzD
|
||||
/Ofz8Jxc/ZhqL+9FFK4qU+AJp8yXAnACSB46DlNltJrode0y5tmPhtS37ZF7EFb8
|
||||
UZWwZVgtuQyuyz9RYUS6jtiGuq6s8GlRwjTe7wIDAQABAoIBAFoWIYeyln+sQxR4
|
||||
W88umfkmgxaUGcFX2kIwuJEUst9+WeERzF24C62LeqphWYOvQlVLMAH3iC41fSXr
|
||||
H2AYZoC9WHBd386nAD1iHj+C3Nv+zaTIgjTdszKOUonAxjl0bm40SmyELAdCaoyv
|
||||
3MV9jm4Xk74LpR24b9bvWJNH3MxttH9hiYS+n0IzeTXDfO8GrNvHh92zx+jo8yMm
|
||||
Khhu+TDC9jA2pHpJcF/0EXxYMhwYiQT16nnHb+xMgS4JpalQhvVK01s4VYGHRoFk
|
||||
K6xh4TIS336LDLyalrGsPlfNfEdx+DimShDIfBUx9Jp3Pp11TUQUz4rhIHB9WdfG
|
||||
b6bV4wECgYEA+cgPS2TQ7XQ1RJq1S7OGePtBXvnoH226KwGS6Fey8838tLxbblim
|
||||
MU+EOYs3O66V6U2YpzmIakXo8030k8thY+jKbZl3l0m/hMuPOG66hfE5i7dYsiP4
|
||||
atok5wFiNeNYYjHMEayzk53MhG8EOh36msAO7ohKmenONUBA7pk6yTkCgYEA0jhk
|
||||
HPshwi+wKkx+JLTnuoEgx40tkRgSF2xBqKssMTasaQmX8qG+w9CEs0R8nZCI70Vc
|
||||
tXSFcidjdkHUVE2WsygIFuS1tbsAnpaxtn3E6rjie30X/Z280+TV0HjR0EMETmwl
|
||||
ShC5lZ0oP3LpEZfjbR5qs2kFW4MOxA7tjQVaMWcCgYEA5ZbVMBifzdMl70RA5i9C
|
||||
qEtSQAl3KgRCvar5rKSHsX+iC0Kiy9+iCusq/3WONEZ6NvMDIJpKYFyYDaOW7o5f
|
||||
m2TrRChu+1lnN5mfsGBfBCTBH0JMvZlAin6ussLb0eqBX+ijyY8zlLjTttsQSJcr
|
||||
tThZwTj3UVfOGbZQuL+RgEkCgYBXO3U3nXI9vUIx2zoBC1yZRNoQVGITMlTXiWGZ
|
||||
lyYoadKTZ5q44Sti4BUguounaoGYIEU/OtHhM70PJnPwY53kS/lHXrKUbbvtEwU9
|
||||
f+UFraC1s4wP/rOLjgq3jlsqO5T+4dt7Z4NLNUKtSYazeT6zWgrW1f6WIcUv0C38
|
||||
9bqegwKBgFCK3Oa5ibL5sPaPQ/1UfdeW4JVuu6A4JhHS7r+cVLsmcrvE1Qv7Wcvw
|
||||
B5aqXeqLu2dtIN8/f++3tzccs9LXKY/fh72D4TVjfrqOSSZoGTH9l4U5NXbqWM3I
|
||||
skkAYb2bMST/d1qSyYesgXVNAlaQHRh3vEz8x853nJ3v9OFj8/rW
|
||||
-----END RSA PRIVATE KEY-----
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* corstone1000 platform provides custom values for the macros defined in
|
||||
* arm_def.h , so only platform_def.h needs to be included
|
||||
*/
|
||||
#if !defined(TARGET_PLATFORM_FVP) && !defined(TARGET_PLATFORM_FPGA)
|
||||
#include "plat/arm/common/arm_def.h"
|
||||
#else
|
||||
#include <platform_def.h>
|
||||
#endif
|
||||
|
||||
.global arm_rotpk_header
|
||||
.global arm_rotpk_header_end
|
||||
.section .rodata.arm_rotpk_hash, "a"
|
||||
|
||||
arm_rotpk_header:
|
||||
.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
|
||||
.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
arm_rotpk_header_len:
|
||||
|
||||
#ifdef ARM_ROTPK_HASH
|
||||
.global arm_rotpk_hash_end
|
||||
.incbin ARM_ROTPK_HASH
|
||||
arm_rotpk_hash_end:
|
||||
#endif
|
||||
|
||||
.if ARM_ROTPK_HEADER_LEN != arm_rotpk_header_len - arm_rotpk_header
|
||||
.error "Invalid ROTPK header length."
|
||||
.endif
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+5
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEINSaX6nvzS3teiBJA7WlTLRKJOajpy29o2cArLbUXoZBoAoGCCqGSM49
|
||||
AwEHoUQDQgAEm+ZIvTQ44aKk83DhVLsvsFpKDP/Ch9vA+4Hp+fmVfX6gDH8K1OBi
|
||||
SpRf7FJ9RGPIn2H6xst+a1OtLMWUDRqGkQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLLGDVjWPUB3l+
|
||||
xxaWvU0kTqyG5rdx48VUC+cUHL0pGsE/erYCqqs2xNk2aWziZcObsb89qFYmy/0E
|
||||
AbqsPlQyynleu7IF6gZY8nS64fSHwBkKH2YHd4SDoRzv/yhZ58NofSYgQ+tWY/M5
|
||||
MdgrUam8T9D23pXcX1vB7ZBv7CiRfhfteJD0YKfEx09Q7V0TOiErcMVhewghZTrN
|
||||
glaMekesieilSEgx2R1G5YWGmKDlwKZqvQfkkldhB499Wk3Krja5VgQQ8my+9jts
|
||||
gD6+DqNNx9R+p0nU8tK8zzCo53SPZN+8XEdozEBM+IPMy0A1BGDKs6QXnwPKHVr6
|
||||
0a8hVxDTAgMBAAECggEAfwsc8ewbhDW4TwIGqfNtDUr0rtYN13VpqohW0ki2L8G/
|
||||
HQaKUViO/wxQFqoNn/OqQO0AfHmKhXAAokTCiXngBHJ/OjF7vB7+IRhazZEE6u2/
|
||||
uoivr/OYNQbFpXyTqsQ1eFzpPju6KKcPK7BzT4Mc89ek/vloFAi8w6LdMl8lbvOg
|
||||
LBWqX+5A+UQoenPUTvYM4U22YNcEAWubkpsYAmViiWiac+a+uPRk39aKyfOedDNu
|
||||
+ty9MtCwekivoUTfP/1+O+jFlDnPMJUOEkBmcBqxseYYAHu7blBpdHxYpAItC2pv
|
||||
YwJJSvsE+HLBLPk177Jahg7sOUqcP0F/X+T65yuvIQKBgQDxdjXdJT5K8j7rG2fv
|
||||
2bvF2H1GPaHaTYRk0EGI2Ql6Nn+ddfeCE6gaT7aPPgg87wAhNu93coFuYHw0p/sc
|
||||
ZkXMJ+BmlstPV555cWXmwcxZLsni0fOXrt4YxwWkZwmh74m0NVM/cSFw56PU0oj1
|
||||
yDNeq3fgmsJocmuNTe1eG9qA7QKBgQDXaAGrNA5Xel5mqqMYTHHQWI6l2uzdNtt7
|
||||
eDn3K9+Eh3ywTqrwP845MAjKDU2Lq61I6t2H89dEifHq823VIcLCHd9BF04MrAH7
|
||||
qDPzrmPP2iB9g+YFmGBKe+K0HFE1t1KrTlo9VV6ZAC6RJNLAgwD4kvfIVYNkCGwe
|
||||
+hoZBdhgvwKBgBrOsPQ4ak4PzwRzKnrqhXpVqrLdrNZ7vLMkm+IBlpfG7SwiKLR8
|
||||
UjF5oB8PGAML1cvaOYPdZplGhQOjkrF4eU9NLhC1tSS96Y46FMIlyfYsx6UzAgRZ
|
||||
GbdOgUXbWqpr2bH0KaXlfXz3eqzqIuKGs41TJB//jo3iBibN/AhytzORAoGAeGov
|
||||
5KDpE4XYl9Pz8HVremjG9Xh4yQENmOwQm1fvT4rd7UFM1ZkVk2qCv1DIdLe32vdQ
|
||||
d9ucDzh+ADWsxGRnF1TTpPN+Mh9FzISu5h4qtdreJsxBHgecbIbsqHrb+wdMM29N
|
||||
itPaWfV8Eq9fETcqp8qgsWD8XkNHDdoKFMrrtskCgYAoSt/Je1D3ZE/3HEjez7bq
|
||||
fenS3J6KG2SEn2PNFn+R0R5vBo4DaV/cQysKh44GD2+sh0QDyh6nuWJufyhPzROP
|
||||
DU6DCLbwNePj/yaGuzi36oLt6bBgfPWCiJY7jIdK8DmTLW25m7fRtCC5pxZlSzgl
|
||||
KBf7R6cbaTvaFe05Y2FJXA==
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -0,0 +1,14 @@
|
||||
This directory contains some development keys to be used as the secure world
|
||||
root-of-trust key used in the CCA chain of trust.
|
||||
|
||||
* swd_rotprivk_rsa.pem is a 2K RSA private key in PEM format. It has been
|
||||
generated using the openssl command line tool:
|
||||
|
||||
openssl genrsa 2048 > arm_swd_rotprivk_rsa.pem
|
||||
|
||||
* swd_rotpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key
|
||||
associated with the above private key. It has been generated using the openssl
|
||||
command line tool:
|
||||
|
||||
openssl rsa -in arm_swd_rotprivk_rsa.pem -pubout -outform DER | \
|
||||
openssl dgst -sha256 -binary > arm_swd_rotpk_rsa_sha256.bin
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
.global arm_swd_rotpk_hash
|
||||
.global arm_swd_rotpk_hash_end
|
||||
|
||||
.section .rodata.arm_swd_rotpk_hash, "a"
|
||||
|
||||
arm_swd_rotpk_hash:
|
||||
/* DER header. */
|
||||
.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
|
||||
.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
/* Key hash. */
|
||||
.incbin ARM_SWD_ROTPK_HASH
|
||||
arm_swd_rotpk_hash_end:
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA8igTd5QdZd181kz9vINr7Au34Rr/pQ1jpesfLlc1ZXCNAI9y
|
||||
/rhQlpw00y8rwOfgZsf18gPwGWWGhDJMsXI7OPem7BEUr8xKumuJuCiOdJh1STcR
|
||||
/JoFvz8wJPyycj/DOERRGsz+RvFBs6cLjSZHNQdzKDW+DE5vVJpmNWBVkoK7MCRD
|
||||
Wh/PMZVSoq9PeJOzayYcsipKvifT1+Wo9y2MG5zTDxi28rLr/FBm0CpTepBcRe8L
|
||||
pmgS7XJKhCQYxdDSzxi/0t/qXAwWuME4jv2HbNxsUZjahiBYpA0BafXanSuxVHly
|
||||
qpD0BmKAu7PpgKrEnUcPuHpZ2W+a05lNk6zjewIDAQABAoIBAG3twYCcTYgrtvs1
|
||||
8k38vyZl33CiKAGOhXkRtpL75fKJ2IizljmKBJOKj/R6ynsFCHrANadLIFj3HMyw
|
||||
ZN59A+OFkVJDIsf3jsj3/ooKZzkI6N120YSBizBZiAqSaJOy3HWTldn7y0b7SJ88
|
||||
quLFyLeLDTzowMCnbqTSfqmmdNJQAn+Q+7RX5sZGyBQUF2pRAA67cOYzc3a5MZ5E
|
||||
zBOs2u8VboC3ulEq876XWQbcXpRh/ap3eplQ1kAdyy64IPp2WbxqyXW0IQAQqaqh
|
||||
6oj19ME6mVD5wtELcYscJCDb7pA6WJtPp6nz/og2ifCJE/75T5RJ6fc6eBFMcofQ
|
||||
STIClGECgYEA/ZC0GX1HTKEKK3c1TiS3Zy0DS5ZoN5KFK7Sp1ZAjPE63iAr1a3z9
|
||||
Kepb+L8TBSw50tVD74MF5ChEid/ghF5BrVC3/YJkiiNpM1F51SMLGFeiDPRzJcx5
|
||||
KJkSflX7Q36BAXqj85Yz5AjgTPKcBqQRVZ6pNZN1HY99MloMg22WPRECgYEA9HtU
|
||||
FXmnTplXaNnihdq+vL5Z4/KDM+1f1E95y1PB8vkLI+o1szVNFP+BYz+w42lKtHW+
|
||||
c+z40AhFBGZQ0QCx83NOyObCReFjEbP8Nz71BsHe6GyMk9tSPIpzu9XB49Rs+9EO
|
||||
DAvFM5y2j5bH+lXE0pSyS3oBf51L9ZCPhp/vB8sCgYEAydwB1Gzsbu+hFfs/v2bx
|
||||
brzh67HgY6VMSP/5WF/3/RG5gB8hQ6HsNQsyjrMmZC7SFarb+3e2H+2CqrREm3wi
|
||||
EuS4pKPCgEoyfL03HVtZgNZ61o9gf83pAk3h8Bto/VFfSBsnHEsOIlKCph9Z4NuK
|
||||
RTwa/uDWEmNhyszvO03pldECgYEA2zB7GWnhc1mNgabfLY0JtuSeaPzzXqnyYcID
|
||||
eyUT3QglUcTY8lvWSP4ufdILgEfVP2fVIdAS30iawDAPQuLxqEf4Gayx/r7s+GE6
|
||||
vjlGqxFEDXPMsX9QApFK49voop/AOiCbDHe9DOHy11ei4TDmbrn8BClVkJlxEa/S
|
||||
ziszvfMCgYEA2V0zXziooI0toaOJEWZlAYhEONS5SG2z28HMLNgbdMcueGNhseaR
|
||||
NBGgPcu3EQhbL/hD0tBs09u6gjy1WD1i0HYnm1K1YQ1flzfbjUa3BqZETMbNhugd
|
||||
CM9yv0GEL/udZyOmO401aYl+QGXZX/WwlLQOe7WqQXOXJvW73oSqy7M=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/desc_image_load.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Following descriptor provides BL image/ep information that gets used
|
||||
* by BL2 to load the images and also subset of this information is
|
||||
* passed to next BL image. The image loading sequence is managed by
|
||||
* populating the images in required loading order. The image execution
|
||||
* sequence is managed by populating the `next_handoff_image_id` with
|
||||
* the next executable image id.
|
||||
******************************************************************************/
|
||||
static bl_mem_params_node_t bl2_mem_params_descs[] = {
|
||||
|
||||
/* Fill BL31 related information */
|
||||
{
|
||||
.image_id = BL31_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | EXECUTABLE | EP_FIRST_EXE),
|
||||
.ep_info.pc = BL31_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
.ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL,
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
|
||||
.image_info.image_base = BL31_BASE,
|
||||
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
|
||||
|
||||
.next_handoff_image_id = BL32_IMAGE_ID,
|
||||
},
|
||||
|
||||
/* Fill BL32 related information */
|
||||
{
|
||||
.image_id = BL32_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
|
||||
.ep_info.pc = BL32_BASE,
|
||||
.ep_info.args.arg0 = CORSTONE1000_TOS_FW_CONFIG_BASE,
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
|
||||
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
},
|
||||
|
||||
/* Fill TOS_FW_CONFIG related information */
|
||||
{
|
||||
.image_id = TOS_FW_CONFIG_ID,
|
||||
.image_info.image_base = CORSTONE1000_TOS_FW_CONFIG_BASE,
|
||||
.image_info.image_max_size = (CORSTONE1000_TOS_FW_CONFIG_LIMIT -
|
||||
CORSTONE1000_TOS_FW_CONFIG_BASE),
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
|
||||
VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
|
||||
/* Fill BL33 related information */
|
||||
{
|
||||
.image_id = BL33_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
|
||||
.ep_info.pc = BL33_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = BL33_BASE,
|
||||
.image_info.image_max_size = BL33_LIMIT - BL33_BASE,
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
};
|
||||
|
||||
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*
|
||||
* corstone1000 error handler
|
||||
*/
|
||||
void __dead2 plat_arm_error_handler(int err)
|
||||
{
|
||||
while (1) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_arm_calc_core_pos
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* For AArch32, cold-booting secondary CPUs is not yet
|
||||
* implemented and they panic.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
cb_panic:
|
||||
b cb_panic
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and warm
|
||||
* boot. On corstone1000, this information can be queried from the power
|
||||
* controller. The Power Control SYS Status Register (PSYSR) indicates
|
||||
* the wake-up reason for the CPU.
|
||||
*
|
||||
* For a cold boot, return 0.
|
||||
* For a warm boot, Not yet supported.
|
||||
*
|
||||
* TODO: PSYSR is a common register and should be
|
||||
* accessed using locks. Since it is not possible
|
||||
* to use locks immediately after a cold reset
|
||||
* we are relying on the fact that after a cold
|
||||
* reset all cpus will read the same WK field
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* TODO support warm boot */
|
||||
/* Cold reset */
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current CPU is the primary
|
||||
* CPU.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
mov_imm x1, MPIDR_AFFINITY_MASK
|
||||
and x0, x0, x1
|
||||
cmp x0, #CORSTONE1000_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <plat/arm/common/arm_fconf_getter.h>
|
||||
#include <plat/arm/common/arm_fconf_io_storage.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* Table of regions to map using the MMU.
|
||||
* Replace or extend the below regions as required
|
||||
*/
|
||||
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
ARM_MAP_NS_SHARED_RAM,
|
||||
ARM_MAP_NS_DRAM1,
|
||||
CORSTONE1000_MAP_DEVICE,
|
||||
CORSTONE1000_EXTERNAL_FLASH,
|
||||
{0}
|
||||
};
|
||||
|
||||
static void set_fip_image_source(void)
|
||||
{
|
||||
const struct plat_io_policy *policy;
|
||||
/*
|
||||
* metadata for firmware update is written at 0x0000 offset of the flash.
|
||||
* PLAT_ARM_BOOT_BANK_FLAG contains the boot bank that TF-M is booted.
|
||||
* As per firmware update spec, at a given point of time, only one bank
|
||||
* is active. This means, TF-A should boot from the same bank as TF-M.
|
||||
*/
|
||||
volatile uint32_t *boot_bank_flag = (uint32_t *)(PLAT_ARM_BOOT_BANK_FLAG);
|
||||
|
||||
if (*boot_bank_flag > 1) {
|
||||
VERBOSE("Boot_bank is set higher than possible values");
|
||||
}
|
||||
|
||||
VERBOSE("Boot bank flag = %u.\n\r", *boot_bank_flag);
|
||||
|
||||
policy = FCONF_GET_PROPERTY(arm, io_policies, FIP_IMAGE_ID);
|
||||
|
||||
assert(policy != NULL);
|
||||
assert(policy->image_spec != 0UL);
|
||||
|
||||
io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
|
||||
|
||||
if ((*boot_bank_flag) == 0) {
|
||||
VERBOSE("Booting from bank 0: fip offset = 0x%lx\n\r",
|
||||
PLAT_ARM_FIP_BASE_BANK0);
|
||||
spec->offset = PLAT_ARM_FIP_BASE_BANK0;
|
||||
} else {
|
||||
VERBOSE("Booting from bank 1: fip offset = 0x%lx\n\r",
|
||||
PLAT_ARM_FIP_BASE_BANK1);
|
||||
spec->offset = PLAT_ARM_FIP_BASE_BANK1;
|
||||
}
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
arm_bl2_platform_setup();
|
||||
/*
|
||||
* Identify the start address of the FIP by reading the boot
|
||||
* index flag from the flash.
|
||||
*/
|
||||
set_fip_image_source();
|
||||
}
|
||||
|
||||
/* corstone1000 only has one always-on power domain and there
|
||||
* is no power control present
|
||||
*/
|
||||
void __init plat_arm_pwrc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
/* Returning the Generic Timer Frequency */
|
||||
return SYS_COUNTER_FREQ_IN_TICKS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper function to initialize ARM interconnect driver.
|
||||
*/
|
||||
void plat_arm_interconnect_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to place current master into coherency
|
||||
*/
|
||||
void plat_arm_interconnect_enter_coherency(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to remove current master from coherency
|
||||
*/
|
||||
void plat_arm_interconnect_exit_coherency(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is invoked during Mbed TLS library initialisation to get a heap
|
||||
* The function simply returns the default allocated heap.
|
||||
*/
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
|
||||
{
|
||||
assert(heap_addr != NULL);
|
||||
assert(heap_size != NULL);
|
||||
|
||||
return arm_get_mbedtls_heap(heap_addr, heap_size);
|
||||
}
|
||||
#endif
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <platform_def.h>
|
||||
/*******************************************************************************
|
||||
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
|
||||
* platform layer will take care of registering the handlers with PSCI.
|
||||
******************************************************************************/
|
||||
|
||||
static void __dead2 corstone1000_system_reset(void)
|
||||
{
|
||||
|
||||
uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG;
|
||||
uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG;
|
||||
|
||||
*(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL;
|
||||
*watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
|
||||
while (1) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
|
||||
plat_psci_ops_t plat_arm_psci_pm_ops = {
|
||||
.system_reset = corstone1000_system_reset,
|
||||
.validate_ns_entrypoint = NULL
|
||||
};
|
||||
|
||||
const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
|
||||
{
|
||||
ops = &plat_arm_psci_pm_ops;
|
||||
return ops;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* We assume that all security programming is done by the primary core.
|
||||
*/
|
||||
void plat_arm_security_setup(void)
|
||||
{
|
||||
/*
|
||||
* If the platform had additional peripheral specific security
|
||||
* configurations, those would be configured here.
|
||||
*/
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
static uint32_t plat_generate_random_number(void)
|
||||
{
|
||||
uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
|
||||
uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
|
||||
uint64_t cntpct = read_cntpct_el0();
|
||||
|
||||
/* Generate 32-bit pattern: saving the 2 least significant bytes
|
||||
* in random_lo and random_hi
|
||||
*/
|
||||
uint16_t random_lo = (uint16_t)(
|
||||
(((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct
|
||||
);
|
||||
|
||||
uint16_t random_hi = (uint16_t)(
|
||||
(((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct
|
||||
);
|
||||
|
||||
return (((uint32_t)random_hi) << 16) | random_lo;
|
||||
}
|
||||
|
||||
u_register_t plat_get_stack_protector_canary(void)
|
||||
{
|
||||
return plat_generate_random_number(); /* a 32-bit pattern returned */
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
/* The corstone1000 power domain tree descriptor */
|
||||
static unsigned char corstone1000_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
|
||||
+ 2];
|
||||
/*******************************************************************************
|
||||
* This function dynamically constructs the topology according to
|
||||
* CLUSTER_COUNT and returns it.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The highest level is the system level. The next level is constituted
|
||||
* by clusters and then cores in clusters.
|
||||
*/
|
||||
corstone1000_power_domain_tree_desc[0] = 1;
|
||||
corstone1000_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT;
|
||||
|
||||
for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++)
|
||||
corstone1000_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT;
|
||||
|
||||
return corstone1000_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function implements a part of the critical interface between the PSCI
|
||||
* generic layer and the platform that allows the former to query the platform
|
||||
* to convert an MPIDR to a unique linear index. An error code (-1) is
|
||||
* returned in case the MPIDR is invalid.
|
||||
*****************************************************************************/
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
return plat_arm_calc_core_pos(mpidr);
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*
|
||||
* Return the ROTPK hash in the following ASN.1 structure in DER format:
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* }
|
||||
*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm AlgorithmIdentifier,
|
||||
* digest OCTET STRING
|
||||
* }
|
||||
*
|
||||
* The function returns 0 on success. Any other value is treated as error by the
|
||||
* Trusted Board Boot. The function also reports extra information related
|
||||
* to the ROTPK in the flags parameter: ROTPK_IS_HASH, ROTPK_NOT_DEPLOYED.
|
||||
*
|
||||
* Refer to the TF-A porting-guide document for more details.
|
||||
*/
|
||||
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* STUB overriding the non-volatile counter reading.
|
||||
* NV counters are not implemented at this stage of development.
|
||||
* Return: 0 = success
|
||||
*/
|
||||
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
|
||||
{
|
||||
*nv_ctr = CORSTONE1000_FW_NVCTR_VAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* STUB overriding the non-volatile counter updating.
|
||||
* NV counters are not implemented at this stage of development.
|
||||
* Return: 0 = success
|
||||
*/
|
||||
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
compatible = "arm,ffa-core-manifest-1.0";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
|
||||
/*
|
||||
* BL32 image details needed by SPMC
|
||||
*
|
||||
* Note:
|
||||
* binary_size: size of BL32 + TOS_FW_CONFIG
|
||||
*/
|
||||
|
||||
attribute {
|
||||
spmc_id = <0x8000>;
|
||||
maj_ver = <0x1>;
|
||||
min_ver = <0x1>;
|
||||
exec_state = <0x0>;
|
||||
load_address = <0x0 0x2002000>;
|
||||
entrypoint = <0x0 0x2002000>;
|
||||
binary_size = <0xae000>;
|
||||
};
|
||||
|
||||
};
|
||||
+394
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <plat/arm/board/common/v2m_def.h>
|
||||
#include <plat/arm/common/arm_spm_def.h>
|
||||
#include <plat/arm/common/smccc_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
#include <plat/arm/soc/common/soc_css_def.h>
|
||||
|
||||
#define ARM_ROTPK_HEADER_LEN 19
|
||||
#define ARM_ROTPK_HASH_LEN 32
|
||||
|
||||
/* Special value used to verify platform parameters from BL2 to BL31 */
|
||||
#define ARM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978)
|
||||
|
||||
/* PL011 UART related constants */
|
||||
#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ
|
||||
#undef V2M_IOFPGA_UART0_CLK_IN_HZ
|
||||
#endif
|
||||
|
||||
#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ
|
||||
#undef V2M_IOFPGA_UART1_CLK_IN_HZ
|
||||
#endif
|
||||
|
||||
#define V2M_IOFPGA_UART0_CLK_IN_HZ 50000000
|
||||
#define V2M_IOFPGA_UART1_CLK_IN_HZ 50000000
|
||||
|
||||
/* Core/Cluster/Thread counts for corstone1000 */
|
||||
#define CORSTONE1000_CLUSTER_COUNT U(1)
|
||||
#define CORSTONE1000_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define CORSTONE1000_MAX_PE_PER_CPU U(1)
|
||||
#define CORSTONE1000_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_ARM_CLUSTER_COUNT CORSTONE1000_CLUSTER_COUNT
|
||||
|
||||
#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
|
||||
CORSTONE1000_MAX_CPUS_PER_CLUSTER * \
|
||||
CORSTONE1000_MAX_PE_PER_CPU)
|
||||
|
||||
/* UART related constants */
|
||||
#define PLAT_ARM_BOOT_UART_BASE 0x1a510000
|
||||
#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
|
||||
#define PLAT_ARM_RUN_UART_BASE 0x1a520000
|
||||
#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
|
||||
#define ARM_CONSOLE_BAUDRATE 115200
|
||||
#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
|
||||
#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
|
||||
|
||||
/* Memory related constants */
|
||||
|
||||
/* SRAM (CVM) memory layout
|
||||
*
|
||||
* <ARM_TRUSTED_SRAM_BASE>
|
||||
* partition size: sizeof(meminfo_t) = 16 bytes
|
||||
* content: memory info area used by the next BL
|
||||
*
|
||||
* <ARM_FW_CONFIG_BASE>
|
||||
* partition size: 4080 bytes
|
||||
*
|
||||
* <ARM_BL2_MEM_DESC_BASE>
|
||||
* partition size: 4 KB
|
||||
* content: Area where BL2 copies the images descriptors
|
||||
*
|
||||
* <ARM_BL_RAM_BASE> = <BL32_BASE>
|
||||
* partition size: 688 KB
|
||||
* content: BL32 (optee-os)
|
||||
*
|
||||
* <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x20ae000
|
||||
* partition size: 8 KB
|
||||
* content: BL32 config (TOS_FW_CONFIG)
|
||||
*
|
||||
* <BL31_BASE>
|
||||
* partition size: 140 KB
|
||||
* content: BL31
|
||||
*
|
||||
* <BL2_SIGNATURE_BASE>
|
||||
* partition size: 4 KB
|
||||
* content: MCUBOOT data needed to verify TF-A BL2
|
||||
*
|
||||
* <BL2_BASE>
|
||||
* partition size: 176 KB
|
||||
* content: BL2
|
||||
*
|
||||
* <ARM_NS_SHARED_RAM_BASE> = <ARM_TRUSTED_SRAM_BASE> + 1 MB
|
||||
* partition size: 512 KB
|
||||
* content: BL33 (u-boot)
|
||||
*/
|
||||
|
||||
/* DDR memory */
|
||||
#define ARM_DRAM1_BASE UL(0x80000000)
|
||||
#define ARM_DRAM1_SIZE (SZ_2G) /* 2GB*/
|
||||
#define ARM_DRAM1_END (ARM_DRAM1_BASE + ARM_DRAM1_SIZE - 1)
|
||||
|
||||
/* DRAM1 and DRAM2 are the same for corstone1000 */
|
||||
#define ARM_DRAM2_BASE ARM_DRAM1_BASE
|
||||
#define ARM_DRAM2_SIZE ARM_DRAM1_SIZE
|
||||
#define ARM_DRAM2_END ARM_DRAM1_END
|
||||
|
||||
#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE
|
||||
#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE
|
||||
#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE - 1)
|
||||
|
||||
/* The first 8 KB of Trusted SRAM are used as shared memory */
|
||||
#define ARM_TRUSTED_SRAM_BASE UL(0x02000000)
|
||||
#define ARM_SHARED_RAM_SIZE (SZ_8K) /* 8 KB */
|
||||
#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
|
||||
|
||||
/* The remaining Trusted SRAM is used to load the BL images */
|
||||
#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */
|
||||
|
||||
/* Last 512KB of CVM is allocated for shared RAM as an example openAMP */
|
||||
#define ARM_NS_SHARED_RAM_SIZE (512 * SZ_1K)
|
||||
|
||||
#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \
|
||||
ARM_NS_SHARED_RAM_SIZE - \
|
||||
ARM_SHARED_RAM_SIZE)
|
||||
|
||||
#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */
|
||||
|
||||
#define PLAT_ARM_MAX_BL31_SIZE (140 * SZ_1K) /* 140 KB */
|
||||
|
||||
#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE)
|
||||
#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
|
||||
ARM_SHARED_RAM_SIZE)
|
||||
|
||||
#define BL2_SIGNATURE_SIZE (SZ_4K) /* 4 KB */
|
||||
|
||||
#define BL2_SIGNATURE_BASE (BL2_LIMIT - PLAT_ARM_MAX_BL2_SIZE)
|
||||
#define BL2_BASE (BL2_LIMIT - \
|
||||
PLAT_ARM_MAX_BL2_SIZE + \
|
||||
BL2_SIGNATURE_SIZE)
|
||||
#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
|
||||
|
||||
#define BL31_BASE (BL2_SIGNATURE_BASE - PLAT_ARM_MAX_BL31_SIZE)
|
||||
#define BL31_LIMIT BL2_SIGNATURE_BASE
|
||||
|
||||
#define CORSTONE1000_TOS_FW_CONFIG_BASE (BL31_BASE - \
|
||||
CORSTONE1000_TOS_FW_CONFIG_SIZE)
|
||||
#define CORSTONE1000_TOS_FW_CONFIG_SIZE (SZ_8K) /* 8 KB */
|
||||
#define CORSTONE1000_TOS_FW_CONFIG_LIMIT BL31_BASE
|
||||
|
||||
#define BL32_BASE ARM_BL_RAM_BASE
|
||||
#define PLAT_ARM_MAX_BL32_SIZE (CORSTONE1000_TOS_FW_CONFIG_BASE - BL32_BASE)
|
||||
|
||||
#define BL32_LIMIT (BL32_BASE + PLAT_ARM_MAX_BL32_SIZE)
|
||||
|
||||
/* SPD_spmd settings */
|
||||
|
||||
#define PLAT_ARM_SPMC_BASE BL32_BASE
|
||||
#define PLAT_ARM_SPMC_SIZE PLAT_ARM_MAX_BL32_SIZE
|
||||
|
||||
/* NS memory */
|
||||
|
||||
/* The last 512KB of the SRAM is allocated as shared memory */
|
||||
#define ARM_NS_SHARED_RAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SRAM_SIZE - \
|
||||
(PLAT_ARM_MAX_BL31_SIZE + \
|
||||
PLAT_ARM_MAX_BL32_SIZE))
|
||||
|
||||
#define BL33_BASE ARM_DRAM1_BASE
|
||||
#define PLAT_ARM_MAX_BL33_SIZE (12 * SZ_1M) /* 12 MB*/
|
||||
#define BL33_LIMIT (ARM_DRAM1_BASE + PLAT_ARM_MAX_BL33_SIZE)
|
||||
|
||||
/* end of the definition of SRAM memory layout */
|
||||
|
||||
/* NOR Flash */
|
||||
|
||||
#define PLAT_ARM_BOOT_BANK_FLAG UL(0x08002000)
|
||||
#define PLAT_ARM_FIP_BASE_BANK0 UL(0x081EF000)
|
||||
#define PLAT_ARM_FIP_BASE_BANK1 UL(0x0916F000)
|
||||
#define PLAT_ARM_FIP_MAX_SIZE UL(0x1ff000) /* 1.996 MB */
|
||||
|
||||
#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
|
||||
#define PLAT_ARM_NVM_SIZE (SZ_32M) /* 32 MB */
|
||||
|
||||
#define PLAT_ARM_FLASH_IMAGE_BASE PLAT_ARM_FIP_BASE_BANK0
|
||||
#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE PLAT_ARM_FIP_MAX_SIZE
|
||||
|
||||
/*
|
||||
* Some data must be aligned on the biggest cache line size in the platform.
|
||||
* This is known only to the platform as it might have a combination of
|
||||
* integrated and external caches.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
|
||||
#define ARM_CACHE_WRITEBACK_SHIFT 6
|
||||
|
||||
/*
|
||||
* Define FW_CONFIG area base and limit. Leave enough space for BL2 meminfo.
|
||||
* FW_CONFIG is intended to host the device tree. Currently, This area is not
|
||||
* used because corstone1000 platform doesn't use a device tree at TF-A level.
|
||||
*/
|
||||
#define ARM_FW_CONFIG_BASE (ARM_SHARED_RAM_BASE + sizeof(meminfo_t))
|
||||
#define ARM_FW_CONFIG_LIMIT (ARM_SHARED_RAM_BASE + \
|
||||
(ARM_SHARED_RAM_SIZE >> 1))
|
||||
|
||||
/*
|
||||
* Boot parameters passed from BL2 to BL31/BL32 are stored here
|
||||
*/
|
||||
#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
|
||||
#define ARM_BL2_MEM_DESC_LIMIT ARM_BL_RAM_BASE
|
||||
|
||||
/*
|
||||
* The max number of regions like RO(code), coherent and data required by
|
||||
* different BL stages which need to be mapped in the MMU.
|
||||
*/
|
||||
#define ARM_BL_REGIONS 3
|
||||
#define PLAT_ARM_MMAP_ENTRIES 8
|
||||
#define MAX_XLAT_TABLES 5
|
||||
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS)
|
||||
#define MAX_IO_DEVICES 2
|
||||
#define MAX_IO_HANDLES 3
|
||||
#define MAX_IO_BLOCK_DEVICES 1
|
||||
|
||||
/* GIC related constants */
|
||||
#define PLAT_ARM_GICD_BASE 0x1C010000
|
||||
#define PLAT_ARM_GICC_BASE 0x1C02F000
|
||||
|
||||
/* MHUv2 Secure Channel receiver and sender */
|
||||
#define PLAT_SDK700_MHU0_SEND 0x1B800000
|
||||
#define PLAT_SDK700_MHU0_RECV 0x1B810000
|
||||
|
||||
/* Timer/watchdog related constants */
|
||||
#define ARM_SYS_CNTCTL_BASE UL(0x1a200000)
|
||||
#define ARM_SYS_CNTREAD_BASE UL(0x1a210000)
|
||||
#define ARM_SYS_TIMCTL_BASE UL(0x1a220000)
|
||||
|
||||
#define SECURE_WATCHDOG_ADDR_CTRL_REG 0x1A320000
|
||||
#define SECURE_WATCHDOG_ADDR_VAL_REG 0x1A320008
|
||||
#define SECURE_WATCHDOG_MASK_ENABLE 0x01
|
||||
#define SECURE_WATCHDOG_COUNTDOWN_VAL 0x1000
|
||||
|
||||
#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */
|
||||
|
||||
#define CORSTONE1000_IRQ_TZ_WDOG 32
|
||||
#define CORSTONE1000_IRQ_SEC_SYS_TIMER 34
|
||||
|
||||
#define PLAT_MAX_PWR_LVL 2
|
||||
/*
|
||||
* Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The
|
||||
* power levels have a 1:1 mapping with the MPIDR affinity levels.
|
||||
*/
|
||||
#define ARM_PWR_LVL0 MPIDR_AFFLVL0
|
||||
#define ARM_PWR_LVL1 MPIDR_AFFLVL1
|
||||
#define ARM_PWR_LVL2 MPIDR_AFFLVL2
|
||||
|
||||
/*
|
||||
* Macros for local power states in ARM platforms encoded by State-ID field
|
||||
* within the power-state parameter.
|
||||
*/
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define ARM_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define ARM_LOCAL_STATE_RET U(1)
|
||||
/* Local power state for OFF/power-down. Valid for CPU and cluster
|
||||
* power domains
|
||||
*/
|
||||
#define ARM_LOCAL_STATE_OFF U(2)
|
||||
|
||||
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
|
||||
#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
|
||||
|
||||
#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
/*
|
||||
* This macro defines the deepest retention state possible. A higher state
|
||||
* ID will represent an invalid or a power down state.
|
||||
*/
|
||||
#define PLAT_MAX_RET_STATE 1
|
||||
|
||||
/*
|
||||
* This macro defines the deepest power down states possible. Any state ID
|
||||
* higher than this is invalid.
|
||||
*/
|
||||
#define PLAT_MAX_OFF_STATE 2
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x440)
|
||||
|
||||
#define CORSTONE1000_EXTERNAL_FLASH MAP_REGION_FLAT( \
|
||||
PLAT_ARM_NVM_BASE, \
|
||||
PLAT_ARM_NVM_SIZE, \
|
||||
MT_DEVICE | MT_RO | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
|
||||
ARM_SHARED_RAM_BASE, \
|
||||
ARM_SHARED_RAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \
|
||||
ARM_NS_SHARED_RAM_BASE, \
|
||||
ARM_NS_SHARED_RAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
|
||||
ARM_NS_DRAM1_BASE, \
|
||||
ARM_NS_DRAM1_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
|
||||
BL_CODE_BASE, \
|
||||
(BL_CODE_END - BL_CODE_BASE), \
|
||||
MT_CODE | MT_SECURE), \
|
||||
MAP_REGION_FLAT( \
|
||||
BL_RO_DATA_BASE, \
|
||||
(BL_RO_DATA_END - BL_RO_DATA_BASE), \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
#if USE_COHERENT_MEM
|
||||
#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
|
||||
BL_COHERENT_RAM_BASE, \
|
||||
(BL_COHERENT_RAM_END \
|
||||
- BL_COHERENT_RAM_BASE), \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map the region for the optional device tree configuration with read and
|
||||
* write permissions
|
||||
*/
|
||||
#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \
|
||||
ARM_FW_CONFIG_BASE, \
|
||||
(ARM_FW_CONFIG_LIMIT \
|
||||
- ARM_FW_CONFIG_BASE), \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define CORSTONE1000_DEVICE_BASE (0x1A000000)
|
||||
#define CORSTONE1000_DEVICE_SIZE (0x26000000)
|
||||
#define CORSTONE1000_MAP_DEVICE MAP_REGION_FLAT( \
|
||||
CORSTONE1000_DEVICE_BASE, \
|
||||
CORSTONE1000_DEVICE_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define ARM_IRQ_SEC_SGI_0 8
|
||||
#define ARM_IRQ_SEC_SGI_1 9
|
||||
#define ARM_IRQ_SEC_SGI_2 10
|
||||
#define ARM_IRQ_SEC_SGI_3 11
|
||||
#define ARM_IRQ_SEC_SGI_4 12
|
||||
#define ARM_IRQ_SEC_SGI_5 13
|
||||
#define ARM_IRQ_SEC_SGI_6 14
|
||||
#define ARM_IRQ_SEC_SGI_7 15
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define ARM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define ARM_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||
ARM_G1S_IRQ_PROPS(grp), \
|
||||
INTR_PROP_DESC(CORSTONE1000_IRQ_TZ_WDOG, \
|
||||
GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(CORSTONE1000_IRQ_SEC_SYS_TIMER, \
|
||||
GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
#include <css_macros.S>
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below required platform porting macro
|
||||
* prints out relevant platform registers
|
||||
* whenever an unhandled exception is taken in
|
||||
* BL31.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
css_print_gic_regs
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Making sure the corstone1000 platform type is specified
|
||||
ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
|
||||
$(error TARGET_PLATFORM must be fpga or fvp)
|
||||
endif
|
||||
|
||||
CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S
|
||||
|
||||
PLAT_INCLUDES := -Iplat/arm/board/corstone1000/common/include \
|
||||
-Iplat/arm/board/corstone1000/include \
|
||||
-Iinclude/plat/arm/common \
|
||||
-Iinclude/plat/arm/css/common/aarch64
|
||||
|
||||
|
||||
CORSTONE1000_FW_NVCTR_VAL := 255
|
||||
TFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL}
|
||||
NTFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL}
|
||||
|
||||
override NEED_BL1 := no
|
||||
|
||||
override NEED_BL2 := yes
|
||||
FIP_BL2_ARGS := tb-fw
|
||||
|
||||
override NEED_BL2U := no
|
||||
override NEED_BL31 := yes
|
||||
NEED_BL32 := yes
|
||||
override NEED_BL33 := yes
|
||||
|
||||
# Include GICv2 driver files
|
||||
include drivers/arm/gic/v2/gicv2.mk
|
||||
|
||||
CORSTONE1000_GIC_SOURCES := ${GICV2_SOURCES} \
|
||||
plat/common/plat_gicv2.c \
|
||||
plat/arm/common/arm_gicv2.c
|
||||
|
||||
|
||||
BL2_SOURCES += plat/arm/board/corstone1000/common/corstone1000_security.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_err.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c \
|
||||
lib/utils/mem_region.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_helpers.S \
|
||||
plat/arm/board/corstone1000/common/corstone1000_plat.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c \
|
||||
${CORSTONE1000_CPU_LIBS} \
|
||||
|
||||
|
||||
BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \
|
||||
lib/utils/mem_region.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_helpers.S \
|
||||
plat/arm/board/corstone1000/common/corstone1000_topology.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_security.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_plat.c \
|
||||
plat/arm/board/corstone1000/common/corstone1000_pm.c \
|
||||
${CORSTONE1000_CPU_LIBS} \
|
||||
${CORSTONE1000_GIC_SOURCES}
|
||||
|
||||
ifneq (${ENABLE_STACK_PROTECTOR},0)
|
||||
ifneq (${ENABLE_STACK_PROTECTOR},none)
|
||||
CORSTONE1000_SECURITY_SOURCES := plat/arm/board/corstone1000/common/corstone1000_stack_protector.c
|
||||
BL2_SOURCES += ${CORSTONE1000_SECURITY_SOURCES}
|
||||
BL31_SOURCES += ${CORSTONE1000_SECURITY_SOURCES}
|
||||
endif
|
||||
endif
|
||||
|
||||
FDT_SOURCES += plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts
|
||||
CORSTONE1000_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/corstone1000_spmc_manifest.dtb
|
||||
|
||||
# Add the SPMC manifest to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE1000_TOS_FW_CONFIG},--tos-fw-config,${CORSTONE1000_TOS_FW_CONFIG}))
|
||||
|
||||
# Adding TARGET_PLATFORM as a GCC define (-D option)
|
||||
$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
|
||||
|
||||
# Adding CORSTONE1000_FW_NVCTR_VAL as a GCC define (-D option)
|
||||
$(eval $(call add_define,CORSTONE1000_FW_NVCTR_VAL))
|
||||
|
||||
include plat/arm/common/arm_common.mk
|
||||
include plat/arm/board/common/board_common.mk
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_arm_calc_core_pos
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* For AArch32, cold-booting secondary CPUs is not yet
|
||||
* implemented and they panic.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
cb_panic:
|
||||
b cb_panic
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and warm
|
||||
* boot. On Corstone700, this information can be queried from the power
|
||||
* controller. The Power Control SYS Status Register (PSYSR) indicates
|
||||
* the wake-up reason for the CPU.
|
||||
*
|
||||
* For a cold boot, return 0.
|
||||
* For a warm boot, Not yet supported.
|
||||
*
|
||||
* TODO: PSYSR is a common register and should be
|
||||
* accessed using locks. Since it is not possible
|
||||
* to use locks immediately after a cold reset
|
||||
* we are relying on the fact that after a cold
|
||||
* reset all cpus will read the same WK field
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* TODO support warm boot */
|
||||
/* Cold reset */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current CPU is the primary
|
||||
* CPU.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
ldcopr r0, MPIDR
|
||||
ldr r1, =MPIDR_AFFINITY_MASK
|
||||
and r0, r1
|
||||
cmp r0, #0
|
||||
moveq r0, #1
|
||||
movne r0, #0
|
||||
bx lr
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
|
||||
*
|
||||
* Function to calculate the core position on Corstone700.
|
||||
*
|
||||
* (ClusterId * MAX_CPUS_PER_CLUSTER * MAX_PE_PER_CPU) +
|
||||
* (CPUId * MAX_PE_PER_CPU) +
|
||||
* ThreadId
|
||||
*
|
||||
* which can be simplified as:
|
||||
*
|
||||
* ((ClusterId * MAX_CPUS_PER_CLUSTER + CPUId) * MAX_PE_PER_CPU)
|
||||
* + ThreadId
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_arm_calc_core_pos
|
||||
mov r3, r0
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Compute linear position */
|
||||
mov r3, #CORSTONE700_MAX_CPUS_PER_CLUSTER
|
||||
mla r1, r2, r3, r1
|
||||
mov r3, #CORSTONE700_MAX_PE_PER_CPU
|
||||
mla r0, r1, r3, r0
|
||||
|
||||
bx lr
|
||||
endfunc plat_arm_calc_core_pos
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include <corstone700_mhu.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* Table of regions to map using the MMU.
|
||||
* Replace or extend the below regions as required
|
||||
*/
|
||||
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
ARM_MAP_NS_SHARED_RAM,
|
||||
ARM_MAP_NS_DRAM1,
|
||||
CORSTONE700_MAP_DEVICE,
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Corstone700 only has one always-on power domain and there
|
||||
* is no power control present
|
||||
*/
|
||||
void __init plat_arm_pwrc_setup(void)
|
||||
{
|
||||
mhu_secure_init();
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
/* Returning the Generic Timer Frequency */
|
||||
return SYS_COUNTER_FREQ_IN_TICKS;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
|
||||
* platform layer will take care of registering the handlers with PSCI.
|
||||
******************************************************************************/
|
||||
plat_psci_ops_t plat_arm_psci_pm_ops = {
|
||||
/* dummy struct */
|
||||
.validate_ns_entrypoint = NULL
|
||||
};
|
||||
|
||||
const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
|
||||
{
|
||||
return ops;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* We assume that all security programming is done by the primary core.
|
||||
*/
|
||||
void plat_arm_security_setup(void)
|
||||
{
|
||||
/*
|
||||
* If the platform had additional peripheral specific security
|
||||
* configurations, those would be configured here.
|
||||
*/
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
static uint32_t plat_generate_random_number(void)
|
||||
{
|
||||
uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
|
||||
uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
|
||||
uint64_t cntpct = read_cntpct_el0();
|
||||
|
||||
/* Generate 32-bit pattern: saving the 2 least significant bytes
|
||||
* in random_lo and random_hi
|
||||
*/
|
||||
uint16_t random_lo = (uint16_t)(
|
||||
(((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct
|
||||
);
|
||||
|
||||
uint16_t random_hi = (uint16_t)(
|
||||
(((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct
|
||||
);
|
||||
|
||||
return (((uint32_t)random_hi) << 16) | random_lo;
|
||||
}
|
||||
|
||||
u_register_t plat_get_stack_protector_canary(void)
|
||||
{
|
||||
return plat_generate_random_number(); /* a 32-bit pattern is returned */
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
/* The Corstone700 power domain tree descriptor */
|
||||
static unsigned char corstone700_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
|
||||
+ 2];
|
||||
/*******************************************************************************
|
||||
* This function dynamically constructs the topology according to
|
||||
* CLUSTER_COUNT and returns it.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The highest level is the system level. The next level is constituted
|
||||
* by clusters and then cores in clusters.
|
||||
*/
|
||||
corstone700_power_domain_tree_desc[0] = 1;
|
||||
corstone700_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT;
|
||||
|
||||
for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++)
|
||||
corstone700_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT;
|
||||
|
||||
return corstone700_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function implements a part of the critical interface between the PSCI
|
||||
* generic layer and the platform that allows the former to query the platform
|
||||
* to convert an MPIDR to a unique linear index. An error code (-1) is
|
||||
* returned in case the MPIDR is invalid.
|
||||
*****************************************************************************/
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
return plat_arm_calc_core_pos(mpidr);
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include "corstone700_mhu.h"
|
||||
#include <plat_arm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
ARM_INSTANTIATE_LOCK;
|
||||
|
||||
#pragma weak plat_arm_pwrc_setup
|
||||
|
||||
/*
|
||||
* Slot 31 is reserved because the MHU hardware uses this register bit to
|
||||
* indicate a non-secure access attempt. The total number of available slots is
|
||||
* therefore 31 [30:0].
|
||||
*/
|
||||
#define MHU_MAX_SLOT_ID 30
|
||||
|
||||
void mhu_secure_message_start(uintptr_t address, unsigned int slot_id)
|
||||
{
|
||||
unsigned int intr_stat_check;
|
||||
uint64_t timeout_cnt;
|
||||
volatile uint8_t expiration;
|
||||
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
arm_lock_get();
|
||||
|
||||
/*
|
||||
* Make sure any previous command has finished
|
||||
* and polling timeout not expired
|
||||
*/
|
||||
|
||||
timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
|
||||
|
||||
do {
|
||||
intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) &
|
||||
(1 << slot_id));
|
||||
|
||||
expiration = timeout_elapsed(timeout_cnt);
|
||||
|
||||
} while ((intr_stat_check != 0U) && (expiration == 0U));
|
||||
|
||||
/*
|
||||
* Note: No risk of timer overflows while waiting
|
||||
* for the timeout expiration.
|
||||
* According to Armv8 TRM: System counter roll-over
|
||||
* time of not less than 40 years
|
||||
*/
|
||||
}
|
||||
|
||||
void mhu_secure_message_send(uintptr_t address,
|
||||
unsigned int slot_id,
|
||||
unsigned int message)
|
||||
{
|
||||
unsigned char access_ready;
|
||||
uint64_t timeout_cnt;
|
||||
volatile uint8_t expiration;
|
||||
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
assert((mmio_read_32(address + CPU_INTR_S_STAT) &
|
||||
(1 << slot_id)) == 0U);
|
||||
|
||||
MHU_V2_ACCESS_REQUEST(address);
|
||||
|
||||
timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
|
||||
|
||||
do {
|
||||
access_ready = MHU_V2_IS_ACCESS_READY(address);
|
||||
expiration = timeout_elapsed(timeout_cnt);
|
||||
|
||||
} while ((access_ready == 0U) && (expiration == 0U));
|
||||
|
||||
/*
|
||||
* Note: No risk of timer overflows while waiting
|
||||
* for the timeout expiration.
|
||||
* According to Armv8 TRM: System counter roll-over
|
||||
* time of not less than 40 years
|
||||
*/
|
||||
|
||||
mmio_write_32(address + CPU_INTR_S_SET, message);
|
||||
}
|
||||
|
||||
void mhu_secure_message_end(uintptr_t address, unsigned int slot_id)
|
||||
{
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
/*
|
||||
* Clear any response we got by writing one in the relevant slot bit to
|
||||
* the CLEAR register
|
||||
*/
|
||||
MHU_V2_CLEAR_REQUEST(address);
|
||||
|
||||
arm_lock_release();
|
||||
}
|
||||
|
||||
void __init mhu_secure_init(void)
|
||||
{
|
||||
arm_lock_init();
|
||||
|
||||
/*
|
||||
* The STAT register resets to zero. Ensure it is in the expected state,
|
||||
* as a stale or garbage value would make us think it's a message we've
|
||||
* already sent.
|
||||
*/
|
||||
|
||||
assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0);
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef CORSTONE700_MHU_H
|
||||
#define CORSTONE700_MHU_H
|
||||
|
||||
#define MHU_POLL_INTR_STAT_TIMEOUT 50000 /*timeout value in us*/
|
||||
|
||||
/* CPU MHU secure channel registers */
|
||||
#define CPU_INTR_S_STAT 0x00
|
||||
#define CPU_INTR_S_SET 0x0C
|
||||
|
||||
/* MHUv2 Control Registers Offsets */
|
||||
#define MHU_V2_MSG_CFG_OFFSET 0xF80
|
||||
#define MHU_V2_ACCESS_REQ_OFFSET 0xF88
|
||||
#define MHU_V2_ACCESS_READY_OFFSET 0xF8C
|
||||
|
||||
#define MHU_V2_ACCESS_REQUEST(addr) \
|
||||
mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1)
|
||||
|
||||
#define MHU_V2_CLEAR_REQUEST(addr) \
|
||||
mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0)
|
||||
|
||||
#define MHU_V2_IS_ACCESS_READY(addr) \
|
||||
(mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1)
|
||||
|
||||
void mhu_secure_message_start(uintptr_t address, unsigned int slot_id);
|
||||
void mhu_secure_message_send(uintptr_t address,
|
||||
unsigned int slot_id,
|
||||
unsigned int message);
|
||||
void mhu_secure_message_end(uintptr_t address, unsigned int slot_id);
|
||||
void mhu_secure_init(void);
|
||||
|
||||
#endif /* CORSTONE700_MHU_H */
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <plat/arm/board/common/v2m_def.h>
|
||||
#include <plat/arm/common/arm_spm_def.h>
|
||||
#include <plat/arm/common/smccc_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* PL011 UART related constants */
|
||||
#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ
|
||||
#undef V2M_IOFPGA_UART0_CLK_IN_HZ
|
||||
#endif
|
||||
|
||||
#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ
|
||||
#undef V2M_IOFPGA_UART1_CLK_IN_HZ
|
||||
#endif
|
||||
|
||||
#define V2M_IOFPGA_UART0_CLK_IN_HZ 32000000
|
||||
#define V2M_IOFPGA_UART1_CLK_IN_HZ 32000000
|
||||
|
||||
/* Core/Cluster/Thread counts for Corstone700 */
|
||||
#define CORSTONE700_CLUSTER_COUNT U(1)
|
||||
#define CORSTONE700_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define CORSTONE700_MAX_PE_PER_CPU U(1)
|
||||
|
||||
#define PLAT_ARM_CLUSTER_COUNT CORSTONE700_CLUSTER_COUNT
|
||||
|
||||
#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
|
||||
CORSTONE700_MAX_CPUS_PER_CLUSTER * \
|
||||
CORSTONE700_MAX_PE_PER_CPU)
|
||||
|
||||
|
||||
/* UART related constants */
|
||||
#define PLAT_ARM_BOOT_UART_BASE 0x1a510000
|
||||
#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
|
||||
#define PLAT_ARM_RUN_UART_BASE 0x1a520000
|
||||
#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
|
||||
#define ARM_CONSOLE_BAUDRATE 115200
|
||||
#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
|
||||
#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
|
||||
|
||||
/* Memory related constants */
|
||||
#define ARM_DRAM1_BASE UL(0x80000000)
|
||||
#define ARM_DRAM1_SIZE UL(0x80000000)
|
||||
#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
|
||||
ARM_DRAM1_SIZE - 1)
|
||||
#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE
|
||||
#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE
|
||||
#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \
|
||||
ARM_NS_DRAM1_SIZE - 1)
|
||||
#define ARM_TRUSTED_SRAM_BASE UL(0x02000000)
|
||||
#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
|
||||
#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
|
||||
#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */
|
||||
|
||||
/* The remaining Trusted SRAM is used to load the BL images */
|
||||
#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + \
|
||||
ARM_SHARED_RAM_SIZE)
|
||||
#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
|
||||
ARM_SHARED_RAM_SIZE)
|
||||
|
||||
#define ARM_NS_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + UL(0x00100000)
|
||||
#define ARM_NS_SHARED_RAM_SIZE 0x00300000
|
||||
|
||||
/*
|
||||
* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
|
||||
* the page reserved for fw_configs) to BL32
|
||||
*/
|
||||
#define BL32_BASE (ARM_BL_RAM_BASE + PAGE_SIZE)
|
||||
#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
|
||||
|
||||
/*
|
||||
* Some data must be aligned on the biggest cache line size in the platform.
|
||||
* This is known only to the platform as it might have a combination of
|
||||
* integrated and external caches.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
|
||||
#define ARM_CACHE_WRITEBACK_SHIFT 6
|
||||
|
||||
/*
|
||||
* To enable FW_CONFIG to be loaded by BL1, define the corresponding base
|
||||
* and limit. Leave enough space for BL2 meminfo.
|
||||
*/
|
||||
#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
|
||||
#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
|
||||
|
||||
/*
|
||||
* Boot parameters passed from BL2 to BL31/BL32 are stored here
|
||||
*/
|
||||
#define ARM_BL2_MEM_DESC_BASE (ARM_FW_CONFIG_LIMIT)
|
||||
#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
|
||||
+ (PAGE_SIZE / 2U))
|
||||
|
||||
/*
|
||||
* Define limit of firmware configuration memory:
|
||||
* ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
|
||||
*/
|
||||
#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
|
||||
|
||||
/*
|
||||
* The max number of regions like RO(code), coherent and data required by
|
||||
* different BL stages which need to be mapped in the MMU.
|
||||
*/
|
||||
#define ARM_BL_REGIONS 3
|
||||
#define PLAT_ARM_MMAP_ENTRIES 8
|
||||
#define MAX_XLAT_TABLES 5
|
||||
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
|
||||
ARM_BL_REGIONS)
|
||||
|
||||
/* GIC related constants */
|
||||
#define PLAT_ARM_GICD_BASE 0x1C010000
|
||||
#define PLAT_ARM_GICC_BASE 0x1C02F000
|
||||
|
||||
/* MHUv2 Secure Channel receiver and sender */
|
||||
#define PLAT_SDK700_MHU0_SEND 0x1B800000
|
||||
#define PLAT_SDK700_MHU0_RECV 0x1B810000
|
||||
|
||||
/* Timer/watchdog related constants */
|
||||
#define ARM_SYS_CNTCTL_BASE UL(0x1a200000)
|
||||
#define ARM_SYS_CNTREAD_BASE UL(0x1a210000)
|
||||
#define ARM_SYS_TIMCTL_BASE UL(0x1a220000)
|
||||
|
||||
#ifdef TARGET_PLATFORM_FVP
|
||||
#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */
|
||||
#else
|
||||
#define SYS_COUNTER_FREQ_IN_TICKS UL(32000000) /* 32MHz */
|
||||
#endif
|
||||
|
||||
#define CORSTONE700_IRQ_TZ_WDOG 32
|
||||
#define CORSTONE700_IRQ_SEC_SYS_TIMER 34
|
||||
|
||||
#define PLAT_MAX_PWR_LVL 2
|
||||
/*
|
||||
* Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The
|
||||
* power levels have a 1:1 mapping with the MPIDR affinity levels.
|
||||
*/
|
||||
#define ARM_PWR_LVL0 MPIDR_AFFLVL0
|
||||
#define ARM_PWR_LVL1 MPIDR_AFFLVL1
|
||||
#define ARM_PWR_LVL2 MPIDR_AFFLVL2
|
||||
|
||||
/*
|
||||
* Macros for local power states in ARM platforms encoded by State-ID field
|
||||
* within the power-state parameter.
|
||||
*/
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define ARM_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define ARM_LOCAL_STATE_RET U(1)
|
||||
/* Local power state for OFF/power-down. Valid for CPU and cluster
|
||||
* power domains
|
||||
*/
|
||||
#define ARM_LOCAL_STATE_OFF U(2)
|
||||
|
||||
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
|
||||
#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
|
||||
|
||||
#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
/*
|
||||
* This macro defines the deepest retention state possible. A higher state
|
||||
* ID will represent an invalid or a power down state.
|
||||
*/
|
||||
#define PLAT_MAX_RET_STATE 1
|
||||
|
||||
/*
|
||||
* This macro defines the deepest power down states possible. Any state ID
|
||||
* higher than this is invalid.
|
||||
*/
|
||||
#define PLAT_MAX_OFF_STATE 2
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x440)
|
||||
|
||||
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
|
||||
ARM_SHARED_RAM_BASE, \
|
||||
ARM_SHARED_RAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \
|
||||
ARM_NS_SHARED_RAM_BASE, \
|
||||
ARM_NS_SHARED_RAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
|
||||
ARM_NS_DRAM1_BASE, \
|
||||
ARM_NS_DRAM1_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
|
||||
BL_CODE_BASE, \
|
||||
BL_CODE_END \
|
||||
- BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE), \
|
||||
MAP_REGION_FLAT( \
|
||||
BL_RO_DATA_BASE, \
|
||||
BL_RO_DATA_END \
|
||||
- BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
#if USE_COHERENT_MEM
|
||||
#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
|
||||
BL_COHERENT_RAM_BASE, \
|
||||
BL_COHERENT_RAM_END \
|
||||
- BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map the region for device tree configuration with read and write permissions
|
||||
*/
|
||||
#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
|
||||
(ARM_FW_CONFIGS_LIMIT \
|
||||
- ARM_BL_RAM_BASE), \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define CORSTONE700_DEVICE_BASE (0x1A000000)
|
||||
#define CORSTONE700_DEVICE_SIZE (0x26000000)
|
||||
#define CORSTONE700_MAP_DEVICE MAP_REGION_FLAT( \
|
||||
CORSTONE700_DEVICE_BASE,\
|
||||
CORSTONE700_DEVICE_SIZE,\
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define ARM_IRQ_SEC_SGI_0 8
|
||||
#define ARM_IRQ_SEC_SGI_1 9
|
||||
#define ARM_IRQ_SEC_SGI_2 10
|
||||
#define ARM_IRQ_SEC_SGI_3 11
|
||||
#define ARM_IRQ_SEC_SGI_4 12
|
||||
#define ARM_IRQ_SEC_SGI_5 13
|
||||
#define ARM_IRQ_SEC_SGI_6 14
|
||||
#define ARM_IRQ_SEC_SGI_7 15
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define ARM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define ARM_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||
ARM_G1S_IRQ_PROPS(grp), \
|
||||
INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \
|
||||
(grp), GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER, \
|
||||
GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Making sure the corstone700 platform type is specified
|
||||
ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
|
||||
$(error TARGET_PLATFORM must be fpga or fvp)
|
||||
endif
|
||||
|
||||
CORSTONE700_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S
|
||||
|
||||
BL32_SOURCES += plat/arm/common/aarch32/arm_helpers.S \
|
||||
plat/arm/common/arm_console.c \
|
||||
plat/arm/common/arm_common.c \
|
||||
lib/xlat_tables/aarch32/xlat_tables.c \
|
||||
lib/xlat_tables/xlat_tables_common.c \
|
||||
${CORSTONE700_CPU_LIBS} \
|
||||
plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c
|
||||
|
||||
PLAT_INCLUDES := -Iplat/arm/board/corstone700/common/include \
|
||||
-Iinclude/plat/arm/common \
|
||||
-Iplat/arm/board/corstone700/common/drivers/mhu
|
||||
|
||||
NEED_BL32 := yes
|
||||
|
||||
# Include GICv2 driver files
|
||||
include drivers/arm/gic/v2/gicv2.mk
|
||||
|
||||
CORSTONE700_GIC_SOURCES := ${GICV2_SOURCES} \
|
||||
plat/common/plat_gicv2.c \
|
||||
plat/arm/common/arm_gicv2.c
|
||||
|
||||
# BL1/BL2 Image not a part of the capsule Image for Corstone700
|
||||
override NEED_BL1 := no
|
||||
override NEED_BL2 := no
|
||||
override NEED_BL2U := no
|
||||
override NEED_BL33 := yes
|
||||
|
||||
#TFA for Corstone700 starts from BL32
|
||||
override RESET_TO_SP_MIN := 1
|
||||
|
||||
#Device tree
|
||||
CORSTONE700_HW_CONFIG_DTS := fdts/corstone700_${TARGET_PLATFORM}.dts
|
||||
CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb
|
||||
FDT_SOURCES += ${CORSTONE700_HW_CONFIG_DTS}
|
||||
$(eval CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS)))
|
||||
|
||||
# Add the HW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE700_HW_CONFIG},--hw-config,${CORSTONE700_HW_CONFIG}))
|
||||
|
||||
# Check for Linux kernel as a BL33 image by default
|
||||
$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
|
||||
ifndef ARM_PRELOADED_DTB_BASE
|
||||
$(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
|
||||
endif
|
||||
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
|
||||
|
||||
# Adding TARGET_PLATFORM as a GCC define (-D option)
|
||||
$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
|
||||
|
||||
include plat/arm/board/common/board_common.mk
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# SP_MIN source files specific to FVP platform
|
||||
BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \
|
||||
lib/utils/mem_region.c \
|
||||
plat/arm/board/corstone700/common/corstone700_helpers.S \
|
||||
plat/arm/board/corstone700/common/corstone700_topology.c \
|
||||
plat/arm/board/corstone700/common/corstone700_security.c \
|
||||
plat/arm/board/corstone700/common/corstone700_plat.c \
|
||||
plat/arm/board/corstone700/common/corstone700_pm.c \
|
||||
plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c \
|
||||
${CORSTONE700_GIC_SOURCES}
|
||||
|
||||
ifneq (${ENABLE_STACK_PROTECTOR},0)
|
||||
ifneq (${ENABLE_STACK_PROTECTOR},none)
|
||||
BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c
|
||||
endif
|
||||
endif
|
||||
|
||||
include plat/arm/common/sp_min/arm_sp_min.mk
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <drivers/arm/fvp/fvp_pwrc.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_arm_calc_core_pos
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* For AArch32, cold-booting secondary CPUs is not yet
|
||||
* implemented and they panic.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
cb_panic:
|
||||
b cb_panic
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and warm
|
||||
* boot. On FVP, this information can be queried from the power
|
||||
* controller. The Power Control SYS Status Register (PSYSR) indicates
|
||||
* the wake-up reason for the CPU.
|
||||
*
|
||||
* For a cold boot, return 0.
|
||||
* For a warm boot, read the mailbox and return the address it contains.
|
||||
*
|
||||
* TODO: PSYSR is a common register and should be
|
||||
* accessed using locks. Since it is not possible
|
||||
* to use locks immediately after a cold reset
|
||||
* we are relying on the fact that after a cold
|
||||
* reset all cpus will read the same WK field
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* ---------------------------------------------------------------------
|
||||
* When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
|
||||
* WakeRequest signal" then it is a warm boot.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldcopr r2, MPIDR
|
||||
ldr r1, =PWRC_BASE
|
||||
str r2, [r1, #PSYSR_OFF]
|
||||
ldr r2, [r1, #PSYSR_OFF]
|
||||
ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
|
||||
cmp r2, #WKUP_PPONR
|
||||
beq warm_reset
|
||||
cmp r2, #WKUP_GICREQ
|
||||
beq warm_reset
|
||||
|
||||
/* Cold reset */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
warm_reset:
|
||||
/* ---------------------------------------------------------------------
|
||||
* A mailbox is maintained in the trusted SRAM. It is flushed out of the
|
||||
* caches after every update using normal memory so it is safe to read
|
||||
* it here with SO attributes.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE
|
||||
ldr r0, [r0]
|
||||
cmp r0, #0
|
||||
beq _panic
|
||||
bx lr
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* The power controller indicates this is a warm reset but the mailbox
|
||||
* is empty. This should never happen!
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
_panic:
|
||||
b _panic
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
ldcopr r0, MPIDR
|
||||
ldr r1, =MPIDR_AFFINITY_MASK
|
||||
and r0, r1
|
||||
cmp r0, #FVP_PRIMARY_CPU
|
||||
moveq r0, #1
|
||||
movne r0, #0
|
||||
bx lr
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
|
||||
*
|
||||
* Function to calculate the core position on FVP.
|
||||
*
|
||||
* (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
|
||||
* (CPUId * FVP_MAX_PE_PER_CPU) +
|
||||
* ThreadId
|
||||
*
|
||||
* which can be simplified as:
|
||||
*
|
||||
* ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
|
||||
* + ThreadId
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_arm_calc_core_pos
|
||||
mov r3, r0
|
||||
|
||||
/*
|
||||
* Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
|
||||
* look as if in a multi-threaded implementation
|
||||
*/
|
||||
tst r0, #MPIDR_MT_MASK
|
||||
lsleq r3, r0, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Compute linear position */
|
||||
mov r3, #FVP_MAX_CPUS_PER_CLUSTER
|
||||
mla r1, r2, r3, r1
|
||||
mov r3, #FVP_MAX_PE_PER_CPU
|
||||
mla r0, r1, r3, r0
|
||||
|
||||
bx lr
|
||||
endfunc plat_arm_calc_core_pos
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <drivers/arm/fvp/fvp_pwrc.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_arm_calc_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset e.g
|
||||
* mark the cpu's presence, mechanism to place it in a
|
||||
* holding pen etc.
|
||||
* TODO: Should we read the PSYS register to make sure
|
||||
* that the request has gone through.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
#ifndef EL3_PAYLOAD_BASE
|
||||
/* ---------------------------------------------
|
||||
* Power down this cpu.
|
||||
* TODO: Do we need to worry about powering the
|
||||
* cluster down as well here. That will need
|
||||
* locks which we won't have unless an elf-
|
||||
* loader zeroes out the zi section.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
mrs x0, mpidr_el1
|
||||
mov_imm x1, PWRC_BASE
|
||||
str w0, [x1, #PPOFFR_OFF]
|
||||
|
||||
/* ---------------------------------------------
|
||||
* There is no sane reason to come out of this
|
||||
* wfi so panic if we do. This cpu will be pow-
|
||||
* ered on and reset by the cpu_on pm api
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
dsb sy
|
||||
wfi
|
||||
no_ret plat_panic_handler
|
||||
#else
|
||||
mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
|
||||
|
||||
/* Wait until the entrypoint gets populated */
|
||||
poll_mailbox:
|
||||
ldr x1, [x0]
|
||||
cbz x1, 1f
|
||||
br x1
|
||||
1:
|
||||
wfe
|
||||
b poll_mailbox
|
||||
#endif /* EL3_PAYLOAD_BASE */
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* uintptr_t plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and warm
|
||||
* boot. On FVP, this information can be queried from the power
|
||||
* controller. The Power Control SYS Status Register (PSYSR) indicates
|
||||
* the wake-up reason for the CPU.
|
||||
*
|
||||
* For a cold boot, return 0.
|
||||
* For a warm boot, read the mailbox and return the address it contains.
|
||||
*
|
||||
* TODO: PSYSR is a common register and should be
|
||||
* accessed using locks. Since it is not possible
|
||||
* to use locks immediately after a cold reset
|
||||
* we are relying on the fact that after a cold
|
||||
* reset all cpus will read the same WK field
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* ---------------------------------------------------------------------
|
||||
* When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
|
||||
* WakeRequest signal" then it is a warm boot.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mrs x2, mpidr_el1
|
||||
mov_imm x1, PWRC_BASE
|
||||
str w2, [x1, #PSYSR_OFF]
|
||||
ldr w2, [x1, #PSYSR_OFF]
|
||||
ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
|
||||
cmp w2, #WKUP_PPONR
|
||||
beq warm_reset
|
||||
cmp w2, #WKUP_GICREQ
|
||||
beq warm_reset
|
||||
|
||||
/* Cold reset */
|
||||
mov x0, #0
|
||||
ret
|
||||
|
||||
warm_reset:
|
||||
/* ---------------------------------------------------------------------
|
||||
* A mailbox is maintained in the trusted SRAM. It is flushed out of the
|
||||
* caches after every update using normal memory so it is safe to read
|
||||
* it here with SO attributes.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
|
||||
ldr x0, [x0]
|
||||
cbz x0, _panic_handler
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* The power controller indicates this is a warm reset but the mailbox
|
||||
* is empty. This should never happen!
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
_panic_handler:
|
||||
no_ret plat_panic_handler
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
mov_imm x1, MPIDR_AFFINITY_MASK
|
||||
and x0, x0, x1
|
||||
cmp x0, #FVP_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
|
||||
*
|
||||
* Function to calculate the core position on FVP.
|
||||
*
|
||||
* (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
|
||||
* (CPUId * FVP_MAX_PE_PER_CPU) +
|
||||
* ThreadId
|
||||
*
|
||||
* which can be simplified as:
|
||||
*
|
||||
* ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
|
||||
* + ThreadId
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_arm_calc_core_pos
|
||||
/*
|
||||
* Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
|
||||
* look as if in a multi-threaded implementation.
|
||||
*/
|
||||
tst x0, #MPIDR_MT_MASK
|
||||
lsl x3, x0, #MPIDR_AFFINITY_BITS
|
||||
csel x3, x3, x0, eq
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Compute linear position */
|
||||
mov x4, #FVP_MAX_CPUS_PER_CLUSTER
|
||||
madd x1, x2, x4, x1
|
||||
mov x5, #FVP_MAX_PE_PER_CPU
|
||||
madd x0, x1, x5, x0
|
||||
ret
|
||||
endfunc plat_arm_calc_core_pos
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/extensions/ras.h>
|
||||
|
||||
struct ras_interrupt fvp_ras_interrupts[] = {
|
||||
};
|
||||
|
||||
struct err_record_info fvp_err_records[] = {
|
||||
};
|
||||
|
||||
REGISTER_ERR_RECORD_INFO(fvp_err_records);
|
||||
REGISTER_RAS_INTERRUPTS(fvp_ras_interrupts);
|
||||
+299
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <fconf_hw_config_getter.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
struct gicv3_config_t gicv3_config;
|
||||
struct hw_topology_t soc_topology;
|
||||
struct uart_serial_config_t uart_serial_config;
|
||||
struct cpu_timer_t cpu_timer;
|
||||
|
||||
#define ILLEGAL_ADDR ULL(~0)
|
||||
|
||||
int fconf_populate_gicv3_config(uintptr_t config)
|
||||
{
|
||||
int err;
|
||||
int node;
|
||||
uintptr_t addr;
|
||||
|
||||
/* Necessary to work with libfdt APIs */
|
||||
const void *hw_config_dtb = (const void *)config;
|
||||
|
||||
/*
|
||||
* Find the offset of the node containing "arm,gic-v3" compatible property.
|
||||
* Populating fconf strucutures dynamically is not supported for legacy
|
||||
* systems which use GICv2 IP. Simply skip extracting GIC properties.
|
||||
*/
|
||||
node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
|
||||
if (node < 0) {
|
||||
WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n");
|
||||
return 0;
|
||||
}
|
||||
/* The GICv3 DT binding holds at least two address/size pairs,
|
||||
* the first describing the distributor, the second the redistributors.
|
||||
* See: bindings/interrupt-controller/arm,gic-v3.yaml
|
||||
*/
|
||||
err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Failed to read GICD reg property of GIC node\n");
|
||||
return err;
|
||||
}
|
||||
gicv3_config.gicd_base = addr;
|
||||
|
||||
err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Failed to read GICR reg property of GIC node\n");
|
||||
} else {
|
||||
gicv3_config.gicr_base = addr;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int fconf_populate_topology(uintptr_t config)
|
||||
{
|
||||
int err, node, cluster_node, core_node, thread_node;
|
||||
uint32_t cluster_count = 0, max_cpu_per_cluster = 0, total_cpu_count = 0;
|
||||
uint32_t max_pwr_lvl = 0;
|
||||
|
||||
/* Necessary to work with libfdt APIs */
|
||||
const void *hw_config_dtb = (const void *)config;
|
||||
|
||||
/* Find the offset of the node containing "arm,psci-1.0" compatible property */
|
||||
node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,psci-1.0");
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Unable to locate node with arm,psci-1.0 compatible property\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
err = fdt_read_uint32(hw_config_dtb, node, "max-pwr-lvl", &max_pwr_lvl);
|
||||
if (err < 0) {
|
||||
/*
|
||||
* Some legacy FVP dts may not have this property. Assign the default
|
||||
* value.
|
||||
*/
|
||||
WARN("FCONF: Could not locate max-pwr-lvl property\n");
|
||||
max_pwr_lvl = 2;
|
||||
}
|
||||
|
||||
assert(max_pwr_lvl <= MPIDR_AFFLVL2);
|
||||
|
||||
/* Find the offset of the "cpus" node */
|
||||
node = fdt_path_offset(hw_config_dtb, "/cpus");
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpus");
|
||||
return node;
|
||||
}
|
||||
|
||||
/* A typical cpu-map node in a device tree is shown here for reference
|
||||
cpu-map {
|
||||
cluster0 {
|
||||
core0 {
|
||||
cpu = <&CPU0>;
|
||||
};
|
||||
core1 {
|
||||
cpu = <&CPU1>;
|
||||
};
|
||||
};
|
||||
|
||||
cluster1 {
|
||||
core0 {
|
||||
cpu = <&CPU2>;
|
||||
};
|
||||
core1 {
|
||||
cpu = <&CPU3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
/* Locate the cpu-map child node */
|
||||
node = fdt_subnode_offset(hw_config_dtb, node, "cpu-map");
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpu-map");
|
||||
return node;
|
||||
}
|
||||
|
||||
uint32_t cpus_per_cluster[PLAT_ARM_CLUSTER_COUNT] = {0};
|
||||
|
||||
/* Iterate through cluster nodes */
|
||||
fdt_for_each_subnode(cluster_node, hw_config_dtb, node) {
|
||||
assert(cluster_count < PLAT_ARM_CLUSTER_COUNT);
|
||||
|
||||
/* Iterate through core nodes */
|
||||
fdt_for_each_subnode(core_node, hw_config_dtb, cluster_node) {
|
||||
/* core nodes may have child nodes i.e., "thread" nodes */
|
||||
if (fdt_first_subnode(hw_config_dtb, core_node) < 0) {
|
||||
cpus_per_cluster[cluster_count]++;
|
||||
} else {
|
||||
/* Multi-threaded CPU description is found in dtb */
|
||||
fdt_for_each_subnode(thread_node, hw_config_dtb, core_node) {
|
||||
cpus_per_cluster[cluster_count]++;
|
||||
}
|
||||
|
||||
/* Since in some dtbs, core nodes may not have thread node,
|
||||
* no need to error if even one child node is not found.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure every cluster node has at least 1 child node */
|
||||
if (cpus_per_cluster[cluster_count] < 1U) {
|
||||
ERROR("FCONF: Unable to locate the core node in cluster %d\n", cluster_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
VERBOSE("CLUSTER ID: %d cpu-count: %d\n", cluster_count,
|
||||
cpus_per_cluster[cluster_count]);
|
||||
|
||||
/* Find the maximum number of cpus in any cluster */
|
||||
max_cpu_per_cluster = MAX(max_cpu_per_cluster, cpus_per_cluster[cluster_count]);
|
||||
total_cpu_count += cpus_per_cluster[cluster_count];
|
||||
cluster_count++;
|
||||
}
|
||||
|
||||
|
||||
/* At least one cluster node is expected in hardware configuration dtb */
|
||||
if (cluster_count < 1U) {
|
||||
ERROR("FCONF: Unable to locate the cluster node in cpu-map node\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
soc_topology.plat_max_pwr_level = max_pwr_lvl;
|
||||
soc_topology.plat_cluster_count = cluster_count;
|
||||
soc_topology.cluster_cpu_count = max_cpu_per_cluster;
|
||||
soc_topology.plat_cpu_count = total_cpu_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fconf_populate_uart_config(uintptr_t config)
|
||||
{
|
||||
int uart_node, node, err;
|
||||
uintptr_t addr;
|
||||
const char *path;
|
||||
uint32_t phandle;
|
||||
uint64_t translated_addr;
|
||||
|
||||
/* Necessary to work with libfdt APIs */
|
||||
const void *hw_config_dtb = (const void *)config;
|
||||
|
||||
/*
|
||||
* uart child node is indirectly referenced through its path which is
|
||||
* specified in the `serial1` property of the "aliases" node.
|
||||
* Note that TF-A boot console is mapped to serial0 while runtime
|
||||
* console is mapped to serial1.
|
||||
*/
|
||||
|
||||
path = fdt_get_alias(hw_config_dtb, "serial1");
|
||||
if (path == NULL) {
|
||||
ERROR("FCONF: Could not read serial1 property in aliases node\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find the offset of the uart serial node */
|
||||
uart_node = fdt_path_offset(hw_config_dtb, path);
|
||||
if (uart_node < 0) {
|
||||
ERROR("FCONF: Failed to locate uart serial node using its path\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* uart serial node has its offset and size of address in reg property */
|
||||
err = fdt_get_reg_props_by_index(hw_config_dtb, uart_node, 0, &addr,
|
||||
NULL);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Failed to read reg property of '%s' node\n",
|
||||
"uart serial");
|
||||
return err;
|
||||
}
|
||||
VERBOSE("FCONF: UART node address: %lx\n", addr);
|
||||
|
||||
/*
|
||||
* Perform address translation of local device address to CPU address
|
||||
* domain.
|
||||
*/
|
||||
translated_addr = fdtw_translate_address(hw_config_dtb,
|
||||
uart_node, (uint64_t)addr);
|
||||
if (translated_addr == ILLEGAL_ADDR) {
|
||||
ERROR("FCONF: failed to translate UART node base address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uart_serial_config.uart_base = translated_addr;
|
||||
|
||||
VERBOSE("FCONF: UART serial device base address: %" PRIx64 "\n",
|
||||
uart_serial_config.uart_base);
|
||||
|
||||
/*
|
||||
* The phandle of the DT node which captures the clock info of uart
|
||||
* serial node is specified in the "clocks" property.
|
||||
*/
|
||||
err = fdt_read_uint32(hw_config_dtb, uart_node, "clocks", &phandle);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Could not read clocks property in uart serial node\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_phandle(hw_config_dtb, phandle);
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Failed to locate clk node using its path\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve clock frequency. We assume clock provider generates a fixed
|
||||
* clock.
|
||||
*/
|
||||
err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency",
|
||||
&uart_serial_config.uart_clk);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Could not read clock-frequency property in clk node\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
VERBOSE("FCONF: UART serial device clk frequency: %x\n",
|
||||
uart_serial_config.uart_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fconf_populate_cpu_timer(uintptr_t config)
|
||||
{
|
||||
int err, node;
|
||||
|
||||
/* Necessary to work with libfdt APIs */
|
||||
const void *hw_config_dtb = (const void *)config;
|
||||
|
||||
/* Find the node offset point to "arm,armv8-timer" compatible property,
|
||||
* a per-core architected timer attached to a GIC to deliver its per-processor
|
||||
* interrupts via PPIs */
|
||||
node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,armv8-timer");
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Unrecognized hardware configuration dtb (%d)\n", node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Locate the cell holding the clock-frequency, an optional field */
|
||||
err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", &cpu_timer.clock_freq);
|
||||
if (err < 0) {
|
||||
WARN("FCONF failed to read clock-frequency property\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <fconf_nt_config_getter.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
struct event_log_config_t event_log_config;
|
||||
|
||||
int fconf_populate_event_log_config(uintptr_t config)
|
||||
{
|
||||
int err;
|
||||
int node;
|
||||
|
||||
/* Necessary to work with libfdt APIs */
|
||||
const void *dtb = (const void *)config;
|
||||
|
||||
/*
|
||||
* Find the offset of the node containing "arm,tpm_event_log"
|
||||
* compatible property
|
||||
*/
|
||||
const char *compatible_str = "arm,tpm_event_log";
|
||||
|
||||
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Can't find '%s' compatible in dtb\n",
|
||||
compatible_str);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Retrieve Event Log details from the DTB */
|
||||
#ifdef SPD_opteed
|
||||
err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2,
|
||||
&event_log_config.tpm_event_log_sm_addr);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n");
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
err = fdtw_read_cells(dtb, node,
|
||||
"tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = fdtw_read_cells(dtb, node,
|
||||
"tpm_event_log_size", 1, &event_log_config.tpm_event_log_size);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config,
|
||||
fconf_populate_event_log_config);
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* TPM Event Log Config */
|
||||
event_log: tpm_event_log {
|
||||
compatible = "arm,tpm_event_log";
|
||||
tpm_event_log_addr = <0x0 0x0>;
|
||||
tpm_event_log_size = <0x0>;
|
||||
};
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
dtb-registry {
|
||||
compatible = "fconf,dyn_cfg-dtb_registry";
|
||||
|
||||
tb_fw-config {
|
||||
load-address = <0x0 0x4001300>;
|
||||
max-size = <0x1800>;
|
||||
id = <TB_FW_CONFIG_ID>;
|
||||
};
|
||||
|
||||
hw-config {
|
||||
load-address = <0x0 0x07f00000>;
|
||||
max-size = <0x00100000>;
|
||||
id = <HW_CONFIG_ID>;
|
||||
ns-load-address = <0x0 0x82000000>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Load SoC and TOS firmware configs at the base of
|
||||
* non shared SRAM. The runtime checks ensure we don't
|
||||
* overlap BL2, BL31 or BL32. The NT firmware config
|
||||
* is loaded at base of DRAM.
|
||||
*/
|
||||
soc_fw-config {
|
||||
load-address = <0x0 0x04001300>;
|
||||
max-size = <0x200>;
|
||||
id = <SOC_FW_CONFIG_ID>;
|
||||
};
|
||||
|
||||
/* If required, SPD should enable loading of trusted OS fw config */
|
||||
#if defined(SPD_tspd) || defined(SPD_spmd)
|
||||
tos_fw-config {
|
||||
load-address = <0x0 0x04001500>;
|
||||
max-size = <0xB00>;
|
||||
id = <TOS_FW_CONFIG_ID>;
|
||||
};
|
||||
#endif
|
||||
|
||||
nt_fw-config {
|
||||
load-address = <0x0 0x80000000>;
|
||||
max-size = <0x200>;
|
||||
id = <NT_FW_CONFIG_ID>;
|
||||
};
|
||||
};
|
||||
};
|
||||
+19
@@ -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
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
|
||||
};
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
#define AFF 00
|
||||
|
||||
#include "fvp-defs.dtsi"
|
||||
#undef POST
|
||||
#define POST \
|
||||
};
|
||||
|
||||
/ {
|
||||
compatible = "arm,ffa-core-manifest-1.0";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
|
||||
attribute {
|
||||
spmc_id = <0x8000>;
|
||||
maj_ver = <0x1>;
|
||||
min_ver = <0x1>;
|
||||
exec_state = <0x0>;
|
||||
load_address = <0x0 0x6000000>;
|
||||
entrypoint = <0x0 0x6000000>;
|
||||
binary_size = <0x80000>;
|
||||
};
|
||||
|
||||
hypervisor {
|
||||
compatible = "hafnium,hafnium";
|
||||
vm1 {
|
||||
is_ffa_partition;
|
||||
debug_name = "cactus-primary";
|
||||
load_address = <0x7000000>;
|
||||
vcpu_count = <8>;
|
||||
mem_size = <1048576>;
|
||||
};
|
||||
vm2 {
|
||||
is_ffa_partition;
|
||||
debug_name = "cactus-secondary";
|
||||
load_address = <0x7100000>;
|
||||
vcpu_count = <8>;
|
||||
mem_size = <1048576>;
|
||||
};
|
||||
vm3 {
|
||||
is_ffa_partition;
|
||||
debug_name = "cactus-tertiary";
|
||||
load_address = <0x7200000>;
|
||||
vcpu_count = <1>;
|
||||
mem_size = <1048576>;
|
||||
};
|
||||
vm4 {
|
||||
is_ffa_partition;
|
||||
debug_name = "ivy";
|
||||
load_address = <0x7600000>;
|
||||
vcpu_count = <1>;
|
||||
mem_size = <1048576>;
|
||||
};
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x0>;
|
||||
|
||||
CPU_0
|
||||
|
||||
/*
|
||||
* SPMC (Hafnium) requires secondary core nodes are declared
|
||||
* in descending order.
|
||||
*/
|
||||
CPU_7
|
||||
CPU_6
|
||||
CPU_5
|
||||
CPU_4
|
||||
CPU_3
|
||||
CPU_2
|
||||
CPU_1
|
||||
};
|
||||
|
||||
memory@6000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
|
||||
};
|
||||
|
||||
#if MEASURED_BOOT
|
||||
#include "event_log.dtsi"
|
||||
#endif
|
||||
};
|
||||
+64
@@ -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 */
|
||||
};
|
||||
};
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/libc/cdefs.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
tb_fw-config {
|
||||
compatible = "arm,tb_fw";
|
||||
|
||||
/* Disable authentication for development */
|
||||
disable_auth = <0x0>;
|
||||
|
||||
/*
|
||||
* The following two entries are placeholders for Mbed TLS
|
||||
* heap information. The default values don't matter since
|
||||
* they will be overwritten by BL1.
|
||||
* In case of having shared Mbed TLS heap between BL1 and BL2,
|
||||
* BL1 will populate these two properties with the respective
|
||||
* info about the shared heap. This info will be available for
|
||||
* BL2 in order to locate and re-use the heap.
|
||||
*/
|
||||
mbedtls_heap_addr = <0x0 0x0>;
|
||||
mbedtls_heap_size = <0x0>;
|
||||
};
|
||||
|
||||
/*
|
||||
* UUID's here are UUID RFC 4122 compliant meaning fieds are stored in
|
||||
* network order (big endian)
|
||||
*/
|
||||
|
||||
#if ARM_IO_IN_DTB
|
||||
arm-io_policies {
|
||||
fip-handles {
|
||||
compatible = "arm,io-fip-handle";
|
||||
scp_bl2_uuid = "9766fd3d-89be-e849-ae5d-78a140608213";
|
||||
bl31_uuid = "47d4086d-4cfe-9846-9b95-2950cbbd5a00";
|
||||
bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38";
|
||||
bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288";
|
||||
bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9";
|
||||
bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
|
||||
hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
|
||||
soc_fw_cfg_uuid = "9979814b-0376-fb46-8c8e-8d267f7859e0";
|
||||
tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
|
||||
nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
|
||||
cca_cert_uuid = "36d83d85-761d-4daf-96f1-cd99d6569b00";
|
||||
core_swd_cert_uuid = "52222d31-820f-494d-8bbc-ea6825d3c35a";
|
||||
plat_cert_uuid = "d43cd902-5b9f-412e-8ac6-92b6d18be60d";
|
||||
t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c";
|
||||
scp_fw_key_uuid = "024221a1-f860-e411-8d9b-f33c0e15a014";
|
||||
soc_fw_key_uuid = "8ab8becc-f960-e411-9ad0-eb4822d8dcf8";
|
||||
tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04";
|
||||
nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859";
|
||||
scp_fw_content_cert_uuid = "44be6f04-5e63-e411-b28b-73d8eaae9656";
|
||||
soc_fw_content_cert_uuid = "e2b20c20-5e63-e411-9ce8-abccf92bb666";
|
||||
tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d";
|
||||
nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7";
|
||||
sp_content_cert_uuid = "776dfd44-8697-4c3b-91eb-c13e025a2a6f";
|
||||
};
|
||||
};
|
||||
#endif /* ARM_IO_IN_DTB */
|
||||
|
||||
secure-partitions {
|
||||
compatible = "arm,sp";
|
||||
|
||||
#ifdef ARM_BL2_SP_LIST_DTS
|
||||
#include __XSTRING(ARM_BL2_SP_LIST_DTS)
|
||||
#else
|
||||
#ifdef OPTEE_SP_FW_CONFIG
|
||||
op-tee {
|
||||
uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
|
||||
load-address = <0x6280000>;
|
||||
};
|
||||
#else
|
||||
cactus-primary {
|
||||
uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb";
|
||||
load-address = <0x7000000>;
|
||||
owner = "SiP";
|
||||
};
|
||||
|
||||
cactus-secondary {
|
||||
uuid = "d1582309-f023-47b9-827c-4464f5578fc8";
|
||||
load-address = <0x7100000>;
|
||||
owner = "Plat";
|
||||
};
|
||||
|
||||
cactus-tertiary {
|
||||
uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2";
|
||||
load-address = <0x7200000>;
|
||||
owner = "Plat";
|
||||
};
|
||||
|
||||
ivy {
|
||||
uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7";
|
||||
load-address = <0x7600000>;
|
||||
owner = "Plat";
|
||||
};
|
||||
#endif
|
||||
#endif /* ARM_BL2_SP_LIST_DTS */
|
||||
};
|
||||
|
||||
#if COT_DESC_IN_DTB
|
||||
#include "cot_descriptors.dtsi"
|
||||
#endif
|
||||
|
||||
#if MEASURED_BOOT
|
||||
#include "event_log.dtsi"
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#if COT_DESC_IN_DTB
|
||||
|
||||
#include "../fvp_def.h"
|
||||
|
||||
&trusted_nv_counter {
|
||||
reg = <TFW_NVCTR_BASE>;
|
||||
};
|
||||
|
||||
&non_trusted_nv_counter {
|
||||
reg = <NTFW_CTR_BASE>;
|
||||
};
|
||||
#endif
|
||||
+13
@@ -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
|
||||
};
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
#define AFF 00
|
||||
|
||||
#include "fvp-defs.dtsi"
|
||||
#undef POST
|
||||
#define POST \
|
||||
};
|
||||
|
||||
#define S_EL0 (0x1)
|
||||
#define S_EL1 (0x2)
|
||||
|
||||
/* For consumption by EL3 SPMC. */
|
||||
/ {
|
||||
compatible = "arm,ffa-manifest-1.0";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
|
||||
ffa-version = <0x00010001>; /* 31:16 - Major, 15:0 - Minor */
|
||||
id = <0x8001>;
|
||||
uuid = <0x6b43b460 0x74a24b78 0xade24502 0x40682886>;
|
||||
messaging-method = <0x3>; /* Direct Messaging Only */
|
||||
exception-level = <S_EL1>;
|
||||
execution-state = <0>;
|
||||
execution-ctx-count = <8>;
|
||||
gp-register-num = <0>;
|
||||
/* Subscribe to CPU_OFF, CPU_SUSPEND and CPU_SUSPEND_RESUME PM Msgs */
|
||||
power-management-messages = <0x7>;
|
||||
};
|
||||
+44
@@ -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 */
|
||||
};
|
||||
};
|
||||
};
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <drivers/measured_boot/event_log/event_log.h>
|
||||
#include <drivers/measured_boot/rss/rss_measured_boot.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/* Event Log data */
|
||||
static uint8_t event_log[PLAT_ARM_EVENT_LOG_MAX_SIZE];
|
||||
|
||||
/* FVP table with platform specific image IDs, names and PCRs */
|
||||
const event_log_metadata_t fvp_event_log_metadata[] = {
|
||||
{ FW_CONFIG_ID, EVLOG_FW_CONFIG_STRING, PCR_0 },
|
||||
{ TB_FW_CONFIG_ID, EVLOG_TB_FW_CONFIG_STRING, PCR_0 },
|
||||
{ BL2_IMAGE_ID, EVLOG_BL2_STRING, PCR_0 },
|
||||
|
||||
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
|
||||
};
|
||||
|
||||
/* FVP table with platform specific image IDs and metadata. Intentionally not a
|
||||
* const struct, some members might set by bootloaders during trusted boot.
|
||||
*/
|
||||
struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
|
||||
{
|
||||
.id = FW_CONFIG_ID,
|
||||
.slot = U(6),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_FW_CONFIG_STRING,
|
||||
.lock_measurement = true },
|
||||
{
|
||||
.id = TB_FW_CONFIG_ID,
|
||||
.slot = U(7),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING,
|
||||
.lock_measurement = true },
|
||||
{
|
||||
.id = BL2_IMAGE_ID,
|
||||
.slot = U(8),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_BL2_STRING,
|
||||
.lock_measurement = true },
|
||||
|
||||
{
|
||||
.id = RSS_MBOOT_INVALID_ID }
|
||||
};
|
||||
|
||||
void bl1_plat_mboot_init(void)
|
||||
{
|
||||
event_log_init(event_log, event_log + sizeof(event_log));
|
||||
event_log_write_header();
|
||||
|
||||
rss_measured_boot_init();
|
||||
}
|
||||
|
||||
void bl1_plat_mboot_finish(void)
|
||||
{
|
||||
size_t event_log_cur_size;
|
||||
|
||||
event_log_cur_size = event_log_get_cur_size(event_log);
|
||||
int rc = arm_set_tb_fw_info((uintptr_t)event_log,
|
||||
event_log_cur_size);
|
||||
if (rc != 0) {
|
||||
/*
|
||||
* It is a fatal error because on FVP platform, BL2 software
|
||||
* assumes that a valid Event Log buffer exist and it will use
|
||||
* same Event Log buffer to append image measurements.
|
||||
*/
|
||||
panic();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <bl1/bl1.h>
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <drivers/arm/smmu_v3.h>
|
||||
#include <drivers/arm/sp805.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/arm/common/arm_config.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/arm/common/arm_def.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include "fvp_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL1 specific platform actions.
|
||||
******************************************************************************/
|
||||
void bl1_early_platform_setup(void)
|
||||
{
|
||||
arm_bl1_early_platform_setup();
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
|
||||
/*
|
||||
* Initialize Interconnect for this cluster during cold boot.
|
||||
* No need for locks as no other CPU is active.
|
||||
*/
|
||||
fvp_interconnect_init();
|
||||
/*
|
||||
* Enable coherency in Interconnect for the primary CPU's cluster.
|
||||
*/
|
||||
fvp_interconnect_enable();
|
||||
}
|
||||
|
||||
void plat_arm_secure_wdt_start(void)
|
||||
{
|
||||
sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
|
||||
}
|
||||
|
||||
void plat_arm_secure_wdt_stop(void)
|
||||
{
|
||||
sp805_stop(ARM_SP805_TWDG_BASE);
|
||||
}
|
||||
|
||||
void bl1_platform_setup(void)
|
||||
{
|
||||
arm_bl1_platform_setup();
|
||||
|
||||
/* Initialize System level generic or SP804 timer */
|
||||
fvp_timer_init();
|
||||
|
||||
/* On FVP RevC, initialize SMMUv3 */
|
||||
if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
|
||||
smmuv3_security_init(PLAT_FVP_SMMUV3_BASE);
|
||||
}
|
||||
|
||||
__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
|
||||
{
|
||||
uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
|
||||
|
||||
/* Clear the NV flags register. */
|
||||
mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR),
|
||||
nv_flags);
|
||||
|
||||
/* Setup the watchdog to reset the system as soon as possible */
|
||||
sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
|
||||
|
||||
while (true)
|
||||
wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* The following function checks if Firmware update is needed by checking error
|
||||
* reported in NV flag.
|
||||
******************************************************************************/
|
||||
bool plat_arm_bl1_fwu_needed(void)
|
||||
{
|
||||
int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
|
||||
|
||||
/* if image load/authentication failed */
|
||||
return ((nv_flags == -EAUTH) || (nv_flags == -ENOENT));
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
#include "fvp_private.h"
|
||||
|
||||
void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
|
||||
u_register_t arg1 __unused,
|
||||
u_register_t arg2 __unused,
|
||||
u_register_t arg3 __unused)
|
||||
{
|
||||
arm_bl2_el3_early_platform_setup();
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
|
||||
/*
|
||||
* Initialize Interconnect for this cluster during cold boot.
|
||||
* No need for locks as no other CPU is active.
|
||||
*/
|
||||
fvp_interconnect_init();
|
||||
/*
|
||||
* Enable coherency in Interconnect for the primary CPU's cluster.
|
||||
*/
|
||||
fvp_interconnect_enable();
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <drivers/measured_boot/event_log/event_log.h>
|
||||
#include <drivers/measured_boot/rss/rss_measured_boot.h>
|
||||
#include <tools_share/tbbr_oid.h>
|
||||
#include <fvp_critical_data.h>
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* Event Log data */
|
||||
static uint64_t event_log_base;
|
||||
|
||||
/* FVP table with platform specific image IDs, names and PCRs */
|
||||
const event_log_metadata_t fvp_event_log_metadata[] = {
|
||||
{ BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 },
|
||||
{ BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 },
|
||||
{ BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 },
|
||||
{ BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 },
|
||||
{ BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 },
|
||||
{ HW_CONFIG_ID, EVLOG_HW_CONFIG_STRING, PCR_0 },
|
||||
{ NT_FW_CONFIG_ID, EVLOG_NT_FW_CONFIG_STRING, PCR_0 },
|
||||
{ SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 },
|
||||
{ SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 },
|
||||
{ TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 },
|
||||
{ RMM_IMAGE_ID, EVLOG_RMM_STRING, PCR_0},
|
||||
|
||||
#if defined(SPD_spmd)
|
||||
{ SP_PKG1_ID, EVLOG_SP1_STRING, PCR_0 },
|
||||
{ SP_PKG2_ID, EVLOG_SP2_STRING, PCR_0 },
|
||||
{ SP_PKG3_ID, EVLOG_SP3_STRING, PCR_0 },
|
||||
{ SP_PKG4_ID, EVLOG_SP4_STRING, PCR_0 },
|
||||
{ SP_PKG5_ID, EVLOG_SP5_STRING, PCR_0 },
|
||||
{ SP_PKG6_ID, EVLOG_SP6_STRING, PCR_0 },
|
||||
{ SP_PKG7_ID, EVLOG_SP7_STRING, PCR_0 },
|
||||
{ SP_PKG8_ID, EVLOG_SP8_STRING, PCR_0 },
|
||||
#endif
|
||||
|
||||
{ CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 },
|
||||
|
||||
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
|
||||
};
|
||||
|
||||
/* FVP table with platform specific image IDs and metadata. Intentionally not a
|
||||
* const struct, some members might set by bootloaders during trusted boot.
|
||||
*/
|
||||
struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
|
||||
{
|
||||
.id = BL31_IMAGE_ID,
|
||||
.slot = U(9),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_BL31_STRING,
|
||||
.lock_measurement = true },
|
||||
{
|
||||
.id = HW_CONFIG_ID,
|
||||
.slot = U(10),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_HW_CONFIG_STRING,
|
||||
.lock_measurement = true },
|
||||
{
|
||||
.id = SOC_FW_CONFIG_ID,
|
||||
.slot = U(11),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING,
|
||||
.lock_measurement = true },
|
||||
{
|
||||
.id = RMM_IMAGE_ID,
|
||||
.slot = U(12),
|
||||
.signer_id_size = SIGNER_ID_MIN_SIZE,
|
||||
.sw_type = RSS_MBOOT_RMM_STRING,
|
||||
.lock_measurement = true },
|
||||
{
|
||||
.id = RSS_MBOOT_INVALID_ID }
|
||||
};
|
||||
|
||||
void bl2_plat_mboot_init(void)
|
||||
{
|
||||
uint8_t *event_log_start;
|
||||
uint8_t *event_log_finish;
|
||||
size_t bl1_event_log_size;
|
||||
int rc;
|
||||
|
||||
rc = arm_get_tb_fw_info(&event_log_base, &bl1_event_log_size);
|
||||
if (rc != 0) {
|
||||
ERROR("%s(): Unable to get Event Log info from TB_FW_CONFIG\n",
|
||||
__func__);
|
||||
/*
|
||||
* It is a fatal error because on FVP platform, BL2 software
|
||||
* assumes that a valid Event Log buffer exist and it will use
|
||||
* same Event Log buffer to append image measurements.
|
||||
*/
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* BL1 and BL2 share the same Event Log buffer and that BL2 will
|
||||
* append its measurements after BL1's
|
||||
*/
|
||||
event_log_start = (uint8_t *)((uintptr_t)event_log_base +
|
||||
bl1_event_log_size);
|
||||
event_log_finish = (uint8_t *)((uintptr_t)event_log_base +
|
||||
PLAT_ARM_EVENT_LOG_MAX_SIZE);
|
||||
|
||||
event_log_init((uint8_t *)event_log_start, event_log_finish);
|
||||
|
||||
rss_measured_boot_init();
|
||||
}
|
||||
|
||||
int plat_mboot_measure_critical_data(unsigned int critical_data_id,
|
||||
const void *base, size_t size)
|
||||
{
|
||||
/*
|
||||
* It is very unlikely that the critical data size would be
|
||||
* bigger than 2^32 bytes
|
||||
*/
|
||||
assert(size < UINT32_MAX);
|
||||
assert(base != NULL);
|
||||
|
||||
/* Calculate image hash and record data in Event Log */
|
||||
int err = event_log_measure_and_record((uintptr_t)base, (uint32_t)size,
|
||||
critical_data_id);
|
||||
if (err != 0) {
|
||||
ERROR("%s%s critical data (%i)\n",
|
||||
"Failed to ", "record", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
static int fvp_populate_critical_data(struct fvp_critical_data *critical_data)
|
||||
{
|
||||
char *nv_ctr_oids[MAX_NV_CTR_IDS] = {
|
||||
[TRUSTED_NV_CTR_ID] = TRUSTED_FW_NVCOUNTER_OID,
|
||||
[NON_TRUSTED_NV_CTR_ID] = NON_TRUSTED_FW_NVCOUNTER_OID,
|
||||
};
|
||||
|
||||
for (int i = 0; i < MAX_NV_CTR_IDS; i++) {
|
||||
int rc = plat_get_nv_ctr(nv_ctr_oids[i],
|
||||
&critical_data->nv_ctr[i]);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
static int fvp_populate_and_measure_critical_data(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
* FVP platform only measures 'platform NV-counter' and hence its
|
||||
* measurement makes sense during Trusted-Boot flow only.
|
||||
*/
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
struct fvp_critical_data populate_critical_data;
|
||||
|
||||
rc = fvp_populate_critical_data(&populate_critical_data);
|
||||
if (rc == 0) {
|
||||
rc = plat_mboot_measure_critical_data(CRITICAL_DATA_ID,
|
||||
&populate_critical_data,
|
||||
sizeof(populate_critical_data));
|
||||
}
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void bl2_plat_mboot_finish(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Event Log address in Non-Secure memory */
|
||||
uintptr_t ns_log_addr;
|
||||
|
||||
/* Event Log filled size */
|
||||
size_t event_log_cur_size;
|
||||
|
||||
rc = fvp_populate_and_measure_critical_data();
|
||||
if (rc != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
|
||||
|
||||
rc = arm_set_nt_fw_info(
|
||||
#ifdef SPD_opteed
|
||||
(uintptr_t)event_log_base,
|
||||
#endif
|
||||
event_log_cur_size, &ns_log_addr);
|
||||
if (rc != 0) {
|
||||
ERROR("%s(): Unable to update %s_FW_CONFIG\n",
|
||||
__func__, "NT");
|
||||
/*
|
||||
* It is a fatal error because on FVP secure world software
|
||||
* assumes that a valid event log exists and will use it to
|
||||
* record the measurements into the fTPM.
|
||||
* Note: In FVP platform, OP-TEE uses nt_fw_config to get the
|
||||
* secure Event Log buffer address.
|
||||
*/
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Copy Event Log to Non-secure memory */
|
||||
(void)memcpy((void *)ns_log_addr, (const void *)event_log_base,
|
||||
event_log_cur_size);
|
||||
|
||||
/* Ensure that the Event Log is visible in Non-secure memory */
|
||||
flush_dcache_range(ns_log_addr, event_log_cur_size);
|
||||
|
||||
#if defined(SPD_tspd) || defined(SPD_spmd)
|
||||
/* Set Event Log data in TOS_FW_CONFIG */
|
||||
rc = arm_set_tos_fw_info((uintptr_t)event_log_base,
|
||||
event_log_cur_size);
|
||||
if (rc != 0) {
|
||||
ERROR("%s(): Unable to update %s_FW_CONFIG\n",
|
||||
__func__, "TOS");
|
||||
panic();
|
||||
}
|
||||
#endif /* defined(SPD_tspd) || defined(SPD_spmd) */
|
||||
|
||||
dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/desc_image_load.h>
|
||||
#include <drivers/arm/sp804_delay_timer.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <lib/fconf/fconf_dyn_cfg_getter.h>
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "fvp_private.h"
|
||||
|
||||
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
arm_bl2_platform_setup();
|
||||
|
||||
/* Initialize System level generic or SP804 timer */
|
||||
fvp_timer_init();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the list of executable images
|
||||
******************************************************************************/
|
||||
struct bl_params *plat_get_next_bl_params(void)
|
||||
{
|
||||
struct bl_params *arm_bl_params;
|
||||
const struct dyn_cfg_dtb_info_t *hw_config_info __unused;
|
||||
bl_mem_params_node_t *param_node __unused;
|
||||
|
||||
arm_bl_params = arm_get_next_bl_params();
|
||||
|
||||
#if !BL2_AT_EL3 && !EL3_PAYLOAD_BASE
|
||||
const struct dyn_cfg_dtb_info_t *fw_config_info;
|
||||
uintptr_t fw_config_base = 0UL;
|
||||
entry_point_info_t *ep_info;
|
||||
|
||||
#if __aarch64__
|
||||
/* Get BL31 image node */
|
||||
param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
|
||||
#else /* aarch32 */
|
||||
/* Get SP_MIN image node */
|
||||
param_node = get_bl_mem_params_node(BL32_IMAGE_ID);
|
||||
#endif /* __aarch64__ */
|
||||
assert(param_node != NULL);
|
||||
|
||||
/* get fw_config load address */
|
||||
fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
|
||||
assert(fw_config_info != NULL);
|
||||
|
||||
fw_config_base = fw_config_info->config_addr;
|
||||
assert(fw_config_base != 0UL);
|
||||
|
||||
/*
|
||||
* Get the entry point info of next executable image and override
|
||||
* arg1 of entry point info with fw_config base address
|
||||
*/
|
||||
ep_info = ¶m_node->ep_info;
|
||||
ep_info->args.arg1 = (uint32_t)fw_config_base;
|
||||
|
||||
/* grab NS HW config address */
|
||||
hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
|
||||
assert(hw_config_info != NULL);
|
||||
|
||||
/* To retrieve actual size of the HW_CONFIG */
|
||||
param_node = get_bl_mem_params_node(HW_CONFIG_ID);
|
||||
assert(param_node != NULL);
|
||||
|
||||
/* Copy HW config from Secure address to NS address */
|
||||
memcpy((void *)hw_config_info->ns_config_addr,
|
||||
(void *)hw_config_info->config_addr,
|
||||
(size_t)param_node->image_info.image_size);
|
||||
|
||||
/*
|
||||
* Ensure HW-config device tree committed to memory, as there is
|
||||
* a possibility to use HW-config without cache and MMU enabled
|
||||
* at BL33
|
||||
*/
|
||||
flush_dcache_range(hw_config_info->ns_config_addr,
|
||||
param_node->image_info.image_size);
|
||||
|
||||
param_node = get_bl_mem_params_node(BL33_IMAGE_ID);
|
||||
assert(param_node != NULL);
|
||||
|
||||
/* Update BL33's ep info with NS HW config address */
|
||||
param_node->ep_info.args.arg1 = hw_config_info->ns_config_addr;
|
||||
#endif /* !BL2_AT_EL3 && !EL3_PAYLOAD_BASE */
|
||||
|
||||
return arm_bl_params;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "fvp_private.h"
|
||||
|
||||
void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
|
||||
{
|
||||
arm_bl2u_early_platform_setup(mem_layout, plat_info);
|
||||
|
||||
/* Initialize System level generic or SP804 timer */
|
||||
fvp_timer_init();
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/smmu_v3.h>
|
||||
#include <fconf_hw_config_getter.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <lib/fconf/fconf_dyn_cfg_getter.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/arm/common/arm_config.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "fvp_private.h"
|
||||
|
||||
static const struct dyn_cfg_dtb_info_t *hw_config_info __unused;
|
||||
|
||||
void __init bl31_early_platform_setup2(u_register_t arg0,
|
||||
u_register_t arg1, u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
arm_console_boot_init();
|
||||
|
||||
#if !RESET_TO_BL31 && !BL2_AT_EL3
|
||||
const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
|
||||
|
||||
INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
|
||||
/* Fill the properties struct with the info from the config dtb */
|
||||
fconf_populate("FW_CONFIG", arg1);
|
||||
|
||||
soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
|
||||
if (soc_fw_config_info != NULL) {
|
||||
arg1 = soc_fw_config_info->config_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* arg2 is currently holding the 'secure' address of HW_CONFIG.
|
||||
* But arm_bl31_early_platform_setup() below expects the 'non-secure'
|
||||
* address of HW_CONFIG (which it will pass to BL33).
|
||||
* This why we need to override arg2 here.
|
||||
*/
|
||||
hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
|
||||
assert(hw_config_info != NULL);
|
||||
assert(hw_config_info->ns_config_addr != 0UL);
|
||||
arg2 = hw_config_info->ns_config_addr;
|
||||
#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 */
|
||||
|
||||
arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
|
||||
|
||||
/* Initialize the platform config for future decision making */
|
||||
fvp_config_setup();
|
||||
|
||||
/*
|
||||
* Initialize the correct interconnect for this cluster during cold
|
||||
* boot. No need for locks as no other CPU is active.
|
||||
*/
|
||||
fvp_interconnect_init();
|
||||
|
||||
/*
|
||||
* Enable coherency in interconnect for the primary CPU's cluster.
|
||||
* Earlier bootloader stages might already do this (e.g. Trusted
|
||||
* Firmware's BL1 does it) but we can't assume so. There is no harm in
|
||||
* executing this code twice anyway.
|
||||
* FVP PSCI code will enable coherency for other clusters.
|
||||
*/
|
||||
fvp_interconnect_enable();
|
||||
|
||||
/* Initialize System level generic or SP804 timer */
|
||||
fvp_timer_init();
|
||||
|
||||
/* On FVP RevC, initialize SMMUv3 */
|
||||
if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
|
||||
smmuv3_init(PLAT_FVP_SMMUV3_BASE);
|
||||
}
|
||||
|
||||
void __init bl31_plat_arch_setup(void)
|
||||
{
|
||||
int rc __unused;
|
||||
uintptr_t hw_config_base_align __unused;
|
||||
size_t mapped_size_align __unused;
|
||||
|
||||
arm_bl31_plat_arch_setup();
|
||||
|
||||
/*
|
||||
* For RESET_TO_BL31 systems, BL31 is the first bootloader to run.
|
||||
* So there is no BL2 to load the HW_CONFIG dtb into memory before
|
||||
* control is passed to BL31. The code below relies on dynamic mapping
|
||||
* capability, which is not supported by xlat tables lib V1.
|
||||
* TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support
|
||||
* gets deprecated.
|
||||
*/
|
||||
#if !RESET_TO_BL31 && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1
|
||||
assert(hw_config_info != NULL);
|
||||
assert(hw_config_info->config_addr != 0UL);
|
||||
|
||||
/* Page aligned address and size if necessary */
|
||||
hw_config_base_align = page_align(hw_config_info->config_addr, DOWN);
|
||||
mapped_size_align = page_align(hw_config_info->config_max_size, UP);
|
||||
|
||||
if ((hw_config_info->config_addr != hw_config_base_align) &&
|
||||
(hw_config_info->config_max_size == mapped_size_align)) {
|
||||
mapped_size_align += PAGE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* map dynamically HW config region with its aligned base address and
|
||||
* size
|
||||
*/
|
||||
rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align,
|
||||
hw_config_base_align,
|
||||
mapped_size_align,
|
||||
MT_RO_DATA);
|
||||
if (rc != 0) {
|
||||
ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc);
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Populate HW_CONFIG device tree with the mapped address */
|
||||
fconf_populate("HW_CONFIG", hw_config_info->config_addr);
|
||||
|
||||
/* unmap the HW_CONFIG memory region */
|
||||
rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align);
|
||||
if (rc != 0) {
|
||||
ERROR("Error while unmapping HW_CONFIG device tree (%d).\n",
|
||||
rc);
|
||||
panic();
|
||||
}
|
||||
#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 */
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
unsigned int counter_base_frequency;
|
||||
|
||||
#if !RESET_TO_BL31 && !BL2_AT_EL3
|
||||
/* Get the frequency through FCONF API for HW_CONFIG */
|
||||
counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq);
|
||||
if (counter_base_frequency > 0U) {
|
||||
return counter_base_frequency;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read the frequency from Frequency modes table */
|
||||
counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
|
||||
|
||||
/* The first entry of the frequency modes table must not be 0 */
|
||||
if (counter_base_frequency == 0U) {
|
||||
panic();
|
||||
}
|
||||
|
||||
return counter_base_frequency;
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/cci.h>
|
||||
#include <drivers/arm/ccn.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/arm/sp804_delay_timer.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/smccc.h>
|
||||
#include <lib/xlat_tables/xlat_tables_compat.h>
|
||||
#include <platform_def.h>
|
||||
#include <services/arm_arch_svc.h>
|
||||
#if ENABLE_RME
|
||||
#include <services/rmm_core_manifest.h>
|
||||
#endif
|
||||
#if SPM_MM
|
||||
#include <services/spm_mm_partition.h>
|
||||
#endif
|
||||
|
||||
#include <plat/arm/common/arm_config.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "fvp_private.h"
|
||||
|
||||
/* Defines for GIC Driver build time selection */
|
||||
#define FVP_GICV2 1
|
||||
#define FVP_GICV3 2
|
||||
|
||||
/*******************************************************************************
|
||||
* arm_config holds the characteristics of the differences between the three FVP
|
||||
* platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
|
||||
* at each boot stage by the primary before enabling the MMU (to allow
|
||||
* interconnect configuration) & used thereafter. Each BL will have its own copy
|
||||
* to allow independent operation.
|
||||
******************************************************************************/
|
||||
arm_config_t arm_config;
|
||||
|
||||
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
|
||||
DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
|
||||
DEVICE1_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#if FVP_GICR_REGION_PROTECTION
|
||||
#define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \
|
||||
BASE_GICD_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/* Map all core's redistributor memory as read-only. After boots up,
|
||||
* per-core map its redistributor memory as read-write */
|
||||
#define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \
|
||||
(BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\
|
||||
MT_DEVICE | MT_RO | MT_SECURE)
|
||||
#endif /* FVP_GICR_REGION_PROTECTION */
|
||||
|
||||
/*
|
||||
* Need to be mapped with write permissions in order to set a new non-volatile
|
||||
* counter value.
|
||||
*/
|
||||
#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \
|
||||
DEVICE2_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*
|
||||
* Table of memory regions for various BL stages to map using the MMU.
|
||||
* This doesn't include Trusted SRAM as setup_page_tables() already takes care
|
||||
* of mapping it.
|
||||
*/
|
||||
#ifdef IMAGE_BL1
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
V2M_MAP_FLASH0_RO,
|
||||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
|
||||
MAP_DEVICE1,
|
||||
#endif
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/* To access the Root of Trust Public Key registers. */
|
||||
MAP_DEVICE2,
|
||||
/* Map DRAM to authenticate NS_BL2U image. */
|
||||
ARM_MAP_NS_DRAM1,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL2
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
V2M_MAP_FLASH0_RW,
|
||||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
|
||||
MAP_DEVICE1,
|
||||
#endif
|
||||
ARM_MAP_NS_DRAM1,
|
||||
#ifdef __aarch64__
|
||||
ARM_MAP_DRAM2,
|
||||
#endif
|
||||
/*
|
||||
* Required to load HW_CONFIG, SPMC and SPs to trusted DRAM.
|
||||
*/
|
||||
ARM_MAP_TRUSTED_DRAM,
|
||||
#if ENABLE_RME
|
||||
ARM_MAP_RMM_DRAM,
|
||||
ARM_MAP_GPT_L1_DRAM,
|
||||
#endif /* ENABLE_RME */
|
||||
#ifdef SPD_tspd
|
||||
ARM_MAP_TSP_SEC_MEM,
|
||||
#endif
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/* To access the Root of Trust Public Key registers. */
|
||||
MAP_DEVICE2,
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
#if CRYPTO_SUPPORT && !BL2_AT_EL3
|
||||
/*
|
||||
* To access shared the Mbed TLS heap while booting the
|
||||
* system with Crypto support
|
||||
*/
|
||||
ARM_MAP_BL1_RW,
|
||||
#endif /* CRYPTO_SUPPORT && !BL2_AT_EL3 */
|
||||
#if SPM_MM || SPMC_AT_EL3
|
||||
ARM_SP_IMAGE_MMAP,
|
||||
#endif
|
||||
#if ARM_BL31_IN_DRAM
|
||||
ARM_MAP_BL31_SEC_DRAM,
|
||||
#endif
|
||||
#ifdef SPD_opteed
|
||||
ARM_MAP_OPTEE_CORE_MEM,
|
||||
ARM_OPTEE_PAGEABLE_LOAD_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL2U
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
MAP_DEVICE0,
|
||||
V2M_MAP_IOFPGA,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL31
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
#if USE_DEBUGFS
|
||||
/* Required by devfip, can be removed if devfip is not used */
|
||||
V2M_MAP_FLASH0_RW,
|
||||
#endif /* USE_DEBUGFS */
|
||||
ARM_MAP_EL3_TZC_DRAM,
|
||||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
#if FVP_GICR_REGION_PROTECTION
|
||||
MAP_GICD_MEM,
|
||||
MAP_GICR_MEM,
|
||||
#else
|
||||
MAP_DEVICE1,
|
||||
#endif /* FVP_GICR_REGION_PROTECTION */
|
||||
ARM_V2M_MAP_MEM_PROTECT,
|
||||
#if SPM_MM
|
||||
ARM_SPM_BUF_EL3_MMAP,
|
||||
#endif
|
||||
#if ENABLE_RME
|
||||
ARM_MAP_GPT_L1_DRAM,
|
||||
ARM_MAP_EL3_RMM_SHARED_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
|
||||
#if defined(IMAGE_BL31) && SPM_MM
|
||||
const mmap_region_t plat_arm_secure_partition_mmap[] = {
|
||||
V2M_MAP_IOFPGA_EL0, /* for the UART */
|
||||
MAP_REGION_FLAT(DEVICE0_BASE, \
|
||||
DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RO | MT_SECURE | MT_USER),
|
||||
ARM_SP_IMAGE_MMAP,
|
||||
ARM_SP_IMAGE_NS_BUF_MMAP,
|
||||
ARM_SP_IMAGE_RW_MMAP,
|
||||
ARM_SPM_BUF_EL0_MMAP,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
#ifdef IMAGE_BL32
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
#ifndef __aarch64__
|
||||
ARM_MAP_SHARED_RAM,
|
||||
ARM_V2M_MAP_MEM_PROTECT,
|
||||
#endif
|
||||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
MAP_DEVICE1,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef IMAGE_RMM
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
MAP_DEVICE1,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
ARM_CASSERT_MMAP
|
||||
|
||||
#if FVP_INTERCONNECT_DRIVER != FVP_CCN
|
||||
static const int fvp_cci400_map[] = {
|
||||
PLAT_FVP_CCI400_CLUS0_SL_PORT,
|
||||
PLAT_FVP_CCI400_CLUS1_SL_PORT,
|
||||
};
|
||||
|
||||
static const int fvp_cci5xx_map[] = {
|
||||
PLAT_FVP_CCI5XX_CLUS0_SL_PORT,
|
||||
PLAT_FVP_CCI5XX_CLUS1_SL_PORT,
|
||||
};
|
||||
|
||||
static unsigned int get_interconnect_master(void)
|
||||
{
|
||||
unsigned int master;
|
||||
u_register_t mpidr;
|
||||
|
||||
mpidr = read_mpidr_el1();
|
||||
master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
|
||||
MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);
|
||||
|
||||
assert(master < FVP_CLUSTER_COUNT);
|
||||
return master;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(IMAGE_BL31) && SPM_MM
|
||||
/*
|
||||
* Boot information passed to a secure partition during initialisation. Linear
|
||||
* indices in MP information will be filled at runtime.
|
||||
*/
|
||||
static spm_mm_mp_info_t sp_mp_info[] = {
|
||||
[0] = {0x80000000, 0},
|
||||
[1] = {0x80000001, 0},
|
||||
[2] = {0x80000002, 0},
|
||||
[3] = {0x80000003, 0},
|
||||
[4] = {0x80000100, 0},
|
||||
[5] = {0x80000101, 0},
|
||||
[6] = {0x80000102, 0},
|
||||
[7] = {0x80000103, 0},
|
||||
};
|
||||
|
||||
const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
|
||||
.h.type = PARAM_SP_IMAGE_BOOT_INFO,
|
||||
.h.version = VERSION_1,
|
||||
.h.size = sizeof(spm_mm_boot_info_t),
|
||||
.h.attr = 0,
|
||||
.sp_mem_base = ARM_SP_IMAGE_BASE,
|
||||
.sp_mem_limit = ARM_SP_IMAGE_LIMIT,
|
||||
.sp_image_base = ARM_SP_IMAGE_BASE,
|
||||
.sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
|
||||
.sp_heap_base = ARM_SP_IMAGE_HEAP_BASE,
|
||||
.sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
|
||||
.sp_shared_buf_base = PLAT_SPM_BUF_BASE,
|
||||
.sp_image_size = ARM_SP_IMAGE_SIZE,
|
||||
.sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
|
||||
.sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE,
|
||||
.sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
|
||||
.sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
|
||||
.num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS,
|
||||
.num_cpus = PLATFORM_CORE_COUNT,
|
||||
.mp_info = &sp_mp_info[0],
|
||||
};
|
||||
|
||||
const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
|
||||
{
|
||||
return plat_arm_secure_partition_mmap;
|
||||
}
|
||||
|
||||
const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
|
||||
void *cookie)
|
||||
{
|
||||
return &plat_arm_secure_partition_boot_info;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* A single boot loader stack is expected to work on both the Foundation FVP
|
||||
* models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
|
||||
* SYS_ID register provides a mechanism for detecting the differences between
|
||||
* these platforms. This information is stored in a per-BL array to allow the
|
||||
* code to take the correct path.Per BL platform configuration.
|
||||
******************************************************************************/
|
||||
void __init fvp_config_setup(void)
|
||||
{
|
||||
unsigned int rev, hbi, bld, arch, sys_id;
|
||||
|
||||
sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
|
||||
rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
|
||||
hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
|
||||
bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
|
||||
arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
|
||||
|
||||
if (arch != ARCH_MODEL) {
|
||||
ERROR("This firmware is for FVP models\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* The build field in the SYS_ID tells which variant of the GIC
|
||||
* memory is implemented by the model.
|
||||
*/
|
||||
switch (bld) {
|
||||
case BLD_GIC_VE_MMAP:
|
||||
ERROR("Legacy Versatile Express memory map for GIC peripheral"
|
||||
" is not supported\n");
|
||||
panic();
|
||||
break;
|
||||
case BLD_GIC_A53A57_MMAP:
|
||||
break;
|
||||
default:
|
||||
ERROR("Unsupported board build %x\n", bld);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010
|
||||
* for the Foundation FVP.
|
||||
*/
|
||||
switch (hbi) {
|
||||
case HBI_FOUNDATION_FVP:
|
||||
arm_config.flags = 0;
|
||||
|
||||
/*
|
||||
* Check for supported revisions of Foundation FVP
|
||||
* Allow future revisions to run but emit warning diagnostic
|
||||
*/
|
||||
switch (rev) {
|
||||
case REV_FOUNDATION_FVP_V2_0:
|
||||
case REV_FOUNDATION_FVP_V2_1:
|
||||
case REV_FOUNDATION_FVP_v9_1:
|
||||
case REV_FOUNDATION_FVP_v9_6:
|
||||
break;
|
||||
default:
|
||||
WARN("Unrecognized Foundation FVP revision %x\n", rev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HBI_BASE_FVP:
|
||||
arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
|
||||
|
||||
/*
|
||||
* Check for supported revisions
|
||||
* Allow future revisions to run but emit warning diagnostic
|
||||
*/
|
||||
switch (rev) {
|
||||
case REV_BASE_FVP_V0:
|
||||
arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
|
||||
break;
|
||||
case REV_BASE_FVP_REVC:
|
||||
arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 |
|
||||
ARM_CONFIG_FVP_HAS_CCI5XX);
|
||||
break;
|
||||
default:
|
||||
WARN("Unrecognized Base FVP revision %x\n", rev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR("Unsupported board HBI number 0x%x\n", hbi);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that the presence of MT bit, and therefore shifted
|
||||
* affinities, is uniform across the platform: either all CPUs, or no
|
||||
* CPUs implement it.
|
||||
*/
|
||||
if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U)
|
||||
arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
|
||||
}
|
||||
|
||||
|
||||
void __init fvp_interconnect_init(void)
|
||||
{
|
||||
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
|
||||
if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
|
||||
ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported");
|
||||
panic();
|
||||
}
|
||||
|
||||
plat_arm_interconnect_init();
|
||||
#else
|
||||
uintptr_t cci_base = 0U;
|
||||
const int *cci_map = NULL;
|
||||
unsigned int map_size = 0U;
|
||||
|
||||
/* Initialize the right interconnect */
|
||||
if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
|
||||
cci_base = PLAT_FVP_CCI5XX_BASE;
|
||||
cci_map = fvp_cci5xx_map;
|
||||
map_size = ARRAY_SIZE(fvp_cci5xx_map);
|
||||
} else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
|
||||
cci_base = PLAT_FVP_CCI400_BASE;
|
||||
cci_map = fvp_cci400_map;
|
||||
map_size = ARRAY_SIZE(fvp_cci400_map);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(cci_base != 0U);
|
||||
assert(cci_map != NULL);
|
||||
cci_init(cci_base, cci_map, map_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fvp_interconnect_enable(void)
|
||||
{
|
||||
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
|
||||
plat_arm_interconnect_enter_coherency();
|
||||
#else
|
||||
unsigned int master;
|
||||
|
||||
if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
|
||||
ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
|
||||
master = get_interconnect_master();
|
||||
cci_enable_snoop_dvm_reqs(master);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void fvp_interconnect_disable(void)
|
||||
{
|
||||
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
|
||||
plat_arm_interconnect_exit_coherency();
|
||||
#else
|
||||
unsigned int master;
|
||||
|
||||
if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
|
||||
ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
|
||||
master = get_interconnect_master();
|
||||
cci_disable_snoop_dvm_reqs(master);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CRYPTO_SUPPORT
|
||||
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
|
||||
{
|
||||
assert(heap_addr != NULL);
|
||||
assert(heap_size != NULL);
|
||||
|
||||
return arm_get_mbedtls_heap(heap_addr, heap_size);
|
||||
}
|
||||
#endif /* CRYPTO_SUPPORT */
|
||||
|
||||
void fvp_timer_init(void)
|
||||
{
|
||||
#if USE_SP804_TIMER
|
||||
/* Enable the clock override for SP804 timer 0, which means that no
|
||||
* clock dividers are applied and the raw (35MHz) clock will be used.
|
||||
*/
|
||||
mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
|
||||
|
||||
/* Initialize delay timer driver using SP804 dual timer 0 */
|
||||
sp804_timer_init(V2M_SP804_TIMER0_BASE,
|
||||
SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
|
||||
#else
|
||||
generic_delay_timer_init();
|
||||
|
||||
/* Enable System level generic timer */
|
||||
mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
|
||||
CNTCR_FCREQ(0U) | CNTCR_EN);
|
||||
#endif /* USE_SP804_TIMER */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* plat_is_smccc_feature_available() - This function checks whether SMCCC
|
||||
* feature is availabile for platform.
|
||||
* @fid: SMCCC function id
|
||||
*
|
||||
* Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
|
||||
* SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
|
||||
*****************************************************************************/
|
||||
int32_t plat_is_smccc_feature_available(u_register_t fid)
|
||||
{
|
||||
switch (fid) {
|
||||
case SMCCC_ARCH_SOC_ID:
|
||||
return SMC_ARCH_CALL_SUCCESS;
|
||||
default:
|
||||
return SMC_ARCH_CALL_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get SOC version */
|
||||
int32_t plat_get_soc_version(void)
|
||||
{
|
||||
return (int32_t)
|
||||
(SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE,
|
||||
ARM_SOC_IDENTIFICATION_CODE) |
|
||||
(FVP_SOC_ID & SOC_ID_IMPL_DEF_MASK));
|
||||
}
|
||||
|
||||
/* Get SOC revision */
|
||||
int32_t plat_get_soc_revision(void)
|
||||
{
|
||||
unsigned int sys_id;
|
||||
|
||||
sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
|
||||
return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
|
||||
V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
|
||||
}
|
||||
|
||||
#if ENABLE_RME
|
||||
/*
|
||||
* Get a pointer to the RMM-EL3 Shared buffer and return it
|
||||
* through the pointer passed as parameter.
|
||||
*
|
||||
* This function returns the size of the shared buffer.
|
||||
*/
|
||||
size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared)
|
||||
{
|
||||
*shared = (uintptr_t)RMM_SHARED_BASE;
|
||||
|
||||
return (size_t)RMM_SHARED_SIZE;
|
||||
}
|
||||
|
||||
int plat_rmmd_load_manifest(rmm_manifest_t *manifest)
|
||||
{
|
||||
assert(manifest != NULL);
|
||||
|
||||
manifest->version = RMMD_MANIFEST_VERSION;
|
||||
manifest->plat_data = (uintptr_t)NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/desc_image_load.h>
|
||||
#include <drivers/measured_boot/event_log/event_log.h>
|
||||
#include <drivers/measured_boot/rss/rss_measured_boot.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
extern event_log_metadata_t fvp_event_log_metadata[];
|
||||
extern struct rss_mboot_metadata fvp_rss_mboot_metadata[];
|
||||
|
||||
const event_log_metadata_t *plat_event_log_get_metadata(void)
|
||||
{
|
||||
return fvp_event_log_metadata;
|
||||
}
|
||||
|
||||
struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void)
|
||||
{
|
||||
return fvp_rss_mboot_metadata;
|
||||
}
|
||||
|
||||
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
|
||||
{
|
||||
int err;
|
||||
int rc = 0;
|
||||
|
||||
/* Calculate image hash and record data in Event Log */
|
||||
err = event_log_measure_and_record(image_data->image_base,
|
||||
image_data->image_size,
|
||||
image_id);
|
||||
if (err != 0) {
|
||||
ERROR("%s%s image id %u (%i)\n",
|
||||
"Failed to ", "record in event log", image_id, err);
|
||||
rc = err;
|
||||
}
|
||||
|
||||
/* Calculate image hash and record data in RSS */
|
||||
err = rss_mboot_measure_and_record(image_data->image_base,
|
||||
image_data->image_size,
|
||||
image_id);
|
||||
if (err != 0) {
|
||||
ERROR("%s%s image id %u (%i)\n",
|
||||
"Failed to ", "record in RSS", image_id, err);
|
||||
rc = (rc == 0) ? err : -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/pl011.h>
|
||||
#include <drivers/console.h>
|
||||
#include <fconf_hw_config_getter.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
static console_t fvp_runtime_console;
|
||||
|
||||
/* Initialize the runtime console */
|
||||
void arm_console_runtime_init(void)
|
||||
{
|
||||
uintptr_t uart_base;
|
||||
uint32_t uart_clk;
|
||||
|
||||
/*
|
||||
* fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and
|
||||
* BL2_AT_EL3 systems.
|
||||
*/
|
||||
#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3
|
||||
uart_base = PLAT_ARM_RUN_UART_BASE;
|
||||
uart_clk = PLAT_ARM_RUN_UART_CLK_IN_HZ;
|
||||
#else
|
||||
uart_base = FCONF_GET_PROPERTY(hw_config, uart_serial_config,
|
||||
uart_base);
|
||||
uart_clk = FCONF_GET_PROPERTY(hw_config, uart_serial_config,
|
||||
uart_clk);
|
||||
#endif
|
||||
|
||||
int rc = console_pl011_register(uart_base, uart_clk,
|
||||
ARM_CONSOLE_BAUDRATE,
|
||||
&fvp_runtime_console);
|
||||
|
||||
if (rc == 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
console_set_scope(&fvp_runtime_console, CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
|
||||
void arm_console_runtime_end(void)
|
||||
{
|
||||
console_flush();
|
||||
(void)console_unregister(&fvp_runtime_console);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#
|
||||
# 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_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_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
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef FVP_DEF_H
|
||||
#define FVP_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#ifndef FVP_CLUSTER_COUNT
|
||||
#error "FVP_CLUSTER_COUNT is not set in makefile"
|
||||
#endif
|
||||
|
||||
#ifndef FVP_MAX_CPUS_PER_CLUSTER
|
||||
#error "FVP_MAX_CPUS_PER_CLUSTER is not set in makefile"
|
||||
#endif
|
||||
|
||||
#ifndef FVP_MAX_PE_PER_CPU
|
||||
#error "FVP_MAX_PE_PER_CPU is not set in makefile"
|
||||
#endif
|
||||
|
||||
#define FVP_PRIMARY_CPU 0x0
|
||||
|
||||
/* Defines for the Interconnect build selection */
|
||||
#define FVP_CCI 1
|
||||
#define FVP_CCN 2
|
||||
|
||||
/******************************************************************************
|
||||
* Definition of platform soc id
|
||||
*****************************************************************************/
|
||||
#define FVP_SOC_ID 0
|
||||
|
||||
/*******************************************************************************
|
||||
* FVP memory map related constants
|
||||
******************************************************************************/
|
||||
|
||||
#define FLASH1_BASE UL(0x0c000000)
|
||||
#define FLASH1_SIZE UL(0x04000000)
|
||||
|
||||
#define PSRAM_BASE UL(0x14000000)
|
||||
#define PSRAM_SIZE UL(0x04000000)
|
||||
|
||||
#define VRAM_BASE UL(0x18000000)
|
||||
#define VRAM_SIZE UL(0x02000000)
|
||||
|
||||
/* Aggregate of all devices in the first GB */
|
||||
#define DEVICE0_BASE UL(0x20000000)
|
||||
#define DEVICE0_SIZE UL(0x0c200000)
|
||||
|
||||
/*
|
||||
* In case of FVP models with CCN, the CCN register space overlaps into
|
||||
* the NSRAM area.
|
||||
*/
|
||||
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
|
||||
#define DEVICE1_BASE UL(0x2e000000)
|
||||
#define DEVICE1_SIZE UL(0x1A00000)
|
||||
#else
|
||||
#define DEVICE1_BASE BASE_GICD_BASE
|
||||
|
||||
#if GIC_ENABLE_V4_EXTN
|
||||
/* GICv4 mapping: GICD + CORE_COUNT * 256KB */
|
||||
#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \
|
||||
(PLATFORM_CORE_COUNT * 0x40000))
|
||||
#else
|
||||
/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */
|
||||
#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \
|
||||
(PLATFORM_CORE_COUNT * 0x20000))
|
||||
#endif /* GIC_ENABLE_V4_EXTN */
|
||||
|
||||
#define NSRAM_BASE UL(0x2e000000)
|
||||
#define NSRAM_SIZE UL(0x10000)
|
||||
#endif
|
||||
/* Devices in the second GB */
|
||||
#define DEVICE2_BASE UL(0x7fe00000)
|
||||
#define DEVICE2_SIZE UL(0x00200000)
|
||||
|
||||
#define PCIE_EXP_BASE UL(0x40000000)
|
||||
#define TZRNG_BASE UL(0x7fe60000)
|
||||
|
||||
/* Non-volatile counters */
|
||||
#define TRUSTED_NVCTR_BASE UL(0x7fe70000)
|
||||
#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000))
|
||||
#define TFW_NVCTR_SIZE UL(4)
|
||||
#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004))
|
||||
#define NTFW_CTR_SIZE UL(4)
|
||||
|
||||
/* Keys */
|
||||
#define SOC_KEYS_BASE UL(0x7fe80000)
|
||||
#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000))
|
||||
#define TZ_PUB_KEY_HASH_SIZE UL(32)
|
||||
#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020))
|
||||
#define HU_KEY_SIZE UL(16)
|
||||
#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044))
|
||||
#define END_KEY_SIZE UL(32)
|
||||
|
||||
/* Constants to distinguish FVP type */
|
||||
#define HBI_BASE_FVP U(0x020)
|
||||
#define REV_BASE_FVP_V0 U(0x0)
|
||||
#define REV_BASE_FVP_REVC U(0x2)
|
||||
|
||||
#define HBI_FOUNDATION_FVP U(0x010)
|
||||
#define REV_FOUNDATION_FVP_V2_0 U(0x0)
|
||||
#define REV_FOUNDATION_FVP_V2_1 U(0x1)
|
||||
#define REV_FOUNDATION_FVP_v9_1 U(0x2)
|
||||
#define REV_FOUNDATION_FVP_v9_6 U(0x3)
|
||||
|
||||
#define BLD_GIC_VE_MMAP U(0x0)
|
||||
#define BLD_GIC_A53A57_MMAP U(0x1)
|
||||
|
||||
#define ARCH_MODEL U(0x1)
|
||||
|
||||
/* FVP Power controller base address*/
|
||||
#define PWRC_BASE UL(0x1c100000)
|
||||
|
||||
/* FVP SP804 timer frequency is 35 MHz*/
|
||||
#define SP804_TIMER_CLKMULT 1
|
||||
#define SP804_TIMER_CLKDIV 35
|
||||
|
||||
/* SP810 controller. FVP specific flags */
|
||||
#define FVP_SP810_CTRL_TIM0_OV BIT_32(16)
|
||||
#define FVP_SP810_CTRL_TIM1_OV BIT_32(18)
|
||||
#define FVP_SP810_CTRL_TIM2_OV BIT_32(20)
|
||||
#define FVP_SP810_CTRL_TIM3_OV BIT_32(22)
|
||||
|
||||
/*******************************************************************************
|
||||
* GIC & interrupt handling related constants
|
||||
******************************************************************************/
|
||||
/* VE compatible GIC memory map */
|
||||
#define VE_GICD_BASE UL(0x2c001000)
|
||||
#define VE_GICC_BASE UL(0x2c002000)
|
||||
#define VE_GICH_BASE UL(0x2c004000)
|
||||
#define VE_GICV_BASE UL(0x2c006000)
|
||||
|
||||
/* Base FVP compatible GIC memory map */
|
||||
#define BASE_GICD_BASE UL(0x2f000000)
|
||||
#define BASE_GICD_SIZE UL(0x10000)
|
||||
#define BASE_GICR_BASE UL(0x2f100000)
|
||||
|
||||
#if GIC_ENABLE_V4_EXTN
|
||||
/* GICv4 redistributor size: 256KB */
|
||||
#define BASE_GICR_SIZE UL(0x40000)
|
||||
#else
|
||||
#define BASE_GICR_SIZE UL(0x20000)
|
||||
#endif /* GIC_ENABLE_V4_EXTN */
|
||||
|
||||
#define BASE_GICC_BASE UL(0x2c000000)
|
||||
#define BASE_GICH_BASE UL(0x2c010000)
|
||||
#define BASE_GICV_BASE UL(0x2c02f000)
|
||||
|
||||
#define FVP_IRQ_TZ_WDOG 56
|
||||
#define FVP_IRQ_SEC_SYS_TIMER 57
|
||||
|
||||
/*******************************************************************************
|
||||
* TrustZone address space controller related constants
|
||||
******************************************************************************/
|
||||
|
||||
/* NSAIDs used by devices in TZC filter 0 on FVP */
|
||||
#define FVP_NSAID_DEFAULT 0
|
||||
#define FVP_NSAID_PCI 1
|
||||
#define FVP_NSAID_VIRTIO 8 /* from FVP v5.6 onwards */
|
||||
#define FVP_NSAID_AP 9 /* Application Processors */
|
||||
#define FVP_NSAID_VIRTIO_OLD 15 /* until FVP v5.5 */
|
||||
|
||||
/* NSAIDs used by devices in TZC filter 2 on FVP */
|
||||
#define FVP_NSAID_HDLCD0 2
|
||||
#define FVP_NSAID_CLCD 7
|
||||
|
||||
/*******************************************************************************
|
||||
* Memprotect definitions
|
||||
******************************************************************************/
|
||||
/* PSCI memory protect definitions:
|
||||
* This variable is stored in a non-secure flash because some ARM reference
|
||||
* platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
|
||||
* support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
|
||||
*/
|
||||
#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
|
||||
V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
|
||||
|
||||
#endif /* FVP_DEF_H */
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Check passed region is within Non-Secure region of DRAM
|
||||
******************************************************************************/
|
||||
int plat_drtm_validate_ns_region(uintptr_t region_start,
|
||||
size_t region_size)
|
||||
{
|
||||
uintptr_t region_end = region_start + region_size - 1;
|
||||
|
||||
if (region_start >= region_end) {
|
||||
return -1;
|
||||
} else if ((region_start >= ARM_NS_DRAM1_BASE) &&
|
||||
(region_start < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE)) &&
|
||||
(region_end >= ARM_NS_DRAM1_BASE) &&
|
||||
(region_end < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) {
|
||||
return 0;
|
||||
} else if ((region_start >= ARM_DRAM2_BASE) &&
|
||||
(region_start < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE)) &&
|
||||
(region_end >= ARM_DRAM2_BASE) &&
|
||||
(region_end < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <drivers/arm/smmu_v3.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <plat/arm/common/arm_config.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/**
|
||||
* Array mentioning number of SMMUs supported by FVP
|
||||
*/
|
||||
static const uintptr_t fvp_smmus[] = {
|
||||
PLAT_FVP_SMMUV3_BASE,
|
||||
};
|
||||
|
||||
bool plat_has_non_host_platforms(void)
|
||||
{
|
||||
/* FVP base platforms typically have GPU, as per FVP Reference guide */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plat_has_unmanaged_dma_peripherals(void)
|
||||
{
|
||||
/*
|
||||
* FVP Reference guide does not show devices that are described as
|
||||
* DMA-capable but not managed by an SMMU in the FVP documentation.
|
||||
* However, the SMMU seems to have only been introduced in the RevC
|
||||
* revision.
|
||||
*/
|
||||
return (arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) == 0;
|
||||
}
|
||||
|
||||
unsigned int plat_get_total_smmus(void)
|
||||
{
|
||||
if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) {
|
||||
return ARRAY_SIZE(fvp_smmus);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void plat_enumerate_smmus(const uintptr_t **smmus_out,
|
||||
size_t *smmu_count_out)
|
||||
{
|
||||
if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) {
|
||||
*smmus_out = fvp_smmus;
|
||||
*smmu_count_out = ARRAY_SIZE(fvp_smmus);
|
||||
} else {
|
||||
*smmus_out = NULL;
|
||||
*smmu_count_out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* DRTM DMA Protection Features */
|
||||
static const plat_drtm_dma_prot_features_t dma_prot_features = {
|
||||
.max_num_mem_prot_regions = 0, /* No protection regions are present */
|
||||
.dma_protection_support = 0x1 /* Complete DMA protection only */
|
||||
};
|
||||
|
||||
const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void)
|
||||
{
|
||||
return &dma_prot_features;
|
||||
}
|
||||
|
||||
uint64_t plat_drtm_dma_prot_get_max_table_bytes(void)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
int plat_set_drtm_error(uint64_t error_code)
|
||||
{
|
||||
/* TODO: Set DRTM error in NV-storage */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_drtm_error(uint64_t *error_code)
|
||||
{
|
||||
/* TODO: Get DRTM error from NV-storage */
|
||||
*error_code = 0;
|
||||
return 0;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <drivers/measured_boot/event_log/event_log.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* DRTM TPM Features */
|
||||
static const plat_drtm_tpm_features_t tpm_features = {
|
||||
/* No TPM-based hashing supported. */
|
||||
.tpm_based_hash_support = false,
|
||||
|
||||
/* Set to decided algorithm by Event Log driver */
|
||||
.firmware_hash_algorithm = TPM_ALG_ID
|
||||
|
||||
};
|
||||
|
||||
const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void)
|
||||
{
|
||||
return &tpm_features;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user