diff --git a/Makefile b/Makefile index 0c3303f..ae9b41b 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 @@ -150,6 +152,7 @@ # target 'certificates' to create them all ifneq (${GENERATE_COT},0) FIP_DEPS += certificates + FWU_FIP_DEPS += fwu_certificates endif @@ -195,7 +198,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 +324,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) @@ -409,6 +415,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 +434,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 +477,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 +541,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 +584,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 #include #include -#include +#include +#include .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 +#include +#include +#include +#include + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 #include #include +#include #include #include #include #include +#include #include "bl1_private.h" +#include -/******************************************************************************* - * 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 Service UUID */ +DEFINE_SVC_UUID(bl1_svc_uid, + 0xfd3967d4, 0x72cb, 0x4d9a, 0xb5, 0x75, + 0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a); - bl1_arch_next_el_setup(); - /* 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(); - 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 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; + + /* 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 + /******************************************************************************* * 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 +#include +#include + +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 #include #include +#include #include #include #include @@ -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 +#include +#include + + + .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 + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/context.S b/bl31/aarch64/context.S deleted file mode 100644 index a72879b..0000000 --- a/bl31/aarch64/context.S +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2013-2014, 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 -#include -#include - -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to save EL1 system register context. It assumes that - * 'x0' is pointing to a 'el1_sys_regs' structure where - * the register context will be saved. - * ----------------------------------------------------- - */ - .global el1_sysregs_context_save -func el1_sysregs_context_save - - mrs x9, spsr_el1 - mrs x10, elr_el1 - stp x9, x10, [x0, #CTX_SPSR_EL1] - - mrs x11, spsr_abt - mrs x12, spsr_und - stp x11, x12, [x0, #CTX_SPSR_ABT] - - mrs x13, spsr_irq - mrs x14, spsr_fiq - stp x13, x14, [x0, #CTX_SPSR_IRQ] - - mrs x15, sctlr_el1 - mrs x16, actlr_el1 - stp x15, x16, [x0, #CTX_SCTLR_EL1] - - mrs x17, cpacr_el1 - mrs x9, csselr_el1 - stp x17, x9, [x0, #CTX_CPACR_EL1] - - mrs x10, sp_el1 - mrs x11, esr_el1 - stp x10, x11, [x0, #CTX_SP_EL1] - - mrs x12, ttbr0_el1 - mrs x13, ttbr1_el1 - stp x12, x13, [x0, #CTX_TTBR0_EL1] - - mrs x14, mair_el1 - mrs x15, amair_el1 - stp x14, x15, [x0, #CTX_MAIR_EL1] - - mrs x16, tcr_el1 - mrs x17, tpidr_el1 - stp x16, x17, [x0, #CTX_TCR_EL1] - - mrs x9, tpidr_el0 - mrs x10, tpidrro_el0 - stp x9, x10, [x0, #CTX_TPIDR_EL0] - - mrs x11, dacr32_el2 - mrs x12, ifsr32_el2 - stp x11, x12, [x0, #CTX_DACR32_EL2] - - mrs x13, par_el1 - mrs x14, far_el1 - stp x13, x14, [x0, #CTX_PAR_EL1] - - mrs x15, afsr0_el1 - mrs x16, afsr1_el1 - stp x15, x16, [x0, #CTX_AFSR0_EL1] - - mrs x17, contextidr_el1 - mrs x9, vbar_el1 - stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] - - /* Save NS timer registers if the build has instructed so */ -#if NS_TIMER_SWITCH - mrs x10, cntp_ctl_el0 - mrs x11, cntp_cval_el0 - stp x10, x11, [x0, #CTX_CNTP_CTL_EL0] - - mrs x12, cntv_ctl_el0 - mrs x13, cntv_cval_el0 - stp x12, x13, [x0, #CTX_CNTV_CTL_EL0] - - mrs x14, cntkctl_el1 - str x14, [x0, #CTX_CNTKCTL_EL1] -#endif - - mrs x15, fpexc32_el2 - str x15, [x0, #CTX_FP_FPEXC32_EL2] - - ret -endfunc el1_sysregs_context_save - -/* ----------------------------------------------------- - * The following function strictly follows the AArch64 - * PCS to use x9-x17 (temporary caller-saved registers) - * to restore EL1 system register context. It assumes - * that 'x0' is pointing to a 'el1_sys_regs' structure - * 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] - msr spsr_el1, x9 - msr elr_el1, x10 - - ldp x11, x12, [x0, #CTX_SPSR_ABT] - msr spsr_abt, x11 - msr spsr_und, x12 - - ldp x13, x14, [x0, #CTX_SPSR_IRQ] - msr spsr_irq, x13 - msr spsr_fiq, x14 - - ldp x15, x16, [x0, #CTX_SCTLR_EL1] - msr sctlr_el1, x15 - msr actlr_el1, x16 - - ldp x17, x9, [x0, #CTX_CPACR_EL1] - msr cpacr_el1, x17 - msr csselr_el1, x9 - - ldp x10, x11, [x0, #CTX_SP_EL1] - msr sp_el1, x10 - msr esr_el1, x11 - - ldp x12, x13, [x0, #CTX_TTBR0_EL1] - msr ttbr0_el1, x12 - msr ttbr1_el1, x13 - - ldp x14, x15, [x0, #CTX_MAIR_EL1] - msr mair_el1, x14 - msr amair_el1, x15 - - ldp x16, x17, [x0, #CTX_TCR_EL1] - msr tcr_el1, x16 - msr tpidr_el1, x17 - - ldp x9, x10, [x0, #CTX_TPIDR_EL0] - msr tpidr_el0, x9 - msr tpidrro_el0, x10 - - ldp x11, x12, [x0, #CTX_DACR32_EL2] - msr dacr32_el2, x11 - msr ifsr32_el2, x12 - - ldp x13, x14, [x0, #CTX_PAR_EL1] - msr par_el1, x13 - msr far_el1, x14 - - ldp x15, x16, [x0, #CTX_AFSR0_EL1] - msr afsr0_el1, x15 - msr afsr1_el1, x16 - - ldp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] - msr contextidr_el1, x17 - msr vbar_el1, x9 - - /* Restore NS timer registers if the build has instructed so */ -#if NS_TIMER_SWITCH - ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0] - msr cntp_ctl_el0, x10 - msr cntp_cval_el0, x11 - - ldp x12, x13, [x0, #CTX_CNTV_CTL_EL0] - msr cntv_ctl_el0, x12 - msr cntv_cval_el0, x13 - - ldr x14, [x0, #CTX_CNTKCTL_EL1] - msr cntkctl_el1, x14 -#endif - - ldr x15, [x0, #CTX_FP_FPEXC32_EL2] - msr fpexc32_el2, x15 - - /* No explict ISB required here as ERET covers it */ - - ret -endfunc el1_sysregs_context_restore - -/* ----------------------------------------------------- - * The following function follows the aapcs_64 strictly - * to use x9-x17 (temporary caller-saved registers - * according to AArch64 PCS) to save floating point - * register context. It assumes that 'x0' is pointing to - * a 'fp_regs' structure where the register context will - * be saved. - * - * Access to VFP registers will trap if CPTR_EL3.TFP is - * set. However currently we don't use VFP registers - * nor set traps in Trusted Firmware, and assume it's - * cleared - * - * TODO: Revisit when VFP is used in secure world - * ----------------------------------------------------- - */ -#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] - stp q4, q5, [x0, #CTX_FP_Q4] - stp q6, q7, [x0, #CTX_FP_Q6] - stp q8, q9, [x0, #CTX_FP_Q8] - stp q10, q11, [x0, #CTX_FP_Q10] - stp q12, q13, [x0, #CTX_FP_Q12] - stp q14, q15, [x0, #CTX_FP_Q14] - stp q16, q17, [x0, #CTX_FP_Q16] - stp q18, q19, [x0, #CTX_FP_Q18] - stp q20, q21, [x0, #CTX_FP_Q20] - stp q22, q23, [x0, #CTX_FP_Q22] - stp q24, q25, [x0, #CTX_FP_Q24] - stp q26, q27, [x0, #CTX_FP_Q26] - stp q28, q29, [x0, #CTX_FP_Q28] - stp q30, q31, [x0, #CTX_FP_Q30] - - mrs x9, fpsr - str x9, [x0, #CTX_FP_FPSR] - - mrs x10, fpcr - str x10, [x0, #CTX_FP_FPCR] - - ret -endfunc fpregs_context_save - -/* ----------------------------------------------------- - * The following function follows the aapcs_64 strictly - * to use x9-x17 (temporary caller-saved registers - * according to AArch64 PCS) to restore floating point - * register context. It assumes that 'x0' is pointing to - * a 'fp_regs' structure from where the register context - * will be restored. - * - * Access to VFP registers will trap if CPTR_EL3.TFP is - * set. However currently we don't use VFP registers - * nor set traps in Trusted Firmware, and assume it's - * cleared - * - * 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] - ldp q4, q5, [x0, #CTX_FP_Q4] - ldp q6, q7, [x0, #CTX_FP_Q6] - ldp q8, q9, [x0, #CTX_FP_Q8] - ldp q10, q11, [x0, #CTX_FP_Q10] - ldp q12, q13, [x0, #CTX_FP_Q12] - ldp q14, q15, [x0, #CTX_FP_Q14] - ldp q16, q17, [x0, #CTX_FP_Q16] - ldp q18, q19, [x0, #CTX_FP_Q18] - ldp q20, q21, [x0, #CTX_FP_Q20] - ldp q22, q23, [x0, #CTX_FP_Q22] - ldp q24, q25, [x0, #CTX_FP_Q24] - ldp q26, q27, [x0, #CTX_FP_Q26] - ldp q28, q29, [x0, #CTX_FP_Q28] - ldp q30, q31, [x0, #CTX_FP_Q30] - - ldr x9, [x0, #CTX_FP_FPSR] - msr fpsr, x9 - - ldr x10, [x0, #CTX_FP_FPCR] - msr fpcr, x10 - - /* - * No explict ISB required here as ERET to - * swtich to secure EL1 or non-secure world - * covers it - */ - - ret -endfunc fpregs_context_restore -#endif /* CTX_INCLUDE_FPREGS */ 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 .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 +#include +#include +#include +#include +#include + + +/******************************************************************************* + * 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/context_mgmt.c b/bl31/context_mgmt.c deleted file mode 100644 index 2b619aa..0000000 --- a/bl31/context_mgmt.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/******************************************************************************* - * Context management library initialisation routine. This library is used by - * runtime services to share pointers to 'cpu_context' structures for the secure - * and non-secure states. Management of the structures and their associated - * memory is not done by the context management library e.g. the PSCI service - * manages the cpu context used for entry from and exit to the non-secure state. - * The Secure payload dispatcher service manages the context(s) corresponding to - * the secure state. It also uses this library to get access to the non-secure - * state cpu context pointers. - * Lastly, this library provides the api to make SP_EL3 point to the cpu context - * which will used for programming an entry into a lower EL. The same context - * will used to save state upon exception entry from that EL. - ******************************************************************************/ -void cm_init(void) -{ - /* - * The context management library has only global data to intialize, but - * that will be done when the BSS is zeroed out - */ -} - -/******************************************************************************* - * 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. - * - * The security state to initialize is determined by the SECURE attribute - * of the entry_point_info. The function returns a pointer to the initialized - * context and sets this as the next context to return to. - * - * The EE and ST attributes are used to configure the endianess and secure - * timer availability for the new execution context. - * - * To prepare the register state for entry call cm_prepare_el3_exit() and - * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to - * cm_e1_sysreg_context_restore(). - ******************************************************************************/ -static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep) -{ - unsigned int security_state; - uint32_t scr_el3; - el3_state_t *state; - gp_regs_t *gp_regs; - unsigned long sctlr_elx; - - assert(ctx); - - security_state = GET_SECURITY_STATE(ep->h.attr); - - /* Clear any residual register values from the context */ - memset(ctx, 0, sizeof(*ctx)); - - /* - * Base the context SCR on the current value, adjust for entry point - * specific requirements and set trap bits from the IMF - * TODO: provide the base/global SCR bits using another mechanism? - */ - scr_el3 = read_scr(); - scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT | - SCR_ST_BIT | SCR_HCE_BIT); - - if (security_state != SECURE) - scr_el3 |= SCR_NS_BIT; - - if (GET_RW(ep->spsr) == MODE_RW_64) - scr_el3 |= SCR_RW_BIT; - - if (EP_GET_ST(ep->h.attr)) - scr_el3 |= SCR_ST_BIT; - - scr_el3 |= get_scr_el3_from_routing_model(security_state); - - /* - * Set up SCTLR_ELx for the target exception level: - * EE bit is taken from the entrpoint attributes - * M, C and I bits must be zero (as required by PSCI specification) - * - * The target exception level is based on the spsr mode requested. - * If execution is requested to EL2 or hyp mode, HVC is enabled - * via SCR_EL3.HCE. - * - * Always compute the SCTLR_EL1 value and save in the cpu_context - * - the EL2 registers are set up by cm_preapre_ns_entry() as they - * are not part of the stored cpu_context - * - * TODO: In debug builds the spsr should be validated and checked - * against the CPU support, security state, endianess and pc - */ - sctlr_elx = EP_GET_EE(ep->h.attr) ? SCTLR_EE_BIT : 0; - if (GET_RW(ep->spsr) == MODE_RW_64) - sctlr_elx |= SCTLR_EL1_RES1; - else - sctlr_elx |= SCTLR_AARCH32_EL1_RES1; - write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); - - if ((GET_RW(ep->spsr) == MODE_RW_64 - && GET_EL(ep->spsr) == MODE_EL2) - || (GET_RW(ep->spsr) != MODE_RW_64 - && GET_M32(ep->spsr) == MODE32_hyp)) { - scr_el3 |= SCR_HCE_BIT; - } - - /* Populate EL3 state so that we've the right context before doing ERET */ - state = get_el3state_ctx(ctx); - write_ctx_reg(state, CTX_SCR_EL3, scr_el3); - write_ctx_reg(state, CTX_ELR_EL3, ep->pc); - write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr); - - /* - * Store the X0-X7 value from the entrypoint into the context - * Use memcpy as we are in control of the layout of the structures - */ - gp_regs = get_gpregs_ctx(ctx); - memcpy(gp_regs, (void *)&ep->args, sizeof(aapcs64_params_t)); -} - -/******************************************************************************* - * The following function initializes the cpu_context for a CPU specified by - * its `cpu_idx` for first use, and sets the initial entrypoint state as - * specified by the entry_point_info structure. - ******************************************************************************/ -void cm_init_context_by_index(unsigned int cpu_idx, - const entry_point_info_t *ep) -{ - cpu_context_t *ctx; - ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr)); - cm_init_context_common(ctx, ep); -} - -/******************************************************************************* - * The following function initializes the cpu_context for the current CPU - * for first use, and sets the initial entrypoint state as specified by the - * entry_point_info structure. - ******************************************************************************/ -void cm_init_my_context(const entry_point_info_t *ep) -{ - cpu_context_t *ctx; - ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr)); - cm_init_context_common(ctx, ep); -} - -/******************************************************************************* - * Prepare the CPU system registers for first entry into secure or normal world - * - * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized - * If execution is requested to non-secure EL1 or svc mode, and the CPU supports - * EL2 then EL2 is disabled by configuring all necessary EL2 registers. - * For all entries, the EL1 registers are initialized from the cpu_context - ******************************************************************************/ -void cm_prepare_el3_exit(uint32_t security_state) -{ - uint32_t sctlr_elx, scr_el3, cptr_el2; - cpu_context_t *ctx = cm_get_context(security_state); - - assert(ctx); - - if (security_state == NON_SECURE) { - scr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3); - if (scr_el3 & SCR_HCE_BIT) { - /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */ - sctlr_elx = read_ctx_reg(get_sysregs_ctx(ctx), - CTX_SCTLR_EL1); - sctlr_elx &= ~SCTLR_EE_BIT; - sctlr_elx |= SCTLR_EL2_RES1; - write_sctlr_el2(sctlr_elx); - } else if (read_id_aa64pfr0_el1() & - (ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) { - /* EL2 present but unused, need to disable safely */ - - /* HCR_EL2 = 0, except RW bit set to match SCR_EL3 */ - write_hcr_el2((scr_el3 & SCR_RW_BIT) ? HCR_RW_BIT : 0); - - /* SCTLR_EL2 : can be ignored when bypassing */ - - /* CPTR_EL2 : disable all traps TCPAC, TTA, TFP */ - cptr_el2 = read_cptr_el2(); - cptr_el2 &= ~(TCPAC_BIT | TTA_BIT | TFP_BIT); - write_cptr_el2(cptr_el2); - - /* Enable EL1 access to timer */ - write_cnthctl_el2(EL1PCEN_BIT | EL1PCTEN_BIT); - - /* Reset CNTVOFF_EL2 */ - write_cntvoff_el2(0); - - /* 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); - } - } - - el1_sysregs_context_restore(get_sysregs_ctx(ctx)); - - cm_set_next_context(ctx); -} - -/******************************************************************************* - * The next four functions are used by runtime services to save and restore - * EL1 context on the 'cpu_context' structure for the specified security - * state. - ******************************************************************************/ -void cm_el1_sysregs_context_save(uint32_t security_state) -{ - cpu_context_t *ctx; - - ctx = cm_get_context(security_state); - assert(ctx); - - el1_sysregs_context_save(get_sysregs_ctx(ctx)); -} - -void cm_el1_sysregs_context_restore(uint32_t security_state) -{ - cpu_context_t *ctx; - - ctx = cm_get_context(security_state); - assert(ctx); - - el1_sysregs_context_restore(get_sysregs_ctx(ctx)); -} - -/******************************************************************************* - * This function populates ELR_EL3 member of 'cpu_context' pertaining to the - * given security state with the given entrypoint - ******************************************************************************/ -void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint) -{ - cpu_context_t *ctx; - el3_state_t *state; - - ctx = cm_get_context(security_state); - assert(ctx); - - /* Populate EL3 state so that ERET jumps to the correct entry */ - state = get_el3state_ctx(ctx); - write_ctx_reg(state, CTX_ELR_EL3, entrypoint); -} - -/******************************************************************************* - * This function populates ELR_EL3 and SPSR_EL3 members of 'cpu_context' - * pertaining to the given security state - ******************************************************************************/ -void cm_set_elr_spsr_el3(uint32_t security_state, - uint64_t entrypoint, uint32_t spsr) -{ - cpu_context_t *ctx; - el3_state_t *state; - - ctx = cm_get_context(security_state); - assert(ctx); - - /* Populate EL3 state so that ERET jumps to the correct entry */ - state = get_el3state_ctx(ctx); - write_ctx_reg(state, CTX_ELR_EL3, entrypoint); - write_ctx_reg(state, CTX_SPSR_EL3, spsr); -} - -/******************************************************************************* - * This function updates a single bit in the SCR_EL3 member of the 'cpu_context' - * pertaining to the given security state using the value and bit position - * specified in the parameters. It preserves all other bits. - ******************************************************************************/ -void cm_write_scr_el3_bit(uint32_t security_state, - uint32_t bit_pos, - uint32_t value) -{ - cpu_context_t *ctx; - el3_state_t *state; - uint32_t scr_el3; - - ctx = cm_get_context(security_state); - assert(ctx); - - /* Ensure that the bit position is a valid one */ - assert((1 << bit_pos) & SCR_VALID_BIT_MASK); - - /* Ensure that the 'value' is only a bit wide */ - assert(value <= 1); - - /* - * Get the SCR_EL3 value from the cpu context, clear the desired bit - * and set it to its new value. - */ - state = get_el3state_ctx(ctx); - scr_el3 = read_ctx_reg(state, CTX_SCR_EL3); - scr_el3 &= ~(1 << bit_pos); - scr_el3 |= value << bit_pos; - write_ctx_reg(state, CTX_SCR_EL3, scr_el3); -} - -/******************************************************************************* - * This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the - * given security state. - ******************************************************************************/ -uint32_t cm_get_scr_el3(uint32_t security_state) -{ - cpu_context_t *ctx; - el3_state_t *state; - - ctx = cm_get_context(security_state); - assert(ctx); - - /* Populate EL3 state so that ERET jumps to the correct entry */ - state = get_el3state_ctx(ctx); - return read_ctx_reg(state, CTX_SCR_EL3); -} - -/******************************************************************************* - * 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_set_next_eret_context(uint32_t security_state) -{ - cpu_context_t *ctx; - - ctx = cm_get_context(security_state); - assert(ctx); - - cm_set_next_context(ctx); -} diff --git a/common/aarch64/context.S b/common/aarch64/context.S new file mode 100644 index 0000000..3d13a80 --- /dev/null +++ b/common/aarch64/context.S @@ -0,0 +1,401 @@ +/* + * 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 +#include +#include + + .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) + * to save EL1 system register context. It assumes that + * 'x0' is pointing to a 'el1_sys_regs' structure where + * the register context will be saved. + * ----------------------------------------------------- + */ +func el1_sysregs_context_save + + mrs x9, spsr_el1 + mrs x10, elr_el1 + stp x9, x10, [x0, #CTX_SPSR_EL1] + + mrs x11, spsr_abt + mrs x12, spsr_und + stp x11, x12, [x0, #CTX_SPSR_ABT] + + mrs x13, spsr_irq + mrs x14, spsr_fiq + stp x13, x14, [x0, #CTX_SPSR_IRQ] + + mrs x15, sctlr_el1 + mrs x16, actlr_el1 + stp x15, x16, [x0, #CTX_SCTLR_EL1] + + mrs x17, cpacr_el1 + mrs x9, csselr_el1 + stp x17, x9, [x0, #CTX_CPACR_EL1] + + mrs x10, sp_el1 + mrs x11, esr_el1 + stp x10, x11, [x0, #CTX_SP_EL1] + + mrs x12, ttbr0_el1 + mrs x13, ttbr1_el1 + stp x12, x13, [x0, #CTX_TTBR0_EL1] + + mrs x14, mair_el1 + mrs x15, amair_el1 + stp x14, x15, [x0, #CTX_MAIR_EL1] + + mrs x16, tcr_el1 + mrs x17, tpidr_el1 + stp x16, x17, [x0, #CTX_TCR_EL1] + + mrs x9, tpidr_el0 + mrs x10, tpidrro_el0 + stp x9, x10, [x0, #CTX_TPIDR_EL0] + + mrs x11, dacr32_el2 + mrs x12, ifsr32_el2 + stp x11, x12, [x0, #CTX_DACR32_EL2] + + mrs x13, par_el1 + mrs x14, far_el1 + stp x13, x14, [x0, #CTX_PAR_EL1] + + mrs x15, afsr0_el1 + mrs x16, afsr1_el1 + stp x15, x16, [x0, #CTX_AFSR0_EL1] + + mrs x17, contextidr_el1 + mrs x9, vbar_el1 + stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + + /* Save NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH + mrs x10, cntp_ctl_el0 + mrs x11, cntp_cval_el0 + stp x10, x11, [x0, #CTX_CNTP_CTL_EL0] + + mrs x12, cntv_ctl_el0 + mrs x13, cntv_cval_el0 + stp x12, x13, [x0, #CTX_CNTV_CTL_EL0] + + mrs x14, cntkctl_el1 + str x14, [x0, #CTX_CNTKCTL_EL1] +#endif + + mrs x15, fpexc32_el2 + str x15, [x0, #CTX_FP_FPEXC32_EL2] + + ret +endfunc el1_sysregs_context_save + +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x17 (temporary caller-saved registers) + * to restore EL1 system register context. It assumes + * that 'x0' is pointing to a 'el1_sys_regs' structure + * from where the register context will be restored + * ----------------------------------------------------- + */ +func el1_sysregs_context_restore + + ldp x9, x10, [x0, #CTX_SPSR_EL1] + msr spsr_el1, x9 + msr elr_el1, x10 + + ldp x11, x12, [x0, #CTX_SPSR_ABT] + msr spsr_abt, x11 + msr spsr_und, x12 + + ldp x13, x14, [x0, #CTX_SPSR_IRQ] + msr spsr_irq, x13 + msr spsr_fiq, x14 + + ldp x15, x16, [x0, #CTX_SCTLR_EL1] + msr sctlr_el1, x15 + msr actlr_el1, x16 + + ldp x17, x9, [x0, #CTX_CPACR_EL1] + msr cpacr_el1, x17 + msr csselr_el1, x9 + + ldp x10, x11, [x0, #CTX_SP_EL1] + msr sp_el1, x10 + msr esr_el1, x11 + + ldp x12, x13, [x0, #CTX_TTBR0_EL1] + msr ttbr0_el1, x12 + msr ttbr1_el1, x13 + + ldp x14, x15, [x0, #CTX_MAIR_EL1] + msr mair_el1, x14 + msr amair_el1, x15 + + ldp x16, x17, [x0, #CTX_TCR_EL1] + msr tcr_el1, x16 + msr tpidr_el1, x17 + + ldp x9, x10, [x0, #CTX_TPIDR_EL0] + msr tpidr_el0, x9 + msr tpidrro_el0, x10 + + ldp x11, x12, [x0, #CTX_DACR32_EL2] + msr dacr32_el2, x11 + msr ifsr32_el2, x12 + + ldp x13, x14, [x0, #CTX_PAR_EL1] + msr par_el1, x13 + msr far_el1, x14 + + ldp x15, x16, [x0, #CTX_AFSR0_EL1] + msr afsr0_el1, x15 + msr afsr1_el1, x16 + + ldp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + msr contextidr_el1, x17 + msr vbar_el1, x9 + + /* Restore NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH + ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0] + msr cntp_ctl_el0, x10 + msr cntp_cval_el0, x11 + + ldp x12, x13, [x0, #CTX_CNTV_CTL_EL0] + msr cntv_ctl_el0, x12 + msr cntv_cval_el0, x13 + + ldr x14, [x0, #CTX_CNTKCTL_EL1] + msr cntkctl_el1, x14 +#endif + + ldr x15, [x0, #CTX_FP_FPEXC32_EL2] + msr fpexc32_el2, x15 + + /* No explict ISB required here as ERET covers it */ + + ret +endfunc el1_sysregs_context_restore + +/* ----------------------------------------------------- + * The following function follows the aapcs_64 strictly + * to use x9-x17 (temporary caller-saved registers + * according to AArch64 PCS) to save floating point + * register context. It assumes that 'x0' is pointing to + * a 'fp_regs' structure where the register context will + * be saved. + * + * Access to VFP registers will trap if CPTR_EL3.TFP is + * set. However currently we don't use VFP registers + * nor set traps in Trusted Firmware, and assume it's + * cleared + * + * TODO: Revisit when VFP is used in secure world + * ----------------------------------------------------- + */ +#if CTX_INCLUDE_FPREGS +func fpregs_context_save + stp q0, q1, [x0, #CTX_FP_Q0] + stp q2, q3, [x0, #CTX_FP_Q2] + stp q4, q5, [x0, #CTX_FP_Q4] + stp q6, q7, [x0, #CTX_FP_Q6] + stp q8, q9, [x0, #CTX_FP_Q8] + stp q10, q11, [x0, #CTX_FP_Q10] + stp q12, q13, [x0, #CTX_FP_Q12] + stp q14, q15, [x0, #CTX_FP_Q14] + stp q16, q17, [x0, #CTX_FP_Q16] + stp q18, q19, [x0, #CTX_FP_Q18] + stp q20, q21, [x0, #CTX_FP_Q20] + stp q22, q23, [x0, #CTX_FP_Q22] + stp q24, q25, [x0, #CTX_FP_Q24] + stp q26, q27, [x0, #CTX_FP_Q26] + stp q28, q29, [x0, #CTX_FP_Q28] + stp q30, q31, [x0, #CTX_FP_Q30] + + mrs x9, fpsr + str x9, [x0, #CTX_FP_FPSR] + + mrs x10, fpcr + str x10, [x0, #CTX_FP_FPCR] + + ret +endfunc fpregs_context_save + +/* ----------------------------------------------------- + * The following function follows the aapcs_64 strictly + * to use x9-x17 (temporary caller-saved registers + * according to AArch64 PCS) to restore floating point + * register context. It assumes that 'x0' is pointing to + * a 'fp_regs' structure from where the register context + * will be restored. + * + * Access to VFP registers will trap if CPTR_EL3.TFP is + * set. However currently we don't use VFP registers + * nor set traps in Trusted Firmware, and assume it's + * cleared + * + * TODO: Revisit when VFP is used in secure world + * ----------------------------------------------------- + */ +func fpregs_context_restore + ldp q0, q1, [x0, #CTX_FP_Q0] + ldp q2, q3, [x0, #CTX_FP_Q2] + ldp q4, q5, [x0, #CTX_FP_Q4] + ldp q6, q7, [x0, #CTX_FP_Q6] + ldp q8, q9, [x0, #CTX_FP_Q8] + ldp q10, q11, [x0, #CTX_FP_Q10] + ldp q12, q13, [x0, #CTX_FP_Q12] + ldp q14, q15, [x0, #CTX_FP_Q14] + ldp q16, q17, [x0, #CTX_FP_Q16] + ldp q18, q19, [x0, #CTX_FP_Q18] + ldp q20, q21, [x0, #CTX_FP_Q20] + ldp q22, q23, [x0, #CTX_FP_Q22] + ldp q24, q25, [x0, #CTX_FP_Q24] + ldp q26, q27, [x0, #CTX_FP_Q26] + ldp q28, q29, [x0, #CTX_FP_Q28] + ldp q30, q31, [x0, #CTX_FP_Q30] + + ldr x9, [x0, #CTX_FP_FPSR] + msr fpsr, x9 + + ldr x10, [x0, #CTX_FP_FPCR] + msr fpcr, x10 + + /* + * No explict ISB required here as ERET to + * swtich to secure EL1 or non-secure world + * covers it + */ + + 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 -#include +#include .globl early_exceptions diff --git a/common/context_mgmt.c b/common/context_mgmt.c new file mode 100644 index 0000000..68ec894 --- /dev/null +++ b/common/context_mgmt.c @@ -0,0 +1,378 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/******************************************************************************* + * Context management library initialisation routine. This library is used by + * runtime services to share pointers to 'cpu_context' structures for the secure + * and non-secure states. Management of the structures and their associated + * memory is not done by the context management library e.g. the PSCI service + * manages the cpu context used for entry from and exit to the non-secure state. + * The Secure payload dispatcher service manages the context(s) corresponding to + * the secure state. It also uses this library to get access to the non-secure + * state cpu context pointers. + * Lastly, this library provides the api to make SP_EL3 point to the cpu context + * which will used for programming an entry into a lower EL. The same context + * will used to save state upon exception entry from that EL. + ******************************************************************************/ +void cm_init(void) +{ + /* + * The context management library has only global data to intialize, but + * that will be done when the BSS is zeroed out + */ +} + +/******************************************************************************* + * 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. + * + * The security state to initialize is determined by the SECURE attribute + * of the entry_point_info. The function returns a pointer to the initialized + * context and sets this as the next context to return to. + * + * The EE and ST attributes are used to configure the endianess and secure + * timer availability for the new execution context. + * + * To prepare the register state for entry call cm_prepare_el3_exit() and + * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to + * cm_e1_sysreg_context_restore(). + ******************************************************************************/ +static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep) +{ + unsigned int security_state; + uint32_t scr_el3; + el3_state_t *state; + gp_regs_t *gp_regs; + unsigned long sctlr_elx; + + assert(ctx); + + security_state = GET_SECURITY_STATE(ep->h.attr); + + /* Clear any residual register values from the context */ + memset(ctx, 0, sizeof(*ctx)); + + /* + * Base the context SCR on the current value, adjust for entry point + * specific requirements and set trap bits from the IMF + * TODO: provide the base/global SCR bits using another mechanism? + */ + scr_el3 = read_scr(); + scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT | + SCR_ST_BIT | SCR_HCE_BIT); + + if (security_state != SECURE) + scr_el3 |= SCR_NS_BIT; + + if (GET_RW(ep->spsr) == MODE_RW_64) + scr_el3 |= SCR_RW_BIT; + + 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: + * EE bit is taken from the entrpoint attributes + * M, C and I bits must be zero (as required by PSCI specification) + * + * The target exception level is based on the spsr mode requested. + * If execution is requested to EL2 or hyp mode, HVC is enabled + * via SCR_EL3.HCE. + * + * Always compute the SCTLR_EL1 value and save in the cpu_context + * - the EL2 registers are set up by cm_preapre_ns_entry() as they + * are not part of the stored cpu_context + * + * TODO: In debug builds the spsr should be validated and checked + * against the CPU support, security state, endianess and pc + */ + sctlr_elx = EP_GET_EE(ep->h.attr) ? SCTLR_EE_BIT : 0; + if (GET_RW(ep->spsr) == MODE_RW_64) + sctlr_elx |= SCTLR_EL1_RES1; + else + sctlr_elx |= SCTLR_AARCH32_EL1_RES1; + write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); + + if ((GET_RW(ep->spsr) == MODE_RW_64 + && GET_EL(ep->spsr) == MODE_EL2) + || (GET_RW(ep->spsr) != MODE_RW_64 + && GET_M32(ep->spsr) == MODE32_hyp)) { + scr_el3 |= SCR_HCE_BIT; + } + + /* Populate EL3 state so that we've the right context before doing ERET */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); + write_ctx_reg(state, CTX_ELR_EL3, ep->pc); + write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr); + + /* + * Store the X0-X7 value from the entrypoint into the context + * Use memcpy as we are in control of the layout of the structures + */ + gp_regs = get_gpregs_ctx(ctx); + memcpy(gp_regs, (void *)&ep->args, sizeof(aapcs64_params_t)); +} + +/******************************************************************************* + * The following function initializes the cpu_context for a CPU specified by + * its `cpu_idx` for first use, and sets the initial entrypoint state as + * specified by the entry_point_info structure. + ******************************************************************************/ +void cm_init_context_by_index(unsigned int cpu_idx, + const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr)); + cm_init_context_common(ctx, ep); +} + +/******************************************************************************* + * The following function initializes the cpu_context for the current CPU + * for first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + ******************************************************************************/ +void cm_init_my_context(const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr)); + cm_init_context_common(ctx, ep); +} + +/******************************************************************************* + * Prepare the CPU system registers for first entry into secure or normal world + * + * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized + * If execution is requested to non-secure EL1 or svc mode, and the CPU supports + * EL2 then EL2 is disabled by configuring all necessary EL2 registers. + * For all entries, the EL1 registers are initialized from the cpu_context + ******************************************************************************/ +void cm_prepare_el3_exit(uint32_t security_state) +{ + uint32_t sctlr_elx, scr_el3, cptr_el2; + cpu_context_t *ctx = cm_get_context(security_state); + + assert(ctx); + + if (security_state == NON_SECURE) { + scr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3); + if (scr_el3 & SCR_HCE_BIT) { + /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */ + sctlr_elx = read_ctx_reg(get_sysregs_ctx(ctx), + CTX_SCTLR_EL1); + sctlr_elx &= ~SCTLR_EE_BIT; + sctlr_elx |= SCTLR_EL2_RES1; + write_sctlr_el2(sctlr_elx); + } else if (read_id_aa64pfr0_el1() & + (ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) { + /* EL2 present but unused, need to disable safely */ + + /* HCR_EL2 = 0, except RW bit set to match SCR_EL3 */ + write_hcr_el2((scr_el3 & SCR_RW_BIT) ? HCR_RW_BIT : 0); + + /* SCTLR_EL2 : can be ignored when bypassing */ + + /* CPTR_EL2 : disable all traps TCPAC, TTA, TFP */ + cptr_el2 = read_cptr_el2(); + cptr_el2 &= ~(TCPAC_BIT | TTA_BIT | TFP_BIT); + write_cptr_el2(cptr_el2); + + /* Enable EL1 access to timer */ + write_cnthctl_el2(EL1PCEN_BIT | EL1PCTEN_BIT); + + /* Reset CNTVOFF_EL2 */ + write_cntvoff_el2(0); + + /* 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); + } + } + + el1_sysregs_context_restore(get_sysregs_ctx(ctx)); + + cm_set_next_context(ctx); +} + +/******************************************************************************* + * The next four functions are used by runtime services to save and restore + * EL1 context on the 'cpu_context' structure for the specified security + * state. + ******************************************************************************/ +void cm_el1_sysregs_context_save(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx); + + el1_sysregs_context_save(get_sysregs_ctx(ctx)); +} + +void cm_el1_sysregs_context_restore(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx); + + el1_sysregs_context_restore(get_sysregs_ctx(ctx)); +} + +/******************************************************************************* + * This function populates ELR_EL3 member of 'cpu_context' pertaining to the + * given security state with the given entrypoint + ******************************************************************************/ +void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_ELR_EL3, entrypoint); +} + +/******************************************************************************* + * This function populates ELR_EL3 and SPSR_EL3 members of 'cpu_context' + * pertaining to the given security state + ******************************************************************************/ +void cm_set_elr_spsr_el3(uint32_t security_state, + uint64_t entrypoint, uint32_t spsr) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_ELR_EL3, entrypoint); + write_ctx_reg(state, CTX_SPSR_EL3, spsr); +} + +/******************************************************************************* + * This function updates a single bit in the SCR_EL3 member of the 'cpu_context' + * pertaining to the given security state using the value and bit position + * specified in the parameters. It preserves all other bits. + ******************************************************************************/ +void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value) +{ + cpu_context_t *ctx; + el3_state_t *state; + uint32_t scr_el3; + + ctx = cm_get_context(security_state); + assert(ctx); + + /* Ensure that the bit position is a valid one */ + assert((1 << bit_pos) & SCR_VALID_BIT_MASK); + + /* Ensure that the 'value' is only a bit wide */ + assert(value <= 1); + + /* + * Get the SCR_EL3 value from the cpu context, clear the desired bit + * and set it to its new value. + */ + state = get_el3state_ctx(ctx); + scr_el3 = read_ctx_reg(state, CTX_SCR_EL3); + scr_el3 &= ~(1 << bit_pos); + scr_el3 |= value << bit_pos; + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); +} + +/******************************************************************************* + * This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the + * given security state. + ******************************************************************************/ +uint32_t cm_get_scr_el3(uint32_t security_state) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + return read_ctx_reg(state, CTX_SCR_EL3); +} + +/******************************************************************************* + * 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_set_next_eret_context(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx); + + cm_set_next_context(ctx); +} 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/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 + +/* + * 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 + +/* + * 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/include/bl1/tbbr/tbbr_img_desc.h b/include/bl1/tbbr/tbbr_img_desc.h new file mode 100644 index 0000000..56f3507 --- /dev/null +++ b/include/bl1/tbbr/tbbr_img_desc.h @@ -0,0 +1,38 @@ +/* + * 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 __TBBR_IMG_DESC_H__ +#define __TBBR_IMG_DESC_H__ + +#include + +extern image_desc_t bl1_tbbr_image_descs[]; + +#endif /* __TBBR_IMG_DESC_H__ */ diff --git a/include/bl31/context.h b/include/bl31/context.h deleted file mode 100644 index 0dfebe0..0000000 --- a/include/bl31/context.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2013-2014, 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 __CONTEXT_H__ -#define __CONTEXT_H__ - -/******************************************************************************* - * Constants that allow assembler code to access members of and the 'gp_regs' - * structure at their correct offsets. - ******************************************************************************/ -#define CTX_GPREGS_OFFSET 0x0 -#define CTX_GPREG_X0 0x0 -#define CTX_GPREG_X1 0x8 -#define CTX_GPREG_X2 0x10 -#define CTX_GPREG_X3 0x18 -#define CTX_GPREG_X4 0x20 -#define CTX_GPREG_X5 0x28 -#define CTX_GPREG_X6 0x30 -#define CTX_GPREG_X7 0x38 -#define CTX_GPREG_X8 0x40 -#define CTX_GPREG_X9 0x48 -#define CTX_GPREG_X10 0x50 -#define CTX_GPREG_X11 0x58 -#define CTX_GPREG_X12 0x60 -#define CTX_GPREG_X13 0x68 -#define CTX_GPREG_X14 0x70 -#define CTX_GPREG_X15 0x78 -#define CTX_GPREG_X16 0x80 -#define CTX_GPREG_X17 0x88 -#define CTX_GPREG_X18 0x90 -#define CTX_GPREG_X19 0x98 -#define CTX_GPREG_X20 0xa0 -#define CTX_GPREG_X21 0xa8 -#define CTX_GPREG_X22 0xb0 -#define CTX_GPREG_X23 0xb8 -#define CTX_GPREG_X24 0xc0 -#define CTX_GPREG_X25 0xc8 -#define CTX_GPREG_X26 0xd0 -#define CTX_GPREG_X27 0xd8 -#define CTX_GPREG_X28 0xe0 -#define CTX_GPREG_X29 0xe8 -#define CTX_GPREG_LR 0xf0 -#define CTX_GPREG_SP_EL0 0xf8 -#define CTX_GPREGS_END 0x100 - -/******************************************************************************* - * Constants that allow assembler code to access members of and the 'el3_state' - * structure at their correct offsets. Note that some of the registers are only - * 32-bits wide but are stored as 64-bit values for convenience - ******************************************************************************/ -#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END) -#define CTX_SCR_EL3 0x0 -#define CTX_RUNTIME_SP 0x8 -#define CTX_SPSR_EL3 0x10 -#define CTX_ELR_EL3 0x18 -#define CTX_EL3STATE_END 0x20 - -/******************************************************************************* - * Constants that allow assembler code to access members of and the - * 'el1_sys_regs' structure at their correct offsets. Note that some of the - * registers are only 32-bits wide but are stored as 64-bit values for - * convenience - ******************************************************************************/ -#define CTX_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END) -#define CTX_SPSR_EL1 0x0 -#define CTX_ELR_EL1 0x8 -#define CTX_SPSR_ABT 0x10 -#define CTX_SPSR_UND 0x18 -#define CTX_SPSR_IRQ 0x20 -#define CTX_SPSR_FIQ 0x28 -#define CTX_SCTLR_EL1 0x30 -#define CTX_ACTLR_EL1 0x38 -#define CTX_CPACR_EL1 0x40 -#define CTX_CSSELR_EL1 0x48 -#define CTX_SP_EL1 0x50 -#define CTX_ESR_EL1 0x58 -#define CTX_TTBR0_EL1 0x60 -#define CTX_TTBR1_EL1 0x68 -#define CTX_MAIR_EL1 0x70 -#define CTX_AMAIR_EL1 0x78 -#define CTX_TCR_EL1 0x80 -#define CTX_TPIDR_EL1 0x88 -#define CTX_TPIDR_EL0 0x90 -#define CTX_TPIDRRO_EL0 0x98 -#define CTX_DACR32_EL2 0xa0 -#define CTX_IFSR32_EL2 0xa8 -#define CTX_PAR_EL1 0xb0 -#define CTX_FAR_EL1 0xb8 -#define CTX_AFSR0_EL1 0xc0 -#define CTX_AFSR1_EL1 0xc8 -#define CTX_CONTEXTIDR_EL1 0xd0 -#define CTX_VBAR_EL1 0xd8 -/* - * If the timer registers aren't saved and restored, we don't have to reserve - * space for them in the context - */ -#if NS_TIMER_SWITCH -#define CTX_CNTP_CTL_EL0 0xe0 -#define CTX_CNTP_CVAL_EL0 0xe8 -#define CTX_CNTV_CTL_EL0 0xf0 -#define CTX_CNTV_CVAL_EL0 0xf8 -#define CTX_CNTKCTL_EL1 0x100 -#define CTX_FP_FPEXC32_EL2 0x108 -#define CTX_SYSREGS_END 0x110 -#else -#define CTX_FP_FPEXC32_EL2 0xe0 -#define CTX_SYSREGS_END 0xf0 -#endif - -/******************************************************************************* - * Constants that allow assembler code to access members of and the 'fp_regs' - * structure at their correct offsets. - ******************************************************************************/ -#if CTX_INCLUDE_FPREGS -#define CTX_FPREGS_OFFSET (CTX_SYSREGS_OFFSET + CTX_SYSREGS_END) -#define CTX_FP_Q0 0x0 -#define CTX_FP_Q1 0x10 -#define CTX_FP_Q2 0x20 -#define CTX_FP_Q3 0x30 -#define CTX_FP_Q4 0x40 -#define CTX_FP_Q5 0x50 -#define CTX_FP_Q6 0x60 -#define CTX_FP_Q7 0x70 -#define CTX_FP_Q8 0x80 -#define CTX_FP_Q9 0x90 -#define CTX_FP_Q10 0xa0 -#define CTX_FP_Q11 0xb0 -#define CTX_FP_Q12 0xc0 -#define CTX_FP_Q13 0xd0 -#define CTX_FP_Q14 0xe0 -#define CTX_FP_Q15 0xf0 -#define CTX_FP_Q16 0x100 -#define CTX_FP_Q17 0x110 -#define CTX_FP_Q18 0x120 -#define CTX_FP_Q19 0x130 -#define CTX_FP_Q20 0x140 -#define CTX_FP_Q21 0x150 -#define CTX_FP_Q22 0x160 -#define CTX_FP_Q23 0x170 -#define CTX_FP_Q24 0x180 -#define CTX_FP_Q25 0x190 -#define CTX_FP_Q26 0x1a0 -#define CTX_FP_Q27 0x1b0 -#define CTX_FP_Q28 0x1c0 -#define CTX_FP_Q29 0x1d0 -#define CTX_FP_Q30 0x1e0 -#define CTX_FP_Q31 0x1f0 -#define CTX_FP_FPSR 0x200 -#define CTX_FP_FPCR 0x208 -#define CTX_FPREGS_END 0x210 -#endif - -#ifndef __ASSEMBLY__ - -#include -#include /* for CACHE_WRITEBACK_GRANULE */ -#include - -/* - * Common constants to help define the 'cpu_context' structure and its - * members below. - */ -#define DWORD_SHIFT 3 -#define DEFINE_REG_STRUCT(name, num_regs) \ - typedef struct name { \ - uint64_t _regs[num_regs]; \ - } __aligned(16) name##_t - -/* Constants to determine the size of individual context structures */ -#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT) -#define CTX_SYSREG_ALL (CTX_SYSREGS_END >> DWORD_SHIFT) -#if CTX_INCLUDE_FPREGS -#define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) -#endif -#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT) - -/* - * AArch64 general purpose register context structure. Usually x0-x18, - * lr are saved as the compiler is expected to preserve the remaining - * callee saved registers if used by the C runtime and the assembler - * does not touch the remaining. But in case of world switch during - * exception handling, we need to save the callee registers too. - */ -DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL); - -/* - * AArch64 EL1 system register context structure for preserving the - * architectural state during switches from one security state to - * another in EL1. - */ -DEFINE_REG_STRUCT(el1_sys_regs, CTX_SYSREG_ALL); - -/* - * AArch64 floating point register context structure for preserving - * the floating point state during switches from one security state to - * another. - */ -#if CTX_INCLUDE_FPREGS -DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL); -#endif - -/* - * Miscellaneous registers used by EL3 firmware to maintain its state - * across exception entries and exits - */ -DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL); - -/* - * Macros to access members of any of the above structures using their - * offsets - */ -#define read_ctx_reg(ctx, offset) ((ctx)->_regs[offset >> DWORD_SHIFT]) -#define write_ctx_reg(ctx, offset, val) (((ctx)->_regs[offset >> DWORD_SHIFT]) \ - = val) - -/* - * Top-level context structure which is used by EL3 firmware to - * preserve the state of a core at EL1 in one of the two security - * states and save enough EL3 meta data to be able to return to that - * EL and security state. The context management library will be used - * to ensure that SP_EL3 always points to an instance of this - * structure at exception entry and exit. Each instance will - * correspond to either the secure or the non-secure state. - */ -typedef struct cpu_context { - gp_regs_t gpregs_ctx; - el3_state_t el3state_ctx; - el1_sys_regs_t sysregs_ctx; -#if CTX_INCLUDE_FPREGS - fp_regs_t fpregs_ctx; -#endif -} cpu_context_t; - -/* Macros to access members of the 'cpu_context_t' structure */ -#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx) -#if CTX_INCLUDE_FPREGS -#define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx) -#endif -#define get_sysregs_ctx(h) (&((cpu_context_t *) h)->sysregs_ctx) -#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) - -/* - * Compile time assertions related to the 'cpu_context' structure to - * ensure that the assembler and the compiler view of the offsets of - * the structure members is the same. - */ -CASSERT(CTX_GPREGS_OFFSET == __builtin_offsetof(cpu_context_t, gpregs_ctx), \ - assert_core_context_gp_offset_mismatch); -CASSERT(CTX_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, sysregs_ctx), \ - assert_core_context_sys_offset_mismatch); -#if CTX_INCLUDE_FPREGS -CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx), \ - assert_core_context_fp_offset_mismatch); -#endif -CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx), \ - assert_core_context_el3state_offset_mismatch); - -/* - * Helper macro to set the general purpose registers that correspond to - * parameters in an aapcs_64 call i.e. x0-x7 - */ -#define set_aapcs_args0(ctx, x0) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, x0); \ - } while (0); -#define set_aapcs_args1(ctx, x0, x1) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, x1); \ - set_aapcs_args0(ctx, x0); \ - } while (0); -#define set_aapcs_args2(ctx, x0, x1, x2) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, x2); \ - set_aapcs_args1(ctx, x0, x1); \ - } while (0); -#define set_aapcs_args3(ctx, x0, x1, x2, x3) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, x3); \ - set_aapcs_args2(ctx, x0, x1, x2); \ - } while (0); -#define set_aapcs_args4(ctx, x0, x1, x2, x3, x4) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4, x4); \ - set_aapcs_args3(ctx, x0, x1, x2, x3); \ - } while (0); -#define set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5, x5); \ - set_aapcs_args4(ctx, x0, x1, x2, x3, x4); \ - } while (0); -#define set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6, x6); \ - set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5); \ - } while (0); -#define set_aapcs_args7(ctx, x0, x1, x2, x3, x4, x5, x6, x7) do { \ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7, x7); \ - set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6); \ - } while (0); - -/******************************************************************************* - * Function prototypes - ******************************************************************************/ -void el1_sysregs_context_save(el1_sys_regs_t *regs); -void el1_sysregs_context_restore(el1_sys_regs_t *regs); -#if CTX_INCLUDE_FPREGS -void fpregs_context_save(fp_regs_t *regs); -void fpregs_context_restore(fp_regs_t *regs); -#endif - - -#undef CTX_SYSREG_ALL -#if CTX_INCLUDE_FPREGS -#undef CTX_FPREG_ALL -#endif -#undef CTX_GPREG_ALL -#undef CTX_EL3STATE_ALL - -#endif /* __ASSEMBLY__ */ - -#endif /* __CONTEXT_H__ */ diff --git a/include/bl31/context_mgmt.h b/include/bl31/context_mgmt.h deleted file mode 100644 index 1ef4076..0000000 --- a/include/bl31/context_mgmt.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ - -#ifndef __CM_H__ -#define __CM_H__ - -#include -#include -#include - -/******************************************************************************* - * Forward declarations - ******************************************************************************/ -struct entry_point_info; - -/******************************************************************************* - * Function & variable prototypes - ******************************************************************************/ -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; -void *cm_get_context_by_index(unsigned int cpu_idx, - unsigned int security_state); -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_init_context(uint64_t mpidr, - const struct entry_point_info *ep) __warn_deprecated; -void cm_init_my_context(const struct entry_point_info *ep); -void cm_init_context_by_index(unsigned int cpu_idx, - const struct entry_point_info *ep); -void cm_prepare_el3_exit(uint32_t security_state); -void cm_el1_sysregs_context_save(uint32_t security_state); -void cm_el1_sysregs_context_restore(uint32_t security_state); -void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint); -void cm_set_elr_spsr_el3(uint32_t security_state, - uint64_t entrypoint, uint32_t spsr); -void cm_write_scr_el3_bit(uint32_t security_state, - uint32_t bit_pos, - uint32_t value); -void cm_set_next_eret_context(uint32_t security_state); -uint32_t cm_get_scr_el3(uint32_t security_state); - -/* 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. - ******************************************************************************/ -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); -} - - -#endif /* __CM_H__ */ 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 +#include /* to include exception types */ +#include /* to include SMCC definitions */ -#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 - -/******************************************************************************* - * 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 -#include -#include - -/* 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/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 /* For __dead2 */ #include @@ -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/common/context.h b/include/common/context.h new file mode 100644 index 0000000..0dfebe0 --- /dev/null +++ b/include/common/context.h @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013-2014, 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 __CONTEXT_H__ +#define __CONTEXT_H__ + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'gp_regs' + * structure at their correct offsets. + ******************************************************************************/ +#define CTX_GPREGS_OFFSET 0x0 +#define CTX_GPREG_X0 0x0 +#define CTX_GPREG_X1 0x8 +#define CTX_GPREG_X2 0x10 +#define CTX_GPREG_X3 0x18 +#define CTX_GPREG_X4 0x20 +#define CTX_GPREG_X5 0x28 +#define CTX_GPREG_X6 0x30 +#define CTX_GPREG_X7 0x38 +#define CTX_GPREG_X8 0x40 +#define CTX_GPREG_X9 0x48 +#define CTX_GPREG_X10 0x50 +#define CTX_GPREG_X11 0x58 +#define CTX_GPREG_X12 0x60 +#define CTX_GPREG_X13 0x68 +#define CTX_GPREG_X14 0x70 +#define CTX_GPREG_X15 0x78 +#define CTX_GPREG_X16 0x80 +#define CTX_GPREG_X17 0x88 +#define CTX_GPREG_X18 0x90 +#define CTX_GPREG_X19 0x98 +#define CTX_GPREG_X20 0xa0 +#define CTX_GPREG_X21 0xa8 +#define CTX_GPREG_X22 0xb0 +#define CTX_GPREG_X23 0xb8 +#define CTX_GPREG_X24 0xc0 +#define CTX_GPREG_X25 0xc8 +#define CTX_GPREG_X26 0xd0 +#define CTX_GPREG_X27 0xd8 +#define CTX_GPREG_X28 0xe0 +#define CTX_GPREG_X29 0xe8 +#define CTX_GPREG_LR 0xf0 +#define CTX_GPREG_SP_EL0 0xf8 +#define CTX_GPREGS_END 0x100 + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'el3_state' + * structure at their correct offsets. Note that some of the registers are only + * 32-bits wide but are stored as 64-bit values for convenience + ******************************************************************************/ +#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END) +#define CTX_SCR_EL3 0x0 +#define CTX_RUNTIME_SP 0x8 +#define CTX_SPSR_EL3 0x10 +#define CTX_ELR_EL3 0x18 +#define CTX_EL3STATE_END 0x20 + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'el1_sys_regs' structure at their correct offsets. Note that some of the + * registers are only 32-bits wide but are stored as 64-bit values for + * convenience + ******************************************************************************/ +#define CTX_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END) +#define CTX_SPSR_EL1 0x0 +#define CTX_ELR_EL1 0x8 +#define CTX_SPSR_ABT 0x10 +#define CTX_SPSR_UND 0x18 +#define CTX_SPSR_IRQ 0x20 +#define CTX_SPSR_FIQ 0x28 +#define CTX_SCTLR_EL1 0x30 +#define CTX_ACTLR_EL1 0x38 +#define CTX_CPACR_EL1 0x40 +#define CTX_CSSELR_EL1 0x48 +#define CTX_SP_EL1 0x50 +#define CTX_ESR_EL1 0x58 +#define CTX_TTBR0_EL1 0x60 +#define CTX_TTBR1_EL1 0x68 +#define CTX_MAIR_EL1 0x70 +#define CTX_AMAIR_EL1 0x78 +#define CTX_TCR_EL1 0x80 +#define CTX_TPIDR_EL1 0x88 +#define CTX_TPIDR_EL0 0x90 +#define CTX_TPIDRRO_EL0 0x98 +#define CTX_DACR32_EL2 0xa0 +#define CTX_IFSR32_EL2 0xa8 +#define CTX_PAR_EL1 0xb0 +#define CTX_FAR_EL1 0xb8 +#define CTX_AFSR0_EL1 0xc0 +#define CTX_AFSR1_EL1 0xc8 +#define CTX_CONTEXTIDR_EL1 0xd0 +#define CTX_VBAR_EL1 0xd8 +/* + * If the timer registers aren't saved and restored, we don't have to reserve + * space for them in the context + */ +#if NS_TIMER_SWITCH +#define CTX_CNTP_CTL_EL0 0xe0 +#define CTX_CNTP_CVAL_EL0 0xe8 +#define CTX_CNTV_CTL_EL0 0xf0 +#define CTX_CNTV_CVAL_EL0 0xf8 +#define CTX_CNTKCTL_EL1 0x100 +#define CTX_FP_FPEXC32_EL2 0x108 +#define CTX_SYSREGS_END 0x110 +#else +#define CTX_FP_FPEXC32_EL2 0xe0 +#define CTX_SYSREGS_END 0xf0 +#endif + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'fp_regs' + * structure at their correct offsets. + ******************************************************************************/ +#if CTX_INCLUDE_FPREGS +#define CTX_FPREGS_OFFSET (CTX_SYSREGS_OFFSET + CTX_SYSREGS_END) +#define CTX_FP_Q0 0x0 +#define CTX_FP_Q1 0x10 +#define CTX_FP_Q2 0x20 +#define CTX_FP_Q3 0x30 +#define CTX_FP_Q4 0x40 +#define CTX_FP_Q5 0x50 +#define CTX_FP_Q6 0x60 +#define CTX_FP_Q7 0x70 +#define CTX_FP_Q8 0x80 +#define CTX_FP_Q9 0x90 +#define CTX_FP_Q10 0xa0 +#define CTX_FP_Q11 0xb0 +#define CTX_FP_Q12 0xc0 +#define CTX_FP_Q13 0xd0 +#define CTX_FP_Q14 0xe0 +#define CTX_FP_Q15 0xf0 +#define CTX_FP_Q16 0x100 +#define CTX_FP_Q17 0x110 +#define CTX_FP_Q18 0x120 +#define CTX_FP_Q19 0x130 +#define CTX_FP_Q20 0x140 +#define CTX_FP_Q21 0x150 +#define CTX_FP_Q22 0x160 +#define CTX_FP_Q23 0x170 +#define CTX_FP_Q24 0x180 +#define CTX_FP_Q25 0x190 +#define CTX_FP_Q26 0x1a0 +#define CTX_FP_Q27 0x1b0 +#define CTX_FP_Q28 0x1c0 +#define CTX_FP_Q29 0x1d0 +#define CTX_FP_Q30 0x1e0 +#define CTX_FP_Q31 0x1f0 +#define CTX_FP_FPSR 0x200 +#define CTX_FP_FPCR 0x208 +#define CTX_FPREGS_END 0x210 +#endif + +#ifndef __ASSEMBLY__ + +#include +#include /* for CACHE_WRITEBACK_GRANULE */ +#include + +/* + * Common constants to help define the 'cpu_context' structure and its + * members below. + */ +#define DWORD_SHIFT 3 +#define DEFINE_REG_STRUCT(name, num_regs) \ + typedef struct name { \ + uint64_t _regs[num_regs]; \ + } __aligned(16) name##_t + +/* Constants to determine the size of individual context structures */ +#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT) +#define CTX_SYSREG_ALL (CTX_SYSREGS_END >> DWORD_SHIFT) +#if CTX_INCLUDE_FPREGS +#define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) +#endif +#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT) + +/* + * AArch64 general purpose register context structure. Usually x0-x18, + * lr are saved as the compiler is expected to preserve the remaining + * callee saved registers if used by the C runtime and the assembler + * does not touch the remaining. But in case of world switch during + * exception handling, we need to save the callee registers too. + */ +DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL); + +/* + * AArch64 EL1 system register context structure for preserving the + * architectural state during switches from one security state to + * another in EL1. + */ +DEFINE_REG_STRUCT(el1_sys_regs, CTX_SYSREG_ALL); + +/* + * AArch64 floating point register context structure for preserving + * the floating point state during switches from one security state to + * another. + */ +#if CTX_INCLUDE_FPREGS +DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL); +#endif + +/* + * Miscellaneous registers used by EL3 firmware to maintain its state + * across exception entries and exits + */ +DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL); + +/* + * Macros to access members of any of the above structures using their + * offsets + */ +#define read_ctx_reg(ctx, offset) ((ctx)->_regs[offset >> DWORD_SHIFT]) +#define write_ctx_reg(ctx, offset, val) (((ctx)->_regs[offset >> DWORD_SHIFT]) \ + = val) + +/* + * Top-level context structure which is used by EL3 firmware to + * preserve the state of a core at EL1 in one of the two security + * states and save enough EL3 meta data to be able to return to that + * EL and security state. The context management library will be used + * to ensure that SP_EL3 always points to an instance of this + * structure at exception entry and exit. Each instance will + * correspond to either the secure or the non-secure state. + */ +typedef struct cpu_context { + gp_regs_t gpregs_ctx; + el3_state_t el3state_ctx; + el1_sys_regs_t sysregs_ctx; +#if CTX_INCLUDE_FPREGS + fp_regs_t fpregs_ctx; +#endif +} cpu_context_t; + +/* Macros to access members of the 'cpu_context_t' structure */ +#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx) +#if CTX_INCLUDE_FPREGS +#define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx) +#endif +#define get_sysregs_ctx(h) (&((cpu_context_t *) h)->sysregs_ctx) +#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) + +/* + * Compile time assertions related to the 'cpu_context' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(CTX_GPREGS_OFFSET == __builtin_offsetof(cpu_context_t, gpregs_ctx), \ + assert_core_context_gp_offset_mismatch); +CASSERT(CTX_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, sysregs_ctx), \ + assert_core_context_sys_offset_mismatch); +#if CTX_INCLUDE_FPREGS +CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx), \ + assert_core_context_fp_offset_mismatch); +#endif +CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx), \ + assert_core_context_el3state_offset_mismatch); + +/* + * Helper macro to set the general purpose registers that correspond to + * parameters in an aapcs_64 call i.e. x0-x7 + */ +#define set_aapcs_args0(ctx, x0) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, x0); \ + } while (0); +#define set_aapcs_args1(ctx, x0, x1) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, x1); \ + set_aapcs_args0(ctx, x0); \ + } while (0); +#define set_aapcs_args2(ctx, x0, x1, x2) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, x2); \ + set_aapcs_args1(ctx, x0, x1); \ + } while (0); +#define set_aapcs_args3(ctx, x0, x1, x2, x3) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, x3); \ + set_aapcs_args2(ctx, x0, x1, x2); \ + } while (0); +#define set_aapcs_args4(ctx, x0, x1, x2, x3, x4) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4, x4); \ + set_aapcs_args3(ctx, x0, x1, x2, x3); \ + } while (0); +#define set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5, x5); \ + set_aapcs_args4(ctx, x0, x1, x2, x3, x4); \ + } while (0); +#define set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6, x6); \ + set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5); \ + } while (0); +#define set_aapcs_args7(ctx, x0, x1, x2, x3, x4, x5, x6, x7) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7, x7); \ + set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6); \ + } while (0); + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void el1_sysregs_context_save(el1_sys_regs_t *regs); +void el1_sysregs_context_restore(el1_sys_regs_t *regs); +#if CTX_INCLUDE_FPREGS +void fpregs_context_save(fp_regs_t *regs); +void fpregs_context_restore(fp_regs_t *regs); +#endif + + +#undef CTX_SYSREG_ALL +#if CTX_INCLUDE_FPREGS +#undef CTX_FPREG_ALL +#endif +#undef CTX_GPREG_ALL +#undef CTX_EL3STATE_ALL + +#endif /* __ASSEMBLY__ */ + +#endif /* __CONTEXT_H__ */ diff --git a/include/common/context_mgmt.h b/include/common/context_mgmt.h new file mode 100644 index 0000000..141b348 --- /dev/null +++ b/include/common/context_mgmt.h @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#ifndef __CM_H__ +#define __CM_H__ + +#include +#include +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct entry_point_info; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void cm_init(void); +void *cm_get_context_by_mpidr(uint64_t mpidr, + uint32_t security_state) __warn_deprecated; +void cm_set_context_by_mpidr(uint64_t mpidr, + void *context, + uint32_t security_state) __warn_deprecated; +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state); +void cm_set_context_by_index(unsigned int cpu_idx, + void *context, + unsigned int 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); +void cm_init_context_by_index(unsigned int cpu_idx, + const struct entry_point_info *ep); +void cm_prepare_el3_exit(uint32_t security_state); +void cm_el1_sysregs_context_save(uint32_t security_state); +void cm_el1_sysregs_context_restore(uint32_t security_state); +void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint); +void cm_set_elr_spsr_el3(uint32_t security_state, + uint64_t entrypoint, uint32_t spsr); +void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); +void cm_set_next_eret_context(uint32_t security_state); +uint32_t cm_get_scr_el3(uint32_t security_state); + +/* Inline definitions */ + +/******************************************************************************* + * 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 + ******************************************************************************/ +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)); +} +#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 +#include +#include + +/* 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/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,17 +105,27 @@ * 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 -# define MAX_XLAT_TABLES 3 -# endif /* PLAT_ */ +# 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_BL2U +# if PLAT_juno +# define MAX_XLAT_TABLES 3 +# else +# define MAX_XLAT_TABLES 4 +# endif /* PLAT_ */ #elif IMAGE_BL31 # define MAX_XLAT_TABLES 2 #elif IMAGE_BL32 diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 5c03feb..4a50c1c 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -310,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 f0b3ff6..bcb2e2b 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -165,6 +165,12 @@ 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); @@ -174,6 +180,8 @@ /* 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 diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h index 99491f8..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 @@ -112,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 +#include + /****************************************************************************** * 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..9fbc172 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,6 +193,23 @@ ******************************************************************************/ /******************************************************************************* + * 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, 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 e089405..305505d 100644 --- a/plat/arm/board/fvp/aarch64/fvp_common.c +++ b/plat/arm/board/fvp/aarch64/fvp_common.c @@ -82,6 +82,9 @@ MAP_DEVICE0, MAP_DEVICE1, MAP_DEVICE2, +#if TRUSTED_BOARD_BOOT + ARM_MAP_NS_DRAM1, +#endif {0} }; #endif @@ -98,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, 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 +#include #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_bl2u_setup.c b/plat/arm/board/fvp/fvp_bl2u_setup.c new file mode 100644 index 0000000..b26f0e0 --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2u_setup.c @@ -0,0 +1,41 @@ +/* + * 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 +#include "fvp_def.h" +#include "fvp_private.h" + +void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) +{ + arm_bl2u_early_platform_setup(mem_layout, plat_info); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index b6f0739..cb5f5d7 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -83,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 \ 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 +#include +#include +#include +#include +#include + +#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 0212fdd..fae30e7 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -41,11 +41,14 @@ 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 \ 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 +#include +#include +#include +#include +#include + + +/* 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 +#include +#include +#include +#include +#include +#include + + +/* + * 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_common.mk b/plat/arm/common/arm_common.mk index 1336e23..4ac12d9 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -106,6 +106,11 @@ 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/tzc400/tzc400.c \ @@ -127,9 +132,16 @@ 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_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/css/common/css_bl1_setup.c b/plat/arm/css/common/css_bl1_setup.c new file mode 100644 index 0000000..2abed3b --- /dev/null +++ b/plat/arm/css/common/css_bl1_setup.c @@ -0,0 +1,45 @@ +/* + * 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 +#include +#include +#include + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); + /* + * Do ARM CSS SoC security setup. + * BL1 needs to enable normal world access to memory. + */ + soc_css_security_setup(); +} + 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 +#include +#include +#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 6394197..49fedc3 100644 --- a/plat/arm/css/common/css_common.mk +++ b/plat/arm/css/common/css_common.mk @@ -34,18 +34,26 @@ 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/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/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 +#include +#include +#include +#include +#include + +/* + * 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/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,