diff --git a/Makefile b/Makefile index 0c3303f86..ae9b41b82 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,8 @@ USE_COHERENT_MEM := 1 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 @@ VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STR # target 'certificates' to create them all ifneq (${GENERATE_COT},0) FIP_DEPS += certificates + FWU_FIP_DEPS += fwu_certificates endif @@ -195,7 +198,8 @@ BL_COMMON_SOURCES += common/bl_common.c \ 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 @@ ifneq (${GENERATE_COT},0) # 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 @@ NEED_BL2 := yes 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 @@ endif # 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 @@ ifeq (${NEED_BL33},yes) $(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 @@ ${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} @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 @@ help: @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 83594f218..ce2775243 100644 --- a/bl1/aarch64/bl1_entrypoint.S +++ b/bl1/aarch64/bl1_entrypoint.S @@ -69,10 +69,14 @@ func bl1_entrypoint /* -------------------------------------------------- * 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 5415d3955..9ff6a57b0 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 @@ SynchronousExceptionA64: /* 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 @@ SErrorA32: 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 @@ unexpected_sync_exception: 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 8e73bef43..21e87c79c 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_SOURCES += bl1/bl1_main.c \ 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 000000000..6355190e5 --- /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 000000000..f8b414e3f --- /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 73f023aba..84d561103 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 @@ void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout, /* 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 @@ void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout, /******************************************************************************* * 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 @@ void bl1_main(void) 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 @@ void bl1_main(void) /* 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 @@ void bl1_main(void) 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 @@ void print_debug_loop_message(void) 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 0a8fc45c4..283bbb972 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 @@ extern uint64_t __BL1_RAM_END__; 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 000000000..42de8517f --- /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 1d2622974..75eb02a9d 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. @@ -73,14 +72,6 @@ func bl2_entrypoint msr sctlr_el1, x0 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 @@ -126,7 +117,7 @@ func bl2_entrypoint * 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 a3f016f9c..f47564054 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 @@ void bl2_main(void) * 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 000000000..c9aad81f6 --- /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 000000000..ec1207791 --- /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 000000000..aa9de544c --- /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 000000000..515ddfb73 --- /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/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 28353202d..dc11e0a72 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 @@ smc_handler64: #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 @@ rt_svc_fw_critical_error: 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 a31c1f475..0c2b631a6 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 000000000..ae2442471 --- /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/aarch64/context.S b/common/aarch64/context.S similarity index 66% rename from bl31/aarch64/context.S rename to common/aarch64/context.S index a72879be2..3d13a8027 100644 --- a/bl31/aarch64/context.S +++ b/common/aarch64/context.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -32,6 +32,17 @@ #include #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) @@ -40,7 +51,6 @@ * the register context will be saved. * ----------------------------------------------------- */ - .global el1_sysregs_context_save func el1_sysregs_context_save mrs x9, spsr_el1 @@ -127,7 +137,6 @@ endfunc el1_sysregs_context_save * from where the register context will be restored * ----------------------------------------------------- */ - .global el1_sysregs_context_restore func el1_sysregs_context_restore ldp x9, x10, [x0, #CTX_SPSR_EL1] @@ -225,7 +234,6 @@ endfunc el1_sysregs_context_restore * ----------------------------------------------------- */ #if CTX_INCLUDE_FPREGS - .global fpregs_context_save func fpregs_context_save stp q0, q1, [x0, #CTX_FP_Q0] stp q2, q3, [x0, #CTX_FP_Q2] @@ -269,7 +277,6 @@ endfunc fpregs_context_save * 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] @@ -303,3 +310,92 @@ func fpregs_context_restore 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 90f5421b0..780a38f6d 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/bl31/context_mgmt.c b/common/context_mgmt.c similarity index 77% rename from bl31/context_mgmt.c rename to common/context_mgmt.c index 2b619aaa5..68ec89456 100644 --- a/bl31/context_mgmt.c +++ b/common/context_mgmt.c @@ -32,14 +32,12 @@ #include #include #include -#include #include #include -#include #include #include #include -#include +#include #include @@ -64,105 +62,6 @@ void cm_init(void) */ } -/******************************************************************************* - * 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 @@ -212,7 +111,13 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t 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: diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c index 79a896514..71634a19d 100644 --- a/drivers/auth/tbbr/tbbr_cot.c +++ b/drivers/auth/tbbr/tbbr_cot.c @@ -89,6 +89,12 @@ static auth_param_type_desc_t bl32_hash = AUTH_PARAM_TYPE_DESC( 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 @@ static const auth_img_desc_t cot_desc[] = { } } } + }, + /* + * 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 000000000..9fb3cb283 --- /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 000000000..56f35075b --- /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/runtime_svc.h b/include/bl31/runtime_svc.h index f11241835..30ba29f04 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 @@ CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \ ((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 c9a7a3dab..b7cb95aa2 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_START__; 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 @@ typedef struct image_info { param_header_t h; uintptr_t image_base; /* physical address of base of image */ uint32_t image_size; /* bytes read from image file */ + uint32_t copied_size; /* image size copied in blocks */ } image_info_t; +/***************************************************************************** + * The image descriptor struct definition. + *****************************************************************************/ +typedef struct image_desc { + /* Contains unique image id for the image. */ + unsigned int image_id; + image_info_t image_info; + entry_point_info_t ep_info; + /* + * This member contains Image state information. + * Refer IMAGE_STATE_XXX defined above. + */ + unsigned int state; +} image_desc_t; + /******************************************************************************* * This structure represents the superset of information that can be passed to * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be diff --git a/include/bl31/context.h b/include/common/context.h similarity index 100% rename from include/bl31/context.h rename to include/common/context.h diff --git a/include/bl31/context_mgmt.h b/include/common/context_mgmt.h similarity index 77% rename from include/bl31/context_mgmt.h rename to include/common/context_mgmt.h index 1ef40766b..141b34818 100644 --- a/include/bl31/context_mgmt.h +++ b/include/common/context_mgmt.h @@ -31,9 +31,9 @@ #ifndef __CM_H__ #define __CM_H__ +#include +#include #include -#include -#include /******************************************************************************* * Forward declarations @@ -46,7 +46,6 @@ struct entry_point_info; void cm_init(void); void *cm_get_context_by_mpidr(uint64_t mpidr, uint32_t security_state) __warn_deprecated; -static inline void *cm_get_context(uint32_t security_state); void cm_set_context_by_mpidr(uint64_t mpidr, void *context, uint32_t security_state) __warn_deprecated; @@ -55,7 +54,9 @@ void *cm_get_context_by_index(unsigned int cpu_idx, void cm_set_context_by_index(unsigned int cpu_idx, void *context, unsigned int security_state); -static inline void cm_set_context(void *context, uint32_t security_state); +void *cm_get_context(uint32_t security_state); +void cm_set_context(void *context, uint32_t security_state); +inline void cm_set_next_context(void *context); void cm_init_context(uint64_t mpidr, const struct entry_point_info *ep) __warn_deprecated; void cm_init_my_context(const struct entry_point_info *ep); @@ -76,27 +77,28 @@ 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. + * This function is used to program the context that's used for exception + * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for + * the required security state ******************************************************************************/ -void *cm_get_context(uint32_t security_state) +inline void cm_set_next_context(void *context) { - assert(security_state <= NON_SECURE); +#if DEBUG + uint64_t sp_mode; - return get_cpu_data(cpu_context[security_state]); + /* + * Check that this function is called with SP_EL0 as the stack + * pointer + */ + __asm__ volatile("mrs %0, SPSel\n" + : "=r" (sp_mode)); + + assert(sp_mode == MODE_SP_EL0); +#endif + + __asm__ volatile("msr spsel, #1\n" + "mov sp, %0\n" + "msr spsel, #0\n" + : : "r" (context)); } - -/******************************************************************************* - * 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/common/el3_common_macros.S b/include/common/el3_common_macros.S index 87e172e84..0514e2a24 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 8fb669e3d..daa043a86 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 000000000..6a07b0132 --- /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 c43c39540..fabe0b942 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 3abf235eb..b4e431348 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 5c03feb9a..4a50c1c8c 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 f0b3ff675..bcb2e2b8a 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -165,6 +165,12 @@ void arm_bl2_plat_arch_setup(void); 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 @@ void arm_bl31_plat_arch_setup(void); /* TSP utility functions */ void arm_tsp_early_platform_setup(void); +/* FIP TOC validity check */ +int arm_io_is_toc_valid(void); /* * Mandatory functions required in ARM standard platforms diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h index 99491f88b..3fa4c153d 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 43c69cc83..4175b1452 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 de9848b7c..9fbc17211 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -43,6 +43,7 @@ struct meminfo; struct image_info; struct entry_point_info; struct bl31_params; +struct image_desc; /******************************************************************************* * plat_get_rotpk_info() flags @@ -92,11 +93,11 @@ void bl1_platform_setup(void); 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_plat_set_bl2_ep_info(struct image_info *image, 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 ******************************************************************************/ @@ -172,6 +192,23 @@ void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info); * Optional BL2 functions (may be overridden) ******************************************************************************/ +/******************************************************************************* + * 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 ******************************************************************************/ diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk index 9ab6e6488..08cb4b120 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 @@ define FIP_ADD_PAYLOAD $(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 @@ check_$(1): $$(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 @@ $(strip $(foreach goal,$(1),$(filter $(goal),$(MAKECMDGOALS)))) 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 @@ endif # 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 @@ endef # 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 @@ endef # 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 2ec72b90c..bf0d29677 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 @@ ifneq (${BL33},) $(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 7bf0273d1..62253f8c4 100644 --- a/plat/arm/board/common/board_css_common.c +++ b/plat/arm/board/common/board_css_common.c @@ -42,6 +42,9 @@ const mmap_region_t plat_arm_mmap[] = { 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 @@ const mmap_region_t plat_arm_mmap[] = { {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 e089405dc..305505d30 100644 --- a/plat/arm/board/fvp/aarch64/fvp_common.c +++ b/plat/arm/board/fvp/aarch64/fvp_common.c @@ -82,6 +82,9 @@ const mmap_region_t plat_arm_mmap[] = { MAP_DEVICE0, MAP_DEVICE1, MAP_DEVICE2, +#if TRUSTED_BOARD_BOOT + ARM_MAP_NS_DRAM1, +#endif {0} }; #endif @@ -98,6 +101,13 @@ const mmap_region_t plat_arm_mmap[] = { {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 33712d1ef..91bc9c4ec 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 @@ void bl1_early_platform_setup(void) */ 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 000000000..b26f0e04d --- /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 b6f073943..cb5f5d7ed 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -83,6 +83,9 @@ BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \ 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 000000000..61a573817 --- /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 0212fddea..fae30e7e1 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -41,11 +41,14 @@ PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/aarch64/juno_helpers.S 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 000000000..9a0d93ad6 --- /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 79c7d9440..d0a4c0b2f 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 @@ void bl1_plat_prepare_exit(entry_point_info_t *ep_info) 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 000000000..5b7354b3e --- /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 1336e2307..4ac12d9b9 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -106,6 +106,11 @@ BL2_SOURCES += drivers/arm/tzc400/tzc400.c \ 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 @@ ifneq (${TRUSTED_BOARD_BOOT},0) 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 ae67cde00..f7e99e9c4 100644 --- a/plat/arm/common/arm_io_storage.c +++ b/plat/arm/common/arm_io_storage.c @@ -308,3 +308,17 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 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 000000000..2abed3b92 --- /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 000000000..878b6faf8 --- /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 639419798..49fedc3a0 100644 --- a/plat/arm/css/common/css_common.mk +++ b/plat/arm/css/common/css_common.mk @@ -34,18 +34,26 @@ PLAT_INCLUDES += -Iinclude/plat/arm/css/common \ 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 d8a99a8c4..7ae8fdb72 100644 --- a/plat/arm/soc/common/soc_css.mk +++ b/plat/arm/soc/common/soc_css.mk @@ -32,9 +32,10 @@ PLAT_INCLUDES += -Iinclude/plat/arm/soc/common/ #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 000000000..aee9440a3 --- /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 3c65473b0..0ede36518 100644 --- a/tools/cert_create/include/ext.h +++ b/tools/cert_create/include/ext.h @@ -72,6 +72,8 @@ typedef struct ext_s { 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 21626c726..2bc3be63c 100644 --- a/tools/cert_create/include/tbbr/tbb_cert.h +++ b/tools/cert_create/include/tbbr/tbb_cert.h @@ -46,7 +46,8 @@ enum { 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 03b12d7ae..ecbe8669d 100644 --- a/tools/cert_create/include/tbbr/tbb_ext.h +++ b/tools/cert_create/include/tbbr/tbb_ext.h @@ -46,7 +46,10 @@ enum { 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 b7ad33fe3..de15ef6fe 100644 --- a/tools/cert_create/src/main.c +++ b/tools/cert_create/src/main.c @@ -217,8 +217,11 @@ static void check_cmd_params(void) } 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 @@ int main(int argc, char *argv[]) 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 770bd6a0a..59a1cd9c7 100644 --- a/tools/cert_create/src/tbbr/tbb_cert.c +++ b/tools/cert_create/src/tbbr/tbb_cert.c @@ -160,6 +160,20 @@ static cert_t tbb_certs[] = { 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 c39c9e6a4..b0af6f1a5 100644 --- a/tools/cert_create/src/tbbr/tbb_ext.c +++ b/tools/cert_create/src/tbbr/tbb_ext.c @@ -145,6 +145,33 @@ static ext_t tbb_ext[] = { .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 c6869f956..571318406 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 @@ uuid_t uuid_null = {0}; /* 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,