aboutsummaryrefslogtreecommitdiffstats
path: root/bl1/bl1_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'bl1/bl1_main.c')
-rw-r--r--bl1/bl1_main.c344
1 files changed, 201 insertions, 143 deletions
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index 491fd5cf..821b6a35 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -1,69 +1,32 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2017, 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.
+ * SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
-#include <auth.h>
+#include <auth_mod.h>
+#include <bl1.h>
#include <bl_common.h>
+#include <console.h>
#include <debug.h>
+#include <errata_report.h>
#include <platform.h>
#include <platform_def.h>
+#include <smcc_helpers.h>
+#include <utils.h>
+#include <uuid.h>
#include "bl1_private.h"
-/*******************************************************************************
- * Runs BL2 from the given entry point. It results in dropping the
- * exception level
- ******************************************************************************/
-static void __dead2 bl1_run_bl2(entry_point_info_t *bl2_ep)
-{
- bl1_arch_next_el_setup();
-
- /* Tell next EL what we want done */
- bl2_ep->args.arg0 = RUN_IMAGE;
-
- if (GET_SECURITY_STATE(bl2_ep->h.attr) == NON_SECURE)
- change_security_state(GET_SECURITY_STATE(bl2_ep->h.attr));
+/* BL1 Service UUID */
+DEFINE_SVC_UUID(bl1_svc_uid,
+ 0xfd3967d4, 0x72cb, 0x4d9a, 0xb5, 0x75,
+ 0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a);
- write_spsr_el3(bl2_ep->spsr);
- write_elr_el3(bl2_ep->pc);
- 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
@@ -79,125 +42,158 @@ static void __dead2 bl1_run_bl2(entry_point_info_t *bl2_ep)
void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
meminfo_t *bl2_mem_layout)
{
- const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
assert(bl1_mem_layout != NULL);
assert(bl2_mem_layout != NULL);
+#if LOAD_IMAGE_V2
+ /*
+ * Remove BL1 RW data from the scope of memory visible to BL2.
+ * This is assuming BL1 RW data is at the top of bl1_mem_layout.
+ */
+ assert(BL1_RW_BASE > bl1_mem_layout->total_base);
+ bl2_mem_layout->total_base = bl1_mem_layout->total_base;
+ bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
+#else
/* 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;
reserve_mem(&bl2_mem_layout->total_base,
&bl2_mem_layout->total_size,
BL1_RAM_BASE,
- bl1_size);
+ BL1_RAM_LIMIT - BL1_RAM_BASE);
+#endif /* LOAD_IMAGE_V2 */
flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
}
/*******************************************************************************
* 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);
NOTICE("BL1: %s\n", build_message);
- INFO("BL1: RAM 0x%lx - 0x%lx\n", BL1_RAM_BASE, BL1_RAM_LIMIT);
+ INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE,
+ (void *)BL1_RAM_LIMIT);
-#if DEBUG
- unsigned long sctlr_el3 = read_sctlr_el3();
-#endif
- 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;
+ print_errata_status();
+#if ENABLE_ASSERTIONS
+ u_register_t val;
/*
* Ensure that MMU/Caches and coherency are turned on
*/
- assert(sctlr_el3 | SCTLR_M_BIT);
- assert(sctlr_el3 | SCTLR_C_BIT);
- assert(sctlr_el3 | SCTLR_I_BIT);
+#ifdef AARCH32
+ val = read_sctlr();
+#else
+ val = read_sctlr_el3();
+#endif
+ assert(val & SCTLR_M_BIT);
+ assert(val & SCTLR_C_BIT);
+ assert(val & SCTLR_I_BIT);
+ /*
+ * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
+ * provided platform value
+ */
+ val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
+ /*
+ * If CWG is zero, then no CWG information is available but we can
+ * at least check the platform value is less than the architectural
+ * maximum.
+ */
+ if (val != 0)
+ assert(CACHE_WRITEBACK_GRANULE == SIZE_FROM_LOG2_WORDS(val));
+ else
+ assert(CACHE_WRITEBACK_GRANULE <= MAX_CACHE_LINE_SIZE);
+#endif /* ENABLE_ASSERTIONS */
/* 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);
+
+ console_flush();
+}
+
+/*******************************************************************************
+ * 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();
-#if TRUSTED_BOARD_BOOT
- /* Initialize authentication module */
- auth_init();
+ INFO("BL1: Loading BL2\n");
- /*
- * Load the BL2 certificate into the BL2 region. This region will be
- * overwritten by the image, so the authentication module is responsible
- * for storing the relevant data from the certificate (keys, hashes,
- * etc.) so it can be used later.
- */
- err = load_image(bl1_tzram_layout,
- BL2_CERT_NAME,
- BL2_BASE,
- &bl2_image_info,
- NULL);
- if (err) {
- ERROR("Failed to load BL2 certificate.\n");
- panic();
- }
+#if LOAD_IMAGE_V2
+ err = load_auth_image(BL2_IMAGE_ID, image_info);
+#else
+ /* Load the BL2 image */
+ err = load_auth_image(bl1_tzram_layout,
+ BL2_IMAGE_ID,
+ image_info->image_base,
+ image_info,
+ ep_info);
- err = auth_verify_obj(AUTH_BL2_IMG_CERT, bl2_image_info.image_base,
- bl2_image_info.image_size);
- if (err) {
- ERROR("Failed to validate BL2 certificate.\n");
- panic();
- }
-#endif /* TRUSTED_BOARD_BOOT */
+#endif /* LOAD_IMAGE_V2 */
- /* Load the BL2 image */
- err = load_image(bl1_tzram_layout,
- BL2_IMAGE_NAME,
- BL2_BASE,
- &bl2_image_info,
- &bl2_ep);
if (err) {
- /*
- * TODO: print failure to load BL2 but also add a tzwdog timer
- * which will reset the system eventually.
- */
ERROR("Failed to load BL2 firmware.\n");
- panic();
+ plat_error_handler(err);
}
-#if TRUSTED_BOARD_BOOT
- err = auth_verify_obj(AUTH_BL2_IMG, bl2_image_info.image_base,
- bl2_image_info.image_size);
- if (err) {
- ERROR("Failed to validate BL2 image.\n");
- panic();
- }
-
- /* After working with data, invalidate the data cache */
- inv_dcache_range(bl2_image_info.image_base,
- (size_t)bl2_image_info.image_size);
-#endif /* TRUSTED_BOARD_BOOT */
-
/*
* Create a new layout of memory for BL2 as seen by BL1 i.e.
* tell it the amount of total and free memory available.
@@ -205,36 +201,98 @@ void bl1_main(void)
* to BL2. BL2 will read the memory layout before using its
* memory for other purposes.
*/
+#if LOAD_IMAGE_V2
+ bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->total_base;
+#else
bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base;
+#endif /* LOAD_IMAGE_V2 */
+
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;
+ ep_info->args.arg1 = (uintptr_t)bl2_tzram_layout;
NOTICE("BL1: Booting BL2\n");
- INFO("BL1: BL2 address = 0x%llx\n",
- (unsigned long long) bl2_ep.pc);
- INFO("BL1: BL2 spsr = 0x%x\n", bl2_ep.spsr);
- VERBOSE("BL1: BL2 memory layout address = 0x%llx\n",
- (unsigned long long) bl2_tzram_layout);
+ VERBOSE("BL1: BL2 memory layout address = %p\n",
+ (void *) bl2_tzram_layout);
+}
+
+/*******************************************************************************
+ * Function called just before handing over to the next BL to inform the user
+ * about the boot progress. In debug mode, also print details about the BL
+ * image's execution context.
+ ******************************************************************************/
+void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
+{
+#ifdef AARCH32
+ NOTICE("BL1: Booting BL32\n");
+#else
+ NOTICE("BL1: Booting BL31\n");
+#endif /* AARCH32 */
+ print_entry_point_info(bl_ep_info);
+}
+
+#if SPIN_ON_BL1_EXIT
+void print_debug_loop_message(void)
+{
+ NOTICE("BL1: Debug loop, spinning forever\n");
+ NOTICE("BL1: Please connect the debugger to continue\n");
+}
+#endif
+
+/*******************************************************************************
+ * 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);
- bl1_run_bl2(&bl2_ep);
+ case BL1_SMC_UID:
+ SMC_UUID_RET(handle, bl1_svc_uid);
- return;
+ 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);
}
/*******************************************************************************
- * Temporary function to print the fact that BL2 has done its job and BL31 is
- * about to be loaded. This is needed as long as printfs cannot be used
+ * BL1 SMC wrapper. This function is only used in AArch32 mode to ensure ABI
+ * compliance when invoking bl1_smc_handler.
******************************************************************************/
-void display_boot_progress(entry_point_info_t *bl31_ep_info)
+register_t bl1_smc_wrapper(uint32_t smc_fid,
+ void *cookie,
+ void *handle,
+ unsigned int flags)
{
- NOTICE("BL1: Booting BL3-1\n");
- INFO("BL1: BL3-1 address = 0x%llx\n",
- (unsigned long long)bl31_ep_info->pc);
- INFO("BL1: BL3-1 spsr = 0x%llx\n",
- (unsigned long long)bl31_ep_info->spsr);
- INFO("BL1: BL3-1 params address = 0x%llx\n",
- (unsigned long long)bl31_ep_info->args.arg0);
- INFO("BL1: BL3-1 plat params address = 0x%llx\n",
- (unsigned long long)bl31_ep_info->args.arg1);
+ register_t x1, x2, x3, x4;
+
+ assert(handle);
+
+ get_smc_params_from_ctx(handle, x1, x2, x3, x4);
+ return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
}