Merge "fix(stm32mp1_clk): fix MCU/AXI parent clock" into integration
diff --git a/Makefile b/Makefile
index 59d14ba..ec6f885 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -129,6 +129,23 @@
$(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION})
endif
+# FEAT_RME
+ifeq (${ENABLE_RME},1)
+# RME doesn't support PIE
+ifneq (${ENABLE_PIE},0)
+ $(error ENABLE_RME does not support PIE)
+endif
+# RME requires AARCH64
+ifneq (${ARCH},aarch64)
+ $(error ENABLE_RME requires AArch64)
+endif
+# RME requires el2 context to be saved for now.
+CTX_INCLUDE_EL2_REGS := 1
+CTX_INCLUDE_AARCH32_REGS := 0
+ARM_ARCH_MAJOR := 8
+ARM_ARCH_MINOR := 6
+endif
+
# USE_SPINLOCK_CAS requires AArch64 build
ifeq (${USE_SPINLOCK_CAS},1)
ifneq (${ARCH},aarch64)
@@ -559,6 +576,18 @@
endif
################################################################################
+# Include rmmd Makefile if RME is enabled
+################################################################################
+
+ifneq (${ENABLE_RME},0)
+ifneq (${ARCH},aarch64)
+ $(error ENABLE_RME requires AArch64)
+endif
+include services/std_svc/rmmd/rmmd.mk
+$(warning "RME is an experimental feature")
+endif
+
+################################################################################
# Include the platform specific Makefile after the SPD Makefile (the platform
# makefile may use all previous definitions in this file)
################################################################################
@@ -776,10 +805,16 @@
# Process platform overrideable behaviour
################################################################################
+ifdef BL1_SOURCES
+NEED_BL1 := yes
+endif
+
-# Using BL2 implies that a BL33 image also needs to be supplied for the FIP and
-# Certificate generation tools. This flag can be overridden by the platform.
ifdef BL2_SOURCES
- ifdef EL3_PAYLOAD_BASE
+ NEED_BL2 := yes
+
+ # Using BL2 implies that a BL33 image also needs to be supplied for the FIP and
+ # Certificate generation tools. This flag can be overridden by the platform.
+ ifdef EL3_PAYLOAD_BASE
# If booting an EL3 payload there is no need for a BL33 image
# in the FIP file.
NEED_BL33 := no
@@ -794,6 +829,10 @@
endif
endif
+ifdef BL2U_SOURCES
+NEED_BL2U := yes
+endif
+
# If SCP_BL2 is given, we always want FIP to include it.
ifdef SCP_BL2
NEED_SCP_BL2 := yes
@@ -831,6 +870,10 @@
FIP_ARGS += --align ${FIP_ALIGN}
endif
+ifdef FDT_SOURCES
+NEED_FDT := yes
+endif
+
################################################################################
# Include libraries' Makefile that are used in all BL
################################################################################
@@ -874,30 +917,22 @@
################################################################################
# Include BL specific makefiles
################################################################################
-ifdef BL1_SOURCES
-NEED_BL1 := yes
+
+ifeq (${NEED_BL1},yes)
include bl1/bl1.mk
endif
-ifdef BL2_SOURCES
-NEED_BL2 := yes
+ifeq (${NEED_BL2},yes)
include bl2/bl2.mk
endif
-ifdef BL2U_SOURCES
-NEED_BL2U := yes
+ifeq (${NEED_BL2U},yes)
include bl2u/bl2u.mk
endif
ifeq (${NEED_BL31},yes)
-ifdef BL31_SOURCES
include bl31/bl31.mk
endif
-endif
-
-ifdef FDT_SOURCES
-NEED_FDT := yes
-endif
################################################################################
# Build options checks
@@ -926,6 +961,7 @@
ENABLE_PIE \
ENABLE_PMF \
ENABLE_PSCI_STAT \
+ ENABLE_RME \
ENABLE_RUNTIME_INSTRUMENTATION \
ENABLE_SPE_FOR_LOWER_ELS \
ENABLE_SVE_FOR_NS \
@@ -1028,6 +1064,7 @@
ENABLE_PIE \
ENABLE_PMF \
ENABLE_PSCI_STAT \
+ ENABLE_RME \
ENABLE_RUNTIME_INSTRUMENTATION \
ENABLE_SPE_FOR_LOWER_ELS \
ENABLE_SVE_FOR_NS \
@@ -1148,7 +1185,7 @@
# Expand build macros for the different images
ifeq (${NEED_BL1},yes)
-$(eval $(call MAKE_BL,1))
+$(eval $(call MAKE_BL,bl1))
endif
ifeq (${NEED_BL2},yes)
@@ -1157,7 +1194,7 @@
endif
$(if ${BL2}, $(eval $(call TOOL_ADD_IMG,bl2,--${FIP_BL2_ARGS})),\
- $(eval $(call MAKE_BL,2,${FIP_BL2_ARGS})))
+ $(eval $(call MAKE_BL,bl2,${FIP_BL2_ARGS})))
endif
ifeq (${NEED_SCP_BL2},yes)
@@ -1170,10 +1207,10 @@
BL31_SOURCES := $(sort ${BL31_SOURCES})
ifneq (${DECRYPTION_SUPPORT},none)
$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\
- $(eval $(call MAKE_BL,31,soc-fw,,$(ENCRYPT_BL31))))
+ $(eval $(call MAKE_BL,bl31,soc-fw,,$(ENCRYPT_BL31))))
else
$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\
- $(eval $(call MAKE_BL,31,soc-fw)))
+ $(eval $(call MAKE_BL,bl31,soc-fw)))
endif
endif
@@ -1186,14 +1223,25 @@
BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1))
ifneq (${DECRYPTION_SUPPORT},none)
-$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw,,$(ENCRYPT_BL32))),\
+$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw,,$(ENCRYPT_BL32))),\
$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32))))
else
-$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw)),\
+$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw)),\
$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw)))
endif
endif
+# If RMM image is needed but RMM is not defined, Test Realm Payload (TRP)
+# needs to be built from RMM_SOURCES.
+ifeq (${NEED_RMM},yes)
+# Sort RMM source files to remove duplicates
+RMM_SOURCES := $(sort ${RMM_SOURCES})
+BUILD_RMM := $(if $(RMM),,$(if $(RMM_SOURCES),1))
+
+$(if ${BUILD_RMM}, $(eval $(call MAKE_BL,rmm,rmm-fw)),\
+ $(eval $(call TOOL_ADD_IMG,rmm,--rmm-fw)))
+endif
+
# Add the BL33 image if required by the platform
ifeq (${NEED_BL33},yes)
$(eval $(call TOOL_ADD_IMG,bl33,--nt-fw))
@@ -1201,7 +1249,7 @@
ifeq (${NEED_BL2U},yes)
$(if ${BL2U}, $(eval $(call TOOL_ADD_IMG,bl2u,--ap-fwu-cfg,FWU_)),\
- $(eval $(call MAKE_BL,2u,ap-fwu-cfg,FWU_)))
+ $(eval $(call MAKE_BL,bl2u,ap-fwu-cfg,FWU_)))
endif
# Expand build macros for the different images
diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c
index 2a8d58e..b9a7e5b 100644
--- a/bl1/aarch64/bl1_context_mgmt.c
+++ b/bl1/aarch64/bl1_context_mgmt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,6 +16,7 @@
/* Following contains the cpu context pointers. */
static void *bl1_cpu_context_ptr[2];
+entry_point_info_t *bl2_ep_info;
void *cm_get_context(uint32_t security_state)
@@ -30,6 +31,40 @@
bl1_cpu_context_ptr[security_state] = context;
}
+#if ENABLE_RME
+/*******************************************************************************
+ * This function prepares the entry point information to run BL2 in Root world,
+ * i.e. EL3, for the case when FEAT_RME is enabled.
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+ image_desc_t *bl2_desc;
+
+ assert(image_id == BL2_IMAGE_ID);
+
+ /* Get the image descriptor. */
+ bl2_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(bl2_desc != NULL);
+
+ /* Get the entry point info. */
+ bl2_ep_info = &bl2_desc->ep_info;
+
+ bl2_ep_info->spsr = (uint32_t)SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+
+ /*
+ * Flush cache since bl2_ep_info is accessed after MMU is disabled
+ * before jumping to BL2.
+ */
+ flush_dcache_range((uintptr_t)bl2_ep_info, sizeof(entry_point_info_t));
+
+ /* Indicate that image is in execution state. */
+ bl2_desc->state = IMAGE_STATE_EXECUTED;
+
+ /* Print debug info and flush the console before running BL2. */
+ print_entry_point_info(bl2_ep_info);
+}
+#else
/*******************************************************************************
* This function prepares the context for Secure/Normal world images.
* Normal world images are transitioned to EL2(if supported) else EL1.
@@ -93,3 +128,4 @@
print_entry_point_info(next_bl_ep);
}
+#endif /* ENABLE_RME */
diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S
index 00f2718..f61c060 100644
--- a/bl1/aarch64/bl1_entrypoint.S
+++ b/bl1/aarch64/bl1_entrypoint.S
@@ -1,13 +1,15 @@
/*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
+#include <common/bl_common.h>
#include <el3_common_macros.S>
.globl bl1_entrypoint
+ .globl bl1_run_bl2_in_root
/* -----------------------------------------------------
@@ -66,5 +68,41 @@
* Do the transition to next boot image.
* --------------------------------------------------
*/
+#if ENABLE_RME
+ b bl1_run_bl2_in_root
+#else
b el3_exit
+#endif
endfunc bl1_entrypoint
+
+ /* -----------------------------------------------------
+ * void bl1_run_bl2_in_root();
+ * This function runs BL2 in root/EL3 when RME is enabled.
+ * -----------------------------------------------------
+ */
+
+func bl1_run_bl2_in_root
+ /* read bl2_ep_info */
+ adrp x20, bl2_ep_info
+ add x20, x20, :lo12:bl2_ep_info
+ ldr x20, [x20]
+
+ /* ---------------------------------------------
+ * MMU needs to be disabled because BL2 executes
+ * in EL3. It will initialize the address space
+ * according to its own requirements.
+ * ---------------------------------------------
+ */
+ bl disable_mmu_icache_el3
+ tlbi alle3
+
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el3, x0
+ msr spsr_el3, 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_bl2_in_root
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index 8f44151..9f63fd5 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -4,14 +4,12 @@
# SPDX-License-Identifier: BSD-3-Clause
#
-ifneq (${PLAT},fvp_r)
BL1_SOURCES += bl1/${ARCH}/bl1_arch_setup.c \
bl1/${ARCH}/bl1_context_mgmt.c \
bl1/${ARCH}/bl1_entrypoint.S \
bl1/${ARCH}/bl1_exceptions.S \
- bl1/bl1_main.c
-endif
-BL1_SOURCES += lib/cpus/${ARCH}/cpu_helpers.S \
+ bl1/bl1_main.c \
+ lib/cpus/${ARCH}/cpu_helpers.S \
lib/cpus/errata_report.c \
lib/el3_runtime/${ARCH}/context_mgmt.c \
plat/common/plat_bl1_common.c \
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index fd60232..663ec64 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.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
*/
@@ -126,6 +126,9 @@
auth_mod_init();
#endif /* TRUSTED_BOARD_BOOT */
+ /* Initialize the measured boot */
+ bl1_plat_mboot_init();
+
/* Perform platform setup in BL1. */
bl1_platform_setup();
@@ -147,6 +150,9 @@
else
NOTICE("BL1-FWU: *******FWU Process Started*******\n");
+ /* Teardown the measured boot driver */
+ bl1_plat_mboot_finish();
+
bl1_prepare_next_image(image_id);
console_flush();
diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h
index 2cfeeea..e119ba7 100644
--- a/bl1/bl1_private.h
+++ b/bl1/bl1_private.h
@@ -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
*/
@@ -11,6 +11,8 @@
#include <common/bl_common.h>
+extern entry_point_info_t *bl2_ep_info;
+
/******************************************
* Function prototypes
*****************************************/
@@ -18,6 +20,7 @@
void bl1_arch_next_el_setup(void);
void bl1_prepare_next_image(unsigned int image_id);
+void bl1_run_bl2_in_root(void);
u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
u_register_t x1,
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
index 7e85551..40154aa 100644
--- a/bl2/aarch32/bl2_el3_entrypoint.S
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,7 +10,6 @@
#include <el3_common_macros.S>
.globl bl2_entrypoint
- .globl bl2_run_next_image
func bl2_entrypoint
@@ -56,37 +55,3 @@
no_ret plat_panic_handler
endfunc bl2_entrypoint
-
-func bl2_run_next_image
- mov r8,r0
-
- /*
- * MMU needs to be disabled because both BL2 and BL32 execute
- * in PL1, and therefore share the same address space.
- * BL32 will initialize the address space according to its
- * own requirement.
- */
- bl disable_mmu_icache_secure
- stcopr r0, TLBIALL
- dsb sy
- isb
- mov r0, r8
- bl bl2_el3_plat_prepare_exit
-
- /*
- * Extract PC and SPSR based on struct `entry_point_info_t`
- * and load it in LR and SPSR registers respectively.
- */
- ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
- ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
- msr spsr_xc, r1
-
- /* Some BL32 stages expect lr_svc to provide the BL33 entry address */
- cps #MODE32_svc
- ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
- cps #MODE32_mon
-
- add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
- ldm r8, {r0, r1, r2, r3}
- exception_return
-endfunc bl2_run_next_image
diff --git a/bl2/aarch32/bl2_run_next_image.S b/bl2/aarch32/bl2_run_next_image.S
new file mode 100644
index 0000000..0b3554e
--- /dev/null
+++ b/bl2/aarch32/bl2_run_next_image.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+
+ .globl bl2_run_next_image
+
+
+func bl2_run_next_image
+ mov r8,r0
+
+ /*
+ * MMU needs to be disabled because both BL2 and BL32 execute
+ * in PL1, and therefore share the same address space.
+ * BL32 will initialize the address space according to its
+ * own requirement.
+ */
+ bl disable_mmu_icache_secure
+ stcopr r0, TLBIALL
+ dsb sy
+ isb
+ mov r0, r8
+ bl bl2_el3_plat_prepare_exit
+
+ /*
+ * Extract PC and SPSR based on struct `entry_point_info_t`
+ * and load it in LR and SPSR registers respectively.
+ */
+ ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
+ ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
+ msr spsr_xc, r1
+
+ /* Some BL32 stages expect lr_svc to provide the BL33 entry address */
+ cps #MODE32_svc
+ ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
+ cps #MODE32_mon
+
+ add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
+ ldm r8, {r0, r1, r2, r3}
+ exception_return
+endfunc bl2_run_next_image
diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S
index 4eab39c..45bac7d 100644
--- a/bl2/aarch64/bl2_el3_entrypoint.S
+++ b/bl2/aarch64/bl2_el3_entrypoint.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,8 +12,6 @@
#include <el3_common_macros.S>
.globl bl2_entrypoint
- .globl bl2_el3_run_image
- .globl bl2_run_next_image
#if BL2_IN_XIP_MEM
#define FIXUP_SIZE 0
@@ -72,36 +70,3 @@
*/
no_ret plat_panic_handler
endfunc bl2_entrypoint
-
-func bl2_run_next_image
- mov x20,x0
- /* ---------------------------------------------
- * MMU needs to be disabled because both BL2 and BL31 execute
- * in EL3, and therefore share the same address space.
- * BL31 will initialize the address space according to its
- * own requirement.
- * ---------------------------------------------
- */
- bl disable_mmu_icache_el3
- tlbi alle3
- bl bl2_el3_plat_prepare_exit
-
-#if ENABLE_PAUTH
- /* ---------------------------------------------
- * Disable pointer authentication before jumping
- * to next boot image.
- * ---------------------------------------------
- */
- bl pauth_disable_el3
-#endif /* ENABLE_PAUTH */
-
- ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
- msr elr_el3, x0
- msr spsr_el3, 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 bl2_run_next_image
diff --git a/bl2/aarch64/bl2_rme_entrypoint.S b/bl2/aarch64/bl2_rme_entrypoint.S
new file mode 100644
index 0000000..076e326
--- /dev/null
+++ b/bl2/aarch64/bl2_rme_entrypoint.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <el3_common_macros.S>
+
+ .globl bl2_entrypoint
+
+
+func bl2_entrypoint
+ /* Save arguments x0-x3 from previous Boot loader */
+ mov x20, x0
+ mov x21, x1
+ mov x22, x2
+ mov x23, x3
+
+ el3_entrypoint_common \
+ _init_sctlr=0 \
+ _warm_boot_mailbox=0 \
+ _secondary_cold_boot=0 \
+ _init_memory=0 \
+ _init_c_runtime=1 \
+ _exception_vectors=bl2_el3_exceptions \
+ _pie_fixup_size=0
+
+ /* ---------------------------------------------
+ * Restore parameters of boot rom
+ * ---------------------------------------------
+ */
+ mov x0, x20
+ mov x1, x21
+ mov x2, x22
+ mov x3, x23
+
+ /* ---------------------------------------------
+ * Perform BL2 setup
+ * ---------------------------------------------
+ */
+ bl bl2_setup
+
+#if ENABLE_PAUTH
+ /* ---------------------------------------------
+ * Program APIAKey_EL1 and enable pointer authentication.
+ * ---------------------------------------------
+ */
+ bl pauth_init_enable_el3
+#endif /* ENABLE_PAUTH */
+
+ /* ---------------------------------------------
+ * Jump to main function.
+ * ---------------------------------------------
+ */
+ bl bl2_main
+
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ no_ret plat_panic_handler
+endfunc bl2_entrypoint
diff --git a/bl2/aarch64/bl2_run_next_image.S b/bl2/aarch64/bl2_run_next_image.S
new file mode 100644
index 0000000..f0a8be8
--- /dev/null
+++ b/bl2/aarch64/bl2_run_next_image.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+
+ .globl bl2_run_next_image
+
+
+func bl2_run_next_image
+ mov x20,x0
+ /* ---------------------------------------------
+ * MMU needs to be disabled because both BL2 and BL31 execute
+ * in EL3, and therefore share the same address space.
+ * BL31 will initialize the address space according to its
+ * own requirement.
+ * ---------------------------------------------
+ */
+ bl disable_mmu_icache_el3
+ tlbi alle3
+ bl bl2_el3_plat_prepare_exit
+
+#if ENABLE_PAUTH
+ /* ---------------------------------------------
+ * Disable pointer authentication before jumping
+ * to next boot image.
+ * ---------------------------------------------
+ */
+ bl pauth_disable_el3
+#endif /* ENABLE_PAUTH */
+
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el3, x0
+ msr spsr_el3, 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 bl2_run_next_image
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 37849c3..d332ec0 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -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
*/
@@ -25,7 +25,11 @@
#if SEPARATE_CODE_AND_RODATA
.text . : {
__TEXT_START__ = .;
+#if ENABLE_RME
+ *bl2_rme_entrypoint.o(.text*)
+#else /* ENABLE_RME */
*bl2_entrypoint.o(.text*)
+#endif /* ENABLE_RME */
*(SORT_BY_ALIGNMENT(.text*))
*(.vectors)
. = ALIGN(PAGE_SIZE);
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index 735e7e0..7a973e5 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -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
#
@@ -15,13 +15,26 @@
BL2_SOURCES += common/aarch64/early_exceptions.S
endif
-ifeq (${BL2_AT_EL3},0)
+ifeq (${ENABLE_RME},1)
+# Using RME, run BL2 at EL3
+include lib/gpt_rme/gpt_rme.mk
+
+BL2_SOURCES += bl2/${ARCH}/bl2_rme_entrypoint.S \
+ bl2/${ARCH}/bl2_el3_exceptions.S \
+ bl2/${ARCH}/bl2_run_next_image.S \
+ ${GPT_LIB_SRCS}
+BL2_LINKERFILE := bl2/bl2.ld.S
+
+else ifeq (${BL2_AT_EL3},0)
+# Normal operation, no RME, no BL2 at EL3
BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S
BL2_LINKERFILE := bl2/bl2.ld.S
else
+# BL2 at EL3, no RME
BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \
bl2/${ARCH}/bl2_el3_exceptions.S \
+ bl2/${ARCH}/bl2_run_next_image.S \
lib/cpus/${ARCH}/cpu_helpers.S \
lib/cpus/errata_report.c
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index d2de135..90fe39b 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -15,9 +15,6 @@
#include <drivers/auth/auth_mod.h>
#include <drivers/console.h>
#include <drivers/fwu/fwu.h>
-#if MEASURED_BOOT
-#include <drivers/measured_boot/measured_boot.h>
-#endif
#include <lib/extensions/pauth.h>
#include <plat/common/platform.h>
@@ -29,18 +26,18 @@
#define NEXT_IMAGE "BL32"
#endif
-#if !BL2_AT_EL3
+#if BL2_AT_EL3
/*******************************************************************************
- * Setup function for BL2.
+ * Setup function for BL2 when BL2_AT_EL3=1
******************************************************************************/
-void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
- u_register_t arg3)
+void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
+ u_register_t arg3)
{
/* Perform early platform-specific setup */
- bl2_early_platform_setup2(arg0, arg1, arg2, arg3);
+ bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3);
/* Perform late platform-specific setup */
- bl2_plat_arch_setup();
+ bl2_el3_plat_arch_setup();
#if CTX_INCLUDE_PAUTH_REGS
/*
@@ -50,19 +47,18 @@
assert(is_armv8_3_pauth_present());
#endif /* CTX_INCLUDE_PAUTH_REGS */
}
-
-#else /* if BL2_AT_EL3 */
+#else /* BL2_AT_EL3 */
/*******************************************************************************
- * Setup function for BL2 when BL2_AT_EL3=1.
+ * Setup function for BL2 when BL2_AT_EL3=0
******************************************************************************/
-void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
- u_register_t arg3)
+void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
+ u_register_t arg3)
{
/* Perform early platform-specific setup */
- bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3);
+ bl2_early_platform_setup2(arg0, arg1, arg2, arg3);
/* Perform late platform-specific setup */
- bl2_el3_plat_arch_setup();
+ bl2_plat_arch_setup();
#if CTX_INCLUDE_PAUTH_REGS
/*
@@ -96,26 +92,21 @@
#if TRUSTED_BOARD_BOOT
/* Initialize authentication module */
auth_mod_init();
-
-#if MEASURED_BOOT
- /* Initialize measured boot module */
- measured_boot_init();
-
-#endif /* MEASURED_BOOT */
#endif /* TRUSTED_BOARD_BOOT */
+ /* Initialize the Measured Boot backend */
+ bl2_plat_mboot_init();
+
/* Initialize boot source */
bl2_plat_preload_setup();
/* Load the subsequent bootloader images. */
next_bl_ep_info = bl2_load_images();
-#if MEASURED_BOOT
- /* Finalize measured boot */
- measured_boot_finish();
-#endif /* MEASURED_BOOT */
+ /* Teardown the Measured Boot backend */
+ bl2_plat_mboot_finish();
-#if !BL2_AT_EL3
+#if !BL2_AT_EL3 && !ENABLE_RME
#ifndef __aarch64__
/*
* For AArch32 state BL1 and BL2 share the MMU setup.
@@ -140,7 +131,7 @@
* be passed to next BL image as an argument.
*/
smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0);
-#else /* if BL2_AT_EL3 */
+#else /* if BL2_AT_EL3 || ENABLE_RME */
NOTICE("BL2: Booting " NEXT_IMAGE "\n");
print_entry_point_info(next_bl_ep_info);
console_flush();
@@ -153,5 +144,5 @@
#endif /* ENABLE_PAUTH */
bl2_run_next_image(next_bl_ep_info);
-#endif /* BL2_AT_EL3 */
+#endif /* BL2_AT_EL3 && ENABLE_RME */
}
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 2d672dd..ed05864 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -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
*/
@@ -195,6 +195,19 @@
#endif
bl bl31_plat_enable_mmu
+#if ENABLE_RME
+ /*
+ * At warm boot GPT data structures have already been initialized in RAM
+ * but the sysregs for this CPU need to be initialized. Note that the GPT
+ * accesses are controlled attributes in GPCCR and do not depend on the
+ * SCR_EL3.C bit.
+ */
+ bl gpt_enable
+ cbz x0, 1f
+ no_ret plat_panic_handler
+1:
+#endif
+
#if ENABLE_PAUTH
/* --------------------------------------------------------------------
* Program APIAKey_EL1 and enable pointer authentication
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 51eb2bd..0d0a12d 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -500,6 +500,21 @@
stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ /* Clear flag register */
+ mov x7, xzr
+
+#if ENABLE_RME
+ /* Copy SCR_EL3.NSE bit to the flag to indicate caller's security */
+ ubfx x7, x18, #SCR_NSE_SHIFT, 1
+
+ /*
+ * Shift copied SCR_EL3.NSE bit by 5 to create space for
+ * SCR_EL3.NS bit. Bit 5 of the flag correspondes to
+ * the SCR_EL3.NSE bit.
+ */
+ lsl x7, x7, #5
+#endif /* ENABLE_RME */
+
/* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
bfi x7, x18, #0, #1
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 7819141..106d410 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -111,6 +111,13 @@
BL31_SOURCES += services/std_svc/pci_svc.c
endif
+ifeq (${ENABLE_RME},1)
+include lib/gpt_rme/gpt_rme.mk
+
+BL31_SOURCES += ${GPT_LIB_SRCS} \
+ ${RMMD_SOURCES}
+endif
+
BL31_LINKERFILE := bl31/bl31.ld.S
# Flag used to indicate if Crash reporting via console should be included
diff --git a/bl31/bl31_context_mgmt.c b/bl31/bl31_context_mgmt.c
index 9175ee3..34f69ad 100644
--- a/bl31/bl31_context_mgmt.c
+++ b/bl31/bl31_context_mgmt.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
*/
@@ -19,9 +19,9 @@
******************************************************************************/
void *cm_get_context(uint32_t security_state)
{
- assert(security_state <= NON_SECURE);
+ assert(sec_state_is_valid(security_state));
- return get_cpu_data(cpu_context[security_state]);
+ return get_cpu_data(cpu_context[get_cpu_context_index(security_state)]);
}
/*******************************************************************************
@@ -30,9 +30,10 @@
******************************************************************************/
void cm_set_context(void *context, uint32_t security_state)
{
- assert(security_state <= NON_SECURE);
+ assert(sec_state_is_valid(security_state));
- set_cpu_data(cpu_context[security_state], context);
+ set_cpu_data(cpu_context[get_cpu_context_index(security_state)],
+ context);
}
/*******************************************************************************
@@ -46,7 +47,8 @@
{
assert(sec_state_is_valid(security_state));
- return get_cpu_data_by_index(cpu_idx, cpu_context[security_state]);
+ return get_cpu_data_by_index(cpu_idx,
+ cpu_context[get_cpu_context_index(security_state)]);
}
/*******************************************************************************
@@ -58,5 +60,7 @@
{
assert(sec_state_is_valid(security_state));
- set_cpu_data_by_index(cpu_idx, cpu_context[security_state], context);
+ set_cpu_data_by_index(cpu_idx,
+ cpu_context[get_cpu_context_index(security_state)],
+ context);
}
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index f272af5..9ac10e2 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.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
*/
@@ -35,6 +35,13 @@
******************************************************************************/
static int32_t (*bl32_init)(void);
+/*****************************************************************************
+ * Function used to initialise RMM if RME is enabled
+ *****************************************************************************/
+#if ENABLE_RME
+static int32_t (*rmm_init)(void);
+#endif
+
/*******************************************************************************
* Variable to indicate whether next image to execute after BL31 is BL33
* (non-secure & default) or BL32 (secure).
@@ -139,12 +146,15 @@
/*
* All the cold boot actions on the primary cpu are done. We now need to
- * decide which is the next image (BL32 or BL33) and how to execute it.
+ * decide which is the next image and how to execute it.
* If the SPD runtime service is present, it would want to pass control
* to BL32 first in S-EL1. In that case, SPD would have registered a
* function to initialize bl32 where it takes responsibility of entering
- * S-EL1 and returning control back to bl31_main. Once this is done we
- * can prepare entry into BL33 as normal.
+ * S-EL1 and returning control back to bl31_main. Similarly, if RME is
+ * enabled and a function is registered to initialize RMM, control is
+ * transferred to RMM in R-EL2. After RMM initialization, control is
+ * returned back to bl31_main. Once this is done we can prepare entry
+ * into BL33 as normal.
*/
/*
@@ -155,9 +165,27 @@
int32_t rc = (*bl32_init)();
- if (rc == 0)
+ if (rc == 0) {
WARN("BL31: BL32 initialization failed\n");
+ }
+ }
+
+ /*
+ * If RME is enabled and init hook is registered, initialize RMM
+ * in R-EL2.
+ */
+#if ENABLE_RME
+ if (rmm_init != NULL) {
+ INFO("BL31: Initializing RMM\n");
+
+ int32_t rc = (*rmm_init)();
+
+ if (rc == 0) {
+ WARN("BL31: RMM initialization failed\n");
+ }
}
+#endif
+
/*
* We are ready to enter the next EL. Prepare entry into the image
* corresponding to the desired security state after the next ERET.
@@ -236,3 +264,14 @@
{
bl32_init = func;
}
+
+#if ENABLE_RME
+/*******************************************************************************
+ * This function initializes the pointer to RMM init function. This is expected
+ * to be called by the RMMD after it finishes all its initialization
+ ******************************************************************************/
+void bl31_register_rmm_init(int32_t (*func)(void))
+{
+ rmm_init = func;
+}
+#endif
diff --git a/common/bl_common.c b/common/bl_common.c
index a7e2816..eb2352a 100644
--- a/common/bl_common.c
+++ b/common/bl_common.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
*/
@@ -202,12 +202,26 @@
return -EAUTH;
}
- /*
- * Flush the image to main memory so that it can be executed later by
- * any CPU, regardless of cache and MMU state. This is only needed for
- * child images, not for the parents (certificates).
- */
if (is_parent_image == 0) {
+ /*
+ * Measure the image.
+ * We do not measure its parents because these only play a role
+ * in authentication, which is orthogonal to measured boot.
+ *
+ * TODO: Change this code if we change our minds about measuring
+ * certificates.
+ */
+ rc = plat_mboot_measure_image(image_id, image_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /*
+ * Flush the image to main memory so that it can be executed
+ * later by any CPU, regardless of cache and MMU state. This
+ * is only needed for child images, not for the parents
+ * (certificates).
+ */
flush_dcache_range(image_data->image_base,
image_data->image_size);
}
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 1bd4666..7db81fc 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -109,6 +109,16 @@
:|G|: `john-powell-arm`_
:|F|: bl31/ehf.c
+Realm Management Extension (RME)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Bipin Ravi <bipin.ravi@arm.com>
+:|G|: `bipinravi-arm`_
+:|M|: Mark Dykes <mark.dykes@arm.com>
+:|G|: `mardyk01`_
+:|M|: John Powell <John.Powell@arm.com>
+:|G|: `john-powell-arm`_
+:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:|G|: `zelalem-aweke`_
Drivers, Libraries and Framework Code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index 3e8dd91..b65571d 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -46,7 +46,7 @@
+-----------------+---------------------------+------------------------------+
| v2.5 | 3rd week of May '21 | 5th week of Apr '21 |
+-----------------+---------------------------+------------------------------+
-| v2.6 | 4th week of Oct '21 | 1st week of Oct '21 |
+| v2.6 | 4th week of Nov '21 | 2nd week of Nov '21 |
+-----------------+---------------------------+------------------------------+
Removal of Deprecated Interfaces
diff --git a/docs/components/index.rst b/docs/components/index.rst
index 2409f96..f349d8d 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -22,3 +22,4 @@
ffa-manifest-binding
xlat-tables-lib-v2-design
cot-binding
+ realm-management-extension
diff --git a/docs/components/measured_boot/event_log.rst b/docs/components/measured_boot/event_log.rst
index 5347dcc..0881248 100644
--- a/docs/components/measured_boot/event_log.rst
+++ b/docs/components/measured_boot/event_log.rst
@@ -9,7 +9,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Measured Boot driver expects a *tpm_event_log* node with the following field
-in 'nt_fw_config' and 'tsp_fw_config' DTS files:
+in 'tb_fw_config', 'nt_fw_config' and 'tsp_fw_config' DTS files:
- compatible [mandatory]
- value type: <string>
diff --git a/docs/components/realm-management-extension.rst b/docs/components/realm-management-extension.rst
new file mode 100644
index 0000000..5c580f3
--- /dev/null
+++ b/docs/components/realm-management-extension.rst
@@ -0,0 +1,194 @@
+
+Realm Management Extension (RME)
+====================================
+
+FEAT_RME (or RME for short) is an Armv9-A extension and is one component of the
+`Arm Confidential Compute Architecture (Arm CCA)`_. TF-A supports RME starting
+from version 2.6. This document provides instructions on how to build and run
+TF-A with RME.
+
+Building and running TF-A with RME
+------------------------------------
+
+This section describes how you can build and run TF-A with RME enabled.
+We assume you have all the :ref:`Prerequisites` to build TF-A.
+
+To enable RME, you need to set the ENABLE_RME build flag when building
+TF-A. Currently, this feature is only supported for the FVP platform.
+
+The following instructions show you how to build and run TF-A with RME
+for two scenarios: TF-A with TF-A Tests, and four-world execution with
+Hafnium and TF-A Tests. The instructions assume you have already obtained
+TF-A. You can use the following command to clone TF-A.
+
+.. code:: shell
+
+ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
+
+To run the tests, you need an FVP model. You can download a model that supports
+RME from the `Arm Architecture Models website`_. Please select the
+*Base RevC AEM FVP* model. After extracting the downloaded file, you should be able to
+find the *FVP_Base_RevC-2xAEMvA* binary. The instructions below have been tested
+with model version 11.15 revision 18.
+
+.. note::
+
+ ENABLE_RME build option is currently experimental.
+
+Building TF-A with TF-A Tests
+********************************************
+Use the following instructions to build TF-A with `TF-A Tests`_ as the
+non-secure payload (BL33).
+
+**1. Obtain and build TF-A Tests**
+
+.. code:: shell
+
+ git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git
+ cd tf-a-tests
+ make CROSS_COMPILE=aarch64-none-elf- PLAT=fvp DEBUG=1
+
+This produces a TF-A Tests binary (*tftf.bin*) in the *build/fvp/debug* directory.
+
+**2. Build TF-A**
+
+.. code:: shell
+
+ cd trusted-firmware-a
+ make CROSS_COMPILE=aarch64-none-elf- \
+ PLAT=fvp \
+ ENABLE_RME=1 \
+ FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
+ DEBUG=1 \
+ BL33=<path/to/tftf.bin> \
+ all fip
+
+This produces *bl1.bin* and *fip.bin* binaries in the *build/fvp/debug* directory.
+The above command also builds a Test Realm Payload (TRP), which is a small test
+payload that implements Realm Monitor Management (RMM) functionalities and runs
+in the realm world (R-EL2). The TRP binary is packaged in *fip.bin*.
+
+Four-world execution with Hafnium and TF-A Tests
+****************************************************
+Four-world execution involves software components at each security state: root,
+secure, realm and non-secure. This section describes how to build TF-A
+with four-world support. We use TF-A as the root firmware, `Hafnium`_ as the
+secure component, TRP as the realm-world firmware and TF-A Tests as the
+non-secure payload.
+
+Before building TF-A, you first need to build the other software components.
+You can find instructions on how to get and build TF-A Tests above.
+
+**1. Obtain and build Hafnium**
+
+.. code:: shell
+
+ git clone --recurse-submodules https://git.trustedfirmware.org/hafnium/hafnium.git
+ cd hafnium
+ make PROJECT=reference
+
+The Hafnium binary should be located at
+*out/reference/secure_aem_v8a_fvp_clang/hafnium.bin*
+
+**2. Build TF-A**
+
+Build TF-A with RME as well as SPM enabled.
+
+.. code:: shell
+
+ make CROSS_COMPILE=aarch64-none-elf- \
+ PLAT=fvp \
+ ENABLE_RME=1 \
+ FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
+ SPD=spmd \
+ SPMD_SPM_AT_SEL2=1 \
+ BRANCH_PROTECTION=1 \
+ CTX_INCLUDE_PAUTH_REGS=1 \
+ DEBUG=1 \
+ SP_LAYOUT_FILE=<path/to/tf-a-tests>/build/fvp/debug/sp_layout.json> \
+ BL32=<path/to/hafnium.bin> \
+ BL33=<path/to/tftf.bin> \
+ all fip
+
+Running the tests
+*********************
+Use the following command to run the tests on FVP. TF-A Tests should boot
+and run the default tests including RME tests.
+
+.. code:: shell
+
+ FVP_Base_RevC-2xAEMvA \
+ -C bp.flashloader0.fname=<path/to/fip.bin> \
+ -C bp.secureflashloader.fname=<path/to/bl1.bin> \
+ -C bp.refcounter.non_arch_start_at_default=1 \
+ -C bp.refcounter.use_real_time=0 \
+ -C bp.ve_sysregs.exit_on_shutdown=1 \
+ -C cache_state_modelled=1 \
+ -C cluster0.NUM_CORES=4 \
+ -C cluster0.PA_SIZE=48 \
+ -C cluster0.ecv_support_level=2 \
+ -C cluster0.gicv3.cpuintf-mmap-access-level=2 \
+ -C cluster0.gicv3.without-DS-support=1 \
+ -C cluster0.gicv4.mask-virtual-interrupt=1 \
+ -C cluster0.has_arm_v8-6=1 \
+ -C cluster0.has_branch_target_exception=1 \
+ -C cluster0.has_rme=1 \
+ -C cluster0.has_rndr=1 \
+ -C cluster0.has_amu=1 \
+ -C cluster0.has_v8_7_pmu_extension=2 \
+ -C cluster0.max_32bit_el=-1 \
+ -C cluster0.restriction_on_speculative_execution=2 \
+ -C cluster0.restriction_on_speculative_execution_aarch32=2 \
+ -C cluster1.NUM_CORES=4 \
+ -C cluster1.PA_SIZE=48 \
+ -C cluster1.ecv_support_level=2 \
+ -C cluster1.gicv3.cpuintf-mmap-access-level=2 \
+ -C cluster1.gicv3.without-DS-support=1 \
+ -C cluster1.gicv4.mask-virtual-interrupt=1 \
+ -C cluster1.has_arm_v8-6=1 \
+ -C cluster1.has_branch_target_exception=1 \
+ -C cluster1.has_rme=1 \
+ -C cluster1.has_rndr=1 \
+ -C cluster1.has_amu=1 \
+ -C cluster1.has_v8_7_pmu_extension=2 \
+ -C cluster1.max_32bit_el=-1 \
+ -C cluster1.restriction_on_speculative_execution=2 \
+ -C cluster1.restriction_on_speculative_execution_aarch32=2 \
+ -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0475 \
+ -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \
+ -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 \
+ -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 \
+ -C bp.pl011_uart0.out_file=uart0.log \
+ -C bp.pl011_uart1.out_file=uart1.log \
+ -C bp.pl011_uart2.out_file=uart2.log \
+ -C pctl.startup=0.0.0.0 \
+ -Q 1000 \
+ "$@"
+
+The bottom of the output from *uart0* should look something like the following.
+
+.. code-block:: shell
+
+ ...
+
+ > Test suite 'FF-A Interrupt'
+ Passed
+ > Test suite 'SMMUv3 tests'
+ Passed
+ > Test suite 'PMU Leakage'
+ Passed
+ > Test suite 'DebugFS'
+ Passed
+ > Test suite 'Realm payload tests'
+ Passed
+ ...
+
+
+.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture
+.. _Arm Architecture Models website: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models
+.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io/en/latest
+.. _Hafnium: https://www.trustedfirmware.org/projects/hafnium
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 7fe6ccd..1259881 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -271,6 +271,10 @@
be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in
software.
+- ``ENABLE_RME``: Boolean option to enable support for the ARMv9 Realm
+ Management Extension. Default value is 0. This is currently an experimental
+ feature.
+
- ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime
instrumentation which injects timestamp collection points into TF-A to
allow runtime performance to be measured. Currently, only PSCI is
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 54754fe..6569a47 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1199,6 +1199,25 @@
the SMCCC function specified in the argument; otherwise returns
SMC_ARCH_CALL_NOT_SUPPORTED.
+Function : plat_mboot_measure_image()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : unsigned int, image_info_t *
+ Return : void
+
+When the MEASURED_BOOT flag is enabled:
+
+- This function measures the given image and records its measurement using
+ the measured boot backend driver.
+- On the Arm FVP port, this function measures the given image using its
+ passed id and information and then records that measurement in the
+ Event Log buffer.
+- This function must return 0 on success, a negative error code otherwise.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
Modifications specific to a Boot Loader stage
---------------------------------------------
@@ -1450,6 +1469,42 @@
The default implementation of this function asserts therefore platforms must
override it when using the FWU feature.
+Function : bl1_plat_mboot_init() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : void
+
+When the MEASURED_BOOT flag is enabled:
+
+- This function is used to initialize the backend driver(s) of measured boot.
+- On the Arm FVP port, this function is used to initialize the Event Log
+ backend driver, and also to write header information in the Event Log buffer.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
+Function : bl1_plat_mboot_finish() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : void
+
+When the MEASURED_BOOT flag is enabled:
+
+- This function is used to finalize the measured boot backend driver(s),
+ and also, set the information for the next bootloader component to
+ extend the measurement if needed.
+- On the Arm FVP port, this function is used to pass the base address of
+ the Event Log buffer and its size to BL2 via tb_fw_config to extend the
+ Event Log buffer with the measurement of various images loaded by BL2.
+ It results in panic on error.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
Boot Loader Stage 2 (BL2)
-------------------------
@@ -1738,6 +1793,42 @@
This function returns 0 on success, a negative error code otherwise.
This function is included if SCP_BL2U_BASE is defined.
+Function : bl2_plat_mboot_init() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : void
+
+When the MEASURED_BOOT flag is enabled:
+
+- This function is used to initialize the backend driver(s) of measured boot.
+- On the Arm FVP port, this function is used to initialize the Event Log
+ backend driver with the Event Log buffer information (base address and
+ size) received from BL1. It results in panic on error.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
+Function : bl2_plat_mboot_finish() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : void
+
+When the MEASURED_BOOT flag is enabled:
+
+- This function is used to finalize the measured boot backend driver(s),
+ and also, set the information for the next bootloader component to extend
+ the measurement if needed.
+- On the Arm FVP port, this function is used to pass the Event Log buffer
+ information (base address and size) to non-secure(BL33) and trusted OS(BL32)
+ via nt_fw and tos_fw config respectively. It results in panic on error.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
Boot Loader Stage 3-1 (BL31)
----------------------------
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index b125144..6872f56 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -58,6 +58,7 @@
- a3700 - A3720 DB, EspressoBin and Turris MOX
- a70x0
- a70x0_amc - AMC board
+ - a70x0_mochabin - Globalscale MOCHAbin
- a80x0
- a80x0_mcbin - MacchiatoBin
- a80x0_puzzle - IEI Puzzle-M801
@@ -150,6 +151,16 @@
Specify path to the MSS fimware image binary which will run on Cortex-M3 coprocessor.
It is available in Marvell binaries-marvell git repository. Required when ``MSS_SUPPORT=1``.
+Globalscale MOCHAbin specific build options:
+
+- DDR_TOPOLOGY
+
+ The DDR topology map index/name, default is 0.
+
+ Supported Options:
+ - 0 - DDR4 1CS 2GB
+ - 1 - DDR4 1CS 4GB
+ - 2 - DDR4 2CS 8GB
Armada37x0 specific build options:
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c
index 0ad14a8..a3e414c 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.c
+++ b/drivers/marvell/comphy/phy-comphy-3700.c
@@ -815,6 +815,12 @@
debug_enter();
+ /* Configure phy selector for PCIe */
+ ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+ if (ret) {
+ return ret;
+ }
+
/* 1. Enable max PLL. */
reg_set16(LANE_CFG1_ADDR(PCIE) + COMPHY_SD_ADDR,
USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN);
diff --git a/drivers/measured_boot/event_log.c b/drivers/measured_boot/event_log.c
deleted file mode 100644
index 0157b03..0000000
--- a/drivers/measured_boot/event_log.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <arch_helpers.h>
-
-#include <common/bl_common.h>
-#include <common/debug.h>
-#include <drivers/auth/crypto_mod.h>
-#include <drivers/measured_boot/event_log.h>
-#include <mbedtls/md.h>
-
-#include <plat/common/platform.h>
-
-/* Event Log data */
-static uint8_t event_log[EVENT_LOG_SIZE];
-
-/* End of Event Log */
-#define EVENT_LOG_END ((uintptr_t)event_log + sizeof(event_log) - 1U)
-
-CASSERT(sizeof(event_log) >= LOG_MIN_SIZE, assert_event_log_size);
-
-/* Pointer in event_log[] */
-static uint8_t *log_ptr = event_log;
-
-/* Pointer to measured_boot_data_t */
-const static measured_boot_data_t *plat_data_ptr;
-
-static uintptr_t tos_fw_config_base;
-static uintptr_t nt_fw_config_base;
-
-/* TCG_EfiSpecIdEvent */
-static const id_event_headers_t id_event_header = {
- .header = {
- .pcr_index = PCR_0,
- .event_type = EV_NO_ACTION,
- .digest = {0},
- .event_size = (uint32_t)(sizeof(id_event_struct_t) +
- (sizeof(id_event_algorithm_size_t) *
- HASH_ALG_COUNT))
- },
-
- .struct_header = {
- .signature = TCG_ID_EVENT_SIGNATURE_03,
- .platform_class = PLATFORM_CLASS_CLIENT,
- .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
- .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
- .spec_errata = TCG_SPEC_ERRATA_TPM2,
- .uintn_size = (uint8_t)(sizeof(unsigned int) /
- sizeof(uint32_t)),
- .number_of_algorithms = HASH_ALG_COUNT
- }
-};
-
-static const event2_header_t locality_event_header = {
- /*
- * All EV_NO_ACTION events SHALL set
- * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
- */
- .pcr_index = PCR_0,
-
- /*
- * All EV_NO_ACTION events SHALL set
- * TCG_PCR_EVENT2.eventType = 03h
- */
- .event_type = EV_NO_ACTION,
-
- /*
- * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all
- * 0x00's for each allocated Hash algorithm
- */
- .digests = {
- .count = HASH_ALG_COUNT
- }
-};
-
-/*
- * Add TCG_PCR_EVENT2 event
- *
- * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes
- * @param[in] image_ptr Pointer to image_data_t structure
- *
- * There must be room for storing this new event into the event log buffer.
- */
-static void add_event2(const uint8_t *hash, const image_data_t *image_ptr)
-{
- void *ptr = log_ptr;
- uint32_t name_len;
-
- assert(image_ptr != NULL);
- assert(image_ptr->name != NULL);
-
- name_len = (uint32_t)strlen(image_ptr->name) + 1U;
-
- /* Check for space in Event Log buffer */
- assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) <=
- EVENT_LOG_END);
-
- /*
- * As per TCG specifications, firmware components that are measured
- * into PCR[0] must be logged in the event log using the event type
- * EV_POST_CODE.
- */
- /* TCG_PCR_EVENT2.PCRIndex */
- ((event2_header_t *)ptr)->pcr_index = image_ptr->pcr;
-
- /* TCG_PCR_EVENT2.EventType */
- ((event2_header_t *)ptr)->event_type = EV_POST_CODE;
-
- /* TCG_PCR_EVENT2.Digests.Count */
- ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
- ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
-
- /* TCG_PCR_EVENT2.Digests[] */
- ptr = (uint8_t *)((uintptr_t)ptr +
- offsetof(tpml_digest_values, digests));
-
- /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
- ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
-
- /* TCG_PCR_EVENT2.Digests[].Digest[] */
- ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
-
- if (hash == NULL) {
- /* Get BL2 hash from DTB */
- bl2_plat_get_hash(ptr);
- } else {
- /* Copy digest */
- (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
- }
-
- /* TCG_PCR_EVENT2.EventSize */
- ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE);
- ((event2_data_t *)ptr)->event_size = name_len;
-
- /* Copy event data to TCG_PCR_EVENT2.Event */
- (void)memcpy((void *)(((event2_data_t *)ptr)->event),
- (const void *)image_ptr->name, name_len);
-
- /* End of event data */
- log_ptr = (uint8_t *)((uintptr_t)ptr +
- offsetof(event2_data_t, event) + name_len);
-}
-
-/*
- * Init Event Log
- *
- * Initialises Event Log by writing Specification ID and
- * Startup Locality events.
- */
-void event_log_init(void)
-{
- const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
- void *ptr = event_log;
-
- /* Get pointer to platform's measured_boot_data_t structure */
- plat_data_ptr = plat_get_measured_boot_data();
-
- /*
- * Add Specification ID Event first
- *
- * Copy TCG_EfiSpecIDEventStruct structure header
- */
- (void)memcpy(ptr, (const void *)&id_event_header,
- sizeof(id_event_header));
- ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header));
-
- /* TCG_EfiSpecIdEventAlgorithmSize structure */
- ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
- ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
- ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t));
-
- /*
- * TCG_EfiSpecIDEventStruct.vendorInfoSize
- * No vendor data
- */
- ((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
- ptr = (uint8_t *)((uintptr_t)ptr +
- offsetof(id_event_struct_data_t, vendor_info));
-
- /*
- * The Startup Locality event should be placed in the log before
- * any event which extends PCR[0].
- *
- * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
- */
-
- /* Copy Startup Locality Event Header */
- (void)memcpy(ptr, (const void *)&locality_event_header,
- sizeof(locality_event_header));
- ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header));
-
- /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
- ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
-
- /* TCG_PCR_EVENT2.Digests[].Digest[] */
- (void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID);
- ptr = (uint8_t *)((uintptr_t)ptr +
- offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE);
-
- /* TCG_PCR_EVENT2.EventSize */
- ((event2_data_t *)ptr)->event_size =
- (uint32_t)sizeof(startup_locality_event_t);
- ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
-
- /* TCG_EfiStartupLocalityEvent.Signature */
- (void)memcpy(ptr, (const void *)locality_signature,
- sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
-
- /*
- * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
- * the platform's boot firmware
- */
- ((startup_locality_event_t *)ptr)->startup_locality = 0U;
- ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t));
-
- log_ptr = (uint8_t *)ptr;
-
- /* Add BL2 event */
- add_event2(NULL, plat_data_ptr->images_data);
-}
-
-/*
- * Calculate and write hash of image, configuration data, etc.
- * to Event Log.
- *
- * @param[in] data_base Address of data
- * @param[in] data_size Size of data
- * @param[in] data_id Data ID
- * @return:
- * 0 = success
- * < 0 = error
- */
-int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
- uint32_t data_id)
-{
- const image_data_t *data_ptr = plat_data_ptr->images_data;
- unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
- int rc;
-
- /* Get the metadata associated with this image. */
- while ((data_ptr->id != INVALID_ID) && (data_ptr->id != data_id)) {
- data_ptr++;
- }
- assert(data_ptr->id != INVALID_ID);
-
- if (data_id == TOS_FW_CONFIG_ID) {
- tos_fw_config_base = data_base;
- } else if (data_id == NT_FW_CONFIG_ID) {
- nt_fw_config_base = data_base;
- } else {
- /* No action */
- }
-
- /* Calculate hash */
- rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
- (void *)data_base, data_size, hash_data);
- if (rc != 0) {
- return rc;
- }
-
- add_event2(hash_data, data_ptr);
- return 0;
-}
-
-/*
- * Finalise Event Log
- *
- * @param[out] log_addr Pointer to return Event Log address
- * @param[out] log_size Pointer to return Event Log size
- * @return:
- * 0 = success
- * < 0 = error code
- */
-int event_log_finalise(uint8_t **log_addr, size_t *log_size)
-{
- /* Event Log size */
- size_t num_bytes = (uintptr_t)log_ptr - (uintptr_t)event_log;
- int rc;
-
- assert(log_addr != NULL);
- assert(log_size != NULL);
-
- if (nt_fw_config_base == 0UL) {
- ERROR("%s(): %s_FW_CONFIG not loaded\n", __func__, "NT");
- return -ENOENT;
- }
-
- /*
- * Set Event Log data in NT_FW_CONFIG and
- * get Event Log address in Non-Secure memory
- */
- if (plat_data_ptr->set_nt_fw_info != NULL) {
-
- /* Event Log address in Non-Secure memory */
- uintptr_t ns_log_addr;
-
- rc = plat_data_ptr->set_nt_fw_info(
- nt_fw_config_base,
-#ifdef SPD_opteed
- (uintptr_t)event_log,
-#endif
- num_bytes, &ns_log_addr);
- if (rc != 0) {
- ERROR("%s(): Unable to update %s_FW_CONFIG\n",
- __func__, "NT");
- return rc;
- }
-
- /* Copy Event Log to Non-secure memory */
- (void)memcpy((void *)ns_log_addr, (const void *)event_log,
- num_bytes);
-
- /* Ensure that the Event Log is visible in Non-secure memory */
- flush_dcache_range(ns_log_addr, num_bytes);
-
- /* Return Event Log address in Non-Secure memory */
- *log_addr = (uint8_t *)ns_log_addr;
-
- } else {
- INFO("%s(): set_%s_fw_info not set\n", __func__, "nt");
-
- /* Return Event Log address in Secure memory */
- *log_addr = event_log;
- }
-
- if (tos_fw_config_base != 0UL) {
- if (plat_data_ptr->set_tos_fw_info != NULL) {
-
- /* Set Event Log data in TOS_FW_CONFIG */
- rc = plat_data_ptr->set_tos_fw_info(
- tos_fw_config_base,
- (uintptr_t)event_log,
- num_bytes);
- if (rc != 0) {
- ERROR("%s(): Unable to update %s_FW_CONFIG\n",
- __func__, "TOS");
- return rc;
- }
- } else {
- INFO("%s(): set_%s_fw_info not set\n", __func__, "tos");
- }
- } else {
- INFO("%s(): %s_FW_CONFIG not loaded\n", __func__, "TOS");
- }
-
- /* Ensure that the Event Log is visible in Secure memory */
- flush_dcache_range((uintptr_t)event_log, num_bytes);
-
- /* Return Event Log size */
- *log_size = num_bytes;
-
- return 0;
-}
diff --git a/drivers/measured_boot/event_log/event_log.c b/drivers/measured_boot/event_log/event_log.c
new file mode 100644
index 0000000..1755dd9
--- /dev/null
+++ b/drivers/measured_boot/event_log/event_log.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <arch_helpers.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <mbedtls/md.h>
+
+#include <plat/common/platform.h>
+
+/* Running Event Log Pointer */
+static uint8_t *log_ptr;
+
+/* Pointer to the first byte past end of the Event Log buffer */
+static uintptr_t log_end;
+
+/* Pointer to event_log_metadata_t */
+static const event_log_metadata_t *plat_metadata_ptr;
+
+/* TCG_EfiSpecIdEvent */
+static const id_event_headers_t id_event_header = {
+ .header = {
+ .pcr_index = PCR_0,
+ .event_type = EV_NO_ACTION,
+ .digest = {0},
+ .event_size = (uint32_t)(sizeof(id_event_struct_t) +
+ (sizeof(id_event_algorithm_size_t) *
+ HASH_ALG_COUNT))
+ },
+
+ .struct_header = {
+ .signature = TCG_ID_EVENT_SIGNATURE_03,
+ .platform_class = PLATFORM_CLASS_CLIENT,
+ .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
+ .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
+ .spec_errata = TCG_SPEC_ERRATA_TPM2,
+ .uintn_size = (uint8_t)(sizeof(unsigned int) /
+ sizeof(uint32_t)),
+ .number_of_algorithms = HASH_ALG_COUNT
+ }
+};
+
+static const event2_header_t locality_event_header = {
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
+ */
+ .pcr_index = PCR_0,
+
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.eventType = 03h
+ */
+ .event_type = EV_NO_ACTION,
+
+ /*
+ * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all
+ * 0x00's for each allocated Hash algorithm
+ */
+ .digests = {
+ .count = HASH_ALG_COUNT
+ }
+};
+
+/*
+ * Record a measurement as a TCG_PCR_EVENT2 event
+ *
+ * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes
+ * @param[in] metadata_ptr Pointer to event_log_metadata_t structure
+ *
+ * There must be room for storing this new event into the event log buffer.
+ */
+static void event_log_record(const uint8_t *hash,
+ const event_log_metadata_t *metadata_ptr)
+{
+ void *ptr = log_ptr;
+ uint32_t name_len;
+
+ assert(hash != NULL);
+ assert(metadata_ptr != NULL);
+ assert(metadata_ptr->name != NULL);
+ /* event_log_init() must have been called prior to this. */
+ assert(log_ptr != NULL);
+
+ name_len = (uint32_t)strlen(metadata_ptr->name) + 1U;
+
+ /* Check for space in Event Log buffer */
+ assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) <
+ log_end);
+
+ /*
+ * As per TCG specifications, firmware components that are measured
+ * into PCR[0] must be logged in the event log using the event type
+ * EV_POST_CODE.
+ */
+ /* TCG_PCR_EVENT2.PCRIndex */
+ ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr;
+
+ /* TCG_PCR_EVENT2.EventType */
+ ((event2_header_t *)ptr)->event_type = EV_POST_CODE;
+
+ /* TCG_PCR_EVENT2.Digests.Count */
+ ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
+ ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
+
+ /* TCG_PCR_EVENT2.Digests[] */
+ ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(tpml_digest_values, digests));
+
+ /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+ ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+ /* TCG_PCR_EVENT2.Digests[].Digest[] */
+ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
+
+ /* Copy digest */
+ (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
+
+ /* TCG_PCR_EVENT2.EventSize */
+ ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE);
+ ((event2_data_t *)ptr)->event_size = name_len;
+
+ /* Copy event data to TCG_PCR_EVENT2.Event */
+ (void)memcpy((void *)(((event2_data_t *)ptr)->event),
+ (const void *)metadata_ptr->name, name_len);
+
+ /* End of event data */
+ log_ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(event2_data_t, event) + name_len);
+}
+
+/*
+ * Initialise Event Log global variables, used during the recording
+ * of various payload measurements into the Event Log buffer
+ *
+ * @param[in] event_log_start Base address of Event Log buffer
+ * @param[in] event_log_finish End address of Event Log buffer,
+ * it is a first byte past end of the
+ * buffer
+ */
+void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+{
+ assert(event_log_start != NULL);
+ assert(event_log_finish > event_log_start);
+
+ log_ptr = event_log_start;
+ log_end = (uintptr_t)event_log_finish;
+
+ /* Get pointer to platform's event_log_metadata_t structure */
+ plat_metadata_ptr = plat_event_log_get_metadata();
+ assert(plat_metadata_ptr != NULL);
+}
+
+/*
+ * Initialises Event Log by writing Specification ID and
+ * Startup Locality events
+ */
+void event_log_write_header(void)
+{
+ const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
+ void *ptr = log_ptr;
+
+ /* event_log_init() must have been called prior to this. */
+ assert(log_ptr != NULL);
+
+ /*
+ * Add Specification ID Event first
+ *
+ * Copy TCG_EfiSpecIDEventStruct structure header
+ */
+ (void)memcpy(ptr, (const void *)&id_event_header,
+ sizeof(id_event_header));
+ ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header));
+
+ /* TCG_EfiSpecIdEventAlgorithmSize structure */
+ ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
+ ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
+ ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t));
+
+ /*
+ * TCG_EfiSpecIDEventStruct.vendorInfoSize
+ * No vendor data
+ */
+ ((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
+ ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(id_event_struct_data_t, vendor_info));
+
+ /*
+ * The Startup Locality event should be placed in the log before
+ * any event which extends PCR[0].
+ *
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+
+ /* Copy Startup Locality Event Header */
+ (void)memcpy(ptr, (const void *)&locality_event_header,
+ sizeof(locality_event_header));
+ ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header));
+
+ /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+ ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+ /* TCG_PCR_EVENT2.Digests[].Digest[] */
+ (void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID);
+ ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE);
+
+ /* TCG_PCR_EVENT2.EventSize */
+ ((event2_data_t *)ptr)->event_size =
+ (uint32_t)sizeof(startup_locality_event_t);
+ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
+
+ /* TCG_EfiStartupLocalityEvent.Signature */
+ (void)memcpy(ptr, (const void *)locality_signature,
+ sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
+
+ /*
+ * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
+ * the platform's boot firmware
+ */
+ ((startup_locality_event_t *)ptr)->startup_locality = 0U;
+ log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t));
+}
+
+/*
+ * Calculate and write hash of image, configuration data, etc.
+ * to Event Log.
+ *
+ * @param[in] data_base Address of data
+ * @param[in] data_size Size of data
+ * @param[in] data_id Data ID
+ * @return:
+ * 0 = success
+ * < 0 = error
+ */
+int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id)
+{
+ unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
+ int rc;
+ const event_log_metadata_t *metadata_ptr = plat_metadata_ptr;
+
+ /* Get the metadata associated with this image. */
+ while ((metadata_ptr->id != INVALID_ID) &&
+ (metadata_ptr->id != data_id)) {
+ metadata_ptr++;
+ }
+ assert(metadata_ptr->id != INVALID_ID);
+
+ /* Calculate hash */
+ rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
+ (void *)data_base, data_size, hash_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ event_log_record(hash_data, metadata_ptr);
+
+ return 0;
+}
+
+/*
+ * Get current Event Log buffer size i.e. used space of Event Log buffer
+ *
+ * @param[in] event_log_start Base Pointer to Event Log buffer
+ *
+ * @return: current Size of Event Log buffer
+ */
+size_t event_log_get_cur_size(uint8_t *event_log_start)
+{
+ assert(event_log_start != NULL);
+ assert(log_ptr >= event_log_start);
+
+ return (size_t)((uintptr_t)log_ptr - (uintptr_t)event_log_start);
+}
diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/event_log/event_log.mk
similarity index 63%
rename from drivers/measured_boot/measured_boot.mk
rename to drivers/measured_boot/event_log/event_log.mk
index 497fdba..37e5e29 100644
--- a/drivers/measured_boot/measured_boot.mk
+++ b/drivers/measured_boot/event_log/event_log.mk
@@ -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
#
@@ -7,7 +7,8 @@
# Default log level to dump the event log (LOG_LEVEL_INFO)
EVENT_LOG_LEVEL ?= 40
-# TPM hash algorithm
+# TPM hash algorithm.
+# SHA-256 (or stronger) is required for all devices that are TPM 2.0 compliant.
TPM_HASH_ALG := sha256
ifeq (${TPM_HASH_ALG}, sha512)
@@ -24,8 +25,6 @@
TCG_DIGEST_SIZE := 32U
endif
-# Event Log length in bytes
-EVENT_LOG_SIZE := 1024
# Set definitions for mbed TLS library and Measured Boot driver
$(eval $(call add_defines,\
@@ -33,20 +32,19 @@
MBEDTLS_MD_ID \
TPM_ALG_ID \
TCG_DIGEST_SIZE \
- EVENT_LOG_SIZE \
EVENT_LOG_LEVEL \
)))
ifeq (${HASH_ALG}, sha256)
-ifneq (${TPM_HASH_ALG}, sha256)
-$(eval $(call add_define,MBEDTLS_SHA512_C))
-endif
+ ifneq (${TPM_HASH_ALG}, sha256)
+ $(eval $(call add_define,MBEDTLS_SHA512_C))
+ endif
endif
-MEASURED_BOOT_SRC_DIR := drivers/measured_boot/
+MEASURED_BOOT_SRC_DIR := drivers/measured_boot/event_log/
-MEASURED_BOOT_SOURCES := ${MEASURED_BOOT_SRC_DIR}measured_boot.c \
- ${MEASURED_BOOT_SRC_DIR}event_log.c \
- ${MEASURED_BOOT_SRC_DIR}event_print.c
+MEASURED_BOOT_SOURCES := ${MEASURED_BOOT_SRC_DIR}event_log.c \
+ ${MEASURED_BOOT_SRC_DIR}event_print.c
BL2_SOURCES += ${MEASURED_BOOT_SOURCES}
+BL1_SOURCES += ${MEASURED_BOOT_SOURCES}
diff --git a/drivers/measured_boot/event_print.c b/drivers/measured_boot/event_log/event_print.c
similarity index 98%
rename from drivers/measured_boot/event_print.c
rename to drivers/measured_boot/event_log/event_print.c
index 84ed4b1..e2ba174 100644
--- a/drivers/measured_boot/event_print.c
+++ b/drivers/measured_boot/event_log/event_print.c
@@ -8,7 +8,7 @@
#include <string.h>
#include <common/debug.h>
-#include <drivers/measured_boot/event_log.h>
+#include <drivers/measured_boot/event_log/event_log.h>
#if LOG_LEVEL >= EVENT_LOG_LEVEL
diff --git a/drivers/measured_boot/measured_boot.c b/drivers/measured_boot/measured_boot.c
deleted file mode 100644
index 37fddfb..0000000
--- a/drivers/measured_boot/measured_boot.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <common/debug.h>
-#include <drivers/measured_boot/measured_boot.h>
-
-/*
- * Init Measured Boot driver
- *
- * Initialises Event Log.
- */
-void measured_boot_init(void)
-{
- event_log_init();
-}
-
-/*
- * Finish Measured Boot driver
- *
- * Finalises Event Log and dumps the records to the debug console.
- */
-void measured_boot_finish(void)
-{
- uint8_t *log_addr;
- size_t log_size;
- int rc;
-
- rc = event_log_finalise(&log_addr, &log_size);
- if (rc != 0) {
- panic();
- }
-
- dump_event_log(log_addr, log_size);
-}
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index b6753de..3cb613f 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -24,7 +24,11 @@
#address-cells = <2>;
#size-cells = <2>;
- chosen { };
+#if (ENABLE_RME == 1)
+ chosen { bootargs = "mem=1G console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda ip=on";};
+#else
+ chosen {};
+#endif
aliases {
serial0 = &v2m_serial0;
@@ -135,8 +139,13 @@
memory@80000000 {
device_type = "memory";
+#if (ENABLE_RME == 1)
+ reg = <0x00000000 0x80000000 0 0x7C000000>,
+ <0x00000008 0x80000000 0 0x80000000>;
+#else
reg = <0x00000000 0x80000000 0 0x7F000000>,
<0x00000008 0x80000000 0 0x80000000>;
+#endif
};
gic: interrupt-controller@2f000000 {
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 1b3ae02..74bc8cb 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -182,6 +182,11 @@
#define ID_AA64PFR0_CSV2_SHIFT U(56)
#define ID_AA64PFR0_CSV2_MASK ULL(0xf)
#define ID_AA64PFR0_CSV2_LENGTH U(4)
+#define ID_AA64PFR0_FEAT_RME_SHIFT U(52)
+#define ID_AA64PFR0_FEAT_RME_MASK ULL(0xf)
+#define ID_AA64PFR0_FEAT_RME_LENGTH U(4)
+#define ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED U(0)
+#define ID_AA64PFR0_FEAT_RME_V1 U(1)
/* Exception level handling */
#define EL_IMPL_NONE ULL(0)
@@ -432,6 +437,9 @@
/* SCR definitions */
#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5))
+#define SCR_NSE_SHIFT U(62)
+#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT)
+#define SCR_GPF_BIT (UL(1) << 48)
#define SCR_TWEDEL_SHIFT U(30)
#define SCR_TWEDEL_MASK ULL(0xf)
#define SCR_HXEn_BIT (UL(1) << 38)
@@ -440,6 +448,7 @@
#define SCR_ECVEN_BIT (UL(1) << 28)
#define SCR_FGTEN_BIT (UL(1) << 27)
#define SCR_ATA_BIT (UL(1) << 26)
+#define SCR_EnSCXT_BIT (UL(1) << 25)
#define SCR_FIEN_BIT (UL(1) << 21)
#define SCR_EEL2_BIT (UL(1) << 18)
#define SCR_API_BIT (UL(1) << 17)
@@ -576,6 +585,10 @@
#define CPTR_EL2_TZ_BIT (U(1) << 8)
#define CPTR_EL2_RESET_VAL CPTR_EL2_RES1
+/* VTCR_EL2 definitions */
+#define VTCR_RESET_VAL U(0x0)
+#define VTCR_EL2_MSA (U(1) << 31)
+
/* CPSR/SPSR definitions */
#define DAIF_FIQ_BIT (U(1) << 0)
#define DAIF_IRQ_BIT (U(1) << 1)
@@ -601,6 +614,7 @@
#define SPSR_M_MASK U(0x1)
#define SPSR_M_AARCH64 U(0x0)
#define SPSR_M_AARCH32 U(0x1)
+#define SPSR_M_EL2H U(0x9)
#define SPSR_EL_SHIFT U(2)
#define SPSR_EL_WIDTH U(2)
@@ -1093,6 +1107,12 @@
#define AMEVCNTVOFF1F_EL2 S3_4_C13_C11_7
/*******************************************************************************
+ * Realm management extension register definitions
+ ******************************************************************************/
+#define GPCCR_EL3 S3_6_C2_C1_6
+#define GPTBR_EL3 S3_6_C2_C1_4
+
+/*******************************************************************************
* RAS system registers
******************************************************************************/
#define DISR_EL1 S3_0_C12_C1_1
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 3ff67e5..46cd1c9 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -123,4 +123,15 @@
ID_AA64MMFR1_EL1_HCX_MASK) == ID_AA64MMFR1_EL1_HCX_SUPPORTED);
}
+static inline unsigned int get_armv9_2_feat_rme_support(void)
+{
+ /*
+ * Return the RME version, zero if not supported. This function can be
+ * used as both an integer value for the RME version or compared to zero
+ * to detect RME presence.
+ */
+ return (unsigned int)(read_id_aa64pfr0_el1() >>
+ ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK;
+}
+
#endif /* ARCH_FEATURES_H */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 72b87c8..cae05dc 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -442,6 +442,8 @@
DEFINE_SYSREG_READ_FUNC(cntpct_el0)
DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
+DEFINE_SYSREG_RW_FUNCS(vtcr_el2)
+
#define get_cntp_ctl_enable(x) (((x) >> CNTP_CTL_ENABLE_SHIFT) & \
CNTP_CTL_ENABLE_MASK)
#define get_cntp_ctl_imask(x) (((x) >> CNTP_CTL_IMASK_SHIFT) & \
@@ -540,6 +542,10 @@
/* DynamIQ Shared Unit power management */
DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
+/* Armv9.2 RME Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)
+
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
@@ -583,7 +589,28 @@
}
}
+/*
+ * TLBIPAALLOS instruction
+ * (TLB Inivalidate GPT Information by PA,
+ * All Entries, Outer Shareable)
+ */
+static inline void tlbipaallos(void)
+{
+ __asm__("SYS #6,c8,c1,#4");
+}
+
+/*
+ * Invalidate cached copies of GPT entries
+ * from TLBs by physical address
+ *
+ * @pa: the starting address for the range
+ * of invalidation
+ * @size: size of the range of invalidation
+ */
+void gpt_tlbi_by_pa(uint64_t pa, size_t size);
+
+
-/* Previously defined accesor functions with incomplete register names */
+/* Previously defined accessor functions with incomplete register names */
#define read_current_el() read_CurrentEl()
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index d496584..7d6a963 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -88,6 +88,13 @@
*/
orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT)
#endif
+#if ENABLE_RME
+ /*
+ * TODO: Settting the EEL2 bit to allow EL3 access to secure only registers
+ * in context management. This will need to be refactored.
+ */
+ orr x0, x0, #SCR_EEL2_BIT
+#endif
msr scr_el3, x0
/* ---------------------------------------------------------------------
@@ -365,6 +372,7 @@
msr vbar_el3, x0
isb
+#if !(defined(IMAGE_BL2) && ENABLE_RME)
/* ---------------------------------------------------------------------
* It is a cold boot.
* Perform any processor specific actions upon reset e.g. cache, TLB
@@ -372,6 +380,7 @@
* ---------------------------------------------------------------------
*/
bl reset_handler
+#endif
el3_arch_init_common
@@ -414,7 +423,8 @@
* ---------------------------------------------------------------------
*/
.if \_init_c_runtime
-#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_INV_DCACHE)
+#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \
+ ((BL2_AT_EL3 && BL2_INV_DCACHE) || ENABLE_RME))
/* -------------------------------------------------------------
* Invalidate the RW memory used by the BL31 image. This
* includes the data and NOBITS sections. This is done to
diff --git a/include/bl31/bl31.h b/include/bl31/bl31.h
index 3deb0a5..1d58ef9 100644
--- a/include/bl31/bl31.h
+++ b/include/bl31/bl31.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,6 +19,7 @@
uint32_t bl31_get_next_image_type(void);
void bl31_prepare_next_image_entry(void);
void bl31_register_bl32_init(int32_t (*func)(void));
+void bl31_register_rmm_init(int32_t (*func)(void));
void bl31_warm_entrypoint(void);
void bl31_main(void);
void bl31_lib_init(void);
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index e33840c..8cb4990 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -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
*/
@@ -126,6 +126,8 @@
IMPORT_SYM(uintptr_t, __BL31_END__, BL31_END);
#elif defined(IMAGE_BL32)
IMPORT_SYM(uintptr_t, __BL32_END__, BL32_END);
+#elif defined(IMAGE_RMM)
+IMPORT_SYM(uintptr_t, __RMM_END__, RMM_END);
#endif /* IMAGE_BLX */
/* The following symbols are only exported from the BL2 at EL3 linker script. */
diff --git a/include/common/ep_info.h b/include/common/ep_info.h
index 4bfa1fa..771572c 100644
--- a/include/common/ep_info.h
+++ b/include/common/ep_info.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,14 +18,21 @@
#define SECURE EP_SECURE
#define NON_SECURE EP_NON_SECURE
+#define REALM EP_REALM
+#if ENABLE_RME
+#define sec_state_is_valid(s) (((s) == SECURE) || \
+ ((s) == NON_SECURE) || \
+ ((s) == REALM))
+#else
#define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE))
+#endif
#define PARAM_EP_SECURITY_MASK EP_SECURITY_MASK
#define NON_EXECUTABLE EP_NON_EXECUTABLE
#define EXECUTABLE EP_EXECUTABLE
-/* Secure or Non-secure image */
+/* Get/set security state of an image */
#define GET_SECURITY_STATE(x) ((x) & EP_SECURITY_MASK)
#define SET_SECURITY_STATE(x, security) \
((x) = ((x) & ~EP_SECURITY_MASK) | (security))
diff --git a/include/drivers/measured_boot/event_log.h b/include/drivers/measured_boot/event_log.h
deleted file mode 100644
index efde117..0000000
--- a/include/drivers/measured_boot/event_log.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef EVENT_LOG_H
-#define EVENT_LOG_H
-
-#include <stdint.h>
-
-#include <common/debug.h>
-#include <drivers/measured_boot/tcg.h>
-
-/*
- * Set Event Log debug level to one of:
- *
- * LOG_LEVEL_ERROR
- * LOG_LEVEL_INFO
- * LOG_LEVEL_WARNING
- * LOG_LEVEL_VERBOSE
- */
-#if EVENT_LOG_LEVEL == LOG_LEVEL_ERROR
-#define LOG_EVENT ERROR
-#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
-#define LOG_EVENT NOTICE
-#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
-#define LOG_EVENT WARN
-#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
-#define LOG_EVENT INFO
-#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
-#define LOG_EVENT VERBOSE
-#else
-#error "Not supported EVENT_LOG_LEVEL"
-#endif
-
-/* Number of hashing algorithms supported */
-#define HASH_ALG_COUNT 1U
-
-#define INVALID_ID MAX_NUMBER_IDS
-
-#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
-
-#define BL2_STRING "BL_2"
-#define BL31_STRING "BL_31"
-#define BL32_STRING "BL_32"
-#define BL32_EXTRA1_IMAGE_STRING "BL32_EXTRA1_IMAGE"
-#define BL32_EXTRA2_IMAGE_STRING "BL32_EXTRA2_IMAGE"
-#define BL33_STRING "BL_33"
-#define GPT_IMAGE_STRING "GPT"
-#define HW_CONFIG_STRING "HW_CONFIG"
-#define NT_FW_CONFIG_STRING "NT_FW_CONFIG"
-#define SCP_BL2_IMAGE_STRING "SCP_BL2_IMAGE"
-#define SOC_FW_CONFIG_STRING "SOC_FW_CONFIG"
-#define STM32_IMAGE_STRING "STM32"
-#define TOS_FW_CONFIG_STRING "TOS_FW_CONFIG"
-
-typedef struct {
- unsigned int id;
- const char *name;
- unsigned int pcr;
-} image_data_t;
-
-typedef struct {
- const image_data_t *images_data;
- int (*set_nt_fw_info)(uintptr_t config_base,
-#ifdef SPD_opteed
- uintptr_t log_addr,
-#endif
- size_t log_size, uintptr_t *ns_log_addr);
- int (*set_tos_fw_info)(uintptr_t config_base, uintptr_t log_addr,
- size_t log_size);
-} measured_boot_data_t;
-
-#define ID_EVENT_SIZE (sizeof(id_event_headers_t) + \
- (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
- sizeof(id_event_struct_data_t))
-
-#define LOC_EVENT_SIZE (sizeof(event2_header_t) + \
- sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
- sizeof(event2_data_t) + \
- sizeof(startup_locality_event_t))
-
-#define LOG_MIN_SIZE (ID_EVENT_SIZE + LOC_EVENT_SIZE)
-
-#define EVENT2_HDR_SIZE (sizeof(event2_header_t) + \
- sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
- sizeof(event2_data_t))
-
-/* Functions' declarations */
-void event_log_init(void);
-int event_log_finalise(uint8_t **log_addr, size_t *log_size);
-void dump_event_log(uint8_t *log_addr, size_t log_size);
-const measured_boot_data_t *plat_get_measured_boot_data(void);
-int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
- uint32_t data_id);
-#endif /* EVENT_LOG_H */
diff --git a/include/drivers/measured_boot/event_log/event_log.h b/include/drivers/measured_boot/event_log/event_log.h
new file mode 100644
index 0000000..c6eb29c
--- /dev/null
+++ b/include/drivers/measured_boot/event_log/event_log.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_H
+#define EVENT_LOG_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/measured_boot/event_log/tcg.h>
+
+/*
+ * Set Event Log debug level to one of:
+ *
+ * LOG_LEVEL_ERROR
+ * LOG_LEVEL_INFO
+ * LOG_LEVEL_WARNING
+ * LOG_LEVEL_VERBOSE
+ */
+#if EVENT_LOG_LEVEL == LOG_LEVEL_ERROR
+#define LOG_EVENT ERROR
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
+#define LOG_EVENT NOTICE
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
+#define LOG_EVENT WARN
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
+#define LOG_EVENT INFO
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
+#define LOG_EVENT VERBOSE
+#else
+#error "Not supported EVENT_LOG_LEVEL"
+#endif
+
+/* Number of hashing algorithms supported */
+#define HASH_ALG_COUNT 1U
+
+#define INVALID_ID MAX_NUMBER_IDS
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+/*
+ * Each event log entry has some metadata (i.e. a string) that identifies
+ * what is measured.These macros define these strings.
+ * Note that these strings follow the standardization recommendations
+ * defined in the Arm Server Base Security Guide (a.k.a. SBSG, Arm DEN 0086),
+ * where applicable. They should not be changed in the code.
+ * Where the SBSG does not make recommendations, we are free to choose any
+ * naming convention.
+ * The key thing is to choose meaningful strings so that when the TPM event
+ * log is used in attestation, the different components can be identified.
+ */
+#define EVLOG_BL2_STRING "BL_2"
+#define EVLOG_BL31_STRING "SECURE_RT_EL3"
+#if defined(SPD_opteed)
+#define EVLOG_BL32_STRING "SECURE_RT_EL1_OPTEE"
+#elif defined(SPD_tspd)
+#define EVLOG_BL32_STRING "SECURE_RT_EL1_TSPD"
+#elif defined(SPD_tlkd)
+#define EVLOG_BL32_STRING "SECURE_RT_EL1_TLKD"
+#elif defined(SPD_trusty)
+#define EVLOG_BL32_STRING "SECURE_RT_EL1_TRUSTY"
+#else
+#define EVLOG_BL32_STRING "SECURE_RT_EL1_UNKNOWN"
+#endif
+#define EVLOG_BL32_EXTRA1_STRING "SECURE_RT_EL1_OPTEE_EXTRA1"
+#define EVLOG_BL32_EXTRA2_STRING "SECURE_RT_EL1_OPTEE_EXTRA2"
+#define EVLOG_BL33_STRING "BL_33"
+#define EVLOG_FW_CONFIG_STRING "FW_CONFIG"
+#define EVLOG_HW_CONFIG_STRING "HW_CONFIG"
+#define EVLOG_NT_FW_CONFIG_STRING "NT_FW_CONFIG"
+#define EVLOG_SCP_BL2_STRING "SYS_CTRL_2"
+#define EVLOG_SOC_FW_CONFIG_STRING "SOC_FW_CONFIG"
+#define EVLOG_STM32_STRING "STM32"
+#define EVLOG_TB_FW_CONFIG_STRING "TB_FW_CONFIG"
+#define EVLOG_TOS_FW_CONFIG_STRING "TOS_FW_CONFIG"
+
+typedef struct {
+ unsigned int id;
+ const char *name;
+ unsigned int pcr;
+} event_log_metadata_t;
+
+#define ID_EVENT_SIZE (sizeof(id_event_headers_t) + \
+ (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
+ sizeof(id_event_struct_data_t))
+
+#define LOC_EVENT_SIZE (sizeof(event2_header_t) + \
+ sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+ sizeof(event2_data_t) + \
+ sizeof(startup_locality_event_t))
+
+#define LOG_MIN_SIZE (ID_EVENT_SIZE + LOC_EVENT_SIZE)
+
+#define EVENT2_HDR_SIZE (sizeof(event2_header_t) + \
+ sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+ sizeof(event2_data_t))
+
+/* Functions' declarations */
+void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish);
+void event_log_write_header(void);
+void dump_event_log(uint8_t *log_addr, size_t log_size);
+const event_log_metadata_t *plat_event_log_get_metadata(void);
+int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id);
+size_t event_log_get_cur_size(uint8_t *event_log_start);
+
+#endif /* EVENT_LOG_H */
diff --git a/include/drivers/measured_boot/tcg.h b/include/drivers/measured_boot/event_log/tcg.h
similarity index 100%
rename from include/drivers/measured_boot/tcg.h
rename to include/drivers/measured_boot/event_log/tcg.h
diff --git a/include/drivers/measured_boot/measured_boot.h b/include/drivers/measured_boot/measured_boot.h
deleted file mode 100644
index 05be4a9..0000000
--- a/include/drivers/measured_boot/measured_boot.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef MEASURED_BOOT_H
-#define MEASURED_BOOT_H
-
-#include <stdint.h>
-
-#include <drivers/measured_boot/event_log.h>
-
-/* Functions' declarations */
-void measured_boot_init(void);
-void measured_boot_finish(void);
-
-#endif /* MEASURED_BOOT_H */
diff --git a/include/drivers/nxp/flexspi/flash_info.h b/include/drivers/nxp/flexspi/flash_info.h
index 94c9f02..d0ffc86 100644
--- a/include/drivers/nxp/flexspi/flash_info.h
+++ b/include/drivers/nxp/flexspi/flash_info.h
@@ -12,6 +12,7 @@
#define SZ_16M_BYTES 0x1000000U
+/* Start of "if defined(CONFIG_MT25QU512A)" */
#if defined(CONFIG_MT25QU512A)
#define F_SECTOR_64K 0x10000U
#define F_PAGE_256 0x100U
@@ -22,6 +23,9 @@
#define F_SECTOR_ERASE_SZ F_SECTOR_4K
#endif
+/* End of "if defined(CONFIG_MT25QU512A)" */
+
+/* Start of "if defined(CONFIG_MX25U25645G)" */
#elif defined(CONFIG_MX25U25645G)
#define F_SECTOR_64K 0x10000U
#define F_PAGE_256 0x100U
@@ -32,6 +36,9 @@
#define F_SECTOR_ERASE_SZ F_SECTOR_4K
#endif
+/* End of "if defined(CONFIG_MX25U25645G)" */
+
+/* Start of "if defined(CONFIG_MX25U51245G)" */
#elif defined(CONFIG_MX25U51245G)
#define F_SECTOR_64K 0x10000U
#define F_PAGE_256 0x100U
@@ -42,6 +49,9 @@
#define F_SECTOR_ERASE_SZ F_SECTOR_4K
#endif
+/* End of "if defined(CONFIG_MX25U51245G)" */
+
+/* Start of "if defined(CONFIG_MT35XU512A)" */
#elif defined(CONFIG_MT35XU512A)
#define F_SECTOR_128K 0x20000U
#define F_SECTOR_32K 0x8000U
@@ -52,7 +62,18 @@
#ifdef CONFIG_FSPI_4K_ERASE
#define F_SECTOR_ERASE_SZ F_SECTOR_4K
#endif
+/* If Warm boot is enabled for the platform,
+ * count of arm instruction N-OP(s) to mark
+ * the completion of write operation to flash;
+ * varies from one flash to other.
+ */
+#ifdef NXP_WARM_BOOT
+#define FLASH_WR_COMP_WAIT_BY_NOP_COUNT 0x20000
+#endif
+/* End of "if defined(CONFIG_MT35XU512A)" */
+
+/* Start of #elif defined(CONFIG_MT35XU02G) */
#elif defined(CONFIG_MT35XU02G)
#define F_SECTOR_128K 0x20000U
#define F_PAGE_256 0x100U
@@ -63,9 +84,6 @@
#define F_SECTOR_ERASE_SZ F_SECTOR_4K
#endif
-#ifdef NXP_WARM_BOOT
-#define FLASH_WR_COMP_WAIT_BY_NOP_COUNT 0x20000
-#endif
+#endif /* End of #elif defined(CONFIG_MT35XU02G) */
-#endif
#endif /* FLASH_INFO_H */
diff --git a/include/export/common/ep_info_exp.h b/include/export/common/ep_info_exp.h
index 9d2969f..a5bd10a 100644
--- a/include/export/common/ep_info_exp.h
+++ b/include/export/common/ep_info_exp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,11 +24,23 @@
#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x14)
#endif
-/* Security state of the image. */
-#define EP_SECURITY_MASK UL(0x1)
+/*
+ * Security state of the image. Bit 0 and
+ * bit 5 are used to determine the security
+ * state of the image as follows:
+ *
+ * ---------------------------------
+ * Bit 5 | Bit 0 | Security state
+ * ---------------------------------
+ * 0 0 EP_SECURE
+ * 0 1 EP_NON_SECURE
+ * 1 1 EP_REALM
+ */
+#define EP_SECURITY_MASK UL(0x21)
#define EP_SECURITY_SHIFT UL(0)
#define EP_SECURE UL(0x0)
#define EP_NON_SECURE UL(0x1)
+#define EP_REALM UL(0x21)
/* Endianness of the image. */
#define EP_EE_MASK U(0x2)
diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index 2623c75..98544c0 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -101,7 +101,10 @@
*/
#define BKUP_FWU_METADATA_IMAGE_ID U(33)
+/* Realm Monitor Manager (RMM) */
+#define RMM_IMAGE_ID U(34)
+
/* Max Images */
-#define MAX_IMAGE_IDS U(34)
+#define MAX_IMAGE_IDS U(35)
#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index c3f4117..698e208 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -405,13 +405,12 @@
= (uint64_t) (val))
/*
- * Top-level context structure which is used by EL3 firmware to
- * preserve the state of a core at EL1 in one of the two security
- * states and save enough EL3 meta data to be able to return to that
- * EL and security state. The context management library will be used
- * to ensure that SP_EL3 always points to an instance of this
- * structure at exception entry and exit. Each instance will
- * correspond to either the secure or the non-secure state.
+ * Top-level context structure which is used by EL3 firmware to preserve
+ * the state of a core at the next lower EL in a given security state and
+ * save enough EL3 meta data to be able to return to that EL and security
+ * state. The context management library will be used to ensure that
+ * SP_EL3 always points to an instance of this structure at exception
+ * entry and exit.
*/
typedef struct cpu_context {
gp_regs_t gpregs_ctx;
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 3d57a5c..2c7b619 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,16 +19,25 @@
/* 8-bytes aligned size of psci_cpu_data structure */
#define PSCI_CPU_DATA_SIZE_ALIGNED ((PSCI_CPU_DATA_SIZE + 7) & ~7)
+#if ENABLE_RME
+/* Size of cpu_context array */
+#define CPU_DATA_CONTEXT_NUM 3
/* Offset of cpu_ops_ptr, size 8 bytes */
+#define CPU_DATA_CPU_OPS_PTR 0x18
+#else /* ENABLE_RME */
+#define CPU_DATA_CONTEXT_NUM 2
#define CPU_DATA_CPU_OPS_PTR 0x10
+#endif /* ENABLE_RME */
#if ENABLE_PAUTH
/* 8-bytes aligned offset of apiakey[2], size 16 bytes */
-#define CPU_DATA_APIAKEY_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED)
-#define CPU_DATA_CRASH_BUF_OFFSET (CPU_DATA_APIAKEY_OFFSET + 0x10)
-#else
-#define CPU_DATA_CRASH_BUF_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED)
-#endif /* ENABLE_PAUTH */
+#define CPU_DATA_APIAKEY_OFFSET (0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \
+ + CPU_DATA_CPU_OPS_PTR)
+#define CPU_DATA_CRASH_BUF_OFFSET (0x10 + CPU_DATA_APIAKEY_OFFSET)
+#else /* ENABLE_PAUTH */
+#define CPU_DATA_CRASH_BUF_OFFSET (0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \
+ + CPU_DATA_CPU_OPS_PTR)
+#endif /* ENABLE_PAUTH */
/* need enough space in crash buffer to save 8 registers */
#define CPU_DATA_CRASH_BUF_SIZE 64
@@ -65,11 +74,14 @@
#ifndef __ASSEMBLER__
+#include <assert.h>
+#include <stdint.h>
+
#include <arch_helpers.h>
#include <lib/cassert.h>
#include <lib/psci/psci.h>
+
#include <platform_def.h>
-#include <stdint.h>
/* Offsets for the cpu_data structure */
#define CPU_DATA_PSCI_LOCK_OFFSET __builtin_offsetof\
@@ -80,27 +92,34 @@
(cpu_data_t, platform_cpu_data)
#endif
+typedef enum context_pas {
+ CPU_CONTEXT_SECURE = 0,
+ CPU_CONTEXT_NS,
+#if ENABLE_RME
+ CPU_CONTEXT_REALM,
+#endif
+ CPU_CONTEXT_NUM
+} context_pas_t;
+
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
/*******************************************************************************
* Cache of frequently used per-cpu data:
- * Pointers to non-secure and secure security state contexts
+ * Pointers to non-secure, realm, and secure security state contexts
* Address of the crash stack
* It is aligned to the cache line boundary to allow efficient concurrent
* manipulation of these pointers on different cpus
*
- * TODO: Add other commonly used variables to this (tf_issues#90)
- *
* The data structure and the _cpu_data accessors should not be used directly
* by components that have per-cpu members. The member access macros should be
* used for this.
******************************************************************************/
typedef struct cpu_data {
#ifdef __aarch64__
- void *cpu_context[2];
-#endif
+ void *cpu_context[CPU_DATA_CONTEXT_NUM];
+#endif /* __aarch64__ */
uintptr_t cpu_ops_ptr;
struct psci_cpu_data psci_svc_cpu_data;
#if ENABLE_PAUTH
@@ -122,6 +141,11 @@
extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT];
+#ifdef __aarch64__
+CASSERT(CPU_DATA_CONTEXT_NUM == CPU_CONTEXT_NUM,
+ assert_cpu_data_context_num_mismatch);
+#endif
+
#if ENABLE_PAUTH
CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof
(cpu_data_t, apiakey),
@@ -160,6 +184,31 @@
struct cpu_data *_cpu_data(void);
#endif
+/*
+ * Returns the index of the cpu_context array for the given security state.
+ * All accesses to cpu_context should be through this helper to make sure
+ * an access is not out-of-bounds. The function assumes security_state is
+ * valid.
+ */
+static inline context_pas_t get_cpu_context_index(uint32_t security_state)
+{
+ if (security_state == SECURE) {
+ return CPU_CONTEXT_SECURE;
+ } else {
+#if ENABLE_RME
+ if (security_state == NON_SECURE) {
+ return CPU_CONTEXT_NS;
+ } else {
+ assert(security_state == REALM);
+ return CPU_CONTEXT_REALM;
+ }
+#else
+ assert(security_state == NON_SECURE);
+ return CPU_CONTEXT_NS;
+#endif
+ }
+}
+
/**************************************************************************
* APIs for initialising and accessing per-cpu data
*************************************************************************/
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
index 6066af6..db98b68 100644
--- a/include/lib/fconf/fconf_tbbr_getter.h
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -23,9 +23,6 @@
uint32_t disable_auth;
void *mbedtls_heap_addr;
size_t mbedtls_heap_size;
-#if MEASURED_BOOT
- uint8_t bl2_hash_data[TCG_DIGEST_SIZE];
-#endif
};
extern struct tbbr_dyn_config_t tbbr_dyn_config;
diff --git a/include/lib/gpt_rme/gpt_rme.h b/include/lib/gpt_rme/gpt_rme.h
new file mode 100644
index 0000000..379b915
--- /dev/null
+++ b/include/lib/gpt_rme/gpt_rme.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPT_RME_H
+#define GPT_RME_H
+
+#include <stdint.h>
+
+#include <arch.h>
+
+/******************************************************************************/
+/* GPT helper macros and definitions */
+/******************************************************************************/
+
+/*
+ * Structure for specifying a mapping range and it's properties. This should not
+ * be manually initialized, using the MAP_GPT_REGION_x macros is recommended as
+ * to avoid potential incompatibilities in the future.
+ */
+typedef struct pas_region {
+ uintptr_t base_pa; /* Base address for PAS. */
+ size_t size; /* Size of the PAS. */
+ unsigned int attrs; /* PAS GPI and entry type. */
+} pas_region_t;
+
+/* GPT GPI definitions */
+#define GPT_GPI_NO_ACCESS U(0x0)
+#define GPT_GPI_SECURE U(0x8)
+#define GPT_GPI_NS U(0x9)
+#define GPT_GPI_ROOT U(0xA)
+#define GPT_GPI_REALM U(0xB)
+#define GPT_GPI_ANY U(0xF)
+#define GPT_GPI_VAL_MASK UL(0xF)
+
+/* PAS attribute GPI definitions. */
+#define GPT_PAS_ATTR_GPI_SHIFT U(0)
+#define GPT_PAS_ATTR_GPI_MASK U(0xF)
+#define GPT_PAS_ATTR_GPI(_attrs) (((_attrs) \
+ >> GPT_PAS_ATTR_GPI_SHIFT) \
+ & GPT_PAS_ATTR_GPI_MASK)
+
+/* PAS attribute mapping type definitions */
+#define GPT_PAS_ATTR_MAP_TYPE_BLOCK U(0x0)
+#define GPT_PAS_ATTR_MAP_TYPE_GRANULE U(0x1)
+#define GPT_PAS_ATTR_MAP_TYPE_SHIFT U(4)
+#define GPT_PAS_ATTR_MAP_TYPE_MASK U(0x1)
+#define GPT_PAS_ATTR_MAP_TYPE(_attrs) (((_attrs) \
+ >> GPT_PAS_ATTR_MAP_TYPE_SHIFT) \
+ & GPT_PAS_ATTR_MAP_TYPE_MASK)
+
+/*
+ * Macro to initialize the attributes field in the pas_region_t structure.
+ * [31:5] Reserved
+ * [4] Mapping type (GPT_PAS_ATTR_MAP_TYPE_x definitions)
+ * [3:0] PAS GPI type (GPT_GPI_x definitions)
+ */
+#define GPT_PAS_ATTR(_type, _gpi) \
+ ((((_type) & GPT_PAS_ATTR_MAP_TYPE_MASK) \
+ << GPT_PAS_ATTR_MAP_TYPE_SHIFT) | \
+ (((_gpi) & GPT_PAS_ATTR_GPI_MASK) \
+ << GPT_PAS_ATTR_GPI_SHIFT))
+
+/*
+ * Macro to create a GPT entry for this PAS range as a block descriptor. If this
+ * region does not fit the requirements for a block descriptor then GPT
+ * initialization will fail.
+ */
+#define GPT_MAP_REGION_BLOCK(_pa, _sz, _gpi) \
+ { \
+ .base_pa = (_pa), \
+ .size = (_sz), \
+ .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_BLOCK, (_gpi)), \
+ }
+
+/*
+ * Macro to create a GPT entry for this PAS range as a table descriptor. If this
+ * region does not fit the requirements for a table descriptor then GPT
+ * initialization will fail.
+ */
+#define GPT_MAP_REGION_GRANULE(_pa, _sz, _gpi) \
+ { \
+ .base_pa = (_pa), \
+ .size = (_sz), \
+ .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_GRANULE, (_gpi)), \
+ }
+
+/******************************************************************************/
+/* GPT register field definitions */
+/******************************************************************************/
+
+/*
+ * Least significant address bits protected by each entry in level 0 GPT. This
+ * field is read-only.
+ */
+#define GPCCR_L0GPTSZ_SHIFT U(20)
+#define GPCCR_L0GPTSZ_MASK U(0xF)
+
+typedef enum {
+ GPCCR_L0GPTSZ_30BITS = U(0x0),
+ GPCCR_L0GPTSZ_34BITS = U(0x4),
+ GPCCR_L0GPTSZ_36BITS = U(0x6),
+ GPCCR_L0GPTSZ_39BITS = U(0x9)
+} gpccr_l0gptsz_e;
+
+/* Granule protection check priority bit definitions */
+#define GPCCR_GPCP_SHIFT U(17)
+#define GPCCR_GPCP_BIT (ULL(1) << GPCCR_EL3_GPCP_SHIFT)
+
+/* Granule protection check bit definitions */
+#define GPCCR_GPC_SHIFT U(16)
+#define GPCCR_GPC_BIT (ULL(1) << GPCCR_GPC_SHIFT)
+
+/* Physical granule size bit definitions */
+#define GPCCR_PGS_SHIFT U(14)
+#define GPCCR_PGS_MASK U(0x3)
+#define SET_GPCCR_PGS(x) (((x) & GPCCR_PGS_MASK) << GPCCR_PGS_SHIFT)
+
+typedef enum {
+ GPCCR_PGS_4K = U(0x0),
+ GPCCR_PGS_64K = U(0x1),
+ GPCCR_PGS_16K = U(0x2)
+} gpccr_pgs_e;
+
+/* GPT fetch shareability attribute bit definitions */
+#define GPCCR_SH_SHIFT U(12)
+#define GPCCR_SH_MASK U(0x3)
+#define SET_GPCCR_SH(x) (((x) & GPCCR_SH_MASK) << GPCCR_SH_SHIFT)
+
+typedef enum {
+ GPCCR_SH_NS = U(0x0),
+ GPCCR_SH_OS = U(0x2),
+ GPCCR_SH_IS = U(0x3)
+} gpccr_sh_e;
+
+/* GPT fetch outer cacheability attribute bit definitions */
+#define GPCCR_ORGN_SHIFT U(10)
+#define GPCCR_ORGN_MASK U(0x3)
+#define SET_GPCCR_ORGN(x) (((x) & GPCCR_ORGN_MASK) << GPCCR_ORGN_SHIFT)
+
+typedef enum {
+ GPCCR_ORGN_NC = U(0x0),
+ GPCCR_ORGN_WB_RA_WA = U(0x1),
+ GPCCR_ORGN_WT_RA_NWA = U(0x2),
+ GPCCR_ORGN_WB_RA_NWA = U(0x3)
+} gpccr_orgn_e;
+
+/* GPT fetch inner cacheability attribute bit definitions */
+#define GPCCR_IRGN_SHIFT U(8)
+#define GPCCR_IRGN_MASK U(0x3)
+#define SET_GPCCR_IRGN(x) (((x) & GPCCR_IRGN_MASK) << GPCCR_IRGN_SHIFT)
+
+typedef enum {
+ GPCCR_IRGN_NC = U(0x0),
+ GPCCR_IRGN_WB_RA_WA = U(0x1),
+ GPCCR_IRGN_WT_RA_NWA = U(0x2),
+ GPCCR_IRGN_WB_RA_NWA = U(0x3)
+} gpccr_irgn_e;
+
+/* Protected physical address size bit definitions */
+#define GPCCR_PPS_SHIFT U(0)
+#define GPCCR_PPS_MASK U(0x7)
+#define SET_GPCCR_PPS(x) (((x) & GPCCR_PPS_MASK) << GPCCR_PPS_SHIFT)
+
+typedef enum {
+ GPCCR_PPS_4GB = U(0x0),
+ GPCCR_PPS_64GB = U(0x1),
+ GPCCR_PPS_1TB = U(0x2),
+ GPCCR_PPS_4TB = U(0x3),
+ GPCCR_PPS_16TB = U(0x4),
+ GPCCR_PPS_256TB = U(0x5),
+ GPCCR_PPS_4PB = U(0x6)
+} gpccr_pps_e;
+
+/* Base Address for the GPT bit definitions */
+#define GPTBR_BADDR_SHIFT U(0)
+#define GPTBR_BADDR_VAL_SHIFT U(12)
+#define GPTBR_BADDR_MASK ULL(0xffffffffff)
+
+/******************************************************************************/
+/* GPT public APIs */
+/******************************************************************************/
+
+/*
+ * Public API that initializes the entire protected space to GPT_GPI_ANY using
+ * the L0 tables (block descriptors). Ideally, this function is invoked prior
+ * to DDR discovery and initialization. The MMU must be initialized before
+ * calling this function.
+ *
+ * Parameters
+ * pps PPS value to use for table generation
+ * l0_mem_base Base address of L0 tables in memory.
+ * l0_mem_size Total size of memory available for L0 tables.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_l0_tables(gpccr_pps_e pps,
+ uintptr_t l0_mem_base,
+ size_t l0_mem_size);
+
+/*
+ * Public API that carves out PAS regions from the L0 tables and builds any L1
+ * tables that are needed. This function ideally is run after DDR discovery and
+ * initialization. The L0 tables must have already been initialized to GPI_ANY
+ * when this function is called.
+ *
+ * Parameters
+ * pgs PGS value to use for table generation.
+ * l1_mem_base Base address of memory used for L1 tables.
+ * l1_mem_size Total size of memory available for L1 tables.
+ * *pas_regions Pointer to PAS regions structure array.
+ * pas_count Total number of PAS regions.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_pas_l1_tables(gpccr_pgs_e pgs,
+ uintptr_t l1_mem_base,
+ size_t l1_mem_size,
+ pas_region_t *pas_regions,
+ unsigned int pas_count);
+
+/*
+ * Public API to initialize the runtime gpt_config structure based on the values
+ * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization
+ * typically happens in a bootloader stage prior to setting up the EL3 runtime
+ * environment for the granule transition service so this function detects the
+ * initialization from a previous stage. Granule protection checks must be
+ * enabled already or this function will return an error.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_runtime_init(void);
+
+/*
+ * Public API to enable granule protection checks once the tables have all been
+ * initialized. This function is called at first initialization and then again
+ * later during warm boots of CPU cores.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_enable(void);
+
+/*
+ * Public API to disable granule protection checks.
+ */
+void gpt_disable(void);
+
+/*
+ * This function is the core of the granule transition service. When a granule
+ * transition request occurs it is routed to this function where the request is
+ * validated then fulfilled if possible.
+ *
+ * TODO: implement support for transitioning multiple granules at once.
+ *
+ * Parameters
+ * base: Base address of the region to transition, must be aligned to granule
+ * size.
+ * size: Size of region to transition, must be aligned to granule size.
+ * src_sec_state: Security state of the caller.
+ * target_pas: Target PAS of the specified memory region.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_transition_pas(uint64_t base,
+ size_t size,
+ unsigned int src_sec_state,
+ unsigned int target_pas);
+
+#endif /* GPT_RME_H */
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index deaeb1d..1a39f24 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -108,9 +108,24 @@
#define SMC_ARCH_CALL_NOT_REQUIRED -2
#define SMC_ARCH_CALL_INVAL_PARAM -3
-/* Various flags passed to SMC handlers */
+/*
+ * Various flags passed to SMC handlers
+ *
+ * Bit 5 and bit 0 of the flag are used to
+ * determine the source security state as
+ * follows:
+ * ---------------------------------
+ * Bit 5 | Bit 0 | Security state
+ * ---------------------------------
+ * 0 0 SMC_FROM_SECURE
+ * 0 1 SMC_FROM_NON_SECURE
+ * 1 1 SMC_FROM_REALM
+ */
+
#define SMC_FROM_SECURE (U(0) << 0)
#define SMC_FROM_NON_SECURE (U(1) << 0)
+#define SMC_FROM_REALM U(0x21)
+#define SMC_FROM_MASK U(0x21)
#ifndef __ASSEMBLER__
@@ -118,8 +133,18 @@
#include <lib/cassert.h>
+#if ENABLE_RME
+#define is_caller_non_secure(_f) (((_f) & SMC_FROM_MASK) \
+ == SMC_FROM_NON_SECURE)
+#define is_caller_secure(_f) (((_f) & SMC_FROM_MASK) \
+ == SMC_FROM_SECURE)
+#define is_caller_realm(_f) (((_f) & SMC_FROM_MASK) \
+ == SMC_FROM_REALM)
+#define caller_sec_state(_f) ((_f) & SMC_FROM_MASK)
+#else /* ENABLE_RME */
#define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0))
#define is_caller_secure(_f) (!is_caller_non_secure(_f))
+#endif /* ENABLE_RME */
/* The macro below is used to identify a Standard Service SMC call */
#define is_std_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_STD_START)
diff --git a/include/lib/xlat_tables/xlat_tables.h b/include/lib/xlat_tables/xlat_tables.h
index 082bb5e..a156969 100644
--- a/include/lib/xlat_tables/xlat_tables.h
+++ b/include/lib/xlat_tables/xlat_tables.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -72,6 +72,13 @@
#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE)
#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
+/* Memory type for EL3 regions */
+#if ENABLE_RME
+#error FEAT_RME requires version 2 of the Translation Tables Library
+#else
+#define EL3_PAS MT_SECURE
+#endif
+
/*
* Structure for specifying a single region of memory.
*/
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 579d8d8..2d0949b 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -142,6 +142,7 @@
#define AP_NO_ACCESS_UNPRIVILEGED (AP1_NO_ACCESS_UNPRIVILEGED << 4)
#define AP_ONE_VA_RANGE_RES1 (AP1_RES1 << 4)
#define NS (U(0x1) << 3)
+#define EL3_S1_NSE (U(0x1) << 9)
#define ATTR_NON_CACHEABLE_INDEX ULL(0x2)
#define ATTR_DEVICE_INDEX ULL(0x1)
#define ATTR_IWBWA_OWBWA_NTR_INDEX ULL(0x0)
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 359b983..69ad027 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -60,17 +60,22 @@
#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK)
/* Access permissions (RO/RW) */
#define MT_PERM_SHIFT U(3)
-/* Security state (SECURE/NS) */
-#define MT_SEC_SHIFT U(4)
+
+/* Physical address space (SECURE/NS/Root/Realm) */
+#define MT_PAS_SHIFT U(4)
+#define MT_PAS_MASK (U(3) << MT_PAS_SHIFT)
+#define MT_PAS(_attr) ((_attr) & MT_PAS_MASK)
+
/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
-#define MT_EXECUTE_SHIFT U(5)
+#define MT_EXECUTE_SHIFT U(6)
/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */
-#define MT_USER_SHIFT U(6)
+#define MT_USER_SHIFT U(7)
/* Shareability attribute for the memory region */
-#define MT_SHAREABILITY_SHIFT U(7)
+#define MT_SHAREABILITY_SHIFT U(8)
#define MT_SHAREABILITY_MASK (U(3) << MT_SHAREABILITY_SHIFT)
#define MT_SHAREABILITY(_attr) ((_attr) & MT_SHAREABILITY_MASK)
+
/* All other bits are reserved */
/*
@@ -91,8 +96,10 @@
#define MT_RO (U(0) << MT_PERM_SHIFT)
#define MT_RW (U(1) << MT_PERM_SHIFT)
-#define MT_SECURE (U(0) << MT_SEC_SHIFT)
-#define MT_NS (U(1) << MT_SEC_SHIFT)
+#define MT_SECURE (U(0) << MT_PAS_SHIFT)
+#define MT_NS (U(1) << MT_PAS_SHIFT)
+#define MT_ROOT (U(2) << MT_PAS_SHIFT)
+#define MT_REALM (U(3) << MT_PAS_SHIFT)
/*
* Access permissions for instruction execution are only relevant for normal
@@ -149,6 +156,13 @@
#define EL3_REGIME 3
#define EL_REGIME_INVALID -1
+/* Memory type for EL3 regions. With RME, EL3 is in ROOT PAS */
+#if ENABLE_RME
+#define EL3_PAS MT_ROOT
+#else
+#define EL3_PAS MT_SECURE
+#endif /* ENABLE_RME */
+
/*
* Declare the translation context type.
* Its definition is private.
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 7cc215f..1993cb4 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -74,38 +74,84 @@
ARM_SHARED_RAM_SIZE)
/*
- * The top 16MB of DRAM1 is configured as secure access only using the TZC
+ * The top 16MB (or 64MB if RME is enabled) of DRAM1 is configured as
+ * follows:
* - SCP TZC DRAM: If present, DRAM reserved for SCP use
+ * - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled
+ * - REALM DRAM: Reserved for Realm world if RME is enabled
* - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use
+ *
+ * RME enabled(64MB) RME not enabled(16MB)
+ * -------------------- -------------------
+ * | | | |
+ * | AP TZC (~28MB) | | AP TZC (~14MB) |
+ * -------------------- -------------------
+ * | | | |
+ * | REALM (32MB) | | EL3 TZC (2MB) |
+ * -------------------- -------------------
+ * | | | |
+ * | EL3 TZC (3MB) | | SCP TZC |
+ * -------------------- 0xFFFF_FFFF-------------------
+ * | L1 GPT + SCP TZC |
+ * | (~1MB) |
+ * 0xFFFF_FFFF --------------------
*/
-#define ARM_TZC_DRAM1_SIZE UL(0x01000000)
+#if ENABLE_RME
+#define ARM_TZC_DRAM1_SIZE UL(0x04000000) /* 64MB */
+/*
+ * Define a region within the TZC secured DRAM for use by EL3 runtime
+ * firmware. This region is meant to be NOLOAD and will not be zero
+ * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be
+ * placed here. 3MB region is reserved if RME is enabled, 2MB otherwise.
+ */
+#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00300000) /* 3MB */
+#define ARM_L1_GPT_SIZE UL(0x00100000) /* 1MB */
+#define ARM_REALM_SIZE UL(0x02000000) /* 32MB */
+#else
+#define ARM_TZC_DRAM1_SIZE UL(0x01000000) /* 16MB */
+#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2MB */
+#define ARM_L1_GPT_SIZE UL(0)
+#define ARM_REALM_SIZE UL(0)
+#endif /* ENABLE_RME */
#define ARM_SCP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \
- ARM_DRAM1_SIZE - \
- ARM_SCP_TZC_DRAM1_SIZE)
+ ARM_DRAM1_SIZE - \
+ (ARM_SCP_TZC_DRAM1_SIZE + \
+ ARM_L1_GPT_SIZE))
#define ARM_SCP_TZC_DRAM1_SIZE PLAT_ARM_SCP_TZC_DRAM1_SIZE
#define ARM_SCP_TZC_DRAM1_END (ARM_SCP_TZC_DRAM1_BASE + \
- ARM_SCP_TZC_DRAM1_SIZE - 1U)
+ ARM_SCP_TZC_DRAM1_SIZE - 1U)
+#if ENABLE_RME
+#define ARM_L1_GPT_ADDR_BASE (ARM_DRAM1_BASE + \
+ ARM_DRAM1_SIZE - \
+ ARM_L1_GPT_SIZE)
+#define ARM_L1_GPT_END (ARM_L1_GPT_ADDR_BASE + \
+ ARM_L1_GPT_SIZE - 1U)
-/*
- * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime
- * firmware. This region is meant to be NOLOAD and will not be zero
- * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be
- * placed here.
- */
-#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
-#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2 MB */
+#define ARM_REALM_BASE (ARM_DRAM1_BASE + \
+ ARM_DRAM1_SIZE - \
+ (ARM_SCP_TZC_DRAM1_SIZE + \
+ ARM_EL3_TZC_DRAM1_SIZE + \
+ ARM_REALM_SIZE + \
+ ARM_L1_GPT_SIZE))
+#define ARM_REALM_END (ARM_REALM_BASE + ARM_REALM_SIZE - 1U)
+#endif /* ENABLE_RME */
+
+#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - \
+ ARM_EL3_TZC_DRAM1_SIZE)
#define ARM_EL3_TZC_DRAM1_END (ARM_EL3_TZC_DRAM1_BASE + \
ARM_EL3_TZC_DRAM1_SIZE - 1U)
#define ARM_AP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \
- ARM_DRAM1_SIZE - \
- ARM_TZC_DRAM1_SIZE)
+ ARM_DRAM1_SIZE - \
+ ARM_TZC_DRAM1_SIZE)
#define ARM_AP_TZC_DRAM1_SIZE (ARM_TZC_DRAM1_SIZE - \
- (ARM_SCP_TZC_DRAM1_SIZE + \
- ARM_EL3_TZC_DRAM1_SIZE))
+ (ARM_SCP_TZC_DRAM1_SIZE + \
+ ARM_EL3_TZC_DRAM1_SIZE + \
+ ARM_REALM_SIZE + \
+ ARM_L1_GPT_SIZE))
#define ARM_AP_TZC_DRAM1_END (ARM_AP_TZC_DRAM1_BASE + \
- ARM_AP_TZC_DRAM1_SIZE - 1U)
+ ARM_AP_TZC_DRAM1_SIZE - 1U)
/* Define the Access permissions for Secure peripherals to NS_DRAM */
#if ARM_CRYPTOCELL_INTEG
@@ -206,45 +252,58 @@
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE)
-#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
- ARM_SHARED_RAM_BASE, \
- ARM_SHARED_RAM_SIZE, \
- MT_DEVICE | MT_RW | MT_SECURE)
+#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
+ ARM_SHARED_RAM_BASE, \
+ ARM_SHARED_RAM_SIZE, \
+ MT_DEVICE | MT_RW | EL3_PAS)
-#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
- ARM_NS_DRAM1_BASE, \
- ARM_NS_DRAM1_SIZE, \
- MT_MEMORY | MT_RW | MT_NS)
+#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
+ ARM_NS_DRAM1_BASE, \
+ ARM_NS_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
-#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \
- ARM_DRAM2_BASE, \
- ARM_DRAM2_SIZE, \
- MT_MEMORY | MT_RW | MT_NS)
+#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \
+ ARM_DRAM2_BASE, \
+ ARM_DRAM2_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
-#define ARM_MAP_TSP_SEC_MEM MAP_REGION_FLAT( \
- TSP_SEC_MEM_BASE, \
- TSP_SEC_MEM_SIZE, \
- MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_TSP_SEC_MEM MAP_REGION_FLAT( \
+ TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
#if ARM_BL31_IN_DRAM
-#define ARM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \
- BL31_BASE, \
- PLAT_ARM_MAX_BL31_SIZE, \
- MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \
+ BL31_BASE, \
+ PLAT_ARM_MAX_BL31_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
#endif
-#define ARM_MAP_EL3_TZC_DRAM MAP_REGION_FLAT( \
- ARM_EL3_TZC_DRAM1_BASE, \
- ARM_EL3_TZC_DRAM1_SIZE, \
- MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_EL3_TZC_DRAM MAP_REGION_FLAT( \
+ ARM_EL3_TZC_DRAM1_BASE, \
+ ARM_EL3_TZC_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | EL3_PAS)
#if defined(SPD_spmd)
-#define ARM_MAP_TRUSTED_DRAM MAP_REGION_FLAT( \
- PLAT_ARM_TRUSTED_DRAM_BASE, \
- PLAT_ARM_TRUSTED_DRAM_SIZE, \
- MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_TRUSTED_DRAM MAP_REGION_FLAT( \
+ PLAT_ARM_TRUSTED_DRAM_BASE, \
+ PLAT_ARM_TRUSTED_DRAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
#endif
+#if ENABLE_RME
+#define ARM_MAP_RMM_DRAM MAP_REGION_FLAT( \
+ PLAT_ARM_RMM_BASE, \
+ PLAT_ARM_RMM_SIZE, \
+ MT_MEMORY | MT_RW | MT_REALM)
+
+
+#define ARM_MAP_GPT_L1_DRAM MAP_REGION_FLAT( \
+ ARM_L1_GPT_ADDR_BASE, \
+ ARM_L1_GPT_SIZE, \
+ MT_MEMORY | MT_RW | EL3_PAS)
+
+#endif /* ENABLE_RME */
/*
* Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
@@ -255,7 +314,7 @@
#define ARM_MAP_BL1_RW MAP_REGION_FLAT( \
BL1_RW_BASE, \
BL1_RW_LIMIT - BL1_RW_BASE, \
- MT_MEMORY | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | EL3_PAS)
/*
* If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
@@ -265,35 +324,35 @@
#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
BL_CODE_BASE, \
BL_CODE_END - BL_CODE_BASE, \
- MT_CODE | MT_SECURE), \
+ MT_CODE | EL3_PAS), \
MAP_REGION_FLAT( \
BL_RO_DATA_BASE, \
BL_RO_DATA_END \
- BL_RO_DATA_BASE, \
- MT_RO_DATA | MT_SECURE)
+ MT_RO_DATA | EL3_PAS)
#else
#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
BL_CODE_BASE, \
BL_CODE_END - BL_CODE_BASE, \
- MT_CODE | MT_SECURE)
+ MT_CODE | EL3_PAS)
#endif
#if USE_COHERENT_MEM
#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
BL_COHERENT_RAM_BASE, \
BL_COHERENT_RAM_END \
- BL_COHERENT_RAM_BASE, \
- MT_DEVICE | MT_RW | MT_SECURE)
+ MT_DEVICE | MT_RW | EL3_PAS)
#endif
#if USE_ROMLIB
#define ARM_MAP_ROMLIB_CODE MAP_REGION_FLAT( \
ROMLIB_RO_BASE, \
ROMLIB_RO_LIMIT - ROMLIB_RO_BASE,\
- MT_CODE | MT_SECURE)
+ MT_CODE | EL3_PAS)
#define ARM_MAP_ROMLIB_DATA MAP_REGION_FLAT( \
ROMLIB_RW_BASE, \
ROMLIB_RW_END - ROMLIB_RW_BASE,\
- MT_MEMORY | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | EL3_PAS)
#endif
/*
@@ -308,7 +367,15 @@
#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
(ARM_FW_CONFIGS_LIMIT \
- ARM_BL_RAM_BASE), \
- MT_MEMORY | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | EL3_PAS)
+/*
+ * Map L0_GPT with read and write permissions
+ */
+#if ENABLE_RME
+#define ARM_MAP_L0_GPT_REGION MAP_REGION_FLAT(ARM_L0_GPT_ADDR_BASE, \
+ ARM_L0_GPT_SIZE, \
+ MT_MEMORY | MT_RW | MT_ROOT)
+#endif
/*
* The max number of regions like RO(code), coherent and data required by
@@ -409,6 +476,18 @@
*/
#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+#if ENABLE_RME
+/*
+ * Store the L0 GPT on Trusted SRAM next to firmware
+ * configuration memory, 4KB aligned.
+ */
+#define ARM_L0_GPT_SIZE (PAGE_SIZE)
+#define ARM_L0_GPT_ADDR_BASE (ARM_FW_CONFIGS_LIMIT)
+#define ARM_L0_GPT_LIMIT (ARM_L0_GPT_ADDR_BASE + ARM_L0_GPT_SIZE)
+#else
+#define ARM_L0_GPT_SIZE U(0)
+#endif
+
/*******************************************************************************
* BL1 specific defines.
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
@@ -501,6 +580,14 @@
#endif
#endif
+/******************************************************************************
+ * RMM specific defines
+ *****************************************************************************/
+#if ENABLE_RME
+#define RMM_BASE (ARM_REALM_BASE)
+#define RMM_LIMIT (RMM_BASE + ARM_REALM_SIZE)
+#endif
+
#if !defined(__aarch64__) || JUNO_AARCH32_EL3_RUNTIME
/*******************************************************************************
* BL32 specific defines for EL3 runtime in AArch32 mode
diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h
index 34bf07c..ff00fe7 100644
--- a/include/plat/arm/common/arm_dyn_cfg_helpers.h
+++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,8 +14,4 @@
int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr,
size_t heap_size);
-#if MEASURED_BOOT
-int arm_set_bl2_hash_info(void *dtb, void *data);
-#endif
-
#endif /* ARM_DYN_CFG_HELPERS_H */
diff --git a/include/plat/arm/common/arm_pas_def.h b/include/plat/arm/common/arm_pas_def.h
new file mode 100644
index 0000000..4fee41b
--- /dev/null
+++ b/include/plat/arm/common/arm_pas_def.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ARM_PAS_DEF_H
+#define ARM_PAS_DEF_H
+
+#include <lib/gpt_rme/gpt_rme.h>
+#include <plat/arm/common/arm_def.h>
+
+/*****************************************************************************
+ * PAS regions used to initialize the Granule Protection Table (GPT)
+ ****************************************************************************/
+
+/*
+ * The PA space is initially mapped in the GPT as follows:
+ *
+ * ============================================================================
+ * Base Addr| Size |L? GPT|PAS |Content |Comment
+ * ============================================================================
+ * 0GB | 1GB |L0 GPT|ANY |TBROM (EL3 code) |Fixed mapping
+ * | | | |TSRAM (EL3 data) |
+ * | | | |IO (incl.UARTs & GIC) |
+ * ----------------------------------------------------------------------------
+ * 1GB | 1GB |L0 GPT|ANY |IO |Fixed mapping
+ * ----------------------------------------------------------------------------
+ * 2GB | 1GB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 3GB |1GB-64MB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-64MB |64MB-32MB | | | |
+ * | -4MB |L1 GPT|SECURE|DRAM TZC |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-32MB | | | | |
+ * -3MB-1MB |32MB |L1 GPT|REALM |RMM |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-3MB | | | | |
+ * -1MB |3MB |L1 GPT|ROOT |EL3 DRAM data |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-1MB |1MB |L1 GPT|ROOT |DRAM (L1 GPTs, SCP TZC) |Fixed mapping
+ * ============================================================================
+ *
+ * - 4KB of L0 GPT reside in TSRAM, on top of the CONFIG section.
+ * - ~1MB of L1 GPTs reside at the top of DRAM1 (TZC area).
+ * - The first 1GB region has GPT_GPI_ANY and, therefore, is not protected by
+ * the GPT.
+ * - The DRAM TZC area is split into three regions: the L1 GPT region and
+ * 3MB of region below that are defined as GPT_GPI_ROOT, 32MB Realm region
+ * below that is defined as GPT_GPI_REALM and the rest of it is defined as
+ * GPT_GPI_SECURE.
+ */
+
+/* TODO: This might not be the best way to map the PAS */
+
+/* Device memory 0 to 2GB */
+#define ARM_PAS_1_BASE (U(0))
+#define ARM_PAS_1_SIZE ((ULL(1)<<31)) /* 2GB */
+
+/* NS memory 2GB to (end - 64MB) */
+#define ARM_PAS_2_BASE (ARM_PAS_1_BASE + ARM_PAS_1_SIZE)
+#define ARM_PAS_2_SIZE (ARM_NS_DRAM1_SIZE)
+
+/* Secure TZC region */
+#define ARM_PAS_3_BASE (ARM_AP_TZC_DRAM1_BASE)
+#define ARM_PAS_3_SIZE (ARM_AP_TZC_DRAM1_SIZE)
+
+#define ARM_PAS_GPI_ANY MAP_GPT_REGION(ARM_PAS_1_BASE, \
+ ARM_PAS_1_SIZE, \
+ GPT_GPI_ANY)
+#define ARM_PAS_KERNEL GPT_MAP_REGION_GRANULE(ARM_PAS_2_BASE, \
+ ARM_PAS_2_SIZE, \
+ GPT_GPI_NS)
+
+#define ARM_PAS_SECURE GPT_MAP_REGION_GRANULE(ARM_PAS_3_BASE, \
+ ARM_PAS_3_SIZE, \
+ GPT_GPI_SECURE)
+
+#define ARM_PAS_REALM GPT_MAP_REGION_GRANULE(ARM_REALM_BASE, \
+ ARM_REALM_SIZE, \
+ GPT_GPI_REALM)
+
+#define ARM_PAS_EL3_DRAM GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \
+ ARM_EL3_TZC_DRAM1_SIZE, \
+ GPT_GPI_ROOT)
+
+#define ARM_PAS_GPTS GPT_MAP_REGION_GRANULE(ARM_L1_GPT_ADDR_BASE, \
+ ARM_L1_GPT_SIZE, \
+ GPT_GPI_ROOT)
+
+/* GPT Configuration options */
+#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS
+
+#endif /* ARM_PAS_DEF_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 0a19d8b..9618700 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -41,7 +41,7 @@
******************************************************************************/
#if SPM_MM
#define ARM_TZC_REGIONS_DEF \
- {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \
+ {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\
TZC_REGION_S_RDWR, 0}, \
{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
PLAT_ARM_TZC_NS_DEV_ACCESS}, \
@@ -51,9 +51,20 @@
PLAT_SP_IMAGE_NS_BUF_SIZE) - 1, TZC_REGION_S_NONE, \
PLAT_ARM_TZC_NS_DEV_ACCESS}
+#elif ENABLE_RME
+#define ARM_TZC_REGIONS_DEF \
+ {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0},\
+ {ARM_EL3_TZC_DRAM1_BASE, ARM_L1_GPT_END, TZC_REGION_S_RDWR, 0}, \
+ {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {ARM_REALM_BASE, ARM_REALM_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}
+
#else
#define ARM_TZC_REGIONS_DEF \
- {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \
+ {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\
TZC_REGION_S_RDWR, 0}, \
{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
PLAT_ARM_TZC_NS_DEV_ACCESS}, \
@@ -239,12 +250,8 @@
int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
#if MEASURED_BOOT
-/* Measured boot related functions */
-void arm_bl1_set_bl2_hash(const image_desc_t *image_desc);
-void arm_bl2_get_hash(void *data);
-int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
- size_t log_size);
-int arm_set_nt_fw_info(uintptr_t config_base,
+int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size);
+int arm_set_nt_fw_info(
/*
* Currently OP-TEE does not support reading DTBs from Secure memory
* and this option should be removed when feature is supported.
@@ -253,6 +260,8 @@
uintptr_t log_addr,
#endif
size_t log_size, uintptr_t *ns_log_addr);
+int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size);
+int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size);
#endif /* MEASURED_BOOT */
/*
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 434835e..3fa63f5 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -122,6 +122,16 @@
void bl2_plat_preload_setup(void);
int plat_try_next_boot_source(void);
+#if MEASURED_BOOT
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data);
+#else
+static inline int plat_mboot_measure_image(unsigned int image_id __unused,
+ image_info_t *image_data __unused)
+{
+ return 0;
+}
+#endif /* MEASURED_BOOT */
+
/*******************************************************************************
* Mandatory BL1 functions
******************************************************************************/
@@ -182,12 +192,16 @@
int bl1_plat_handle_post_image_load(unsigned int image_id);
#if MEASURED_BOOT
-/*
- * Calculates and writes BL2 hash data to the platform's defined location.
- * For ARM platforms the data are written to TB_FW_CONFIG DTB.
- */
-void bl1_plat_set_bl2_hash(const image_desc_t *image_desc);
-#endif
+void bl1_plat_mboot_init(void);
+void bl1_plat_mboot_finish(void);
+#else
+static inline void bl1_plat_mboot_init(void)
+{
+}
+static inline void bl1_plat_mboot_finish(void)
+{
+}
+#endif /* MEASURED_BOOT */
/*******************************************************************************
* Mandatory BL2 functions
@@ -208,9 +222,16 @@
* Optional BL2 functions (may be overridden)
******************************************************************************/
#if MEASURED_BOOT
-/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
-void bl2_plat_get_hash(void *data);
-#endif
+void bl2_plat_mboot_init(void);
+void bl2_plat_mboot_finish(void);
+#else
+static inline void bl2_plat_mboot_init(void)
+{
+}
+static inline void bl2_plat_mboot_finish(void)
+{
+}
+#endif /* MEASURED_BOOT */
/*******************************************************************************
* Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is
diff --git a/include/services/gtsi_svc.h b/include/services/gtsi_svc.h
new file mode 100644
index 0000000..cb942ed
--- /dev/null
+++ b/include/services/gtsi_svc.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GTSI_SVC_H
+#define GTSI_SVC_H
+
+/* GTSI error codes. */
+#define GTSI_SUCCESS 0
+#define GTSI_ERROR_NOT_SUPPORTED -1
+#define GTSI_ERROR_INVALID_ADDRESS -2
+#define GTSI_ERROR_INVALID_PAS -3
+
+/* The macros below are used to identify GTSI calls from the SMC function ID */
+#define GTSI_FNUM_MIN_VALUE U(0x100)
+#define GTSI_FNUM_MAX_VALUE U(0x101)
+#define is_gtsi_fid(fid) __extension__ ({ \
+ __typeof__(fid) _fid = (fid); \
+ ((GET_SMC_NUM(_fid) >= GTSI_FNUM_MIN_VALUE) && \
+ (GET_SMC_NUM(_fid) <= GTSI_FNUM_MAX_VALUE)); })
+
+/* Get GTSI fastcall std FID from function number */
+#define GTSI_FID(smc_cc, func_num) \
+ ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+ ((smc_cc) << FUNCID_CC_SHIFT) | \
+ (OEN_STD_START << FUNCID_OEN_SHIFT) | \
+ ((func_num) << FUNCID_NUM_SHIFT))
+
+#define GRAN_TRANS_TO_REALM_FNUM U(0x100)
+#define GRAN_TRANS_TO_NS_FNUM U(0x101)
+
+#define SMC_ASC_MARK_REALM GTSI_FID(SMC_64, GRAN_TRANS_TO_REALM_FNUM)
+#define SMC_ASC_MARK_NONSECURE GTSI_FID(SMC_64, GRAN_TRANS_TO_NS_FNUM)
+
+#define GRAN_TRANS_RET_BAD_ADDR -2
+#define GRAN_TRANS_RET_BAD_PAS -3
+
+#endif /* GTSI_SVC_H */
diff --git a/include/services/rmi_svc.h b/include/services/rmi_svc.h
new file mode 100644
index 0000000..9106f08
--- /dev/null
+++ b/include/services/rmi_svc.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMI_SVC_H
+#define RMI_SVC_H
+
+#include <lib/smccc.h>
+#include <lib/utils_def.h>
+
+/* RMI error codes. */
+#define RMI_SUCCESS 0
+#define RMI_ERROR_NOT_SUPPORTED -1
+#define RMI_ERROR_INVALID_ADDRESS -2
+#define RMI_ERROR_INVALID_PAS -3
+
+/* The macros below are used to identify RMI calls from the SMC function ID */
+#define RMI_FNUM_MIN_VALUE U(0x00)
+#define RMI_FNUM_MAX_VALUE U(0x20)
+#define is_rmi_fid(fid) __extension__ ({ \
+ __typeof__(fid) _fid = (fid); \
+ ((GET_SMC_NUM(_fid) >= RMI_FNUM_MIN_VALUE) && \
+ (GET_SMC_NUM(_fid) <= RMI_FNUM_MAX_VALUE) && \
+ (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST) && \
+ (GET_SMC_CC(_fid) == SMC_64) && \
+ (GET_SMC_OEN(_fid) == OEN_ARM_START) && \
+ ((_fid & 0x00FE0000) == 0U)); })
+
+/* Get RMI fastcall std FID from function number */
+#define RMI_FID(smc_cc, func_num) \
+ ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+ ((smc_cc) << FUNCID_CC_SHIFT) | \
+ (OEN_ARM_START << FUNCID_OEN_SHIFT) | \
+ ((func_num) << FUNCID_NUM_SHIFT))
+
+/*
+ * SMC_RMM_INIT_COMPLETE is the only function in the RMI that originates from
+ * the Realm world and is handled by the RMMD. The remaining functions are
+ * always invoked by the Normal world, forwarded by RMMD and handled by the
+ * RMM
+ */
+#define RMI_FNUM_REQ_COMPLETE U(0x10)
+#define RMI_FNUM_VERSION_REQ U(0x00)
+
+#define RMI_FNUM_GRAN_NS_REALM U(0x01)
+#define RMI_FNUM_GRAN_REALM_NS U(0x10)
+
+/* RMI SMC64 FIDs handled by the RMMD */
+#define RMI_RMM_REQ_COMPLETE RMI_FID(SMC_64, RMI_FNUM_REQ_COMPLETE)
+#define RMI_RMM_REQ_VERSION RMI_FID(SMC_64, RMI_FNUM_VERSION_REQ)
+
+#define RMI_RMM_GRANULE_DELEGATE RMI_FID(SMC_64, RMI_FNUM_GRAN_NS_REALM)
+#define RMI_RMM_GRANULE_UNDELEGATE RMI_FID(SMC_64, RMI_FNUM_GRAN_REALM_NS)
+
+
+#define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
+#define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
+
+/* Reserve a special value for MBZ parameters. */
+#define RMI_PARAM_MBZ U(0x0)
+
+#endif /* RMI_SVC_H */
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
new file mode 100644
index 0000000..132973b
--- /dev/null
+++ b/include/services/rmmd_svc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_SVC_H
+#define RMMD_SVC_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+
+int rmmd_setup(void);
+uint64_t rmmd_rmi_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags);
+
+uint64_t rmmd_gtsi_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* RMMD_SVC_H */
diff --git a/include/services/trp/platform_trp.h b/include/services/trp/platform_trp.h
new file mode 100644
index 0000000..b34da85
--- /dev/null
+++ b/include/services/trp/platform_trp.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_TRP_H
+#define PLATFORM_TRP_H
+
+/*******************************************************************************
+ * Mandatory TRP functions (only if platform contains a TRP)
+ ******************************************************************************/
+void trp_early_platform_setup(void);
+
+#endif /* PLATFORM_TRP_H */
diff --git a/include/tools_share/firmware_image_package.h b/include/tools_share/firmware_image_package.h
index dc65cc6..bd5b14b 100644
--- a/include/tools_share/firmware_image_package.h
+++ b/include/tools_share/firmware_image_package.h
@@ -38,6 +38,8 @@
{{0x8e, 0xa8, 0x7b, 0xb1}, {0xcf, 0xa2}, {0x3f, 0x4d}, 0x85, 0xfd, {0xe7, 0xbb, 0xa5, 0x02, 0x20, 0xd9} }
#define UUID_NON_TRUSTED_FIRMWARE_BL33 \
{{0xd6, 0xd0, 0xee, 0xa7}, {0xfc, 0xea}, {0xd5, 0x4b}, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+#define UUID_REALM_MONITOR_MGMT_FIRMWARE \
+ {{0x6c, 0x07, 0x62, 0xa6}, {0x12, 0xf2}, {0x4b, 0x56}, 0x92, 0xcb, {0xba, 0x8f, 0x63, 0x36, 0x06, 0xd9} }
/* Key certificates */
#define UUID_ROT_KEY_CERT \
{{0x86, 0x2d, 0x1d, 0x72}, {0xf8, 0x60}, {0xe4, 0x11}, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} }
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index b6f6c9d..6e4d1fc 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -15,6 +15,7 @@
.globl zero_normalmem
.globl zeromem
.globl memcpy16
+ .globl gpt_tlbi_by_pa
.globl disable_mmu_el1
.globl disable_mmu_el3
@@ -162,7 +163,8 @@
* Check for M bit (MMU enabled) of the current SCTLR_EL(1|3)
* register value and panic if the MMU is disabled.
*/
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
+#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \
+ (BL2_AT_EL3 || ENABLE_RME))
mrs tmp1, sctlr_el3
#else
mrs tmp1, sctlr_el1
@@ -592,3 +594,20 @@
b.lo 1b
ret
endfunc fixup_gdt_reloc
+
+/*
+ * TODO: Currently only supports size of 4KB,
+ * support other sizes as well.
+ */
+func gpt_tlbi_by_pa
+#if ENABLE_ASSERTIONS
+ cmp x1, #PAGE_SIZE_4KB
+ ASM_ASSERT(eq)
+ tst x0, #(PAGE_SIZE_MASK)
+ ASM_ASSERT(eq)
+#endif
+ lsr x0, x0, #FOUR_KB_SHIFT /* 4KB size encoding is zero */
+ sys #6, c8, c4, #3, x0 /* TLBI RPAOS, <Xt> */
+ dsb sy
+ ret
+endfunc gpt_tlbi_by_pa
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 08022d4..0ec7e7e 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -93,24 +93,41 @@
scr_el3 = read_scr();
scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT |
SCR_ST_BIT | SCR_HCE_BIT);
+
+#if ENABLE_RME
+ /* When RME support is enabled, clear the NSE bit as well. */
+ scr_el3 &= ~SCR_NSE_BIT;
+#endif /* ENABLE_RME */
+
/*
* SCR_NS: Set the security state of the next EL.
*/
- if (security_state != SECURE)
+ if (security_state == NON_SECURE) {
scr_el3 |= SCR_NS_BIT;
+ }
+
+#if ENABLE_RME
+ /* Check for realm state if RME support enabled. */
+ if (security_state == REALM) {
+ scr_el3 |= SCR_NS_BIT | SCR_NSE_BIT | SCR_EnSCXT_BIT;
+ }
+#endif /* ENABLE_RME */
+
/*
* SCR_EL3.RW: Set the execution state, AArch32 or AArch64, for next
* Exception level as specified by SPSR.
*/
- if (GET_RW(ep->spsr) == MODE_RW_64)
+ if (GET_RW(ep->spsr) == MODE_RW_64) {
scr_el3 |= SCR_RW_BIT;
+ }
/*
* SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical
* Secure timer registers to EL3, from AArch64 state only, if specified
* by the entrypoint attributes.
*/
- if (EP_GET_ST(ep->h.attr) != 0U)
+ if (EP_GET_ST(ep->h.attr) != 0U) {
scr_el3 |= SCR_ST_BIT;
+ }
/*
* If FEAT_HCX is enabled, enable access to HCRX_EL2 by setting
@@ -152,8 +169,9 @@
* If the Secure world wants to use pointer authentication,
* CTX_INCLUDE_PAUTH_REGS must be set to 1.
*/
- if (security_state == NON_SECURE)
+ if (security_state == NON_SECURE) {
scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+ }
#endif /* !CTX_INCLUDE_PAUTH_REGS */
#if !CTX_INCLUDE_MTE_REGS || ENABLE_ASSERTIONS
@@ -188,8 +206,14 @@
/*
* SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as
* indicated by the interrupt routing model for BL31.
+ *
+ * TODO: The interrupt routing model code is not updated for REALM
+ * state. Use the default values of IRQ = FIQ = 0 for REALM security
+ * state for now.
*/
- scr_el3 |= get_scr_el3_from_routing_model(security_state);
+ if (security_state != REALM) {
+ scr_el3 |= get_scr_el3_from_routing_model(security_state);
+ }
#endif
/* Save the initialized value of CPTR_EL3 register */
@@ -256,9 +280,9 @@
* required by PSCI specification)
*/
sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U;
- if (GET_RW(ep->spsr) == MODE_RW_64)
+ if (GET_RW(ep->spsr) == MODE_RW_64) {
sctlr_elx |= SCTLR_EL1_RES1;
- else {
+ } else {
/*
* If the target execution state is AArch32 then the following
* fields need to be set.
@@ -413,7 +437,8 @@
}
/*******************************************************************************
- * Prepare the CPU system registers for first entry into secure or normal world
+ * Prepare the CPU system registers for first entry into realm, secure, or
+ * normal world.
*
* If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized
* If execution is requested to non-secure EL1 or svc mode, and the CPU supports
@@ -497,7 +522,7 @@
* 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
+ * CNTHCTL_EL2.EL1PTEN: Set to one to disable traps to
* Hyp mode of Non-secure EL0 and EL1 accesses to the
* physical timer registers.
*
@@ -645,10 +670,10 @@
u_register_t scr_el3 = read_scr();
/*
- * Always save the non-secure EL2 context, only save the
+ * Always save the non-secure and realm EL2 context, only save the
* S-EL2 context if S-EL2 is enabled.
*/
- if ((security_state == NON_SECURE) ||
+ if ((security_state != SECURE) ||
((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) {
cpu_context_t *ctx;
@@ -667,10 +692,10 @@
u_register_t scr_el3 = read_scr();
/*
- * Always restore the non-secure EL2 context, only restore the
+ * Always restore the non-secure and realm EL2 context, only restore the
* S-EL2 context if S-EL2 is enabled.
*/
- if ((security_state == NON_SECURE) ||
+ if ((security_state != SECURE) ||
((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) {
cpu_context_t *ctx;
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index 9a20ced..6f043e6 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -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
*/
@@ -71,26 +71,13 @@
}
tbbr_dyn_config.mbedtls_heap_size = val32;
-#if MEASURED_BOOT
- /* Retrieve BL2 hash data details from the DTB */
- err = fdtw_read_bytes(dtb, node, "bl2_hash_data", TCG_DIGEST_SIZE,
- &tbbr_dyn_config.bl2_hash_data);
- if (err < 0) {
- ERROR("FCONF: Read %s failed for '%s'\n",
- "bytes", "bl2_hash_data");
- return err;
- }
-#endif
VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth",
"` cell found with value =", tbbr_dyn_config.disable_auth);
VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
"` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size",
"` cell found with value =", tbbr_dyn_config.mbedtls_heap_size);
-#if MEASURED_BOOT
- VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "bl2_hash_data",
- "` array found at address =", tbbr_dyn_config.bl2_hash_data);
-#endif
+
return 0;
}
diff --git a/lib/gpt_rme/gpt_rme.c b/lib/gpt_rme/gpt_rme.c
new file mode 100644
index 0000000..1f90e64
--- /dev/null
+++ b/lib/gpt_rme/gpt_rme.c
@@ -0,0 +1,1112 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include "gpt_rme_private.h"
+#include <lib/gpt_rme/gpt_rme.h>
+#include <lib/smccc.h>
+#include <lib/spinlock.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#if !ENABLE_RME
+#error "ENABLE_RME must be enabled to use the GPT library."
+#endif
+
+/*
+ * Lookup T from PPS
+ *
+ * PPS Size T
+ * 0b000 4GB 32
+ * 0b001 64GB 36
+ * 0b010 1TB 40
+ * 0b011 4TB 42
+ * 0b100 16TB 44
+ * 0b101 256TB 48
+ * 0b110 4PB 52
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+static const gpt_t_val_e gpt_t_lookup[] = {PPS_4GB_T, PPS_64GB_T,
+ PPS_1TB_T, PPS_4TB_T,
+ PPS_16TB_T, PPS_256TB_T,
+ PPS_4PB_T};
+
+/*
+ * Lookup P from PGS
+ *
+ * PGS Size P
+ * 0b00 4KB 12
+ * 0b10 16KB 14
+ * 0b01 64KB 16
+ *
+ * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo.
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+static const gpt_p_val_e gpt_p_lookup[] = {PGS_4KB_P, PGS_64KB_P, PGS_16KB_P};
+
+/*
+ * This structure contains GPT configuration data.
+ */
+typedef struct {
+ uintptr_t plat_gpt_l0_base;
+ gpccr_pps_e pps;
+ gpt_t_val_e t;
+ gpccr_pgs_e pgs;
+ gpt_p_val_e p;
+} gpt_config_t;
+
+static gpt_config_t gpt_config;
+
+/* These variables are used during initialization of the L1 tables. */
+static unsigned int gpt_next_l1_tbl_idx;
+static uintptr_t gpt_l1_tbl;
+
+/*
+ * This function checks to see if a GPI value is valid.
+ *
+ * These are valid GPI values.
+ * GPT_GPI_NO_ACCESS U(0x0)
+ * GPT_GPI_SECURE U(0x8)
+ * GPT_GPI_NS U(0x9)
+ * GPT_GPI_ROOT U(0xA)
+ * GPT_GPI_REALM U(0xB)
+ * GPT_GPI_ANY U(0xF)
+ *
+ * Parameters
+ * gpi GPI to check for validity.
+ *
+ * Return
+ * true for a valid GPI, false for an invalid one.
+ */
+static bool gpt_is_gpi_valid(unsigned int gpi)
+{
+ if ((gpi == GPT_GPI_NO_ACCESS) || (gpi == GPT_GPI_ANY) ||
+ ((gpi >= GPT_GPI_SECURE) && (gpi <= GPT_GPI_REALM))) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*
+ * This function checks to see if two PAS regions overlap.
+ *
+ * Parameters
+ * base_1: base address of first PAS
+ * size_1: size of first PAS
+ * base_2: base address of second PAS
+ * size_2: size of second PAS
+ *
+ * Return
+ * True if PAS regions overlap, false if they do not.
+ */
+static bool gpt_check_pas_overlap(uintptr_t base_1, size_t size_1,
+ uintptr_t base_2, size_t size_2)
+{
+ if (((base_1 + size_1) > base_2) && ((base_2 + size_2) > base_1)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*
+ * This helper function checks to see if a PAS region from index 0 to
+ * (pas_idx - 1) occupies the L0 region at index l0_idx in the L0 table.
+ *
+ * Parameters
+ * l0_idx: Index of the L0 entry to check
+ * pas_regions: PAS region array
+ * pas_idx: Upper bound of the PAS array index.
+ *
+ * Return
+ * True if a PAS region occupies the L0 region in question, false if not.
+ */
+static bool gpt_does_previous_pas_exist_here(unsigned int l0_idx,
+ pas_region_t *pas_regions,
+ unsigned int pas_idx)
+{
+ /* Iterate over PAS regions up to pas_idx. */
+ for (unsigned int i = 0U; i < pas_idx; i++) {
+ if (gpt_check_pas_overlap((GPT_L0GPTSZ_ACTUAL_SIZE * l0_idx),
+ GPT_L0GPTSZ_ACTUAL_SIZE,
+ pas_regions[i].base_pa, pas_regions[i].size)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * This function iterates over all of the PAS regions and checks them to ensure
+ * proper alignment of base and size, that the GPI is valid, and that no regions
+ * overlap. As a part of the overlap checks, this function checks existing L0
+ * mappings against the new PAS regions in the event that gpt_init_pas_l1_tables
+ * is called multiple times to place L1 tables in different areas of memory. It
+ * also counts the number of L1 tables needed and returns it on success.
+ *
+ * Parameters
+ * *pas_regions Pointer to array of PAS region structures.
+ * pas_region_cnt Total number of PAS regions in the array.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, number of L1 regions
+ * required when successful.
+ */
+static int gpt_validate_pas_mappings(pas_region_t *pas_regions,
+ unsigned int pas_region_cnt)
+{
+ unsigned int idx;
+ unsigned int l1_cnt = 0U;
+ unsigned int pas_l1_cnt;
+ uint64_t *l0_desc = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+ assert(pas_regions != NULL);
+ assert(pas_region_cnt != 0U);
+
+ for (idx = 0U; idx < pas_region_cnt; idx++) {
+ /* Check for arithmetic overflow in region. */
+ if ((ULONG_MAX - pas_regions[idx].base_pa) <
+ pas_regions[idx].size) {
+ ERROR("[GPT] Address overflow in PAS[%u]!\n", idx);
+ return -EOVERFLOW;
+ }
+
+ /* Initial checks for PAS validity. */
+ if (((pas_regions[idx].base_pa + pas_regions[idx].size) >
+ GPT_PPS_ACTUAL_SIZE(gpt_config.t)) ||
+ !gpt_is_gpi_valid(GPT_PAS_ATTR_GPI(pas_regions[idx].attrs))) {
+ ERROR("[GPT] PAS[%u] is invalid!\n", idx);
+ return -EFAULT;
+ }
+
+ /*
+ * Make sure this PAS does not overlap with another one. We
+ * start from idx + 1 instead of 0 since prior PAS mappings will
+ * have already checked themselves against this one.
+ */
+ for (unsigned int i = idx + 1; i < pas_region_cnt; i++) {
+ if (gpt_check_pas_overlap(pas_regions[idx].base_pa,
+ pas_regions[idx].size,
+ pas_regions[i].base_pa,
+ pas_regions[i].size)) {
+ ERROR("[GPT] PAS[%u] overlaps with PAS[%u]\n",
+ i, idx);
+ return -EFAULT;
+ }
+ }
+
+ /*
+ * Since this function can be called multiple times with
+ * separate L1 tables we need to check the existing L0 mapping
+ * to see if this PAS would fall into one that has already been
+ * initialized.
+ */
+ for (unsigned int i = GPT_L0_IDX(pas_regions[idx].base_pa);
+ i <= GPT_L0_IDX(pas_regions[idx].base_pa + pas_regions[idx].size - 1);
+ i++) {
+ if ((GPT_L0_TYPE(l0_desc[i]) == GPT_L0_TYPE_BLK_DESC) &&
+ (GPT_L0_BLKD_GPI(l0_desc[i]) == GPT_GPI_ANY)) {
+ /* This descriptor is unused so continue. */
+ continue;
+ }
+
+ /*
+ * This descriptor has been initialized in a previous
+ * call to this function so cannot be initialized again.
+ */
+ ERROR("[GPT] PAS[%u] overlaps with previous L0[%d]!\n",
+ idx, i);
+ return -EFAULT;
+ }
+
+ /* Check for block mapping (L0) type. */
+ if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) ==
+ GPT_PAS_ATTR_MAP_TYPE_BLOCK) {
+ /* Make sure base and size are block-aligned. */
+ if (!GPT_IS_L0_ALIGNED(pas_regions[idx].base_pa) ||
+ !GPT_IS_L0_ALIGNED(pas_regions[idx].size)) {
+ ERROR("[GPT] PAS[%u] is not block-aligned!\n",
+ idx);
+ return -EFAULT;
+ }
+
+ continue;
+ }
+
+ /* Check for granule mapping (L1) type. */
+ if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) ==
+ GPT_PAS_ATTR_MAP_TYPE_GRANULE) {
+ /* Make sure base and size are granule-aligned. */
+ if (!GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].base_pa) ||
+ !GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].size)) {
+ ERROR("[GPT] PAS[%u] is not granule-aligned!\n",
+ idx);
+ return -EFAULT;
+ }
+
+ /* Find how many L1 tables this PAS occupies. */
+ pas_l1_cnt = (GPT_L0_IDX(pas_regions[idx].base_pa +
+ pas_regions[idx].size - 1) -
+ GPT_L0_IDX(pas_regions[idx].base_pa) + 1);
+
+ /*
+ * This creates a situation where, if multiple PAS
+ * regions occupy the same table descriptor, we can get
+ * an artificially high total L1 table count. The way we
+ * handle this is by checking each PAS against those
+ * before it in the array, and if they both occupy the
+ * same PAS we subtract from pas_l1_cnt and only the
+ * first PAS in the array gets to count it.
+ */
+
+ /*
+ * If L1 count is greater than 1 we know the start and
+ * end PAs are in different L0 regions so we must check
+ * both for overlap against other PAS.
+ */
+ if (pas_l1_cnt > 1) {
+ if (gpt_does_previous_pas_exist_here(
+ GPT_L0_IDX(pas_regions[idx].base_pa +
+ pas_regions[idx].size - 1),
+ pas_regions, idx)) {
+ pas_l1_cnt = pas_l1_cnt - 1;
+ }
+ }
+
+ if (gpt_does_previous_pas_exist_here(
+ GPT_L0_IDX(pas_regions[idx].base_pa),
+ pas_regions, idx)) {
+ pas_l1_cnt = pas_l1_cnt - 1;
+ }
+
+ l1_cnt += pas_l1_cnt;
+ continue;
+ }
+
+ /* If execution reaches this point, mapping type is invalid. */
+ ERROR("[GPT] PAS[%u] has invalid mapping type 0x%x.\n", idx,
+ GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs));
+ return -EINVAL;
+ }
+
+ return l1_cnt;
+}
+
+/*
+ * This function validates L0 initialization parameters.
+ *
+ * Parameters
+ * l0_mem_base Base address of memory used for L0 tables.
+ * l1_mem_size Size of memory available for L0 tables.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+static int gpt_validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base,
+ size_t l0_mem_size)
+{
+ size_t l0_alignment;
+
+ /*
+ * Make sure PPS is valid and then store it since macros need this value
+ * to work.
+ */
+ if (pps > GPT_PPS_MAX) {
+ ERROR("[GPT] Invalid PPS: 0x%x\n", pps);
+ return -EINVAL;
+ }
+ gpt_config.pps = pps;
+ gpt_config.t = gpt_t_lookup[pps];
+
+ /* Alignment must be the greater of 4k or l0 table size. */
+ l0_alignment = PAGE_SIZE_4KB;
+ if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) {
+ l0_alignment = GPT_L0_TABLE_SIZE(gpt_config.t);
+ }
+
+ /* Check base address. */
+ if ((l0_mem_base == 0U) || ((l0_mem_base & (l0_alignment - 1)) != 0U)) {
+ ERROR("[GPT] Invalid L0 base address: 0x%lx\n", l0_mem_base);
+ return -EFAULT;
+ }
+
+ /* Check size. */
+ if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) {
+ ERROR("[GPT] Inadequate L0 memory: need 0x%lx, have 0x%lx)\n",
+ GPT_L0_TABLE_SIZE(gpt_config.t),
+ l0_mem_size);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/*
+ * In the event that L1 tables are needed, this function validates
+ * the L1 table generation parameters.
+ *
+ * Parameters
+ * l1_mem_base Base address of memory used for L1 table allocation.
+ * l1_mem_size Total size of memory available for L1 tables.
+ * l1_gpt_cnt Number of L1 tables needed.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+static int gpt_validate_l1_params(uintptr_t l1_mem_base, size_t l1_mem_size,
+ unsigned int l1_gpt_cnt)
+{
+ size_t l1_gpt_mem_sz;
+
+ /* Check if the granularity is supported */
+ if (!xlat_arch_is_granule_size_supported(
+ GPT_PGS_ACTUAL_SIZE(gpt_config.p))) {
+ return -EPERM;
+ }
+
+ /* Make sure L1 tables are aligned to their size. */
+ if ((l1_mem_base & (GPT_L1_TABLE_SIZE(gpt_config.p) - 1)) != 0U) {
+ ERROR("[GPT] Unaligned L1 GPT base address: 0x%lx\n",
+ l1_mem_base);
+ return -EFAULT;
+ }
+
+ /* Get total memory needed for L1 tables. */
+ l1_gpt_mem_sz = l1_gpt_cnt * GPT_L1_TABLE_SIZE(gpt_config.p);
+
+ /* Check for overflow. */
+ if ((l1_gpt_mem_sz / GPT_L1_TABLE_SIZE(gpt_config.p)) != l1_gpt_cnt) {
+ ERROR("[GPT] Overflow calculating L1 memory size.\n");
+ return -ENOMEM;
+ }
+
+ /* Make sure enough space was supplied. */
+ if (l1_mem_size < l1_gpt_mem_sz) {
+ ERROR("[GPT] Inadequate memory for L1 GPTs. ");
+ ERROR(" Expected 0x%lx bytes. Got 0x%lx bytes\n",
+ l1_gpt_mem_sz, l1_mem_size);
+ return -ENOMEM;
+ }
+
+ VERBOSE("[GPT] Requested 0x%lx bytes for L1 GPTs.\n", l1_gpt_mem_sz);
+ return 0;
+}
+
+/*
+ * This function initializes L0 block descriptors (regions that cannot be
+ * transitioned at the granule level) according to the provided PAS.
+ *
+ * Parameters
+ * *pas Pointer to the structure defining the PAS region to
+ * initialize.
+ */
+static void gpt_generate_l0_blk_desc(pas_region_t *pas)
+{
+ uint64_t gpt_desc;
+ unsigned int end_idx;
+ unsigned int idx;
+ uint64_t *l0_gpt_arr;
+
+ assert(gpt_config.plat_gpt_l0_base != 0U);
+ assert(pas != NULL);
+
+ /*
+ * Checking of PAS parameters has already been done in
+ * gpt_validate_pas_mappings so no need to check the same things again.
+ */
+
+ l0_gpt_arr = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+ /* Create the GPT Block descriptor for this PAS region */
+ gpt_desc = GPT_L0_BLK_DESC(GPT_PAS_ATTR_GPI(pas->attrs));
+
+ /* Start index of this region in L0 GPTs */
+ idx = pas->base_pa >> GPT_L0_IDX_SHIFT;
+
+ /*
+ * Determine number of L0 GPT descriptors covered by
+ * this PAS region and use the count to populate these
+ * descriptors.
+ */
+ end_idx = (pas->base_pa + pas->size) >> GPT_L0_IDX_SHIFT;
+
+ /* Generate the needed block descriptors. */
+ for (; idx < end_idx; idx++) {
+ l0_gpt_arr[idx] = gpt_desc;
+ VERBOSE("[GPT] L0 entry (BLOCK) index %u [%p]: GPI = 0x%llx (0x%llx)\n",
+ idx, &l0_gpt_arr[idx],
+ (gpt_desc >> GPT_L0_BLK_DESC_GPI_SHIFT) &
+ GPT_L0_BLK_DESC_GPI_MASK, l0_gpt_arr[idx]);
+ }
+}
+
+/*
+ * Helper function to determine if the end physical address lies in the same L0
+ * region as the current physical address. If true, the end physical address is
+ * returned else, the start address of the next region is returned.
+ *
+ * Parameters
+ * cur_pa Physical address of the current PA in the loop through
+ * the range.
+ * end_pa Physical address of the end PA in a PAS range.
+ *
+ * Return
+ * The PA of the end of the current range.
+ */
+static uintptr_t gpt_get_l1_end_pa(uintptr_t cur_pa, uintptr_t end_pa)
+{
+ uintptr_t cur_idx;
+ uintptr_t end_idx;
+
+ cur_idx = cur_pa >> GPT_L0_IDX_SHIFT;
+ end_idx = end_pa >> GPT_L0_IDX_SHIFT;
+
+ assert(cur_idx <= end_idx);
+
+ if (cur_idx == end_idx) {
+ return end_pa;
+ }
+
+ return (cur_idx + 1U) << GPT_L0_IDX_SHIFT;
+}
+
+/*
+ * Helper function to fill out GPI entries in a single L1 table. This function
+ * fills out entire L1 descriptors at a time to save memory writes.
+ *
+ * Parameters
+ * gpi GPI to set this range to
+ * l1 Pointer to L1 table to fill out
+ * first Address of first granule in range.
+ * last Address of last granule in range (inclusive).
+ */
+static void gpt_fill_l1_tbl(uint64_t gpi, uint64_t *l1, uintptr_t first,
+ uintptr_t last)
+{
+ uint64_t gpi_field = GPT_BUILD_L1_DESC(gpi);
+ uint64_t gpi_mask = 0xFFFFFFFFFFFFFFFF;
+
+ assert(first <= last);
+ assert((first & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U);
+ assert((last & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U);
+ assert(GPT_L0_IDX(first) == GPT_L0_IDX(last));
+ assert(l1 != NULL);
+
+ /* Shift the mask if we're starting in the middle of an L1 entry. */
+ gpi_mask = gpi_mask << (GPT_L1_GPI_IDX(gpt_config.p, first) << 2);
+
+ /* Fill out each L1 entry for this region. */
+ for (unsigned int i = GPT_L1_IDX(gpt_config.p, first);
+ i <= GPT_L1_IDX(gpt_config.p, last); i++) {
+ /* Account for stopping in the middle of an L1 entry. */
+ if (i == GPT_L1_IDX(gpt_config.p, last)) {
+ gpi_mask &= (gpi_mask >> ((15 -
+ GPT_L1_GPI_IDX(gpt_config.p, last)) << 2));
+ }
+
+ /* Write GPI values. */
+ assert((l1[i] & gpi_mask) ==
+ (GPT_BUILD_L1_DESC(GPT_GPI_ANY) & gpi_mask));
+ l1[i] = (l1[i] & ~gpi_mask) | (gpi_mask & gpi_field);
+
+ /* Reset mask. */
+ gpi_mask = 0xFFFFFFFFFFFFFFFF;
+ }
+}
+
+/*
+ * This function finds the next available unused L1 table and initializes all
+ * granules descriptor entries to GPI_ANY. This ensures that there are no chunks
+ * of GPI_NO_ACCESS (0b0000) memory floating around in the system in the
+ * event that a PAS region stops midway through an L1 table, thus guaranteeing
+ * that all memory not explicitly assigned is GPI_ANY. This function does not
+ * check for overflow conditions, that should be done by the caller.
+ *
+ * Return
+ * Pointer to the next available L1 table.
+ */
+static uint64_t *gpt_get_new_l1_tbl(void)
+{
+ /* Retrieve the next L1 table. */
+ uint64_t *l1 = (uint64_t *)((uint64_t)(gpt_l1_tbl) +
+ (GPT_L1_TABLE_SIZE(gpt_config.p) *
+ gpt_next_l1_tbl_idx));
+
+ /* Increment L1 counter. */
+ gpt_next_l1_tbl_idx++;
+
+ /* Initialize all GPIs to GPT_GPI_ANY */
+ for (unsigned int i = 0U; i < GPT_L1_ENTRY_COUNT(gpt_config.p); i++) {
+ l1[i] = GPT_BUILD_L1_DESC(GPT_GPI_ANY);
+ }
+
+ return l1;
+}
+
+/*
+ * When L1 tables are needed, this function creates the necessary L0 table
+ * descriptors and fills out the L1 table entries according to the supplied
+ * PAS range.
+ *
+ * Parameters
+ * *pas Pointer to the structure defining the PAS region.
+ */
+static void gpt_generate_l0_tbl_desc(pas_region_t *pas)
+{
+ uintptr_t end_pa;
+ uintptr_t cur_pa;
+ uintptr_t last_gran_pa;
+ uint64_t *l0_gpt_base;
+ uint64_t *l1_gpt_arr;
+ unsigned int l0_idx;
+
+ assert(gpt_config.plat_gpt_l0_base != 0U);
+ assert(pas != NULL);
+
+ /*
+ * Checking of PAS parameters has already been done in
+ * gpt_validate_pas_mappings so no need to check the same things again.
+ */
+
+ end_pa = pas->base_pa + pas->size;
+ l0_gpt_base = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+ /* We start working from the granule at base PA */
+ cur_pa = pas->base_pa;
+
+ /* Iterate over each L0 region in this memory range. */
+ for (l0_idx = GPT_L0_IDX(pas->base_pa);
+ l0_idx <= GPT_L0_IDX(end_pa - 1U);
+ l0_idx++) {
+
+ /*
+ * See if the L0 entry is already a table descriptor or if we
+ * need to create one.
+ */
+ if (GPT_L0_TYPE(l0_gpt_base[l0_idx]) == GPT_L0_TYPE_TBL_DESC) {
+ /* Get the L1 array from the L0 entry. */
+ l1_gpt_arr = GPT_L0_TBLD_ADDR(l0_gpt_base[l0_idx]);
+ } else {
+ /* Get a new L1 table from the L1 memory space. */
+ l1_gpt_arr = gpt_get_new_l1_tbl();
+
+ /* Fill out the L0 descriptor and flush it. */
+ l0_gpt_base[l0_idx] = GPT_L0_TBL_DESC(l1_gpt_arr);
+ }
+
+ VERBOSE("[GPT] L0 entry (TABLE) index %u [%p] ==> L1 Addr 0x%llx (0x%llx)\n",
+ l0_idx, &l0_gpt_base[l0_idx],
+ (unsigned long long)(l1_gpt_arr),
+ l0_gpt_base[l0_idx]);
+
+ /*
+ * Determine the PA of the last granule in this L0 descriptor.
+ */
+ last_gran_pa = gpt_get_l1_end_pa(cur_pa, end_pa) -
+ GPT_PGS_ACTUAL_SIZE(gpt_config.p);
+
+ /*
+ * Fill up L1 GPT entries between these two addresses. This
+ * function needs the addresses of the first granule and last
+ * granule in the range.
+ */
+ gpt_fill_l1_tbl(GPT_PAS_ATTR_GPI(pas->attrs), l1_gpt_arr,
+ cur_pa, last_gran_pa);
+
+ /* Advance cur_pa to first granule in next L0 region. */
+ cur_pa = gpt_get_l1_end_pa(cur_pa, end_pa);
+ }
+}
+
+/*
+ * This function flushes a range of L0 descriptors used by a given PAS region
+ * array. There is a chance that some unmodified L0 descriptors would be flushed
+ * in the case that there are "holes" in an array of PAS regions but overall
+ * this should be faster than individually flushing each modified L0 descriptor
+ * as they are created.
+ *
+ * Parameters
+ * *pas Pointer to an array of PAS regions.
+ * pas_count Number of entries in the PAS array.
+ */
+static void flush_l0_for_pas_array(pas_region_t *pas, unsigned int pas_count)
+{
+ unsigned int idx;
+ unsigned int start_idx;
+ unsigned int end_idx;
+ uint64_t *l0 = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+ assert(pas != NULL);
+ assert(pas_count > 0);
+
+ /* Initial start and end values. */
+ start_idx = GPT_L0_IDX(pas[0].base_pa);
+ end_idx = GPT_L0_IDX(pas[0].base_pa + pas[0].size - 1);
+
+ /* Find lowest and highest L0 indices used in this PAS array. */
+ for (idx = 1; idx < pas_count; idx++) {
+ if (GPT_L0_IDX(pas[idx].base_pa) < start_idx) {
+ start_idx = GPT_L0_IDX(pas[idx].base_pa);
+ }
+ if (GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1) > end_idx) {
+ end_idx = GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1);
+ }
+ }
+
+ /*
+ * Flush all covered L0 descriptors, add 1 because we need to include
+ * the end index value.
+ */
+ flush_dcache_range((uintptr_t)&l0[start_idx],
+ ((end_idx + 1) - start_idx) * sizeof(uint64_t));
+}
+
+/*
+ * Public API to enable granule protection checks once the tables have all been
+ * initialized. This function is called at first initialization and then again
+ * later during warm boots of CPU cores.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_enable(void)
+{
+ u_register_t gpccr_el3;
+
+ /*
+ * Granule tables must be initialised before enabling
+ * granule protection.
+ */
+ if (gpt_config.plat_gpt_l0_base == 0U) {
+ ERROR("[GPT] Tables have not been initialized!\n");
+ return -EPERM;
+ }
+
+ /* Invalidate any stale TLB entries */
+ tlbipaallos();
+ dsb();
+
+ /* Write the base address of the L0 tables into GPTBR */
+ write_gptbr_el3(((gpt_config.plat_gpt_l0_base >> GPTBR_BADDR_VAL_SHIFT)
+ >> GPTBR_BADDR_SHIFT) & GPTBR_BADDR_MASK);
+
+ /* GPCCR_EL3.PPS */
+ gpccr_el3 = SET_GPCCR_PPS(gpt_config.pps);
+
+ /* GPCCR_EL3.PGS */
+ gpccr_el3 |= SET_GPCCR_PGS(gpt_config.pgs);
+
+ /* Set shareability attribute to Outher Shareable */
+ gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_OS);
+
+ /* Outer and Inner cacheability set to Normal memory, WB, RA, WA. */
+ gpccr_el3 |= SET_GPCCR_ORGN(GPCCR_ORGN_WB_RA_WA);
+ gpccr_el3 |= SET_GPCCR_IRGN(GPCCR_IRGN_WB_RA_WA);
+
+ /* Enable GPT */
+ gpccr_el3 |= GPCCR_GPC_BIT;
+
+ /* TODO: Configure GPCCR_EL3_GPCP for Fault control. */
+ write_gpccr_el3(gpccr_el3);
+ tlbipaallos();
+ dsb();
+ isb();
+
+ return 0;
+}
+
+/*
+ * Public API to disable granule protection checks.
+ */
+void gpt_disable(void)
+{
+ u_register_t gpccr_el3 = read_gpccr_el3();
+
+ write_gpccr_el3(gpccr_el3 & ~GPCCR_GPC_BIT);
+ dsbsy();
+ isb();
+}
+
+/*
+ * Public API that initializes the entire protected space to GPT_GPI_ANY using
+ * the L0 tables (block descriptors). Ideally, this function is invoked prior
+ * to DDR discovery and initialization. The MMU must be initialized before
+ * calling this function.
+ *
+ * Parameters
+ * pps PPS value to use for table generation
+ * l0_mem_base Base address of L0 tables in memory.
+ * l0_mem_size Total size of memory available for L0 tables.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_l0_tables(unsigned int pps, uintptr_t l0_mem_base,
+ size_t l0_mem_size)
+{
+ int ret;
+ uint64_t gpt_desc;
+
+ /* Ensure that MMU and caches are enabled. */
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
+ /* Validate other parameters. */
+ ret = gpt_validate_l0_params(pps, l0_mem_base, l0_mem_size);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Create the descriptor to initialize L0 entries with. */
+ gpt_desc = GPT_L0_BLK_DESC(GPT_GPI_ANY);
+
+ /* Iterate through all L0 entries */
+ for (unsigned int i = 0U; i < GPT_L0_REGION_COUNT(gpt_config.t); i++) {
+ ((uint64_t *)l0_mem_base)[i] = gpt_desc;
+ }
+
+ /* Flush updated L0 tables to memory. */
+ flush_dcache_range((uintptr_t)l0_mem_base,
+ (size_t)GPT_L0_TABLE_SIZE(gpt_config.t));
+
+ /* Stash the L0 base address once initial setup is complete. */
+ gpt_config.plat_gpt_l0_base = l0_mem_base;
+
+ return 0;
+}
+
+/*
+ * Public API that carves out PAS regions from the L0 tables and builds any L1
+ * tables that are needed. This function ideally is run after DDR discovery and
+ * initialization. The L0 tables must have already been initialized to GPI_ANY
+ * when this function is called.
+ *
+ * This function can be called multiple times with different L1 memory ranges
+ * and PAS regions if it is desirable to place L1 tables in different locations
+ * in memory. (ex: you have multiple DDR banks and want to place the L1 tables
+ * in the DDR bank that they control)
+ *
+ * Parameters
+ * pgs PGS value to use for table generation.
+ * l1_mem_base Base address of memory used for L1 tables.
+ * l1_mem_size Total size of memory available for L1 tables.
+ * *pas_regions Pointer to PAS regions structure array.
+ * pas_count Total number of PAS regions.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base,
+ size_t l1_mem_size, pas_region_t *pas_regions,
+ unsigned int pas_count)
+{
+ int ret;
+ int l1_gpt_cnt;
+
+ /* Ensure that MMU and caches are enabled. */
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
+ /* PGS is needed for gpt_validate_pas_mappings so check it now. */
+ if (pgs > GPT_PGS_MAX) {
+ ERROR("[GPT] Invalid PGS: 0x%x\n", pgs);
+ return -EINVAL;
+ }
+ gpt_config.pgs = pgs;
+ gpt_config.p = gpt_p_lookup[pgs];
+
+ /* Make sure L0 tables have been initialized. */
+ if (gpt_config.plat_gpt_l0_base == 0U) {
+ ERROR("[GPT] L0 tables must be initialized first!\n");
+ return -EPERM;
+ }
+
+ /* Check if L1 GPTs are required and how many. */
+ l1_gpt_cnt = gpt_validate_pas_mappings(pas_regions, pas_count);
+ if (l1_gpt_cnt < 0) {
+ return l1_gpt_cnt;
+ }
+
+ VERBOSE("[GPT] %u L1 GPTs requested.\n", l1_gpt_cnt);
+
+ /* If L1 tables are needed then validate the L1 parameters. */
+ if (l1_gpt_cnt > 0) {
+ ret = gpt_validate_l1_params(l1_mem_base, l1_mem_size,
+ l1_gpt_cnt);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Set up parameters for L1 table generation. */
+ gpt_l1_tbl = l1_mem_base;
+ gpt_next_l1_tbl_idx = 0U;
+ }
+
+ INFO("[GPT] Boot Configuration\n");
+ INFO(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t);
+ INFO(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p);
+ INFO(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL);
+ INFO(" PAS count: 0x%x\n", pas_count);
+ INFO(" L0 base: 0x%lx\n", gpt_config.plat_gpt_l0_base);
+
+ /* Generate the tables in memory. */
+ for (unsigned int idx = 0U; idx < pas_count; idx++) {
+ INFO("[GPT] PAS[%u]: base 0x%lx, size 0x%lx, GPI 0x%x, type 0x%x\n",
+ idx, pas_regions[idx].base_pa, pas_regions[idx].size,
+ GPT_PAS_ATTR_GPI(pas_regions[idx].attrs),
+ GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs));
+
+ /* Check if a block or table descriptor is required */
+ if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) ==
+ GPT_PAS_ATTR_MAP_TYPE_BLOCK) {
+ gpt_generate_l0_blk_desc(&pas_regions[idx]);
+
+ } else {
+ gpt_generate_l0_tbl_desc(&pas_regions[idx]);
+ }
+ }
+
+ /* Flush modified L0 tables. */
+ flush_l0_for_pas_array(pas_regions, pas_count);
+
+ /* Flush L1 tables if needed. */
+ if (l1_gpt_cnt > 0) {
+ flush_dcache_range(l1_mem_base,
+ GPT_L1_TABLE_SIZE(gpt_config.p) *
+ l1_gpt_cnt);
+ }
+
+ /* Make sure that all the entries are written to the memory. */
+ dsbishst();
+
+ return 0;
+}
+
+/*
+ * Public API to initialize the runtime gpt_config structure based on the values
+ * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization
+ * typically happens in a bootloader stage prior to setting up the EL3 runtime
+ * environment for the granule transition service so this function detects the
+ * initialization from a previous stage. Granule protection checks must be
+ * enabled already or this function will return an error.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_runtime_init(void)
+{
+ u_register_t reg;
+
+ /* Ensure that MMU and caches are enabled. */
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
+ /* Ensure GPC are already enabled. */
+ if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0U) {
+ ERROR("[GPT] Granule protection checks are not enabled!\n");
+ return -EPERM;
+ }
+
+ /*
+ * Read the L0 table address from GPTBR, we don't need the L1 base
+ * address since those are included in the L0 tables as needed.
+ */
+ reg = read_gptbr_el3();
+ gpt_config.plat_gpt_l0_base = ((reg >> GPTBR_BADDR_SHIFT) &
+ GPTBR_BADDR_MASK) <<
+ GPTBR_BADDR_VAL_SHIFT;
+
+ /* Read GPCCR to get PGS and PPS values. */
+ reg = read_gpccr_el3();
+ gpt_config.pps = (reg >> GPCCR_PPS_SHIFT) & GPCCR_PPS_MASK;
+ gpt_config.t = gpt_t_lookup[gpt_config.pps];
+ gpt_config.pgs = (reg >> GPCCR_PGS_SHIFT) & GPCCR_PGS_MASK;
+ gpt_config.p = gpt_p_lookup[gpt_config.pgs];
+
+ VERBOSE("[GPT] Runtime Configuration\n");
+ VERBOSE(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t);
+ VERBOSE(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p);
+ VERBOSE(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL);
+ VERBOSE(" L0 base: 0x%lx\n", gpt_config.plat_gpt_l0_base);
+
+ return 0;
+}
+
+/*
+ * The L1 descriptors are protected by a spinlock to ensure that multiple
+ * CPUs do not attempt to change the descriptors at once. In the future it
+ * would be better to have separate spinlocks for each L1 descriptor.
+ */
+static spinlock_t gpt_lock;
+
+/*
+ * Check if caller is allowed to transition a PAS.
+ *
+ * - Secure world caller can only request S <-> NS transitions on a
+ * granule that is already in either S or NS PAS.
+ *
+ * - Realm world caller can only request R <-> NS transitions on a
+ * granule that is already in either R or NS PAS.
+ *
+ * Parameters
+ * src_sec_state Security state of the caller.
+ * current_gpi Current GPI of the granule.
+ * target_gpi Requested new GPI for the granule.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+static int gpt_check_transition_gpi(unsigned int src_sec_state,
+ unsigned int current_gpi,
+ unsigned int target_gpi)
+{
+ unsigned int check_gpi;
+
+ /* Cannot transition a granule to the state it is already in. */
+ if (current_gpi == target_gpi) {
+ return -EINVAL;
+ }
+
+ /* Check security state, only secure and realm can transition. */
+ if (src_sec_state == SMC_FROM_REALM) {
+ check_gpi = GPT_GPI_REALM;
+ } else if (src_sec_state == SMC_FROM_SECURE) {
+ check_gpi = GPT_GPI_SECURE;
+ } else {
+ return -EINVAL;
+ }
+
+ /* Make sure security state is allowed to make the transition. */
+ if ((target_gpi != check_gpi) && (target_gpi != GPT_GPI_NS)) {
+ return -EINVAL;
+ }
+ if ((current_gpi != check_gpi) && (current_gpi != GPT_GPI_NS)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * This function is the core of the granule transition service. When a granule
+ * transition request occurs it is routed to this function where the request is
+ * validated then fulfilled if possible.
+ *
+ * TODO: implement support for transitioning multiple granules at once.
+ *
+ * Parameters
+ * base Base address of the region to transition, must be
+ * aligned to granule size.
+ * size Size of region to transition, must be aligned to granule
+ * size.
+ * src_sec_state Security state of the caller.
+ * target_pas Target PAS of the specified memory region.
+ *
+ * Return
+ * Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_transition_pas(uint64_t base, size_t size, unsigned int src_sec_state,
+ unsigned int target_pas)
+{
+ int idx;
+ unsigned int gpi_shift;
+ unsigned int gpi;
+ uint64_t gpt_l0_desc;
+ uint64_t gpt_l1_desc;
+ uint64_t *gpt_l1_addr;
+ uint64_t *gpt_l0_base;
+
+ /* Ensure that the tables have been set up before taking requests. */
+ assert(gpt_config.plat_gpt_l0_base != 0U);
+
+ /* Check for address range overflow. */
+ if ((ULONG_MAX - base) < size) {
+ VERBOSE("[GPT] Transition request address overflow!\n");
+ VERBOSE(" Base=0x%llx\n", base);
+ VERBOSE(" Size=0x%lx\n", size);
+ return -EINVAL;
+ }
+
+ /* Make sure base and size are valid. */
+ if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0U) ||
+ ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0U) ||
+ (size == 0U) ||
+ ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) {
+ VERBOSE("[GPT] Invalid granule transition address range!\n");
+ VERBOSE(" Base=0x%llx\n", base);
+ VERBOSE(" Size=0x%lx\n", size);
+ return -EINVAL;
+ }
+
+ /* See if this is a single granule transition or a range of granules. */
+ if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) {
+ /*
+ * TODO: Add support for transitioning multiple granules with a
+ * single call to this function.
+ */
+ panic();
+ }
+
+ /* Get the L0 descriptor and make sure it is for a table. */
+ gpt_l0_base = (uint64_t *)gpt_config.plat_gpt_l0_base;
+ gpt_l0_desc = gpt_l0_base[GPT_L0_IDX(base)];
+ if (GPT_L0_TYPE(gpt_l0_desc) != GPT_L0_TYPE_TBL_DESC) {
+ VERBOSE("[GPT] Granule is not covered by a table descriptor!\n");
+ VERBOSE(" Base=0x%llx\n", base);
+ return -EINVAL;
+ }
+
+ /* Get the table index and GPI shift from PA. */
+ gpt_l1_addr = GPT_L0_TBLD_ADDR(gpt_l0_desc);
+ idx = GPT_L1_IDX(gpt_config.p, base);
+ gpi_shift = GPT_L1_GPI_IDX(gpt_config.p, base) << 2;
+
+ /*
+ * Access to L1 tables is controlled by a global lock to ensure
+ * that no more than one CPU is allowed to make changes at any
+ * given time.
+ */
+ spin_lock(&gpt_lock);
+ gpt_l1_desc = gpt_l1_addr[idx];
+ gpi = (gpt_l1_desc >> gpi_shift) & GPT_L1_GRAN_DESC_GPI_MASK;
+
+ /* Make sure caller state and source/target PAS are allowed. */
+ if (gpt_check_transition_gpi(src_sec_state, gpi, target_pas) < 0) {
+ spin_unlock(&gpt_lock);
+ VERBOSE("[GPT] Invalid caller state and PAS combo!\n");
+ VERBOSE(" Caller: %u, Current GPI: %u, Target GPI: %u\n",
+ src_sec_state, gpi, target_pas);
+ return -EPERM;
+ }
+
+ /* Clear existing GPI encoding and transition granule. */
+ gpt_l1_desc &= ~(GPT_L1_GRAN_DESC_GPI_MASK << gpi_shift);
+ gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift);
+ gpt_l1_addr[idx] = gpt_l1_desc;
+
+ /* Ensure that the write operation happens before the unlock. */
+ dmbishst();
+
+ /* Unlock access to the L1 tables. */
+ spin_unlock(&gpt_lock);
+
+ /* Cache maintenance. */
+ clean_dcache_range((uintptr_t)&gpt_l1_addr[idx],
+ sizeof(uint64_t));
+ gpt_tlbi_by_pa(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+ dsbishst();
+
+ VERBOSE("[GPT] Granule 0x%llx, GPI 0x%x->0x%x\n", base, gpi,
+ target_pas);
+
+ return 0;
+}
diff --git a/lib/gpt_rme/gpt_rme.mk b/lib/gpt_rme/gpt_rme.mk
new file mode 100644
index 0000000..60176f4
--- /dev/null
+++ b/lib/gpt_rme/gpt_rme.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+GPT_LIB_SRCS := $(addprefix lib/gpt_rme/, \
+ gpt_rme.c)
diff --git a/lib/gpt_rme/gpt_rme_private.h b/lib/gpt_rme/gpt_rme_private.h
new file mode 100644
index 0000000..5770bf7
--- /dev/null
+++ b/lib/gpt_rme/gpt_rme_private.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPT_RME_PRIVATE_H
+#define GPT_RME_PRIVATE_H
+
+#include <arch.h>
+#include <lib/gpt_rme/gpt_rme.h>
+#include <lib/utils_def.h>
+
+/******************************************************************************/
+/* GPT descriptor definitions */
+/******************************************************************************/
+
+/* GPT level 0 descriptor bit definitions. */
+#define GPT_L0_TYPE_MASK UL(0xF)
+#define GPT_L0_TYPE_SHIFT U(0)
+
+/* For now, we don't support contiguous descriptors, only table and block. */
+#define GPT_L0_TYPE_TBL_DESC UL(0x3)
+#define GPT_L0_TYPE_BLK_DESC UL(0x1)
+
+#define GPT_L0_TBL_DESC_L1ADDR_MASK UL(0xFFFFFFFFFF)
+#define GPT_L0_TBL_DESC_L1ADDR_SHIFT U(12)
+
+#define GPT_L0_BLK_DESC_GPI_MASK UL(0xF)
+#define GPT_L0_BLK_DESC_GPI_SHIFT U(4)
+
+/* GPT level 1 descriptor bit definitions */
+#define GPT_L1_GRAN_DESC_GPI_MASK UL(0xF)
+
+/*
+ * This macro fills out every GPI entry in a granules descriptor to the same
+ * value.
+ */
+#define GPT_BUILD_L1_DESC(_gpi) (((uint64_t)(_gpi) << 4*0) | \
+ ((uint64_t)(_gpi) << 4*1) | \
+ ((uint64_t)(_gpi) << 4*2) | \
+ ((uint64_t)(_gpi) << 4*3) | \
+ ((uint64_t)(_gpi) << 4*4) | \
+ ((uint64_t)(_gpi) << 4*5) | \
+ ((uint64_t)(_gpi) << 4*6) | \
+ ((uint64_t)(_gpi) << 4*7) | \
+ ((uint64_t)(_gpi) << 4*8) | \
+ ((uint64_t)(_gpi) << 4*9) | \
+ ((uint64_t)(_gpi) << 4*10) | \
+ ((uint64_t)(_gpi) << 4*11) | \
+ ((uint64_t)(_gpi) << 4*12) | \
+ ((uint64_t)(_gpi) << 4*13) | \
+ ((uint64_t)(_gpi) << 4*14) | \
+ ((uint64_t)(_gpi) << 4*15))
+
+/******************************************************************************/
+/* GPT platform configuration */
+/******************************************************************************/
+
+/* This value comes from GPCCR_EL3 so no externally supplied definition. */
+#define GPT_L0GPTSZ ((unsigned int)((read_gpccr_el3() >> \
+ GPCCR_L0GPTSZ_SHIFT) & GPCCR_L0GPTSZ_MASK))
+
+/* The "S" value is directly related to L0GPTSZ */
+#define GPT_S_VAL (GPT_L0GPTSZ + 30U)
+
+/*
+ * Map PPS values to T values.
+ *
+ * PPS Size T
+ * 0b000 4GB 32
+ * 0b001 64GB 36
+ * 0b010 1TB 40
+ * 0b011 4TB 42
+ * 0b100 16TB 44
+ * 0b101 256TB 48
+ * 0b110 4PB 52
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+typedef enum {
+ PPS_4GB_T = 32U,
+ PPS_64GB_T = 36U,
+ PPS_1TB_T = 40U,
+ PPS_4TB_T = 42U,
+ PPS_16TB_T = 44U,
+ PPS_256TB_T = 48U,
+ PPS_4PB_T = 52U
+} gpt_t_val_e;
+
+/*
+ * Map PGS values to P values.
+ *
+ * PGS Size P
+ * 0b00 4KB 12
+ * 0b10 16KB 14
+ * 0b01 64KB 16
+ *
+ * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo.
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+typedef enum {
+ PGS_4KB_P = 12U,
+ PGS_16KB_P = 14U,
+ PGS_64KB_P = 16U
+} gpt_p_val_e;
+
+/* Max valid value for PGS. */
+#define GPT_PGS_MAX (2U)
+
+/* Max valid value for PPS. */
+#define GPT_PPS_MAX (6U)
+
+/******************************************************************************/
+/* L0 address attribute macros */
+/******************************************************************************/
+
+/*
+ * If S is greater than or equal to T then there is a single L0 region covering
+ * the entire protected space so there is no L0 index, so the width (and the
+ * derivative mask value) are both zero. If we don't specifically handle this
+ * special case we'll get a negative width value which does not make sense and
+ * could cause a lot of problems.
+ */
+#define GPT_L0_IDX_WIDTH(_t) (((_t) > GPT_S_VAL) ? \
+ ((_t) - GPT_S_VAL) : (0U))
+
+/* Bit shift for the L0 index field in a PA. */
+#define GPT_L0_IDX_SHIFT (GPT_S_VAL)
+
+/* Mask for the L0 index field, must be shifted. */
+#define GPT_L0_IDX_MASK(_t) (0xFFFFFFFFFFFFFFFFUL >> \
+ (64U - (GPT_L0_IDX_WIDTH(_t))))
+
+/* Total number of L0 regions. */
+#define GPT_L0_REGION_COUNT(_t) ((GPT_L0_IDX_MASK(_t)) + 1U)
+
+/* Total size of each GPT L0 region in bytes. */
+#define GPT_L0_REGION_SIZE (1UL << (GPT_L0_IDX_SHIFT))
+
+/* Total size in bytes of the whole L0 table. */
+#define GPT_L0_TABLE_SIZE(_t) ((GPT_L0_REGION_COUNT(_t)) << 3U)
+
+/******************************************************************************/
+/* L1 address attribute macros */
+/******************************************************************************/
+
+/* Width of the L1 index field. */
+#define GPT_L1_IDX_WIDTH(_p) ((GPT_S_VAL - 1U) - ((_p) + 3U))
+
+/* Bit shift for the L1 index field. */
+#define GPT_L1_IDX_SHIFT(_p) ((_p) + 4U)
+
+/* Mask for the L1 index field, must be shifted. */
+#define GPT_L1_IDX_MASK(_p) (0xFFFFFFFFFFFFFFFFUL >> \
+ (64U - (GPT_L1_IDX_WIDTH(_p))))
+
+/* Bit shift for the index of the L1 GPI in a PA. */
+#define GPT_L1_GPI_IDX_SHIFT(_p) (_p)
+
+/* Mask for the index of the L1 GPI in a PA. */
+#define GPT_L1_GPI_IDX_MASK (0xF)
+
+/* Total number of entries in each L1 table. */
+#define GPT_L1_ENTRY_COUNT(_p) ((GPT_L1_IDX_MASK(_p)) + 1U)
+
+/* Total size in bytes of each L1 table. */
+#define GPT_L1_TABLE_SIZE(_p) ((GPT_L1_ENTRY_COUNT(_p)) << 3U)
+
+/******************************************************************************/
+/* General helper macros */
+/******************************************************************************/
+
+/* Protected space actual size in bytes. */
+#define GPT_PPS_ACTUAL_SIZE(_t) (1UL << (_t))
+
+/* Granule actual size in bytes. */
+#define GPT_PGS_ACTUAL_SIZE(_p) (1UL << (_p))
+
+/* L0 GPT region size in bytes. */
+#define GPT_L0GPTSZ_ACTUAL_SIZE (1UL << GPT_S_VAL)
+
+/* Get the index of the L0 entry from a physical address. */
+#define GPT_L0_IDX(_pa) ((_pa) >> GPT_L0_IDX_SHIFT)
+
+/*
+ * This definition is used to determine if a physical address lies on an L0
+ * region boundary.
+ */
+#define GPT_IS_L0_ALIGNED(_pa) (((_pa) & (GPT_L0_REGION_SIZE - U(1))) == U(0))
+
+/* Get the type field from an L0 descriptor. */
+#define GPT_L0_TYPE(_desc) (((_desc) >> GPT_L0_TYPE_SHIFT) & \
+ GPT_L0_TYPE_MASK)
+
+/* Create an L0 block descriptor. */
+#define GPT_L0_BLK_DESC(_gpi) (GPT_L0_TYPE_BLK_DESC | \
+ (((_gpi) & GPT_L0_BLK_DESC_GPI_MASK) << \
+ GPT_L0_BLK_DESC_GPI_SHIFT))
+
+/* Create an L0 table descriptor with an L1 table address. */
+#define GPT_L0_TBL_DESC(_pa) (GPT_L0_TYPE_TBL_DESC | ((uint64_t)(_pa) & \
+ (GPT_L0_TBL_DESC_L1ADDR_MASK << \
+ GPT_L0_TBL_DESC_L1ADDR_SHIFT)))
+
+/* Get the GPI from an L0 block descriptor. */
+#define GPT_L0_BLKD_GPI(_desc) (((_desc) >> GPT_L0_BLK_DESC_GPI_SHIFT) & \
+ GPT_L0_BLK_DESC_GPI_MASK)
+
+/* Get the L1 address from an L0 table descriptor. */
+#define GPT_L0_TBLD_ADDR(_desc) ((uint64_t *)(((_desc) & \
+ (GPT_L0_TBL_DESC_L1ADDR_MASK << \
+ GPT_L0_TBL_DESC_L1ADDR_SHIFT))))
+
+/* Get the index into the L1 table from a physical address. */
+#define GPT_L1_IDX(_p, _pa) (((_pa) >> GPT_L1_IDX_SHIFT(_p)) & \
+ GPT_L1_IDX_MASK(_p))
+
+/* Get the index of the GPI within an L1 table entry from a physical address. */
+#define GPT_L1_GPI_IDX(_p, _pa) (((_pa) >> GPT_L1_GPI_IDX_SHIFT(_p)) & \
+ GPT_L1_GPI_IDX_MASK)
+
+/* Determine if an address is granule-aligned. */
+#define GPT_IS_L1_ALIGNED(_p, _pa) (((_pa) & (GPT_PGS_ACTUAL_SIZE(_p) - U(1))) \
+ == U(0))
+
+#endif /* GPT_RME_PRIVATE_H */
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index a95ef07..a1a44af 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -39,6 +39,23 @@
return PAGE_SIZE_4KB;
}
+/*
+ * Determine the physical address space encoded in the 'attr' parameter.
+ *
+ * The physical address will fall into one of two spaces; secure or
+ * nonsecure.
+ */
+uint32_t xlat_arch_get_pas(uint32_t attr)
+{
+ uint32_t pas = MT_PAS(attr);
+
+ if (pas == MT_NS) {
+ return LOWER_ATTRS(NS);
+ } else { /* MT_SECURE */
+ return 0U;
+ }
+}
+
#if ENABLE_ASSERTIONS
unsigned long long xlat_arch_get_max_supported_pa(void)
{
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 3832b07..719110a 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -53,6 +53,33 @@
}
}
+/*
+ * Determine the physical address space encoded in the 'attr' parameter.
+ *
+ * The physical address will fall into one of four spaces; secure,
+ * nonsecure, root, or realm if RME is enabled, or one of two spaces;
+ * secure and nonsecure otherwise.
+ */
+uint32_t xlat_arch_get_pas(uint32_t attr)
+{
+ uint32_t pas = MT_PAS(attr);
+
+ switch (pas) {
+#if ENABLE_RME
+ /* TTD.NSE = 1 and TTD.NS = 1 for Realm PAS */
+ case MT_REALM:
+ return LOWER_ATTRS(EL3_S1_NSE | NS);
+ /* TTD.NSE = 1 and TTD.NS = 0 for Root PAS */
+ case MT_ROOT:
+ return LOWER_ATTRS(EL3_S1_NSE);
+#endif
+ case MT_NS:
+ return LOWER_ATTRS(NS);
+ default: /* MT_SECURE */
+ return 0U;
+ }
+}
+
unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr)
{
/* Physical address can't exceed 48 bits */
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index bb6d184..de57184 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -125,11 +125,14 @@
* faults aren't managed.
*/
desc |= LOWER_ATTRS(ACCESS_FLAG);
+
+ /* Determine the physical address space this region belongs to. */
+ desc |= xlat_arch_get_pas(attr);
+
/*
- * Deduce other fields of the descriptor based on the MT_NS and MT_RW
- * memory region attributes.
+ * Deduce other fields of the descriptor based on the MT_RW memory
+ * region attributes.
*/
- desc |= ((attr & MT_NS) != 0U) ? LOWER_ATTRS(NS) : 0U;
desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
/*
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index 863470c..42c9a43 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,6 +40,9 @@
extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
+/* Determine the physical address space encoded in the 'attr' parameter. */
+uint32_t xlat_arch_get_pas(uint32_t attr);
+
/*
* Return the execute-never mask that will prevent instruction fetch at the
* given translation regime.
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index 9fae7e9..df17386 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -95,7 +95,23 @@
? "-USER" : "-PRIV");
}
+#if ENABLE_RME
+ switch (desc & LOWER_ATTRS(EL3_S1_NSE | NS)) {
+ case 0ULL:
+ printf("-S");
+ break;
+ case LOWER_ATTRS(NS):
+ printf("-NS");
+ break;
+ case LOWER_ATTRS(EL3_S1_NSE):
+ printf("-RT");
+ break;
+ default: /* LOWER_ATTRS(EL3_S1_NSE | NS) */
+ printf("-RL");
+ }
+#else
printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S");
+#endif
#ifdef __aarch64__
/* Check Guarded Page bit */
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 8655028..12aaee6 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -98,41 +98,41 @@
endef
# IMG_LINKERFILE defines the linker script corresponding to a BL stage
-# $(1) = BL stage (1, 2, 2u, 31, 32)
+# $(1) = BL stage
define IMG_LINKERFILE
- ${BUILD_DIR}/bl$(1).ld
+ ${BUILD_DIR}/$(1).ld
endef
# IMG_MAPFILE defines the output file describing the memory map corresponding
# to a BL stage
-# $(1) = BL stage (1, 2, 2u, 31, 32)
+# $(1) = BL stage
define IMG_MAPFILE
- ${BUILD_DIR}/bl$(1).map
+ ${BUILD_DIR}/$(1).map
endef
# IMG_ELF defines the elf file corresponding to a BL stage
-# $(1) = BL stage (1, 2, 2u, 31, 32)
+# $(1) = BL stage
define IMG_ELF
- ${BUILD_DIR}/bl$(1).elf
+ ${BUILD_DIR}/$(1).elf
endef
# IMG_DUMP defines the symbols dump file corresponding to a BL stage
-# $(1) = BL stage (1, 2, 2u, 31, 32)
+# $(1) = BL stage
define IMG_DUMP
- ${BUILD_DIR}/bl$(1).dump
+ ${BUILD_DIR}/$(1).dump
endef
# IMG_BIN defines the default image file corresponding to a BL stage
-# $(1) = BL stage (1, 2, 2u, 31, 32)
+# $(1) = BL stage
define IMG_BIN
- ${BUILD_PLAT}/bl$(1).bin
+ ${BUILD_PLAT}/$(1).bin
endef
# IMG_ENC_BIN defines the default encrypted image file corresponding to a
# BL stage
-# $(1) = BL stage (2, 30, 31, 32, 33)
+# $(1) = BL stage
define IMG_ENC_BIN
- ${BUILD_PLAT}/bl$(1)_enc.bin
+ ${BUILD_PLAT}/$(1)_enc.bin
endef
# ENCRYPT_FW invokes enctool to encrypt firmware binary
@@ -294,15 +294,15 @@
# MAKE_C builds a C source file and generates the dependency file
# $(1) = output directory
# $(2) = source file (%.c)
-# $(3) = BL stage (1, 2, 2u, 31, 32)
+# $(3) = BL stage
define MAKE_C
$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
$(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3)))
-$(eval BL_CFLAGS := $(BL$(call uppercase,$(3))_CFLAGS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+$(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
$$(ECHO) " CC $$<"
$$(Q)$$(CC) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -314,15 +314,15 @@
# MAKE_S builds an assembly source file and generates the dependency file
# $(1) = output directory
# $(2) = assembly file (%.S)
-# $(3) = BL stage (1, 2, 2u, 31, 32)
+# $(3) = BL stage
define MAKE_S
$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
$(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3)))
-$(eval BL_ASFLAGS := $(BL$(call uppercase,$(3))_ASFLAGS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+$(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
$$(ECHO) " AS $$<"
$$(Q)$$(AS) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -334,13 +334,13 @@
# MAKE_LD generate the linker script using the C preprocessor
# $(1) = output linker script
# $(2) = input template
-# $(3) = BL stage (1, 2, 2u, 31, 32)
+# $(3) = BL stage
define MAKE_LD
$(eval DEP := $(1).d)
-$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3)))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
-$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs
+$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
$$(ECHO) " PP $$<"
$$(Q)$$(CPP) $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$<
@@ -368,7 +368,7 @@
# MAKE_OBJS builds both C and assembly source files
# $(1) = output directory
# $(2) = list of source files (both C and assembly)
-# $(3) = BL stage (1, 2, 2u, 31, 32)
+# $(3) = BL stage
define MAKE_OBJS
$(eval C_OBJS := $(filter %.c,$(2)))
$(eval REMAIN := $(filter-out %.c,$(2)))
@@ -445,13 +445,13 @@
# MAKE_BL macro defines the targets and options to build each BL image.
# Arguments:
-# $(1) = BL stage (1, 2, 2u, 31, 32)
+# $(1) = BL stage
# $(2) = FIP command line option (if empty, image will not be included in the FIP)
# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
# $(4) = BL encryption flag (optional) (0, 1)
define MAKE_BL
- $(eval BUILD_DIR := ${BUILD_PLAT}/bl$(1))
- $(eval BL_SOURCES := $(BL$(call uppercase,$(1))_SOURCES))
+ $(eval BUILD_DIR := ${BUILD_PLAT}/$(1))
+ $(eval BL_SOURCES := $($(call uppercase,$(1))_SOURCES))
$(eval SOURCES := $(BL_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES))
$(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
$(eval LINKERFILE := $(call IMG_LINKERFILE,$(1)))
@@ -460,8 +460,8 @@
$(eval DUMP := $(call IMG_DUMP,$(1)))
$(eval BIN := $(call IMG_BIN,$(1)))
$(eval ENC_BIN := $(call IMG_ENC_BIN,$(1)))
- $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
- $(eval BL_LIBS := $(BL$(call uppercase,$(1))_LIBS))
+ $(eval BL_LINKERFILE := $($(call uppercase,$(1))_LINKERFILE))
+ $(eval BL_LIBS := $($(call uppercase,$(1))_LIBS))
# We use sort only to get a list of unique object directory names.
# ordering is not relevant but sort removes duplicates.
$(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS} ${LINKERFILE})))
@@ -475,21 +475,21 @@
$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-.PHONY : bl${1}_dirs
+.PHONY : ${1}_dirs
# We use order-only prerequisites to ensure that directories are created,
# but do not cause re-builds every time a file is written.
-bl${1}_dirs: | ${OBJ_DIRS}
+${1}_dirs: | ${OBJ_DIRS}
$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE),$(1)))
-$(eval BL_LDFLAGS := $(BL$(call uppercase,$(1))_LDFLAGS))
+$(eval BL_LDFLAGS := $($(call uppercase,$(1))_LDFLAGS))
ifeq ($(USE_ROMLIB),1)
$(ELF): romlib.bin
endif
-$(ELF): $(OBJS) $(LINKERFILE) | bl$(1)_dirs libraries $(BL_LIBS)
+$(ELF): $(OBJS) $(LINKERFILE) | $(1)_dirs libraries $(BL_LIBS)
$$(ECHO) " LD $$@"
ifdef MAKE_BUILD_STRINGS
$(call MAKE_BUILD_STRINGS, $(BUILD_DIR)/build_message.o)
@@ -499,10 +499,10 @@
$$(CC) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o
endif
ifneq ($(findstring armlink,$(notdir $(LD))),)
- $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=bl${1}_entrypoint \
+ $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \
--predefine="-D__LINKER__=$(__LINKER__)" \
--predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \
- --map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/bl${1}.scat \
+ --map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/${1}.scat \
$(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) \
$(BUILD_DIR)/build_message.o $(OBJS)
else ifneq ($(findstring gcc,$(notdir $(LD))),)
@@ -531,21 +531,21 @@
@echo "Built $$@ successfully"
@${ECHO_BLANK_LINE}
-.PHONY: bl$(1)
+.PHONY: $(1)
ifeq ($(DISABLE_BIN_GENERATION),1)
-bl$(1): $(ELF) $(DUMP)
+$(1): $(ELF) $(DUMP)
else
-bl$(1): $(BIN) $(DUMP)
+$(1): $(BIN) $(DUMP)
endif
-all: bl$(1)
+all: $(1)
ifeq ($(4),1)
$(call ENCRYPT_FW,$(BIN),$(ENC_BIN))
-$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \
+$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \
$(ENC_BIN)))
else
-$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(BIN),$(3)))
+$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(BIN),$(3)))
endif
endef
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 8b350db..819c536 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016-2021, ARM Limited. All rights reserved.
+# Copyright (c) 2016-2021, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -105,6 +105,9 @@
# Flag to enable PSCI STATs functionality
ENABLE_PSCI_STAT := 0
+# Flag to enable Realm Management Extension (FEAT_RME)
+ENABLE_RME := 0
+
# Flag to enable runtime instrumentation using PMF
ENABLE_RUNTIME_INSTRUMENTATION := 0
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 293e854..0a280b4 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -11,6 +11,7 @@
# Expected environment:
#
# BUILD_PLAT: output directory
+# NEED_BL2: indicates whether BL2 is needed by the platform
# NEED_BL32: indicates whether BL32 is needed by the platform
# BL2: image filename (optional). Default is IMG_BIN(2) (see macro IMG_BIN)
# SCP_BL2: image filename (optional). Default is IMG_BIN(30)
@@ -67,8 +68,8 @@
# Add the BL2 CoT (image cert)
+ifeq (${NEED_BL2},yes)
ifeq (${BL2_AT_EL3}, 0)
-ifneq (${PLAT},fvp_r)
$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
endif
endif
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 1217425..901fabf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -117,9 +117,9 @@
${FPGA_CPU_LIBS} \
${FPGA_GIC_SOURCES}
-$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,31))
-$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,31))
-$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,31))
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,bl31))
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,bl31))
+$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,bl31))
bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld
$(ECHO) " LD $@"
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 08d3c32..cf4ef2d 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -26,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 */
};
/*
@@ -117,6 +104,10 @@
#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/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
new file mode 100644
index 0000000..47af1f5
--- /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 06ee037..59fc0f3 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -76,63 +76,6 @@
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 0000000..5ebfede
--- /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 f2f2143..5a17a0d 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 @@
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 9d3c031..e7a28ac 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -107,6 +107,10 @@
#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 @@
#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 @@
};
#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 0000000..6a403d9
--- /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 5dcadba..0000000
--- 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/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 8b25a54..d89e122 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 73f09e5..70b1051 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -186,6 +186,10 @@
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 \
@@ -372,7 +376,10 @@
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
diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk
new file mode 100644
index 0000000..a450541
--- /dev/null
+++ b/plat/arm/board/fvp/trp/trp-fvp.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files specific to FVP platform
+
+RMM_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S
+
+include plat/arm/common/trp/arm_trp.mk
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
index 7ae853b..c6544b4 100644
--- a/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
@@ -15,7 +15,7 @@
#include <plat/common/platform.h>
-void cm_prepare_el2_exit(uint32_t security_state);
+void cm_prepare_el2_exit(void);
/* Following contains the cpu context pointers. */
static void *bl1_cpu_context_ptr[2];
@@ -81,6 +81,9 @@
/* 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;
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
index 5e31d39..68872c1 100644
--- a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
@@ -9,12 +9,12 @@
#include <assert.h>
-#include "../../../../lib/xlat_mpu/xlat_mpu.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>
@@ -140,7 +140,6 @@
*/
void arm_bl1_platform_setup(void)
{
- image_desc_t *desc;
uint32_t fw_config_max_size;
/* Initialise the IO layer and register platform IO devices */
@@ -157,8 +156,7 @@
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);
- desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
- assert(desc != NULL);
+ assert(bl1_plat_get_image_desc(BL33_IMAGE_ID) != NULL);
/*
* Allow access to the System counter timer module and program
diff --git a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
index 678b879..d172d2d 100644
--- a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
+++ b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
@@ -4,25 +4,50 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <lib/el3_runtime/context_mgmt.h>
-#include <lib/el3_runtime/pubsub_events.h>
+#include <arch_helpers.h>
-#include <platform_def.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);
-/*******************************************************************************
- * File contains EL2 equivalents of EL3 functions from
- * .../lib/el3_runtime/aarch64/context_mgmt.c
- ******************************************************************************/
+ /*
+ * 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);
-/*******************************************************************************
- * Prepare the CPU system registers for first entry into secure or normal world
- *
- * The majority of the work needed is only for switching to non-secure, which
- * is not available on v8-R64 cores, so this function is very simple.
- ******************************************************************************/
-void cm_prepare_el2_exit(uint32_t security_state)
-{
- cm_el1_sysregs_context_restore(security_state);
- cm_set_next_eret_context(security_state);
+ /*
+ * 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/platform.mk b/plat/arm/board/fvp_r/platform.mk
index 39509dd..8f5878f 100644
--- a/plat/arm/board/fvp_r/platform.mk
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -11,6 +11,7 @@
override NEED_BL2 := no
override NEED_BL2U := no
override NEED_BL31 := no
+NEED_BL32 := no
override CTX_INCLUDE_AARCH32_REGS := 0
@@ -56,70 +57,90 @@
$(error "Incorrect CCN driver chosen on FVP_R port")
endif
-PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include
-
-PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp_r/fvp_r_common.c
-
-FVP_R_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+include plat/arm/board/common/board_common.mk
+include plat/arm/common/arm_common.mk
-# select a different set of CPU files, depending on whether we compile for
-# hardware assisted coherency cores or not
-ifeq (${HW_ASSISTED_COHERENCY}, 0)
-# Cores used without DSU
-# FVP_R_CPU_LIBS += lib/cpus/aarch64/fvp_r.S
-else
-# Cores used with DSU only
-# FVP_R_CPU_LIBS += lib/cpus/aarch64/fvp_r.S
-endif
+PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include
-BL1_SOURCES += drivers/arm/sp805/sp805.c \
- drivers/delay_timer/delay_timer.c \
- drivers/io/io_semihosting.c \
- lib/semihosting/semihosting.c \
- lib/semihosting/${ARCH}/semihosting_call.S \
- plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c \
- plat/arm/board/fvp_r/fvp_r_bl1_setup.c \
+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_context.S \
+ 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 \
+ plat/arm/board/fvp_r/fvp_r_pauth_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_context_mgmt.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 \
- plat/arm/board/fvp_r/fvp_r_context.S \
- plat/arm/board/fvp_r/fvp_r_debug.S \
- plat/arm/board/fvp_r/fvp_r_helpers.S \
- plat/arm/board/fvp_r/fvp_r_misc_helpers.S \
- plat/arm/board/fvp_r/fvp_r_pauth_helpers.S \
- ${FVP_R_CPU_LIBS} \
- ${FVP_R_INTERCONNECT_SOURCES}
+ 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 \
+ common/uuid.c \
+ plat/arm/common/arm_dyn_cfg.c \
+ plat/arm/common/arm_dyn_cfg_helpers.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 \
+ bl1/tbbr/tbbr_img_desc.c \
+ plat/arm/common/arm_bl1_fwu.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)
-BL1_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+FVP_R_BL_COMMON_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
else
-BL1_SOURCES += drivers/delay_timer/generic_delay_timer.c
+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)
-PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c
+FVP_R_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c
endif
-NEED_BL32 := no
-
-ifneq (${BL2_AT_EL3}, 0)
- override BL1_SOURCES =
-endif
-
-include plat/arm/board/common/board_common.mk
-include plat/arm/common/arm_common.mk
-
-ifeq (${TRUSTED_BOARD_BOOT}, 1)
-BL1_SOURCES += plat/arm/board/fvp_r/fvp_r_trusted_boot.c
-
-# FVP being a development platform, enable capability to disable Authentication
-# dynamically if TRUSTED_BOARD_BOOT is set.
-DYN_DISABLE_AUTH := 1
-endif
+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/cpus/errata_report.c \
+ lib/cpus/aarch64/dsu_helpers.S \
+ lib/el3_runtime/aarch64/context.S \
+ lib/el3_runtime/aarch64/context_mgmt.c \
+ lib/fconf/fconf.c \
+ 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/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 5299a7b..d61ba5d 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/common/aarch64/arm_bl2_mem_params_desc.c b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
index 6a8943d..0666e57 100644
--- a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
+++ b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
@@ -1,5 +1,5 @@
/*
- * 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
*/
@@ -75,8 +75,10 @@
.image_info.image_base = BL31_BASE,
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
-# ifdef BL32_BASE
+# if defined(BL32_BASE)
.next_handoff_image_id = BL32_IMAGE_ID,
+# elif ENABLE_RME
+ .next_handoff_image_id = RMM_IMAGE_ID,
# else
.next_handoff_image_id = BL33_IMAGE_ID,
# endif
@@ -99,6 +101,22 @@
VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
+
+# if ENABLE_RME
+ /* Fill RMM related information */
+ {
+ .image_id = RMM_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, EP_REALM | EXECUTABLE),
+ .ep_info.pc = RMM_BASE,
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = RMM_BASE,
+ .image_info.image_max_size = RMM_LIMIT - RMM_BASE,
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+# endif
+
# ifdef BL32_BASE
/* Fill BL32 related information */
{
@@ -113,7 +131,11 @@
.image_info.image_base = BL32_BASE,
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+# if ENABLE_RME
+ .next_handoff_image_id = RMM_IMAGE_ID,
+# else
.next_handoff_image_id = BL33_IMAGE_ID,
+# endif
},
/*
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 872de3e..320bb82 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -32,7 +32,7 @@
#define MAP_BL1_TOTAL MAP_REGION_FLAT( \
bl1_tzram_layout.total_base, \
bl1_tzram_layout.total_size, \
- MT_MEMORY | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | EL3_PAS)
/*
* If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
* otherwise one region is defined containing both
@@ -41,17 +41,17 @@
#define MAP_BL1_RO MAP_REGION_FLAT( \
BL_CODE_BASE, \
BL1_CODE_END - BL_CODE_BASE, \
- MT_CODE | MT_SECURE), \
+ MT_CODE | EL3_PAS), \
MAP_REGION_FLAT( \
BL1_RO_DATA_BASE, \
BL1_RO_DATA_END \
- BL_RO_DATA_BASE, \
- MT_RO_DATA | MT_SECURE)
+ MT_RO_DATA | EL3_PAS)
#else
#define MAP_BL1_RO MAP_REGION_FLAT( \
BL_CODE_BASE, \
BL1_CODE_END - BL_CODE_BASE, \
- MT_CODE | MT_SECURE)
+ MT_CODE | EL3_PAS)
#endif
/* Data structure which holds the extents of the trusted SRAM for BL1*/
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 5b26a1d..08c014d 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -9,6 +9,7 @@
#include <platform_def.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
@@ -17,10 +18,16 @@
#include <drivers/partition/partition.h>
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#if ENABLE_RME
+#include <lib/gpt_rme/gpt_rme.h>
+#endif /* ENABLE_RME */
#ifdef SPD_opteed
#include <lib/optee_utils.h>
#endif
#include <lib/utils.h>
+#if ENABLE_RME
+#include <plat/arm/common/arm_pas_def.h>
+#endif /* ENABLE_RME */
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
@@ -41,15 +48,18 @@
#pragma weak bl2_platform_setup
#pragma weak bl2_plat_arch_setup
#pragma weak bl2_plat_sec_mem_layout
-#if MEASURED_BOOT
-#pragma weak bl2_plat_get_hash
-#endif
+#if ENABLE_RME
+#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
+ bl2_tzram_layout.total_base, \
+ bl2_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | MT_ROOT)
+#else
#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
bl2_tzram_layout.total_base, \
bl2_tzram_layout.total_size, \
MT_MEMORY | MT_RW | MT_SECURE)
-
+#endif /* ENABLE_RME */
#pragma weak arm_bl2_plat_handle_post_image_load
@@ -105,8 +115,10 @@
*/
void arm_bl2_platform_setup(void)
{
+#if !ENABLE_RME
/* Initialize the secure environment */
plat_arm_security_setup();
+#endif
#if defined(PLAT_ARM_MEM_PROT_ADDR)
arm_nor_psci_do_static_mem_protect();
@@ -118,9 +130,54 @@
arm_bl2_platform_setup();
}
+#if ENABLE_RME
+
+static void arm_bl2_plat_gpt_setup(void)
+{
+ /*
+ * The GPT library might modify the gpt regions structure to optimize
+ * the layout, so the array cannot be constant.
+ */
+ pas_region_t pas_regions[] = {
+ ARM_PAS_KERNEL,
+ ARM_PAS_SECURE,
+ ARM_PAS_REALM,
+ ARM_PAS_EL3_DRAM,
+ ARM_PAS_GPTS
+ };
+
+ /* Initialize entire protected space to GPT_GPI_ANY. */
+ if (gpt_init_l0_tables(GPCCR_PPS_4GB, ARM_L0_GPT_ADDR_BASE,
+ ARM_L0_GPT_SIZE) < 0) {
+ ERROR("gpt_init_l0_tables() failed!\n");
+ panic();
+ }
+
+ /* Carve out defined PAS ranges. */
+ if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
+ ARM_L1_GPT_ADDR_BASE,
+ ARM_L1_GPT_SIZE,
+ pas_regions,
+ (unsigned int)(sizeof(pas_regions) /
+ sizeof(pas_region_t))) < 0) {
+ ERROR("gpt_init_pas_l1_tables() failed!\n");
+ panic();
+ }
+
+ INFO("Enabling Granule Protection Checks\n");
+ if (gpt_enable() < 0) {
+ ERROR("gpt_enable() failed!\n");
+ panic();
+ }
+}
+
+#endif /* ENABLE_RME */
+
/*******************************************************************************
- * Perform the very early platform specific architectural setup here. At the
- * moment this is only initializes the mmu in a quick and dirty way.
+ * Perform the very early platform specific architectural setup here.
+ * When RME is enabled the secure environment is initialised before
+ * initialising and enabling Granule Protection.
+ * This function initialises the MMU in a quick and dirty way.
******************************************************************************/
void arm_bl2_plat_arch_setup(void)
{
@@ -143,13 +200,29 @@
ARM_MAP_BL_COHERENT_RAM,
#endif
ARM_MAP_BL_CONFIG_REGION,
+#if ENABLE_RME
+ ARM_MAP_L0_GPT_REGION,
+#endif
{0}
};
+#if ENABLE_RME
+ /* Initialise the secure environment */
+ plat_arm_security_setup();
+#endif
setup_page_tables(bl_regions, plat_arm_get_mmap());
#ifdef __aarch64__
+#if ENABLE_RME
+ /* BL2 runs in EL3 when RME enabled. */
+ assert(get_armv9_2_feat_rme_support() != 0U);
+ enable_mmu_el3(0);
+
+ /* Initialise and enable granule protection after MMU. */
+ arm_bl2_plat_gpt_setup();
+#else
enable_mmu_el1(0);
+#endif
#else
enable_mmu_svc_mon(0);
#endif
@@ -247,11 +320,3 @@
{
return arm_bl2_plat_handle_post_image_load(image_id);
}
-
-#if MEASURED_BOOT
-/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
-void bl2_plat_get_hash(void *data)
-{
- arm_bl2_get_hash(data);
-}
-#endif
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index b819888..6472590 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,9 @@
#include <drivers/console.h>
#include <lib/debugfs.h>
#include <lib/extensions/ras.h>
+#if ENABLE_RME
+#include <lib/gpt_rme/gpt_rme.h>
+#endif
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
#include <plat/arm/common/plat_arm.h>
@@ -25,6 +28,9 @@
*/
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
+#if ENABLE_RME
+static entry_point_info_t rmm_image_ep_info;
+#endif
#if !RESET_TO_BL31
/*
@@ -43,7 +49,7 @@
#define MAP_BL31_TOTAL MAP_REGION_FLAT( \
BL31_START, \
BL31_END - BL31_START, \
- MT_MEMORY | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | EL3_PAS)
#if RECLAIM_INIT_CODE
IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE);
IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_CODE_END_UNALIGNED);
@@ -58,7 +64,7 @@
BL_INIT_CODE_BASE, \
BL_INIT_CODE_END \
- BL_INIT_CODE_BASE, \
- MT_CODE | MT_SECURE)
+ MT_CODE | EL3_PAS)
#endif
#if SEPARATE_NOBITS_REGION
@@ -66,7 +72,7 @@
BL31_NOBITS_BASE, \
BL31_NOBITS_LIMIT \
- BL31_NOBITS_BASE, \
- MT_MEMORY | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | EL3_PAS)
#endif
/*******************************************************************************
@@ -80,8 +86,18 @@
entry_point_info_t *next_image_info;
assert(sec_state_is_valid(type));
- next_image_info = (type == NON_SECURE)
- ? &bl33_image_ep_info : &bl32_image_ep_info;
+ if (type == NON_SECURE) {
+ next_image_info = &bl33_image_ep_info;
+ }
+#if ENABLE_RME
+ else if (type == REALM) {
+ next_image_info = &rmm_image_ep_info;
+ }
+#endif
+ else {
+ next_image_info = &bl32_image_ep_info;
+ }
+
/*
* None of the images on the ARM development platforms can have 0x0
* as the entrypoint
@@ -169,21 +185,31 @@
bl_params_node_t *bl_params = params_from_bl2->head;
/*
- * Copy BL33 and BL32 (if present), entry point information.
+ * Copy BL33, BL32 and RMM (if present), entry point information.
* They are stored in Secure RAM, in BL2's address space.
*/
while (bl_params != NULL) {
- if (bl_params->image_id == BL32_IMAGE_ID)
+ if (bl_params->image_id == BL32_IMAGE_ID) {
bl32_image_ep_info = *bl_params->ep_info;
-
- if (bl_params->image_id == BL33_IMAGE_ID)
+ }
+#if ENABLE_RME
+ else if (bl_params->image_id == RMM_IMAGE_ID) {
+ rmm_image_ep_info = *bl_params->ep_info;
+ }
+#endif
+ else if (bl_params->image_id == BL33_IMAGE_ID) {
bl33_image_ep_info = *bl_params->ep_info;
+ }
bl_params = bl_params->next_params_info;
}
if (bl33_image_ep_info.pc == 0U)
panic();
+#if ENABLE_RME
+ if (rmm_image_ep_info.pc == 0U)
+ panic();
+#endif
#endif /* RESET_TO_BL31 */
# if ARM_LINUX_KERNEL_AS_BL33
@@ -193,7 +219,11 @@
* tree blob (DTB) in x0, while x1-x3 are reserved for future use and
* must be 0.
*/
+#if RESET_TO_BL31
bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+#else
+ bl33_image_ep_info.args.arg0 = (u_register_t)hw_config;
+#endif
bl33_image_ep_info.args.arg1 = 0U;
bl33_image_ep_info.args.arg2 = 0U;
bl33_image_ep_info.args.arg3 = 0U;
@@ -355,6 +385,9 @@
{
const mmap_region_t bl_regions[] = {
MAP_BL31_TOTAL,
+#if ENABLE_RME
+ ARM_MAP_L0_GPT_REGION,
+#endif
#if RECLAIM_INIT_CODE
MAP_BL_INIT_CODE,
#endif
@@ -376,6 +409,19 @@
enable_mmu_el3(0);
+#if ENABLE_RME
+ /*
+ * Initialise Granule Protection library and enable GPC for the primary
+ * processor. The tables have already been initialized by a previous BL
+ * stage, so there is no need to provide any PAS here. This function
+ * sets up pointers to those tables.
+ */
+ if (gpt_runtime_init() < 0) {
+ ERROR("gpt_runtime_init() failed!\n");
+ panic();
+ }
+#endif /* ENABLE_RME */
+
arm_setup_romlib();
}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index dc8c6d0..a20e258 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -52,9 +52,10 @@
$(eval $(call add_define,ARM_RECOM_STATE_ID_ENC))
# Process ARM_DISABLE_TRUSTED_WDOG flag
-# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
+# By default, Trusted Watchdog is always enabled unless
+# SPIN_ON_BL1_EXIT or ENABLE_RME is set
ARM_DISABLE_TRUSTED_WDOG := 0
-ifeq (${SPIN_ON_BL1_EXIT}, 1)
+ifneq ($(filter 1,${SPIN_ON_BL1_EXIT} ${ENABLE_RME}),)
ARM_DISABLE_TRUSTED_WDOG := 1
endif
$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
@@ -94,10 +95,13 @@
ifndef PRELOADED_BL33_BASE
$(error "PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
endif
- ifndef ARM_PRELOADED_DTB_BASE
- $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
+ ifeq (${RESET_TO_BL31},1)
+ ifndef ARM_PRELOADED_DTB_BASE
+ $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is
+ used with RESET_TO_BL31.")
+ endif
+ $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
endif
- $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
endif
# Arm Ethos-N NPU SiP service
@@ -355,13 +359,8 @@
# Include the selected chain of trust sources.
ifeq (${COT},tbbr)
- ifeq (${PLAT},fvp_r)
- BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
- drivers/auth/tbbr/tbbr_cot_bl1_r64.c
- else
BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
drivers/auth/tbbr/tbbr_cot_bl1.c
- endif
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
else
@@ -407,7 +406,7 @@
endif
ifeq (${MEASURED_BOOT},1)
- MEASURED_BOOT_MK := drivers/measured_boot/measured_boot.mk
+ MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
$(info Including ${MEASURED_BOOT_MK})
include ${MEASURED_BOOT_MK}
endif
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 30473be..6aae9ae 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,10 +15,6 @@
#include <common/tbbr/tbbr_img_def.h>
#if TRUSTED_BOARD_BOOT
#include <drivers/auth/mbedtls/mbedtls_config.h>
-#if MEASURED_BOOT
-#include <drivers/auth/crypto_mod.h>
-#include <mbedtls/md.h>
-#endif
#endif
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
@@ -115,82 +111,13 @@
* images. It's critical because BL2 won't be able to proceed
* without the heap info.
*
- * In MEASURED_BOOT case flushing is done in
- * arm_bl1_set_bl2_hash() function which is called after heap
- * information is written in the DTB.
+ * In MEASURED_BOOT case flushing is done in a function which
+ * is called after heap information is written in the DTB.
*/
flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb));
#endif /* !MEASURED_BOOT */
}
-}
-
-#if MEASURED_BOOT
-/*
- * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
- * Executed only from BL1.
- */
-void arm_bl1_set_bl2_hash(const image_desc_t *image_desc)
-{
- unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
- const image_info_t image_info = image_desc->image_info;
- uintptr_t tb_fw_cfg_dtb;
- int err;
- const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
-
- tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
- assert(tb_fw_config_info != NULL);
-
- tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
-
- /*
- * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
- * platform. As such, we cannot write to the DTB at all and pass
- * measured data.
- */
- if (tb_fw_cfg_dtb == 0UL) {
- panic();
- }
-
- /* Calculate hash */
- err = crypto_mod_calc_hash(MBEDTLS_MD_ID,
- (void *)image_info.image_base,
- image_info.image_size, hash_data);
- if (err != 0) {
- ERROR("%scalculate%s\n", "BL1: unable to ",
- " BL2 hash");
- panic();
- }
-
- err = arm_set_bl2_hash_info((void *)tb_fw_cfg_dtb, hash_data);
- if (err < 0) {
- ERROR("%swrite%sdata%s\n", "BL1: unable to ",
- " BL2 hash ", "to DTB\n");
- panic();
- }
-
- /*
- * Ensure that the info written to the DTB is visible to other
- * images. It's critical because BL2 won't be able to proceed
- * without the heap info and its hash data.
- */
- flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize((void *)tb_fw_cfg_dtb));
-}
-
-/*
- * Reads TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB.
- * Executed only from BL2.
- */
-void arm_bl2_get_hash(void *data)
-{
- const void *bl2_hash;
-
- assert(data != NULL);
-
- /* Retrieve TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB */
- bl2_hash = FCONF_GET_PROPERTY(tbbr, dyn_config, bl2_hash_data);
- (void)memcpy(data, bl2_hash, TCG_DIGEST_SIZE);
}
-#endif /* MEASURED_BOOT */
#endif /* TRUSTED_BOARD_BOOT */
/*
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index 5f20c8d..6a2a6f8 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -11,6 +11,8 @@
#endif
#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <libfdt.h>
#include <plat/arm/common/arm_dyn_cfg_helpers.h>
@@ -20,18 +22,15 @@
#define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
#if MEASURED_BOOT
-#define DTB_PROP_BL2_HASH_DATA "bl2_hash_data"
#ifdef SPD_opteed
/*
* Currently OP-TEE does not support reading DTBs from Secure memory
* and this property should be removed when this feature is supported.
*/
#define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr"
-#endif
+#endif /* SPD_opteed */
#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
-
-static int dtb_root = -1;
#endif /* MEASURED_BOOT */
/*******************************************************************************
@@ -81,9 +80,8 @@
*/
int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size)
{
-#if !MEASURED_BOOT
int dtb_root;
-#endif
+
/*
* Verify that the DTB is valid, before attempting to write to it,
* and get the DTB root node.
@@ -123,32 +121,8 @@
#if MEASURED_BOOT
/*
- * This function writes the BL2 hash data in HW_FW_CONFIG DTB.
- * When it is called, it is guaranteed that a DTB is available.
- *
- * This function is supposed to be called only by BL1.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
-int arm_set_bl2_hash_info(void *dtb, void *data)
-{
- assert(dtb_root >= 0);
-
- /*
- * Write the BL2 hash data in the DTB.
- */
- return fdtw_write_inplace_bytes(dtb, dtb_root,
- DTB_PROP_BL2_HASH_DATA,
- TCG_DIGEST_SIZE, data);
-}
-
-/*
* Write the Event Log address and its size in the DTB.
*
- * This function is supposed to be called only by BL2.
- *
* Returns:
* 0 = success
* < 0 = error
@@ -231,14 +205,20 @@
* 0 = success
* < 0 = error
*/
-int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
- size_t log_size)
+int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size)
{
+ uintptr_t config_base;
+ const bl_mem_params_node_t *cfg_mem_params;
int err;
- assert(config_base != 0UL);
assert(log_addr != 0UL);
+ /* Get the config load address and size of TOS_FW_CONFIG */
+ cfg_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
+ assert(cfg_mem_params != NULL);
+
+ config_base = cfg_mem_params->image_info.image_base;
+
/* Write the Event Log address and its size in the DTB */
err = arm_set_event_log_info(config_base,
#ifdef SPD_opteed
@@ -263,23 +243,25 @@
* 0 = success
* < 0 = error
*/
-int arm_set_nt_fw_info(uintptr_t config_base,
+int arm_set_nt_fw_info(
#ifdef SPD_opteed
uintptr_t log_addr,
#endif
size_t log_size, uintptr_t *ns_log_addr)
{
+ uintptr_t config_base;
uintptr_t ns_addr;
const bl_mem_params_node_t *cfg_mem_params;
int err;
- assert(config_base != 0UL);
assert(ns_log_addr != NULL);
/* Get the config load address and size from NT_FW_CONFIG */
cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
assert(cfg_mem_params != NULL);
+ config_base = cfg_mem_params->image_info.image_base;
+
/* Calculate Event Log address in Non-secure memory */
ns_addr = cfg_mem_params->image_info.image_base +
cfg_mem_params->image_info.image_max_size;
@@ -300,4 +282,87 @@
*ns_log_addr = (err < 0) ? 0UL : ns_addr;
return err;
}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TB_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL1.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size)
+{
+ /*
+ * Read tb_fw_config device tree for Event Log properties
+ * and write the Event Log address and its size in the DTB
+ */
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+ uintptr_t tb_fw_cfg_dtb;
+ int err;
+
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
+
+ err = arm_set_event_log_info(tb_fw_cfg_dtb,
+#ifdef SPD_opteed
+ 0UL,
+#endif
+ log_addr, log_size);
+ return err;
+}
+
+/*
+ * This function reads the Event Log address and its size
+ * properties present in TB_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ * Alongside returns Event Log address and its size.
+ */
+
+int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size)
+{
+ /* As libfdt uses void *, we can't avoid this cast */
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+ int node, rc;
+
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ void *dtb = (void *)tb_fw_config_info->config_addr;
+ const char *compatible = "arm,tpm_event_log";
+
+ /* Assert the node offset point to compatible property */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible);
+ if (node < 0) {
+ WARN("The compatible property '%s'%s", compatible,
+ " not specified in TB_FW config.\n");
+ return node;
+ }
+
+ VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
+
+ rc = fdt_read_uint64(dtb, node, DTB_PROP_HW_LOG_ADDR, log_addr);
+ if (rc != 0) {
+ ERROR("%s%s", DTB_PROP_HW_LOG_ADDR,
+ " not specified in TB_FW config.\n");
+ return rc;
+ }
+
+ rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_SIZE, (uint32_t *)log_size);
+ if (rc != 0) {
+ ERROR("%s%s", DTB_PROP_HW_LOG_SIZE,
+ " not specified in TB_FW config.\n");
+ }
+
+ return rc;
+}
#endif /* MEASURED_BOOT */
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 86fd6d5..aea2f38 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -67,6 +67,7 @@
[SOC_FW_CONFIG_ID] = {UUID_SOC_FW_CONFIG},
[TOS_FW_CONFIG_ID] = {UUID_TOS_FW_CONFIG},
[NT_FW_CONFIG_ID] = {UUID_NT_FW_CONFIG},
+ [RMM_IMAGE_ID] = {UUID_REALM_MONITOR_MGMT_FIRMWARE},
#endif /* ARM_IO_IN_DTB */
#if TRUSTED_BOARD_BOOT
[TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT},
@@ -162,6 +163,11 @@
(uintptr_t)&arm_uuid_spec[BL33_IMAGE_ID],
open_fip
},
+ [RMM_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[RMM_IMAGE_ID],
+ open_fip
+ },
[HW_CONFIG_ID] = {
&fip_dev_handle,
(uintptr_t)&arm_uuid_spec[HW_CONFIG_ID],
diff --git a/plat/arm/common/trp/arm_trp.mk b/plat/arm/common/trp/arm_trp.mk
new file mode 100644
index 0000000..997111f
--- /dev/null
+++ b/plat/arm/common/trp/arm_trp.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files common to ARM standard platforms
+RMM_SOURCES += plat/arm/common/trp/arm_trp_setup.c \
+ plat/arm/common/arm_topology.c \
+ plat/common/aarch64/platform_mp_stack.S
diff --git a/plat/arm/common/trp/arm_trp_setup.c b/plat/arm/common/trp/arm_trp_setup.c
new file mode 100644
index 0000000..8e48293
--- /dev/null
+++ b/plat/arm/common/trp/arm_trp_setup.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+static console_t arm_trp_runtime_console;
+
+void arm_trp_early_platform_setup(void)
+{
+ /*
+ * Initialize a different console than already in use to display
+ * messages from trp
+ */
+ int rc = console_pl011_register(PLAT_ARM_TRP_UART_BASE,
+ PLAT_ARM_TRP_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE,
+ &arm_trp_runtime_console);
+ if (rc == 0) {
+ panic();
+ }
+
+ console_set_scope(&arm_trp_runtime_console,
+ CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+}
+
+void trp_early_platform_setup(void)
+{
+ arm_trp_early_platform_setup();
+}
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index 1c6d68b..bcf9f89 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -27,9 +27,6 @@
#pragma weak bl1_plat_fwu_done
#pragma weak bl1_plat_handle_pre_image_load
#pragma weak bl1_plat_handle_post_image_load
-#if MEASURED_BOOT
-#pragma weak bl1_plat_set_bl2_hash
-#endif
unsigned int bl1_plat_get_next_image_id(void)
{
@@ -118,12 +115,3 @@
(void *) bl2_secram_layout);
return 0;
}
-
-#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)
-{
-}
-#endif
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 9550452..c3f78c5 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -76,6 +76,7 @@
ifdef WTP
+# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
$(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist"))
$(if $(shell git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid A3700-utils-marvell git repository"))
@@ -143,6 +144,7 @@
CRYPTOPP_INCDIR ?= $(CRYPTOPP_PATH)
$(TBB): FORCE
+ # Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
$(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory"))
$(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory"))
$(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist"))
@@ -159,6 +161,7 @@
$(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin
$(TIMDDRTOOL): FORCE
+ # Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
$(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c b/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c
new file mode 100644
index 0000000..68d335b
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2021 Sartura Ltd.
+ * Copyright (C) 2021 Globalscale technologies, Inc.
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mv_ddr_if.h>
+#include <plat_marvell.h>
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+}
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+#if DDR_TOPOLOGY == 0
+static struct mv_ddr_topology_map board_topology_map_2g = {
+/* 1CS 4Gb x4 devices of Samsung K4A4G085WF */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400R, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_4GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ BUS_MASK_32BIT, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+#endif
+
+#if DDR_TOPOLOGY == 1
+static struct mv_ddr_topology_map board_topology_map_4g = {
+/* 1CS 8Gb x4 devices of Samsung K4A8G085WC-BCTD */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400R, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ BUS_MASK_32BIT, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+#endif
+
+#if DDR_TOPOLOGY == 2
+static struct mv_ddr_topology_map board_topology_map_8g = {
+/* 2CS 8Gb x8 devices of Micron MT40A1G8WE-083E IT */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400R, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ BUS_MASK_32BIT, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+#endif
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+/* a70x0_mochabin board supports 3 DDR4 models (2G/1CS, 4G/1CS, 8G/2CS) */
+#if DDR_TOPOLOGY == 0
+ return &board_topology_map_2g;
+#elif DDR_TOPOLOGY == 1
+ return &board_topology_map_4g;
+#elif DDR_TOPOLOGY == 2
+ return &board_topology_map_8g;
+#else
+ #error "Unknown DDR topology"
+#endif
+}
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c
new file mode 100644
index 0000000..1ed6323
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 Sartura Ltd.
+ * Copyright (C) 2021 Globalscale technologies, Inc.
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP0 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win,
+ uint32_t *size, uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO_WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#ifndef IMAGE_BLE
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map[] = {
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ {0x00000000c0000000, 0x30000000, PEX2_TID},
+ {0x0000000800000000, 0x100000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = iob_memory_map;
+ *size = ARRAY_SIZE(iob_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = { /* IO window */
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID},
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+#if PLAT_RECOVERY_IMAGE_ENABLE
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* No recovery button on a70x0_mochabin board */
+ return NULL;
+}
+#endif
+#endif
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h b/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h
new file mode 100644
index 0000000..ab76c31
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 Sartura Ltd.
+ * Copyright (C) 2021 Globalscale technologies, Inc.
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __PHY_PORTING_LAYER_H
+#define __PHY_PORTING_LAYER_H
+
+#define MAX_LANE_NR 6
+
+static const struct xfi_params
+ xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 */
+ { 0 }, /* Comphy1 */
+ { 0 }, /* Comphy2 */
+ { 0 }, /* Comphy3 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, .align90 = 0x60,
+ .g1_dfe_res = 0x1, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+ },
+};
+
+static const struct sata_params
+ sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 */
+ { 0 }, /* Comphy1 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy2 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy3 */
+ { 0 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+ },
+};
+
+static const struct usb_params
+ usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT
+ },
+};
+
+#endif /* __PHY_PORTING_LAYER_H */
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h b/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h
new file mode 100644
index 0000000..768f735
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 1 /* A70x0 has single CP0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk b/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk
new file mode 100644
index 0000000..2495591
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2021 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index 30e6280..4d8a87f 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -75,6 +75,10 @@
# This define specifies DDR type for BLE
$(eval $(call add_define,CONFIG_DDR4))
+# This define specifies DDR topology for BLE
+DDR_TOPOLOGY ?= 0
+$(eval $(call add_define,DDR_TOPOLOGY))
+
MARVELL_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v2/gicv2_main.c \
drivers/arm/gic/v2/gicv2_helpers.c \
@@ -166,7 +170,7 @@
BLE_PATH ?= $(PLAT_COMMON_BASE)/ble
include ${BLE_PATH}/ble.mk
-$(eval $(call MAKE_BL,e))
+$(eval $(call MAKE_BL,ble))
clean realclean distclean: mrvl_clean
diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
index 87e2ce0..e41ab3e 100644
--- a/plat/marvell/armada/a8k/common/ble/ble.mk
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
@@ -28,6 +28,7 @@
$(BLE_OBJS): $(MV_DDR_LIB)
$(MV_DDR_LIB): FORCE
+ # Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
$(if $(value MV_DDR_PATH),,$(error "Platform '$(PLAT)' for BLE requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
diff --git a/plat/mediatek/common/mtk_cirq.c b/plat/mediatek/common/mtk_cirq.c
index de37986..9cf7144 100644
--- a/plat/mediatek/common/mtk_cirq.c
+++ b/plat/mediatek/common/mtk_cirq.c
@@ -541,11 +541,9 @@
void mt_cirq_sw_reset(void)
{
-#ifdef CIRQ_NEED_SW_RESET
uint32_t st;
st = mmio_read_32(CIRQ_CON);
st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
mmio_write_32(CIRQ_CON, st);
-#endif
}
diff --git a/plat/mediatek/mt8183/drivers/sspm/sspm.c b/plat/mediatek/mt8183/drivers/sspm/sspm.c
index 3917638..6e76124 100644
--- a/plat/mediatek/mt8183/drivers/sspm/sspm.c
+++ b/plat/mediatek/mt8183/drivers/sspm/sspm.c
@@ -149,7 +149,7 @@
while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
&ipi_data,
- sizeof(ipi_data))
+ sizeof(ipi_data) / sizeof(uint32_t))
&& count) {
mdelay(100);
count--;
diff --git a/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..c083318
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+ uint64_t cache_dump)
+{
+ mmio_write_32(MTK_WDT_LATCH_CTL2, MTK_WDT_LATCH_CTL2_VAL);
+ mmio_write_32(MTK_WDT_INTERVAL, MTK_WDT_INTERVAL_VAL);
+ mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_VAL);
+ mmio_write_32(MTK_DRM_LATCH_CTL1, MTK_DRM_LATCH_CTL1_VAL);
+
+ /* Bit[2] = 0 (default=1), disable dfd apb bus protect_en */
+ mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 0x1 << 2);
+
+ /* Bit[0] : enable?mcusys_vproc?external_off?dfd?trigger -> 1 */
+ mmio_setbits_32(DFD_V50_GROUP_0_63_DIFF, 0x1);
+
+ /* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */
+ /* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */
+ sync_writel(DFD_INTERNAL_CTL, 0x5);
+
+ /* bit[13]: xreset_b_update_disable */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13);
+
+ /*
+ * bit[10:3]: DFD trigger selection mask
+ * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger)
+ * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger)
+ * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger)
+ * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger)
+ * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger)
+ */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1F << 3);
+
+ /*
+ * bit[9] : rg_rw_dfd_trigger_sel[6] = 1(cpu_eb_sw_dfd_trigger)
+ * bit[10] : rg_rw_dfd_trigger_sel[7] = 1(cpu_eb_wdt_dfd_trigger)
+ */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 9);
+
+ /* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+ /*
+ * bit[0]: rg_rw_dfd_auto_power_on = 1
+ * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us)
+ * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us)
+ */
+ mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+
+ /* longest scan chain length */
+ mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+
+ /* bit[1:0]: rg_rw_dfd_shift_clock_ratio */
+ mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+
+ /* rg_dfd_test_so_over_64 */
+ mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+ /* DFD3.0 */
+ mmio_write_32(DFD_TEST_SI_0, 0x0);
+ mmio_write_32(DFD_TEST_SI_1, 0x0);
+ mmio_write_32(DFD_TEST_SI_2, 0x0);
+ mmio_write_32(DFD_TEST_SI_3, 0x0);
+
+ /* for iLDO feature */
+ sync_writel(DFD_POWER_CTL, 0xF9);
+
+ /* read offset */
+ sync_writel(DFD_READ_ADDR, DFD_READ_ADDR_VAL);
+
+ /* for DFD-3.0 setup */
+ sync_writel(DFD_V30_CTL, 0xD);
+
+ /* set base address */
+ mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+ mmio_write_32(DFD_O_REG_0, 0);
+
+ /* setup global variables for suspend and resume */
+ dfd_enabled = true;
+ dfd_base_addr = base_addr;
+ dfd_chain_length = chain_length;
+ dfd_cache_dump = cache_dump;
+
+ if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+ mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_CACHE_VAL);
+ sync_writel(DFD_V35_ENABLE, 0x1);
+ sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+ sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+ sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+ /* Cache dump only mode */
+ sync_writel(DFD_V35_CTL, 0x1);
+ mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 0xF);
+ mmio_write_32(DFD_CHAIN_LENGTH0, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH1, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH2, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH3, DFD_CHAIN_LENGTH_VAL);
+
+ if ((cache_dump & DFD_PARITY_ERR_TRIGGER) != 0UL) {
+ sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+ }
+ }
+ dsbsy();
+}
+
+void dfd_resume(void)
+{
+ if (dfd_enabled == true) {
+ dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+ }
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3)
+{
+ uint64_t ret = 0L;
+
+ switch (arg0) {
+ case PLAT_MTK_DFD_SETUP_MAGIC:
+ INFO("[%s] DFD setup call from kernel\n", __func__);
+ dfd_setup(arg1, arg2, arg3);
+ break;
+ case PLAT_MTK_DFD_READ_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+ }
+ break;
+ case PLAT_MTK_DFD_WRITE_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ sync_writel(MISC1_CFG_BASE + arg1, arg2);
+ }
+ break;
+ default:
+ ret = MTK_SIP_E_INVALID_PARAM;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..2a7e979
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \
+ dsbsy(); \
+ } while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC (0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152)
+
+#define MTK_DRM_LATCH_CTL1 (DRM_BASE + 0x40)
+#define MTK_DRM_LATCH_CTL2 (DRM_BASE + 0x44)
+
+#define MTK_WDT_BASE (RGU_BASE)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x10)
+#define MTK_WDT_LATCH_CTL2 (MTK_WDT_BASE + 0x48)
+
+#define MCU_BIU_BASE (MCUCFG_BASE)
+#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34)
+#define DFD_INTERNAL_SW_NS_TRIGGER (MISC1_CFG_BASE + 0x3c)
+#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC)
+#define DFD_READ_ADDR (MISC1_CFG_BASE + 0x1E8)
+#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENABLE (MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4)
+#define DFD_V50_GROUP_0_63_DIFF (MCU_BIU_BASE + 0xE2AC)
+
+#define DFD_O_PROTECT_EN_REG (0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG (0x10043000)
+#define DFD_O_REG_0 (0x10001390)
+
+#define DFD_CACHE_DUMP_ENABLE 1U
+#define DFD_PARITY_ERR_TRIGGER 2U
+
+#define DFD_V35_TAP_EN_VAL (0x43FF)
+#define DFD_V35_SEQ0_0_VAL (0x63668820)
+#define DFD_READ_ADDR_VAL (0x40000008)
+#define DFD_CHAIN_LENGTH_VAL (0xFFFFFFFF)
+
+#define MTK_WDT_LATCH_CTL2_VAL (0x9507FFFF)
+#define MTK_WDT_INTERVAL_VAL (0x6600000A)
+#define MTK_DRM_LATCH_CTL2_VAL (0x950600C8)
+#define MTK_DRM_LATCH_CTL2_CACHE_VAL (0x95065DC0)
+
+#define MTK_DRM_LATCH_CTL1_VAL (0x95000013)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8195/include/plat_sip_calls.h b/plat/mediatek/mt8195/include/plat_sip_calls.h
index 181aec0..ce25c6f 100644
--- a/plat/mediatek/mt8195/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8195/include/plat_sip_calls.h
@@ -10,7 +10,11 @@
/*******************************************************************************
* Plat SiP function constants
******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS 2
+#define MTK_PLAT_SIP_NUM_CALLS 4
+
+/* DFD */
+#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205
+#define MTK_SIP_KERNEL_DFD_AARCH64 0xC2000205
/* DP/eDP */
#define MTK_SIP_DP_CONTROL_AARCH32 0x82000523
diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h
index 44de8eb..68301d6 100644
--- a/plat/mediatek/mt8195/include/platform_def.h
+++ b/plat/mediatek/mt8195/include/platform_def.h
@@ -24,7 +24,9 @@
#define TOPCKGEN_BASE (IO_PHYS + 0x00000000)
#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
#define SPM_BASE (IO_PHYS + 0x00006000)
+#define RGU_BASE (IO_PHYS + 0x00007000)
#define APMIXEDSYS (IO_PHYS + 0x0000C000)
+#define DRM_BASE (IO_PHYS + 0x0000D000)
#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000)
#define PERICFG_AO_BASE (IO_PHYS + 0x01003000)
#define VPPSYS0_BASE (IO_PHYS + 0x04000000)
diff --git a/plat/mediatek/mt8195/plat_pm.c b/plat/mediatek/mt8195/plat_pm.c
index 2beeb02..b77ab27 100644
--- a/plat/mediatek/mt8195/plat_pm.c
+++ b/plat/mediatek/mt8195/plat_pm.c
@@ -17,6 +17,7 @@
#include <mtk_ptp3_common.h>
#include <mtspmc.h>
#include <plat/common/platform.h>
+#include <plat_dfd.h>
#include <plat_mtk_lpm.h>
#include <plat_params.h>
#include <plat_pm.h>
@@ -166,6 +167,8 @@
mt_gic_distif_restore();
gic_sgi_restore_all();
+ dfd_resume();
+
plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
}
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
index ee36898..ddc7502 100644
--- a/plat/mediatek/mt8195/plat_sip_calls.c
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -10,6 +10,7 @@
#include <mt_spm.h>
#include <mt_spm_vcorefs.h>
#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
#include "plat_sip_calls.h"
uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
@@ -35,6 +36,11 @@
ret = spm_vcorefs_v2_args(x1, x2, x3, &x4);
SMC_RET2(handle, ret, x4);
break;
+ case MTK_SIP_KERNEL_DFD_AARCH32:
+ case MTK_SIP_KERNEL_DFD_AARCH64:
+ ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+ SMC_RET1(handle, ret);
+ break;
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
index 48a2f72..ef7ff81 100644
--- a/plat/mediatek/mt8195/platform.mk
+++ b/plat/mediatek/mt8195/platform.mk
@@ -15,6 +15,7 @@
-I${MTK_PLAT}/common/drivers/uart/ \
-I${MTK_PLAT}/common/lpm/ \
-I${MTK_PLAT_SOC}/drivers/dcm \
+ -I${MTK_PLAT_SOC}/drivers/dfd \
-I${MTK_PLAT_SOC}/drivers/dp/ \
-I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
-I${MTK_PLAT_SOC}/drivers/gpio/ \
@@ -60,6 +61,7 @@
${MTK_PLAT_SOC}/bl31_plat_setup.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
+ ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \
${MTK_PLAT_SOC}/drivers/dp/mt_dp.c \
${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
diff --git a/plat/qemu/common/qemu_pm.c b/plat/qemu/common/qemu_pm.c
index c4ffcf9..c2b5091 100644
--- a/plat/qemu/common/qemu_pm.c
+++ b/plat/qemu/common/qemu_pm.c
@@ -208,8 +208,8 @@
#ifdef SECURE_GPIO_BASE
ERROR("QEMU System Power off: with GPIO.\n");
gpio_set_direction(SECURE_GPIO_POWEROFF, GPIO_DIR_OUT);
- gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_HIGH);
gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_LOW);
+ gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_HIGH);
#else
semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0);
ERROR("QEMU System Off: semihosting call unexpectedly returned.\n");
@@ -222,8 +222,8 @@
ERROR("QEMU System Reset: with GPIO.\n");
#ifdef SECURE_GPIO_BASE
gpio_set_direction(SECURE_GPIO_RESET, GPIO_DIR_OUT);
- gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_HIGH);
gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_HIGH);
#else
ERROR("QEMU System Reset: operation not handled.\n");
#endif
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 1c2c9f0..28463f1 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -323,7 +323,7 @@
-c plat/st/stm32mp1/stm32mp1.S -o $@
endif
-$(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,2))
+$(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,bl2))
tf-a-%.elf: stm32mp1-%.o ${STM32_TF_LINKERFILE}
@echo " LDS $<"
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 37bfc62..1d4423c 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,9 +11,19 @@
#include <lib/cpus/wa_cve_2018_3639.h>
#include <lib/smccc.h>
#include <services/arm_arch_svc.h>
+#include <services/rmi_svc.h>
+#include <services/rmmd_svc.h>
#include <smccc_helpers.h>
#include <plat/common/platform.h>
+#if ENABLE_RME
+/* Setup Arm architecture Services */
+static int32_t arm_arch_svc_setup(void)
+{
+ return rmmd_setup();
+}
+#endif
+
static int32_t smccc_version(void)
{
return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
@@ -133,6 +143,16 @@
SMC_RET0(handle);
#endif
default:
+#if ENABLE_RME
+ /*
+ * RMI functions are allocated from the Arch service range. Call
+ * the RMM dispatcher to handle RMI calls.
+ */
+ if (is_rmi_fid(smc_fid)) {
+ return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+#endif
WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
smc_fid);
SMC_RET1(handle, SMC_UNK);
@@ -145,6 +165,10 @@
OEN_ARM_START,
OEN_ARM_END,
SMC_TYPE_FAST,
+#if ENABLE_RME
+ arm_arch_svc_setup,
+#else
NULL,
+#endif
arm_arch_svc_smc_handler
);
diff --git a/services/std_svc/rmmd/aarch64/rmmd_helpers.S b/services/std_svc/rmmd/aarch64/rmmd_helpers.S
new file mode 100644
index 0000000..6229baf
--- /dev/null
+++ b/services/std_svc/rmmd/aarch64/rmmd_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../rmmd_private.h"
+#include <asm_macros.S>
+
+ .global rmmd_rmm_enter
+ .global rmmd_rmm_exit
+
+ /* ---------------------------------------------------------------------
+ * This function is called with SP_EL0 as stack. Here we stash our EL3
+ * callee-saved registers on to the stack as a part of saving the C
+ * runtime and enter the secure payload.
+ * 'x0' contains a pointer to the memory where the address of the C
+ * runtime context is to be saved.
+ * ---------------------------------------------------------------------
+ */
+func rmmd_rmm_enter
+ /* Make space for the registers that we're going to save */
+ mov x3, sp
+ str x3, [x0, #0]
+ sub sp, sp, #RMMD_C_RT_CTX_SIZE
+
+ /* Save callee-saved registers on to the stack */
+ stp x19, x20, [sp, #RMMD_C_RT_CTX_X19]
+ stp x21, x22, [sp, #RMMD_C_RT_CTX_X21]
+ stp x23, x24, [sp, #RMMD_C_RT_CTX_X23]
+ stp x25, x26, [sp, #RMMD_C_RT_CTX_X25]
+ stp x27, x28, [sp, #RMMD_C_RT_CTX_X27]
+ stp x29, x30, [sp, #RMMD_C_RT_CTX_X29]
+
+ /* ---------------------------------------------------------------------
+ * Everything is setup now. el3_exit() will use the secure context to
+ * restore to the general purpose and EL3 system registers to ERET
+ * into the secure payload.
+ * ---------------------------------------------------------------------
+ */
+ b el3_exit
+endfunc rmmd_rmm_enter
+
+ /* ---------------------------------------------------------------------
+ * This function is called with 'x0' pointing to a C runtime context.
+ * It restores the saved registers and jumps to that runtime with 'x0'
+ * as the new SP register. This destroys the C runtime context that had
+ * been built on the stack below the saved context by the caller. Later
+ * the second parameter 'x1' is passed as a return value to the caller.
+ * ---------------------------------------------------------------------
+ */
+func rmmd_rmm_exit
+ /* Restore the previous stack */
+ mov sp, x0
+
+ /* Restore callee-saved registers on to the stack */
+ ldp x19, x20, [x0, #(RMMD_C_RT_CTX_X19 - RMMD_C_RT_CTX_SIZE)]
+ ldp x21, x22, [x0, #(RMMD_C_RT_CTX_X21 - RMMD_C_RT_CTX_SIZE)]
+ ldp x23, x24, [x0, #(RMMD_C_RT_CTX_X23 - RMMD_C_RT_CTX_SIZE)]
+ ldp x25, x26, [x0, #(RMMD_C_RT_CTX_X25 - RMMD_C_RT_CTX_SIZE)]
+ ldp x27, x28, [x0, #(RMMD_C_RT_CTX_X27 - RMMD_C_RT_CTX_SIZE)]
+ ldp x29, x30, [x0, #(RMMD_C_RT_CTX_X29 - RMMD_C_RT_CTX_SIZE)]
+
+ /* ---------------------------------------------------------------------
+ * This should take us back to the instruction after the call to the
+ * last rmmd_rmm_enter().* Place the second parameter to x0
+ * so that the caller will see it as a return value from the original
+ * entry call.
+ * ---------------------------------------------------------------------
+ */
+ mov x0, x1
+ ret
+endfunc rmmd_rmm_exit
diff --git a/services/std_svc/rmmd/rmmd.mk b/services/std_svc/rmmd/rmmd.mk
new file mode 100644
index 0000000..bac0a9f
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifneq (${ARCH},aarch64)
+ $(error "Error: RMMD is only supported on aarch64.")
+endif
+
+include services/std_svc/rmmd/trp/trp.mk
+
+RMMD_SOURCES += $(addprefix services/std_svc/rmmd/, \
+ ${ARCH}/rmmd_helpers.S \
+ rmmd_main.c)
+
+# Let the top-level Makefile know that we intend to include RMM image
+NEED_RMM := yes
diff --git a/services/std_svc/rmmd/rmmd_initial_context.h b/services/std_svc/rmmd/rmmd_initial_context.h
new file mode 100644
index 0000000..d7a743d
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_initial_context.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_INITIAL_CONTEXT_H
+#define RMMD_INITIAL_CONTEXT_H
+
+#include <arch.h>
+
+/*
+ * SPSR_EL2
+ * M=0x9 (0b1001 EL2h)
+ * M[4]=0
+ * DAIF=0xF Exceptions masked on entry.
+ * BTYPE=0 BTI not yet supported.
+ * SSBS=0 Not yet supported.
+ * IL=0 Not an illegal exception return.
+ * SS=0 Not single stepping.
+ * PAN=1 RMM shouldn't access realm memory.
+ * UAO=0
+ * DIT=0
+ * TCO=0
+ * NZCV=0
+ */
+#define REALM_SPSR_EL2 ( \
+ SPSR_M_EL2H | \
+ (0xF << SPSR_DAIF_SHIFT) | \
+ SPSR_PAN_BIT \
+ )
+
+#endif /* RMMD_INITIAL_CONTEXT_H */
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
new file mode 100644
index 0000000..dacd150
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <arch_features.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/el3_runtime/pubsub.h>
+#include <lib/gpt_rme/gpt_rme.h>
+
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <services/gtsi_svc.h>
+#include <services/rmi_svc.h>
+#include <services/rmmd_svc.h>
+#include <smccc_helpers.h>
+#include "rmmd_initial_context.h"
+#include "rmmd_private.h"
+
+/*******************************************************************************
+ * RMM context information.
+ ******************************************************************************/
+rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * RMM entry point information. Discovered on the primary core and reused
+ * on secondary cores.
+ ******************************************************************************/
+static entry_point_info_t *rmm_ep_info;
+
+/*******************************************************************************
+ * Static function declaration.
+ ******************************************************************************/
+static int32_t rmm_init(void);
+static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
+ uint32_t dst_sec_state, uint64_t x1,
+ uint64_t x2, uint64_t x3, uint64_t x4,
+ void *handle);
+
+/*******************************************************************************
+ * This function takes an RMM context pointer and performs a synchronous entry
+ * into it.
+ ******************************************************************************/
+uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *rmm_ctx)
+{
+ uint64_t rc;
+
+ assert(rmm_ctx != NULL);
+
+ cm_set_context(&(rmm_ctx->cpu_ctx), REALM);
+
+ /* Save the current el1/el2 context before loading realm context. */
+ cm_el1_sysregs_context_save(NON_SECURE);
+ cm_el2_sysregs_context_save(NON_SECURE);
+
+ /* Restore the realm context assigned above */
+ cm_el1_sysregs_context_restore(REALM);
+ cm_el2_sysregs_context_restore(REALM);
+ cm_set_next_eret_context(REALM);
+
+ /* Enter RMM */
+ rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx);
+
+ /* Save realm context */
+ cm_el1_sysregs_context_save(REALM);
+ cm_el2_sysregs_context_save(REALM);
+
+ /* Restore the el1/el2 context again. */
+ cm_el1_sysregs_context_restore(NON_SECURE);
+ cm_el2_sysregs_context_restore(NON_SECURE);
+
+ return rc;
+}
+
+/*******************************************************************************
+ * This function returns to the place where rmmd_rmm_sync_entry() was
+ * called originally.
+ ******************************************************************************/
+__dead2 void rmmd_rmm_sync_exit(uint64_t rc)
+{
+ rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
+
+ /* Get context of the RMM in use by this CPU. */
+ assert(cm_get_context(REALM) == &(ctx->cpu_ctx));
+
+ /*
+ * The RMMD must have initiated the original request through a
+ * synchronous entry into RMM. Jump back to the original C runtime
+ * context with the value of rc in x0;
+ */
+ rmmd_rmm_exit(ctx->c_rt_ctx, rc);
+
+ panic();
+}
+
+static void rmm_el2_context_init(el2_sysregs_t *regs)
+{
+ regs->ctx_regs[CTX_SPSR_EL2 >> 3] = REALM_SPSR_EL2;
+ regs->ctx_regs[CTX_SCTLR_EL2 >> 3] = SCTLR_EL2_RES1;
+}
+
+/*******************************************************************************
+ * Jump to the RMM for the first time.
+ ******************************************************************************/
+static int32_t rmm_init(void)
+{
+
+ uint64_t rc;
+
+ rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
+
+ INFO("RMM init start.\n");
+ ctx->state = RMM_STATE_RESET;
+
+ /* Initialize RMM EL2 context. */
+ rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
+
+ rc = rmmd_rmm_sync_entry(ctx);
+ if (rc != 0ULL) {
+ ERROR("RMM initialisation failed 0x%llx\n", rc);
+ panic();
+ }
+
+ ctx->state = RMM_STATE_IDLE;
+ INFO("RMM init end.\n");
+
+ return 1;
+}
+
+/*******************************************************************************
+ * Load and read RMM manifest, setup RMM.
+ ******************************************************************************/
+int rmmd_setup(void)
+{
+ uint32_t ep_attr;
+ unsigned int linear_id = plat_my_core_pos();
+ rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id];
+
+ /* Make sure RME is supported. */
+ assert(get_armv9_2_feat_rme_support() != 0U);
+
+ rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM);
+ if (rmm_ep_info == NULL) {
+ WARN("No RMM image provided by BL2 boot loader, Booting "
+ "device without RMM initialization. SMCs destined for "
+ "RMM will return SMC_UNK\n");
+ return -ENOENT;
+ }
+
+ /* Under no circumstances will this parameter be 0 */
+ assert(rmm_ep_info->pc == RMM_BASE);
+
+ /* Initialise an entrypoint to set up the CPU context */
+ ep_attr = EP_REALM;
+ if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) {
+ ep_attr |= EP_EE_BIG;
+ }
+
+ SET_PARAM_HEAD(rmm_ep_info, PARAM_EP, VERSION_1, ep_attr);
+ rmm_ep_info->spsr = SPSR_64(MODE_EL2,
+ MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+
+ /* Initialise RMM context with this entry point information */
+ cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info);
+
+ INFO("RMM setup done.\n");
+
+ /* Register init function for deferred init. */
+ bl31_register_rmm_init(&rmm_init);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Forward SMC to the other security state
+ ******************************************************************************/
+static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
+ uint32_t dst_sec_state, uint64_t x1,
+ uint64_t x2, uint64_t x3, uint64_t x4,
+ void *handle)
+{
+ /* Save incoming security state */
+ cm_el1_sysregs_context_save(src_sec_state);
+ cm_el2_sysregs_context_save(src_sec_state);
+
+ /* Restore outgoing security state */
+ cm_el1_sysregs_context_restore(dst_sec_state);
+ cm_el2_sysregs_context_restore(dst_sec_state);
+ cm_set_next_eret_context(dst_sec_state);
+
+ SMC_RET8(cm_get_context(dst_sec_state), smc_fid, x1, x2, x3, x4,
+ SMC_GET_GP(handle, CTX_GPREG_X5),
+ SMC_GET_GP(handle, CTX_GPREG_X6),
+ SMC_GET_GP(handle, CTX_GPREG_X7));
+}
+
+/*******************************************************************************
+ * This function handles all SMCs in the range reserved for RMI. Each call is
+ * either forwarded to the other security state or handled by the RMM dispatcher
+ ******************************************************************************/
+uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+ uint64_t x3, uint64_t x4, void *cookie,
+ void *handle, uint64_t flags)
+{
+ rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
+ uint32_t src_sec_state;
+
+ /* Determine which security state this SMC originated from */
+ src_sec_state = caller_sec_state(flags);
+
+ /* RMI must not be invoked by the Secure world */
+ if (src_sec_state == SMC_FROM_SECURE) {
+ WARN("RMM: RMI invoked by secure world.\n");
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /*
+ * Forward an RMI call from the Normal world to the Realm world as it
+ * is.
+ */
+ if (src_sec_state == SMC_FROM_NON_SECURE) {
+ VERBOSE("RMM: RMI call from non-secure world.\n");
+ return rmmd_smc_forward(smc_fid, NON_SECURE, REALM,
+ x1, x2, x3, x4, handle);
+ }
+
+ assert(src_sec_state == SMC_FROM_REALM);
+
+ switch (smc_fid) {
+ case RMI_RMM_REQ_COMPLETE:
+ if (ctx->state == RMM_STATE_RESET) {
+ VERBOSE("RMM: running rmmd_rmm_sync_exit\n");
+ rmmd_rmm_sync_exit(x1);
+ }
+
+ return rmmd_smc_forward(x1, REALM, NON_SECURE,
+ x2, x3, x4, 0, handle);
+
+ default:
+ WARN("RMM: Unsupported RMM call 0x%08x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+/*******************************************************************************
+ * This cpu has been turned on. Enter RMM to initialise R-EL2. Entry into RMM
+ * is done after initialising minimal architectural state that guarantees safe
+ * execution.
+ ******************************************************************************/
+static void *rmmd_cpu_on_finish_handler(const void *arg)
+{
+ int32_t rc;
+ uint32_t linear_id = plat_my_core_pos();
+ rmmd_rmm_context_t *ctx = &rmm_context[linear_id];
+
+ ctx->state = RMM_STATE_RESET;
+
+ /* Initialise RMM context with this entry point information */
+ cm_setup_context(&ctx->cpu_ctx, rmm_ep_info);
+
+ /* Initialize RMM EL2 context. */
+ rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
+
+ rc = rmmd_rmm_sync_entry(ctx);
+ if (rc != 0) {
+ ERROR("RMM initialisation failed (%d) on CPU%d\n", rc,
+ linear_id);
+ panic();
+ }
+
+ ctx->state = RMM_STATE_IDLE;
+ return NULL;
+}
+
+/* Subscribe to PSCI CPU on to initialize RMM on secondary */
+SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler);
+
+static int gtsi_transition_granule(uint64_t pa,
+ unsigned int src_sec_state,
+ unsigned int target_pas)
+{
+ int ret;
+
+ ret = gpt_transition_pas(pa, PAGE_SIZE_4KB, src_sec_state, target_pas);
+
+ /* Convert TF-A error codes into GTSI error codes */
+ if (ret == -EINVAL) {
+ ERROR("[GTSI] Transition failed: invalid %s\n", "address");
+ ERROR(" PA: 0x%llx, SRC: %d, PAS: %d\n", pa,
+ src_sec_state, target_pas);
+ ret = GRAN_TRANS_RET_BAD_ADDR;
+ } else if (ret == -EPERM) {
+ ERROR("[GTSI] Transition failed: invalid %s\n", "caller/PAS");
+ ERROR(" PA: 0x%llx, SRC: %d, PAS: %d\n", pa,
+ src_sec_state, target_pas);
+ ret = GRAN_TRANS_RET_BAD_PAS;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * This function handles all SMCs in the range reserved for GTF.
+ ******************************************************************************/
+uint64_t rmmd_gtsi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+ uint64_t x3, uint64_t x4, void *cookie,
+ void *handle, uint64_t flags)
+{
+ uint32_t src_sec_state;
+
+ /* Determine which security state this SMC originated from */
+ src_sec_state = caller_sec_state(flags);
+
+ if (src_sec_state != SMC_FROM_REALM) {
+ WARN("RMM: GTF call originated from secure or normal world\n");
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ switch (smc_fid) {
+ case SMC_ASC_MARK_REALM:
+ SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
+ GPT_GPI_REALM));
+ case SMC_ASC_MARK_NONSECURE:
+ SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
+ GPT_GPI_NS));
+ default:
+ WARN("RMM: Unsupported GTF call 0x%08x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/services/std_svc/rmmd/rmmd_private.h b/services/std_svc/rmmd/rmmd_private.h
new file mode 100644
index 0000000..d170bcd
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_PRIVATE_H
+#define RMMD_PRIVATE_H
+
+#include <context.h>
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve callee-saved registers of the
+ * C runtime context while performing a security state switch.
+ ******************************************************************************/
+#define RMMD_C_RT_CTX_X19 0x0
+#define RMMD_C_RT_CTX_X20 0x8
+#define RMMD_C_RT_CTX_X21 0x10
+#define RMMD_C_RT_CTX_X22 0x18
+#define RMMD_C_RT_CTX_X23 0x20
+#define RMMD_C_RT_CTX_X24 0x28
+#define RMMD_C_RT_CTX_X25 0x30
+#define RMMD_C_RT_CTX_X26 0x38
+#define RMMD_C_RT_CTX_X27 0x40
+#define RMMD_C_RT_CTX_X28 0x48
+#define RMMD_C_RT_CTX_X29 0x50
+#define RMMD_C_RT_CTX_X30 0x58
+
+#define RMMD_C_RT_CTX_SIZE 0x60
+#define RMMD_C_RT_CTX_ENTRIES (RMMD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#include <services/rmi_svc.h>
+
+typedef enum rmm_state {
+ RMM_STATE_RESET = 0,
+ RMM_STATE_IDLE
+} rmm_state_t;
+
+/*
+ * Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of
+ * the RMM at R-EL2.
+ */
+typedef struct rmmd_rmm_context {
+ uint64_t c_rt_ctx;
+ cpu_context_t cpu_ctx;
+ rmm_state_t state;
+} rmmd_rmm_context_t;
+
+/* Functions used to enter/exit the RMM synchronously */
+uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *ctx);
+__dead2 void rmmd_rmm_sync_exit(uint64_t rc);
+
+/* Assembly helpers */
+uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);
+void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret);
+
+/* Reference to PM ops for the RMMD */
+extern const spd_pm_ops_t rmmd_pm;
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* RMMD_PRIVATE_H */
diff --git a/services/std_svc/rmmd/trp/linker.lds b/services/std_svc/rmmd/trp/linker.lds
new file mode 100644
index 0000000..2b7f383
--- /dev/null
+++ b/services/std_svc/rmmd/trp/linker.lds
@@ -0,0 +1,71 @@
+/*
+ * (C) COPYRIGHT 2021 Arm Limited or its affiliates.
+ * ALL RIGHTS RESERVED
+ */
+
+#include <common/bl_common.ld.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+/* Mapped using 4K pages, requires us to align different sections with
+ * different property at the same granularity. */
+PAGE_SIZE_4K = 4096;
+
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(trp_head)
+
+MEMORY {
+ RAM (rwx): ORIGIN = RMM_BASE, LENGTH = RMM_LIMIT - RMM_BASE
+}
+
+
+SECTIONS
+{
+ . = RMM_BASE;
+
+ .text : {
+ *(.head.text)
+ . = ALIGN(8);
+ *(.text*)
+ } >RAM
+
+ . = ALIGN(PAGE_SIZE_4K);
+
+ .rodata : {
+ *(.rodata*)
+ } >RAM
+
+ . = ALIGN(PAGE_SIZE_4K);
+
+ __RW_START__ = . ;
+
+ .data : {
+ *(.data*)
+ } >RAM
+
+ .bss (NOLOAD) : {
+ __BSS_START__ = .;
+ *(.bss*)
+ __BSS_END__ = .;
+ } >RAM
+ __BSS_SIZE__ = SIZEOF(.bss);
+
+
+ STACK_SECTION >RAM
+
+
+ /*
+ * Define a linker symbol to mark the end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
+ __RMM_END__ = .;
+
+
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.note*) }
+}
diff --git a/services/std_svc/rmmd/trp/trp.mk b/services/std_svc/rmmd/trp/trp.mk
new file mode 100644
index 0000000..a4f6e03
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+RMM_SOURCES += services/std_svc/rmmd/trp/trp_entry.S \
+ services/std_svc/rmmd/trp/trp_main.c
+
+RMM_LINKERFILE := services/std_svc/rmmd/trp/linker.lds
+
+# Include the platform-specific TRP Makefile
+# If no platform-specific TRP Makefile exists, it means TRP is not supported
+# on this platform.
+TRP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/trp/trp-${PLAT}.mk)
+ifeq (,${TRP_PLAT_MAKEFILE})
+ $(error TRP is not supported on platform ${PLAT})
+else
+ include ${TRP_PLAT_MAKEFILE}
+endif
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
new file mode 100644
index 0000000..23b48fb
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <services/gtsi_svc.h>
+#include <services/rmi_svc.h>
+#include "trp_private.h"
+
+.global trp_head
+.global trp_smc
+
+.section ".head.text", "ax"
+
+ /* ---------------------------------------------
+ * Populate the params in x0-x7 from the pointer
+ * to the smc args structure in x0.
+ * ---------------------------------------------
+ */
+ .macro restore_args_call_smc
+ ldp x6, x7, [x0, #TRP_ARG6]
+ ldp x4, x5, [x0, #TRP_ARG4]
+ ldp x2, x3, [x0, #TRP_ARG2]
+ ldp x0, x1, [x0, #TRP_ARG0]
+ smc #0
+ .endm
+
+ /* ---------------------------------------------
+ * Entry point for TRP
+ * ---------------------------------------------
+ */
+trp_head:
+ bl plat_set_my_stack
+ bl plat_is_my_cpu_primary
+ cbz x0, trp_secondary_cpu_entry
+
+ /* ---------------------------------------------
+ * Zero out BSS section
+ * ---------------------------------------------
+ */
+ ldr x0, =__BSS_START__
+ ldr x1, =__BSS_SIZE__
+ bl zeromem
+
+ bl trp_setup
+
+ bl trp_main
+trp_secondary_cpu_entry:
+ mov_imm x0, RMI_RMM_REQ_COMPLETE
+ mov x1, xzr
+ smc #0
+ b trp_handler
+
+ /* ---------------------------------------------
+ * Direct SMC call to BL31 service provided by
+ * RMM Dispatcher
+ * ---------------------------------------------
+ */
+func trp_smc
+ restore_args_call_smc
+ ret
+endfunc trp_smc
+
+ /* ---------------------------------------------
+ * RMI call handler
+ * ---------------------------------------------
+ */
+func trp_handler
+ bl trp_rmi_handler
+ restore_args_call_smc
+ b trp_handler
+endfunc trp_handler
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
new file mode 100644
index 0000000..2ab9ecc
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+#include <services/gtsi_svc.h>
+#include <services/rmi_svc.h>
+#include <services/trp/platform_trp.h>
+
+#include <platform_def.h>
+#include "trp_private.h"
+
+/*******************************************************************************
+ * Per cpu data structure to populate parameters for an SMC in C code and use
+ * a pointer to this structure in assembler code to populate x0-x7
+ ******************************************************************************/
+static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * Set the arguments for SMC call
+ ******************************************************************************/
+static trp_args_t *set_smc_args(uint64_t arg0,
+ uint64_t arg1,
+ uint64_t arg2,
+ uint64_t arg3,
+ uint64_t arg4,
+ uint64_t arg5,
+ uint64_t arg6,
+ uint64_t arg7)
+{
+ uint32_t linear_id;
+ trp_args_t *pcpu_smc_args;
+
+ /*
+ * Return to Secure Monitor by raising an SMC. The results of the
+ * service are passed as an arguments to the SMC
+ */
+ linear_id = plat_my_core_pos();
+ pcpu_smc_args = &trp_smc_args[linear_id];
+ write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0);
+ write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1);
+ write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2);
+ write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3);
+ write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4);
+ write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5);
+ write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6);
+ write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7);
+
+ return pcpu_smc_args;
+}
+
+/*******************************************************************************
+ * Setup function for TRP.
+ ******************************************************************************/
+void trp_setup(void)
+{
+ /* Perform early platform-specific setup */
+ trp_early_platform_setup();
+}
+
+/* Main function for TRP */
+void trp_main(void)
+{
+ NOTICE("TRP: %s\n", version_string);
+ NOTICE("TRP: %s\n", build_message);
+ INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
+ INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
+ - RMM_BASE));
+}
+
+/*******************************************************************************
+ * Returning RMI version back to Normal World
+ ******************************************************************************/
+static trp_args_t *trp_ret_rmi_version(void)
+{
+ VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
+ RMI_ABI_VERSION_MINOR);
+ return set_smc_args(RMI_RMM_REQ_COMPLETE, RMI_ABI_VERSION,
+ 0, 0, 0, 0, 0, 0);
+}
+
+/*******************************************************************************
+ * Transitioning granule of NON-SECURE type to REALM type
+ ******************************************************************************/
+static trp_args_t *trp_asc_mark_realm(unsigned long long x1)
+{
+ unsigned long long ret;
+
+ VERBOSE("Delegating granule 0x%llx\n", x1);
+ ret = trp_smc(set_smc_args(SMC_ASC_MARK_REALM, x1, 0, 0, 0, 0, 0, 0));
+
+ if (ret != 0ULL) {
+ ERROR("Granule transition from NON-SECURE type to REALM type "
+ "failed 0x%llx\n", ret);
+ }
+ return set_smc_args(RMI_RMM_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
+}
+
+/*******************************************************************************
+ * Transitioning granule of REALM type to NON-SECURE type
+ ******************************************************************************/
+static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1)
+{
+ unsigned long long ret;
+
+ VERBOSE("Undelegating granule 0x%llx\n", x1);
+ ret = trp_smc(set_smc_args(SMC_ASC_MARK_NONSECURE, x1, 0, 0, 0, 0, 0, 0));
+
+ if (ret != 0ULL) {
+ ERROR("Granule transition from REALM type to NON-SECURE type "
+ "failed 0x%llx\n", ret);
+ }
+ return set_smc_args(RMI_RMM_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
+}
+
+/*******************************************************************************
+ * Main RMI SMC handler function
+ ******************************************************************************/
+trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1)
+{
+ switch (fid) {
+ case RMI_RMM_REQ_VERSION:
+ return trp_ret_rmi_version();
+ case RMI_RMM_GRANULE_DELEGATE:
+ return trp_asc_mark_realm(x1);
+ case RMI_RMM_GRANULE_UNDELEGATE:
+ return trp_asc_mark_nonsecure(x1);
+ default:
+ ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid);
+ }
+ return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0);
+}
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
new file mode 100644
index 0000000..9231390
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRP_PRIVATE_H
+#define TRP_PRIVATE_H
+
+/* Definitions to help the assembler access the SMC/ERET args structure */
+#define TRP_ARGS_SIZE TRP_ARGS_END
+#define TRP_ARG0 0x0
+#define TRP_ARG1 0x8
+#define TRP_ARG2 0x10
+#define TRP_ARG3 0x18
+#define TRP_ARG4 0x20
+#define TRP_ARG5 0x28
+#define TRP_ARG6 0x30
+#define TRP_ARG7 0x38
+#define TRP_ARGS_END 0x40
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/* Data structure to hold SMC arguments */
+typedef struct trp_args {
+ uint64_t regs[TRP_ARGS_END >> 3];
+} __aligned(CACHE_WRITEBACK_GRANULE) trp_args_t;
+
+#define write_trp_arg(args, offset, val) (((args)->regs[offset >> 3]) \
+ = val)
+
+/* Definitions for RMI VERSION */
+#define RMI_ABI_VERSION_MAJOR U(0x0)
+#define RMI_ABI_VERSION_MINOR U(0x0)
+#define RMI_ABI_VERSION ((RMI_ABI_VERSION_MAJOR << 16) | \
+ RMI_ABI_VERSION_MINOR)
+
+/* Helper to issue SMC calls to BL31 */
+uint64_t trp_smc(trp_args_t *);
+
+/* The main function to executed only by Primary CPU */
+void trp_main(void);
+
+/* Setup TRP. Executed only by Primary CPU */
+void trp_setup(void);
+
+#endif /* __ASSEMBLER__ */
+#endif /* TRP_PRIVATE_H */
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 1917d0a..39db429 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -13,7 +13,9 @@
#include <lib/pmf/pmf.h>
#include <lib/psci/psci.h>
#include <lib/runtime_instr.h>
+#include <services/gtsi_svc.h>
#include <services/pci_svc.h>
+#include <services/rmmd_svc.h>
#include <services/sdei.h>
#include <services/spm_mm_svc.h>
#include <services/spmd_svc.h>
@@ -158,6 +160,16 @@
flags);
}
#endif
+#if ENABLE_RME
+ /*
+ * Granule transition service interface functions (GTSI) are allocated
+ * from the Std service range. Call the RMM dispatcher to handle calls.
+ */
+ if (is_gtsi_fid(smc_fid)) {
+ return rmmd_gtsi_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+#endif
#if SMC_PCI_SUPPORT
if (is_pci_fid(smc_fid)) {
diff --git a/tools/fiptool/tbbr_config.c b/tools/fiptool/tbbr_config.c
index c1e5217..4998bb2 100644
--- a/tools/fiptool/tbbr_config.c
+++ b/tools/fiptool/tbbr_config.c
@@ -1,5 +1,5 @@
/*
- * 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
*/
@@ -67,6 +67,11 @@
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
.cmdline_name = "nt-fw"
},
+ {
+ .name = "Realm Monitor Management Firmware",
+ .uuid = UUID_REALM_MONITOR_MGMT_FIRMWARE,
+ .cmdline_name = "rmm-fw"
+ },
/* Dynamic Configs */
{
.name = "FW_CONFIG",