aboutsummaryrefslogtreecommitdiff
path: root/plat/arm/board
diff options
context:
space:
mode:
Diffstat (limited to 'plat/arm/board')
-rw-r--r--plat/arm/board/a5ds/platform.mk11
-rw-r--r--plat/arm/board/arm_fpga/build_axf.ld.S12
-rw-r--r--plat/arm/board/arm_fpga/fpga_bl31_setup.c256
-rw-r--r--plat/arm/board/arm_fpga/fpga_gicv3.c92
-rw-r--r--plat/arm/board/arm_fpga/fpga_private.h3
-rw-r--r--plat/arm/board/arm_fpga/include/platform_def.h2
-rw-r--r--plat/arm/board/arm_fpga/kernel_trampoline.S35
-rw-r--r--plat/arm/board/arm_fpga/platform.mk17
-rw-r--r--plat/arm/board/fvp/fconf/fconf_hw_config_getter.c5
-rw-r--r--plat/arm/board/fvp/fdts/fvp_fw_config.dts4
-rw-r--r--plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts24
-rw-r--r--plat/arm/board/fvp/fdts/optee_sp_manifest.dts9
-rw-r--r--plat/arm/board/fvp/fvp_bl1_measured_boot.c44
-rw-r--r--plat/arm/board/fvp/fvp_bl1_setup.c57
-rw-r--r--plat/arm/board/fvp/fvp_bl2_measured_boot.c110
-rw-r--r--plat/arm/board/fvp/fvp_bl2_setup.c47
-rw-r--r--plat/arm/board/fvp/fvp_common.c16
-rw-r--r--plat/arm/board/fvp/fvp_common_measured_boot.c35
-rw-r--r--plat/arm/board/fvp/fvp_measured_boot.c38
-rw-r--r--plat/arm/board/fvp/fvp_pm.c24
-rw-r--r--plat/arm/board/fvp/include/platform_def.h51
-rw-r--r--plat/arm/board/fvp/platform.mk31
-rw-r--r--plat/arm/board/fvp/sp_min/sp_min-fvp.mk9
-rw-r--r--plat/arm/board/fvp/trp/trp-fvp.mk12
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c35
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S93
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S120
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_main.c268
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_setup.c247
-rw-r--r--plat/arm/board/fvp_r/fvp_r_common.c289
-rw-r--r--plat/arm/board/fvp_r/fvp_r_context_mgmt.c53
-rw-r--r--plat/arm/board/fvp_r/fvp_r_debug.S47
-rw-r--r--plat/arm/board/fvp_r/fvp_r_def.h103
-rw-r--r--plat/arm/board/fvp_r/fvp_r_err.c48
-rw-r--r--plat/arm/board/fvp_r/fvp_r_helpers.S128
-rw-r--r--plat/arm/board/fvp_r/fvp_r_io_storage.c105
-rw-r--r--plat/arm/board/fvp_r/fvp_r_misc_helpers.S32
-rw-r--r--plat/arm/board/fvp_r/fvp_r_private.h23
-rw-r--r--plat/arm/board/fvp_r/fvp_r_stack_protector.c24
-rw-r--r--plat/arm/board/fvp_r/fvp_r_trusted_boot.c73
-rw-r--r--plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h28
-rw-r--r--plat/arm/board/fvp_r/include/platform_def.h268
-rw-r--r--plat/arm/board/fvp_r/platform.mk99
-rw-r--r--plat/arm/board/fvp_ve/platform.mk11
-rw-r--r--plat/arm/board/juno/include/platform_def.h9
-rw-r--r--plat/arm/board/juno/platform.mk5
-rw-r--r--plat/arm/board/rdn2/platform.mk2
-rw-r--r--plat/arm/board/rdv1/platform.mk2
-rw-r--r--plat/arm/board/tc/fdts/tc_fw_config.dts4
-rw-r--r--plat/arm/board/tc/fdts/tc_spmc_manifest.dts7
-rw-r--r--plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts2
-rw-r--r--plat/arm/board/tc/fdts/tc_tb_fw_config.dts14
-rw-r--r--plat/arm/board/tc/include/platform_def.h25
-rw-r--r--plat/arm/board/tc/platform.mk15
-rw-r--r--plat/arm/board/tc/tc_bl2_setup.c47
-rw-r--r--plat/arm/board/tc/tc_bl31_setup.c20
-rw-r--r--plat/arm/board/tc/tc_plat.c3
57 files changed, 2911 insertions, 282 deletions
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index 8b0dc5cf3..4f873069a 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -1,18 +1,23 @@
#
-# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+# 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 \
- common/fdt_wrappers.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
diff --git a/plat/arm/board/arm_fpga/build_axf.ld.S b/plat/arm/board/arm_fpga/build_axf.ld.S
index d7cd00882..d8254e5b2 100644
--- a/plat/arm/board/arm_fpga/build_axf.ld.S
+++ b/plat/arm/board/arm_fpga/build_axf.ld.S
@@ -15,10 +15,11 @@
OUTPUT_FORMAT("elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
-INPUT(./bl31/bl31.elf)
INPUT(./rom_trampoline.o)
+INPUT(./kernel_trampoline.o)
TARGET(binary)
+INPUT(./bl31.bin)
INPUT(./fdts/arm_fpga.dtb)
ENTRY(_start)
@@ -32,8 +33,7 @@ SECTIONS
.bl31 (BL31_BASE): {
ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned");
- *bl31.elf(.text* .data* .rodata* ro* .bss*)
- *bl31.elf(.stack)
+ *bl31.bin
}
.dtb (FPGA_PRELOADED_DTB_BASE): {
@@ -41,6 +41,12 @@ SECTIONS
*arm_fpga.dtb
}
+ .kern_tramp (PRELOADED_BL33_BASE): {
+ *kernel_trampoline.o(.text*)
+ KEEP(*(.kern_tramp))
+ }
+
+ /DISCARD/ : { *(stacks) }
/DISCARD/ : { *(.debug_*) }
/DISCARD/ : { *(.note*) }
/DISCARD/ : { *(.comment*) }
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index a5f5ea0f3..e1b3abb28 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -13,6 +13,7 @@
#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"
@@ -20,6 +21,7 @@
#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)
@@ -118,18 +120,187 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
}
}
-unsigned int plat_get_syscnt_freq2(void)
+/*
+ * 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;
+ 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) {
- return FPGA_DEFAULT_TIMER_FREQUENCY;
+ WARN("%s(): No PL011 DT node found\n", __func__);
+
+ return;
}
- return fdt_read_uint32_default(fdt, node, "clock-frequency",
- FPGA_DEFAULT_TIMER_FREQUENCY);
+ 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)
@@ -144,56 +315,20 @@ static void fpga_prepare_dtb(void)
panic();
}
- /* Check for the command line signature. */
- if (!strncmp(cmdline, "CMD:", 4)) {
- int chosen;
-
- INFO("using command line at 0x%x\n", FPGA_PRELOADED_CMD_LINE);
+ /* 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");
+ }
- chosen = fdt_add_subnode(fdt, 0, "chosen");
- if (chosen == -FDT_ERR_EXISTS) {
- chosen = fdt_path_offset(fdt, "/chosen");
- }
- if (chosen < 0) {
- ERROR("cannot find /chosen node: %d\n", chosen);
+ /* 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 {
- const char *eol;
- char nul = 0;
- int slen;
-
- /*
- * 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) {
- eol = strchr(cmdline, 0);
- }
- /* Skip the signature and omit the EOL/NUL byte. */
- slen = eol - (cmdline + 4);
-
- /*
- * 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 + 4, slen);
- if (!err) {
- err = fdt_appendprop(fdt, chosen, "bootargs",
- &nul, 1);
- }
- if (err) {
- ERROR("Could not set command line: %d\n", err);
- }
+ ERROR("failed to put command line into DTB: %d\n", err);
}
}
@@ -218,13 +353,16 @@ static void fpga_prepare_dtb(void)
INFO("Adjusting GICR DT region to cover %u cores\n",
nr_cores);
err = fdt_adjust_gic_redist(fdt, nr_cores,
- 1U << GICR_PCPUBASE_SHIFT);
+ 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,
@@ -235,6 +373,16 @@ static void fpga_prepare_dtb(void)
}
}
+ /* 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);
diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c
index bfc116bef..e06a9da56 100644
--- a/plat/arm/board/arm_fpga/fpga_gicv3.c
+++ b/plat/arm/board/arm_fpga/fpga_gicv3.c
@@ -1,13 +1,15 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * 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/gicv3.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>
@@ -20,6 +22,7 @@ static const interrupt_prop_t fpga_interrupt_props[] = {
};
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)
{
@@ -37,6 +40,8 @@ static gicv3_driver_data_t fpga_gicv3_driver_data = {
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");
@@ -53,11 +58,66 @@ void plat_fpga_gic_init(void)
return;
}
- 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;
+ 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);
@@ -82,3 +142,21 @@ unsigned int fpga_get_nr_gic_cores(void)
{
return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base);
}
+
+uintptr_t fpga_get_redist_size(void)
+{
+ uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base +
+ GICR_TYPER);
+
+ return gicv3_redist_size(typer_val);
+}
+
+uintptr_t fpga_get_redist_base(void)
+{
+ return fpga_gicv3_driver_data.gicr_base;
+}
+
+bool fpga_has_its(void)
+{
+ return nr_itses > 0;
+}
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 1ca241f26..84d651cea 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -25,6 +25,9 @@ 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__ */
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index 411b936da..2350d8767 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -30,7 +30,7 @@
#if !ENABLE_PIE
#define BL31_BASE UL(0x80000000)
-#define BL31_LIMIT UL(0x80100000)
+#define BL31_LIMIT UL(0x80070000)
#else
#define BL31_BASE UL(0x0)
#define BL31_LIMIT UL(0x01000000)
diff --git a/plat/arm/board/arm_fpga/kernel_trampoline.S b/plat/arm/board/arm_fpga/kernel_trampoline.S
new file mode 100644
index 000000000..f4c08ef28
--- /dev/null
+++ b/plat/arm/board/arm_fpga/kernel_trampoline.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The traditional arm64 Linux kernel load address is 512KiB from the
+ * beginning of DRAM, caused by this having been the default value of the
+ * kernel's CONFIG_TEXT_OFFSET Kconfig value.
+ * However kernel version 5.8 changed the default offset (into a 2MB page)
+ * to 0, so TF-A's default assumption is no longer true. Fortunately the
+ * kernel got more relaxed about this offset at the same time, so it
+ * tolerates the wrong offset, but issues a warning:
+ * [Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!
+ *
+ * We cannot easily change the load address offset in TF-A to be 2MiB, because
+ * this would break older kernels - and they are not as forgiving in this
+ * respect.
+ *
+ * But we can allow users to load the kernel at the right offset, and
+ * offer this trampoline here to transition to this new load address.
+ * Any older kernels, or newer kernels misloaded, will overwrite this code
+ * here, so it does no harm in this case.
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.ld.h>
+
+.text
+.global _tramp_start
+
+_tramp_start:
+ adr x4, _tramp_start
+ orr x4, x4, #0x1fffff
+ add x4, x4, #1 /* align up to 2MB */
+ br x4
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index f80ea2fef..084532ce2 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include common/fdt_wrappers.mk
include lib/libfdt/libfdt.mk
RESET_TO_BL31 := 1
@@ -89,6 +90,8 @@ 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
@@ -102,8 +105,7 @@ 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_wrappers.c \
- common/fdt_fixup.c \
+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 \
@@ -115,11 +117,14 @@ BL31_SOURCES += common/fdt_wrappers.c \
${FPGA_CPU_LIBS} \
${FPGA_GIC_SOURCES}
-$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,31))
-$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,31))
+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}/build_axf.ld
+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 -o ${BUILD_PLAT}/bl31.axf
+ $(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf
all: bl31.axf
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index 35a777b6f..45e3b7eb2 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -5,6 +5,9 @@
*/
#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <fconf_hw_config_getter.h>
@@ -229,7 +232,7 @@ int fconf_populate_uart_config(uintptr_t config)
uart_serial_config.uart_base = translated_addr;
- VERBOSE("FCONF: UART serial device base address: %llx\n",
+ VERBOSE("FCONF: UART serial device base address: %" PRIx64 "\n",
uart_serial_config.uart_base);
/*
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index cad888f37..c26b51920 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -45,12 +45,10 @@
};
#endif
-#if !defined(SPD_spmd)
nt_fw-config {
load-address = <0x0 0x80000000>;
max-size = <0x200>;
id = <NT_FW_CONFIG_ID>;
};
-#endif
};
};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 62ab27c9d..cf4ef2d02 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <lib/libc/cdefs.h>
+
/dts-v1/;
/ {
@@ -24,19 +26,6 @@
*/
mbedtls_heap_addr = <0x0 0x0>;
mbedtls_heap_size = <0x0>;
-
-#if MEASURED_BOOT
- /* BL2 image hash calculated by BL1 */
- bl2_hash_data = [
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#if BL2_HASH_SIZE > 32
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#if BL2_HASH_SIZE > 48
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#endif /* > 48 */
-#endif /* > 32 */
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00];
-#endif /* MEASURED_BOOT */
};
/*
@@ -74,6 +63,10 @@
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";
@@ -104,12 +97,17 @@
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
diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index 07235b020..551efe69d 100644
--- a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -16,7 +16,7 @@
/* Properties */
description = "op-tee";
ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
- uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+ uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
id = <1>;
execution-ctx-count = <8>;
exception-level = <2>; /* S-EL1 */
@@ -25,8 +25,9 @@
entrypoint-offset = <0x1000>;
xlat-granule = <0>; /* 4KiB */
boot-order = <0>;
- messaging-method = <3>; /* Direct messaging only */
- run-time-model = <1>; /* Run to completion */
+ messaging-method = <0x3>; /* Direct request/response supported. */
+ managed-exit;
+ run-time-model = <1>; /* SP pre-emptible. */
/* Boot protocol */
gp-register-num = <0x0>;
diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
new file mode 100644
index 000000000..47af1f554
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log/event_log.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 },
+ { INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+void bl1_plat_mboot_init(void)
+{
+ event_log_init(event_log, event_log + sizeof(event_log));
+ event_log_write_header();
+}
+
+void bl1_plat_mboot_finish(void)
+{
+ size_t event_log_cur_size;
+
+ event_log_cur_size = event_log_get_cur_size(event_log);
+ int rc = arm_set_tb_fw_info((uintptr_t)event_log,
+ event_log_cur_size);
+ if (rc != 0) {
+ /*
+ * It is a fatal error because on FVP platform, BL2 software
+ * assumes that a valid Event Log buffer exist and it will use
+ * same Event Log buffer to append image measurements.
+ */
+ panic();
+ }
+}
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index 06ee037dc..59fc0f326 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -76,63 +76,6 @@ __dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
wfi();
}
-#if MEASURED_BOOT
-/*
- * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
- */
-void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
-{
- arm_bl1_set_bl2_hash(image_desc);
-}
-
-/*
- * Implementation for bl1_plat_handle_post_image_load(). This function
- * populates the default arguments to BL2. The BL2 memory layout structure
- * is allocated and the calculated layout is populated in arg1 to BL2.
- */
-int bl1_plat_handle_post_image_load(unsigned int image_id)
-{
- meminfo_t *bl2_tzram_layout;
- meminfo_t *bl1_tzram_layout;
- image_desc_t *image_desc;
- entry_point_info_t *ep_info;
-
- if (image_id != BL2_IMAGE_ID) {
- return 0;
- }
-
- /* Get the image descriptor */
- image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
- assert(image_desc != NULL);
-
- /* Calculate BL2 hash and set it in TB_FW_CONFIG */
- bl1_plat_set_bl2_hash(image_desc);
-
- /* Get the entry point info */
- ep_info = &image_desc->ep_info;
-
- /* Find out how much free trusted ram remains after BL1 load */
- bl1_tzram_layout = bl1_plat_sec_mem_layout();
-
- /*
- * Create a new layout of memory for BL2 as seen by BL1 i.e.
- * tell it the amount of total and free memory available.
- * This layout is created at the first free address visible
- * to BL2. BL2 will read the memory layout before using its
- * memory for other purposes.
- */
- bl2_tzram_layout = (meminfo_t *)bl1_tzram_layout->total_base;
-
- bl1_calc_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout);
-
- ep_info->args.arg1 = (uintptr_t)bl2_tzram_layout;
-
- VERBOSE("BL1: BL2 memory layout address = %p\n",
- (void *)bl2_tzram_layout);
- return 0;
-}
-#endif /* MEASURED_BOOT */
-
/*******************************************************************************
* The following function checks if Firmware update is needed by checking error
* reported in NV flag.
diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
new file mode 100644
index 000000000..5ebfedea0
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <plat/arm/common/plat_arm.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 },
+ { INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+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);
+}
+
+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;
+
+ event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
+
+ rc = arm_set_nt_fw_info(
+#ifdef SPD_opteed
+ (uintptr_t)event_log_base,
+#endif
+ event_log_cur_size, &ns_log_addr);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "NT");
+ /*
+ * It is a fatal error because on FVP secure world software
+ * assumes that a valid event log exists and will use it to
+ * record the measurements into the fTPM.
+ * Note: In FVP platform, OP-TEE uses nt_fw_config to get the
+ * secure Event Log buffer address.
+ */
+ panic();
+ }
+
+ /* Copy Event Log to Non-secure memory */
+ (void)memcpy((void *)ns_log_addr, (const void *)event_log_base,
+ event_log_cur_size);
+
+ /* Ensure that the Event Log is visible in Non-secure memory */
+ flush_dcache_range(ns_log_addr, event_log_cur_size);
+
+#if defined(SPD_tspd) || defined(SPD_spmd)
+ /* Set Event Log data in TOS_FW_CONFIG */
+ rc = arm_set_tos_fw_info((uintptr_t)event_log_base,
+ event_log_cur_size);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "TOS");
+ panic();
+ }
+#endif /* defined(SPD_tspd) || defined(SPD_spmd) */
+
+ dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
+}
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index f2f21432d..5a17a0dca 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,9 +9,6 @@
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/arm/sp804_delay_timer.h>
-#if MEASURED_BOOT
-#include <drivers/measured_boot/measured_boot.h>
-#endif
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
@@ -73,45 +70,3 @@ struct bl_params *plat_get_next_bl_params(void)
return arm_bl_params;
}
-#if MEASURED_BOOT
-static int fvp_bl2_plat_handle_post_image_load(unsigned int image_id)
-{
- const bl_mem_params_node_t *bl_mem_params =
- get_bl_mem_params_node(image_id);
-
- assert(bl_mem_params != NULL);
-
- image_info_t info = bl_mem_params->image_info;
- int err;
-
- if ((info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U) {
- /* Calculate image hash and record data in Event Log */
- err = tpm_record_measurement(info.image_base,
- info.image_size, image_id);
- if (err != 0) {
- ERROR("%s%s image id %u (%i)\n",
- "BL2: Failed to ", "record", image_id, err);
- return err;
- }
- }
-
- err = arm_bl2_handle_post_image_load(image_id);
- if (err != 0) {
- ERROR("%s%s image id %u (%i)\n",
- "BL2: Failed to ", "handle", image_id, err);
- }
-
- return err;
-}
-
-int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
-{
- int err = fvp_bl2_plat_handle_post_image_load(image_id);
-
- if (err != 0) {
- ERROR("%s() returns %i\n", __func__, err);
- }
-
- return err;
-}
-#endif /* MEASURED_BOOT */
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 9d3c03133..e7a28ac35 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -107,6 +107,10 @@ const mmap_region_t plat_arm_mmap[] = {
#if defined(SPD_spmd)
ARM_MAP_TRUSTED_DRAM,
#endif
+#if ENABLE_RME
+ ARM_MAP_RMM_DRAM,
+ ARM_MAP_GPT_L1_DRAM,
+#endif /* ENABLE_RME */
#ifdef SPD_tspd
ARM_MAP_TSP_SEC_MEM,
#endif
@@ -159,6 +163,9 @@ const mmap_region_t plat_arm_mmap[] = {
#endif
/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
ARM_DTB_DRAM_NS,
+#if ENABLE_RME
+ ARM_MAP_GPT_L1_DRAM,
+#endif
{0}
};
@@ -191,6 +198,15 @@ const mmap_region_t plat_arm_mmap[] = {
};
#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
diff --git a/plat/arm/board/fvp/fvp_common_measured_boot.c b/plat/arm/board/fvp/fvp_common_measured_boot.c
new file mode 100644
index 000000000..6a403d945
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_common_measured_boot.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, 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 <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+extern event_log_metadata_t fvp_event_log_metadata[];
+
+const event_log_metadata_t *plat_event_log_get_metadata(void)
+{
+ return fvp_event_log_metadata;
+}
+
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
+{
+ /* Calculate image hash and record data in Event Log */
+ int 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", image_id, err);
+ return err;
+ }
+
+ return 0;
+}
diff --git a/plat/arm/board/fvp/fvp_measured_boot.c b/plat/arm/board/fvp/fvp_measured_boot.c
deleted file mode 100644
index 5dcadba36..000000000
--- a/plat/arm/board/fvp/fvp_measured_boot.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <drivers/measured_boot/event_log.h>
-#include <plat/arm/common/plat_arm.h>
-
-/* FVP table with platform specific image IDs, names and PCRs */
-static const image_data_t fvp_images_data[] = {
- { BL2_IMAGE_ID, BL2_STRING, PCR_0 }, /* Reserved for BL2 */
- { BL31_IMAGE_ID, BL31_STRING, PCR_0 },
- { BL32_IMAGE_ID, BL32_STRING, PCR_0 },
- { BL32_EXTRA1_IMAGE_ID, BL32_EXTRA1_IMAGE_STRING, PCR_0 },
- { BL32_EXTRA2_IMAGE_ID, BL32_EXTRA2_IMAGE_STRING, PCR_0 },
- { BL33_IMAGE_ID, BL33_STRING, PCR_0 },
- { HW_CONFIG_ID, HW_CONFIG_STRING, PCR_0 },
- { NT_FW_CONFIG_ID, NT_FW_CONFIG_STRING, PCR_0 },
- { SCP_BL2_IMAGE_ID, SCP_BL2_IMAGE_STRING, PCR_0 },
- { SOC_FW_CONFIG_ID, SOC_FW_CONFIG_STRING, PCR_0 },
- { TOS_FW_CONFIG_ID, TOS_FW_CONFIG_STRING, PCR_0 },
- { INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
-};
-
-static const measured_boot_data_t fvp_measured_boot_data = {
- fvp_images_data,
- arm_set_nt_fw_info,
- arm_set_tos_fw_info
-};
-
-/*
- * Function retuns pointer to FVP plat_measured_boot_data_t structure
- */
-const measured_boot_data_t *plat_get_measured_boot_data(void)
-{
- return &fvp_measured_boot_data;
-}
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 333d89288..6b9d6184c 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -138,21 +138,37 @@ static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_s
fvp_pwrc_clr_wen(mpidr);
}
-
/*******************************************************************************
* FVP handler called when a CPU is about to enter standby.
******************************************************************************/
static void fvp_cpu_standby(plat_local_state_t cpu_state)
{
+ u_register_t scr = read_scr_el3();
assert(cpu_state == ARM_LOCAL_STATE_RET);
/*
- * Enter standby state
- * dsb is good practice before using wfi to enter low power states
+ * Enable the Non-secure interrupt to wake the CPU.
+ * In GICv3 affinity routing mode, the Non-secure Group 1 interrupts
+ * use Physical FIQ at EL3 whereas in GICv2, Physical IRQ is used.
+ * Enabling both the bits works for both GICv2 mode and GICv3 affinity
+ * routing mode.
+ */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+ isb();
+
+ /*
+ * Enter standby state.
+ * dsb is good practice before using wfi to enter low power states.
*/
dsb();
wfi();
+
+ /*
+ * Restore SCR_EL3 to the original value, synchronisation of SCR_EL3
+ * is done by eret in el3_exit() to save some execution cycles.
+ */
+ write_scr_el3(scr);
}
/*******************************************************************************
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 8b25a5463..d89e122c8 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -43,6 +43,11 @@
#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x06000000)
#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */
+#if ENABLE_RME
+#define PLAT_ARM_RMM_BASE (RMM_BASE)
+#define PLAT_ARM_RMM_SIZE (RMM_LIMIT - RMM_BASE)
+#endif
+
/*
* Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to
* max size of BL32 image.
@@ -61,12 +66,13 @@
#define PLAT_ARM_DRAM2_BASE ULL(0x880000000)
#define PLAT_ARM_DRAM2_SIZE UL(0x80000000)
-#define PLAT_HW_CONFIG_DTB_BASE ULL(0x82000000)
-#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
+/* Range of kernel DTB load address */
+#define FVP_DTB_DRAM_MAP_START ULL(0x82000000)
+#define FVP_DTB_DRAM_MAP_SIZE ULL(0x02000000) /* 32 MB */
#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
- PLAT_HW_CONFIG_DTB_BASE, \
- PLAT_HW_CONFIG_DTB_SIZE, \
+ FVP_DTB_DRAM_MAP_START, \
+ FVP_DTB_DRAM_MAP_SIZE, \
MT_MEMORY | MT_RO | MT_NS)
/*
* Load address of BL33 for this platform port
@@ -80,15 +86,27 @@
#if defined(IMAGE_BL31)
# if SPM_MM
# define PLAT_ARM_MMAP_ENTRIES 10
-# define MAX_XLAT_TABLES 9
+# if ENABLE_RME
+# define MAX_XLAT_TABLES 10
+# else
+# define MAX_XLAT_TABLES 9
+# endif
# define PLAT_SP_IMAGE_MMAP_REGIONS 30
# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
# else
# define PLAT_ARM_MMAP_ENTRIES 9
# if USE_DEBUGFS
-# define MAX_XLAT_TABLES 8
+# if ENABLE_RME
+# define MAX_XLAT_TABLES 9
+# else
+# define MAX_XLAT_TABLES 8
+# endif
# else
-# define MAX_XLAT_TABLES 7
+# if ENABLE_RME
+# define MAX_XLAT_TABLES 8
+# else
+# define MAX_XLAT_TABLES 7
+# endif
# endif
# endif
#elif defined(IMAGE_BL32)
@@ -137,16 +155,17 @@
#endif
#if RESET_TO_BL31
-/* Size of Trusted SRAM - the first 4KB of shared memory */
+/* Size of Trusted SRAM - the first 4KB of shared memory - GPT L0 Tables */
#define PLAT_ARM_MAX_BL31_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
- ARM_SHARED_RAM_SIZE)
+ ARM_SHARED_RAM_SIZE - \
+ ARM_L0_GPT_SIZE)
#else
/*
* Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
* calculated using the current BL31 PROGBITS debug size plus the sizes of
* BL2 and BL1-RW
*/
-#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000)
+#define PLAT_ARM_MAX_BL31_SIZE (UL(0x3D000) - ARM_L0_GPT_SIZE)
#endif /* RESET_TO_BL31 */
#ifndef __aarch64__
@@ -177,7 +196,7 @@
# if TRUSTED_BOARD_BOOT
# define PLATFORM_STACK_SIZE UL(0x1000)
# else
-# define PLATFORM_STACK_SIZE UL(0x440)
+# define PLATFORM_STACK_SIZE UL(0x600)
# endif
#elif defined(IMAGE_BL2U)
# define PLATFORM_STACK_SIZE UL(0x400)
@@ -185,6 +204,8 @@
# define PLATFORM_STACK_SIZE UL(0x800)
#elif defined(IMAGE_BL32)
# define PLATFORM_STACK_SIZE UL(0x440)
+#elif defined(IMAGE_RMM)
+# define PLATFORM_STACK_SIZE UL(0x440)
#endif
#define MAX_IO_DEVICES 3
@@ -222,6 +243,9 @@
#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE
#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ
+#define PLAT_ARM_TRP_UART_BASE V2M_IOFPGA_UART3_BASE
+#define PLAT_ARM_TRP_UART_CLK_IN_HZ V2M_IOFPGA_UART3_CLK_IN_HZ
+
#define PLAT_FVP_SMMUV3_BASE UL(0x2b400000)
/* CCI related constants */
@@ -317,4 +341,9 @@
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
#endif
+/*
+ * Maximum size of Event Log buffer used in Measured Boot Event Log driver
+ */
+#define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x400)
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 3c70eede3..0d2c31971 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -4,6 +4,8 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include common/fdt_wrappers.mk
+
# Use the GICv3 driver on the FVP by default
FVP_USE_GIC_DRIVER := FVP_GICV3
@@ -130,15 +132,17 @@ else
lib/cpus/aarch64/neoverse_n2.S \
lib/cpus/aarch64/neoverse_e1.S \
lib/cpus/aarch64/neoverse_v1.S \
+ lib/cpus/aarch64/neoverse_demeter.S \
lib/cpus/aarch64/cortex_a78_ae.S \
lib/cpus/aarch64/cortex_a510.S \
lib/cpus/aarch64/cortex_a710.S \
lib/cpus/aarch64/cortex_makalu.S \
lib/cpus/aarch64/cortex_makalu_elp_arm.S \
- lib/cpus/aarch64/cortex_demeter.S \
lib/cpus/aarch64/cortex_a65.S \
lib/cpus/aarch64/cortex_a65ae.S \
- lib/cpus/aarch64/cortex_a78c.S
+ lib/cpus/aarch64/cortex_a78c.S \
+ lib/cpus/aarch64/cortex_hayes.S \
+ lib/cpus/aarch64/cortex_hunter.S
endif
# AArch64/AArch32 cores
FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \
@@ -185,6 +189,10 @@ ifeq (${COT_DESC_IN_DTB},1)
BL2_SOURCES += plat/arm/common/fconf/fconf_nv_cntr_getter.c
endif
+ifeq (${ENABLE_RME},1)
+BL2_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S
+endif
+
ifeq (${BL2_AT_EL3},1)
BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
plat/arm/board/fvp/fvp_bl2_el3_setup.c \
@@ -222,11 +230,12 @@ BL31_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
# Support for fconf in BL31
# Added separately from the above list for better readability
ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),)
-BL31_SOURCES += common/fdt_wrappers.c \
- lib/fconf/fconf.c \
+BL31_SOURCES += lib/fconf/fconf.c \
lib/fconf/fconf_dyn_cfg_getter.c \
plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
ifeq (${SEC_INT_DESC_IN_FCONF},1)
BL31_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c
endif
@@ -371,10 +380,22 @@ BL1_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c
BL2_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c
ifeq (${MEASURED_BOOT},1)
-BL2_SOURCES += plat/arm/board/fvp/fvp_measured_boot.c
+BL1_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
+ plat/arm/board/fvp/fvp_bl1_measured_boot.c
+BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
+ plat/arm/board/fvp/fvp_bl2_measured_boot.c
endif
# FVP being a development platform, enable capability to disable Authentication
# dynamically if TRUSTED_BOARD_BOOT is set.
DYN_DISABLE_AUTH := 1
endif
+
+# enable trace buffer control registers access to NS by default
+ENABLE_TRBE_FOR_NS := 1
+
+# enable trace system registers access to NS by default
+ENABLE_SYS_REG_TRACE_FOR_NS := 1
+
+# enable trace filter control registers access to NS by default
+ENABLE_TRF_FOR_NS := 1
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
index 64cb7add5..0d8cca597 100644
--- a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -1,9 +1,11 @@
#
-# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
+include common/fdt_wrappers.mk
+
# SP_MIN source files specific to FVP platform
BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
drivers/cfi/v2m/v2m_flash.c \
@@ -22,10 +24,11 @@ BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
# Support for fconf in SP_MIN(BL32)
# Added separately from the above list for better readability
ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),)
-BL32_SOURCES += common/fdt_wrappers.c \
- lib/fconf/fconf.c \
+BL32_SOURCES += lib/fconf/fconf.c \
plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+BL32_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
ifeq (${SEC_INT_DESC_IN_FCONF},1)
BL32_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c
endif
diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk
new file mode 100644
index 000000000..a450541d3
--- /dev/null
+++ b/plat/arm/board/fvp/trp/trp-fvp.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files specific to FVP platform
+
+RMM_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S
+
+include plat/arm/common/trp/arm_trp.mk
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
new file mode 100644
index 000000000..ae6af6c08
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch.h>
+
+#include <fvp_r_arch_helpers.h>
+
+/*******************************************************************************
+ * Function that does the first bit of architectural setup that affects
+ * execution in the non-secure address space.
+ ******************************************************************************/
+void bl1_arch_setup(void)
+{
+ /* v8-R64 does not include SCRs. */
+}
+
+/*******************************************************************************
+ * Set the Secure EL1 required architectural state
+ ******************************************************************************/
+void bl1_arch_next_el_setup(void)
+{
+ u_register_t next_sctlr;
+
+ /* Use the same endianness than the current BL */
+ next_sctlr = (read_sctlr_el2() & SCTLR_EE_BIT);
+
+ /* Set SCTLR Secure EL1 */
+ next_sctlr |= SCTLR_EL1_RES1;
+
+ write_sctlr_el1(next_sctlr);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
new file mode 100644
index 000000000..15f4c4349
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <el2_common_macros.S>
+#include <lib/xlat_mpu/xlat_mpu.h>
+
+ .globl bl1_entrypoint
+ .globl bl1_run_next_image
+
+
+ /* -----------------------------------------------------
+ * bl1_entrypoint() is the entry point into the trusted
+ * firmware code when a cpu is released from warm or
+ * cold reset.
+ * -----------------------------------------------------
+ */
+
+func bl1_entrypoint
+ /* ---------------------------------------------------------------------
+ * If the reset address is programmable then bl1_entrypoint() is
+ * executed only on the cold boot path. Therefore, we can skip the warm
+ * boot mailbox mechanism.
+ * ---------------------------------------------------------------------
+ */
+ el2_entrypoint_common \
+ _init_sctlr=1 \
+ _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
+ _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
+ _init_memory=1 \
+ _init_c_runtime=1 \
+ _exception_vectors=bl1_exceptions \
+ _pie_fixup_size=0
+
+ /* --------------------------------------------------------------------
+ * Perform BL1 setup
+ * --------------------------------------------------------------------
+ */
+ bl bl1_setup
+
+ /* --------------------------------------------------------------------
+ * Initialize platform and jump to our c-entry point
+ * for this type of reset.
+ * --------------------------------------------------------------------
+ */
+ bl bl1_main
+
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ no_ret plat_panic_handler
+endfunc bl1_entrypoint
+
+func bl1_run_next_image
+ mov x20,x0
+
+ /* ---------------------------------------------
+ * MPU needs to be disabled because both BL1 and BL33 execute
+ * in EL2, and therefore share the same address space.
+ * BL33 will initialize the address space according to its
+ * own requirement.
+ * ---------------------------------------------
+ */
+ bl disable_mpu_icache_el2
+
+ /* ---------------------------------------------
+ * Wipe clean and disable all MPU regions. This function expects
+ * that the MPU has already been turned off, and caching concerns
+ * addressed, but it also explicitly turns off the MPU.
+ * ---------------------------------------------
+ */
+ bl clear_all_mpu_regions
+
+ /* --------------------------------------------------
+ * Do the transition to next boot image.
+ * --------------------------------------------------
+ */
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el2, x0
+ msr spsr_el2, x1
+
+ ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
+ ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
+ ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
+ ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
+ exception_return
+endfunc bl1_run_next_image
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
new file mode 100644
index 000000000..43c2e01a2
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <context.h>
+
+/* -----------------------------------------------------------------------------
+ * File contains an EL2 equivalent of the EL3 vector table from:
+ * .../bl1/aarch64/bl1_exceptions.S
+ * -----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------
+ * Very simple stackless exception handlers used by BL1.
+ * -----------------------------------------------------------------------------
+ */
+ .globl bl1_exceptions
+
+vector_base bl1_exceptions
+
+ /* -----------------------------------------------------
+ * Current EL with SP0 : 0x0 - 0x200
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionSP0
+ mov x0, #SYNC_EXCEPTION_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SynchronousExceptionSP0
+
+vector_entry IrqSP0
+ mov x0, #IRQ_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry IrqSP0
+
+vector_entry FiqSP0
+ mov x0, #FIQ_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry FiqSP0
+
+vector_entry SErrorSP0
+ mov x0, #SERROR_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SErrorSP0
+
+ /* -----------------------------------------------------
+ * Current EL with SPx: 0x200 - 0x400
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionSPx
+ mov x0, #SYNC_EXCEPTION_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SynchronousExceptionSPx
+
+vector_entry IrqSPx
+ mov x0, #IRQ_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry IrqSPx
+
+vector_entry FiqSPx
+ mov x0, #FIQ_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry FiqSPx
+
+vector_entry SErrorSPx
+ mov x0, #SERROR_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SErrorSPx
+
+ /* -----------------------------------------------------
+ * Lower EL using AArch64 : 0x400 - 0x600
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionA64
+ /* The current v8-R64 implementation does not support conduit calls */
+ b el2_panic
+end_vector_entry SynchronousExceptionA64
+
+vector_entry IrqA64
+ mov x0, #IRQ_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry IrqA64
+
+vector_entry FiqA64
+ mov x0, #FIQ_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry FiqA64
+
+vector_entry SErrorA64
+ mov x0, #SERROR_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SErrorA64
+
+
+unexpected_sync_exception:
+ mov x0, #SYNC_EXCEPTION_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+
+ /* -----------------------------------------------------
+ * Save Secure/Normal world context and jump to
+ * BL1 SMC handler.
+ * -----------------------------------------------------
+ */
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
new file mode 100644
index 000000000..841a1769a
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/auth_mod.h>
+#include <drivers/console.h>
+#include <lib/cpus/errata_report.h>
+#include <lib/utils.h>
+#include <smccc_helpers.h>
+#include <tools_share/uuid.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+
+void cm_prepare_el2_exit(void);
+
+void bl1_run_next_image(const struct entry_point_info *bl_ep_info);
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
+void bl1_transfer_bl33(void)
+{
+ unsigned int image_id;
+
+ /* Get the image id of next image to load and run. */
+ image_id = bl1_plat_get_next_image_id();
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Disable watchdog before leaving BL1 */
+ plat_arm_secure_wdt_stop();
+#endif
+
+ bl1_run_next_image(&bl1_plat_get_image_desc(image_id)->ep_info);
+}
+
+/*******************************************************************************
+ * This function locates and loads the BL33 raw binary image in the trusted SRAM.
+ * Called by the primary cpu after a cold boot.
+ * TODO: Add support for alternative image load mechanism e.g using virtio/elf
+ * loader etc.
+ ******************************************************************************/
+void bl1_load_bl33(void)
+{
+ image_desc_t *desc;
+ image_info_t *info;
+ int err;
+
+ /* Get the image descriptor */
+ desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+ assert(desc != NULL);
+
+ /* Get the image info */
+ info = &desc->image_info;
+ INFO("BL1: Loading BL33\n");
+
+ err = bl1_plat_handle_pre_image_load(BL33_IMAGE_ID);
+ if (err != 0) {
+ ERROR("Failure in pre image load handling of BL33 (%d)\n", err);
+ plat_error_handler(err);
+ }
+
+ err = load_auth_image(BL33_IMAGE_ID, info);
+ if (err != 0) {
+ ERROR("Failed to load BL33 firmware.\n");
+ plat_error_handler(err);
+ }
+
+ /* Allow platform to handle image information. */
+ err = bl1_plat_handle_post_image_load(BL33_IMAGE_ID);
+ if (err != 0) {
+ ERROR("Failure in post image load handling of BL33 (%d)\n", err);
+ plat_error_handler(err);
+ }
+
+ NOTICE("BL1: Booting BL33\n");
+}
+
+/*******************************************************************************
+ * Helper utility to calculate the BL2 memory layout taking into consideration
+ * the BL1 RW data assuming that it is at the top of the memory layout.
+ ******************************************************************************/
+void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
+ meminfo_t *bl2_mem_layout)
+{
+ assert(bl1_mem_layout != NULL);
+ assert(bl2_mem_layout != NULL);
+
+ /*
+ * Remove BL1 RW data from the scope of memory visible to BL2.
+ * This is assuming BL1 RW data is at the top of bl1_mem_layout.
+ */
+ assert(bl1_mem_layout->total_base < BL1_RW_BASE);
+ bl2_mem_layout->total_base = bl1_mem_layout->total_base;
+ bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
+
+ flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t));
+}
+
+/*******************************************************************************
+ * This function prepares for entry to BL33
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+ unsigned int mode = MODE_EL1;
+ image_desc_t *desc;
+ entry_point_info_t *next_bl_ep;
+
+#if CTX_INCLUDE_AARCH32_REGS
+ /*
+ * Ensure that the build flag to save AArch32 system registers in CPU
+ * context is not set for AArch64-only platforms.
+ */
+ if (el_implemented(1) == EL_IMPL_A64ONLY) {
+ ERROR("EL1 supports AArch64-only. Please set build flag %s",
+ "CTX_INCLUDE_AARCH32_REGS = 0\n");
+ panic();
+ }
+#endif
+
+ /* Get the image descriptor. */
+ desc = bl1_plat_get_image_desc(image_id);
+ assert(desc != NULL);
+
+ /* Get the entry point info. */
+ next_bl_ep = &desc->ep_info;
+
+ /* FVP-R is only secure */
+ assert(GET_SECURITY_STATE(next_bl_ep->h.attr) == SECURE);
+
+ /* Prepare the SPSR for the next BL image. */
+ next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
+ (uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+
+ /* Allow platform to make change */
+ bl1_plat_set_ep_info(image_id, next_bl_ep);
+
+ /* Prepare context for the next EL */
+ cm_prepare_el2_exit();
+
+ /* Indicate that image is in execution state. */
+ desc->state = IMAGE_STATE_EXECUTED;
+
+ print_entry_point_info(next_bl_ep);
+}
+
+/*******************************************************************************
+ * Setup function for BL1.
+ ******************************************************************************/
+void bl1_setup(void)
+{
+ /* Perform early platform-specific setup */
+ bl1_early_platform_setup();
+
+ /* Perform late platform-specific setup */
+ bl1_plat_arch_setup();
+}
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
+void bl1_main(void)
+{
+ unsigned int image_id;
+
+ /* Announce our arrival */
+ NOTICE(FIRMWARE_WELCOME_STR);
+ NOTICE("BL1: %s\n", version_string);
+ NOTICE("BL1: %s\n", build_message);
+
+ INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT);
+
+ print_errata_status();
+
+#if ENABLE_ASSERTIONS
+ u_register_t val;
+ /*
+ * Ensure that MMU/Caches and coherency are turned on
+ */
+ val = read_sctlr_el2();
+
+ assert((val & SCTLR_M_BIT) != 0U);
+ assert((val & SCTLR_C_BIT) != 0U);
+ assert((val & SCTLR_I_BIT) != 0U);
+ /*
+ * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
+ * provided platform value
+ */
+ val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
+ /*
+ * If CWG is zero, then no CWG information is available but we can
+ * at least check the platform value is less than the architectural
+ * maximum.
+ */
+ if (val != 0) {
+ assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE);
+ } else {
+ assert(MAX_CACHE_LINE_SIZE >= CACHE_WRITEBACK_GRANULE);
+ }
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Perform remaining generic architectural setup from ELmax */
+ bl1_arch_setup();
+
+#if TRUSTED_BOARD_BOOT
+ /* Initialize authentication module */
+ auth_mod_init();
+#endif /* TRUSTED_BOARD_BOOT */
+
+ /* Perform platform setup in BL1. */
+ bl1_platform_setup();
+
+ /* Get the image id of next image to load and run. */
+ image_id = bl1_plat_get_next_image_id();
+
+ /*
+ * We currently interpret any image id other than
+ * BL2_IMAGE_ID as the start of firmware update.
+ */
+ if (image_id == BL33_IMAGE_ID) {
+ bl1_load_bl33();
+ } else {
+ NOTICE("BL1-FWU: *******FWU Process Started*******\n");
+ }
+
+ bl1_prepare_next_image(image_id);
+
+ console_flush();
+
+ bl1_transfer_bl33();
+}
+
+/*******************************************************************************
+ * Function called just before handing over to the next BL to inform the user
+ * about the boot progress. In debug mode, also print details about the BL
+ * image's execution context.
+ ******************************************************************************/
+void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
+{
+ NOTICE("BL1: Booting BL31\n");
+ print_entry_point_info(bl_ep_info);
+}
+
+#if SPIN_ON_BL1_EXIT
+void print_debug_loop_message(void)
+{
+ NOTICE("BL1: Debug loop, spinning forever\n");
+ NOTICE("BL1: Please connect the debugger to continue\n");
+}
+#endif
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
new file mode 100644
index 000000000..68872c111
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Use the xlat_tables_v2 data structures: */
+#define XLAT_TABLES_LIB_V2 1
+
+#include <assert.h>
+
+#include <bl1/bl1.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/sp805.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/xlat_mpu/xlat_mpu.h>
+
+#include "fvp_r_private.h"
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#define MAP_BL1_TOTAL MAP_REGION_FLAT( \
+ bl1_tzram_layout.total_base, \
+ bl1_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+/*
+ * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
+ * otherwise one region is defined containing both
+ */
+#if SEPARATE_CODE_AND_RODATA
+#define MAP_BL1_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL1_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE), \
+ MAP_REGION_FLAT( \
+ BL1_RO_DATA_BASE, \
+ BL1_RO_DATA_END \
+ - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+#else
+#define MAP_BL1_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL1_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+#endif
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+struct meminfo *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+void arm_bl1_early_platform_setup(void)
+{
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Enable watchdog */
+ plat_arm_secure_wdt_start();
+#endif
+
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
+ bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE;
+}
+
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ arm_bl1_early_platform_setup();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+ /*
+ * Enable coherency in Interconnect for the primary CPU's cluster.
+ */
+ fvp_interconnect_enable();
+}
+
+void arm_bl1_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL1_TOTAL,
+ MAP_BL1_RO,
+#if USE_ROMLIB
+ ARM_MAP_ROMLIB_CODE,
+ ARM_MAP_ROMLIB_DATA,
+#endif
+#if ARM_CRYPTOCELL_INTEG
+ ARM_MAP_BL_COHERENT_RAM,
+#endif
+ /* DRAM1_region: */
+ MAP_REGION_FLAT( \
+ PLAT_ARM_DRAM1_BASE, \
+ PLAT_ARM_DRAM1_SIZE, \
+ MT_MEMORY | MT_SECURE | MT_EXECUTE \
+ | MT_RW | MT_NON_CACHEABLE),
+ /* NULL terminator: */
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+ enable_mpu_el2(0);
+
+ arm_setup_romlib();
+}
+
+void plat_arm_secure_wdt_start(void)
+{
+ sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sp805_stop(ARM_SP805_TWDG_BASE);
+}
+
+/*
+ * Perform the platform specific architecture setup shared between
+ * ARM standard platforms.
+ */
+void arm_bl1_platform_setup(void)
+{
+ uint32_t fw_config_max_size;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_arm_io_setup();
+
+ /* Check if we need FWU before further processing */
+ is_fwu_needed = plat_arm_bl1_fwu_needed();
+ if (is_fwu_needed) {
+ ERROR("Skip platform setup as FWU detected\n");
+ return;
+ }
+
+ /* Set global DTB info for fixed fw_config information */
+ fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
+ set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID);
+
+ assert(bl1_plat_get_image_desc(BL33_IMAGE_ID) != NULL);
+
+ /*
+ * Allow access to the System counter timer module and program
+ * counter frequency for non secure images during FWU
+ */
+#ifdef ARM_SYS_TIMCTL_BASE
+ arm_configure_sys_timer();
+#endif
+#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+#endif
+}
+
+void bl1_platform_setup(void)
+{
+ arm_bl1_platform_setup();
+
+ /* Initialize System level generic or SP804 timer */
+ fvp_timer_init();
+}
+
+__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
+{
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ while (true) {
+ wfi();
+ }
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL33_IMAGE_ID;
+}
+
+/*
+ * Returns BL33 image details.
+ */
+struct image_desc *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ static image_desc_t bl33_img_desc = BL33_IMAGE_DESC;
+
+ return &bl33_img_desc;
+}
+
+/*
+ * This function populates the default arguments to BL33.
+ * The BL33 memory layout structure is allocated and the
+ * calculated layout is populated in arg1 to BL33.
+ */
+int bl1_plat_handle_post_image_load(unsigned int image_id)
+{
+ meminfo_t *bl33_secram_layout;
+ meminfo_t *bl1_secram_layout;
+ image_desc_t *image_desc;
+ entry_point_info_t *ep_info;
+
+ if (image_id != BL33_IMAGE_ID) {
+ return 0;
+ }
+ /* Get the image descriptor */
+ image_desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+ assert(image_desc != NULL);
+
+ /* Get the entry point info */
+ ep_info = &image_desc->ep_info;
+
+ /* Find out how much free trusted ram remains after BL1 load */
+ bl1_secram_layout = bl1_plat_sec_mem_layout();
+
+ /*
+ * Create a new layout of memory for BL33 as seen by BL1 i.e.
+ * tell it the amount of total and free memory available.
+ * This layout is created at the first free address visible
+ * to BL33. BL33 will read the memory layout before using its
+ * memory for other purposes.
+ */
+ bl33_secram_layout = (meminfo_t *) bl1_secram_layout->total_base;
+
+ bl1_calc_bl2_mem_layout(bl1_secram_layout, bl33_secram_layout);
+
+ ep_info->args.arg1 = (uintptr_t)bl33_secram_layout;
+
+ VERBOSE("BL1: BL3 memory layout address = %p\n",
+ (void *) bl33_secram_layout);
+ return 0;
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_common.c b/plat/arm/board/fvp_r/fvp_r_common.c
new file mode 100644
index 000000000..edcf658b5
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_common.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */
+#define XLAT_TABLES_LIB_V2 1
+
+#include <assert.h>
+#include <common/debug.h>
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
+
+#include "fvp_r_private.h"
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+/* Defines for GIC Driver build time selection */
+#define FVP_R_GICV3 2
+
+/*******************************************************************************
+ * arm_config holds the characteristics of the differences between the FVP_R
+ * platforms. It will be populated during cold boot at each boot stage by the
+ * primary before enabling the MPU (to allow interconnect configuration) &
+ * used thereafter. Each BL will have its own copy to allow independent
+ * operation.
+ ******************************************************************************/
+arm_config_t arm_config;
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
+ DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Need to be mapped with write permissions in order to set a new non-volatile
+ * counter value.
+ */
+#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \
+ DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of memory regions for various BL stages to map using the MPU.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
+ *
+ * The flash needs to be mapped as writable in order to erase the FIP's Table of
+ * Contents in case of unrecoverable error (see plat_error_handler()).
+ */
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH0_RW,
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+ MAP_DEVICE1,
+#if TRUSTED_BOARD_BOOT
+ /* To access the Root of Trust Public Key registers. */
+ MAP_DEVICE2,
+#endif
+ {0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+static const int fvp_cci400_map[] = {
+ PLAT_FVP_R_CCI400_CLUS0_SL_PORT,
+ PLAT_FVP_R_CCI400_CLUS1_SL_PORT,
+};
+
+static const int fvp_cci5xx_map[] = {
+ PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT,
+ PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT,
+};
+
+static unsigned int get_interconnect_master(void)
+{
+ unsigned int master;
+ u_register_t mpidr;
+
+ mpidr = read_mpidr_el1();
+ master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
+ MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);
+
+ assert(master < FVP_R_CLUSTER_COUNT);
+ return master;
+}
+
+/*******************************************************************************
+ * Initialize the platform config for future decision making
+ ******************************************************************************/
+void __init fvp_config_setup(void)
+{
+ unsigned int rev, hbi, bld, arch, sys_id;
+
+ arm_config.flags |= ARM_CONFIG_BASE_MMAP;
+ sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID);
+ rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
+ hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
+ bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
+ arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
+
+ if (arch != ARCH_MODEL) {
+ ERROR("This firmware is for FVP_R models\n");
+ panic();
+ }
+
+ /*
+ * The build field in the SYS_ID tells which variant of the GIC
+ * memory is implemented by the model.
+ */
+ switch (bld) {
+ case BLD_GIC_VE_MMAP:
+ ERROR("Legacy Versatile Express memory map for GIC %s",
+ "peripheral is not supported\n");
+ panic();
+ break;
+ case BLD_GIC_A53A57_MMAP:
+ break;
+ default:
+ ERROR("Unsupported board build %x\n", bld);
+ panic();
+ }
+
+ /*
+ * The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010
+ * for the Foundation FVP_R.
+ */
+ switch (hbi) {
+ case HBI_FOUNDATION_FVP_R:
+ arm_config.flags = 0;
+
+ /*
+ * Check for supported revisions of Foundation FVP_R
+ * Allow future revisions to run but emit warning diagnostic
+ */
+ switch (rev) {
+ case REV_FOUNDATION_FVP_R_V2_0:
+ case REV_FOUNDATION_FVP_R_V2_1:
+ case REV_FOUNDATION_FVP_R_v9_1:
+ case REV_FOUNDATION_FVP_R_v9_6:
+ break;
+ default:
+ WARN("Unrecognized Foundation FVP_R revision %x\n", rev);
+ break;
+ }
+ break;
+ case HBI_BASE_FVP_R:
+ arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
+
+ /*
+ * Check for supported revisions
+ * Allow future revisions to run but emit warning diagnostic
+ */
+ switch (rev) {
+ case REV_BASE_FVP_R_V0:
+ arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
+ break;
+ default:
+ WARN("Unrecognized Base FVP_R revision %x\n", rev);
+ break;
+ }
+ break;
+ default:
+ ERROR("Unsupported board HBI number 0x%x\n", hbi);
+ panic();
+ }
+
+ /*
+ * We assume that the presence of MT bit, and therefore shifted
+ * affinities, is uniform across the platform: either all CPUs, or no
+ * CPUs implement it.
+ */
+ if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) {
+ arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
+ }
+}
+
+
+void __init fvp_interconnect_init(void)
+{
+ uintptr_t cci_base = 0U;
+ const int *cci_map = NULL;
+ unsigned int map_size = 0U;
+
+ /* Initialize the right interconnect */
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
+ cci_base = PLAT_FVP_R_CCI5XX_BASE;
+ cci_map = fvp_cci5xx_map;
+ map_size = ARRAY_SIZE(fvp_cci5xx_map);
+ } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
+ cci_base = PLAT_FVP_R_CCI400_BASE;
+ cci_map = fvp_cci400_map;
+ map_size = ARRAY_SIZE(fvp_cci400_map);
+ } else {
+ return;
+ }
+
+ assert(cci_base != 0U);
+ assert(cci_map != NULL);
+ cci_init(cci_base, cci_map, map_size);
+}
+
+void fvp_interconnect_enable(void)
+{
+ unsigned int master;
+
+ if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+ ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+ master = get_interconnect_master();
+ cci_enable_snoop_dvm_reqs(master);
+ }
+}
+
+void fvp_interconnect_disable(void)
+{
+ unsigned int master;
+
+ if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+ ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+ master = get_interconnect_master();
+ cci_disable_snoop_dvm_reqs(master);
+ }
+}
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void fvp_timer_init(void)
+{
+#if USE_SP804_TIMER
+ /* Enable the clock override for SP804 timer 0, which means that no
+ * clock dividers are applied and the raw (35MHz) clock will be used.
+ */
+ mmio_write_32(V2M_SP810_BASE, FVP_R_SP810_CTRL_TIM0_OV);
+
+ /* Initialize delay timer driver using SP804 dual timer 0 */
+ sp804_timer_init(V2M_SP804_TIMER0_BASE,
+ SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
+#else
+ generic_delay_timer_init();
+
+ /* Enable System level generic timer */
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+#endif /* USE_SP804_TIMER */
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+ return (int32_t)
+ ((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT)
+ | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT)
+ | FVP_R_SOC_ID);
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+ unsigned int sys_id;
+
+ sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+ return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) &
+ V2M_SYS_ID_REV_MASK);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
new file mode 100644
index 000000000..d172d2d90
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+
+/************************************************************
+ * For R-class everything is in secure world.
+ * Prepare the CPU system registers for first entry into EL1
+ ************************************************************/
+void cm_prepare_el2_exit(void)
+{
+ uint64_t hcr_el2 = 0U;
+
+ /*
+ * The use of ARMv8.3 pointer authentication (PAuth) is governed
+ * by fields in HCR_EL2, which trigger a 'trap to EL2' if not
+ * enabled. This register initialized at boot up, update PAuth
+ * bits.
+ *
+ * HCR_API_BIT: Set to one to disable traps to EL2 if lower ELs
+ * access PAuth registers
+ *
+ * HCR_APK_BIT: Set to one to disable traps to EL2 if lower ELs
+ * access PAuth instructions
+ */
+ hcr_el2 = read_hcr_el2();
+ write_hcr_el2(hcr_el2 | HCR_API_BIT | HCR_APK_BIT);
+
+ /*
+ * Initialise CNTHCTL_EL2. All fields are architecturally UNKNOWN
+ * on reset and are set to zero except for field(s) listed below.
+ *
+ * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to EL2
+ * if lower ELs accesses to the physical timer registers.
+ *
+ * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to EL2
+ * if lower ELs access to the physical counter registers.
+ */
+ write_cnthctl_el2(CNTHCTL_RESET_VAL | EL1PCEN_BIT | EL1PCTEN_BIT);
+
+ /*
+ * On Armv8-R, the EL1&0 memory system architecture is configurable
+ * as a VMSA or PMSA. All the fields architecturally UNKNOWN on reset
+ * and are set to zero except for field listed below.
+ *
+ * VCTR_EL2.MSA: Set to one to ensure the VMSA is enabled so that
+ * rich OS can boot.
+ */
+ write_vtcr_el2(VTCR_RESET_VAL | VTCR_EL2_MSA);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_debug.S b/plat/arm/board/fvp_r/fvp_r_debug.S
new file mode 100644
index 000000000..88f0a29a0
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_debug.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/debug.h>
+
+ .globl el2_panic
+
+ /***********************************************************
+ * The common implementation of do_panic for all BL stages
+ ***********************************************************/
+
+.section .rodata.panic_str, "aS"
+ panic_msg: .asciz "PANIC at PC : 0x"
+
+/*
+ * el2_panic will be redefined by the
+ * crash reporting mechanism (if enabled)
+ */
+el2_panic:
+ mov x6, x30
+ bl plat_crash_console_init
+
+ /* Check if the console is initialized */
+ cbz x0, _panic_handler
+
+ /* The console is initialized */
+ adr x4, panic_msg
+ bl asm_print_str
+ mov x4, x6
+
+ /* The panic location is lr -4 */
+ sub x4, x4, #4
+ bl asm_print_hex
+
+ bl plat_crash_console_flush
+
+_panic_handler:
+ /* Pass to plat_panic_handler the address from where el2_panic was
+ * called, not the address of the call from el2_panic.
+ */
+ mov x30, x6
+ b plat_panic_handler
diff --git a/plat/arm/board/fvp_r/fvp_r_def.h b/plat/arm/board/fvp_r/fvp_r_def.h
new file mode 100644
index 000000000..eda39cfb4
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_def.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_DEF_H
+#define FVP_R_DEF_H
+
+#include <lib/utils_def.h>
+
+/******************************************************************************
+ * FVP-R topology constants
+ *****************************************************************************/
+#define FVP_R_CLUSTER_COUNT 2
+#define FVP_R_MAX_CPUS_PER_CLUSTER 4
+#define FVP_R_MAX_PE_PER_CPU 1
+#define FVP_R_PRIMARY_CPU 0x0
+
+/******************************************************************************
+ * Definition of platform soc id
+ *****************************************************************************/
+#define FVP_R_SOC_ID 0
+
+/*******************************************************************************
+ * FVP_R memory map related constants
+ ******************************************************************************/
+
+#define FLASH1_BASE UL(0x8c000000)
+#define FLASH1_SIZE UL(0x04000000)
+
+#define PSRAM_BASE UL(0x94000000)
+#define PSRAM_SIZE UL(0x04000000)
+
+#define VRAM_BASE UL(0x98000000)
+#define VRAM_SIZE UL(0x02000000)
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE UL(0xa0000000)
+#define DEVICE0_SIZE UL(0x0c200000)
+
+/*
+ * In case of FVP_R models with CCN, the CCN register space overlaps into
+ * the NSRAM area.
+ */
+#define DEVICE1_BASE UL(0xae000000)
+#define DEVICE1_SIZE UL(0x1A00000)
+
+#define NSRAM_BASE UL(0xae000000)
+#define NSRAM_SIZE UL(0x10000)
+/* Devices in the second GB */
+#define DEVICE2_BASE UL(0xffe00000)
+#define DEVICE2_SIZE UL(0x00200000)
+
+#define PCIE_EXP_BASE UL(0xc0000000)
+#define TZRNG_BASE UL(0x7fe60000)
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE UL(0xffe70000)
+#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000))
+#define TFW_NVCTR_SIZE UL(4)
+#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004))
+#define NTFW_CTR_SIZE UL(4)
+
+/* Keys */
+#define SOC_KEYS_BASE UL(0xffe80000)
+#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000))
+#define TZ_PUB_KEY_HASH_SIZE UL(32)
+#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020))
+#define HU_KEY_SIZE UL(16)
+#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044))
+#define END_KEY_SIZE UL(32)
+
+/* Constants to distinguish FVP_R type */
+#define HBI_BASE_FVP_R U(0x020)
+#define REV_BASE_FVP_R_V0 U(0x0)
+#define REV_BASE_FVP_R_REVC U(0x2)
+
+#define HBI_FOUNDATION_FVP_R U(0x010)
+#define REV_FOUNDATION_FVP_R_V2_0 U(0x0)
+#define REV_FOUNDATION_FVP_R_V2_1 U(0x1)
+#define REV_FOUNDATION_FVP_R_v9_1 U(0x2)
+#define REV_FOUNDATION_FVP_R_v9_6 U(0x3)
+
+#define BLD_GIC_VE_MMAP U(0x0)
+#define BLD_GIC_A53A57_MMAP U(0x1)
+
+#define ARCH_MODEL U(0x1)
+
+/* FVP_R Power controller base address*/
+#define PWRC_BASE UL(0x1c100000)
+
+/* FVP_R SP804 timer frequency is 35 MHz*/
+#define SP804_TIMER_CLKMULT 1
+#define SP804_TIMER_CLKDIV 35
+
+/* SP810 controller. FVP_R specific flags */
+#define FVP_R_SP810_CTRL_TIM0_OV BIT_32(16)
+#define FVP_R_SP810_CTRL_TIM1_OV BIT_32(18)
+#define FVP_R_SP810_CTRL_TIM2_OV BIT_32(20)
+#define FVP_R_SP810_CTRL_TIM3_OV BIT_32(22)
+
+#endif /* FVP_R_DEF_H */
diff --git a/plat/arm/board/fvp_r/fvp_r_err.c b/plat/arm/board/fvp_r/fvp_r_err.c
new file mode 100644
index 000000000..7ee752b86
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_err.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/cfi/v2m_flash.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * FVP_R error handler
+ */
+__dead2 void plat_arm_error_handler(int err)
+{
+ int ret;
+
+ switch (err) {
+ case -ENOENT:
+ case -EAUTH:
+ /* Image load or authentication error. Erase the ToC */
+ INFO("Erasing FIP ToC from flash...\n");
+ (void)nor_unlock(PLAT_ARM_FLASH_IMAGE_BASE);
+ ret = nor_word_program(PLAT_ARM_FLASH_IMAGE_BASE, 0);
+ if (ret != 0) {
+ ERROR("Cannot erase ToC\n");
+ } else {
+ INFO("Done\n");
+ }
+ break;
+ default:
+ /* Unexpected error */
+ break;
+ }
+
+ (void)console_flush();
+
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_helpers.S b/plat/arm/board/fvp_r/fvp_r_helpers.S
new file mode 100644
index 000000000..ba857779a
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_helpers.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+
+#include <platform_def.h>
+
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * TODO: Should we read the PSYS register to make sure
+ * that the request has gone through.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* ---------------------------------------------
+ * Power down this cpu.
+ * TODO: Do we need to worry about powering the
+ * cluster down as well here? That will need
+ * locks which we won't have unless an elf-
+ * loader zeroes out the zi section.
+ * ---------------------------------------------
+ */
+ mrs x0, mpidr_el1
+ mov_imm x1, PWRC_BASE
+ str w0, [x1, #PPOFFR_OFF]
+
+ /* ---------------------------------------------
+ * There is no sane reason to come out of this
+ * wfi so panic if we do. This cpu will be pow-
+ * ered on and reset by the cpu_on pm api
+ * ---------------------------------------------
+ */
+ dsb sy
+ wfi
+ no_ret plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On FVP_R, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* ---------------------------------------------------------------------
+ * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
+ * WakeRequest signal" then it is a warm boot.
+ * ---------------------------------------------------------------------
+ */
+ mrs x2, mpidr_el1
+ mov_imm x1, PWRC_BASE
+ str w2, [x1, #PSYSR_OFF]
+ ldr w2, [x1, #PSYSR_OFF]
+ ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
+ cmp w2, #WKUP_PPONR
+ beq warm_reset
+ cmp w2, #WKUP_GICREQ
+ beq warm_reset
+
+ /* Cold reset */
+ mov x0, #0
+ ret
+
+warm_reset:
+ /* ---------------------------------------------------------------------
+ * A mailbox is maintained in the trusted SRAM. It is flushed out of the
+ * caches after every update using normal memory so it is safe to read
+ * it here with SO attributes.
+ * ---------------------------------------------------------------------
+ */
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr x0, [x0]
+ cbz x0, _panic_handler
+ ret
+
+ /* ---------------------------------------------------------------------
+ * The power controller indicates this is a warm reset but the mailbox
+ * is empty. This should never happen!
+ * ---------------------------------------------------------------------
+ */
+_panic_handler:
+ no_ret plat_panic_handler
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ mov_imm x1, MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+ cmp x0, #FVP_R_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/arm/board/fvp_r/fvp_r_io_storage.c b/plat/arm/board/fvp_r/fvp_r_io_storage.c
new file mode 100644
index 000000000..3b44828f0
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_io_storage.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_semihosting.h>
+#include <drivers/io/io_storage.h>
+#include <lib/semihosting.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+
+/* Semihosting filenames */
+#define BL33_IMAGE_NAME "bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
+#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
+#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *sh_dev_con;
+static uintptr_t sh_dev_handle;
+
+static const io_file_spec_t sh_file_spec[] = {
+ [BL33_IMAGE_ID] = {
+ .path = BL33_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_KEY_CERT_ID] = {
+ .path = TRUSTED_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ .path = NT_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ .path = NT_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+
+static int open_semihosting(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if the file exists on semi-hosting.*/
+ result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(sh_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Semi-hosting IO\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void plat_arm_io_setup(void)
+{
+ int io_result;
+
+ io_result = arm_io_setup();
+ if (io_result < 0) {
+ panic();
+ }
+
+ /* Register the additional IO devices on this platform */
+ io_result = register_io_dev_sh(&sh_dev_con);
+ if (io_result < 0) {
+ panic();
+ }
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
+ if (io_result < 0) {
+ panic();
+ }
+}
+
+/*
+ * FVP_R provides semihosting as an alternative to load images
+ */
+int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
+
+ if (result == 0) {
+ *dev_handle = sh_dev_handle;
+ *image_spec = (uintptr_t)&sh_file_spec[image_id];
+ }
+
+ return result;
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
new file mode 100644
index 000000000..67ad16400
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+ .globl disable_mpu_el2
+ .globl disable_mpu_icache_el2
+
+/* ---------------------------------------------------------------------------
+ * Disable the MPU at EL2.
+ * ---------------------------------------------------------------------------
+ */
+
+func disable_mpu_el2
+ mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT)
+do_disable_mpu_el2:
+ mrs x0, sctlr_el2
+ bic x0, x0, x1
+ msr sctlr_el2, x0
+ isb /* ensure MMU is off */
+ dsb sy
+ ret
+endfunc disable_mpu_el2
+
+
+func disable_mpu_icache_el2
+ mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
+ b do_disable_mpu_el2
+endfunc disable_mpu_icache_el2
diff --git a/plat/arm/board/fvp_r/fvp_r_private.h b/plat/arm/board/fvp_r/fvp_r_private.h
new file mode 100644
index 000000000..48f6e891e
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_private.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_PRIVATE_H
+#define FVP_R_PRIVATE_H
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void fvp_config_setup(void);
+
+void fvp_interconnect_init(void);
+void fvp_interconnect_enable(void);
+void fvp_interconnect_disable(void);
+void fvp_timer_init(void);
+
+#endif /* FVP_R_PRIVATE_H */
diff --git a/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
new file mode 100644
index 000000000..69b63122f
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <fvp_r_arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 8092347823957523895ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant. As the
+ * FVP_R does not have any random number generator, this is better than
+ * nothing but not necessarily really secure.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
new file mode 100644
index 000000000..de0b28fe8
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <lib/fconf/fconf.h>
+#include <lib/mmio.h>
+#include <tools_share/tbbr_oid.h>
+
+#include <plat/arm/common/fconf_nv_cntr_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
+
+/*
+ * Store a new non-volatile counter value.
+ *
+ * On some FVP_R versions, the non-volatile counters are read-only so this
+ * function will always fail.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ const char *oid;
+ uintptr_t nv_ctr_addr;
+
+ assert(cookie != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ TRUSTED_NV_CTR_ID);
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ NON_TRUSTED_NV_CTR_ID);
+ } else {
+ return 1;
+ }
+
+ mmio_write_32(nv_ctr_addr, nv_ctr);
+
+ /*
+ * If the FVP_R models a locked counter then its value cannot be updated
+ * and the above write operation has been silently ignored.
+ */
+ return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1;
+}
diff --git a/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
new file mode 100644
index 000000000..92bf48472
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_ARCH_HELPERS_H
+#define FVP_R_ARCH_HELPERS_H
+
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * MPU register definitions
+ ******************************************************************************/
+#define MPUIR_EL2 S3_4_C0_C0_4
+#define PRBAR_EL2 S3_4_C6_C8_0
+#define PRLAR_EL2 S3_4_C6_C8_1
+#define PRSELR_EL2 S3_4_C6_C2_1
+#define PRENR_EL2 S3_4_C6_C1_1
+
+/* v8-R64 MPU registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2)
+
+#endif /* FVP_R_ARCH_HELPERS_H */
diff --git a/plat/arm/board/fvp_r/include/platform_def.h b/plat/arm/board/fvp_r/include/platform_def.h
new file mode 100644
index 000000000..ea3a258f6
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/platform_def.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_PLATFORM_DEF_H
+#define FVP_R_PLATFORM_DEF_H
+
+#define PLAT_V2M_OFFSET 0x80000000
+
+#define BL33_IMAGE_DESC { \
+ .image_id = BL33_IMAGE_ID, \
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \
+ VERSION_2, image_info_t, 0), \
+ .image_info.image_base = PLAT_ARM_DRAM1_BASE + 0x1000, \
+ .image_info.image_max_size = UL(0x3ffff000), \
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\
+ .ep_info.pc = PLAT_ARM_DRAM1_BASE + 0x1000, \
+ .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), \
+}
+
+#include "../fvp_r_def.h"
+#include <drivers/arm/tzc400.h>
+#include <lib/utils_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+
+/* These are referenced by arm_def.h #included next, so #define first. */
+#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x80000000)
+#define PLAT_ARM_TRUSTED_SRAM_BASE UL(0x84000000)
+#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x86000000)
+#define PLAT_ARM_DRAM1_BASE ULL(0x0)
+#define PLAT_ARM_DRAM2_BASE ULL(0x080000000)
+
+#define PLAT_HW_CONFIG_DTB_BASE ULL(0x12000000)
+#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000)
+#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000)
+#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000)
+#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000)
+#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000)
+#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000)
+
+#include <plat/arm/common/arm_def.h>
+#include <plat/common/common_def.h>
+
+
+/* Required to create plat_regions: */
+#define MIN_LVL_BLOCK_DESC U(1)
+
+/* Required platform porting definitions */
+#define PLATFORM_CORE_COUNT (U(FVP_R_CLUSTER_COUNT) * \
+ U(FVP_R_MAX_CPUS_PER_CLUSTER) * \
+ U(FVP_R_MAX_PE_PER_CPU))
+
+#define PLAT_NUM_PWR_DOMAINS (U(FVP_R_CLUSTER_COUNT) + \
+ PLATFORM_CORE_COUNT + U(1))
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+#define PLAT_ARM_CLUSTER_COUNT U(FVP_R_CLUSTER_COUNT)
+#define PLAT_ARM_DRAM1_SIZE ULL(0x7fffffff)
+#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */
+#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */
+#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */
+
+/* These two are defined thus in arm_def.h, but doesn't seem to see it... */
+#define PLAT_BL1_RO_LIMIT (BL1_RO_BASE \
+ + PLAT_ARM_TRUSTED_ROM_SIZE)
+
+#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000)
+#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000)
+#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000)
+#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000)
+#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000)
+#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000)
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
+
+/* No SCP in FVP_R */
+#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0)
+
+#define PLAT_ARM_DRAM2_SIZE UL(0x80000000)
+
+#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
+
+#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
+ PLAT_HW_CONFIG_DTB_BASE, \
+ PLAT_HW_CONFIG_DTB_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+
+#define V2M_FVP_R_SYSREGS_BASE UL(0x9c010000)
+
+/*
+ * Load address of BL33 for this platform port,
+ * U-Boot specifically must be loaded at a 4K aligned address.
+ */
+#define PLAT_ARM_NS_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + 0x1000)
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if !USE_ROMLIB
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 5
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+# define N_MPU_REGIONS 16 /* number of MPU regions */
+# define ALL_MPU_EL2_REGIONS_USED 0xffffffff
+ /* this is the PRENR_EL2 value if all MPU regions are in use */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000)
+#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0x6000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0)
+#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#if COT_DESC_IN_DTB
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#endif
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#endif
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000)
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x500)
+# endif
+#endif
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+/*
+ * These nominally reserve the last block of flash for PSCI MEM PROTECT flag,
+ * but no PSCI in FVP_R platform, so reserve nothing:
+ */
+#define PLAT_ARM_FLASH_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + UL(0x40000000))
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (PLAT_ARM_DRAM1_SIZE - UL(0x40000000))
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE
+#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ
+
+/* CCI related constants */
+#define PLAT_FVP_R_CCI400_BASE UL(0xac090000)
+#define PLAT_FVP_R_CCI400_CLUS0_SL_PORT 3
+#define PLAT_FVP_R_CCI400_CLUS1_SL_PORT 4
+
+/* CCI-500/CCI-550 on Base platform */
+#define PLAT_FVP_R_CCI5XX_BASE UL(0xaa000000)
+#define PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT 5
+#define PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT 6
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+
+/* Mailbox base address */
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
+
+
+/* TrustZone controller related constants
+ *
+ * Currently only filters 0 and 2 are connected on Base FVP_R.
+ * Filter 0 : CPU clusters (no access to DRAM by default)
+ * Filter 1 : not connected
+ * Filter 2 : LCDs (access to VRAM allowed by default)
+ * Filter 3 : not connected
+ * Programming unconnected filters will have no effect at the
+ * moment. These filter could, however, be connected in future.
+ * So care should be taken not to configure the unused filters.
+ *
+ * Allow only non-secure access to all DRAM to supported devices.
+ * Give access to the CPUs and Virtio. Some devices
+ * would normally use the default ID so allow that too.
+ */
+#define PLAT_ARM_TZC_BASE UL(0xaa4a0000)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_DEFAULT) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_PCI) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_AP) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO_OLD))
+
+/*
+ * GIC related constants to cater for both GICv2 and GICv3 instances of an
+ * FVP_R. They could be overridden at runtime in case the FVP_R implements the
+ * legacy VE memory map.
+ */
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICR_BASE BASE_GICR_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+
+#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE)
+
+#define PLAT_SP_PRI PLAT_RAS_PRI
+
+/*
+ * Physical and virtual address space limits for MPU in AARCH64 & AARCH32 modes
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+
+#define ARM_SOC_CONTINUATION_SHIFT U(24)
+#define ARM_SOC_IDENTIFICATION_SHIFT U(16)
+
+#endif /* FVP_R_PLATFORM_DEF_H */
diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk
new file mode 100644
index 000000000..93b5cf246
--- /dev/null
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Only aarch64 ARCH supported for FVP_R
+ARCH := aarch64
+
+# Override to exclude BL2, BL2U, BL31, and BL33 for FVP_R
+override NEED_BL2 := no
+override NEED_BL2U := no
+override NEED_BL31 := no
+NEED_BL32 := no
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+# Use MPU-based memory management:
+XLAT_MPU_LIB_V1 := 1
+
+# FVP R will not have more than 2 clusters so just use CCI interconnect
+FVP_R_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c
+
+
+include plat/arm/board/common/board_common.mk
+include plat/arm/common/arm_common.mk
+
+PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include
+
+FVP_R_BL_COMMON_SOURCES := plat/arm/board/fvp_r/fvp_r_common.c \
+ plat/arm/board/fvp_r/fvp_r_context_mgmt.c \
+ plat/arm/board/fvp_r/fvp_r_debug.S \
+ plat/arm/board/fvp_r/fvp_r_err.c \
+ plat/arm/board/fvp_r/fvp_r_helpers.S \
+ plat/arm/board/fvp_r/fvp_r_misc_helpers.S
+
+FVP_R_BL1_SOURCES := plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c \
+ plat/arm/board/fvp_r/fvp_r_bl1_setup.c \
+ plat/arm/board/fvp_r/fvp_r_io_storage.c \
+ plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S \
+ plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S \
+ plat/arm/board/fvp_r/fvp_r_bl1_main.c
+
+FVP_R_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+
+FVP_R_DYNC_CFG_SOURCES := common/fdt_wrappers.c \
+ plat/arm/common/arm_dyn_cfg.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+FVP_R_AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ lib/fconf/fconf_tbbr_getter.c \
+ plat/common/tbbr/plat_tbbr.c \
+ drivers/auth/tbbr/tbbr_cot_bl1_r64.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ plat/arm/board/common/board_arm_trusted_boot.c \
+ plat/arm/board/common/rotpk/arm_dev_rotpk.S \
+ plat/arm/board/fvp_r/fvp_r_trusted_boot.c
+
+FVP_R_BL1_SOURCES += ${MBEDTLS_SOURCES} \
+ ${FVP_R_AUTH_SOURCES}
+endif
+
+ifeq (${USE_SP804_TIMER},1)
+FVP_R_BL_COMMON_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+else
+FVP_R_BL_COMMON_SOURCES += drivers/delay_timer/generic_delay_timer.c
+endif
+
+# Enable Activity Monitor Unit extensions by default
+ENABLE_AMU := 1
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+FVP_R_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c
+endif
+
+override BL1_SOURCES := drivers/arm/sp805/sp805.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_semihosting.c \
+ lib/cpus/aarch64/cpu_helpers.S \
+ lib/fconf/fconf_dyn_cfg_getter.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ plat/arm/common/arm_bl1_setup.c \
+ plat/arm/common/arm_err.c \
+ plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c \
+ plat/common/plat_bl1_common.c \
+ plat/common/aarch64/platform_up_stack.S \
+ ${FVP_R_BL1_SOURCES} \
+ ${FVP_R_BL_COMMON_SOURCES} \
+ ${FVP_R_CPU_LIBS} \
+ ${FVP_R_DYNC_CFG_SOURCES} \
+ ${FVP_R_INTERCONNECT_SOURCES}
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index ac45d57ee..f7eace833 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -1,9 +1,11 @@
#
-# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2021, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
+include common/fdt_wrappers.mk
+
ifdef ARM_CORTEX_A5
# Use the SP804 timer instead of the generic one
USE_SP804_TIMER := 1
@@ -125,10 +127,13 @@ endif
# Firmware Configuration Framework sources
include lib/fconf/fconf.mk
+BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
# Add `libfdt` and Arm common helpers required for Dynamic Config
include lib/libfdt/libfdt.mk
DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \
- plat/arm/common/arm_dyn_cfg_helpers.c \
- common/fdt_wrappers.c
+ plat/arm/common/arm_dyn_cfg_helpers.c
+DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES}
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 5299a7b8a..d61ba5d19 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -53,12 +53,13 @@
#define PLAT_ARM_DRAM2_BASE ULL(0x880000000)
#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
-#define PLAT_HW_CONFIG_DTB_BASE ULL(0x82000000)
-#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x00008000) /* 32KB */
+/* Range of kernel DTB load address */
+#define JUNO_DTB_DRAM_MAP_START ULL(0x82000000)
+#define JUNO_DTB_DRAM_MAP_SIZE ULL(0x00008000) /* 32KB */
#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
- PLAT_HW_CONFIG_DTB_BASE, \
- PLAT_HW_CONFIG_DTB_SIZE, \
+ JUNO_DTB_DRAM_MAP_START, \
+ JUNO_DTB_DRAM_MAP_SIZE, \
MT_MEMORY | MT_RO | MT_NS)
/* virtual address used by dynamic mem_protect for chunk_base */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 92fbf3598..2c84eb34d 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -4,6 +4,8 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include common/fdt_wrappers.mk
+
# Include GICv2 driver files
include drivers/arm/gic/v2/gicv2.mk
@@ -83,7 +85,6 @@ BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
lib/utils/mem_region.c \
- common/fdt_wrappers.c \
lib/fconf/fconf.c \
lib/fconf/fconf_dyn_cfg_getter.c \
plat/arm/board/juno/juno_bl31_setup.c \
@@ -94,6 +95,8 @@ BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \
${JUNO_INTERCONNECT_SOURCES} \
${JUNO_SECURITY_SOURCES}
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
BL1_SOURCES += drivers/arm/css/sds/sds.c
endif
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index 794f8974f..5b24c32bd 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
-# RD-N2 platform uses GIC-Clayton which is based on GICv4.1
+# RD-N2 platform uses GIC-700 which is based on GICv4.1
GIC_ENABLE_V4_EXTN := 1
include plat/arm/css/sgi/sgi-common.mk
diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk
index 1ae85de7c..11f52127e 100644
--- a/plat/arm/board/rdv1/platform.mk
+++ b/plat/arm/board/rdv1/platform.mk
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
-# RD-V1 platform uses GIC-Clayton which is based on GICv4.1
+# RD-V1 platform uses GIC-700 which is based on GICv4.1
GIC_ENABLE_V4_EXTN := 1
include plat/arm/css/sgi/sgi-common.mk
diff --git a/plat/arm/board/tc/fdts/tc_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts
index 4b6abd4d1..a84c7f85f 100644
--- a/plat/arm/board/tc/fdts/tc_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,7 +26,7 @@
hw-config {
load-address = <0x0 0x83000000>;
- max-size = <0x01000000>;
+ max-size = <0x8000>;
id = <HW_CONFIG_ID>;
};
};
diff --git a/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
index a8592f6bf..d3a5e1a77 100644
--- a/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
@@ -43,6 +43,13 @@
vcpu_count = <1>;
mem_size = <1048576>;
};
+ vm4 {
+ is_ffa_partition;
+ debug_name = "ivy";
+ load_address = <0xfe600000>;
+ vcpu_count = <1>;
+ mem_size = <1048576>;
+ };
};
cpus {
diff --git a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
index 34b4e74c3..92e2ddda6 100644
--- a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
@@ -36,7 +36,7 @@
#ifdef TS_SP_FW_CONFIG
vm2 {
is_ffa_partition;
- debug_name = "secure-storage";
+ debug_name = "internal-trusted-storage";
load_address = <0xfee00000>;
vcpu_count = <1>;
mem_size = <2097152>; /* 2MB TZC DRAM */
diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
index 28ed7ae94..4c6ccef25 100644
--- a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <lib/libc/cdefs.h>
+
/dts-v1/;
/ {
@@ -27,8 +29,11 @@
secure-partitions {
compatible = "arm,sp";
+#ifdef ARM_BL2_SP_LIST_DTS
+ #include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
#ifdef TS_SP_FW_CONFIG
- secure-storage {
+ internal-trusted-storage {
uuid = "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14";
load-address = <0xfee00000>;
};
@@ -59,6 +64,13 @@
uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2";
load-address = <0xfe200000>;
};
+
+ ivy {
+ uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7";
+ load-address = <0xfe600000>;
+ owner = "Plat";
+ };
#endif
+#endif /* ARM_BL2_SP_LIST_DTS */
};
};
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index c8edd2fbb..745d91cab 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -55,6 +55,14 @@
TC_TZC_DRAM1_BASE, \
TC_TZC_DRAM1_SIZE, \
MT_MEMORY | MT_RW | MT_SECURE)
+
+#define PLAT_HW_CONFIG_DTB_BASE ULL(0x83000000)
+#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
+
+#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT( \
+ PLAT_HW_CONFIG_DTB_BASE, \
+ PLAT_HW_CONFIG_DTB_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
/*
* Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to
* max size of BL32 image.
@@ -122,7 +130,7 @@
* calculated using the current BL31 PROGBITS debug size plus the sizes of
* BL2 and BL1-RW
*/
-#define PLAT_ARM_MAX_BL31_SIZE 0x3B000
+#define PLAT_ARM_MAX_BL31_SIZE 0x3F000
/*
* Size of cacheable stacks
@@ -177,6 +185,7 @@
#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
+#define PLAT_ARM_DRAM2_END (PLAT_ARM_DRAM2_BASE + PLAT_ARM_DRAM2_SIZE - 1ULL)
#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
@@ -252,13 +261,15 @@
/*
* The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to
* ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as
- * secure. The second region gives non secure access to rest of DRAM.
+ * secure. The second and third regions gives non secure access to rest of DRAM.
*/
-#define TC_TZC_REGIONS_DEF \
- {TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END, \
- TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS}, \
- {TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
- PLAT_ARM_TZC_NS_DEV_ACCESS}
+#define TC_TZC_REGIONS_DEF \
+ {TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END, \
+ TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {PLAT_ARM_DRAM2_BASE, PLAT_ARM_DRAM2_END, \
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}
/* virtual address used by dynamic mem_protect for chunk_base */
#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 8db764ca1..8765fa2e3 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -3,6 +3,8 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include common/fdt_wrappers.mk
+
ifeq ($(filter ${TARGET_PLATFORM}, 0 1),)
$(error TARGET_PLATFORM must be 0 or 1)
endif
@@ -31,6 +33,9 @@ GIC_ENABLE_V4_EXTN := 1
# GIC-600 configuration
GICV3_SUPPORT_GIC600 := 1
+# Enable SVE
+ENABLE_SVE_FOR_NS := 1
+ENABLE_SVE_FOR_SWD := 1
# Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk
@@ -77,6 +82,7 @@ BL1_SOURCES += ${INTERCONNECT_SOURCES} \
BL2_SOURCES += ${TC_BASE}/tc_security.c \
${TC_BASE}/tc_err.c \
${TC_BASE}/tc_trusted_boot.c \
+ ${TC_BASE}/tc_bl2_setup.c \
lib/utils/mem_region.c \
drivers/arm/tzc/tzc400.c \
plat/arm/common/arm_tzc400.c \
@@ -87,10 +93,14 @@ BL31_SOURCES += ${INTERCONNECT_SOURCES} \
${ENT_GIC_SOURCES} \
${TC_BASE}/tc_bl31_setup.c \
${TC_BASE}/tc_topology.c \
+ lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
drivers/cfi/v2m/v2m_flash.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
# Add the FDT_SOURCES and options for Dynamic Config
FDT_SOURCES += ${TC_BASE}/fdts/${PLAT}_fw_config.dts \
${TC_BASE}/fdts/${PLAT}_tb_fw_config.dts
@@ -130,6 +140,11 @@ override CTX_INCLUDE_PAUTH_REGS := 1
override ENABLE_SPE_FOR_LOWER_ELS := 0
override ENABLE_AMU := 1
+override ENABLE_AMU_AUXILIARY_COUNTERS := 1
+override ENABLE_AMU_FCONF := 1
+
+override ENABLE_MPMM := 1
+override ENABLE_MPMM_FCONF := 1
include plat/arm/common/arm_common.mk
include plat/arm/css/common/css_common.mk
diff --git a/plat/arm/board/tc/tc_bl2_setup.c b/plat/arm/board/tc/tc_bl2_setup.c
new file mode 100644
index 000000000..74ef569eb
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl2_setup.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ struct bl_params *arm_bl_params = arm_get_next_bl_params();
+
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ bl_mem_params_node_t *param_node;
+ uintptr_t fw_config_base = 0U;
+ entry_point_info_t *ep_info;
+
+ /* Get BL31 image node */
+ param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+ assert(param_node != NULL);
+
+ /* Get fw_config load address */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ assert(fw_config_info != NULL);
+
+ fw_config_base = fw_config_info->config_addr;
+ assert(fw_config_base != 0U);
+
+ /*
+ * Get the entry point info of BL31 image and override
+ * arg1 of entry point info with fw_config base address
+ */
+ ep_info = &param_node->ep_info;
+ ep_info->args.arg1 = (uint32_t)fw_config_base;
+
+ return arm_bl_params;
+}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index ecec26c05..0523ef8f2 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,8 @@
#include <common/debug.h>
#include <drivers/arm/css/css_mhu_doorbell.h>
#include <drivers/arm/css/scmi.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
@@ -42,6 +44,9 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
}
void tc_bl31_common_platform_setup(void)
@@ -53,3 +58,16 @@ const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
{
return css_scmi_override_pm_ops(ops);
}
+
+void __init bl31_plat_arch_setup(void)
+{
+ arm_bl31_plat_arch_setup();
+
+ /* HW_CONFIG was also loaded by BL2 */
+ const struct dyn_cfg_dtb_info_t *hw_config_info;
+
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+}
diff --git a/plat/arm/board/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c
index 3863a0a13..a9668e117 100644
--- a/plat/arm/board/tc/tc_plat.c
+++ b/plat/arm/board/tc/tc_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -63,6 +63,7 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
V2M_MAP_IOFPGA,
TC_MAP_DEVICE,
+ PLAT_DTB_DRAM_NS,
#if SPM_MM
ARM_SPM_BUF_EL3_MMAP,
#endif