Merge pull request #465 from jcastillo-arm/jc/tbb_mbedtls_2_x
Move up to mbed TLS 2.x
diff --git a/Makefile b/Makefile
index 0c3303f..97fa0ac 100644
--- a/Makefile
+++ b/Makefile
@@ -76,6 +76,8 @@
PSCI_EXTENDED_STATE_ID := 0
# Default FIP file name
FIP_NAME := fip.bin
+# Default FWU_FIP file name
+FWU_FIP_NAME := fwu_fip.bin
# By default, use the -pedantic option in the gcc command line
DISABLE_PEDANTIC := 0
# Flags to generate the Chain of Trust
@@ -95,6 +97,8 @@
# Flag to introduce an infinite loop in BL1 just before it exits into the next
# image. This is meant to help debugging the post-BL2 phase.
SPIN_ON_BL1_EXIT := 0
+# Build PL011 UART driver in minimal generic UART mode
+PL011_GENERIC_UART := 0
################################################################################
@@ -150,6 +154,7 @@
# target 'certificates' to create them all
ifneq (${GENERATE_COT},0)
FIP_DEPS += certificates
+ FWU_FIP_DEPS += fwu_certificates
endif
@@ -195,7 +200,8 @@
lib/stdlib/std.c \
plat/common/aarch64/platform_helpers.S
-INCLUDES += -Iinclude/bl31 \
+INCLUDES += -Iinclude/bl1 \
+ -Iinclude/bl31 \
-Iinclude/bl31/services \
-Iinclude/common \
-Iinclude/drivers \
@@ -320,8 +326,10 @@
# Common cert_create options
ifneq (${CREATE_KEYS},0)
$(eval CRT_ARGS += -n)
+ $(eval FWU_CRT_ARGS += -n)
ifneq (${SAVE_KEYS},0)
$(eval CRT_ARGS += -k)
+ $(eval FWU_CRT_ARGS += -k)
endif
endif
# Include TBBR makefile (unless the platform indicates otherwise)
@@ -365,6 +373,7 @@
$(eval $(call assert_boolean,ERROR_DEPRECATED))
$(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
$(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
+$(eval $(call assert_boolean,PL011_GENERIC_UART))
################################################################################
@@ -393,6 +402,7 @@
ifdef EL3_PAYLOAD_BASE
$(eval $(call add_define,EL3_PAYLOAD_BASE))
endif
+$(eval $(call add_define,PL011_GENERIC_UART))
################################################################################
@@ -409,6 +419,11 @@
include bl2/bl2.mk
endif
+ifdef BL2U_SOURCES
+NEED_BL2U := yes
+include bl2u/bl2u.mk
+endif
+
ifdef BL31_SOURCES
# When booting an EL3 payload, there is no need to compile the BL31 image nor
# put it in the FIP.
@@ -423,7 +438,7 @@
# Build targets
################################################################################
-.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip certtool
+.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool
.SUFFIXES:
all: msg_start
@@ -466,6 +481,12 @@
$(eval $(call FIP_ADD_IMG,BL33,--bl33))
endif
+ifeq (${NEED_BL2U},yes)
+BL2U_PATH := $(if ${BL2U},${BL2U},$(call IMG_BIN,2u))
+$(if ${BL2U}, ,$(eval $(call MAKE_BL,2u)))
+$(eval $(call FWU_FIP_ADD_PAYLOAD,${BL2U_PATH},--bl2u))
+endif
+
locate-checkpatch:
ifndef CHECKPATCH
$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/script/checkpatch.pl")
@@ -524,8 +545,24 @@
@echo "Built $@ successfully"
@echo
+ifneq (${GENERATE_COT},0)
+fwu_certificates: ${FWU_CRT_DEPS} ${CRTTOOL}
+ ${Q}${CRTTOOL} ${FWU_CRT_ARGS}
+ @echo
+ @echo "Built $@ successfully"
+ @echo "FWU certificates can be found in ${BUILD_PLAT}"
+ @echo
+endif
+
+${BUILD_PLAT}/${FWU_FIP_NAME}: ${FWU_FIP_DEPS} ${FIPTOOL}
+ ${Q}${FIPTOOL} --dump ${FWU_FIP_ARGS} $@
+ @echo
+ @echo "Built $@ successfully"
+ @echo
+
fiptool: ${FIPTOOL}
fip: ${BUILD_PLAT}/${FIP_NAME}
+fwu_fip: ${BUILD_PLAT}/${FWU_FIP_NAME}
.PHONY: ${FIPTOOL}
${FIPTOOL}:
@@ -551,10 +588,12 @@
@echo " all Build all individual bootloader binaries"
@echo " bl1 Build the BL1 binary"
@echo " bl2 Build the BL2 binary"
+ @echo " bl2u Build the BL2U binary"
@echo " bl31 Build the BL3-1 binary"
@echo " bl32 Build the BL3-2 binary"
@echo " certificates Build the certificates (requires 'GENERATE_COT=1')"
@echo " fip Build the Firmware Image Package (FIP)"
+ @echo " fwu_fip Build the FWU Firmware Image Package (FIP)"
@echo " checkcodebase Check the coding style of the entire source tree"
@echo " checkpatch Check the coding style on changes in the current"
@echo " branch against BASE_COMMIT (default origin/master)"
diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S
index 83594f2..ce27752 100644
--- a/bl1/aarch64/bl1_entrypoint.S
+++ b/bl1/aarch64/bl1_entrypoint.S
@@ -69,10 +69,14 @@
/* --------------------------------------------------
* Initialize platform and jump to our c-entry point
- * for this type of reset. Panic if it returns
+ * for this type of reset.
* --------------------------------------------------
*/
bl bl1_main
-panic:
- b panic
+
+ /* --------------------------------------------------
+ * Do the transition to next boot image.
+ * --------------------------------------------------
+ */
+ b el3_exit
endfunc bl1_entrypoint
diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S
index 5415d39..9ff6a57 100644
--- a/bl1/aarch64/bl1_exceptions.S
+++ b/bl1/aarch64/bl1_exceptions.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,7 +31,8 @@
#include <arch.h>
#include <asm_macros.S>
#include <bl_common.h>
-#include <runtime_svc.h>
+#include <bl1.h>
+#include <context.h>
.globl bl1_exceptions
@@ -115,10 +116,12 @@
/* Enable the SError interrupt */
msr daifclr, #DAIF_ABT_BIT
+ str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+
/* Expect only SMC exceptions */
- mrs x19, esr_el3
- ubfx x20, x19, #ESR_EC_SHIFT, #ESR_EC_LENGTH
- cmp x20, #EC_AARCH64_SMC
+ mrs x30, esr_el3
+ ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
+ cmp x30, #EC_AARCH64_SMC
b.ne unexpected_sync_exception
b smc_handler64
@@ -179,21 +182,40 @@
func smc_handler64
+
+ /* ----------------------------------------------
+ * Detect if this is a RUN_IMAGE or other SMC.
+ * ----------------------------------------------
+ */
+ mov x30, #BL1_SMC_RUN_IMAGE
+ cmp x30, x0
+ b.ne smc_handler
+
+ /* ------------------------------------------------
+ * Make sure only Secure world reaches here.
+ * ------------------------------------------------
+ */
+ mrs x30, scr_el3
+ tst x30, #SCR_NS_BIT
+ b.ne unexpected_sync_exception
+
+ /* ----------------------------------------------
+ * Handling RUN_IMAGE SMC. First switch back to
+ * SP_EL0 for the C runtime stack.
+ * ----------------------------------------------
+ */
+ ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+ msr spsel, #0
+ mov sp, x30
+
/* ---------------------------------------------------------------------
- * Only a single SMC exception from BL2 to ask BL1 to pass EL3 control
- * to BL31 is expected here. It expects:
- * - X0 with RUN_IMAGE SMC function ID;
- * - X1 with the address of a entry_point_info_t structure describing
- * the BL31 entrypoint.
+ * Pass EL3 control to BL31.
+ * Here it expects X1 with the address of a entry_point_info_t
+ * structure describing the BL31 entrypoint.
* ---------------------------------------------------------------------
*/
- mov x19, x0
mov x20, x1
- mov x0, #RUN_IMAGE
- cmp x19, x0
- b.ne unexpected_sync_exception
-
mov x0, x20
bl bl1_print_bl31_ep_info
@@ -228,3 +250,69 @@
bl plat_report_exception
wfi
b unexpected_sync_exception
+
+ /* -----------------------------------------------------
+ * Save Secure/Normal world context and jump to
+ * BL1 SMC handler.
+ * -----------------------------------------------------
+ */
+smc_handler:
+ /* -----------------------------------------------------
+ * Save the GP registers x0-x29.
+ * TODO: Revisit to store only SMCC specified registers.
+ * -----------------------------------------------------
+ */
+ bl save_gp_registers
+
+ /* -----------------------------------------------------
+ * Populate the parameters for the SMC handler. We
+ * already have x0-x4 in place. x5 will point to a
+ * cookie (not used now). x6 will point to the context
+ * structure (SP_EL3) and x7 will contain flags we need
+ * to pass to the handler.
+ * -----------------------------------------------------
+ */
+ mov x5, xzr
+ mov x6, sp
+
+ /* -----------------------------------------------------
+ * Restore the saved C runtime stack value which will
+ * become the new SP_EL0 i.e. EL3 runtime stack. It was
+ * saved in the 'cpu_context' structure prior to the last
+ * ERET from EL3.
+ * -----------------------------------------------------
+ */
+ ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+
+ /* ---------------------------------------------
+ * Switch back to SP_EL0 for the C runtime stack.
+ * ---------------------------------------------
+ */
+ msr spsel, #0
+ mov sp, x12
+
+ /* -----------------------------------------------------
+ * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there
+ * is a world switch during SMC handling.
+ * -----------------------------------------------------
+ */
+ mrs x16, spsr_el3
+ mrs x17, elr_el3
+ mrs x18, scr_el3
+ stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+ str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+
+ /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
+ bfi x7, x18, #0, #1
+
+ /* -----------------------------------------------------
+ * Go to BL1 SMC handler.
+ * -----------------------------------------------------
+ */
+ bl bl1_smc_handler
+
+ /* -----------------------------------------------------
+ * Do the transition to next BL image.
+ * -----------------------------------------------------
+ */
+ b el3_exit
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index 8e73bef..21e87c7 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -32,6 +32,14 @@
bl1/aarch64/bl1_arch_setup.c \
bl1/aarch64/bl1_entrypoint.S \
bl1/aarch64/bl1_exceptions.S \
- lib/cpus/aarch64/cpu_helpers.S
+ bl1/bl1_context_mgmt.c \
+ common/aarch64/context.S \
+ common/context_mgmt.c \
+ lib/cpus/aarch64/cpu_helpers.S \
+ plat/common/plat_bl1_common.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+BL1_SOURCES += bl1/bl1_fwu.c
+endif
BL1_LINKERFILE := bl1/bl1.ld.S
diff --git a/bl1/bl1_context_mgmt.c b/bl1/bl1_context_mgmt.c
new file mode 100644
index 0000000..6355190
--- /dev/null
+++ b/bl1/bl1_context_mgmt.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <platform.h>
+
+/*
+ * Following array will be used for context management.
+ * There are 2 instances, for the Secure and Non-Secure contexts.
+ */
+static cpu_context_t bl1_cpu_context[2];
+
+/* Following contains the cpu context pointers. */
+static void *bl1_cpu_context_ptr[2];
+
+
+void *cm_get_context(uint32_t security_state)
+{
+ assert(sec_state_is_valid(security_state));
+ return bl1_cpu_context_ptr[security_state];
+}
+
+void cm_set_context(void *context, uint32_t security_state)
+{
+ assert(sec_state_is_valid(security_state));
+ bl1_cpu_context_ptr[security_state] = context;
+}
+
+/*******************************************************************************
+ * This function prepares the context for Secure/Normal world images.
+ * Normal world images are transitioned to EL2(if supported) else EL1.
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+ unsigned int security_state;
+ image_desc_t *image_desc;
+ entry_point_info_t *next_bl_ep;
+
+ /* Get the image descriptor. */
+ image_desc = bl1_plat_get_image_desc(image_id);
+ assert(image_desc);
+
+ /* Get the entry point info. */
+ next_bl_ep = &image_desc->ep_info;
+
+ /* Get the image security state. */
+ security_state = GET_SEC_STATE(next_bl_ep->h.attr);
+
+ /* Setup the Secure/Non-Secure context if not done already. */
+ if (!cm_get_context(security_state))
+ cm_set_context(&bl1_cpu_context[security_state], security_state);
+
+ /* Prepare the SPSR for the next BL image. */
+ if (security_state == SECURE) {
+ next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ } else {
+ /* Use EL2 if supported else use EL1. */
+ if (read_id_aa64pfr0_el1() &
+ (ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) {
+ next_bl_ep->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ } else {
+ next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ }
+ }
+
+ /* Allow platform to make change */
+ bl1_plat_set_ep_info(image_id, next_bl_ep);
+
+ /* Prepare the context for the next BL image. */
+ cm_init_my_context(next_bl_ep);
+ cm_prepare_el3_exit(security_state);
+
+ /* Indicate that image is in execution state. */
+ image_desc->state = IMAGE_STATE_EXECUTED;
+
+ print_entry_point_info(next_bl_ep);
+}
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
new file mode 100644
index 0000000..f8b414e
--- /dev/null
+++ b/bl1/bl1_fwu.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <auth_mod.h>
+#include <bl1.h>
+#include <bl_common.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <smcc_helpers.h>
+#include <string.h>
+#include "bl1_private.h"
+
+/*
+ * Function declarations.
+ */
+static int bl1_fwu_image_copy(unsigned int image_id,
+ uintptr_t image_addr,
+ unsigned int block_size,
+ unsigned int image_size,
+ unsigned int flags);
+static int bl1_fwu_image_auth(unsigned int image_id,
+ uintptr_t image_addr,
+ unsigned int image_size,
+ unsigned int flags);
+static int bl1_fwu_image_execute(unsigned int image_id,
+ void **handle,
+ unsigned int flags);
+static register_t bl1_fwu_image_resume(unsigned int image_id,
+ register_t image_param,
+ void **handle,
+ unsigned int flags);
+static int bl1_fwu_sec_image_done(void **handle,
+ unsigned int flags);
+__dead2 static void bl1_fwu_done(void *cookie, void *reserved);
+
+/*
+ * This keeps track of last executed secure image id.
+ */
+static unsigned int sec_exec_image_id = INVALID_IMAGE_ID;
+
+/*******************************************************************************
+ * Top level handler for servicing FWU SMCs.
+ ******************************************************************************/
+register_t bl1_fwu_smc_handler(unsigned int smc_fid,
+ register_t x1,
+ register_t x2,
+ register_t x3,
+ register_t x4,
+ void *cookie,
+ void *handle,
+ unsigned int flags)
+{
+
+ switch (smc_fid) {
+ case FWU_SMC_IMAGE_COPY:
+ SMC_RET1(handle, bl1_fwu_image_copy(x1, x2, x3, x4, flags));
+
+ case FWU_SMC_IMAGE_AUTH:
+ SMC_RET1(handle, bl1_fwu_image_auth(x1, x2, x3, flags));
+
+ case FWU_SMC_IMAGE_EXECUTE:
+ SMC_RET1(handle, bl1_fwu_image_execute(x1, &handle, flags));
+
+ case FWU_SMC_IMAGE_RESUME:
+ SMC_RET1(handle, bl1_fwu_image_resume(x1, x2, &handle, flags));
+
+ case FWU_SMC_SEC_IMAGE_DONE:
+ SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags));
+
+ case FWU_SMC_UPDATE_DONE:
+ bl1_fwu_done(cookie, NULL);
+ /* We should never return from bl1_fwu_done() */
+
+ default:
+ assert(0);
+ break;
+ }
+
+ SMC_RET0(handle);
+}
+
+/*******************************************************************************
+ * This function is responsible for copying secure images in AP Secure RAM.
+ ******************************************************************************/
+static int bl1_fwu_image_copy(unsigned int image_id,
+ uintptr_t image_src,
+ unsigned int block_size,
+ unsigned int image_size,
+ unsigned int flags)
+{
+ uintptr_t base_addr;
+ meminfo_t *mem_layout;
+
+ /* Get the image descriptor. */
+ image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
+
+ /* Check if we are in correct state. */
+ if ((!image_desc) ||
+ ((image_desc->state != IMAGE_STATE_RESET) &&
+ (image_desc->state != IMAGE_STATE_COPYING))) {
+ WARN("BL1-FWU: Copy not allowed due to invalid state\n");
+ return -EPERM;
+ }
+
+ /* Only Normal world is allowed to copy a Secure image. */
+ if ((GET_SEC_STATE(flags) == SECURE) ||
+ (GET_SEC_STATE(image_desc->ep_info.h.attr) == NON_SECURE)) {
+ WARN("BL1-FWU: Copy not allowed for Non-Secure "
+ "image from Secure-world\n");
+ return -EPERM;
+ }
+
+ if ((!image_src) || (!block_size)) {
+ WARN("BL1-FWU: Copy not allowed due to invalid image source"
+ " or block size\n");
+ return -ENOMEM;
+ }
+
+ /* Get the image base address. */
+ base_addr = image_desc->image_info.image_base;
+
+ if (image_desc->state == IMAGE_STATE_COPYING) {
+ /*
+ * If last block is more than expected then
+ * clip the block to the required image size.
+ */
+ if (image_desc->image_info.copied_size + block_size >
+ image_desc->image_info.image_size) {
+ block_size = image_desc->image_info.image_size -
+ image_desc->image_info.copied_size;
+ WARN("BL1-FWU: Copy argument block_size > remaining image size."
+ " Clipping block_size\n");
+ }
+
+ /* Make sure the image src/size is mapped. */
+ if (bl1_plat_mem_check(image_src, block_size, flags)) {
+ WARN("BL1-FWU: Copy arguments source/size not mapped\n");
+ return -ENOMEM;
+ }
+
+ INFO("BL1-FWU: Continuing image copy in blocks\n");
+
+ /* Copy image for given block size. */
+ base_addr += image_desc->image_info.copied_size;
+ image_desc->image_info.copied_size += block_size;
+ memcpy((void *)base_addr, (const void *)image_src, block_size);
+ flush_dcache_range(base_addr, block_size);
+
+ /* Update the state if last block. */
+ if (image_desc->image_info.copied_size ==
+ image_desc->image_info.image_size) {
+ image_desc->state = IMAGE_STATE_COPIED;
+ INFO("BL1-FWU: Image copy in blocks completed\n");
+ }
+ } else {
+ /* This means image is in RESET state and ready to be copied. */
+ INFO("BL1-FWU: Fresh call to copy an image\n");
+
+ if (!image_size) {
+ WARN("BL1-FWU: Copy not allowed due to invalid image size\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * If block size is more than total size then
+ * assume block size as the total image size.
+ */
+ if (block_size > image_size) {
+ block_size = image_size;
+ WARN("BL1-FWU: Copy argument block_size > image size."
+ " Clipping block_size\n");
+ }
+
+ /* Make sure the image src/size is mapped. */
+ if (bl1_plat_mem_check(image_src, block_size, flags)) {
+ WARN("BL1-FWU: Copy arguments source/size not mapped\n");
+ return -ENOMEM;
+ }
+
+ /* Find out how much free trusted ram remains after BL1 load */
+ mem_layout = bl1_plat_sec_mem_layout();
+ if ((image_desc->image_info.image_base < mem_layout->free_base) ||
+ (image_desc->image_info.image_base + image_size >
+ mem_layout->free_base + mem_layout->free_size)) {
+ WARN("BL1-FWU: Memory not available to copy\n");
+ return -ENOMEM;
+ }
+
+ /* Update the image size. */
+ image_desc->image_info.image_size = image_size;
+
+ /* Copy image for given size. */
+ memcpy((void *)base_addr, (const void *)image_src, block_size);
+ flush_dcache_range(base_addr, block_size);
+
+ /* Update the state. */
+ if (block_size == image_size) {
+ image_desc->state = IMAGE_STATE_COPIED;
+ INFO("BL1-FWU: Image is copied successfully\n");
+ } else {
+ image_desc->state = IMAGE_STATE_COPYING;
+ INFO("BL1-FWU: Started image copy in blocks\n");
+ }
+
+ image_desc->image_info.copied_size = block_size;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function is responsible for authenticating Normal/Secure images.
+ ******************************************************************************/
+static int bl1_fwu_image_auth(unsigned int image_id,
+ uintptr_t image_src,
+ unsigned int image_size,
+ unsigned int flags)
+{
+ int result;
+ uintptr_t base_addr;
+ unsigned int total_size;
+
+ /* Get the image descriptor. */
+ image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
+ if (!image_desc)
+ return -EPERM;
+
+ if (GET_SEC_STATE(flags) == SECURE) {
+ if (image_desc->state != IMAGE_STATE_RESET) {
+ WARN("BL1-FWU: Authentication from secure world "
+ "while in invalid state\n");
+ return -EPERM;
+ }
+ } else {
+ if (GET_SEC_STATE(image_desc->ep_info.h.attr) == SECURE) {
+ if (image_desc->state != IMAGE_STATE_COPIED) {
+ WARN("BL1-FWU: Authentication of secure image "
+ "from non-secure world while not in copied state\n");
+ return -EPERM;
+ }
+ } else {
+ if (image_desc->state != IMAGE_STATE_RESET) {
+ WARN("BL1-FWU: Authentication of non-secure image "
+ "from non-secure world while in invalid state\n");
+ return -EPERM;
+ }
+ }
+ }
+
+ if (image_desc->state == IMAGE_STATE_COPIED) {
+ /*
+ * Image is in COPIED state.
+ * Use the stored address and size.
+ */
+ base_addr = image_desc->image_info.image_base;
+ total_size = image_desc->image_info.image_size;
+ } else {
+ if ((!image_src) || (!image_size)) {
+ WARN("BL1-FWU: Auth not allowed due to invalid"
+ " image source/size\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Image is in RESET state.
+ * Check the parameters and authenticate the source image in place.
+ */
+ if (bl1_plat_mem_check(image_src, image_size, flags)) {
+ WARN("BL1-FWU: Authentication arguments source/size not mapped\n");
+ return -ENOMEM;
+ }
+
+ base_addr = image_src;
+ total_size = image_size;
+
+ /* Update the image size in the descriptor. */
+ image_desc->image_info.image_size = total_size;
+ }
+
+ /*
+ * Authenticate the image.
+ */
+ INFO("BL1-FWU: Authenticating image_id:%d\n", image_id);
+ result = auth_mod_verify_img(image_id, (void *)base_addr, total_size);
+ if (result != 0) {
+ WARN("BL1-FWU: Authentication Failed err=%d\n", result);
+
+ /*
+ * Authentication has failed.
+ * Clear the memory if the image was copied.
+ * This is to prevent an attack where this contains
+ * some malicious code that can somehow be executed later.
+ */
+ if (image_desc->state == IMAGE_STATE_COPIED) {
+ /* Clear the memory.*/
+ memset((void *)base_addr, 0, total_size);
+ flush_dcache_range(base_addr, total_size);
+
+ /* Indicate that image can be copied again*/
+ image_desc->state = IMAGE_STATE_RESET;
+ }
+ return -EAUTH;
+ }
+
+ /* Indicate that image is in authenticated state. */
+ image_desc->state = IMAGE_STATE_AUTHENTICATED;
+
+ /*
+ * Flush image_info to memory so that other
+ * secure world images can see changes.
+ */
+ flush_dcache_range((unsigned long)&image_desc->image_info,
+ sizeof(image_info_t));
+
+ INFO("BL1-FWU: Authentication was successful\n");
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function is responsible for executing Secure images.
+ ******************************************************************************/
+static int bl1_fwu_image_execute(unsigned int image_id,
+ void **handle,
+ unsigned int flags)
+{
+ /* Get the image descriptor. */
+ image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
+
+ /*
+ * Execution is NOT allowed if:
+ * Caller is from Secure world OR
+ * Image is Non-Secure OR
+ * Image is Non-Executable OR
+ * Image is NOT in AUTHENTICATED state.
+ */
+ if ((!image_desc) ||
+ (GET_SEC_STATE(flags) == SECURE) ||
+ (GET_SEC_STATE(image_desc->ep_info.h.attr) == NON_SECURE) ||
+ (GET_EXEC_STATE(image_desc->image_info.h.attr) == NON_EXECUTABLE) ||
+ (image_desc->state != IMAGE_STATE_AUTHENTICATED)) {
+ WARN("BL1-FWU: Execution not allowed due to invalid state/args\n");
+ return -EPERM;
+ }
+
+ INFO("BL1-FWU: Executing Secure image\n");
+
+ /* Save NS-EL1 system registers. */
+ cm_el1_sysregs_context_save(NON_SECURE);
+
+ /* Prepare the image for execution. */
+ bl1_prepare_next_image(image_id);
+
+ /* Update the secure image id. */
+ sec_exec_image_id = image_id;
+
+ *handle = cm_get_context(SECURE);
+ return 0;
+}
+
+/*******************************************************************************
+ * This function is responsible for resuming Secure/Non-Secure images.
+ ******************************************************************************/
+static register_t bl1_fwu_image_resume(unsigned int image_id,
+ register_t image_param,
+ void **handle,
+ unsigned int flags)
+{
+ image_desc_t *image_desc;
+ unsigned int resume_sec_state;
+
+ if (GET_SEC_STATE(flags) == SECURE) {
+ /* Get the image descriptor for last executed secure image id. */
+ image_desc = bl1_plat_get_image_desc(sec_exec_image_id);
+
+ if ((!image_desc) || (image_desc->state != IMAGE_STATE_EXECUTED)) {
+ WARN("BL1-FWU: Resume not allowed for secure image "
+ "due to invalid state\n");
+ return -EPERM;
+ }
+
+ /* Update the flags. */
+ image_desc->state = IMAGE_STATE_INTERRUPTED;
+ resume_sec_state = NON_SECURE;
+ } else {
+ /* Get the image descriptor for image id to be resumed. */
+ image_desc = bl1_plat_get_image_desc(image_id);
+
+ /* Make sure image is secure and was interrupted. */
+ if ((!image_desc) ||
+ (GET_SEC_STATE(image_desc->ep_info.h.attr) == NON_SECURE) ||
+ (image_desc->state != IMAGE_STATE_INTERRUPTED)) {
+ WARN("BL1-FWU: Resume not allowed for NS image/ invalid state\n");
+ return -EPERM;
+ }
+
+ /* Update the flags. */
+ image_desc->state = IMAGE_STATE_EXECUTED;
+ resume_sec_state = SECURE;
+ }
+
+ /* Save the EL1 system registers of calling world. */
+ cm_el1_sysregs_context_save(GET_SEC_STATE(flags));
+
+ /* Restore the EL1 system registers of resuming world. */
+ cm_el1_sysregs_context_restore(resume_sec_state);
+
+ /* Update the next context. */
+ cm_set_next_eret_context(resume_sec_state);
+
+ INFO("BL1-FWU: Resuming %s world context\n",
+ (resume_sec_state == SECURE) ? "Secure" : "Normal");
+
+ *handle = cm_get_context(resume_sec_state);
+ return image_param;
+}
+
+/*******************************************************************************
+ * This function is responsible for resuming normal world context.
+ ******************************************************************************/
+static int bl1_fwu_sec_image_done(void **handle, unsigned int flags)
+{
+
+ /* Get the image descriptor for last executed secure image id. */
+ image_desc_t *image_desc = bl1_plat_get_image_desc(sec_exec_image_id);
+
+ /*
+ * Make sure caller is from secure world
+ * and the image is in EXECUTED state.
+ */
+ if ((!image_desc) ||
+ (GET_SEC_STATE(flags) == NON_SECURE) ||
+ (image_desc->state != IMAGE_STATE_EXECUTED)) {
+ WARN("BL1-FWU: Done not allowed for NS caller/ invalid state\n");
+ return -EPERM;
+ }
+
+ /* Update the flags. */
+ image_desc->state = IMAGE_STATE_RESET;
+ sec_exec_image_id = INVALID_IMAGE_ID;
+
+ /*
+ * Secure world is done so no need to save the context.
+ * Just restore the Non-Secure context.
+ */
+ cm_el1_sysregs_context_restore(NON_SECURE);
+
+ /* Update the next context. */
+ cm_set_next_eret_context(NON_SECURE);
+
+ INFO("BL1-FWU: Resuming Normal world context\n");
+
+ *handle = cm_get_context(NON_SECURE);
+ return 0;
+}
+
+/*******************************************************************************
+ * This function provides the opportunity for users to perform any
+ * platform specific handling after the Firmware update is done.
+ ******************************************************************************/
+__dead2 static void bl1_fwu_done(void *cookie, void *reserved)
+{
+ NOTICE("BL1-FWU: *******FWU Process Completed*******\n");
+
+ /*
+ * Call platform done function.
+ */
+ bl1_plat_fwu_done(cookie, reserved);
+ assert(0);
+}
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index 73f023a..84d5611 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -32,43 +32,22 @@
#include <arch_helpers.h>
#include <assert.h>
#include <auth_mod.h>
+#include <bl1.h>
#include <bl_common.h>
#include <debug.h>
#include <platform.h>
#include <platform_def.h>
+#include <smcc_helpers.h>
#include "bl1_private.h"
+#include <uuid.h>
-/*******************************************************************************
- * Runs BL2 from the given entry point. It results in dropping the
- * exception level
- ******************************************************************************/
-static void __dead2 bl1_run_bl2(entry_point_info_t *bl2_ep)
-{
- /* Check bl2 security state is expected as secure */
- assert(GET_SECURITY_STATE(bl2_ep->h.attr) == SECURE);
- /* Check NS Bit is also set as secure */
- assert(!(read_scr_el3() & SCR_NS_BIT));
-
- bl1_arch_next_el_setup();
+/* BL1 Service UUID */
+DEFINE_SVC_UUID(bl1_svc_uid,
+ 0xfd3967d4, 0x72cb, 0x4d9a, 0xb5, 0x75,
+ 0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a);
- /* Tell next EL what we want done */
- bl2_ep->args.arg0 = RUN_IMAGE;
- write_spsr_el3(bl2_ep->spsr);
- write_elr_el3(bl2_ep->pc);
-
- NOTICE("BL1: Booting BL2\n");
- print_entry_point_info(bl2_ep);
-
- eret(bl2_ep->args.arg0,
- bl2_ep->args.arg1,
- bl2_ep->args.arg2,
- bl2_ep->args.arg3,
- bl2_ep->args.arg4,
- bl2_ep->args.arg5,
- bl2_ep->args.arg6,
- bl2_ep->args.arg7);
-}
+static void bl1_load_bl2(void);
/*******************************************************************************
* The next function has a weak definition. Platform specific code can override
@@ -91,7 +70,8 @@
/* Check that BL1's memory is lying outside of the free memory */
assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) ||
- (BL1_RAM_BASE >= bl1_mem_layout->free_base + bl1_mem_layout->free_size));
+ (BL1_RAM_BASE >= bl1_mem_layout->free_base +
+ bl1_mem_layout->free_size));
/* Remove BL1 RW data from the scope of memory visible to BL2 */
*bl2_mem_layout = *bl1_mem_layout;
@@ -105,13 +85,13 @@
/*******************************************************************************
* Function to perform late architectural and platform specific initialization.
- * It also locates and loads the BL2 raw binary image in the trusted DRAM. Only
- * called by the primary cpu after a cold boot.
- * TODO: Add support for alternative image load mechanism e.g using virtio/elf
- * loader etc.
- ******************************************************************************/
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
void bl1_main(void)
{
+ unsigned int image_id;
+
/* Announce our arrival */
NOTICE(FIRMWARE_WELCOME_STR);
NOTICE("BL1: %s\n", version_string);
@@ -119,11 +99,6 @@
INFO("BL1: RAM 0x%lx - 0x%lx\n", BL1_RAM_BASE, BL1_RAM_LIMIT);
- image_info_t bl2_image_info = { {0} };
- entry_point_info_t bl2_ep = { {0} };
- meminfo_t *bl1_tzram_layout;
- meminfo_t *bl2_tzram_layout = 0x0;
- int err;
#if DEBUG
unsigned long val;
@@ -153,28 +128,65 @@
/* Perform remaining generic architectural setup from EL3 */
bl1_arch_setup();
+#if TRUSTED_BOARD_BOOT
+ /* Initialize authentication module */
+ auth_mod_init();
+#endif /* TRUSTED_BOARD_BOOT */
+
/* Perform platform setup in BL1. */
bl1_platform_setup();
+ /* Get the image id of next image to load and run. */
+ image_id = bl1_plat_get_next_image_id();
+
+ /*
+ * We currently interpret any image id other than
+ * BL2_IMAGE_ID as the start of firmware update.
+ */
+ if (image_id == BL2_IMAGE_ID)
+ bl1_load_bl2();
+ else
+ NOTICE("BL1-FWU: *******FWU Process Started*******\n");
+
+ bl1_prepare_next_image(image_id);
+}
+
+/*******************************************************************************
+ * This function locates and loads the BL2 raw binary image in the trusted SRAM.
+ * Called by the primary cpu after a cold boot.
+ * TODO: Add support for alternative image load mechanism e.g using virtio/elf
+ * loader etc.
+ ******************************************************************************/
+void bl1_load_bl2(void)
+{
+ image_desc_t *image_desc;
+ image_info_t *image_info;
+ entry_point_info_t *ep_info;
+ meminfo_t *bl1_tzram_layout;
+ meminfo_t *bl2_tzram_layout;
+ int err;
+
- SET_PARAM_HEAD(&bl2_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0);
- SET_PARAM_HEAD(&bl2_ep, PARAM_EP, VERSION_1, 0);
+ /* Get the image descriptor */
+ image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(image_desc);
+
+ /* Get the image info */
+ image_info = &image_desc->image_info;
+
+ /* 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();
INFO("BL1: Loading BL2\n");
-#if TRUSTED_BOARD_BOOT
- /* Initialize authentication module */
- auth_mod_init();
-#endif /* TRUSTED_BOARD_BOOT */
-
/* Load the BL2 image */
err = load_auth_image(bl1_tzram_layout,
BL2_IMAGE_ID,
- BL2_BASE,
- &bl2_image_info,
- &bl2_ep);
+ image_info->image_base,
+ image_info,
+ ep_info);
if (err) {
ERROR("Failed to load BL2 firmware.\n");
@@ -191,11 +203,10 @@
bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base;
bl1_init_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout);
- bl1_plat_set_bl2_ep_info(&bl2_image_info, &bl2_ep);
- bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout;
- bl1_run_bl2(&bl2_ep);
-
- return;
+ ep_info->args.arg1 = (unsigned long)bl2_tzram_layout;
+ NOTICE("BL1: Booting BL2\n");
+ VERBOSE("BL1: BL2 memory layout address = 0x%llx\n",
+ (unsigned long long) bl2_tzram_layout);
}
/*******************************************************************************
@@ -216,3 +227,45 @@
NOTICE("BL1: Please connect the debugger to continue\n");
}
#endif
+
+/*******************************************************************************
+ * Top level handler for servicing BL1 SMCs.
+ ******************************************************************************/
+register_t bl1_smc_handler(unsigned int smc_fid,
+ register_t x1,
+ register_t x2,
+ register_t x3,
+ register_t x4,
+ void *cookie,
+ void *handle,
+ unsigned int flags)
+{
+
+#if TRUSTED_BOARD_BOOT
+ /*
+ * Dispatch FWU calls to FWU SMC handler and return its return
+ * value
+ */
+ if (is_fwu_fid(smc_fid)) {
+ return bl1_fwu_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+#endif
+
+ switch (smc_fid) {
+ case BL1_SMC_CALL_COUNT:
+ SMC_RET1(handle, BL1_NUM_SMC_CALLS);
+
+ case BL1_SMC_UID:
+ SMC_UUID_RET(handle, bl1_svc_uid);
+
+ case BL1_SMC_VERSION:
+ SMC_RET1(handle, BL1_SMC_MAJOR_VER | BL1_SMC_MINOR_VER);
+
+ default:
+ break;
+ }
+
+ WARN("Unimplemented BL1 SMC Call: 0x%x \n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h
index 0a8fc45..283bbb9 100644
--- a/bl1/bl1_private.h
+++ b/bl1/bl1_private.h
@@ -31,6 +31,8 @@
#ifndef __BL1_PRIVATE_H__
#define __BL1_PRIVATE_H__
+#include <types.h>
+
/*******************************************************************************
* Declarations of linker defined symbols which will tell us where BL1 lives
* in Trusted RAM
@@ -46,4 +48,14 @@
void bl1_arch_setup(void);
void bl1_arch_next_el_setup(void);
+void bl1_prepare_next_image(unsigned int image_id);
+
+register_t bl1_fwu_smc_handler(unsigned int smc_fid,
+ register_t x1,
+ register_t x2,
+ register_t x3,
+ register_t x4,
+ void *cookie,
+ void *handle,
+ unsigned int flags);
#endif /* __BL1_PRIVATE_H__ */
diff --git a/bl1/tbbr/tbbr_img_desc.c b/bl1/tbbr/tbbr_img_desc.c
new file mode 100644
index 0000000..42de851
--- /dev/null
+++ b/bl1/tbbr/tbbr_img_desc.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl1.h>
+#include <bl_common.h>
+#include <platform_def.h>
+
+image_desc_t bl1_tbbr_image_descs[] = {
+ {
+ .image_id = FWU_CERT_ID,
+ .image_info.h.attr = SET_EXEC_STATE(NON_EXECUTABLE),
+ .image_info.image_base = BL2_BASE,
+ .ep_info.h.attr = SET_SEC_STATE(SECURE),
+ },
+#if NS_BL1U_BASE
+ {
+ .image_id = NS_BL1U_IMAGE_ID,
+ .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),
+ .image_info.image_base = NS_BL1U_BASE,
+ .ep_info.h.attr = SET_SEC_STATE(NON_SECURE),
+ .ep_info.pc = NS_BL1U_BASE,
+ },
+#endif
+#if SCP_BL2U_BASE
+ {
+ .image_id = SCP_BL2U_IMAGE_ID,
+ .image_info.h.attr = SET_EXEC_STATE(NON_EXECUTABLE),
+ .image_info.image_base = SCP_BL2U_BASE,
+ .ep_info.h.attr = SET_SEC_STATE(SECURE),
+ },
+#endif
+#if BL2U_BASE
+ {
+ .image_id = BL2U_IMAGE_ID,
+ .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),
+ .image_info.image_base = BL2U_BASE,
+ .ep_info.h.attr = SET_SEC_STATE(SECURE),
+ .ep_info.pc = BL2U_BASE,
+ },
+#endif
+#if NS_BL2U_BASE
+ {
+ .image_id = NS_BL2U_IMAGE_ID,
+ .image_info.h.attr = SET_EXEC_STATE(NON_EXECUTABLE),
+ .image_info.image_base = NS_BL2U_BASE,
+ .ep_info.h.attr = SET_SEC_STATE(NON_SECURE),
+ },
+#endif
+ BL2_IMAGE_DESC,
+
+ {
+ .image_id = INVALID_IMAGE_ID,
+ }
+};
diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S
index 1d26229..75eb02a 100644
--- a/bl2/aarch64/bl2_entrypoint.S
+++ b/bl2/aarch64/bl2_entrypoint.S
@@ -39,13 +39,12 @@
func bl2_entrypoint
/*---------------------------------------------
- * Store the extents of the tzram available to
- * BL2 for future use. Use the opcode param to
- * allow implement other functions if needed.
+ * Save from x1 the extents of the tzram
+ * available to BL2 for future use.
+ * x0 is not currently used.
* ---------------------------------------------
- */
- mov x20, x0
- mov x21, x1
+ */
+ mov x20, x1
/* ---------------------------------------------
* Set the exception vector to something sane.
@@ -74,14 +73,6 @@
isb
/* ---------------------------------------------
- * Check the opcodes out of paranoia.
- * ---------------------------------------------
- */
- mov x0, #RUN_IMAGE
- cmp x0, x20
- b.ne _panic
-
- /* ---------------------------------------------
* Invalidate the RW memory used by the BL2
* image. This includes the data and NOBITS
* sections. This is done to safeguard against
@@ -126,7 +117,7 @@
* specific early arch. setup e.g. mmu setup
* ---------------------------------------------
*/
- mov x0, x21
+ mov x0, x20
bl bl2_early_platform_setup
bl bl2_plat_arch_setup
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index a3f016f..f475640 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -32,6 +32,7 @@
#include <arch_helpers.h>
#include <assert.h>
#include <auth_mod.h>
+#include <bl1.h>
#include <bl_common.h>
#include <debug.h>
#include <errno.h>
@@ -281,5 +282,5 @@
* the BL3-2 (if present) and BL3-3 software images will be passed to
* BL3-1 as an argument.
*/
- smc(RUN_IMAGE, (unsigned long)bl31_ep_info, 0, 0, 0, 0, 0, 0);
+ smc(BL1_SMC_RUN_IMAGE, (unsigned long)bl31_ep_info, 0, 0, 0, 0, 0, 0);
}
diff --git a/bl2u/aarch64/bl2u_entrypoint.S b/bl2u/aarch64/bl2u_entrypoint.S
new file mode 100644
index 0000000..c9aad81
--- /dev/null
+++ b/bl2u/aarch64/bl2u_entrypoint.S
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+
+
+ .globl bl2u_entrypoint
+
+
+func bl2u_entrypoint
+ /*---------------------------------------------
+ * Store the extents of the tzram available to
+ * BL2U and other platform specific information
+ * for future use. x0 is currently not used.
+ * ---------------------------------------------
+ */
+ mov x20, x1
+ mov x21, x2
+
+ /* ---------------------------------------------
+ * Set the exception vector to something sane.
+ * ---------------------------------------------
+ */
+ adr x0, early_exceptions
+ msr vbar_el1, x0
+ isb
+
+ /* ---------------------------------------------
+ * Enable the SError interrupt now that the
+ * exception vectors have been setup.
+ * ---------------------------------------------
+ */
+ msr daifclr, #DAIF_ABT_BIT
+
+ /* ---------------------------------------------
+ * Enable the instruction cache, stack pointer
+ * and data access alignment checks
+ * ---------------------------------------------
+ */
+ mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
+ mrs x0, sctlr_el1
+ orr x0, x0, x1
+ msr sctlr_el1, x0
+ isb
+
+ /* ---------------------------------------------
+ * Invalidate the RW memory used by the BL2U
+ * image. This includes the data and NOBITS
+ * sections. This is done to safeguard against
+ * possible corruption of this memory by dirty
+ * cache lines in a system cache as a result of
+ * use by an earlier boot loader stage.
+ * ---------------------------------------------
+ */
+ adr x0, __RW_START__
+ adr x1, __RW_END__
+ sub x1, x1, x0
+ bl inv_dcache_range
+
+ /* ---------------------------------------------
+ * Zero out NOBITS sections. There are 2 of them:
+ * - the .bss section;
+ * - the coherent memory section.
+ * ---------------------------------------------
+ */
+ ldr x0, =__BSS_START__
+ ldr x1, =__BSS_SIZE__
+ bl zeromem16
+
+ /* --------------------------------------------
+ * Allocate a stack whose memory will be marked
+ * as Normal-IS-WBWA when the MMU is enabled.
+ * There is no risk of reading stale stack
+ * memory after enabling the MMU as only the
+ * primary cpu is running at the moment.
+ * --------------------------------------------
+ */
+ bl plat_set_my_stack
+
+ /* ---------------------------------------------
+ * Perform early platform setup & platform
+ * specific early arch. setup e.g. mmu setup
+ * ---------------------------------------------
+ */
+ mov x0, x20
+ mov x1, x21
+ bl bl2u_early_platform_setup
+ bl bl2u_plat_arch_setup
+
+ /* ---------------------------------------------
+ * Jump to bl2u_main function.
+ * ---------------------------------------------
+ */
+ bl bl2u_main
+
+_panic:
+ b _panic
+endfunc bl2u_entrypoint
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
new file mode 100644
index 0000000..ec12077
--- /dev/null
+++ b/bl2u/bl2u.ld.S
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+ENTRY(bl2u_entrypoint)
+
+MEMORY {
+ RAM (rwx): ORIGIN = BL2U_BASE, LENGTH = BL2U_LIMIT - BL2U_BASE
+}
+
+
+SECTIONS
+{
+ . = BL2U_BASE;
+ ASSERT(. == ALIGN(4096),
+ "BL2U_BASE address is not aligned on a page boundary.")
+
+ ro . : {
+ __RO_START__ = .;
+ *bl2u_entrypoint.o(.text*)
+ *(.text*)
+ *(.rodata*)
+
+ *(.vectors)
+ __RO_END_UNALIGNED__ = .;
+ /*
+ * Memory page(s) mapped to this section will be marked as
+ * read-only, executable. No RW data from the next section must
+ * creep in. Ensure the rest of the current memory page is unused.
+ */
+ . = NEXT(4096);
+ __RO_END__ = .;
+ } >RAM
+
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
+ .data . : {
+ __DATA_START__ = .;
+ *(.data*)
+ __DATA_END__ = .;
+ } >RAM
+
+ stacks (NOLOAD) : {
+ __STACKS_START__ = .;
+ *(tzfw_normal_stacks)
+ __STACKS_END__ = .;
+ } >RAM
+
+ /*
+ * The .bss section gets initialised to 0 at runtime.
+ * Its base address must be 16-byte aligned.
+ */
+ .bss : ALIGN(16) {
+ __BSS_START__ = .;
+ *(SORT_BY_ALIGNMENT(.bss*))
+ *(COMMON)
+ __BSS_END__ = .;
+ } >RAM
+
+ /*
+ * The xlat_table section is for full, aligned page tables (4K).
+ * Removing them from .bss avoids forcing 4K alignment on
+ * the .bss section and eliminates the unecessary zero init
+ */
+ xlat_table (NOLOAD) : {
+ *(xlat_table)
+ } >RAM
+
+#if USE_COHERENT_MEM
+ /*
+ * The base address of the coherent memory section must be page-aligned (4K)
+ * to guarantee that the coherent data are stored on their own pages and
+ * are not mixed with normal data. This is required to set up the correct
+ * memory attributes for the coherent data page tables.
+ */
+ coherent_ram (NOLOAD) : ALIGN(4096) {
+ __COHERENT_RAM_START__ = .;
+ *(tzfw_coherent_mem)
+ __COHERENT_RAM_END_UNALIGNED__ = .;
+ /*
+ * Memory page(s) mapped to this section will be marked
+ * as device memory. No other unexpected data must creep in.
+ * Ensure the rest of the current memory page is unused.
+ */
+ . = NEXT(4096);
+ __COHERENT_RAM_END__ = .;
+ } >RAM
+#endif
+
+ /*
+ * Define a linker symbol to mark end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
+ __BL2U_END__ = .;
+
+ __BSS_SIZE__ = SIZEOF(.bss);
+
+ ASSERT(. <= BL2U_LIMIT, "BL2U image has exceeded its limit.")
+}
diff --git a/bl2u/bl2u.mk b/bl2u/bl2u.mk
new file mode 100644
index 0000000..aa9de54
--- /dev/null
+++ b/bl2u/bl2u.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BL2U_SOURCES += bl2u/bl2u_main.c \
+ bl2u/aarch64/bl2u_entrypoint.S \
+ common/aarch64/early_exceptions.S
+
+BL2U_LINKERFILE := bl2u/bl2u.ld.S
diff --git a/bl2u/bl2u_main.c b/bl2u/bl2u_main.c
new file mode 100644
index 0000000..515ddfb
--- /dev/null
+++ b/bl2u/bl2u_main.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <auth_mod.h>
+#include <bl_common.h>
+#include <bl1.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * This function is responsible to:
+ * Load SCP_BL2U if platform has defined SCP_BL2U_BASE
+ * Perform platform setup.
+ * Go back to EL3.
+ ******************************************************************************/
+void bl2u_main(void)
+{
+ NOTICE("BL2U: %s\n", version_string);
+ NOTICE("BL2U: %s\n", build_message);
+
+#if SCP_BL2U_BASE
+ int rc;
+ /* Load the subsequent bootloader images */
+ rc = bl2u_plat_handle_scp_bl2u();
+ if (rc) {
+ ERROR("Failed to load SCP_BL2U (%i)\n", rc);
+ panic();
+ }
+#endif
+
+ /* Perform platform setup in BL2U after loading SCP_BL2U */
+ bl2u_platform_setup();
+
+ /*
+ * Indicate that BL2U is done and resume back to
+ * normal world via an SMC to BL1.
+ * x1 could be passed to Normal world,
+ * so DO NOT pass any secret information.
+ */
+ smc(FWU_SMC_SEC_IMAGE_DONE, 0, 0, 0, 0, 0, 0, 0);
+ wfi();
+}
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 2835320..dc11e0a 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -36,7 +36,6 @@
#include <runtime_svc.h>
.globl runtime_exceptions
- .globl el3_exit
/* -----------------------------------------------------
* Handle SMC exceptions separately from other sync.
@@ -426,38 +425,7 @@
#endif
blr x15
- /* -----------------------------------------------------
- * This routine assumes that the SP_EL3 is pointing to
- * a valid context structure from where the gp regs and
- * other special registers can be retrieved.
- *
- * Keep it in the same section as smc_handler as this
- * function uses a fall-through to el3_exit
- * -----------------------------------------------------
- */
-el3_exit: ; .type el3_exit, %function
- /* -----------------------------------------------------
- * Save the current SP_EL0 i.e. the EL3 runtime stack
- * which will be used for handling the next SMC. Then
- * switch to SP_EL3
- * -----------------------------------------------------
- */
- mov x17, sp
- msr spsel, #1
- str x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
-
- /* -----------------------------------------------------
- * Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
- * -----------------------------------------------------
- */
- ldr x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
- ldp x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
- msr scr_el3, x18
- msr spsr_el3, x16
- msr elr_el3, x17
-
- /* Restore saved general purpose registers and return */
- b restore_gp_registers_eret
+ b el3_exit
smc_unknown:
/*
@@ -479,51 +447,3 @@
msr spsel, #1 /* Switch to SP_ELx */
bl report_unhandled_exception
endfunc smc_handler
-
- /* -----------------------------------------------------
- * The following functions are used to saved and restore
- * all the general pupose registers. Ideally we would
- * only save and restore the callee saved registers when
- * a world switch occurs but that type of implementation
- * is more complex. So currently we will always save and
- * restore these registers on entry and exit of EL3.
- * These are not macros to ensure their invocation fits
- * within the 32 instructions per exception vector.
- * -----------------------------------------------------
- */
-func save_gp_registers
- stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
- stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
- stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
- stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
- stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
- stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
- stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
- stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
- stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
- save_x18_to_x29_sp_el0
- ret
-endfunc save_gp_registers
-
-func restore_gp_registers_eret
- ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
- ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
-
-restore_gp_registers_callee_eret:
- ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
- ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
- ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
- ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
- ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
- ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
- ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
- ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
- ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
- ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
- ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
- ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
- ldp x30, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
- msr sp_el0, x17
- ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
- eret
-endfunc restore_gp_registers_eret
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index a31c1f4..0c2b631 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -29,16 +29,17 @@
#
BL31_SOURCES += bl31/bl31_main.c \
- bl31/context_mgmt.c \
bl31/cpu_data_array.c \
bl31/runtime_svc.c \
bl31/interrupt_mgmt.c \
bl31/aarch64/bl31_arch_setup.c \
bl31/aarch64/bl31_entrypoint.S \
- bl31/aarch64/context.S \
bl31/aarch64/cpu_data.S \
bl31/aarch64/runtime_exceptions.S \
bl31/aarch64/crash_reporting.S \
+ bl31/bl31_context_mgmt.c \
+ common/aarch64/context.S \
+ common/context_mgmt.c \
lib/cpus/aarch64/cpu_helpers.S \
lib/locks/exclusive/spinlock.S \
services/std_svc/std_svc_setup.c \
diff --git a/bl31/bl31_context_mgmt.c b/bl31/bl31_context_mgmt.c
new file mode 100644
index 0000000..ae24424
--- /dev/null
+++ b/bl31/bl31_context_mgmt.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl31.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <cpu_data.h>
+#include <platform.h>
+
+
+/*******************************************************************************
+ * This function returns a pointer to the most recent 'cpu_context' structure
+ * for the calling CPU that was set as the context for the specified security
+ * state. NULL is returned if no such structure has been specified.
+ ******************************************************************************/
+void *cm_get_context(uint32_t security_state)
+{
+ assert(security_state <= NON_SECURE);
+
+ return get_cpu_data(cpu_context[security_state]);
+}
+
+/*******************************************************************************
+ * This function sets the pointer to the current 'cpu_context' structure for the
+ * specified security state for the calling CPU
+ ******************************************************************************/
+void cm_set_context(void *context, uint32_t security_state)
+{
+ assert(security_state <= NON_SECURE);
+
+ set_cpu_data(cpu_context[security_state], context);
+}
+
+/*******************************************************************************
+ * This function returns a pointer to the most recent 'cpu_context' structure
+ * for the CPU identified by `cpu_idx` that was set as the context for the
+ * specified security state. NULL is returned if no such structure has been
+ * specified.
+ ******************************************************************************/
+void *cm_get_context_by_index(unsigned int cpu_idx,
+ unsigned int security_state)
+{
+ assert(sec_state_is_valid(security_state));
+
+ return get_cpu_data_by_index(cpu_idx, cpu_context[security_state]);
+}
+
+/*******************************************************************************
+ * This function sets the pointer to the current 'cpu_context' structure for the
+ * specified security state for the CPU identified by CPU index.
+ ******************************************************************************/
+void cm_set_context_by_index(unsigned int cpu_idx, void *context,
+ unsigned int security_state)
+{
+ assert(sec_state_is_valid(security_state));
+
+ set_cpu_data_by_index(cpu_idx, cpu_context[security_state], context);
+}
+
+#if !ERROR_DEPRECATED
+/*
+ * These context management helpers are deprecated but are maintained for use
+ * by SPDs which have not migrated to the new API. If ERROR_DEPRECATED
+ * is enabled, these are excluded from the build so as to force users to
+ * migrate to the new API.
+ */
+
+/*******************************************************************************
+ * This function returns a pointer to the most recent 'cpu_context' structure
+ * for the CPU identified by MPIDR that was set as the context for the specified
+ * security state. NULL is returned if no such structure has been specified.
+ ******************************************************************************/
+void *cm_get_context_by_mpidr(uint64_t mpidr, uint32_t security_state)
+{
+ assert(sec_state_is_valid(security_state));
+
+ return cm_get_context_by_index(platform_get_core_pos(mpidr), security_state);
+}
+
+/*******************************************************************************
+ * This function sets the pointer to the current 'cpu_context' structure for the
+ * specified security state for the CPU identified by MPIDR
+ ******************************************************************************/
+void cm_set_context_by_mpidr(uint64_t mpidr, void *context, uint32_t security_state)
+{
+ assert(sec_state_is_valid(security_state));
+
+ cm_set_context_by_index(platform_get_core_pos(mpidr),
+ context, security_state);
+}
+
+/*******************************************************************************
+ * The following function provides a compatibility function for SPDs using the
+ * existing cm library routines. This function is expected to be invoked for
+ * initializing the cpu_context for the CPU specified by MPIDR for first use.
+ ******************************************************************************/
+void cm_init_context(unsigned long mpidr, const entry_point_info_t *ep)
+{
+ if ((mpidr & MPIDR_AFFINITY_MASK) ==
+ (read_mpidr_el1() & MPIDR_AFFINITY_MASK))
+ cm_init_my_context(ep);
+ else
+ cm_init_context_by_index(platform_get_core_pos(mpidr), ep);
+}
+#endif
\ No newline at end of file
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 9abc395..f22e612 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -77,7 +77,7 @@
/* Perform remaining generic architectural setup from EL3 */
bl31_arch_setup();
- /* Perform platform setup in BL1 */
+ /* Perform platform setup in BL31 */
bl31_platform_setup();
/* Initialise helper libraries */
@@ -109,6 +109,12 @@
* corresponding to the desired security state after the next ERET.
*/
bl31_prepare_next_image_entry();
+
+ /*
+ * Perform any platform specific runtime setup prior to cold boot exit
+ * from BL31
+ */
+ bl31_plat_runtime_setup();
}
/*******************************************************************************
diff --git a/bl31/interrupt_mgmt.c b/bl31/interrupt_mgmt.c
index 206578b..e991851 100644
--- a/bl31/interrupt_mgmt.c
+++ b/bl31/interrupt_mgmt.c
@@ -67,18 +67,15 @@
static intr_type_desc_t intr_type_descs[MAX_INTR_TYPES];
/*******************************************************************************
- * This function validates the interrupt type. EL3 interrupts are currently not
- * supported.
+ * This function validates the interrupt type.
******************************************************************************/
static int32_t validate_interrupt_type(uint32_t type)
{
- if (type == INTR_TYPE_EL3)
- return -ENOTSUP;
-
- if (type != INTR_TYPE_S_EL1 && type != INTR_TYPE_NS)
- return -EINVAL;
+ if (type == INTR_TYPE_S_EL1 || type == INTR_TYPE_NS ||
+ type == INTR_TYPE_EL3)
+ return 0;
- return 0;
+ return -EINVAL;
}
/*******************************************************************************
@@ -95,6 +92,9 @@
if (type == INTR_TYPE_NS)
return validate_ns_interrupt_rm(flags);
+ if (type == INTR_TYPE_EL3)
+ return validate_el3_interrupt_rm(flags);
+
return -EINVAL;
}
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
index 9732ff2..531ab9b 100644
--- a/bl32/tsp/aarch64/tsp_entrypoint.S
+++ b/bl32/tsp/aarch64/tsp_entrypoint.S
@@ -177,7 +177,7 @@
b tsp_cpu_off_entry
b tsp_cpu_resume_entry
b tsp_cpu_suspend_entry
- b tsp_fiq_entry
+ b tsp_sel1_intr_entry
b tsp_system_off_entry
b tsp_system_reset_entry
endfunc tsp_vector_table
@@ -325,13 +325,15 @@
restore_args_call_smc
endfunc tsp_cpu_suspend_entry
- /*---------------------------------------------
+ /*-------------------------------------------------
* This entrypoint is used by the TSPD to pass
- * control for handling a pending S-EL1 FIQ.
- * 'x0' contains a magic number which indicates
- * this. TSPD expects control to be handed back
- * at the end of FIQ processing. This is done
- * through an SMC. The handover agreement is:
+ * control for `synchronously` handling a S-EL1
+ * Interrupt which was triggered while executing
+ * in normal world. 'x0' contains a magic number
+ * which indicates this. TSPD expects control to
+ * be handed back at the end of interrupt
+ * processing. This is done through an SMC.
+ * The handover agreement is:
*
* 1. PSTATE.DAIF are set upon entry. 'x1' has
* the ELR_EL3 from the non-secure state.
@@ -343,40 +345,54 @@
* 4. TSP can use 'x0-x18' to enable its C
* runtime.
* 5. TSP returns to TSPD using an SMC with
- * 'x0' = TSP_HANDLED_S_EL1_FIQ
- * ---------------------------------------------
+ * 'x0' = TSP_HANDLED_S_EL1_INTR
+ * ------------------------------------------------
*/
-func tsp_fiq_entry
+func tsp_sel1_intr_entry
#if DEBUG
- mov x2, #(TSP_HANDLE_FIQ_AND_RETURN & ~0xffff)
- movk x2, #(TSP_HANDLE_FIQ_AND_RETURN & 0xffff)
+ mov_imm x2, TSP_HANDLE_SEL1_INTR_AND_RETURN
cmp x0, x2
- b.ne tsp_fiq_entry_panic
+ b.ne tsp_sel1_int_entry_panic
#endif
- /*---------------------------------------------
+ /*-------------------------------------------------
* Save any previous context needed to perform
* an exception return from S-EL1 e.g. context
- * from a previous IRQ. Update statistics and
- * handle the FIQ before returning to the TSPD.
+ * from a previous Non secure Interrupt.
+ * Update statistics and handle the S-EL1
+ * interrupt before returning to the TSPD.
* IRQ/FIQs are not enabled since that will
* complicate the implementation. Execution
* will be transferred back to the normal world
- * in any case. A non-zero return value from the
- * fiq handler is an error.
- * ---------------------------------------------
+ * in any case. The handler can return 0
+ * if the interrupt was handled or TSP_PREEMPTED
+ * if the expected interrupt was preempted
+ * by an interrupt that should be handled in EL3
+ * e.g. Group 0 interrupt in GICv3. In both
+ * the cases switch to EL3 using SMC with id
+ * TSP_HANDLED_S_EL1_INTR. Any other return value
+ * from the handler will result in panic.
+ * ------------------------------------------------
*/
save_eret_context x2 x3
- bl tsp_update_sync_fiq_stats
- bl tsp_fiq_handler
- cbnz x0, tsp_fiq_entry_panic
+ bl tsp_update_sync_sel1_intr_stats
+ bl tsp_common_int_handler
+ /* Check if the S-EL1 interrupt has been handled */
+ cbnz x0, tsp_sel1_intr_check_preemption
+ b tsp_sel1_intr_return
+tsp_sel1_intr_check_preemption:
+ /* Check if the S-EL1 interrupt has been preempted */
+ mov_imm x1, TSP_PREEMPTED
+ cmp x0, x1
+ b.ne tsp_sel1_int_entry_panic
+tsp_sel1_intr_return:
+ mov_imm x0, TSP_HANDLED_S_EL1_INTR
restore_eret_context x2 x3
- mov x0, #(TSP_HANDLED_S_EL1_FIQ & ~0xffff)
- movk x0, #(TSP_HANDLED_S_EL1_FIQ & 0xffff)
smc #0
-tsp_fiq_entry_panic:
- b tsp_fiq_entry_panic
-endfunc tsp_fiq_entry
+ /* Should never reach here */
+tsp_sel1_int_entry_panic:
+ b tsp_sel1_int_entry_panic
+endfunc tsp_sel1_intr_entry
/*---------------------------------------------
* This entrypoint is used by the TSPD when this
diff --git a/bl32/tsp/aarch64/tsp_exceptions.S b/bl32/tsp/aarch64/tsp_exceptions.S
index 4c0d436..d5e089f 100644
--- a/bl32/tsp/aarch64/tsp_exceptions.S
+++ b/bl32/tsp/aarch64/tsp_exceptions.S
@@ -70,6 +70,28 @@
add sp, sp, SCRATCH_REG_SIZE
.endm
+ /* ----------------------------------------------------
+ * Common TSP interrupt handling routine
+ * ----------------------------------------------------
+ */
+ .macro handle_tsp_interrupt label
+ /* Enable the SError interrupt */
+ msr daifclr, #DAIF_ABT_BIT
+
+ save_caller_regs_and_lr
+ bl tsp_common_int_handler
+ cbz x0, interrupt_exit_\label
+
+ /*
+ * This interrupt was not targetted to S-EL1 so send it to
+ * the monitor and wait for execution to resume.
+ */
+ smc #0
+interrupt_exit_\label:
+ restore_caller_regs_and_lr
+ eret
+ .endm
+
.globl tsp_exceptions
/* -----------------------------------------------------
@@ -120,36 +142,12 @@
.align 7
irq_sp_elx:
- /* Enable the SError interrupt */
- msr daifclr, #DAIF_ABT_BIT
-
- save_caller_regs_and_lr
- /* We just update some statistics in the handler */
- bl tsp_irq_received
- /* Hand over control to the normal world to handle the IRQ */
- smc #0
- /* The resume std smc starts from here */
- restore_caller_regs_and_lr
- eret
+ handle_tsp_interrupt irq_sp_elx
check_vector_size irq_sp_elx
.align 7
fiq_sp_elx:
- /* Enable the SError interrupt */
- msr daifclr, #DAIF_ABT_BIT
-
- save_caller_regs_and_lr
- bl tsp_fiq_handler
- cbz x0, fiq_sp_elx_done
-
- /*
- * This FIQ was not targetted to S-EL1 so send it to
- * the monitor and wait for execution to resume.
- */
- smc #0
-fiq_sp_elx_done:
- restore_caller_regs_and_lr
- eret
+ handle_tsp_interrupt fiq_sp_elx
check_vector_size fiq_sp_elx
.align 7
diff --git a/bl32/tsp/tsp_interrupt.c b/bl32/tsp/tsp_interrupt.c
index 139642d..7654d2e 100644
--- a/bl32/tsp/tsp_interrupt.c
+++ b/bl32/tsp/tsp_interrupt.c
@@ -31,50 +31,70 @@
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
-#include <gic_v2.h>
#include <platform.h>
#include <platform_def.h>
#include <tsp.h>
#include "tsp_private.h"
/*******************************************************************************
- * This function updates the TSP statistics for FIQs handled synchronously i.e
- * the ones that have been handed over by the TSPD. It also keeps count of the
- * number of times control was passed back to the TSPD after handling an FIQ.
- * In the future it will be possible that the TSPD hands over an FIQ to the TSP
- * but does not expect it to return execution. This statistic will be useful to
- * distinguish between these two models of synchronous FIQ handling.
- * The 'elr_el3' parameter contains the address of the instruction in normal
- * world where this FIQ was generated.
+ * This function updates the TSP statistics for S-EL1 interrupts handled
+ * synchronously i.e the ones that have been handed over by the TSPD. It also
+ * keeps count of the number of times control was passed back to the TSPD
+ * after handling the interrupt. In the future it will be possible that the
+ * TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to
+ * return execution. This statistic will be useful to distinguish between these
+ * two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter
+ * contains the address of the instruction in normal world where this S-EL1
+ * interrupt was generated.
******************************************************************************/
-void tsp_update_sync_fiq_stats(uint32_t type, uint64_t elr_el3)
+void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3)
{
uint32_t linear_id = plat_my_core_pos();
- tsp_stats[linear_id].sync_fiq_count++;
- if (type == TSP_HANDLE_FIQ_AND_RETURN)
- tsp_stats[linear_id].sync_fiq_ret_count++;
+ tsp_stats[linear_id].sync_sel1_intr_count++;
+ if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN)
+ tsp_stats[linear_id].sync_sel1_intr_ret_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock);
- VERBOSE("TSP: cpu 0x%lx sync fiq request from 0x%lx\n",
+ VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%lx\n",
read_mpidr(), elr_el3);
- VERBOSE("TSP: cpu 0x%lx: %d sync fiq requests, %d sync fiq returns\n",
+ VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
+ " %d sync s-el1 interrupt returns\n",
read_mpidr(),
- tsp_stats[linear_id].sync_fiq_count,
- tsp_stats[linear_id].sync_fiq_ret_count);
+ tsp_stats[linear_id].sync_sel1_intr_count,
+ tsp_stats[linear_id].sync_sel1_intr_ret_count);
spin_unlock(&console_lock);
#endif
}
+/******************************************************************************
+ * This function is invoked when a non S-EL1 interrupt is received and causes
+ * the preemption of TSP. This function returns TSP_PREEMPTED and results
+ * in the control being handed over to EL3 for handling the interrupt.
+ *****************************************************************************/
+int32_t tsp_handle_preemption(void)
+{
+ uint32_t linear_id = plat_my_core_pos();
+
+ tsp_stats[linear_id].preempt_intr_count++;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ spin_lock(&console_lock);
+ VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n",
+ read_mpidr(), tsp_stats[linear_id].preempt_intr_count);
+ spin_unlock(&console_lock);
+#endif
+ return TSP_PREEMPTED;
+}
+
/*******************************************************************************
- * TSP FIQ handler called as a part of both synchronous and asynchronous
- * handling of FIQ interrupts. It returns 0 upon successfully handling a S-EL1
- * FIQ and treats all other FIQs as EL3 interrupts. It assumes that the GIC
- * architecture version in v2.0 and the secure physical timer interrupt is the
- * only S-EL1 interrupt that it needs to handle.
+ * TSP interrupt handler is called as a part of both synchronous and
+ * asynchronous handling of TSP interrupts. Currently the physical timer
+ * interrupt is the only S-EL1 interrupt that this handler expects. It returns
+ * 0 upon successfully handling the expected interrupt and all other
+ * interrupts are treated as normal world or EL3 interrupts.
******************************************************************************/
-int32_t tsp_fiq_handler(void)
+int32_t tsp_common_int_handler(void)
{
uint32_t linear_id = plat_my_core_pos(), id;
@@ -82,16 +102,21 @@
* Get the highest priority pending interrupt id and see if it is the
* secure physical generic timer interrupt in which case, handle it.
* Otherwise throw this interrupt at the EL3 firmware.
+ *
+ * There is a small time window between reading the highest priority
+ * pending interrupt and acknowledging it during which another
+ * interrupt of higher priority could become the highest pending
+ * interrupt. This is not expected to happen currently for TSP.
*/
id = plat_ic_get_pending_interrupt_id();
/* TSP can only handle the secure physical timer interrupt */
if (id != TSP_IRQ_SEC_PHY_TIMER)
- return TSP_EL3_FIQ;
+ return tsp_handle_preemption();
/*
- * Handle the interrupt. Also sanity check if it has been preempted by
- * another secure interrupt through an assertion.
+ * Acknowledge and handle the secure timer interrupt. Also sanity check
+ * if it has been preempted by another interrupt through an assertion.
*/
id = plat_ic_acknowledge_interrupt();
assert(id == TSP_IRQ_SEC_PHY_TIMER);
@@ -99,29 +124,14 @@
plat_ic_end_of_interrupt(id);
/* Update the statistics and print some messages */
- tsp_stats[linear_id].fiq_count++;
+ tsp_stats[linear_id].sel1_intr_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock);
- VERBOSE("TSP: cpu 0x%lx handled fiq %d\n",
+ VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n",
read_mpidr(), id);
- VERBOSE("TSP: cpu 0x%lx: %d fiq requests\n",
- read_mpidr(), tsp_stats[linear_id].fiq_count);
+ VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
+ read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
spin_unlock(&console_lock);
#endif
return 0;
}
-
-int32_t tsp_irq_received(void)
-{
- uint32_t linear_id = plat_my_core_pos();
-
- tsp_stats[linear_id].irq_count++;
-#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
- spin_lock(&console_lock);
- VERBOSE("TSP: cpu 0x%lx received irq\n", read_mpidr());
- VERBOSE("TSP: cpu 0x%lx: %d irq requests\n",
- read_mpidr(), tsp_stats[linear_id].irq_count);
- spin_unlock(&console_lock);
-#endif
- return TSP_PREEMPTED;
-}
diff --git a/bl32/tsp/tsp_private.h b/bl32/tsp/tsp_private.h
index 39fb5f6..e341cfd 100644
--- a/bl32/tsp/tsp_private.h
+++ b/bl32/tsp/tsp_private.h
@@ -54,10 +54,14 @@
typedef struct work_statistics {
- uint32_t fiq_count; /* Number of FIQs on this cpu */
- uint32_t irq_count; /* Number of IRQs on this cpu */
- uint32_t sync_fiq_count; /* Number of sync. fiqs on this cpu */
- uint32_t sync_fiq_ret_count; /* Number of fiq returns on this cpu */
+ /* Number of s-el1 interrupts on this cpu */
+ uint32_t sel1_intr_count;
+ /* Number of non s-el1 interrupts on this cpu which preempted TSP */
+ uint32_t preempt_intr_count;
+ /* Number of sync s-el1 interrupts on this cpu */
+ uint32_t sync_sel1_intr_count;
+ /* Number of s-el1 interrupts returns on this cpu */
+ uint32_t sync_sel1_intr_ret_count;
uint32_t smc_count; /* Number of returns on this cpu */
uint32_t eret_count; /* Number of entries on this cpu */
uint32_t cpu_on_count; /* Number of cpu on requests */
@@ -115,8 +119,8 @@
void tsp_generic_timer_save(void);
void tsp_generic_timer_restore(void);
-/* FIQ management functions */
-void tsp_update_sync_fiq_stats(uint32_t type, uint64_t elr_el3);
+/* S-EL1 interrupt management functions */
+void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3);
/* Data structure to keep track of TSP statistics */
diff --git a/bl31/aarch64/context.S b/common/aarch64/context.S
similarity index 66%
rename from bl31/aarch64/context.S
rename to common/aarch64/context.S
index 70a1e5d..3d13a80 100644
--- a/bl31/aarch64/context.S
+++ b/common/aarch64/context.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,6 +32,17 @@
#include <asm_macros.S>
#include <context.h>
+ .global el1_sysregs_context_save
+ .global el1_sysregs_context_restore
+#if CTX_INCLUDE_FPREGS
+ .global fpregs_context_save
+ .global fpregs_context_restore
+#endif
+ .global save_gp_registers
+ .global restore_gp_registers_eret
+ .global restore_gp_registers_callee_eret
+ .global el3_exit
+
/* -----------------------------------------------------
* The following function strictly follows the AArch64
* PCS to use x9-x17 (temporary caller-saved registers)
@@ -40,7 +51,6 @@
* the register context will be saved.
* -----------------------------------------------------
*/
- .global el1_sysregs_context_save
func el1_sysregs_context_save
mrs x9, spsr_el1
@@ -127,7 +137,6 @@
* from where the register context will be restored
* -----------------------------------------------------
*/
- .global el1_sysregs_context_restore
func el1_sysregs_context_restore
ldp x9, x10, [x0, #CTX_SPSR_EL1]
@@ -225,7 +234,6 @@
* -----------------------------------------------------
*/
#if CTX_INCLUDE_FPREGS
- .global fpregs_context_save
func fpregs_context_save
stp q0, q1, [x0, #CTX_FP_Q0]
stp q2, q3, [x0, #CTX_FP_Q2]
@@ -269,7 +277,6 @@
* TODO: Revisit when VFP is used in secure world
* -----------------------------------------------------
*/
- .global fpregs_context_restore
func fpregs_context_restore
ldp q0, q1, [x0, #CTX_FP_Q0]
ldp q2, q3, [x0, #CTX_FP_Q2]
@@ -291,7 +298,7 @@
ldr x9, [x0, #CTX_FP_FPSR]
msr fpsr, x9
- str x10, [x0, #CTX_FP_FPCR]
+ ldr x10, [x0, #CTX_FP_FPCR]
msr fpcr, x10
/*
@@ -303,3 +310,92 @@
ret
endfunc fpregs_context_restore
#endif /* CTX_INCLUDE_FPREGS */
+
+/* -----------------------------------------------------
+ * The following functions are used to save and restore
+ * all the general purpose registers. Ideally we would
+ * only save and restore the callee saved registers when
+ * a world switch occurs but that type of implementation
+ * is more complex. So currently we will always save and
+ * restore these registers on entry and exit of EL3.
+ * These are not macros to ensure their invocation fits
+ * within the 32 instructions per exception vector.
+ * clobbers: x18
+ * -----------------------------------------------------
+ */
+func save_gp_registers
+ stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+ stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+ stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+ stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+ stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
+ stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
+ stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
+ stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+ stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+ stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
+ stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
+ stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
+ stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
+ stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+ stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
+ mrs x18, sp_el0
+ str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0]
+ ret
+endfunc save_gp_registers
+
+func restore_gp_registers_eret
+ ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+ ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+ b restore_gp_registers_callee_eret
+endfunc restore_gp_registers_eret
+
+func restore_gp_registers_callee_eret
+ ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+ ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+ ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
+ ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
+ ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
+ ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+ ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
+ ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
+ ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
+ ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
+ ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+ ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
+ ldp x30, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+ msr sp_el0, x17
+ ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+ eret
+endfunc restore_gp_registers_callee_eret
+
+ /* -----------------------------------------------------
+ * This routine assumes that the SP_EL3 is pointing to
+ * a valid context structure from where the gp regs and
+ * other special registers can be retrieved.
+ * -----------------------------------------------------
+ */
+func el3_exit
+ /* -----------------------------------------------------
+ * Save the current SP_EL0 i.e. the EL3 runtime stack
+ * which will be used for handling the next SMC. Then
+ * switch to SP_EL3
+ * -----------------------------------------------------
+ */
+ mov x17, sp
+ msr spsel, #1
+ str x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+
+ /* -----------------------------------------------------
+ * Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
+ * -----------------------------------------------------
+ */
+ ldr x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ ldp x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+ msr scr_el3, x18
+ msr spsr_el3, x16
+ msr elr_el3, x17
+
+ /* Restore saved general purpose registers and return */
+ b restore_gp_registers_eret
+endfunc el3_exit
diff --git a/common/aarch64/early_exceptions.S b/common/aarch64/early_exceptions.S
index 90f5421..780a38f 100644
--- a/common/aarch64/early_exceptions.S
+++ b/common/aarch64/early_exceptions.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,7 +29,7 @@
*/
#include <asm_macros.S>
-#include <runtime_svc.h>
+#include <bl_common.h>
.globl early_exceptions
diff --git a/bl31/context_mgmt.c b/common/context_mgmt.c
similarity index 76%
rename from bl31/context_mgmt.c
rename to common/context_mgmt.c
index 6d40534..68ec894 100644
--- a/bl31/context_mgmt.c
+++ b/common/context_mgmt.c
@@ -32,14 +32,12 @@
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
-#include <bl31.h>
#include <context.h>
#include <context_mgmt.h>
-#include <cpu_data.h>
#include <interrupt_mgmt.h>
#include <platform.h>
#include <platform_def.h>
-#include <runtime_svc.h>
+#include <smcc_helpers.h>
#include <string.h>
@@ -65,105 +63,6 @@
}
/*******************************************************************************
- * This function returns a pointer to the most recent 'cpu_context' structure
- * for the CPU identified by `cpu_idx` that was set as the context for the
- * specified security state. NULL is returned if no such structure has been
- * specified.
- ******************************************************************************/
-void *cm_get_context_by_index(unsigned int cpu_idx,
- unsigned int security_state)
-{
- assert(sec_state_is_valid(security_state));
-
- return get_cpu_data_by_index(cpu_idx, cpu_context[security_state]);
-}
-
-/*******************************************************************************
- * This function sets the pointer to the current 'cpu_context' structure for the
- * specified security state for the CPU identified by CPU index.
- ******************************************************************************/
-void cm_set_context_by_index(unsigned int cpu_idx, void *context,
- unsigned int security_state)
-{
- assert(sec_state_is_valid(security_state));
-
- set_cpu_data_by_index(cpu_idx, cpu_context[security_state], context);
-}
-
-#if !ERROR_DEPRECATED
-/*
- * These context management helpers are deprecated but are maintained for use
- * by SPDs which have not migrated to the new API. If ERROR_DEPRECATED
- * is enabled, these are excluded from the build so as to force users to
- * migrate to the new API.
- */
-
-/*******************************************************************************
- * This function returns a pointer to the most recent 'cpu_context' structure
- * for the CPU identified by MPIDR that was set as the context for the specified
- * security state. NULL is returned if no such structure has been specified.
- ******************************************************************************/
-void *cm_get_context_by_mpidr(uint64_t mpidr, uint32_t security_state)
-{
- assert(sec_state_is_valid(security_state));
-
- return cm_get_context_by_index(platform_get_core_pos(mpidr), security_state);
-}
-
-/*******************************************************************************
- * This function sets the pointer to the current 'cpu_context' structure for the
- * specified security state for the CPU identified by MPIDR
- ******************************************************************************/
-void cm_set_context_by_mpidr(uint64_t mpidr, void *context, uint32_t security_state)
-{
- assert(sec_state_is_valid(security_state));
-
- cm_set_context_by_index(platform_get_core_pos(mpidr),
- context, security_state);
-}
-
-/*******************************************************************************
- * The following function provides a compatibility function for SPDs using the
- * existing cm library routines. This function is expected to be invoked for
- * initializing the cpu_context for the CPU specified by MPIDR for first use.
- ******************************************************************************/
-void cm_init_context(unsigned long mpidr, const entry_point_info_t *ep)
-{
- if ((mpidr & MPIDR_AFFINITY_MASK) ==
- (read_mpidr_el1() & MPIDR_AFFINITY_MASK))
- cm_init_my_context(ep);
- else
- cm_init_context_by_index(platform_get_core_pos(mpidr), ep);
-}
-#endif
-
-/*******************************************************************************
- * This function is used to program the context that's used for exception
- * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for
- * the required security state
- ******************************************************************************/
-static inline void cm_set_next_context(void *context)
-{
-#if DEBUG
- uint64_t sp_mode;
-
- /*
- * Check that this function is called with SP_EL0 as the stack
- * pointer
- */
- __asm__ volatile("mrs %0, SPSel\n"
- : "=r" (sp_mode));
-
- assert(sp_mode == MODE_SP_EL0);
-#endif
-
- __asm__ volatile("msr spsel, #1\n"
- "mov sp, %0\n"
- "msr spsel, #0\n"
- : : "r" (context));
-}
-
-/*******************************************************************************
* The following function initializes the cpu_context 'ctx' for
* first use, and sets the initial entrypoint state as specified by the
* entry_point_info structure.
@@ -212,7 +111,13 @@
if (EP_GET_ST(ep->h.attr))
scr_el3 |= SCR_ST_BIT;
+#if IMAGE_BL31
+ /*
+ * IRQ/FIQ bits only need setting if interrupt routing
+ * model has been set up for BL31.
+ */
scr_el3 |= get_scr_el3_from_routing_model(security_state);
+#endif
/*
* Set up SCTLR_ELx for the target exception level:
@@ -330,6 +235,14 @@
/* Set VPIDR, VMPIDR to match MIDR, MPIDR */
write_vpidr_el2(read_midr_el1());
write_vmpidr_el2(read_mpidr_el1());
+
+ /*
+ * Reset VTTBR_EL2.
+ * Needed because cache maintenance operations depend on
+ * the VMID even when non-secure EL1&0 stage 2 address
+ * translation are disabled.
+ */
+ write_vttbr_el2(0);
}
}
diff --git a/docs/interrupt-framework-design.md b/docs/interrupt-framework-design.md
index 53707ae..271cd92 100644
--- a/docs/interrupt-framework-design.md
+++ b/docs/interrupt-framework-design.md
@@ -399,12 +399,12 @@
1. It passes control to the Test Secure Payload to perform its
initialisation. The TSP provides the address of the vector table
`tsp_vectors` in the SP which also includes the handler for Secure-EL1
- interrupts in the `fiq_entry` field. The TSPD passes control to the TSP at
+ interrupts in the `sel1_intr_entry` field. The TSPD passes control to the TSP at
this address when it receives a Secure-EL1 interrupt.
The handover agreement between the TSP and the TSPD requires that the TSPD
masks all interrupts (`PSTATE.DAIF` bits) when it calls
- `tsp_fiq_entry()`. The TSP has to preserve the callee saved general
+ `tsp_sel1_intr_entry()`. The TSP has to preserve the callee saved general
purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use
`x0-x18` to enable its C runtime.
@@ -514,7 +514,7 @@
The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
described in Section 2.2.2. It is known to the TSPD service at build time.
-The TSP implements an entrypoint (`tsp_fiq_entry()`) for handling Secure-EL1
+The TSP implements an entrypoint (`tsp_sel1_intr_entry()`) for handling Secure-EL1
interrupts taken in non-secure state and routed through the TSPD service
(synchronous handling model). It passes the reference to this entrypoint via
`tsp_vectors` to the TSPD service.
@@ -700,9 +700,9 @@
3. It saves the system register context for the non-secure state by calling
`cm_el1_sysregs_context_save(NON_SECURE);`.
-4. It sets the `ELR_EL3` system register to `tsp_fiq_entry` and sets the
+4. It sets the `ELR_EL3` system register to `tsp_sel1_intr_entry` and sets the
`SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to
- `TSP_HANDLE_FIQ_AND_RETURN`. If the TSP was in the middle of handling a
+ `TSP_HANDLE_SEL1_INTR_AND_RETURN`. If the TSP was in the middle of handling a
standard SMC, then the `ELR_EL3` and `SPSR_EL3` registers in the secure CPU
context are saved first.
@@ -723,20 +723,20 @@
![Image 1](diagrams/sec-int-handling.png?raw=true)
-The TSP issues an SMC with `TSP_HANDLED_S_EL1_FIQ` as the function identifier to
+The TSP issues an SMC with `TSP_HANDLED_S_EL1_INTR` as the function identifier to
signal completion of interrupt handling.
The TSP issues an SMC with `TSP_PREEMPTED` as the function identifier to signal
generation of a non-secure interrupt in Secure-EL1.
The TSPD service takes the following actions in `tspd_smc_handler()` function
-upon receiving an SMC with `TSP_HANDLED_S_EL1_FIQ` and `TSP_PREEMPTED` as the
+upon receiving an SMC with `TSP_HANDLED_S_EL1_INTR` and `TSP_PREEMPTED` as the
function identifiers:
1. It ensures that the call originated from the secure state otherwise
execution returns to the non-secure state with `SMC_UNK` in `x0`.
-2. If the function identifier is `TSP_HANDLED_S_EL1_FIQ`, it restores the
+2. If the function identifier is `TSP_HANDLED_S_EL1_INTR`, it restores the
saved `ELR_EL3` and `SPSR_EL3` system registers back to the secure CPU
context (see step 4 above) in case the TSP had been preempted by a non
secure interrupt earlier. It does not save the secure context since the
@@ -811,7 +811,7 @@
##### 2.3.3.1 Test secure payload behavior
The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
-`tsp_fiq_entry()`. The TSP handles the interrupt while ensuring that the
+`tsp_sel1_intr_entry()`. The TSP handles the interrupt while ensuring that the
handover agreement described in Section 2.2.2.1 is maintained. It updates some
statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
`tsp_fiq_handler()` which.
@@ -827,7 +827,7 @@
end of interrupt processing.
The TSP passes control back to the TSPD by issuing an SMC64 with
-`TSP_HANDLED_S_EL1_FIQ` as the function identifier.
+`TSP_HANDLED_S_EL1_INTR` as the function identifier.
The TSP handles interrupts under the asynchronous model as follows.
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index e5b4a9c..ba550f0 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -1172,6 +1172,21 @@
* Detects the system topology.
+### Function : bl31_plat_runtime_setup() [optional]
+
+ Argument : void
+ Return : void
+
+The purpose of this function is allow the platform to perform any BL31 runtime
+setup just prior to BL31 exit during cold boot. The default weak
+implementation of this function will invoke `console_uninit()` which will
+suppress any BL31 runtime logs.
+
+In ARM Standard platforms, this function will initialize the BL31 runtime
+console which will cause all further BL31 logs to be output to the
+runtime console.
+
+
### Function : bl31_get_next_image_info() [mandatory]
Argument : unsigned int
diff --git a/docs/user-guide.md b/docs/user-guide.md
index f9afccb..f921f87 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -25,7 +25,7 @@
is outside the scope of this document.
This document should be used in conjunction with the [Firmware Design] and the
-[Linaro release notes][Linaro releases].
+[Instructions for using the Linaro software deliverables][Linaro SW Instructions].
2. Host machine requirements
@@ -43,18 +43,15 @@
3. Tools
---------
-In addition to the prerequisite tools listed on the
-[Linaro release notes][Linaro releases], the following tools are needed to use
-the ARM Trusted Firmware:
+In addition to the mandatory prerequisite tools listed in the [instructions for
+using the Linaro software deliverables][Linaro SW Instructions], the following
+optional tools may be needed:
-* `device-tree-compiler` package for building the Flattened Device Tree (FDT)
- source files (`.dts` files) provided with this software.
+* `device-tree-compiler` package if you need to rebuild the Flattened Device
+ Tree (FDT) source files (`.dts` files) provided with this software.
-* `libssl-dev` package to build the certificate generation tool when support
- for Trusted Board Boot is needed.
+* For debugging, ARM [Development Studio 5 (DS-5)][DS-5] v5.22.
-* (Optional) For debugging, ARM [Development Studio 5 (DS-5)][DS-5] v5.21.
-
4. Getting the Trusted Firmware source code
--------------------------------------------
@@ -62,10 +59,8 @@
The Trusted Firmware source code can be obtained as part of the standard Linaro
releases, which provide a full software stack, including the Trusted Firmware,
normal world firmware, Linux kernel and device tree, file system as well as any
-additional micro-controller firmware required by the platform. Please follow the
-instructions on the [Linaro release notes][Linaro releases], section 2.2
-"Downloading the software sources" and section 2.3 "Downloading the filesystem
-binaries".
+additional micro-controller firmware required by the platform. This version of
+Trusted Firmware is tested with the [Linaro 15.10 Release][Linaro Release Notes].
Note: Both the LSK kernel or the latest tracking kernel can be used along the
ARM Trusted Firmware, choose the one that best suits your needs.
@@ -278,10 +273,13 @@
(Coherent memory region is included) or 0 (Coherent memory region is
excluded). Default is 1.
-* `TSPD_ROUTE_IRQ_TO_EL3`: A non zero value enables the routing model
- for non-secure interrupts in which they are routed to EL3 (TSPD). The
- default model (when the value is 0) is to route non-secure interrupts
- to S-EL1 (TSP).
+* `TSP_NS_INTR_ASYNC_PREEMPT`: A non zero value enables the interrupt
+ routing model which routes non-secure interrupts asynchronously from TSP
+ to EL3 causing immediate preemption of TSP. The EL3 is responsible
+ for saving and restoring the TSP context in this routing model. The
+ default routing model (when the value is 0) is to route non-secure
+ interrupts to TSP allowing it to save its context and hand over
+ synchronously to EL3 via an SMC.
* `TRUSTED_BOARD_BOOT`: Boolean flag to include support for the Trusted Board
Boot feature. When set to '1', BL1 and BL2 images include support to load
@@ -388,6 +386,12 @@
payload. Please refer to the "Booting an EL3 payload" section for more
details.
+* `PL011_GENERIC_UART`: Boolean option to indicate the PL011 driver that
+ the underlying hardware is not a full PL011 UART but a minimally compliant
+ generic UART, which is a subset of the PL011. The driver will not access
+ any register that is not part of the SBSA generic UART specification.
+ Default value is 0 (a full PL011 compliant UART is present).
+
#### ARM development platform specific build options
* `ARM_TSP_RAM_LOCATION`: location of the TSP binary. Options:
@@ -840,11 +844,11 @@
This version of the ARM Trusted Firmware has been tested on the following ARM
FVPs (64-bit versions only).
-* `Foundation_Platform` (Version 9.1, Build 9.1.33)
-* `FVP_Base_AEMv8A-AEMv8A` (Version 6.2, Build 0.8.6202)
-* `FVP_Base_Cortex-A57x4-A53x4` (Version 6.2, Build 0.8.6202)
-* `FVP_Base_Cortex-A57x1-A53x1` (Version 6.2, Build 0.8.6202)
-* `FVP_Base_Cortex-A57x2-A53x4` (Version 6.2, Build 0.8.6202)
+* `Foundation_Platform` (Version 9.4, Build 9.4.59)
+* `FVP_Base_AEMv8A-AEMv8A` (Version 7.0, Build 0.8.7004)
+* `FVP_Base_Cortex-A57x4-A53x4` (Version 7.0, Build 0.8.7004)
+* `FVP_Base_Cortex-A57x1-A53x1` (Version 7.0, Build 0.8.7004)
+* `FVP_Base_Cortex-A57x2-A53x4` (Version 7.0, Build 0.8.7004)
NOTE: The build numbers quoted above are those reported by launching the FVP
with the `--version` parameter.
@@ -854,13 +858,17 @@
NOTE: The Foundation FVP does not provide a debugger interface.
-Please refer to the FVP documentation for a detailed description of the model
-parameter options. A brief description of the important ones that affect the
-ARM Trusted Firmware and normal world software behavior is provided below.
-
The Foundation FVP is a cut down version of the AArch64 Base FVP. It can be
downloaded for free from [ARM's website][ARM FVP website].
+The Linaro release provides a script to run the software on FVP. However, it
+only supports a limited number of model parameter options. Therefore, it is
+recommended to launch the FVP manually for all use cases described below.
+
+Please refer to the FVP documentation for a detailed description of the model
+parameter options. A brief description of the important ones that affect the ARM
+Trusted Firmware and normal world software behavior is provided below.
+
### Running on the Foundation FVP with reset to BL1 entrypoint
@@ -1171,13 +1179,11 @@
This version of the ARM Trusted Firmware has been tested on Juno r0 and Juno r1.
-To execute the versions of software components on Juno referred to in this
-document, the latest Juno board recovery image must be installed. If you
-have an earlier version installed or are unsure which version is installed,
-follow the recovery image update instructions in the [Juno Software Guide]
-on the [ARM Connected Community] website. The latest Juno board recovery image
-can be obtained from [Linaro releases], see section 2.7 "Using prebuilt
-binaries".
+To execute the software stack on Juno, the version of the Juno board recovery
+image indicated in the [Linaro Release Notes] must be installed. If you have an
+earlier version installed or are unsure which version is installed, please
+re-install the recovery image by following the [Instructions for using Linaro's
+deliverables on Juno][Juno Instructions].
### Preparing Trusted Firmware images
@@ -1192,23 +1198,24 @@
FIP. Please refer to the section "Building the Trusted Firmware".
After building Trusted Firmware, the files `bl1.bin` and `fip.bin` need copying
-to the `SOFTWARE/` directory as explained in the [Juno Software Guide].
+to the `SOFTWARE/` directory of the Juno SD card.
### Other Juno software information
-Please refer to the [Juno Software Guide] to:
-
-* Install and run the Juno binaries on the board
-* Obtain any other Juno software information
+Please visit the [ARM Platforms Portal] to get support and obtain any other Juno
+software information. Please also refer to the [Juno Getting Started Guide] to
+get more detailed information about the Juno ARM development platform and how to
+configure it.
### Testing SYSTEM SUSPEND on Juno
The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend
-to RAM. For more details refer to section 5.16 of [PSCI]. The [Linaro releases]
-contains the required SCP and motherboard firmware support for this feature on
-Juno. The mainline linux kernel does not yet have support for this feature on
-Juno but it is queued to be merged in v4.4. Till that becomes available, the
-feature can be tested by using a custom kernel built from the following repo:
+to RAM. For more details refer to section 5.16 of [PSCI]. The [Linaro Release
+Notes] point to the required SCP and motherboard firmware binaries supporting
+this feature on Juno. The mainline linux kernel does not yet have support for
+this feature on Juno but it is queued to be merged in v4.4. Till that becomes
+available, the feature can be tested by using a custom kernel built from the
+following repository:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git
cd linux
@@ -1235,9 +1242,8 @@
make ARCH=arm64 Image -j8
-Replace the kernel image in `SOFTWARE/` directory of Juno with the `Image` from
-arch/arm64/boot/ of the linux directory as explained in the
-[Juno Software Guide].
+Replace the kernel image in the `SOFTWARE/` directory of the Juno SD card with
+the `Image` from `arch/arm64/boot/` of the linux directory.
Reset the board and wait for it to boot. At the shell prompt issue the
following command:
@@ -1254,10 +1260,12 @@
[Firmware Design]: firmware-design.md
-[Linaro releases]: http://releases.linaro.org/15.06/members/arm/platforms
[ARM FVP website]: http://www.arm.com/fvp
-[ARM Connected Community]: http://community.arm.com
-[Juno Software Guide]: http://community.arm.com/docs/DOC-8396
+[Linaro Release Notes]: https://community.arm.com/docs/DOC-10952#jive_content_id_Linaro_Release_1510
+[ARM Platforms Portal]: https://community.arm.com/groups/arm-development-platforms
+[Linaro SW Instructions]: https://community.arm.com/docs/DOC-10803
+[Juno Instructions]: https://community.arm.com/docs/DOC-10804
+[Juno Getting Started Guide]: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf
[DS-5]: http://www.arm.com/products/tools/software-tools/ds-5/index.php
[mbed TLS Repository]: https://github.com/ARMmbed/mbedtls.git
[mbed TLS Security Center]: https://tls.mbed.org/security
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index 6e8251d..2fb98cb 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -312,7 +312,7 @@
unsigned int index, irq_num;
uint64_t gic_affinity_val;
- assert((int_grp == INT_TYPE_G1S) || (int_grp == INT_TYPE_G0));
+ assert((int_grp == INTR_GROUP1S) || (int_grp == INTR_GROUP0));
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
assert(num_ints ? (uintptr_t)sec_intr_list : 1);
@@ -324,7 +324,7 @@
gicd_clr_igroupr(gicd_base, irq_num);
/* Configure this interrupt as G0 or a G1S interrupt */
- if (int_grp == INT_TYPE_G1S)
+ if (int_grp == INTR_GROUP1S)
gicd_set_igrpmodr(gicd_base, irq_num);
else
gicd_clr_igrpmodr(gicd_base, irq_num);
@@ -386,7 +386,7 @@
{
unsigned int index, irq_num;
- assert((int_grp == INT_TYPE_G1S) || (int_grp == INT_TYPE_G0));
+ assert((int_grp == INTR_GROUP1S) || (int_grp == INTR_GROUP0));
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
assert(num_ints ? (uintptr_t)sec_intr_list : 1);
@@ -398,7 +398,7 @@
gicr_clr_igroupr0(gicr_base, irq_num);
/* Configure this interrupt as G0 or a G1S interrupt */
- if (int_grp == INT_TYPE_G1S)
+ if (int_grp == INTR_GROUP1S)
gicr_set_igrpmodr0(gicr_base, irq_num);
else
gicr_clr_igrpmodr0(gicr_base, irq_num);
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 06311e3..d5cd0ed 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -144,13 +144,13 @@
gicv3_secure_spis_configure(driver_data->gicd_base,
driver_data->g1s_interrupt_num,
driver_data->g1s_interrupt_array,
- INT_TYPE_G1S);
+ INTR_GROUP1S);
/* Configure the G0 SPIs */
gicv3_secure_spis_configure(driver_data->gicd_base,
driver_data->g0_interrupt_num,
driver_data->g0_interrupt_array,
- INT_TYPE_G0);
+ INTR_GROUP0);
/* Enable the secure SPIs now that they have been configured */
gicd_set_ctlr(driver_data->gicd_base,
@@ -186,13 +186,13 @@
gicv3_secure_ppi_sgi_configure(gicr_base,
driver_data->g1s_interrupt_num,
driver_data->g1s_interrupt_array,
- INT_TYPE_G1S);
+ INTR_GROUP1S);
/* Configure the G0 SGIs/PPIs */
gicv3_secure_ppi_sgi_configure(gicr_base,
driver_data->g0_interrupt_num,
driver_data->g0_interrupt_array,
- INT_TYPE_G0);
+ INTR_GROUP0);
}
/*******************************************************************************
@@ -332,9 +332,9 @@
* this interrupt has been configured under by the interrupt controller i.e.
* group0 or group1 Secure / Non Secure. The return value can be one of the
* following :
- * INT_TYPE_G0 : The interrupt type is a Secure Group 0 interrupt
- * INT_TYPE_G1S : The interrupt type is a Secure Group 1 secure interrupt
- * INT_TYPE_G1NS: The interrupt type is a Secure Group 1 non secure
+ * INTR_GROUP0 : The interrupt type is a Secure Group 0 interrupt
+ * INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt
+ * INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure
* interrupt.
******************************************************************************/
unsigned int gicv3_get_interrupt_type(unsigned int id,
@@ -352,7 +352,7 @@
/* All LPI interrupts are Group 1 non secure */
if (id >= MIN_LPI_ID)
- return INT_TYPE_G1NS;
+ return INTR_GROUP1NS;
if (id < MIN_SPI_ID) {
assert(driver_data->rdistif_base_addrs);
@@ -370,12 +370,12 @@
* interrupt
*/
if (igroup)
- return INT_TYPE_G1NS;
+ return INTR_GROUP1NS;
/* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */
if (grpmodr)
- return INT_TYPE_G1S;
+ return INTR_GROUP1S;
/* Else it is a Group 0 Secure interrupt */
- return INT_TYPE_G0;
+ return INTR_GROUP0;
}
diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S
index ea41e5d..47608da 100644
--- a/drivers/arm/pl011/pl011_console.S
+++ b/drivers/arm/pl011/pl011_console.S
@@ -60,6 +60,7 @@
func console_core_init
/* Check the input base address */
cbz x0, core_init_fail
+#if !PL011_GENERIC_UART
/* Check baud rate and uart clock for sanity */
cbz w1, core_init_fail
cbz w2, core_init_fail
@@ -82,6 +83,7 @@
/* Enable tx, rx, and uart overall */
mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
str w1, [x0, #UARTCR]
+#endif
mov w0, #1
ret
core_init_fail:
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 940e00e..7194443 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -170,9 +170,6 @@
assert(base);
- /* Assert if already initialised */
- assert(!tzc.base);
-
tzc.base = base;
/*
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 79a8965..71634a1 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -89,6 +89,12 @@
AUTH_PARAM_HASH, BL32_HASH_OID);
static auth_param_type_desc_t bl33_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, BL33_HASH_OID);
+static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SCP_BL2U_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, BL2U_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, NS_BL2U_HASH_OID);
/*
* TBBR Chain of trust definition
@@ -438,6 +444,99 @@
}
}
}
+ },
+ /*
+ * FWU auth descriptor.
+ */
+ [FWU_CERT_ID] = {
+ .img_id = FWU_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &scp_bl2u_hash,
+ .data = {
+ .ptr = (void *)plat_bl30_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &bl2u_hash,
+ .data = {
+ .ptr = (void *)plat_bl2_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &ns_bl2u_hash,
+ .data = {
+ .ptr = (void *)plat_bl33_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+ },
+ /*
+ * SCP_BL2U
+ */
+ [SCP_BL2U_IMAGE_ID] = {
+ .img_id = SCP_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[FWU_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &scp_bl2u_hash,
+ }
+ }
+ }
+ },
+ /*
+ * BL2U
+ */
+ [BL2U_IMAGE_ID] = {
+ .img_id = BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[FWU_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl2u_hash,
+ }
+ }
+ }
+ },
+ /*
+ * NS_BL2U
+ */
+ [NS_BL2U_IMAGE_ID] = {
+ .img_id = NS_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[FWU_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ns_bl2u_hash,
+ }
+ }
+ }
}
};
diff --git a/drivers/console/console.S b/drivers/console/console.S
index d966f0d..40a6db9 100644
--- a/drivers/console/console.S
+++ b/drivers/console/console.S
@@ -30,6 +30,7 @@
#include <asm_macros.S>
.globl console_init
+ .globl console_uninit
.globl console_putc
.globl console_getc
@@ -66,6 +67,20 @@
ret
endfunc console_init
+ /* -----------------------------------------------
+ * void console_uninit(void)
+ * Function to finish the use of console driver.
+ * It sets the console_base as NULL so that any
+ * further invocation of `console_putc` or
+ * `console_getc` APIs would return error.
+ * -----------------------------------------------
+ */
+func console_uninit
+ mov x0, #0
+ adrp x3, console_base
+ str x0, [x3, :lo12:console_base]
+endfunc console_uninit
+
/* ---------------------------------------------
* int console_putc(int c)
* Function to output a character over the
diff --git a/include/bl1/bl1.h b/include/bl1/bl1.h
new file mode 100644
index 0000000..9fb3cb2
--- /dev/null
+++ b/include/bl1/bl1.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BL1_FWU_H__
+#define __BL1_FWU_H__
+
+#include <bl_common.h>
+
+/*
+ * Defines for BL1 SMC function ids.
+ */
+#define BL1_SMC_CALL_COUNT 0x0
+#define BL1_SMC_UID 0x1
+/* SMC #0x2 reserved */
+#define BL1_SMC_VERSION 0x3
+
+/*
+ * Corresponds to the function ID of the SMC that
+ * the BL1 exception handler service to execute BL31.
+ */
+#define BL1_SMC_RUN_IMAGE 0x4
+
+/*
+ * BL1 SMC version
+ */
+#define BL1_SMC_MAJOR_VER 0x0
+#define BL1_SMC_MINOR_VER 0x1
+
+/*
+ * Defines for FWU SMC function ids.
+ */
+
+#define FWU_SMC_IMAGE_COPY 0x10
+#define FWU_SMC_IMAGE_AUTH 0x11
+#define FWU_SMC_IMAGE_EXECUTE 0x12
+#define FWU_SMC_IMAGE_RESUME 0x13
+#define FWU_SMC_SEC_IMAGE_DONE 0x14
+#define FWU_SMC_UPDATE_DONE 0x15
+
+/*
+ * Number of FWU calls (above) implemented
+ */
+#define FWU_NUM_SMC_CALLS 6
+
+#if TRUSTED_BOARD_BOOT
+# define BL1_NUM_SMC_CALLS (FWU_NUM_SMC_CALLS + 4)
+#else
+# define BL1_NUM_SMC_CALLS 4
+#endif
+
+/*
+ * The macros below are used to identify FWU
+ * calls from the SMC function ID
+ */
+#define FWU_SMC_FID_START FWU_SMC_IMAGE_COPY
+#define FWU_SMC_FID_END FWU_SMC_UPDATE_DONE
+#define is_fwu_fid(_fid) \
+ ((_fid >= FWU_SMC_FID_START) && (_fid <= FWU_SMC_FID_END))
+
+#ifndef __ASSEMBLY__
+#include <cassert.h>
+
+/*
+ * Check if the total number of FWU SMC calls are as expected.
+ */
+CASSERT(FWU_NUM_SMC_CALLS == \
+ (FWU_SMC_FID_END - FWU_SMC_FID_START + 1),\
+ assert_FWU_NUM_SMC_CALLS_mismatch);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BL1_FWU_H__ */
diff --git a/plat/arm/css/common/css_common.c b/include/bl1/tbbr/tbbr_img_desc.h
similarity index 70%
copy from plat/arm/css/common/css_common.c
copy to include/bl1/tbbr/tbbr_img_desc.h
index 91813f2..56f3507 100644
--- a/plat/arm/css/common/css_common.c
+++ b/include/bl1/tbbr/tbbr_img_desc.h
@@ -28,37 +28,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <arm_gic.h>
-#include <bl_common.h>
-#include <platform_def.h>
-
-
-#if IMAGE_BL31 || IMAGE_BL32
+#ifndef __TBBR_IMG_DESC_H__
+#define __TBBR_IMG_DESC_H__
-const unsigned int irq_sec_array[] = {
- PLAT_CSS_IRQ_SEC_LIST,
- ARM_IRQ_SEC_PHY_TIMER,
- ARM_IRQ_SEC_SGI_0,
- ARM_IRQ_SEC_SGI_1,
- ARM_IRQ_SEC_SGI_2,
- ARM_IRQ_SEC_SGI_3,
- ARM_IRQ_SEC_SGI_4,
- ARM_IRQ_SEC_SGI_5,
- ARM_IRQ_SEC_SGI_6,
- ARM_IRQ_SEC_SGI_7
-};
-
-
-/* Weak definitions may be overridden in specific CSS based platform */
-#pragma weak plat_arm_gic_init
+#include <bl_common.h>
-void plat_arm_gic_init(void)
-{
- arm_gic_init(PLAT_CSS_GICC_BASE,
- PLAT_CSS_GICD_BASE,
- PLAT_CSS_GICR_BASE,
- irq_sec_array,
- ARRAY_SIZE(irq_sec_array));
-}
+extern image_desc_t bl1_tbbr_image_descs[];
-#endif /* IMAGE_BL31 || IMAGE_BL32 */
+#endif /* __TBBR_IMG_DESC_H__ */
diff --git a/include/bl31/interrupt_mgmt.h b/include/bl31/interrupt_mgmt.h
index e07ddf8..0172b60 100644
--- a/include/bl31/interrupt_mgmt.h
+++ b/include/bl31/interrupt_mgmt.h
@@ -63,6 +63,10 @@
#define INTR_NS_VALID_RM0 0x0
/* Routed to EL1/EL2 from NS and to EL3 from Secure */
#define INTR_NS_VALID_RM1 0x1
+/* Routed to EL3 from NS. Taken to S-EL1 from Secure and handed over to EL3 */
+#define INTR_EL3_VALID_RM0 0x2
+/* Routed to EL3 from NS and Secure */
+#define INTR_EL3_VALID_RM1 0x3
/* This is the default routing model */
#define INTR_DEFAULT_RM 0x0
@@ -87,12 +91,16 @@
* of interrupt. If the model does not match one of the valid masks
* -EINVAL is returned.
******************************************************************************/
-#define validate_sel1_interrupt_rm(x) (x == INTR_SEL1_VALID_RM0 ? 0 : \
- (x == INTR_SEL1_VALID_RM1 ? 0 :\
+#define validate_sel1_interrupt_rm(x) ((x) == INTR_SEL1_VALID_RM0 ? 0 : \
+ ((x) == INTR_SEL1_VALID_RM1 ? 0 :\
-EINVAL))
-#define validate_ns_interrupt_rm(x) (x == INTR_NS_VALID_RM0 ? 0 : \
- (x == INTR_NS_VALID_RM1 ? 0 :\
+#define validate_ns_interrupt_rm(x) ((x) == INTR_NS_VALID_RM0 ? 0 : \
+ ((x) == INTR_NS_VALID_RM1 ? 0 :\
+ -EINVAL))
+
+#define validate_el3_interrupt_rm(x) ((x) == INTR_EL3_VALID_RM0 ? 0 : \
+ ((x) == INTR_EL3_VALID_RM1 ? 0 :\
-EINVAL))
/*******************************************************************************
diff --git a/include/bl31/runtime_svc.h b/include/bl31/runtime_svc.h
index f112418..30ba29f 100644
--- a/include/bl31/runtime_svc.h
+++ b/include/bl31/runtime_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,74 +31,9 @@
#ifndef __RUNTIME_SVC_H__
#define __RUNTIME_SVC_H__
-/*******************************************************************************
- * Bit definitions inside the function id as per the SMC calling convention
- ******************************************************************************/
-#define FUNCID_TYPE_SHIFT 31
-#define FUNCID_CC_SHIFT 30
-#define FUNCID_OEN_SHIFT 24
-#define FUNCID_NUM_SHIFT 0
-
-#define FUNCID_TYPE_MASK 0x1
-#define FUNCID_CC_MASK 0x1
-#define FUNCID_OEN_MASK 0x3f
-#define FUNCID_NUM_MASK 0xffff
-
-#define FUNCID_TYPE_WIDTH 1
-#define FUNCID_CC_WIDTH 1
-#define FUNCID_OEN_WIDTH 6
-#define FUNCID_NUM_WIDTH 16
-
-#define GET_SMC_CC(id) ((id >> FUNCID_CC_SHIFT) & \
- FUNCID_CC_MASK)
-#define GET_SMC_TYPE(id) ((id >> FUNCID_TYPE_SHIFT) & \
- FUNCID_TYPE_MASK)
-
-#define SMC_64 1
-#define SMC_32 0
-#define SMC_UNK 0xffffffff
-#define SMC_TYPE_FAST 1
-#define SMC_TYPE_STD 0
-#define SMC_PREEMPTED 0xfffffffe
-/*******************************************************************************
- * Owning entity number definitions inside the function id as per the SMC
- * calling convention
- ******************************************************************************/
-#define OEN_ARM_START 0
-#define OEN_ARM_END 0
-#define OEN_CPU_START 1
-#define OEN_CPU_END 1
-#define OEN_SIP_START 2
-#define OEN_SIP_END 2
-#define OEN_OEM_START 3
-#define OEN_OEM_END 3
-#define OEN_STD_START 4 /* Standard Calls */
-#define OEN_STD_END 4
-#define OEN_TAP_START 48 /* Trusted Applications */
-#define OEN_TAP_END 49
-#define OEN_TOS_START 50 /* Trusted OS */
-#define OEN_TOS_END 63
-#define OEN_LIMIT 64
+#include <bl_common.h> /* to include exception types */
+#include <smcc_helpers.h> /* to include SMCC definitions */
-/*******************************************************************************
- * Constants to indicate type of exception to the common exception handler.
- ******************************************************************************/
-#define SYNC_EXCEPTION_SP_EL0 0x0
-#define IRQ_SP_EL0 0x1
-#define FIQ_SP_EL0 0x2
-#define SERROR_SP_EL0 0x3
-#define SYNC_EXCEPTION_SP_ELX 0x4
-#define IRQ_SP_ELX 0x5
-#define FIQ_SP_ELX 0x6
-#define SERROR_SP_ELX 0x7
-#define SYNC_EXCEPTION_AARCH64 0x8
-#define IRQ_AARCH64 0x9
-#define FIQ_AARCH64 0xa
-#define SERROR_AARCH64 0xb
-#define SYNC_EXCEPTION_AARCH32 0xc
-#define IRQ_AARCH32 0xd
-#define FIQ_AARCH32 0xe
-#define SERROR_AARCH32 0xf
/*******************************************************************************
* Structure definition, typedefs & constants for the runtime service framework
@@ -122,68 +57,9 @@
#ifndef __ASSEMBLY__
-#include <cassert.h>
-#include <context.h>
-#include <stdint.h>
-
-/* Various flags passed to SMC handlers */
-#define SMC_FROM_SECURE (0 << 0)
-#define SMC_FROM_NON_SECURE (1 << 0)
-
-#define is_caller_non_secure(_f) (!!(_f & SMC_FROM_NON_SECURE))
-#define is_caller_secure(_f) (!(is_caller_non_secure(_f)))
-
/* Prototype for runtime service initializing function */
typedef int32_t (*rt_svc_init_t)(void);
-/* Convenience macros to return from SMC handler */
-#define SMC_RET0(_h) { \
- return (uint64_t) (_h); \
-}
-#define SMC_RET1(_h, _x0) { \
- write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X0, (_x0)); \
- SMC_RET0(_h); \
-}
-#define SMC_RET2(_h, _x0, _x1) { \
- write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X1, (_x1)); \
- SMC_RET1(_h, (_x0)); \
-}
-#define SMC_RET3(_h, _x0, _x1, _x2) { \
- write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X2, (_x2)); \
- SMC_RET2(_h, (_x0), (_x1)); \
-}
-#define SMC_RET4(_h, _x0, _x1, _x2, _x3) { \
- write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X3, (_x3)); \
- SMC_RET3(_h, (_x0), (_x1), (_x2)); \
-}
-
-
-/*
- * Convenience macros to access general purpose registers using handle provided
- * to SMC handler. These takes the offset values defined in context.h
- */
-#define SMC_GET_GP(_h, _g) \
- read_ctx_reg(get_gpregs_ctx(_h), (_g));
-#define SMC_SET_GP(_h, _g, _v) \
- write_ctx_reg(get_gpregs_ctx(_h), (_g), (_v));
-
-/*
- * Convenience macros to access EL3 context registers using handle provided to
- * SMC handler. These takes the offset values defined in context.h
- */
-#define SMC_GET_EL3(_h, _e) \
- read_ctx_reg(get_el3state_ctx(_h), (_e));
-#define SMC_SET_EL3(_h, _e, _v) \
- write_ctx_reg(get_el3state_ctx(_h), (_e), (_v));
-
-/* The macro below is used to identify a Standard Service SMC call */
-#define is_std_svc_call(_fid) ((((_fid) >> FUNCID_OEN_SHIFT) & \
- FUNCID_OEN_MASK) == OEN_STD_START)
-
-/* The macro below is used to identify a valid Fast SMC call */
-#define is_valid_fast_smc(_fid) ((!(((_fid) >> 16) & 0xff)) && \
- (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST))
-
/*
* Prototype for runtime service SMC handler function. x0 (SMC Function ID) to
* x4 are as passed by the caller. Rest of the arguments to SMC and the context
@@ -247,28 +123,6 @@
((call_type & FUNCID_TYPE_MASK) \
<< FUNCID_OEN_WIDTH))
-
-/*
- * Macro to define UUID for services. Apart from defining and initializing a
- * uuid_t structure, this macro verifies that the first word of the defined UUID
- * does not equal SMC_UNK. This is to ensure that the caller won't mistake the
- * returned UUID in x0 for an invalid SMC error return
- */
-#define DEFINE_SVC_UUID(_name, _tl, _tm, _th, _cl, _ch, \
- _n0, _n1, _n2, _n3, _n4, _n5) \
- CASSERT(_tl != SMC_UNK, invalid_svc_uuid);\
- static const uuid_t _name = { \
- _tl, _tm, _th, _cl, _ch, \
- { _n0, _n1, _n2, _n3, _n4, _n5 } \
- }
-
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid) \
- SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
- ((const uint32_t *) &(_uuid))[1], \
- ((const uint32_t *) &(_uuid))[2], \
- ((const uint32_t *) &(_uuid))[3])
-
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
diff --git a/include/bl32/tsp/tsp.h b/include/bl32/tsp/tsp.h
index c6578b7..fd43fd3 100644
--- a/include/bl32/tsp/tsp.h
+++ b/include/bl32/tsp/tsp.h
@@ -45,12 +45,12 @@
#define TSP_SYSTEM_RESET_DONE 0xf2000009
/*
- * Function identifiers to handle FIQs through the synchronous handling model.
- * If the TSP was previously interrupted then control has to be returned to
- * the TSPD after handling the interrupt else execution can remain in the TSP.
+ * Function identifiers to handle S-El1 interrupt through the synchronous
+ * handling model. If the TSP was previously interrupted then control has to
+ * be returned to the TSPD after handling the interrupt else execution can
+ * remain in the TSP.
*/
-#define TSP_HANDLED_S_EL1_FIQ 0xf2000006
-#define TSP_EL3_FIQ 0xf2000007
+#define TSP_HANDLED_S_EL1_INTR 0xf2000006
/* SMC function ID that TSP uses to request service from secure monitor */
#define TSP_GET_ARGS 0xf2001000
@@ -63,7 +63,7 @@
#define TSP_SUB 0x2001
#define TSP_MUL 0x2002
#define TSP_DIV 0x2003
-#define TSP_HANDLE_FIQ_AND_RETURN 0x2004
+#define TSP_HANDLE_SEL1_INTR_AND_RETURN 0x2004
/*
* Generate function IDs for TSP services to be used in SMC calls, by
@@ -115,7 +115,7 @@
tsp_vector_isn_t cpu_off_entry;
tsp_vector_isn_t cpu_resume_entry;
tsp_vector_isn_t cpu_suspend_entry;
- tsp_vector_isn_t fiq_entry;
+ tsp_vector_isn_t sel1_intr_entry;
tsp_vector_isn_t system_off_entry;
tsp_vector_isn_t system_reset_entry;
} tsp_vectors_t;
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index c9a7a3d..b7cb95a 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -45,14 +45,6 @@
#define TOP 0x1
#define BOTTOM !TOP
-/******************************************************************************
- * Opcode passed in x0 to tell next EL that we want to run an image.
- * Corresponds to the function ID of the only SMC that the BL1 exception
- * handlers service. That's why the chosen value is the first function ID of
- * the ARM SMC64 range.
- *****************************************************************************/
-#define RUN_IMAGE 0xC0000000
-
/*******************************************************************************
* Constants that allow assembler code to access members of and the
* 'entry_point_info' structure at their correct offsets.
@@ -60,11 +52,41 @@
#define ENTRY_POINT_INFO_PC_OFFSET 0x08
#define ENTRY_POINT_INFO_ARGS_OFFSET 0x18
-#define PARAM_EP_SECURITY_MASK 0x1
+/* The following are used to set/get image attributes. */
+#define EXECUTABLE (0x1)
+#define NON_EXECUTABLE (0x0)
+#define PARAM_EP_EXECUTE_MASK (0x1)
+#define PARAM_EP_EXECUTE_SHIFT (0x1)
+#define PARAM_EP_SECURITY_MASK (0x1)
+#define PARAM_EP_SECURITY_SHIFT (0x0)
+
#define GET_SECURITY_STATE(x) (x & PARAM_EP_SECURITY_MASK)
#define SET_SECURITY_STATE(x, security) \
((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security))
+#define GET_EXEC_STATE(x) \
+ (((x) >> PARAM_EP_EXECUTE_SHIFT) & PARAM_EP_EXECUTE_MASK)
+
+#define SET_EXEC_STATE(x) \
+ (((x) & PARAM_EP_EXECUTE_MASK) << PARAM_EP_EXECUTE_SHIFT)
+
+#define GET_SEC_STATE(x) \
+ (((x) >> PARAM_EP_SECURITY_SHIFT) & PARAM_EP_SECURITY_MASK)
+
+#define SET_SEC_STATE(x) \
+ (((x) & PARAM_EP_SECURITY_MASK) << PARAM_EP_SECURITY_SHIFT)
+
+/*
+ * The following are used for image state attributes.
+ * Image can only be in one of the following state.
+ */
+#define IMAGE_STATE_RESET 0
+#define IMAGE_STATE_COPIED 1
+#define IMAGE_STATE_COPYING 2
+#define IMAGE_STATE_AUTHENTICATED 3
+#define IMAGE_STATE_EXECUTED 4
+#define IMAGE_STATE_INTERRUPTED 5
+
#define EP_EE_MASK 0x2
#define EP_EE_LITTLE 0x0
#define EP_EE_BIG 0x2
@@ -83,6 +105,8 @@
#define VERSION_1 0x01
+#define INVALID_IMAGE_ID (0xFFFFFFFF)
+
#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \
(_p)->h.type = (uint8_t)(_type); \
(_p)->h.version = (uint8_t)(_ver); \
@@ -90,6 +114,26 @@
(_p)->h.attr = (uint32_t)(_attr) ; \
} while (0)
+/*******************************************************************************
+ * Constants to indicate type of exception to the common exception handler.
+ ******************************************************************************/
+#define SYNC_EXCEPTION_SP_EL0 0x0
+#define IRQ_SP_EL0 0x1
+#define FIQ_SP_EL0 0x2
+#define SERROR_SP_EL0 0x3
+#define SYNC_EXCEPTION_SP_ELX 0x4
+#define IRQ_SP_ELX 0x5
+#define FIQ_SP_ELX 0x6
+#define SERROR_SP_ELX 0x7
+#define SYNC_EXCEPTION_AARCH64 0x8
+#define IRQ_AARCH64 0x9
+#define FIQ_AARCH64 0xa
+#define SERROR_AARCH64 0xb
+#define SYNC_EXCEPTION_AARCH32 0xc
+#define IRQ_AARCH32 0xd
+#define FIQ_AARCH32 0xe
+#define SERROR_AARCH32 0xf
+
#ifndef __ASSEMBLY__
#include <cdefs.h> /* For __dead2 */
#include <cassert.h>
@@ -106,6 +150,8 @@
extern unsigned long __RO_END__;
#if IMAGE_BL2
extern unsigned long __BL2_END__;
+#elif IMAGE_BL2U
+extern unsigned long __BL2U_END__;
#elif IMAGE_BL31
extern unsigned long __BL31_END__;
#elif IMAGE_BL32
@@ -177,8 +223,24 @@
param_header_t h;
uintptr_t image_base; /* physical address of base of image */
uint32_t image_size; /* bytes read from image file */
+ uint32_t copied_size; /* image size copied in blocks */
} image_info_t;
+/*****************************************************************************
+ * The image descriptor struct definition.
+ *****************************************************************************/
+typedef struct image_desc {
+ /* Contains unique image id for the image. */
+ unsigned int image_id;
+ image_info_t image_info;
+ entry_point_info_t ep_info;
+ /*
+ * This member contains Image state information.
+ * Refer IMAGE_STATE_XXX defined above.
+ */
+ unsigned int state;
+} image_desc_t;
+
/*******************************************************************************
* This structure represents the superset of information that can be passed to
* BL31 e.g. while passing control to it from BL2. The BL32 parameters will be
diff --git a/include/bl31/context.h b/include/common/context.h
similarity index 100%
rename from include/bl31/context.h
rename to include/common/context.h
diff --git a/include/bl31/context_mgmt.h b/include/common/context_mgmt.h
similarity index 77%
rename from include/bl31/context_mgmt.h
rename to include/common/context_mgmt.h
index 1ef4076..141b348 100644
--- a/include/bl31/context_mgmt.h
+++ b/include/common/context_mgmt.h
@@ -31,9 +31,9 @@
#ifndef __CM_H__
#define __CM_H__
+#include <arch.h>
+#include <bl_common.h>
#include <common_def.h>
-#include <cpu_data.h>
-#include <stdint.h>
/*******************************************************************************
* Forward declarations
@@ -46,7 +46,6 @@
void cm_init(void);
void *cm_get_context_by_mpidr(uint64_t mpidr,
uint32_t security_state) __warn_deprecated;
-static inline void *cm_get_context(uint32_t security_state);
void cm_set_context_by_mpidr(uint64_t mpidr,
void *context,
uint32_t security_state) __warn_deprecated;
@@ -55,7 +54,9 @@
void cm_set_context_by_index(unsigned int cpu_idx,
void *context,
unsigned int security_state);
-static inline void cm_set_context(void *context, uint32_t security_state);
+void *cm_get_context(uint32_t security_state);
+void cm_set_context(void *context, uint32_t security_state);
+inline void cm_set_next_context(void *context);
void cm_init_context(uint64_t mpidr,
const struct entry_point_info *ep) __warn_deprecated;
void cm_init_my_context(const struct entry_point_info *ep);
@@ -76,27 +77,28 @@
/* Inline definitions */
/*******************************************************************************
- * This function returns a pointer to the most recent 'cpu_context' structure
- * for the calling CPU that was set as the context for the specified security
- * state. NULL is returned if no such structure has been specified.
+ * This function is used to program the context that's used for exception
+ * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for
+ * the required security state
******************************************************************************/
-void *cm_get_context(uint32_t security_state)
+inline void cm_set_next_context(void *context)
{
- assert(security_state <= NON_SECURE);
+#if DEBUG
+ uint64_t sp_mode;
- return get_cpu_data(cpu_context[security_state]);
-}
+ /*
+ * Check that this function is called with SP_EL0 as the stack
+ * pointer
+ */
+ __asm__ volatile("mrs %0, SPSel\n"
+ : "=r" (sp_mode));
-/*******************************************************************************
- * This function sets the pointer to the current 'cpu_context' structure for the
- * specified security state for the calling CPU
- ******************************************************************************/
-void cm_set_context(void *context, uint32_t security_state)
-{
- assert(security_state <= NON_SECURE);
+ assert(sp_mode == MODE_SP_EL0);
+#endif
- set_cpu_data(cpu_context[security_state], context);
+ __asm__ volatile("msr spsel, #1\n"
+ "mov sp, %0\n"
+ "msr spsel, #0\n"
+ : : "r" (context));
}
-
-
#endif /* __CM_H__ */
diff --git a/include/common/el3_common_macros.S b/include/common/el3_common_macros.S
index 87e172e..0514e2a 100644
--- a/include/common/el3_common_macros.S
+++ b/include/common/el3_common_macros.S
@@ -247,13 +247,11 @@
#endif
.endif /* _init_c_runtime */
-#if IMAGE_BL31
/* ---------------------------------------------------------------------
* Use SP_EL0 for the C runtime stack.
* ---------------------------------------------------------------------
*/
msr spsel, #0
-#endif /* IMAGE_BL31 */
/* ---------------------------------------------------------------------
* Allocate a stack whose memory will be marked as Normal-IS-WBWA when
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
index 8fb669e..daa043a 100644
--- a/include/common/firmware_image_package.h
+++ b/include/common/firmware_image_package.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -39,6 +39,14 @@
/* ToC Entry UUIDs */
+#define UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U \
+ {0x03279265, 0x742f, 0x44e6, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} }
+#define UUID_TRUSTED_UPDATE_FIRMWARE_BL2U \
+ {0x37ebb360, 0xe5c1, 0x41ea, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} }
+#define UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U \
+ {0x111d514f, 0xe52b, 0x494e, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} }
+#define UUID_TRUSTED_FWU_CERT \
+ {0xb28a4071, 0xd618, 0x4c87, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} }
#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \
{0x0becf95f, 0x224d, 0x4d3e, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} }
#define UUID_SCP_FIRMWARE_BL30 \
diff --git a/include/common/smcc_helpers.h b/include/common/smcc_helpers.h
new file mode 100644
index 0000000..6a07b01
--- /dev/null
+++ b/include/common/smcc_helpers.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SMCC_HELPERS_H__
+#define __SMCC_HELPERS_H__
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT 31
+#define FUNCID_CC_SHIFT 30
+#define FUNCID_OEN_SHIFT 24
+#define FUNCID_NUM_SHIFT 0
+
+#define FUNCID_TYPE_MASK 0x1
+#define FUNCID_CC_MASK 0x1
+#define FUNCID_OEN_MASK 0x3f
+#define FUNCID_NUM_MASK 0xffff
+
+#define FUNCID_TYPE_WIDTH 1
+#define FUNCID_CC_WIDTH 1
+#define FUNCID_OEN_WIDTH 6
+#define FUNCID_NUM_WIDTH 16
+
+#define GET_SMC_CC(id) ((id >> FUNCID_CC_SHIFT) & \
+ FUNCID_CC_MASK)
+#define GET_SMC_TYPE(id) ((id >> FUNCID_TYPE_SHIFT) & \
+ FUNCID_TYPE_MASK)
+
+#define SMC_64 1
+#define SMC_32 0
+#define SMC_UNK 0xffffffff
+#define SMC_TYPE_FAST 1
+#define SMC_TYPE_STD 0
+#define SMC_PREEMPTED 0xfffffffe
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START 0
+#define OEN_ARM_END 0
+#define OEN_CPU_START 1
+#define OEN_CPU_END 1
+#define OEN_SIP_START 2
+#define OEN_SIP_END 2
+#define OEN_OEM_START 3
+#define OEN_OEM_END 3
+#define OEN_STD_START 4 /* Standard Calls */
+#define OEN_STD_END 4
+#define OEN_TAP_START 48 /* Trusted Applications */
+#define OEN_TAP_END 49
+#define OEN_TOS_START 50 /* Trusted OS */
+#define OEN_TOS_END 63
+#define OEN_LIMIT 64
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <context.h>
+#include <stdint.h>
+
+/* Various flags passed to SMC handlers */
+#define SMC_FROM_SECURE (0 << 0)
+#define SMC_FROM_NON_SECURE (1 << 0)
+
+#define is_caller_non_secure(_f) (!!(_f & SMC_FROM_NON_SECURE))
+#define is_caller_secure(_f) (!(is_caller_non_secure(_f)))
+
+/* Convenience macros to return from SMC handler */
+#define SMC_RET0(_h) { \
+ return (uint64_t) (_h); \
+}
+#define SMC_RET1(_h, _x0) { \
+ write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X0, (_x0)); \
+ SMC_RET0(_h); \
+}
+#define SMC_RET2(_h, _x0, _x1) { \
+ write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X1, (_x1)); \
+ SMC_RET1(_h, (_x0)); \
+}
+#define SMC_RET3(_h, _x0, _x1, _x2) { \
+ write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X2, (_x2)); \
+ SMC_RET2(_h, (_x0), (_x1)); \
+}
+#define SMC_RET4(_h, _x0, _x1, _x2, _x3) { \
+ write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X3, (_x3)); \
+ SMC_RET3(_h, (_x0), (_x1), (_x2)); \
+}
+
+/*
+ * Convenience macros to access general purpose registers using handle provided
+ * to SMC handler. These takes the offset values defined in context.h
+ */
+#define SMC_GET_GP(_h, _g) \
+ read_ctx_reg(get_gpregs_ctx(_h), (_g));
+#define SMC_SET_GP(_h, _g, _v) \
+ write_ctx_reg(get_gpregs_ctx(_h), (_g), (_v));
+
+/*
+ * Convenience macros to access EL3 context registers using handle provided to
+ * SMC handler. These takes the offset values defined in context.h
+ */
+#define SMC_GET_EL3(_h, _e) \
+ read_ctx_reg(get_el3state_ctx(_h), (_e));
+#define SMC_SET_EL3(_h, _e, _v) \
+ write_ctx_reg(get_el3state_ctx(_h), (_e), (_v));
+
+/* The macro below is used to identify a Standard Service SMC call */
+#define is_std_svc_call(_fid) ((((_fid) >> FUNCID_OEN_SHIFT) & \
+ FUNCID_OEN_MASK) == OEN_STD_START)
+
+/* The macro below is used to identify a valid Fast SMC call */
+#define is_valid_fast_smc(_fid) ((!(((_fid) >> 16) & 0xff)) && \
+ (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST))
+
+/*
+ * Macro to define UUID for services. Apart from defining and initializing a
+ * uuid_t structure, this macro verifies that the first word of the defined UUID
+ * does not equal SMC_UNK. This is to ensure that the caller won't mistake the
+ * returned UUID in x0 for an invalid SMC error return
+ */
+#define DEFINE_SVC_UUID(_name, _tl, _tm, _th, _cl, _ch, \
+ _n0, _n1, _n2, _n3, _n4, _n5) \
+ CASSERT(_tl != SMC_UNK, invalid_svc_uuid);\
+ static const uuid_t _name = { \
+ _tl, _tm, _th, _cl, _ch, \
+ { _n0, _n1, _n2, _n3, _n4, _n5 } \
+ }
+
+/* Return a UUID in the SMC return registers */
+#define SMC_UUID_RET(_h, _uuid) \
+ SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
+ ((const uint32_t *) &(_uuid))[1], \
+ ((const uint32_t *) &(_uuid))[2], \
+ ((const uint32_t *) &(_uuid))[3])
+
+#endif /*__ASSEMBLY__*/
+#endif /* __SMCC_HELPERS_H__ */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index c43c395..fabe0b9 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -63,4 +63,19 @@
#define BL32_CERT_ID 14
#define BL33_CERT_ID 15
+/* Non-Trusted ROM Firmware NS_BL1U */
+#define NS_BL1U_IMAGE_ID 16
+
+/* Trusted FWU Certificate */
+#define FWU_CERT_ID 17
+
+/* Trusted FWU SCP Firmware SCP_BL2U */
+#define SCP_BL2U_IMAGE_ID 18
+
+/* Trusted FWU Boot Firmware BL2U */
+#define BL2U_IMAGE_ID 19
+
+/* Non-Trusted FWU Firmware NS_BL2U */
+#define NS_BL2U_IMAGE_ID 20
+
#endif /* __TBBR_IMG_DEF_H__ */
diff --git a/include/drivers/arm/cci400.h b/include/drivers/arm/cci400.h
index 620221a..a5dc9a0 100644
--- a/include/drivers/arm/cci400.h
+++ b/include/drivers/arm/cci400.h
@@ -31,6 +31,14 @@
#ifndef __CCI_400_H__
#define __CCI_400_H__
+/**************************************************************
+ * THIS DRIVER IS DEPRECATED. Please use the driver in cci.h
+ **************************************************************/
+#if ERROR_DEPRECATED
+#error " The CCI-400 specific driver is deprecated."
+#endif
+
+
/* Slave interface offsets from PERIPHBASE */
#define SLAVE_IFACE4_OFFSET 0x5000
#define SLAVE_IFACE3_OFFSET 0x4000
@@ -68,6 +76,7 @@
#ifndef __ASSEMBLY__
+#include <common_def.h>
#include <stdint.h>
/* Function declarations */
@@ -83,10 +92,10 @@
*/
void cci_init(uintptr_t cci_base,
int slave_iface3_cluster_ix,
- int slave_iface4_cluster_ix);
+ int slave_iface4_cluster_ix) __warn_deprecated;
-void cci_enable_cluster_coherency(unsigned long mpidr);
-void cci_disable_cluster_coherency(unsigned long mpidr);
+void cci_enable_cluster_coherency(unsigned long mpidr) __warn_deprecated;
+void cci_disable_cluster_coherency(unsigned long mpidr) __warn_deprecated;
#endif /* __ASSEMBLY__ */
#endif /* __CCI_400_H__ */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index e874f5c..ae6fd91 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -35,9 +35,9 @@
* GICv3 miscellaneous definitions
******************************************************************************/
/* Interrupt group definitions */
-#define INT_TYPE_G1S 0
-#define INT_TYPE_G0 1
-#define INT_TYPE_G1NS 2
+#define INTR_GROUP1S 0
+#define INTR_GROUP0 1
+#define INTR_GROUP1NS 2
/* Interrupt IDs reported by the HPPIR and IAR registers */
#define PENDING_G1S_INTID 1020
diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h
index 7c4df62..d5ea890 100644
--- a/include/drivers/arm/pl011.h
+++ b/include/drivers/arm/pl011.h
@@ -36,17 +36,21 @@
#define UARTRSR 0x004
#define UARTECR 0x004
#define UARTFR 0x018
+#define UARTIMSC 0x038
+#define UARTRIS 0x03C
+#define UARTICR 0x044
+
+/* PL011 registers (out of the SBSA specification) */
+#if !PL011_GENERIC_UART
#define UARTILPR 0x020
#define UARTIBRD 0x024
#define UARTFBRD 0x028
#define UARTLCR_H 0x02C
#define UARTCR 0x030
#define UARTIFLS 0x034
-#define UARTIMSC 0x038
-#define UARTRIS 0x03C
#define UARTMIS 0x040
-#define UARTICR 0x044
#define UARTDMACR 0x048
+#endif /* !PL011_GENERIC_UART */
/* Data status bits */
#define UART_DATA_ERROR_MASK 0x0F00
@@ -69,6 +73,7 @@
#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */
/* Control reg bits */
+#if !PL011_GENERIC_UART
#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */
#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */
#define PL011_UARTCR_RTS (1 << 11) /* Request to send */
@@ -95,4 +100,6 @@
#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */
#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */
+#endif /* !PL011_GENERIC_UART */
+
#endif /* __PL011_H__ */
diff --git a/include/drivers/console.h b/include/drivers/console.h
index d374157..69ad0bd 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -35,6 +35,7 @@
int console_init(uintptr_t base_addr,
unsigned int uart_clk, unsigned int baud_rate);
+void console_uninit(void);
int console_putc(int c);
int console_getc(void);
diff --git a/include/drivers/delay_timer.h b/include/drivers/delay_timer.h
index 4f3bdc8..0dec626 100644
--- a/include/drivers/delay_timer.h
+++ b/include/drivers/delay_timer.h
@@ -38,7 +38,7 @@
* The driver must be initialized with a structure that provides a
* function pointer to return the timer value and a clock
* multiplier/divider. The ratio of the multiplier and the divider is
- * the clock frequency in MHz.
+ * the clock period in microseconds.
********************************************************************/
typedef struct timer_ops {
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 43c6917..067b830 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -270,6 +270,8 @@
DEFINE_SYSREG_RW_FUNCS(ttbr1_el1)
+DEFINE_SYSREG_RW_FUNCS(vttbr_el2)
+
DEFINE_SYSREG_RW_FUNCS(cptr_el2)
DEFINE_SYSREG_RW_FUNCS(cptr_el3)
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 3abf235..b4e4313 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -53,6 +53,8 @@
# else
# define PLATFORM_STACK_SIZE 0x400
# endif
+#elif IMAGE_BL2U
+# define PLATFORM_STACK_SIZE 0x200
#elif IMAGE_BL31
# define PLATFORM_STACK_SIZE 0x400
#elif IMAGE_BL32
@@ -65,10 +67,18 @@
*/
#if IMAGE_BL1
# if PLAT_fvp
-# define PLAT_ARM_MMAP_ENTRIES 7
+# if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MMAP_ENTRIES 8
+# else
+# define PLAT_ARM_MMAP_ENTRIES 7
+# endif /* TRUSTED_BOARD_BOOT */
# else
-# define PLAT_ARM_MMAP_ENTRIES 6
-# endif
+# if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MMAP_ENTRIES 7
+# else
+# define PLAT_ARM_MMAP_ENTRIES 6
+# endif /* TRUSTED_BOARD_BOOT */
+# endif /* PLAT_ */
#endif
#if IMAGE_BL2
# if PLAT_fvp
@@ -77,6 +87,13 @@
# define PLAT_ARM_MMAP_ENTRIES 8
# endif
#endif
+#if IMAGE_BL2U
+# if PLAT_fvp
+# define PLAT_ARM_MMAP_ENTRIES 3
+# else
+# define PLAT_ARM_MMAP_ENTRIES 4
+#endif
+#endif
#if IMAGE_BL31
#define PLAT_ARM_MMAP_ENTRIES 5
#endif
@@ -88,12 +105,22 @@
* Platform specific page table and MMU setup constants
*/
#if IMAGE_BL1
-# if PLAT_juno
-# define MAX_XLAT_TABLES 2
+# if TRUSTED_BOARD_BOOT
+# define MAX_XLAT_TABLES 4
# else
+# if PLAT_juno
+# define MAX_XLAT_TABLES 2
+# else
+# define MAX_XLAT_TABLES 3
+# endif /* PLAT_ */
+# endif /* TRUSTED_BOARD_BOOT */
+#elif IMAGE_BL2
+# if PLAT_juno
# define MAX_XLAT_TABLES 3
+# else
+# define MAX_XLAT_TABLES 4
# endif /* PLAT_ */
-#elif IMAGE_BL2
+#elif IMAGE_BL2U
# if PLAT_juno
# define MAX_XLAT_TABLES 3
# else
diff --git a/include/plat/arm/board/common/board_css_def.h b/include/plat/arm/board/common/board_css_def.h
index 2e32b41..975f1fc 100644
--- a/include/plat/arm/board/common/board_css_def.h
+++ b/include/plat/arm/board/common/board_css_def.h
@@ -74,8 +74,11 @@
#define PLAT_ARM_BOOT_UART_BASE SOC_CSS_UART0_BASE
#define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART0_CLK_IN_HZ
-#define PLAT_ARM_CRASH_UART_BASE SOC_CSS_UART1_BASE
-#define PLAT_ARM_CRASH_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ
+#define PLAT_ARM_BL31_RUN_UART_BASE SOC_CSS_UART1_BASE
+#define PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ
#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART0_BASE
#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index 7ed0af6..888792e 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -112,6 +112,13 @@
#define V2M_SP804_TIMER0_BASE 0x1C110000
#define V2M_SP804_TIMER1_BASE 0x1C120000
+/* SP810 controller */
+#define V2M_SP810_BASE 0x1c020000
+#define V2M_SP810_CTRL_TIM0_SEL (1 << 15)
+#define V2M_SP810_CTRL_TIM1_SEL (1 << 17)
+#define V2M_SP810_CTRL_TIM2_SEL (1 << 19)
+#define V2M_SP810_CTRL_TIM3_SEL (1 << 21)
+
#define V2M_MAP_FLASH0_RW MAP_REGION_FLAT(V2M_FLASH0_BASE,\
V2M_FLASH0_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
diff --git a/include/plat/arm/common/aarch64/arm_macros.S b/include/plat/arm/common/aarch64/arm_macros.S
index 594b096..eaaa62f 100644
--- a/include/plat/arm/common/aarch64/arm_macros.S
+++ b/include/plat/arm/common/aarch64/arm_macros.S
@@ -31,12 +31,21 @@
#define __ARM_MACROS_S__
#include <cci.h>
-#include <gic_v2.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <gicv3.h>
#include <platform_def.h>
.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
gicc_regs:
.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
gicd_pend_reg:
.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
" Offset:\t\t\tvalue\n"
@@ -54,6 +63,28 @@
* ---------------------------------------------
*/
.macro arm_print_gic_regs
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
/* Load the gicc reg list to x6 */
adr x6, gicc_regs
/* Load the gicc regs to gp regs used by str_in_crash_buf_print */
@@ -63,6 +94,7 @@
/* Store to the crash buf and print to console */
bl str_in_crash_buf_print
+print_gic_common:
/* Print the GICD_ISPENDR regs */
add x7, x16, #GICD_ISPENDR
adr x4, gicd_pend_reg
diff --git a/include/plat/arm/common/arm_config.h b/include/plat/arm/common/arm_config.h
index 0b16127..24c1f0a 100644
--- a/include/plat/arm/common/arm_config.h
+++ b/include/plat/arm/common/arm_config.h
@@ -42,12 +42,6 @@
};
typedef struct arm_config {
- uintptr_t gicd_base;
- uintptr_t gicc_base;
- uintptr_t gich_base;
- uintptr_t gicv_base;
- unsigned int max_aff0;
- unsigned int max_aff1;
unsigned long flags;
} arm_config_t;
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 4726d5e..4a50c1c 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -135,6 +135,22 @@
#define ARM_IRQ_SEC_SGI_6 14
#define ARM_IRQ_SEC_SGI_7 15
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define ARM_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER, \
+ ARM_IRQ_SEC_SGI_1, \
+ ARM_IRQ_SEC_SGI_2, \
+ ARM_IRQ_SEC_SGI_3, \
+ ARM_IRQ_SEC_SGI_4, \
+ ARM_IRQ_SEC_SGI_5, \
+ ARM_IRQ_SEC_SGI_7
+
+#define ARM_G0_IRQS ARM_IRQ_SEC_SGI_0, \
+ ARM_IRQ_SEC_SGI_6
+
#define ARM_SHARED_RAM_ATTR ((PLAT_ARM_SHARED_RAM_CACHED ? \
MT_MEMORY : MT_DEVICE) \
| MT_RW | MT_SECURE)
@@ -294,6 +310,14 @@
# error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
#endif
+/*******************************************************************************
+ * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
+ ******************************************************************************/
+#define BL2U_BASE BL2_BASE
+#define BL2U_LIMIT BL31_BASE
+#define NS_BL2U_BASE ARM_NS_DRAM1_BASE
+#define NS_BL1U_BASE (V2M_FLASH0_BASE + 0x03EB8000)
+
/*
* ID of the secure physical generic timer interrupt used by the TSP.
*/
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index aadf58d..32c062d 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -37,7 +37,6 @@
#include <stdint.h>
#include <xlat_tables.h>
-
/*
* Extern declarations common to ARM standard platforms
*/
@@ -166,20 +165,33 @@
uint32_t arm_get_spsr_for_bl32_entry(void);
uint32_t arm_get_spsr_for_bl33_entry(void);
+/* BL2U utility functions */
+void arm_bl2u_early_platform_setup(struct meminfo *mem_layout,
+ void *plat_info);
+void arm_bl2u_platform_setup(void);
+void arm_bl2u_plat_arch_setup(void);
+
/* BL3-1 utility functions */
void arm_bl31_early_platform_setup(bl31_params_t *from_bl2,
void *plat_params_from_bl2);
void arm_bl31_platform_setup(void);
+void arm_bl31_plat_runtime_setup(void);
void arm_bl31_plat_arch_setup(void);
/* TSP utility functions */
void arm_tsp_early_platform_setup(void);
+/* FIP TOC validity check */
+int arm_io_is_toc_valid(void);
/*
* Mandatory functions required in ARM standard platforms
*/
+void plat_arm_gic_driver_init(void);
void plat_arm_gic_init(void);
+void plat_arm_gic_cpuif_enable(void);
+void plat_arm_gic_cpuif_disable(void);
+void plat_arm_gic_pcpu_init(void);
void plat_arm_security_setup(void);
void plat_arm_pwrc_setup(void);
diff --git a/include/plat/arm/css/common/aarch64/css_macros.S b/include/plat/arm/css/common/aarch64/css_macros.S
index 2a26eb7..9f18e09 100644
--- a/include/plat/arm/css/common/aarch64/css_macros.S
+++ b/include/plat/arm/css/common/aarch64/css_macros.S
@@ -41,8 +41,8 @@
* ---------------------------------------------
*/
.macro plat_print_gic_regs
- mov_imm x16, PLAT_CSS_GICD_BASE
- mov_imm x17, PLAT_CSS_GICC_BASE
+ mov_imm x16, PLAT_ARM_GICD_BASE
+ mov_imm x17, PLAT_ARM_GICC_BASE
arm_print_gic_regs
.endm
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index 98b69cb..3fa4c15 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -50,6 +50,10 @@
#define NSRAM_BASE 0x2e000000
#define NSRAM_SIZE 0x00008000
+/* System Security Control Registers */
+#define SSC_REG_BASE 0x2a420000
+#define SSC_GPRETN (SSC_REG_BASE + 0x030)
+
/* The slave_bootsecure controls access to GPU, DMC and CS. */
#define CSS_NIC400_SLAVE_BOOTSECURE 8
@@ -61,6 +65,16 @@
#define CSS_IRQ_SEC_SYS_TIMER 91
/*
+ * Define a list of Group 1 Secure interrupts as per GICv3 terminology. On a
+ * GICv2 system or mode, the interrupts will be treated as Group 0 interrupts.
+ */
+#define CSS_G1S_IRQS CSS_IRQ_MHU, \
+ CSS_IRQ_GPU_SMMU_0, \
+ CSS_IRQ_TZC, \
+ CSS_IRQ_TZ_WDOG, \
+ CSS_IRQ_SEC_SYS_TIMER
+
+/*
* SCP <=> AP boot configuration
*
* The SCP/AP boot configuration is a 32-bit word located at a known offset from
@@ -102,6 +116,8 @@
*/
#define BL30_BASE BL31_BASE
+#define SCP_BL2U_BASE BL31_BASE
+
#define PLAT_ARM_SHARED_RAM_CACHED MHU_PAYLOAD_CACHED
/* Load address of Non-Secure Image for CSS platform ports */
diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h
index 43c69cc..4175b14 100644
--- a/include/plat/common/common_def.h
+++ b/include/plat/common/common_def.h
@@ -30,6 +30,9 @@
#ifndef __COMMON_DEF_H__
#define __COMMON_DEF_H__
+#include <bl_common.h>
+#include <platform_def.h>
+
/******************************************************************************
* Required platform porting definitions that are expected to be common to
* all platforms
@@ -74,5 +77,14 @@
*/
#define __warn_deprecated __attribute__ ((deprecated))
+#define BL2_IMAGE_DESC { \
+ .image_id = BL2_IMAGE_ID, \
+ .image_info.h.version = VERSION_1, \
+ .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),\
+ .image_info.image_base = BL2_BASE, \
+ .ep_info.h.attr = SET_SEC_STATE(SECURE), \
+ .ep_info.pc = BL2_BASE \
+}
+
#endif /* __COMMON_DEF_H__ */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index de9848b..b3213b8 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -43,6 +43,7 @@
struct image_info;
struct entry_point_info;
struct bl31_params;
+struct image_desc;
/*******************************************************************************
* plat_get_rotpk_info() flags
@@ -92,11 +93,11 @@
struct meminfo *bl1_plat_sec_mem_layout(void);
/*
- * This function allows the platform to change the entrypoint information for
- * BL2, after BL1 has loaded BL2 into memory but before BL2 is executed.
+ * The following function is mandatory when the
+ * firmware update feature is used.
*/
-void bl1_plat_set_bl2_ep_info(struct image_info *image,
- struct entry_point_info *ep);
+int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size,
+ unsigned int flags);
/*******************************************************************************
* Optional BL1 functions (may be overridden)
@@ -104,6 +105,25 @@
void bl1_init_bl2_mem_layout(const struct meminfo *bl1_mem_layout,
struct meminfo *bl2_mem_layout);
+/*
+ * The following functions are used for image loading process in BL1.
+ */
+void bl1_plat_set_ep_info(unsigned int image_id,
+ struct entry_point_info *ep_info);
+/*
+ * The following functions are mandatory when firmware update
+ * feature is used and optional otherwise.
+ */
+unsigned int bl1_plat_get_next_image_id(void);
+struct image_desc *bl1_plat_get_image_desc(unsigned int image_id);
+
+/*
+ * The following functions are used by firmware update
+ * feature and may optionally be overridden.
+ */
+__dead2 void bl1_plat_fwu_done(void *cookie, void *reserved);
+
+
/*******************************************************************************
* Mandatory BL2 functions
******************************************************************************/
@@ -173,12 +193,30 @@
******************************************************************************/
/*******************************************************************************
+ * Mandatory BL2U functions.
+ ******************************************************************************/
+void bl2u_early_platform_setup(struct meminfo *mem_layout,
+ void *plat_info);
+void bl2u_plat_arch_setup(void);
+void bl2u_platform_setup(void);
+
+/*******************************************************************************
+ * Conditionally mandatory BL2U functions for CSS platforms.
+ ******************************************************************************/
+/*
+ * This function is used to perform any platform-specific actions required to
+ * handle the BL2U_SCP firmware.
+ */
+int bl2u_plat_handle_scp_bl2u(void);
+
+/*******************************************************************************
* Mandatory BL3-1 functions
******************************************************************************/
void bl31_early_platform_setup(struct bl31_params *from_bl2,
void *plat_params_from_bl2);
void bl31_plat_arch_setup(void);
void bl31_platform_setup(void);
+void bl31_plat_runtime_setup(void);
struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type);
/*******************************************************************************
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 9ab6e64..08cb4b1 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -28,6 +28,22 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+# This table is used in converting lower case to upper case.
+uppercase_table:=a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z
+
+# Internal macro used for converting lower case to upper case.
+# $(1) = upper case table
+# $(2) = String to convert
+define uppercase_internal
+$(if $(1),$$(subst $(firstword $(1)),$(call uppercase_internal,$(wordlist 2,$(words $(1)),$(1)),$(2))),$(2))
+endef
+
+# A macro for converting a string to upper case
+# $(1) = String to convert
+define uppercase
+$(eval uppercase_result:=$(call uppercase_internal,$(uppercase_table),$(1)))$(uppercase_result)
+endef
+
# Convenience function for adding build definitions
# $(eval $(call add_define,FOO)) will have:
# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise
@@ -82,7 +98,7 @@
$(eval $(if $(3),FIP_DEPS += $(3)))
endef
-# CERT_ADD_CMD_OPT adds a new command line option to the cert_create invokation
+# CERT_ADD_CMD_OPT adds a new command line option to the cert_create invocation
# $(1) = parameter filename
# $(2) = cert_create command line option for the specified parameter
# $(3) = input parameter (false if empty)
@@ -107,6 +123,38 @@
$$(if $(value $(1)),,$$(error "Platform '${PLAT}' requires $(1). Please set $(1) to point to the right file"))
endef
+# FWU_FIP_ADD_PAYLOAD appends the command line arguments required by the FIP tool
+# to package a new FWU payload. Optionally, it adds the dependency on this payload
+# $(1) = payload filename (e.g. ns_bl2u.bin)
+# $(2) = command line option for the specified payload (e.g. --ns_bl2u)
+# $(3) = fip target dependency (optional) (e.g. ns_bl2u)
+define FWU_FIP_ADD_PAYLOAD
+ $(eval $(if $(3),FWU_FIP_DEPS += $(3)))
+ $(eval FWU_FIP_ARGS += $(2) $(1))
+endef
+
+# FWU_CERT_ADD_CMD_OPT adds a new command line option to the cert_create invocation
+# $(1) = parameter filename
+# $(2) = cert_create command line option for the specified parameter
+# $(3) = input parameter (false if empty)
+define FWU_CERT_ADD_CMD_OPT
+ $(eval $(if $(3),FWU_CRT_DEPS += $(1)))
+ $(eval FWU_CRT_ARGS += $(2) $(1))
+endef
+
+# FWU_FIP_ADD_IMG allows the platform to pack a binary image in the FWU FIP
+# $(1) build option to specify the image filename (BL2U, NS_BL2U, etc)
+# $(2) command line option for the fip_create tool (bl2u, ns_bl2u, etc)
+# Example:
+# $(eval $(call FWU_FIP_ADD_IMG,BL2U,--bl2u))
+define FWU_FIP_ADD_IMG
+ FWU_CRT_DEPS += check_$(1)
+ FWU_FIP_DEPS += check_$(1)
+ $(call FWU_FIP_ADD_PAYLOAD,$(value $(1)),$(2))
+
+check_$(1):
+ $$(if $(value $(1)),,$$(error "Platform '${PLAT}' requires $(1). Please set $(1) to point to the right file"))
+endef
################################################################################
# Auxiliary macros to build TF images from sources
@@ -123,7 +171,7 @@
endef
# List of rules that involve building things
-BUILD_TARGETS := all bl1 bl2 bl31 bl32 certificates fip
+BUILD_TARGETS := all bl1 bl2 bl2u bl31 bl32 certificates fip
# Does the list of goals specified on the command line include a build target?
ifneq ($(call match_goals,${BUILD_TARGETS}),)
@@ -134,15 +182,16 @@
# MAKE_C builds a C source file and generates the dependency file
# $(1) = output directory
# $(2) = source file (%.c)
-# $(3) = BL stage (2, 30, 31, 32, 33)
+# $(3) = BL stage (2, 2u, 30, 31, 32, 33)
define MAKE_C
$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
$(eval PREREQUISITES := $(patsubst %.o,%.d,$(OBJ)))
+$(eval IMAGE := IMAGE_BL$(call uppercase,$(3)))
$(OBJ): $(2)
@echo " CC $$<"
- $$(Q)$$(CC) $$(CFLAGS) -DIMAGE_BL$(3) -c $$< -o $$@
+ $$(Q)$$(CC) $$(CFLAGS) -D$(IMAGE) -c $$< -o $$@
$(PREREQUISITES): $(2)
@@ -160,15 +209,16 @@
# MAKE_S builds an assembly source file and generates the dependency file
# $(1) = output directory
# $(2) = assembly file (%.S)
-# $(3) = BL stage (2, 30, 31, 32, 33)
+# $(3) = BL stage (2, 2u, 30, 31, 32, 33)
define MAKE_S
$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
$(eval PREREQUISITES := $(patsubst %.o,%.d,$(OBJ)))
+$(eval IMAGE := IMAGE_BL$(call uppercase,$(3)))
$(OBJ): $(2)
@echo " AS $$<"
- $$(Q)$$(AS) $$(ASFLAGS) -DIMAGE_BL$(3) -c $$< -o $$@
+ $$(Q)$$(AS) $$(ASFLAGS) -D$(IMAGE) -c $$< -o $$@
$(PREREQUISITES): $(2)
@echo " DEPS $$@"
@@ -243,20 +293,22 @@
# MAKE_BL macro defines the targets and options to build each BL image.
# Arguments:
-# $(1) = BL stage (2, 30, 31, 32, 33)
+# $(1) = BL stage (2, 2u, 30, 31, 32, 33)
# $(2) = In FIP (false if empty)
define MAKE_BL
$(eval BUILD_DIR := ${BUILD_PLAT}/bl$(1))
- $(eval SOURCES := $(BL$(1)_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES))
+ $(eval BL_SOURCES := $(BL$(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)))
$(eval MAPFILE := $(call IMG_MAPFILE,$(1)))
$(eval ELF := $(call IMG_ELF,$(1)))
$(eval DUMP := $(call IMG_DUMP,$(1)))
$(eval BIN := $(call IMG_BIN,$(1)))
+ $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
- $(eval $(call MAKE_LD,$(LINKERFILE),$(BL$(1)_LINKERFILE)))
+ $(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
$(BUILD_DIR):
$$(Q)mkdir -p "$$@"
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 2ec72b9..bf0d296 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -56,16 +56,22 @@
# Certificate generation tool default parameters
TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt
+FWU_CERT := ${BUILD_PLAT}/fwu_cert.crt
# Add Trusted Key certificate to the fip_create and cert_create command line options
$(eval $(call FIP_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert))
$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_KEY_CERT},--trusted-key-cert))
+# Add fwu certificate to the fip_create and cert_create command line options
+$(eval $(call FWU_FIP_ADD_PAYLOAD,${FWU_CERT},--fwu-cert))
+$(eval $(call FWU_CERT_ADD_CMD_OPT,${FWU_CERT},--fwu-cert))
+
# Add the keys to the cert_create command line options (private keys are NOT
# packed in the FIP). Developers can use their own keys by specifying the proper
# build option in the command line when building the Trusted Firmware
$(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg)))
$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key)))
+$(if ${ROT_KEY},$(eval $(call FWU_CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key)))
$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key)))
$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key)))
@@ -114,3 +120,17 @@
$(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/bl33.crt,--bl33-cert))
$(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/bl33_key.crt,--bl33-key-cert))
endif
+
+# Add the BL2U image
+$(if ${BL2U},$(eval $(call FWU_CERT_ADD_CMD_OPT,${BL2U},--bl2u,true)),\
+ $(eval $(call FWU_CERT_ADD_CMD_OPT,$(call IMG_BIN,2u),--bl2u,true)))
+
+# Add the SCP_BL2U image
+ifneq (${SCP_BL2U},)
+ $(eval $(call FWU_CERT_ADD_CMD_OPT,${SCP_BL2U},--scp_bl2u,true))
+endif
+
+# Add the NS_BL2U image
+ifneq (${NS_BL2U},)
+ $(eval $(call FWU_CERT_ADD_CMD_OPT,${NS_BL2U},--ns_bl2u,true))
+endif
diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c
index 7bf0273..62253f8 100644
--- a/plat/arm/board/common/board_css_common.c
+++ b/plat/arm/board/common/board_css_common.c
@@ -42,6 +42,9 @@
V2M_MAP_IOFPGA,
CSS_MAP_DEVICE,
SOC_CSS_MAP_DEVICE,
+#if TRUSTED_BOARD_BOOT
+ ARM_MAP_NS_DRAM1,
+#endif
{0}
};
#endif
@@ -57,6 +60,14 @@
{0}
};
#endif
+#if IMAGE_BL2U
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ CSS_MAP_DEVICE,
+ SOC_CSS_MAP_DEVICE,
+ {0}
+};
+#endif
#if IMAGE_BL31
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
diff --git a/plat/arm/board/fvp/aarch64/fvp_common.c b/plat/arm/board/fvp/aarch64/fvp_common.c
index 8771e5b..305505d 100644
--- a/plat/arm/board/fvp/aarch64/fvp_common.c
+++ b/plat/arm/board/fvp/aarch64/fvp_common.c
@@ -30,14 +30,23 @@
#include <arm_config.h>
#include <arm_def.h>
-#include <arm_gic.h>
#include <cci.h>
#include <debug.h>
+#include <gicv2.h>
#include <mmio.h>
#include <plat_arm.h>
#include <v2m_def.h>
#include "../fvp_def.h"
+#if (FVP_USE_GIC_DRIVER == FVP_GICV2)
+extern gicv2_driver_data_t arm_gic_data;
+#endif
+
+/* Defines for GIC Driver build time selection */
+#define FVP_GICV2 1
+#define FVP_GICV3 2
+#define FVP_GICV3_LEGACY 3
+
/*******************************************************************************
* arm_config holds the characteristics of the differences between the three FVP
* platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
@@ -73,6 +82,9 @@
MAP_DEVICE0,
MAP_DEVICE1,
MAP_DEVICE2,
+#if TRUSTED_BOARD_BOOT
+ ARM_MAP_NS_DRAM1,
+#endif
{0}
};
#endif
@@ -89,6 +101,13 @@
{0}
};
#endif
+#if IMAGE_BL2U
+const mmap_region_t plat_arm_mmap[] = {
+ MAP_DEVICE0,
+ V2M_MAP_IOFPGA,
+ {0}
+};
+#endif
#if IMAGE_BL31
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
@@ -110,33 +129,6 @@
ARM_CASSERT_MMAP
-#if IMAGE_BL31 || IMAGE_BL32
-/* Array of secure interrupts to be configured by the gic driver */
-const unsigned int irq_sec_array[] = {
- ARM_IRQ_SEC_PHY_TIMER,
- ARM_IRQ_SEC_SGI_0,
- ARM_IRQ_SEC_SGI_1,
- ARM_IRQ_SEC_SGI_2,
- ARM_IRQ_SEC_SGI_3,
- ARM_IRQ_SEC_SGI_4,
- ARM_IRQ_SEC_SGI_5,
- ARM_IRQ_SEC_SGI_6,
- ARM_IRQ_SEC_SGI_7,
- FVP_IRQ_TZ_WDOG,
- FVP_IRQ_SEC_SYS_TIMER
-};
-
-void plat_arm_gic_init(void)
-{
- arm_gic_init(arm_config.gicc_base,
- arm_config.gicd_base,
- BASE_GICR_BASE,
- irq_sec_array,
- ARRAY_SIZE(irq_sec_array));
-}
-
-#endif
-
/*******************************************************************************
* A single boot loader stack is expected to work on both the Foundation FVP
* models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
@@ -165,16 +157,28 @@
*/
switch (bld) {
case BLD_GIC_VE_MMAP:
- arm_config.gicd_base = VE_GICD_BASE;
- arm_config.gicc_base = VE_GICC_BASE;
- arm_config.gich_base = VE_GICH_BASE;
- arm_config.gicv_base = VE_GICV_BASE;
+#if IMAGE_BL31 || IMAGE_BL32
+#if FVP_USE_GIC_DRIVER == FVP_GICV2
+ /*
+ * If the FVP implements the VE compatible memory map, then the
+ * GICv2 driver must be included in the build. Update the platform
+ * data with the correct GICv2 base addresses before it is used
+ * to initialise the driver.
+ *
+ * This update of platform data is temporary and will be removed
+ * once VE memory map for FVP is no longer supported by Trusted
+ * Firmware.
+ */
+ arm_gic_data.gicd_base = VE_GICD_BASE;
+ arm_gic_data.gicc_base = VE_GICC_BASE;
+
+#else
+ ERROR("Only GICv2 driver supported for VE memory map\n");
+ panic();
+#endif /* __FVP_USE_GIC_DRIVER == FVP_GICV2__ */
+#endif /* __IMAGE_BL31 || IMAGE_BL32__ */
break;
case BLD_GIC_A53A57_MMAP:
- arm_config.gicd_base = BASE_GICD_BASE;
- arm_config.gicc_base = BASE_GICC_BASE;
- arm_config.gich_base = BASE_GICH_BASE;
- arm_config.gicv_base = BASE_GICV_BASE;
break;
default:
ERROR("Unsupported board build %x\n", bld);
@@ -187,8 +191,6 @@
*/
switch (hbi) {
case HBI_FOUNDATION_FVP:
- arm_config.max_aff0 = 4;
- arm_config.max_aff1 = 1;
arm_config.flags = 0;
/*
@@ -206,8 +208,6 @@
}
break;
case HBI_BASE_FVP:
- arm_config.max_aff0 = 4;
- arm_config.max_aff1 = 2;
arm_config.flags |= ARM_CONFIG_BASE_MMAP |
ARM_CONFIG_HAS_CCI | ARM_CONFIG_HAS_TZC;
diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S
index 2c24e61..338d158 100644
--- a/plat/arm/board/fvp/aarch64/fvp_helpers.S
+++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S
@@ -30,7 +30,8 @@
#include <arch.h>
#include <asm_macros.S>
-#include <gic_v2.h>
+#include <gicv2.h>
+#include <gicv3.h>
#include <platform_def.h>
#include <v2m_def.h>
#include "../drivers/pwrc/fvp_pwrc.h"
@@ -74,9 +75,26 @@
str w0, [x1, #PPOFFR_OFF]
/* ---------------------------------------------
- * Deactivate the gic cpu interface as well
+ * Disable GIC bypass as well
* ---------------------------------------------
*/
+ /* Check for GICv3 system register access */
+ mrs x0, id_aa64pfr0_el1
+ ubfx x0, x0, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x0, #1
+ b.ne gicv2_bypass_disable
+
+ /* Check for SRE enable */
+ mrs x1, ICC_SRE_EL3
+ tst x1, #ICC_SRE_SRE_BIT
+ b.eq gicv2_bypass_disable
+
+ mrs x2, ICC_SRE_EL3
+ orr x2, x2, #(ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT)
+ msr ICC_SRE_EL3, x2
+ b secondary_cold_boot_wait
+
+gicv2_bypass_disable:
ldr x0, =VE_GICC_BASE
ldr x1, =BASE_GICC_BASE
fvp_choose_gicmmap x0, x1, x2, w2, x1
@@ -84,6 +102,7 @@
orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
str w0, [x1, #GICC_CTLR]
+secondary_cold_boot_wait:
/* ---------------------------------------------
* There is no sane reason to come out of this
* wfi so panic if we do. This cpu will be pow-
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index 33712d1..91bc9c4 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -29,6 +29,7 @@
*/
#include <plat_arm.h>
+#include <tbbr_img_def.h>
#include "fvp_private.h"
@@ -52,3 +53,16 @@
*/
fvp_cci_enable();
}
+
+/*******************************************************************************
+ * The following function checks if Firmware update is needed,
+ * by checking if TOC in FIP image is valid or not.
+ ******************************************************************************/
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ if (!arm_io_is_toc_valid())
+ return NS_BL1U_IMAGE_ID;
+
+ return BL2_IMAGE_ID;
+}
+
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index b1cdef4..305309a 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -28,6 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <mmio.h>
#include <plat_arm.h>
#include <sp804_delay_timer.h>
#include <v2m_def.h>
@@ -47,6 +48,10 @@
{
arm_bl2_platform_setup();
+ /* Enable the clock override for SP804 timer 0, which means that no
+ * clock dividers are applied and the raw (35 MHz) clock will be used */
+ mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
+
/* Initialize delay timer driver using SP804 dual timer 0 */
sp804_timer_init(V2M_SP804_TIMER0_BASE,
SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
diff --git a/plat/arm/css/common/css_common.c b/plat/arm/board/fvp/fvp_bl2u_setup.c
similarity index 66%
copy from plat/arm/css/common/css_common.c
copy to plat/arm/board/fvp/fvp_bl2u_setup.c
index 91813f2..b26f0e0 100644
--- a/plat/arm/css/common/css_common.c
+++ b/plat/arm/board/fvp/fvp_bl2u_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,37 +28,14 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <arm_gic.h>
-#include <bl_common.h>
-#include <platform_def.h>
+#include <plat_arm.h>
+#include "fvp_def.h"
+#include "fvp_private.h"
-
-#if IMAGE_BL31 || IMAGE_BL32
-
-const unsigned int irq_sec_array[] = {
- PLAT_CSS_IRQ_SEC_LIST,
- ARM_IRQ_SEC_PHY_TIMER,
- ARM_IRQ_SEC_SGI_0,
- ARM_IRQ_SEC_SGI_1,
- ARM_IRQ_SEC_SGI_2,
- ARM_IRQ_SEC_SGI_3,
- ARM_IRQ_SEC_SGI_4,
- ARM_IRQ_SEC_SGI_5,
- ARM_IRQ_SEC_SGI_6,
- ARM_IRQ_SEC_SGI_7
-};
-
-
-/* Weak definitions may be overridden in specific CSS based platform */
-#pragma weak plat_arm_gic_init
-
-void plat_arm_gic_init(void)
+void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
{
- arm_gic_init(PLAT_CSS_GICC_BASE,
- PLAT_CSS_GICD_BASE,
- PLAT_CSS_GICR_BASE,
- irq_sec_array,
- ARRAY_SIZE(irq_sec_array));
-}
+ arm_bl2u_early_platform_setup(mem_layout, plat_info);
-#endif /* IMAGE_BL31 || IMAGE_BL32 */
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+}
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index 3af4db6..41b872a 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -96,8 +96,14 @@
#define PWRC_BASE 0x1c100000
/* FVP SP804 timer frequency is 35 MHz*/
-#define SP804_TIMER_CLKMULT 35
-#define SP804_TIMER_CLKDIV 1
+#define SP804_TIMER_CLKMULT 1
+#define SP804_TIMER_CLKDIV 35
+
+/* SP810 controller. FVP specific flags */
+#define FVP_SP810_CTRL_TIM0_OV (1 << 16)
+#define FVP_SP810_CTRL_TIM1_OV (1 << 18)
+#define FVP_SP810_CTRL_TIM2_OV (1 << 20)
+#define FVP_SP810_CTRL_TIM3_OV (1 << 22)
/*******************************************************************************
* GIC-400 & interrupt handling related constants
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 21ad14f..c5129a6 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -30,7 +30,6 @@
#include <arch_helpers.h>
#include <arm_config.h>
-#include <arm_gic.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
@@ -72,7 +71,7 @@
static void fvp_cpu_pwrdwn_common(void)
{
/* Prevent interrupts from spuriously waking up this cpu */
- arm_gic_cpuif_deactivate();
+ plat_arm_gic_cpuif_disable();
/* Program the power controller to power off this cpu. */
fvp_pwrc_write_ppoffr(read_mpidr_el1());
@@ -93,6 +92,42 @@
fvp_pwrc_write_pcoffr(mpidr);
}
+static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr;
+
+ assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
+ ARM_LOCAL_STATE_OFF);
+
+ /* Get the mpidr for this cpu */
+ mpidr = read_mpidr_el1();
+
+ /* Perform the common cluster specific operations */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
+ ARM_LOCAL_STATE_OFF) {
+ /*
+ * This CPU might have woken up whilst the cluster was
+ * attempting to power down. In this case the FVP power
+ * controller will have a pending cluster power off request
+ * which needs to be cleared by writing to the PPONR register.
+ * This prevents the power controller from interpreting a
+ * subsequent entry of this cpu into a simple wfi as a power
+ * down request.
+ */
+ fvp_pwrc_write_pponr(mpidr);
+
+ /* Enable coherency if this cluster was off */
+ fvp_cci_enable();
+ }
+
+ /*
+ * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
+ * with a cpu power down unless the bit is set again
+ */
+ fvp_pwrc_clr_wen(mpidr);
+}
+
+
/*******************************************************************************
* FVP handler called when a CPU is about to enter standby.
******************************************************************************/
@@ -196,43 +231,13 @@
******************************************************************************/
void fvp_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
- unsigned long mpidr;
-
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
- /* Get the mpidr for this cpu */
- mpidr = read_mpidr_el1();
-
- /* Perform the common cluster specific operations */
- if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
- ARM_LOCAL_STATE_OFF) {
- /*
- * This CPU might have woken up whilst the cluster was
- * attempting to power down. In this case the FVP power
- * controller will have a pending cluster power off request
- * which needs to be cleared by writing to the PPONR register.
- * This prevents the power controller from interpreting a
- * subsequent entry of this cpu into a simple wfi as a power
- * down request.
- */
- fvp_pwrc_write_pponr(mpidr);
-
- /* Enable coherency if this cluster was off */
- fvp_cci_enable();
- }
-
- /*
- * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
- * with a cpu power down unless the bit is set again
- */
- fvp_pwrc_clr_wen(mpidr);
+ fvp_power_domain_on_finish_common(target_state);
/* Enable the gic cpu interface */
- arm_gic_cpuif_setup();
+ plat_arm_gic_pcpu_init();
- /* TODO: This setup is needed only after a cold boot */
- arm_gic_pcpu_distif_setup();
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_arm_gic_cpuif_enable();
}
/*******************************************************************************
@@ -251,7 +256,10 @@
ARM_LOCAL_STATE_RET)
return;
- fvp_pwr_domain_on_finish(target_state);
+ fvp_power_domain_on_finish_common(target_state);
+
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
}
/*******************************************************************************
diff --git a/plat/arm/board/fvp/include/plat_macros.S b/plat/arm/board/fvp/include/plat_macros.S
index 2feffbe..2ed0d85 100644
--- a/plat/arm/board/fvp/include/plat_macros.S
+++ b/plat/arm/board/fvp/include/plat_macros.S
@@ -53,16 +53,14 @@
/* Check if VE mmap */
cmp w16, #BLD_GIC_VE_MMAP
b.eq use_ve_mmap
- /* Check if Cortex-A53/A57 mmap */
- cmp w16, #BLD_GIC_A53A57_MMAP
- b.ne exit_print_gic_regs
+ /* Assume Base Cortex mmap */
mov_imm x17, BASE_GICC_BASE
mov_imm x16, BASE_GICD_BASE
- b print_gicc_regs
+ b print_gic_regs
use_ve_mmap:
mov_imm x17, VE_GICC_BASE
mov_imm x16, VE_GICD_BASE
-print_gicc_regs:
+print_gic_regs:
arm_print_gic_regs
.endm
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 9ada6b2..e93418d 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -78,8 +78,11 @@
#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE
#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
-#define PLAT_ARM_CRASH_UART_BASE V2M_IOFPGA_UART1_BASE
-#define PLAT_ARM_CRASH_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+#define PLAT_ARM_BL31_RUN_UART_BASE V2M_IOFPGA_UART1_BASE
+#define PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ
#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE
#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ
@@ -121,5 +124,24 @@
TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) | \
TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD))
+/*
+ * GIC related constants to cater for both GICv2 and GICv3 instances of an
+ * FVP. They could be overriden at runtime in case the FVP implements the legacy
+ * VE memory map.
+ */
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICR_BASE BASE_GICR_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \
+ FVP_IRQ_TZ_WDOG, \
+ FVP_IRQ_SEC_SYS_TIMER
+
+#define PLAT_ARM_G0_IRQS ARM_G0_IRQS
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c46d3b7..cb5f5d7 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -28,6 +28,35 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+# Use the Legacy GICv3 driver on the FVP by default to maintain compatibility.
+FVP_USE_GIC_DRIVER := FVP_GICV3_LEGACY
+
+# The FVP platform depends on this macro to build with correct GIC driver.
+$(eval $(call add_define,FVP_USE_GIC_DRIVER))
+
+# Choose the GIC sources depending upon the how the FVP will be invoked
+ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
+FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v3/gicv3_main.c \
+ drivers/arm/gic/v3/gicv3_helpers.c \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c
+else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
+FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3_LEGACY)
+FVP_GIC_SOURCES := drivers/arm/gic/arm_gic.c \
+ drivers/arm/gic/gic_v2.c \
+ drivers/arm/gic/gic_v3.c \
+ plat/common/plat_gic.c \
+ plat/arm/common/arm_gicv3_legacy.c
+else
+$(error "Incorrect GIC driver chosen on FVP port")
+endif
+
PLAT_INCLUDES := -Iplat/arm/board/fvp/include
@@ -54,6 +83,9 @@
plat/arm/board/fvp/fvp_io_storage.c \
plat/arm/board/fvp/fvp_security.c
+BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \
+ plat/arm/board/fvp/fvp_security.c
+
BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \
@@ -62,7 +94,8 @@
plat/arm/board/fvp/fvp_security.c \
plat/arm/board/fvp/fvp_topology.c \
plat/arm/board/fvp/aarch64/fvp_helpers.S \
- plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c
+ plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c \
+ ${FVP_GIC_SOURCES}
# Disable the PSCI platform compatibility layer
ENABLE_PLAT_COMPAT := 0
diff --git a/plat/arm/board/fvp/tsp/tsp-fvp.mk b/plat/arm/board/fvp/tsp/tsp-fvp.mk
index 99db2f4..54a76fd 100644
--- a/plat/arm/board/fvp/tsp/tsp-fvp.mk
+++ b/plat/arm/board/fvp/tsp/tsp-fvp.mk
@@ -31,6 +31,7 @@
# TSP source files specific to FVP platform
BL32_SOURCES += plat/arm/board/fvp/fvp_topology.c \
plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c \
- plat/arm/board/fvp/tsp/fvp_tsp_setup.c
+ plat/arm/board/fvp/tsp/fvp_tsp_setup.c \
+ ${FVP_GIC_SOURCES}
include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 39283c5..924eb0a 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -94,17 +94,18 @@
*/
/* GIC related constants (no GICR in GIC-400) */
-#define PLAT_CSS_GICD_BASE 0x2c010000
-#define PLAT_CSS_GICR_BASE 0x0
-#define PLAT_CSS_GICC_BASE 0x2c02f000
-#define PLAT_CSS_GICH_BASE 0x2c04f000
-#define PLAT_CSS_GICV_BASE 0x2c06f000
+#define PLAT_ARM_GICD_BASE 0x2c010000
+#define PLAT_ARM_GICC_BASE 0x2c02f000
+#define PLAT_ARM_GICH_BASE 0x2c04f000
+#define PLAT_ARM_GICV_BASE 0x2c06f000
-#define PLAT_CSS_IRQ_SEC_LIST CSS_IRQ_MHU, \
- CSS_IRQ_GPU_SMMU_0, \
- CSS_IRQ_TZC, \
- CSS_IRQ_TZ_WDOG, \
- CSS_IRQ_SEC_SYS_TIMER, \
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQS CSS_G1S_IRQS, \
+ ARM_G1S_IRQS, \
JUNO_IRQ_DMA_SMMU, \
JUNO_IRQ_HDLCD0_SMMU, \
JUNO_IRQ_HDLCD1_SMMU, \
@@ -114,6 +115,8 @@
JUNO_IRQ_GPU_SMMU_1, \
JUNO_IRQ_ETR_SMMU
+#define PLAT_ARM_G0_IRQS ARM_G0_IRQS
+
/*
* Required ARM CSS SoC based platform porting definitions
*/
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
new file mode 100644
index 0000000..61a5738
--- /dev/null
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <errno.h>
+#include <platform.h>
+#include <plat_arm.h>
+#include <tbbr_img_def.h>
+#include <v2m_def.h>
+
+#define RESET_REASON_WDOG_RESET (0x2)
+
+/*******************************************************************************
+ * The following function checks if Firmware update is needed,
+ * by checking if TOC in FIP image is valid or watchdog reset happened.
+ ******************************************************************************/
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ unsigned int *reset_flags_ptr = (unsigned int *)SSC_GPRETN;
+ unsigned int *nv_flags_ptr = (unsigned int *)
+ (V2M_SYSREGS_BASE + V2M_SYS_NVFLAGS);
+ /*
+ * Check if TOC is invalid or watchdog reset happened.
+ */
+ if ((arm_io_is_toc_valid() != 1) ||
+ ((*reset_flags_ptr & RESET_REASON_WDOG_RESET) &&
+ ((*nv_flags_ptr == -EAUTH) || (*nv_flags_ptr == -ENOENT))))
+ return NS_BL1U_IMAGE_ID;
+
+ return BL2_IMAGE_ID;
+}
+
+/*******************************************************************************
+ * On JUNO update the arg2 with address of SCP_BL2U image info.
+ ******************************************************************************/
+void bl1_plat_set_ep_info(unsigned int image_id,
+ entry_point_info_t *ep_info)
+{
+ if (image_id == BL2U_IMAGE_ID) {
+ image_desc_t *image_desc = bl1_plat_get_image_desc(SCP_BL2U_IMAGE_ID);
+ ep_info->args.arg2 = (unsigned long)&image_desc->image_info;
+ }
+}
+
+/*******************************************************************************
+ * On Juno clear SYS_NVFLAGS and wait for watchdog reset.
+ ******************************************************************************/
+__dead2 void bl1_plat_fwu_done(void *cookie, void *rsvd_ptr)
+{
+ unsigned int *nv_flags_clr = (unsigned int *)
+ (V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR);
+ unsigned int *nv_flags_ptr = (unsigned int *)
+ (V2M_SYSREGS_BASE + V2M_SYS_NVFLAGS);
+
+ /* Clear the NV flags register. */
+ *nv_flags_clr = *nv_flags_ptr;
+
+ while (1)
+ wfi();
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 127dcbe..fae30e7 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -28,6 +28,12 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+JUNO_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
PLAT_INCLUDES := -Iplat/arm/board/juno/include
PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/aarch64/juno_helpers.S
@@ -35,16 +41,20 @@
BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
+ plat/arm/board/juno/juno_bl1_setup.c \
plat/arm/board/juno/juno_err.c
BL2_SOURCES += plat/arm/board/juno/juno_security.c \
plat/arm/board/juno/juno_err.c
+BL2U_SOURCES += plat/arm/board/juno/juno_security.c
+
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
plat/arm/board/juno/juno_pm.c \
- plat/arm/board/juno/juno_security.c
+ plat/arm/board/juno/juno_security.c \
+ ${JUNO_GIC_SOURCES}
# Enable workarounds for selected Cortex-A57 erratas.
ERRATA_A57_806969 := 0
diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk
index bb67012..2ef964e 100644
--- a/plat/arm/board/juno/tsp/tsp-juno.mk
+++ b/plat/arm/board/juno/tsp/tsp-juno.mk
@@ -28,6 +28,7 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-BL32_SOURCES += plat/arm/css/common/css_topology.c
+BL32_SOURCES += plat/arm/css/common/css_topology.c \
+ ${JUNO_GIC_SOURCES}
include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/common/arm_bl1_fwu.c b/plat/arm/common/arm_bl1_fwu.c
new file mode 100644
index 0000000..9a0d93a
--- /dev/null
+++ b/plat/arm/common/arm_bl1_fwu.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <plat_arm.h>
+#include <tbbr_img_desc.h>
+
+
+/* Struct to keep track of usable memory */
+typedef struct bl1_mem_info{
+ uintptr_t mem_base;
+ unsigned int mem_size;
+} bl1_mem_info_t;
+
+bl1_mem_info_t fwu_addr_map_secure[] = {
+ {
+ .mem_base = ARM_SHARED_RAM_BASE,
+ .mem_size = ARM_SHARED_RAM_SIZE
+ },
+ {
+ .mem_size = 0
+ }
+};
+
+bl1_mem_info_t fwu_addr_map_non_secure[] = {
+ {
+ .mem_base = ARM_NS_DRAM1_BASE,
+ .mem_size = ARM_NS_DRAM1_SIZE
+ },
+ {
+ .mem_base = V2M_FLASH0_BASE,
+ .mem_size = V2M_FLASH0_SIZE
+ },
+ {
+ .mem_size = 0
+ }
+};
+
+int bl1_plat_mem_check(uintptr_t mem_base,
+ unsigned int mem_size,
+ unsigned int flags)
+{
+ unsigned int index = 0;
+ bl1_mem_info_t *mmap;
+
+ assert(mem_base);
+ assert(mem_size);
+
+ /*
+ * Check the given image source and size.
+ */
+ if (GET_SEC_STATE(flags) == SECURE)
+ mmap = fwu_addr_map_secure;
+ else
+ mmap = fwu_addr_map_non_secure;
+
+ while (mmap[index].mem_size) {
+ if ((mem_base >= mmap[index].mem_base) &&
+ ((mem_base + mem_size)
+ <= (mmap[index].mem_base +
+ mmap[index].mem_size)))
+ return 0;
+
+ index++;
+ }
+
+ return -ENOMEM;
+}
+
+/*******************************************************************************
+ * This function does linear search for image_id and returns image_desc.
+ ******************************************************************************/
+image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ unsigned int index = 0;
+
+ while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) {
+ if (bl1_tbbr_image_descs[index].image_id == image_id)
+ return &bl1_tbbr_image_descs[index];
+ index++;
+ }
+
+ return NULL;
+}
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 79c7d94..d0a4c0b 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -57,7 +57,6 @@
#pragma weak bl1_plat_arch_setup
#pragma weak bl1_platform_setup
#pragma weak bl1_plat_sec_mem_layout
-#pragma weak bl1_plat_set_bl2_ep_info
/* Data structure which holds the extents of the trusted SRAM for BL1*/
@@ -169,16 +168,3 @@
sev();
#endif
}
-
-/*******************************************************************************
- * Before calling this function BL2 is loaded in memory and its entrypoint
- * is set by load_image. This is a placeholder for the platform to change
- * the entrypoint of BL2 and set SPSR and security state.
- * On ARM standard platforms we only set the security state of the entrypoint
- ******************************************************************************/
-void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image,
- entry_point_info_t *bl2_ep)
-{
- SET_SECURITY_STATE(bl2_ep->h.attr, SECURE);
- bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
-}
diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c
new file mode 100644
index 0000000..5b7354b
--- /dev/null
+++ b/plat/arm/common/arm_bl2u_setup.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_def.h>
+#include <bl_common.h>
+#include <console.h>
+#include <platform_def.h>
+#include <plat_arm.h>
+#include <string.h>
+
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL2U_RO_BASE (unsigned long)(&__RO_START__)
+#define BL2U_RO_LIMIT (unsigned long)(&__RO_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL2U_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL2U_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak bl2u_platform_setup
+#pragma weak bl2u_early_platform_setup
+#pragma weak bl2u_plat_arch_setup
+
+/*
+ * Perform ARM standard platform setup for BL2U
+ */
+void arm_bl2u_platform_setup(void)
+{
+ /* Initialize the secure environment */
+ plat_arm_security_setup();
+}
+
+void bl2u_platform_setup(void)
+{
+ arm_bl2u_platform_setup();
+}
+
+void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+{
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE);
+}
+
+/*******************************************************************************
+ * BL1 can pass platform dependent information to BL2U in x1.
+ * In case of ARM CSS platforms x1 contains SCP_BL2U image info.
+ * In case of ARM FVP platforms x1 is not used.
+ * In both cases, x0 contains the extents of the memory available to BL2U
+ ******************************************************************************/
+void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+{
+ arm_bl2u_early_platform_setup(mem_layout, plat_info);
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ * The memory that is used by BL2U is only mapped.
+ ******************************************************************************/
+void arm_bl2u_plat_arch_setup(void)
+{
+ arm_configure_mmu_el1(BL2U_RO_LIMIT,
+ BL31_LIMIT,
+ BL2U_RO_BASE,
+ BL2U_RO_LIMIT
+#if USE_COHERENT_MEM
+ ,
+ BL2U_COHERENT_RAM_BASE,
+ BL2U_COHERENT_RAM_LIMIT
+#endif
+ );
+}
+
+void bl2u_plat_arch_setup(void)
+{
+ arm_bl2u_plat_arch_setup();
+}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 8682fd1..a7c2f7d 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -31,7 +31,6 @@
#include <arch.h>
#include <arch_helpers.h>
#include <arm_def.h>
-#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <cci.h>
@@ -200,9 +199,9 @@
******************************************************************************/
void arm_bl31_platform_setup(void)
{
- /* Initialize the gic cpu and distributor interfaces */
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_arm_gic_driver_init();
plat_arm_gic_init();
- arm_gic_setup();
#if RESET_TO_BL31
/*
@@ -224,11 +223,27 @@
plat_arm_pwrc_setup();
}
+/*******************************************************************************
+ * Perform any BL3-1 platform runtime setup prior to BL3-1 exit common to ARM
+ * standard platforms
+ ******************************************************************************/
+void arm_bl31_plat_runtime_setup(void)
+{
+ /* Initialize the runtime console */
+ console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE);
+}
+
void bl31_platform_setup(void)
{
arm_bl31_platform_setup();
}
+void bl31_plat_runtime_setup(void)
+{
+ arm_bl31_plat_runtime_setup();
+}
+
/*******************************************************************************
* Perform the very early platform specific architectural setup here. At the
* moment this is only intializes the mmu in a quick and dirty way.
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 1290cef..4ac12d9 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -106,17 +106,18 @@
plat/arm/common/arm_security.c \
plat/common/aarch64/platform_up_stack.S
+BL2U_SOURCES += drivers/arm/tzc400/tzc400.c \
+ plat/arm/common/arm_bl2u_setup.c \
+ plat/arm/common/arm_security.c \
+ plat/common/aarch64/platform_up_stack.S
+
BL31_SOURCES += drivers/arm/cci/cci.c \
drivers/arm/ccn/ccn.c \
- drivers/arm/gic/arm_gic.c \
- drivers/arm/gic/gic_v2.c \
- drivers/arm/gic/gic_v3.c \
drivers/arm/tzc400/tzc400.c \
plat/arm/common/arm_bl31_setup.c \
plat/arm/common/arm_pm.c \
plat/arm/common/arm_security.c \
plat/arm/common/arm_topology.c \
- plat/common/plat_gic.c \
plat/common/aarch64/platform_mp_stack.S \
plat/common/aarch64/plat_psci_common.c
@@ -127,13 +128,20 @@
# Include common TBB sources
AUTH_SOURCES := drivers/auth/auth_mod.c \
- drivers/auth/crypto_mod.c \
- drivers/auth/img_parser_mod.c \
- drivers/auth/tbbr/tbbr_cot.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot.c \
- BL1_SOURCES += ${AUTH_SOURCES}
+ PLAT_INCLUDES += -Iinclude/bl1/tbbr
+
+ BL1_SOURCES += ${AUTH_SOURCES} \
+ bl1/tbbr/tbbr_img_desc.c \
+ plat/arm/common/arm_bl1_fwu.c
+
BL2_SOURCES += ${AUTH_SOURCES}
+ $(eval $(call FWU_FIP_ADD_IMG,NS_BL2U,--ns_bl2u))
+
MBEDTLS_KEY_ALG := ${KEY_ALG}
# We expect to locate the *.mk files under the directories specified below
diff --git a/plat/arm/common/arm_gicv2.c b/plat/arm/common/arm_gicv2.c
new file mode 100644
index 0000000..76f04cd
--- /dev/null
+++ b/plat/arm/common/arm_gicv2.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <gicv2.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv2 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_gic_driver_init
+#pragma weak plat_arm_gic_init
+#pragma weak plat_arm_gic_cpuif_enable
+#pragma weak plat_arm_gic_cpuif_disable
+#pragma weak plat_arm_gic_pcpu_init
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+const unsigned int g0_interrupt_array[] = {
+ PLAT_ARM_G1S_IRQS,
+ PLAT_ARM_G0_IRQS
+};
+
+/*
+ * Ideally `arm_gic_data` structure definition should be a `const` but it is
+ * kept as modifiable for overwriting with different GICD and GICC base when
+ * running on FVP with VE memory map.
+ */
+gicv2_driver_data_t arm_gic_data = {
+ .gicd_base = PLAT_ARM_GICD_BASE,
+ .gicc_base = PLAT_ARM_GICC_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+};
+
+/******************************************************************************
+ * ARM common helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void plat_arm_gic_driver_init(void)
+{
+ gicv2_driver_init(&arm_gic_data);
+}
+
+void plat_arm_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * ARM common helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * ARM common helper to disable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_disable(void)
+{
+ gicv2_cpuif_disable();
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the per cpu distributor interface in GICv2
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+}
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
new file mode 100644
index 0000000..33f8018
--- /dev/null
+++ b/plat/arm/common/arm_gicv3.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arm_def.h>
+#include <gicv3.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_gic_driver_init
+#pragma weak plat_arm_gic_init
+#pragma weak plat_arm_gic_cpuif_enable
+#pragma weak plat_arm_gic_cpuif_disable
+#pragma weak plat_arm_gic_pcpu_init
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Array of Group1 secure interrupts to be configured by the gic driver */
+const unsigned int g1s_interrupt_array[] = {
+ PLAT_ARM_G1S_IRQS
+};
+
+/* Array of Group0 interrupts to be configured by the gic driver */
+const unsigned int g0_interrupt_array[] = {
+ PLAT_ARM_G0_IRQS
+};
+
+const gicv3_driver_data_t arm_gic_data = {
+ .gicd_base = PLAT_ARM_GICD_BASE,
+ .gicr_base = PLAT_ARM_GICR_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+ .g1s_interrupt_array = g1s_interrupt_array,
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = plat_arm_calc_core_pos
+};
+
+void plat_arm_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&arm_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the GIC. Only invoked by BL31
+ *****************************************************************************/
+void plat_arm_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the per-cpu redistributor interface in GICv3
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/arm/common/arm_gicv3_legacy.c b/plat/arm/common/arm_gicv3_legacy.c
new file mode 100644
index 0000000..6170933
--- /dev/null
+++ b/plat/arm/common/arm_gicv3_legacy.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arm_def.h>
+#include <arm_gic.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following function is defined as weak to allow a platform to override
+ * the way the Legacy GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_gic_driver_init
+#pragma weak plat_arm_gic_init
+#pragma weak plat_arm_gic_cpuif_enable
+#pragma weak plat_arm_gic_cpuif_disable
+#pragma weak plat_arm_gic_pcpu_init
+
+/*
+ * In the GICv3 Legacy mode, the Group 1 secure interrupts are treated as Group
+ * 0 interrupts.
+ */
+const unsigned int irq_sec_array[] = {
+ PLAT_ARM_G0_IRQS,
+ PLAT_ARM_G1S_IRQS
+};
+
+void plat_arm_gic_driver_init(void)
+{
+ arm_gic_init(PLAT_ARM_GICC_BASE,
+ PLAT_ARM_GICD_BASE,
+ PLAT_ARM_GICR_BASE,
+ irq_sec_array,
+ ARRAY_SIZE(irq_sec_array));
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the GIC.
+ *****************************************************************************/
+void plat_arm_gic_init(void)
+{
+ arm_gic_setup();
+}
+
+/******************************************************************************
+ * ARM common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_enable(void)
+{
+ arm_gic_cpuif_setup();
+}
+
+/******************************************************************************
+ * ARM common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_disable(void)
+{
+ arm_gic_cpuif_deactivate();
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the per-cpu distributor in GICv2 or
+ * redistributor interface in GICv3.
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+ arm_gic_pcpu_distif_setup();
+}
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index ae67cde..f7e99e9 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -308,3 +308,17 @@
return result;
}
+
+/*
+ * See if a Firmware Image Package is available,
+ * by checking if TOC is valid or not.
+ */
+int arm_io_is_toc_valid(void)
+{
+ int result;
+
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+
+ return (result == 0);
+}
+
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index cae6597..2ddc583 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -158,15 +158,19 @@
*****************************************************************************/
void arm_system_pwr_domain_resume(void)
{
- console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+ console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
ARM_CONSOLE_BAUDRATE);
/* Assert system power domain is available on the platform */
assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
- arm_gic_setup();
+ /*
+ * TODO: On GICv3 systems, figure out whether the core that wakes up
+ * first from system suspend need to initialize the re-distributor
+ * interface of all the other suspended cores.
+ */
+ plat_arm_gic_init();
plat_arm_security_setup();
-
arm_configure_sys_timer();
}
diff --git a/plat/arm/common/tsp/arm_tsp.mk b/plat/arm/common/tsp/arm_tsp.mk
index f285f58..691a2ab 100644
--- a/plat/arm/common/tsp/arm_tsp.mk
+++ b/plat/arm/common/tsp/arm_tsp.mk
@@ -29,9 +29,6 @@
#
# TSP source files common to ARM standard platforms
-BL32_SOURCES += drivers/arm/gic/arm_gic.c \
- drivers/arm/gic/gic_v2.c \
- plat/arm/common/arm_topology.c \
+BL32_SOURCES += plat/arm/common/arm_topology.c \
plat/arm/common/tsp/arm_tsp_setup.c \
- plat/common/aarch64/platform_mp_stack.S \
- plat/common/plat_gic.c
+ plat/common/aarch64/platform_mp_stack.S
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index 78db160..3631c03 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -89,7 +89,7 @@
******************************************************************************/
void tsp_platform_setup(void)
{
- plat_arm_gic_init();
+ plat_arm_gic_driver_init();
}
/*******************************************************************************
diff --git a/plat/arm/css/common/css_common.c b/plat/arm/css/common/css_bl1_setup.c
similarity index 71%
rename from plat/arm/css/common/css_common.c
rename to plat/arm/css/common/css_bl1_setup.c
index 91813f2..2abed3b 100644
--- a/plat/arm/css/common/css_common.c
+++ b/plat/arm/css/common/css_bl1_setup.c
@@ -28,37 +28,18 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <arm_gic.h>
#include <bl_common.h>
-#include <platform_def.h>
+#include <debug.h>
+#include <plat_arm.h>
+#include <soc_css.h>
-
-#if IMAGE_BL31 || IMAGE_BL32
-
-const unsigned int irq_sec_array[] = {
- PLAT_CSS_IRQ_SEC_LIST,
- ARM_IRQ_SEC_PHY_TIMER,
- ARM_IRQ_SEC_SGI_0,
- ARM_IRQ_SEC_SGI_1,
- ARM_IRQ_SEC_SGI_2,
- ARM_IRQ_SEC_SGI_3,
- ARM_IRQ_SEC_SGI_4,
- ARM_IRQ_SEC_SGI_5,
- ARM_IRQ_SEC_SGI_6,
- ARM_IRQ_SEC_SGI_7
-};
-
-
-/* Weak definitions may be overridden in specific CSS based platform */
-#pragma weak plat_arm_gic_init
-
-void plat_arm_gic_init(void)
+void bl1_platform_setup(void)
{
- arm_gic_init(PLAT_CSS_GICC_BASE,
- PLAT_CSS_GICD_BASE,
- PLAT_CSS_GICR_BASE,
- irq_sec_array,
- ARRAY_SIZE(irq_sec_array));
+ arm_bl1_platform_setup();
+ /*
+ * Do ARM CSS SoC security setup.
+ * BL1 needs to enable normal world access to memory.
+ */
+ soc_css_security_setup();
}
-#endif /* IMAGE_BL31 || IMAGE_BL32 */
diff --git a/plat/arm/css/common/css_bl2u_setup.c b/plat/arm/css/common/css_bl2u_setup.c
new file mode 100644
index 0000000..878b6fa
--- /dev/null
+++ b/plat/arm/css/common/css_bl2u_setup.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <debug.h>
+#include <plat_arm.h>
+#include "css_scp_bootloader.h"
+
+/* Weak definition may be overridden in specific CSS based platform */
+#pragma weak bl2u_plat_handle_scp_bl2u
+
+/* Data structure which holds the SCP_BL2U image info for BL2U */
+static image_info_t scp_bl2u_image_info;
+
+/*******************************************************************************
+ * BL1 can pass platform dependent information to BL2U in x1.
+ * In case of ARM CSS platforms x1 contains SCP_BL2U image info.
+ * In case of ARM FVP platforms x1 is not used.
+ * In both cases, x0 contains the extents of the memory available to BL2U
+ ******************************************************************************/
+void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+{
+ if (!plat_info)
+ panic();
+
+ arm_bl2u_early_platform_setup(mem_layout, plat_info);
+
+ scp_bl2u_image_info = *(image_info_t *)plat_info;
+}
+
+/*******************************************************************************
+ * Transfer SCP_BL2U from Trusted RAM using the SCP Download protocol.
+ ******************************************************************************/
+int bl2u_plat_handle_scp_bl2u(void)
+{
+ int ret;
+
+ INFO("BL2U: Initiating SCP_BL2U transfer to SCP\n");
+
+ ret = scp_bootloader_transfer((void *)scp_bl2u_image_info.image_base,
+ scp_bl2u_image_info.image_size);
+
+ if (ret == 0)
+ INFO("BL2U: SCP_BL2U transferred to SCP\n");
+ else
+ ERROR("BL2U: SCP_BL2U transfer failure\n");
+
+ return ret;
+}
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 6b05869..49fedc3 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -32,21 +32,28 @@
-Iinclude/plat/arm/css/common/aarch64
-PLAT_BL_COMMON_SOURCES += plat/arm/css/common/aarch64/css_helpers.S \
- plat/arm/css/common/css_common.c
+PLAT_BL_COMMON_SOURCES += plat/arm/css/common/aarch64/css_helpers.S
-#BL1_SOURCES +=
+BL1_SOURCES += plat/arm/css/common/css_bl1_setup.c
BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c \
plat/arm/css/common/css_mhu.c \
plat/arm/css/common/css_scp_bootloader.c \
plat/arm/css/common/css_scpi.c
+BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c \
+ plat/arm/css/common/css_mhu.c \
+ plat/arm/css/common/css_scp_bootloader.c \
+ plat/arm/css/common/css_scpi.c
+
BL31_SOURCES += plat/arm/css/common/css_mhu.c \
plat/arm/css/common/css_pm.c \
plat/arm/css/common/css_scpi.c \
plat/arm/css/common/css_topology.c
+ifneq (${TRUSTED_BOARD_BOOT},0)
+$(eval $(call FWU_FIP_ADD_IMG,SCP_BL2U,--scp_bl2u))
+endif
ifneq (${RESET_TO_BL31},0)
$(error "Using BL3-1 as the reset vector is not supported on CSS platforms. \
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 3f46857..6d6646e 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -30,7 +30,6 @@
#include <arch_helpers.h>
#include <assert.h>
-#include <arm_gic.h>
#include <cassert.h>
#include <cci.h>
#include <css_pm.h>
@@ -41,6 +40,12 @@
#include <platform_def.h>
#include "css_scpi.h"
+/* Macros to read the CSS power domain state */
+#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0]
+#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1]
+#define CSS_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) ?\
+ (state)->pwr_domain_state[ARM_PWR_LVL2] : 0)
+
/* Allow CSS platforms to override `plat_arm_psci_pm_ops` */
#pragma weak plat_arm_psci_pm_ops
@@ -93,51 +98,39 @@
return PSCI_E_SUCCESS;
}
-/*******************************************************************************
- * Handler called when a power level has just been powered on after
- * being turned off earlier. The target_state encodes the low power state that
- * each level has woken up from.
- ******************************************************************************/
-void css_pwr_domain_on_finish(const psci_power_state_t *target_state)
+static void css_pwr_domain_on_finisher_common(
+ const psci_power_state_t *target_state)
{
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
- if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
- /*
- * Perform system initialization if woken up from system
- * suspend.
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
- ARM_LOCAL_STATE_OFF)
- arm_system_pwr_domain_resume();
- }
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
/*
* Perform the common cluster specific operations i.e enable coherency
* if this cluster was off.
*/
- if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
- ARM_LOCAL_STATE_OFF)
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/*******************************************************************************
+ * Handler called when a power level has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from. This handler would never be invoked with
+ * the system power domain uninitialized as either the primary would have taken
+ * care of it as part of cold boot or the first core awakened from system
+ * suspend would have already initialized it.
+ ******************************************************************************/
+void css_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Assert that the system power domain need not be initialized */
+ assert(CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_RUN);
+ css_pwr_domain_on_finisher_common(target_state);
- if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
- /*
- * Skip GIC CPU interface and per-CPU Distributor interface
- * setups if woken up from system suspend as it is done as
- * part of css_system_pwr_domain_resume().
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
- ARM_LOCAL_STATE_OFF)
- return;
- }
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_arm_gic_pcpu_init();
/* Enable the gic cpu interface */
- arm_gic_cpuif_setup();
-
- /* todo: Is this setup only needed after a cold boot? */
- arm_gic_pcpu_distif_setup();
+ plat_arm_gic_cpuif_enable();
}
/*******************************************************************************
@@ -152,21 +145,14 @@
uint32_t system_state = scpi_power_on;
/* Prevent interrupts from spuriously waking up this cpu */
- arm_gic_cpuif_deactivate();
+ plat_arm_gic_cpuif_disable();
- if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
- /*
- * Check if power down at system power domain level is
- * requested.
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
- ARM_LOCAL_STATE_OFF)
+ /* Check if power down at system power domain level is requested */
+ if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
system_state = scpi_power_retention;
- }
/* Cluster is to be turned off, so disable coherency */
- if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
- ARM_LOCAL_STATE_OFF) {
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
cluster_state = scpi_power_off;
}
@@ -187,9 +173,7 @@
******************************************************************************/
void css_pwr_domain_off(const psci_power_state_t *target_state)
{
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
css_power_down_common(target_state);
}
@@ -200,16 +184,13 @@
void css_pwr_domain_suspend(const psci_power_state_t *target_state)
{
/*
- * Juno has retention only at cpu level. Just return
+ * CSS currently supports retention only at cpu level. Just return
* as nothing is to be done for retention.
*/
- if (target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_RET)
+ if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
return;
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
css_power_down_common(target_state);
}
@@ -223,14 +204,18 @@
void css_pwr_domain_suspend_finish(
const psci_power_state_t *target_state)
{
- /*
- * Return as nothing is to be done on waking up from retention.
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_RET)
+ /* Return as nothing is to be done on waking up from retention. */
+ if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
return;
- css_pwr_domain_on_finish(target_state);
+ /* Perform system domain restore if woken up from system suspend */
+ if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+ arm_system_pwr_domain_resume();
+ else
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
+
+ css_pwr_domain_on_finisher_common(target_state);
}
/*******************************************************************************
diff --git a/plat/arm/soc/common/soc_css.mk b/plat/arm/soc/common/soc_css.mk
index d8a99a8..7ae8fdb 100644
--- a/plat/arm/soc/common/soc_css.mk
+++ b/plat/arm/soc/common/soc_css.mk
@@ -32,9 +32,10 @@
#PLAT_BL_COMMON_SOURCES +=
-
-#BL1_SOURCES +=
+BL1_SOURCES += plat/arm/soc/common/soc_css_security.c
BL2_SOURCES += plat/arm/soc/common/soc_css_security.c
+BL2U_SOURCES += plat/arm/soc/common/soc_css_security.c
+
BL31_SOURCES += plat/arm/soc/common/soc_css_security.c
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index a6a8476..9070c61 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -28,16 +28,18 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
+#include <console.h>
#include <platform.h>
#include <xlat_tables.h>
/*
- * The following 2 platform setup functions are weakly defined. They
+ * The following platform setup functions are weakly defined. They
* provide typical implementations that may be re-used by multiple
* platforms but may also be overridden by a platform if required.
*/
#pragma weak bl31_plat_enable_mmu
#pragma weak bl32_plat_enable_mmu
+#pragma weak bl31_plat_runtime_setup
void bl31_plat_enable_mmu(uint32_t flags)
{
@@ -49,6 +51,15 @@
enable_mmu_el1(flags);
}
+void bl31_plat_runtime_setup(void)
+{
+ /*
+ * Finish the use of console driver in BL31 so that any runtime logs
+ * from BL31 will be suppressed.
+ */
+ console_uninit();
+}
+
#if !ENABLE_PLAT_COMPAT
/*
* Helper function for platform_get_pos() when platform compatibility is
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
new file mode 100644
index 0000000..aee9440
--- /dev/null
+++ b/plat/common/plat_bl1_common.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform_def.h>
+
+/*
+ * The following platform functions are weakly defined. They
+ * are default implementations that allow BL1 to compile in
+ * absence of real definitions. The Platforms may override
+ * with more complex definitions.
+ */
+#pragma weak bl1_plat_get_next_image_id
+#pragma weak bl1_plat_set_ep_info
+#pragma weak bl1_plat_get_image_desc
+#pragma weak bl1_plat_fwu_done
+
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ /* BL2 load will be done by default. */
+ return BL2_IMAGE_ID;
+}
+
+void bl1_plat_set_ep_info(unsigned int image_id,
+ entry_point_info_t *ep_info)
+{
+
+}
+
+/*
+ * Following is the default definition that always
+ * returns BL2 image details.
+ */
+image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ static image_desc_t bl2_img_desc = BL2_IMAGE_DESC;
+ return &bl2_img_desc;
+}
+
+__dead2 void bl1_plat_fwu_done(void *cookie, void *rsvd_ptr)
+{
+ while (1)
+ wfi();
+}
+
+/*
+ * The Platforms must override with real definition.
+ */
+#pragma weak bl1_plat_mem_check
+
+int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size,
+ unsigned int flags)
+{
+ assert(0);
+ return -ENOMEM;
+}
diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c
new file mode 100644
index 0000000..65f89dc
--- /dev/null
+++ b/plat/common/plat_gicv2.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <assert.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <interrupt_mgmt.h>
+
+/*
+ * The following platform GIC functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_get_pending_interrupt_type
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_get_interrupt_type
+#pragma weak plat_ic_end_of_interrupt
+#pragma weak plat_interrupt_type_to_line
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller
+ */
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ unsigned int id;
+
+ id = gicv2_get_pending_interrupt_id();
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ return INTR_ID_UNAVAILABLE;
+
+ return id;
+}
+
+/*
+ * This function returns the type of the highest priority pending interrupt
+ * at the Interrupt controller. In the case of GICv2, the Highest Priority
+ * Pending interrupt register (`GICC_HPPIR`) is read to determine the id of
+ * the pending interrupt. The type of interrupt depends upon the id value
+ * as follows.
+ * 1. id < PENDING_G1_INTID (1022) is reported as a S-EL1 interrupt
+ * 2. id = PENDING_G1_INTID (1022) is reported as a Non-secure interrupt.
+ * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt
+ * type.
+ */
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ unsigned int id;
+
+ id = gicv2_get_pending_interrupt_type();
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ if (id < PENDING_G1_INTID)
+ return INTR_TYPE_S_EL1;
+
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ return INTR_TYPE_INVAL;
+
+ return INTR_TYPE_NS;
+}
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller and indicates to the Interrupt controller
+ * that the interrupt processing has started.
+ */
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ return gicv2_acknowledge_interrupt();
+}
+
+/*
+ * This function returns the type of the interrupt `id`, depending on how
+ * the interrupt has been configured in the interrupt controller
+ */
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+ unsigned int type;
+
+ type = gicv2_get_interrupt_group(id);
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ return (type) ? INTR_TYPE_NS : INTR_TYPE_S_EL1;
+}
+
+/*
+ * This functions is used to indicate to the interrupt controller that
+ * the processing of the interrupt corresponding to the `id` has
+ * finished.
+ */
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ gicv2_end_of_interrupt(id);
+}
+
+/*
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. It lets the interrupt management framework determine
+ * for a type of interrupt and security state, which line should be used in the
+ * SCR_EL3 to control its routing to EL3. The interrupt line is represented
+ * as the bit position of the IRQ or FIQ bit in the SCR_EL3.
+ */
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+ uint32_t security_state)
+{
+ assert(type == INTR_TYPE_S_EL1 ||
+ type == INTR_TYPE_EL3 ||
+ type == INTR_TYPE_NS);
+
+ /* Non-secure interrupts are signaled on the IRQ line always */
+ if (type == INTR_TYPE_NS)
+ return __builtin_ctz(SCR_IRQ_BIT);
+
+ /*
+ * Secure interrupts are signaled using the IRQ line if the FIQ is
+ * not enabled else they are signaled using the FIQ line.
+ */
+ return ((gicv2_is_fiq_enabled()) ? __builtin_ctz(SCR_FIQ_BIT) :
+ __builtin_ctz(SCR_IRQ_BIT));
+}
diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c
new file mode 100644
index 0000000..249caf8
--- /dev/null
+++ b/plat/common/plat_gicv3.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <cassert.h>
+#include <gic_common.h>
+#include <gicv3.h>
+#include <interrupt_mgmt.h>
+#include <platform.h>
+
+#if IMAGE_BL31
+
+/*
+ * The following platform GIC functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_get_pending_interrupt_type
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_get_interrupt_type
+#pragma weak plat_ic_end_of_interrupt
+#pragma weak plat_interrupt_type_to_line
+
+CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
+ (INTR_TYPE_NS == INTR_GROUP1NS) &&
+ (INTR_TYPE_EL3 == INTR_GROUP0), assert_interrupt_type_mismatch);
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller
+ */
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ unsigned int irqnr;
+
+ assert(IS_IN_EL3());
+ irqnr = gicv3_get_pending_interrupt_id();
+ return (gicv3_is_intr_id_special_identifier(irqnr)) ?
+ INTR_ID_UNAVAILABLE : irqnr;
+}
+
+/*
+ * This function returns the type of the highest priority pending interrupt
+ * at the Interrupt controller. In the case of GICv3, the Highest Priority
+ * Pending interrupt system register (`ICC_HPPIR0_EL1`) is read to determine
+ * the id of the pending interrupt. The type of interrupt depends upon the
+ * id value as follows.
+ * 1. id = PENDING_G1S_INTID (1020) is reported as a S-EL1 interrupt
+ * 2. id = PENDING_G1NS_INTID (1021) is reported as a Non-secure interrupt.
+ * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt
+ * type.
+ * 4. All other interrupt id's are reported as EL3 interrupt.
+ */
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ unsigned int irqnr;
+
+ assert(IS_IN_EL3());
+ irqnr = gicv3_get_pending_interrupt_type();
+
+ switch (irqnr) {
+ case PENDING_G1S_INTID:
+ return INTR_TYPE_S_EL1;
+ case PENDING_G1NS_INTID:
+ return INTR_TYPE_NS;
+ case GIC_SPURIOUS_INTERRUPT:
+ return INTR_TYPE_INVAL;
+ default:
+ return INTR_TYPE_EL3;
+ }
+}
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller and indicates to the Interrupt controller
+ * that the interrupt processing has started.
+ */
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ assert(IS_IN_EL3());
+ return gicv3_acknowledge_interrupt();
+}
+
+/*
+ * This function returns the type of the interrupt `id`, depending on how
+ * the interrupt has been configured in the interrupt controller
+ */
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+ assert(IS_IN_EL3());
+ return gicv3_get_interrupt_type(id, plat_my_core_pos());
+}
+
+/*
+ * This functions is used to indicate to the interrupt controller that
+ * the processing of the interrupt corresponding to the `id` has
+ * finished.
+ */
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ assert(IS_IN_EL3());
+ gicv3_end_of_interrupt(id);
+}
+
+/*
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. It lets the interrupt management framework determine for a type of
+ * interrupt and security state, which line should be used in the SCR_EL3 to
+ * control its routing to EL3. The interrupt line is represented as the bit
+ * position of the IRQ or FIQ bit in the SCR_EL3.
+ */
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+ uint32_t security_state)
+{
+ assert(type == INTR_TYPE_S_EL1 ||
+ type == INTR_TYPE_EL3 ||
+ type == INTR_TYPE_NS);
+
+ assert(sec_state_is_valid(security_state));
+ assert(IS_IN_EL3());
+
+ switch (type) {
+ case INTR_TYPE_S_EL1:
+ /*
+ * The S-EL1 interrupts are signaled as IRQ in S-EL0/1 contexts
+ * and as FIQ in the NS-EL0/1/2 contexts
+ */
+ if (security_state == SECURE)
+ return __builtin_ctz(SCR_IRQ_BIT);
+ else
+ return __builtin_ctz(SCR_FIQ_BIT);
+ case INTR_TYPE_NS:
+ /*
+ * The Non secure interrupts will be signaled as FIQ in S-EL0/1
+ * contexts and as IRQ in the NS-EL0/1/2 contexts.
+ */
+ if (security_state == SECURE)
+ return __builtin_ctz(SCR_FIQ_BIT);
+ else
+ return __builtin_ctz(SCR_IRQ_BIT);
+ default:
+ assert(0);
+ /* Fall through in the release build */
+ case INTR_TYPE_EL3:
+ /*
+ * The EL3 interrupts are signaled as FIQ in both S-EL0/1 and
+ * NS-EL0/1/2 contexts
+ */
+ return __builtin_ctz(SCR_FIQ_BIT);
+ }
+}
+#endif
+#if IMAGE_BL32
+
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_end_of_interrupt
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller
+ */
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ unsigned int irqnr;
+
+ assert(IS_IN_EL1());
+ irqnr = gicv3_get_pending_interrupt_id_sel1();
+ return (irqnr == GIC_SPURIOUS_INTERRUPT) ?
+ INTR_ID_UNAVAILABLE : irqnr;
+}
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller and indicates to the Interrupt controller
+ * that the interrupt processing has started.
+ */
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ assert(IS_IN_EL1());
+ return gicv3_acknowledge_interrupt_sel1();
+}
+
+/*
+ * This functions is used to indicate to the interrupt controller that
+ * the processing of the interrupt corresponding to the `id` has
+ * finished.
+ */
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ assert(IS_IN_EL1());
+ gicv3_end_of_interrupt_sel1(id);
+}
+#endif
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index d9f287c..a4caf5e 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -36,9 +36,9 @@
#include <tegra_def.h>
/* Global functions */
- .globl platform_is_primary_cpu
- .globl platform_get_core_pos
- .globl platform_get_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_get_my_entrypoint
.globl plat_secondary_cold_boot_setup
.globl platform_mem_init
.globl plat_crash_console_init
@@ -47,7 +47,7 @@
.globl plat_reset_handler
/* Global variables */
- .globl sec_entry_point
+ .globl tegra_sec_entry_point
.globl ns_image_entrypoint
.globl tegra_bl31_phys_base
@@ -115,28 +115,47 @@
.endm
/* -----------------------------------------------------
- * int platform_is_primary_cpu(int mpidr);
+ * unsigned int plat_is_my_cpu_primary(void);
*
* This function checks if this is the Primary CPU
* -----------------------------------------------------
*/
-func platform_is_primary_cpu
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
cmp x0, #TEGRA_PRIMARY_CPU
cset x0, eq
ret
-endfunc platform_is_primary_cpu
+endfunc plat_is_my_cpu_primary
/* -----------------------------------------------------
- * int platform_get_core_pos(int mpidr);
+ * unsigned int plat_my_core_pos(void);
+ *
+ * result: CorePos = CoreId + (ClusterId << 2)
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between
+ * a cold and warm boot. If the tegra_sec_entry_point for
+ * this CPU is present, then it's a warm boot.
*
- * With this function: CorePos = CoreId
* -----------------------------------------------------
*/
-func platform_get_core_pos
- and x0, x0, #MPIDR_CPU_MASK
+func plat_get_my_entrypoint
+ adr x1, tegra_sec_entry_point
+ ldr x0, [x1]
ret
-endfunc platform_get_core_pos
+endfunc plat_get_my_entrypoint
/* -----------------------------------------------------
* void plat_secondary_cold_boot_setup (void);
@@ -151,22 +170,6 @@
ret
endfunc plat_secondary_cold_boot_setup
- /* -----------------------------------------------------
- * void platform_get_entrypoint (unsigned int mpidr);
- *
- * Main job of this routine is to distinguish between
- * a cold and warm boot. If the sec_entry_point for
- * this CPU is present, then it's a warm boot.
- *
- * -----------------------------------------------------
- */
-func platform_get_entrypoint
- and x0, x0, #MPIDR_CPU_MASK
- adr x1, sec_entry_point
- ldr x0, [x1, x0, lsl #3]
- ret
-endfunc platform_get_entrypoint
-
/* --------------------------------------------------------
* void platform_mem_init (void);
*
@@ -336,8 +339,7 @@
* Get secure world's entry point and jump to it
* --------------------------------------------------
*/
- mrs x0, mpidr_el1
- bl platform_get_entrypoint
+ bl plat_get_my_entrypoint
br x0
endfunc tegra_secure_entrypoint
@@ -345,13 +347,11 @@
.align 3
/* --------------------------------------------------
- * Per-CPU Secure entry point - resume from suspend
+ * CPU Secure entry point - resume from suspend
* --------------------------------------------------
*/
-sec_entry_point:
- .rept PLATFORM_CORE_COUNT
+tegra_sec_entry_point:
.quad 0
- .endr
/* --------------------------------------------------
* NS world's cold boot entry point
diff --git a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
index b473dd6..3571758 100644
--- a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
+++ b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
@@ -98,9 +98,9 @@
}
/*******************************************************************************
- * Suspend the current CPU
+ * Powerdn the current CPU
******************************************************************************/
-void tegra_fc_cpu_idle(uint32_t mpidr)
+void tegra_fc_cpu_powerdn(uint32_t mpidr)
{
int cpu = mpidr & MPIDR_CPU_MASK;
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index e1c0d84..fcebde3 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -51,6 +51,7 @@
drivers/delay_timer/delay_timer.c \
drivers/ti/uart/16550_console.S \
plat/common/aarch64/platform_mp_stack.S \
+ plat/common/aarch64/plat_psci_common.c \
${COMMON_DIR}/aarch64/tegra_helpers.S \
${COMMON_DIR}/drivers/memctrl/memctrl.c \
${COMMON_DIR}/drivers/pmc/pmc.c \
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index c2c73f6..6fb3e9c 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -44,35 +44,34 @@
#include <tegra_private.h>
extern uint64_t tegra_bl31_phys_base;
-extern uint64_t sec_entry_point[PLATFORM_CORE_COUNT];
-static int system_suspended;
+extern uint64_t tegra_sec_entry_point;
/*
* The following platform setup functions are weakly defined. They
* provide typical implementations that will be overridden by a SoC.
*/
-#pragma weak tegra_soc_prepare_cpu_suspend
-#pragma weak tegra_soc_prepare_cpu_on
-#pragma weak tegra_soc_prepare_cpu_off
-#pragma weak tegra_soc_prepare_cpu_on_finish
+#pragma weak tegra_soc_pwr_domain_suspend
+#pragma weak tegra_soc_pwr_domain_on
+#pragma weak tegra_soc_pwr_domain_off
+#pragma weak tegra_soc_pwr_domain_on_finish
#pragma weak tegra_soc_prepare_system_reset
-int tegra_soc_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
+int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
return PSCI_E_NOT_SUPPORTED;
}
-int tegra_soc_prepare_cpu_on(unsigned long mpidr)
+int tegra_soc_pwr_domain_on(u_register_t mpidr)
{
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_off(unsigned long mpidr)
+int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr)
+int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
return PSCI_E_SUCCESS;
}
@@ -83,33 +82,25 @@
}
/*******************************************************************************
- * Track system suspend entry.
- ******************************************************************************/
-void tegra_pm_system_suspend_entry(void)
-{
- system_suspended = 1;
-}
-
-/*******************************************************************************
- * Track system suspend exit.
- ******************************************************************************/
-void tegra_pm_system_suspend_exit(void)
+ * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
+ * call to get the `power_state` parameter. This allows the platform to encode
+ * the appropriate State-ID field within the `power_state` parameter which can
+ * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
+******************************************************************************/
+void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
- system_suspended = 0;
-}
+ /* lower affinities use PLAT_MAX_OFF_STATE */
+ for (int i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
-/*******************************************************************************
- * Get the system suspend state.
- ******************************************************************************/
-int tegra_system_suspended(void)
-{
- return system_suspended;
+ /* max affinity uses system suspend state id */
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSTATE_ID_SOC_POWERDN;
}
/*******************************************************************************
* Handler called when an affinity instance is about to enter standby.
******************************************************************************/
-void tegra_affinst_standby(unsigned int power_state)
+void tegra_cpu_standby(plat_local_state_t cpu_state)
{
/*
* Enter standby state
@@ -120,132 +111,45 @@
}
/*******************************************************************************
- * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
- * call to get the `power_state` parameter. This allows the platform to encode
- * the appropriate State-ID field within the `power_state` parameter which can
- * be utilized in `affinst_suspend()` to suspend to system affinity level.
-******************************************************************************/
-unsigned int tegra_get_sys_suspend_power_state(void)
-{
- unsigned int power_state;
-
- power_state = psci_make_powerstate(PLAT_SYS_SUSPEND_STATE_ID,
- PSTATE_TYPE_POWERDOWN, MPIDR_AFFLVL2);
-
- return power_state;
-}
-
-/*******************************************************************************
- * Handler called to check the validity of the power state parameter.
- ******************************************************************************/
-int32_t tegra_validate_power_state(unsigned int power_state)
-{
- return tegra_soc_validate_power_state(power_state);
-}
-
-/*******************************************************************************
* Handler called when an affinity instance is about to be turned on. The
* level and mpidr determine the affinity instance.
******************************************************************************/
-int tegra_affinst_on(unsigned long mpidr,
- unsigned long sec_entrypoint,
- unsigned int afflvl,
- unsigned int state)
+int tegra_pwr_domain_on(u_register_t mpidr)
{
- int cpu = mpidr & MPIDR_CPU_MASK;
-
- /*
- * Support individual CPU power on only.
- */
- if (afflvl > MPIDR_AFFLVL0)
- return PSCI_E_SUCCESS;
-
- /*
- * Flush entrypoint variable to PoC since it will be
- * accessed after a reset with the caches turned off.
- */
- sec_entry_point[cpu] = sec_entrypoint;
- flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
-
- return tegra_soc_prepare_cpu_on(mpidr);
+ return tegra_soc_pwr_domain_on(mpidr);
}
/*******************************************************************************
- * Handler called when an affinity instance is about to be turned off. The
- * level determines the affinity instance. The 'state' arg. allows the
- * platform to decide whether the cluster is being turned off and take apt
- * actions.
- *
- * CAUTION: This function is called with coherent stacks so that caches can be
- * turned off, flushed and coherency disabled. There is no guarantee that caches
- * will remain turned on across calls to this function as each affinity level is
- * dealt with. So do not write & read global variables across calls. It will be
- * wise to do flush a write to the global to prevent unpredictable results.
+ * Handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
******************************************************************************/
-void tegra_affinst_off(unsigned int afflvl, unsigned int state)
+void tegra_pwr_domain_off(const psci_power_state_t *target_state)
{
- /*
- * Support individual CPU power off only.
- */
- if (afflvl > MPIDR_AFFLVL0)
- return;
-
- tegra_soc_prepare_cpu_off(read_mpidr());
+ tegra_soc_pwr_domain_off(target_state);
}
/*******************************************************************************
- * Handler called when an affinity instance is about to be suspended. The
- * level and mpidr determine the affinity instance. The 'state' arg. allows the
- * platform to decide whether the cluster is being turned off and take apt
- * actions.
- *
- * CAUTION: This function is called with coherent stacks so that caches can be
- * turned off, flushed and coherency disabled. There is no guarantee that caches
- * will remain turned on across calls to this function as each affinity level is
- * dealt with. So do not write & read global variables across calls. It will be
- * wise to flush a write to the global variable, to prevent unpredictable
- * results.
+ * Handler called when called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
******************************************************************************/
-void tegra_affinst_suspend(unsigned long sec_entrypoint,
- unsigned int afflvl,
- unsigned int state)
+void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
{
- int id = psci_get_suspend_stateid();
- int cpu = read_mpidr() & MPIDR_CPU_MASK;
-
- if (afflvl > PLATFORM_MAX_AFFLVL)
- return;
-
- /*
- * Flush entrypoint variable to PoC since it will be
- * accessed after a reset with the caches turned off.
- */
- sec_entry_point[cpu] = sec_entrypoint;
- flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
-
- tegra_soc_prepare_cpu_suspend(id, afflvl);
+ tegra_soc_pwr_domain_suspend(target_state);
/* disable GICC */
tegra_gic_cpuif_deactivate();
}
/*******************************************************************************
- * Handler called when an affinity instance has just been powered on after
- * being turned off earlier. The level determines the affinity instance.
- * The 'state' arg. allows the platform to decide whether the cluster was
- * turned off prior to wakeup and do what's necessary to set it up.
+ * Handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
******************************************************************************/
-void tegra_affinst_on_finish(unsigned int afflvl, unsigned int state)
+void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
plat_params_from_bl2_t *plat_params;
/*
- * Support individual CPU power on only.
- */
- if (afflvl > MPIDR_AFFLVL0)
- return;
-
- /*
* Initialize the GIC cpu and distributor interfaces
*/
tegra_gic_setup();
@@ -253,7 +157,8 @@
/*
* Check if we are exiting from deep sleep.
*/
- if (tegra_system_suspended()) {
+ if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
+ PSTATE_ID_SOC_POWERDN) {
/*
* Lock scratch registers which hold the CPU vectors.
@@ -276,18 +181,17 @@
/*
* Reset hardware settings.
*/
- tegra_soc_prepare_cpu_on_finish(read_mpidr());
+ tegra_soc_pwr_domain_on_finish(target_state);
}
/*******************************************************************************
- * Handler called when an affinity instance has just been powered on after
- * having been suspended earlier. The level and mpidr determine the affinity
- * instance.
+ * Handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
******************************************************************************/
-void tegra_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
+void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
{
- if (afflvl == MPIDR_AFFLVL0)
- tegra_affinst_on_finish(afflvl, state);
+ tegra_pwr_domain_on_finish(target_state);
}
/*******************************************************************************
@@ -314,35 +218,77 @@
}
/*******************************************************************************
+ * Handler called to check the validity of the power state parameter.
+ ******************************************************************************/
+int32_t tegra_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ return tegra_soc_validate_power_state(power_state, req_state);
+}
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the non secure entrypoint.
+ ******************************************************************************/
+int tegra_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END))
+ return PSCI_E_SUCCESS;
+
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
-static const plat_pm_ops_t tegra_plat_pm_ops = {
- .affinst_standby = tegra_affinst_standby,
- .affinst_on = tegra_affinst_on,
- .affinst_off = tegra_affinst_off,
- .affinst_suspend = tegra_affinst_suspend,
- .affinst_on_finish = tegra_affinst_on_finish,
- .affinst_suspend_finish = tegra_affinst_suspend_finish,
- .system_off = tegra_system_off,
- .system_reset = tegra_system_reset,
- .validate_power_state = tegra_validate_power_state,
- .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state
+static const plat_psci_ops_t tegra_plat_psci_ops = {
+ .cpu_standby = tegra_cpu_standby,
+ .pwr_domain_on = tegra_pwr_domain_on,
+ .pwr_domain_off = tegra_pwr_domain_off,
+ .pwr_domain_suspend = tegra_pwr_domain_suspend,
+ .pwr_domain_on_finish = tegra_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish,
+ .system_off = tegra_system_off,
+ .system_reset = tegra_system_reset,
+ .validate_power_state = tegra_validate_power_state,
+ .validate_ns_entrypoint = tegra_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state,
};
/*******************************************************************************
- * Export the platform specific power ops & initialize the fvp power controller
+ * Export the platform specific power ops and initialize Power Controller
******************************************************************************/
-int platform_setup_pm(const plat_pm_ops_t **plat_ops)
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
{
+ psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } };
+
+ /*
+ * Flush entrypoint variable to PoC since it will be
+ * accessed after a reset with the caches turned off.
+ */
+ tegra_sec_entry_point = sec_entrypoint;
+ flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t));
+
/*
* Reset hardware settings.
*/
- tegra_soc_prepare_cpu_on_finish(read_mpidr());
+ tegra_soc_pwr_domain_on_finish(&target_state);
/*
- * Initialize PM ops struct
+ * Initialize PSCI ops struct
*/
- *plat_ops = &tegra_plat_pm_ops;
+ *psci_ops = &tegra_plat_psci_ops;
return 0;
}
diff --git a/plat/nvidia/tegra/common/tegra_topology.c b/plat/nvidia/tegra/common/tegra_topology.c
index 220e697..0431d98 100644
--- a/plat/nvidia/tegra/common/tegra_topology.c
+++ b/plat/nvidia/tegra/common/tegra_topology.c
@@ -28,45 +28,47 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <arch_helpers.h>
+#include <arch.h>
#include <platform_def.h>
#include <psci.h>
+extern const unsigned char tegra_power_domain_tree_desc[];
+
/*******************************************************************************
- * This function implements a part of the critical interface between the psci
- * generic layer and the platform to allow the former to detect the platform
- * topology. psci queries the platform to determine how many affinity instances
- * are present at a particular level for a given mpidr.
+ * This function returns the Tegra default topology tree information.
******************************************************************************/
-unsigned int plat_get_aff_count(unsigned int aff_lvl,
- unsigned long mpidr)
+const unsigned char *plat_get_power_domain_tree_desc(void)
{
- switch (aff_lvl) {
- case MPIDR_AFFLVL2:
- /* Last supported affinity level */
- return 1;
-
- case MPIDR_AFFLVL1:
- /* Return # of clusters */
- return PLATFORM_CLUSTER_COUNT;
-
- case MPIDR_AFFLVL0:
- /* # of cpus per cluster */
- return PLATFORM_MAX_CPUS_PER_CLUSTER;
-
- default:
- return PSCI_AFF_ABSENT;
- }
+ return tegra_power_domain_tree_desc;
}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
- * generic layer and the platform to allow the former to detect the state of a
- * affinity instance in the platform topology. psci queries the platform to
- * determine whether an affinity instance is present or absent.
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
******************************************************************************/
-unsigned int plat_get_aff_state(unsigned int aff_lvl,
- unsigned long mpidr)
+int plat_core_pos_by_mpidr(u_register_t mpidr)
{
- return (aff_lvl <= MPIDR_AFFLVL2) ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
}
diff --git a/plat/nvidia/tegra/include/drivers/flowctrl.h b/plat/nvidia/tegra/include/drivers/flowctrl.h
index 8bc821d..23909e8 100644
--- a/plat/nvidia/tegra/include/drivers/flowctrl.h
+++ b/plat/nvidia/tegra/include/drivers/flowctrl.h
@@ -73,8 +73,8 @@
mmio_write_32(TEGRA_FLOWCTRL_BASE + off, val);
}
-void tegra_fc_cpu_idle(uint32_t mpidr);
void tegra_fc_cluster_idle(uint32_t midr);
+void tegra_fc_cpu_powerdn(uint32_t mpidr);
void tegra_fc_cluster_powerdn(uint32_t midr);
void tegra_fc_soc_powerdn(uint32_t midr);
void tegra_fc_cpu_on(int cpu);
diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h
index c59e2be..2a7935f 100644
--- a/plat/nvidia/tegra/include/platform_def.h
+++ b/plat/nvidia/tegra/include/platform_def.h
@@ -33,6 +33,7 @@
#include <arch.h>
#include <common_def.h>
+#include <tegra_def.h>
/*******************************************************************************
* Generic platform constants
@@ -47,13 +48,19 @@
#define TEGRA_PRIMARY_CPU 0x0
-#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
PLATFORM_MAX_CPUS_PER_CLUSTER)
-#define PLATFORM_NUM_AFFS (PLATFORM_CORE_COUNT + \
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
PLATFORM_CLUSTER_COUNT + 1)
/*******************************************************************************
+ * Platform power states
+ ******************************************************************************/
+#define PLAT_MAX_RET_STATE 1
+#define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + 1)
+
+/*******************************************************************************
* Platform console related constants
******************************************************************************/
#define TEGRA_CONSOLE_BAUDRATE 115200
diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h
index 2fb9ed7..683c903 100644
--- a/plat/nvidia/tegra/include/t132/tegra_def.h
+++ b/plat/nvidia/tegra/include/t132/tegra_def.h
@@ -37,7 +37,7 @@
* This value is used by the PSCI implementation during the `SYSTEM_SUSPEND`
* call as the `state-id` field in the 'power state' parameter.
******************************************************************************/
-#define PLAT_SYS_SUSPEND_STATE_ID 0xD
+#define PSTATE_ID_SOC_POWERDN 0xD
/*******************************************************************************
* GIC memory map
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index 952e2d8..6fa943f 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -31,8 +31,10 @@
#ifndef __TEGRA_PRIVATE_H__
#define __TEGRA_PRIVATE_H__
-#include <xlat_tables.h>
+#include <arch.h>
#include <platform_def.h>
+#include <psci.h>
+#include <xlat_tables.h>
/*******************************************************************************
* Tegra DRAM memory base address
@@ -45,7 +47,8 @@
} plat_params_from_bl2_t;
/* Declarations for plat_psci_handlers.c */
-int32_t tegra_soc_validate_power_state(unsigned int power_state);
+int32_t tegra_soc_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state);
/* Declarations for plat_setup.c */
const mmap_region_t *plat_get_mmio_map(void);
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index b909335..cec7caf 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -28,7 +28,10 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-SOC_DIR := plat/nvidia/tegra/soc/${TARGET_SOC}
+SOC_DIR := plat/nvidia/tegra/soc/${TARGET_SOC}
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT := 0
include plat/nvidia/tegra/common/tegra_common.mk
include ${SOC_DIR}/platform_${TARGET_SOC}.mk
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
index 46e5940..48a2fba 100644
--- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
@@ -56,28 +56,55 @@
static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
-int32_t tegra_soc_validate_power_state(unsigned int power_state)
+int32_t tegra_soc_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+ int cpu = read_mpidr() & MPIDR_CPU_MASK;
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
/* Sanity check the requested afflvl */
if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
/*
* It's possible to enter standby only on affinity level 0 i.e.
* a cpu on Tegra. Ignore any other affinity level.
*/
- if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
+ if (pwr_lvl != MPIDR_AFFLVL0)
return PSCI_E_INVALID_PARAMS;
+
+ /* power domain in standby state */
+ req_state->pwr_domain_state[pwr_lvl] = PLAT_MAX_RET_STATE;
+
+ return PSCI_E_SUCCESS;
}
- /* Sanity check the requested state id */
- if (psci_get_pstate_id(power_state) != PLAT_SYS_SUSPEND_STATE_ID) {
- ERROR("unsupported state id\n");
- return PSCI_E_NOT_SUPPORTED;
+ /*
+ * Sanity check the requested state id, power level and CPU number.
+ * Currently T132 only supports SYSTEM_SUSPEND on last standing CPU
+ * i.e. CPU 0
+ */
+ if ((pwr_lvl != PLAT_MAX_PWR_LVL) ||
+ (state_id != PSTATE_ID_SOC_POWERDN) ||
+ (cpu != 0)) {
+ ERROR("unsupported state id @ power level\n");
+ return PSCI_E_INVALID_PARAMS;
}
+ /* Set lower power states to PLAT_MAX_OFF_STATE */
+ for (int i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+
+ /* Set the SYSTEM_SUSPEND state-id */
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
+ PSTATE_ID_SOC_POWERDN;
+
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_on(unsigned long mpidr)
+int tegra_soc_pwr_domain_on(u_register_t mpidr)
{
int cpu = mpidr & MPIDR_CPU_MASK;
uint32_t mask = CPU_CORE_RESET_MASK << cpu;
@@ -101,29 +128,29 @@
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_off(unsigned long mpidr)
+int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
- tegra_fc_cpu_off(mpidr & MPIDR_CPU_MASK);
+ tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
+int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
- /* Nothing to be done for lower affinity levels */
- if (afflvl < MPIDR_AFFLVL2)
- return PSCI_E_SUCCESS;
+#if DEBUG
+ int cpu = read_mpidr() & MPIDR_CPU_MASK;
- /* Enter system suspend state */
- tegra_pm_system_suspend_entry();
+ /* SYSTEM_SUSPEND only on CPU0 */
+ assert(cpu == 0);
+#endif
/* Allow restarting CPU #1 using PMC on suspend exit */
cpu_powergate_mask[1] = 0;
/* Program FC to enter suspend state */
- tegra_fc_cpu_idle(read_mpidr());
+ tegra_fc_cpu_powerdn(read_mpidr());
/* Suspend DCO operations */
- write_actlr_el1(id);
+ write_actlr_el1(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
return PSCI_E_SUCCESS;
}
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
index a76999c..6ff2831 100644
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t132/plat_setup.c
@@ -31,6 +31,21 @@
#include <xlat_tables.h>
#include <tegra_def.h>
+/*******************************************************************************
+ * The Tegra power domain tree has a single system level power domain i.e. a
+ * single root node. The first entry in the power domain descriptor specifies
+ * the number of power domains at the highest power level.
+ *******************************************************************************
+ */
+const unsigned char tegra_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ 1,
+ /* No of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of CPU cores */
+ PLATFORM_CORE_COUNT,
+};
+
/* sets of MMIO ranges setup */
#define MMIO_RANGE_0_ADDR 0x50000000
#define MMIO_RANGE_1_ADDR 0x60000000
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 73358d4..b184063 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -55,83 +55,139 @@
static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
-int32_t tegra_soc_validate_power_state(unsigned int power_state)
+int32_t tegra_soc_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL) {
+ ERROR("%s: unsupported power_state (0x%x)\n", __func__,
+ power_state);
+ return PSCI_E_INVALID_PARAMS;
+ }
+
/* Sanity check the requested afflvl */
if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
/*
* It's possible to enter standby only on affinity level 0 i.e.
* a cpu on Tegra. Ignore any other affinity level.
*/
- if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
+ if (pwr_lvl != MPIDR_AFFLVL0)
return PSCI_E_INVALID_PARAMS;
+
+ /* power domain in standby state */
+ req_state->pwr_domain_state[pwr_lvl] = PLAT_MAX_RET_STATE;
+
+ return PSCI_E_SUCCESS;
}
/* Sanity check the requested state id */
- switch (psci_get_pstate_id(power_state)) {
+ switch (state_id) {
case PSTATE_ID_CORE_POWERDN:
+ /*
+ * Core powerdown request only for afflvl 0
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ goto error;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id & 0xff;
+
+ break;
+
case PSTATE_ID_CLUSTER_IDLE:
case PSTATE_ID_CLUSTER_POWERDN:
+ /*
+ * Cluster powerdown/idle request only for afflvl 1
+ */
+ if (pwr_lvl != MPIDR_AFFLVL1)
+ goto error;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+
+ break;
+
case PSTATE_ID_SOC_POWERDN:
+ /*
+ * System powerdown request only for afflvl 2
+ */
+ if (pwr_lvl != PLAT_MAX_PWR_LVL)
+ goto error;
+
+ for (int i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
+ PLAT_SYS_SUSPEND_STATE_ID;
+
break;
default:
- ERROR("unsupported state id\n");
- return PSCI_E_NOT_SUPPORTED;
+ ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
+ return PSCI_E_INVALID_PARAMS;
}
return PSCI_E_SUCCESS;
+
+error:
+ ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
+ return PSCI_E_INVALID_PARAMS;
}
-int tegra_soc_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
+int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
- /* There's nothing to be done for affinity level 1 */
- if (afflvl == MPIDR_AFFLVL1)
- return PSCI_E_SUCCESS;
+ u_register_t mpidr = read_mpidr();
+ const plat_local_state_t *pwr_domain_state =
+ target_state->pwr_domain_state;
+ unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2];
+ unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1];
+ unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0];
- switch (id) {
- /* Prepare for cpu idle */
- case PSTATE_ID_CORE_POWERDN:
- tegra_fc_cpu_idle(read_mpidr());
- return PSCI_E_SUCCESS;
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
- /* Prepare for cluster idle */
- case PSTATE_ID_CLUSTER_IDLE:
- tegra_fc_cluster_idle(read_mpidr());
- return PSCI_E_SUCCESS;
+ assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE);
+ assert(stateid_afflvl1 == PLAT_MAX_OFF_STATE);
- /* Prepare for cluster powerdn */
- case PSTATE_ID_CLUSTER_POWERDN:
- tegra_fc_cluster_powerdn(read_mpidr());
- return PSCI_E_SUCCESS;
+ /* suspend the entire soc */
+ tegra_fc_soc_powerdn(mpidr);
- /* Prepare for system idle */
- case PSTATE_ID_SOC_POWERDN:
+ } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
- /* Enter system suspend state */
- tegra_pm_system_suspend_entry();
+ assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE);
- /* suspend the entire soc */
- tegra_fc_soc_powerdn(read_mpidr());
+ /* Prepare for cluster idle */
+ tegra_fc_cluster_idle(mpidr);
- return PSCI_E_SUCCESS;
+ } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_POWERDN) {
- default:
- ERROR("Unknown state id (%d)\n", id);
- break;
+ assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE);
+
+ /* Prepare for cluster powerdn */
+ tegra_fc_cluster_powerdn(mpidr);
+
+ } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
+
+ /* Prepare for cpu powerdn */
+ tegra_fc_cpu_powerdn(mpidr);
+
+ } else {
+ ERROR("%s: Unknown state id\n", __func__);
+ return PSCI_E_NOT_SUPPORTED;
}
- return PSCI_E_NOT_SUPPORTED;
+ return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr)
+int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
uint32_t val;
/*
* Check if we are exiting from SOC_POWERDN.
*/
- if (tegra_system_suspended()) {
+ if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
+ PLAT_SYS_SUSPEND_STATE_ID) {
/*
* Enable WRAP to INCR burst type conversions for
@@ -147,11 +203,6 @@
* address and reset it.
*/
tegra_fc_reset_bpmp();
-
- /*
- * System resume complete.
- */
- tegra_pm_system_suspend_exit();
}
/*
@@ -159,13 +210,12 @@
* used for power management and boot purposes. Inform the BPMP that
* we have completed the cluster power up.
*/
- if (psci_get_max_phys_off_afflvl() == MPIDR_AFFLVL1)
- tegra_fc_lock_active_cluster();
+ tegra_fc_lock_active_cluster();
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_on(unsigned long mpidr)
+int tegra_soc_pwr_domain_on(u_register_t mpidr)
{
int cpu = mpidr & MPIDR_CPU_MASK;
uint32_t mask = CPU_CORE_RESET_MASK << cpu;
@@ -184,9 +234,9 @@
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_cpu_off(unsigned long mpidr)
+int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
- tegra_fc_cpu_off(mpidr & MPIDR_CPU_MASK);
+ tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
return PSCI_E_SUCCESS;
}
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index cbe7a04..3fce8a2 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -32,6 +32,23 @@
#include <tegra_def.h>
#include <xlat_tables.h>
+/*******************************************************************************
+ * The Tegra power domain tree has a single system level power domain i.e. a
+ * single root node. The first entry in the power domain descriptor specifies
+ * the number of power domains at the highest power level.
+ *******************************************************************************
+ */
+const unsigned char tegra_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ 1,
+ /* No of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of CPU cores - cluster0 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+ /* No of CPU cores - cluster1 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER
+};
+
/* sets of MMIO ranges setup */
#define MMIO_RANGE_0_ADDR 0x50000000
#define MMIO_RANGE_1_ADDR 0x60000000
diff --git a/services/spd/tspd/tspd.mk b/services/spd/tspd/tspd.mk
index 139c7d7..ede2504 100644
--- a/services/spd/tspd/tspd.mk
+++ b/services/spd/tspd/tspd.mk
@@ -55,7 +55,17 @@
# Flag used to enable routing of non-secure interrupts to EL3 when they are
# generated while the code is executing in S-EL1/0.
-TSPD_ROUTE_IRQ_TO_EL3 := 0
+TSP_NS_INTR_ASYNC_PREEMPT := 0
+
+# If TSPD_ROUTE_IRQ_TO_EL3 build flag is defined, use it to define value for
+# TSP_NS_INTR_ASYNC_PREEMPT for backward compatibility.
+ifdef TSPD_ROUTE_IRQ_TO_EL3
+ifeq (${ERROR_DEPRECATED},1)
+$(error "TSPD_ROUTE_IRQ_TO_EL3 is deprecated. Please use the new build flag TSP_NS_INTR_ASYNC_PREEMPT")
+endif
+$(warning "TSPD_ROUTE_IRQ_TO_EL3 is deprecated. Please use the new build flag TSP_NS_INTR_ASYNC_PREEMPT")
+TSP_NS_INTR_ASYNC_PREEMPT := ${TSPD_ROUTE_IRQ_TO_EL3}
+endif
-$(eval $(call assert_boolean,TSPD_ROUTE_IRQ_TO_EL3))
-$(eval $(call add_define,TSPD_ROUTE_IRQ_TO_EL3))
+$(eval $(call assert_boolean,TSP_NS_INTR_ASYNC_PREEMPT))
+$(eval $(call add_define,TSP_NS_INTR_ASYNC_PREEMPT))
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index 6223160..4b89425 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -72,9 +72,16 @@
int32_t tspd_init(void);
+/*
+ * This helper function handles Secure EL1 preemption. The preemption could be
+ * due Non Secure interrupts or EL3 interrupts. In both the cases we context
+ * switch to the normal world and in case of EL3 interrupts, it will again be
+ * routed to EL3 which will get handled at the exception vectors.
+ */
uint64_t tspd_handle_sp_preemption(void *handle)
{
cpu_context_t *ns_cpu_context;
+
assert(handle == cm_get_context(SECURE));
cm_el1_sysregs_context_save(SECURE);
/* Get a reference to the non-secure context */
@@ -82,18 +89,30 @@
assert(ns_cpu_context);
/*
+ * To allow Secure EL1 interrupt handler to re-enter TSP while TSP
+ * is preempted, the secure system register context which will get
+ * overwritten must be additionally saved. This is currently done
+ * by the TSPD S-EL1 interrupt handler.
+ */
+
+ /*
- * Restore non-secure state. The secure system
- * register context will be saved when required.
+ * Restore non-secure state.
*/
cm_el1_sysregs_context_restore(NON_SECURE);
cm_set_next_eret_context(NON_SECURE);
+ /*
+ * The TSP was preempted during STD SMC execution.
+ * Return back to the normal world with SMC_PREEMPTED as error
+ * code in x0.
+ */
SMC_RET1(ns_cpu_context, SMC_PREEMPTED);
}
+
/*******************************************************************************
* This function is the handler registered for S-EL1 interrupts by the TSPD. It
* validates the interrupt and upon success arranges entry into the TSP at
- * 'tsp_fiq_entry()' for handling the interrupt.
+ * 'tsp_sel1_intr_entry()' for handling the interrupt.
******************************************************************************/
static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
uint32_t flags,
@@ -121,44 +140,44 @@
* Determine if the TSP was previously preempted. Its last known
* context has to be preserved in this case.
* The TSP should return control to the TSPD after handling this
- * FIQ. Preserve essential EL3 context to allow entry into the
- * TSP at the FIQ entry point using the 'cpu_context' structure.
- * There is no need to save the secure system register context
- * since the TSP is supposed to preserve it during S-EL1 interrupt
- * handling.
+ * S-EL1 interrupt. Preserve essential EL3 context to allow entry into
+ * the TSP at the S-EL1 interrupt entry point using the 'cpu_context'
+ * structure. There is no need to save the secure system register
+ * context since the TSP is supposed to preserve it during S-EL1
+ * interrupt handling.
*/
if (get_std_smc_active_flag(tsp_ctx->state)) {
tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
CTX_SPSR_EL3);
tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
CTX_ELR_EL3);
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*Need to save the previously interrupted secure context */
memcpy(&tsp_ctx->sp_ctx, &tsp_ctx->cpu_ctx, TSPD_SP_CTX_SIZE);
#endif
}
cm_el1_sysregs_context_restore(SECURE);
- cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->fiq_entry,
+ cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->sel1_intr_entry,
SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
cm_set_next_eret_context(SECURE);
/*
- * Tell the TSP that it has to handle an FIQ synchronously. Also the
- * instruction in normal world where the interrupt was generated is
- * passed for debugging purposes. It is safe to retrieve this address
- * from ELR_EL3 as the secure context will not take effect until
- * el3_exit().
+ * Tell the TSP that it has to handle a S-EL1 interrupt synchronously.
+ * Also the instruction in normal world where the interrupt was
+ * generated is passed for debugging purposes. It is safe to retrieve
+ * this address from ELR_EL3 as the secure context will not take effect
+ * until el3_exit().
*/
- SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_FIQ_AND_RETURN, read_elr_el3());
+ SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_SEL1_INTR_AND_RETURN, read_elr_el3());
}
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*******************************************************************************
- * This function is the handler registered for S-EL1 interrupts by the TSPD. It
- * validates the interrupt and upon success arranges entry into the TSP at
- * 'tsp_fiq_entry()' for handling the interrupt.
+ * This function is the handler registered for Non secure interrupts by the
+ * TSPD. It validates the interrupt and upon success arranges entry into the
+ * normal world for handling the interrupt.
******************************************************************************/
static uint64_t tspd_ns_interrupt_handler(uint32_t id,
uint32_t flags,
@@ -312,10 +331,11 @@
/*
* This function ID is used only by the TSP to indicate that it has
- * finished handling a S-EL1 FIQ interrupt. Execution should resume
+ * finished handling a S-EL1 interrupt or was preempted by a higher
+ * priority pending EL3 interrupt. Execution should resume
* in the normal world.
*/
- case TSP_HANDLED_S_EL1_FIQ:
+ case TSP_HANDLED_S_EL1_INTR:
if (ns)
SMC_RET1(handle, SMC_UNK);
@@ -332,7 +352,7 @@
SMC_SET_EL3(&tsp_ctx->cpu_ctx,
CTX_ELR_EL3,
tsp_ctx->saved_elr_el3);
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*
* Need to restore the previously interrupted
* secure context.
@@ -356,35 +376,6 @@
SMC_RET0((uint64_t) ns_cpu_context);
-
- /*
- * This function ID is used only by the TSP to indicate that it was
- * interrupted due to a EL3 FIQ interrupt. Execution should resume
- * in the normal world.
- */
- case TSP_EL3_FIQ:
- if (ns)
- SMC_RET1(handle, SMC_UNK);
-
- assert(handle == cm_get_context(SECURE));
-
- /* Assert that standard SMC execution has been preempted */
- assert(get_std_smc_active_flag(tsp_ctx->state));
-
- /* Save the secure system register state */
- cm_el1_sysregs_context_save(SECURE);
-
- /* Get a reference to the non-secure context */
- ns_cpu_context = cm_get_context(NON_SECURE);
- assert(ns_cpu_context);
-
- /* Restore non-secure state */
- cm_el1_sysregs_context_restore(NON_SECURE);
- cm_set_next_eret_context(NON_SECURE);
-
- SMC_RET1(ns_cpu_context, TSP_EL3_FIQ);
-
-
/*
* This function ID is used only by the SP to indicate it has
* finished initialising itself after a cold boot
@@ -422,7 +413,7 @@
if (rc)
panic();
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*
* Register an interrupt handler for NS interrupts when
* generated during code executing in secure state are
@@ -438,8 +429,7 @@
panic();
/*
- * Disable the interrupt NS locally since it will be enabled globally
- * within cm_init_my_context.
+ * Disable the NS interrupt locally.
*/
disable_intr_rm_local(INTR_TYPE_NS, SECURE);
#endif
@@ -561,7 +551,7 @@
set_std_smc_active_flag(tsp_ctx->state);
cm_set_elr_el3(SECURE, (uint64_t)
&tsp_vectors->std_smc_entry);
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*
* Enable the routing of NS interrupts to EL3
* during STD SMC processing on this core.
@@ -592,7 +582,7 @@
cm_set_next_eret_context(NON_SECURE);
if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_STD) {
clr_std_smc_active_flag(tsp_ctx->state);
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*
* Disable the routing of NS interrupts to EL3
* after STD SMC processing is finished on this
@@ -635,7 +625,7 @@
* We are done stashing the non-secure context. Ask the
* secure payload to do the work now.
*/
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*
* Enable the routing of NS interrupts to EL3 during resumption
* of STD SMC call on this core.
diff --git a/services/spd/tspd/tspd_pm.c b/services/spd/tspd/tspd_pm.c
index 5089420..55562ba 100644
--- a/services/spd/tspd/tspd_pm.c
+++ b/services/spd/tspd/tspd_pm.c
@@ -130,7 +130,7 @@
/* Initialise this cpu's secure context */
cm_init_my_context(&tsp_on_entrypoint);
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
/*
* Disable the NS interrupt locally since it will be enabled globally
* within cm_init_my_context.
diff --git a/services/spd/tspd/tspd_private.h b/services/spd/tspd/tspd_private.h
index 5f6fb2b..cadc6aa 100644
--- a/services/spd/tspd/tspd_private.h
+++ b/services/spd/tspd/tspd_private.h
@@ -183,10 +183,10 @@
/*******************************************************************************
* Structure which helps the SPD to maintain the per-cpu state of the SP.
- * 'saved_spsr_el3' - temporary copy to allow FIQ handling when the TSP has been
- * preempted.
- * 'saved_elr_el3' - temporary copy to allow FIQ handling when the TSP has been
- * preempted.
+ * 'saved_spsr_el3' - temporary copy to allow S-EL1 interrupt handling when
+ * the TSP has been preempted.
+ * 'saved_elr_el3' - temporary copy to allow S-EL1 interrupt handling when
+ * the TSP has been preempted.
* 'state' - collection of flags to track SP state e.g. on/off
* 'mpidr' - mpidr to associate a context with a cpu
* 'c_rt_ctx' - stack address to restore C runtime context from after
@@ -207,7 +207,7 @@
uint64_t c_rt_ctx;
cpu_context_t cpu_ctx;
uint64_t saved_tsp_args[TSP_NUM_ARGS];
-#if TSPD_ROUTE_IRQ_TO_EL3
+#if TSP_NS_INTR_ASYNC_PREEMPT
sp_ctx_regs_t sp_ctx;
#endif
} tsp_context_t;
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
index 3c65473..0ede365 100644
--- a/tools/cert_create/include/ext.h
+++ b/tools/cert_create/include/ext.h
@@ -72,6 +72,8 @@
X509V3_EXT_METHOD method; /* This field may be used to define a custom
* function to print the contents of the
* extension */
+
+ int optional; /* This field may be used optionally to exclude an image */
} ext_t;
enum {
diff --git a/tools/cert_create/include/tbbr/tbb_cert.h b/tools/cert_create/include/tbbr/tbb_cert.h
index 21626c7..2bc3be6 100644
--- a/tools/cert_create/include/tbbr/tbb_cert.h
+++ b/tools/cert_create/include/tbbr/tbb_cert.h
@@ -46,7 +46,8 @@
BL32_KEY_CERT,
BL32_CERT,
BL33_KEY_CERT,
- BL33_CERT
+ BL33_CERT,
+ FWU_CERT
};
#endif /* TBB_CERT_H_ */
diff --git a/tools/cert_create/include/tbbr/tbb_ext.h b/tools/cert_create/include/tbbr/tbb_ext.h
index 03b12d7..ecbe866 100644
--- a/tools/cert_create/include/tbbr/tbb_ext.h
+++ b/tools/cert_create/include/tbbr/tbb_ext.h
@@ -46,7 +46,10 @@
BL32_CONTENT_CERT_PK_EXT,
BL32_HASH_EXT,
BL33_CONTENT_CERT_PK_EXT,
- BL33_HASH_EXT
+ BL33_HASH_EXT,
+ SCP_BL2U_HASH_EXT,
+ BL2U_HASH_EXT,
+ NS_BL2U_HASH_EXT
};
#endif /* TBB_EXT_H_ */
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index b7ad33f..de15ef6 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -217,8 +217,11 @@
}
break;
case EXT_TYPE_HASH:
- /* Binary image must be specified */
- if (ext->data.fn == NULL) {
+ /*
+ * Binary image must be specified
+ * unless it is explicitly made optional.
+ */
+ if ((!ext->optional) && (ext->data.fn == NULL)) {
ERROR("Image for '%s' not specified\n",
ext->ln);
exit(1);
@@ -410,12 +413,20 @@
break;
case EXT_TYPE_HASH:
if (ext->data.fn == NULL) {
- break;
- }
- if (!sha_file(ext->data.fn, md)) {
- ERROR("Cannot calculate hash of %s\n",
- ext->data.fn);
- exit(1);
+ if (ext->optional) {
+ /* Include a hash filled with zeros */
+ memset(md, 0x0, SHA256_DIGEST_LENGTH);
+ } else {
+ /* Do not include this hash in the certificate */
+ break;
+ }
+ } else {
+ /* Calculate the hash of the file */
+ if (!sha_file(ext->data.fn, md)) {
+ ERROR("Cannot calculate hash of %s\n",
+ ext->data.fn);
+ exit(1);
+ }
}
CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
EXT_CRIT, md_info, md,
diff --git a/tools/cert_create/src/tbbr/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
index 770bd6a..59a1cd9 100644
--- a/tools/cert_create/src/tbbr/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.c
@@ -160,6 +160,20 @@
BL33_HASH_EXT
},
.num_ext = 1
+ },
+ [FWU_CERT] = {
+ .id = FWU_CERT,
+ .opt = "fwu-cert",
+ .fn = NULL,
+ .cn = "FWU Certificate",
+ .key = ROT_KEY,
+ .issuer = FWU_CERT,
+ .ext = {
+ SCP_BL2U_HASH_EXT,
+ BL2U_HASH_EXT,
+ NS_BL2U_HASH_EXT
+ },
+ .num_ext = 3
}
};
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index c39c9e6..b0af6f1 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.c
@@ -145,6 +145,33 @@
.ln = "Non-Trusted World (BL33) hash (SHA256)",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_HASH
+ },
+ [SCP_BL2U_HASH_EXT] = {
+ .oid = SCP_BL2U_HASH_OID,
+ .opt = "scp_bl2u",
+ .sn = "SCPFWUpdateConfig",
+ .ln = "SCP Firmware Update Config (SCP_BL2U) hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+ [BL2U_HASH_EXT] = {
+ .oid = BL2U_HASH_OID,
+ .opt = "bl2u",
+ .sn = "APFWUpdateConfig",
+ .ln = "AP Firmware Update Config (BL2U) hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+ [NS_BL2U_HASH_EXT] = {
+ .oid = NS_BL2U_HASH_OID,
+ .opt = "ns_bl2u",
+ .sn = "FWUpdaterHash",
+ .ln = "Firmware Updater (NS_BL2U) hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
}
};
diff --git a/tools/fip_create/fip_create.c b/tools/fip_create/fip_create.c
index c6869f9..5713184 100644
--- a/tools/fip_create/fip_create.c
+++ b/tools/fip_create/fip_create.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -55,6 +55,14 @@
/* The images used depends on the platform. */
static entry_lookup_list_t toc_entry_lookup_list[] = {
+ { "SCP Firmware Updater Configuration FWU SCP_BL2U", UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U,
+ "scp_bl2u", NULL, FLAG_FILENAME },
+ { "AP Firmware Updater Configuration BL2U", UUID_TRUSTED_UPDATE_FIRMWARE_BL2U,
+ "bl2u", NULL, FLAG_FILENAME },
+ { "Firmware Updater NS_BL2U", UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U,
+ "ns_bl2u", NULL, FLAG_FILENAME },
+ { "Non-Trusted Firmware Updater certificate", UUID_TRUSTED_FWU_CERT,
+ "fwu-cert", NULL, FLAG_FILENAME},
{ "Trusted Boot Firmware BL2", UUID_TRUSTED_BOOT_FIRMWARE_BL2,
"bl2", NULL, FLAG_FILENAME },
{ "SCP Firmware BL3-0", UUID_SCP_FIRMWARE_BL30,