GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -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));
}
@@ -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
@@ -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>;
};
};
};
@@ -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>;
};
};
@@ -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))
@@ -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)
{
}
@@ -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}
@@ -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*) }
}
@@ -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 */
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
@@ -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-----
@@ -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
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEINSaX6nvzS3teiBJA7WlTLRKJOajpy29o2cArLbUXoZBoAoGCCqGSM49
AwEHoUQDQgAEm+ZIvTQ44aKk83DhVLsvsFpKDP/Ch9vA+4Hp+fmVfX6gDH8K1OBi
SpRf7FJ9RGPIn2H6xst+a1OtLMWUDRqGkQ==
-----END EC PRIVATE KEY-----
@@ -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
@@ -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:
@@ -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-----
@@ -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)
@@ -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();
}
}
@@ -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
@@ -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
@@ -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;
}
@@ -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.
*/
}
@@ -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 */
}
@@ -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);
}
@@ -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;
}
@@ -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>;
};
};
@@ -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 */
@@ -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 */
@@ -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
@@ -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
@@ -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;
}
@@ -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;
}
@@ -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.
*/
}
@@ -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 */
}
@@ -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);
}
@@ -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);
}
@@ -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 */
@@ -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
@@ -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);
}
@@ -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
@@ -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
@@ -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);
@@ -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);
@@ -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>;
};
@@ -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>;
};
};
};
@@ -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
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/dts-v1/;
/ {
};
@@ -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
};
@@ -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 */
};
};
@@ -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
@@ -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
};
@@ -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>;
};
@@ -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 */
};
};
};
@@ -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();
}
@@ -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 = &param_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
@@ -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;
}
@@ -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