blob: 08dccfb807dd6c215a15b17f035e597fa5fba623 [file] [log] [blame]
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
* Copyright (c) 2017-2020 Arm Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include "bl2_util.h"
#include "target.h"
#include "tfm_hal_device_header.h"
#include "Driver_Flash.h"
#include "mbedtls/memory_buffer_alloc.h"
#include "bootutil/bootutil_log.h"
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
#include "flash_map_backend/flash_map_backend.h"
#include "boot_record.h"
#include "security_cnt.h"
#include "boot_hal.h"
#if MCUBOOT_LOG_LEVEL > MCUBOOT_LOG_LEVEL_OFF
#include "uart_stdout.h"
#endif
#if defined(CRYPTO_HW_ACCELERATOR) || \
defined(CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING)
#include "crypto_hw.h"
#endif
/* Avoids the semihosting issue */
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
__asm(" .global __ARM_use_no_argv\n");
#endif
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
/* Macros to pick linker symbols */
#define REGION(a, b, c) a##b##c
#define REGION_NAME(a, b, c) REGION(a, b, c)
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
#endif
/* Flash device name must be specified by target */
extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
#define BL2_MBEDTLS_MEM_BUF_LEN 0x2000
/* Static buffer to be used by mbedtls for memory allocation */
static uint8_t mbedtls_mem_buf[BL2_MBEDTLS_MEM_BUF_LEN];
struct arm_vector_table {
uint32_t msp;
uint32_t reset;
};
/*!
* \brief Chain-loading the next image in the boot sequence.
*
* This function calls the Reset_Handler of the next image in the boot sequence,
* usually it is the secure firmware. Before passing the execution to next image
* there is conditional rule to remove the secrets from the memory. This must be
* done if the following conditions are satisfied:
* - Memory is shared between SW components at different stages of the trusted
* boot process.
* - There are secrets in the memory: KDF parameter, symmetric key,
* manufacturer sensitive code/data, etc.
*/
__attribute__((naked)) void boot_jump_to_next_image(uint32_t reset_handler_addr)
{
__ASM volatile(
".syntax unified \n"
"mov r7, r0 \n"
"bl boot_clear_bl2_ram_area \n" /* Clear RAM before jump */
"movs r0, #0 \n" /* Clear registers: R0-R12, */
"mov r1, r0 \n" /* except R7 */
"mov r2, r0 \n"
"mov r3, r0 \n"
"mov r4, r0 \n"
"mov r5, r0 \n"
"mov r6, r0 \n"
"mov r8, r0 \n"
"mov r9, r0 \n"
"mov r10, r0 \n"
"mov r11, r0 \n"
"mov r12, r0 \n"
"mov lr, r0 \n"
"bx r7 \n" /* Jump to Reset_handler */
);
}
static void do_boot(struct boot_rsp *rsp)
{
/* Clang at O0, stores variables on the stack with SP relative addressing.
* When manually set the SP then the place of reset vector is lost.
* Static variables are stored in 'data' or 'bss' section, change of SP has
* no effect on them.
*/
static struct arm_vector_table *vt;
uintptr_t flash_base;
int rc;
/* The beginning of the image is the ARM vector table, containing
* the initial stack pointer address and the reset vector
* consecutively. Manually set the stack pointer and jump into the
* reset vector
*/
rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
assert(rc == 0);
if (rsp->br_hdr->ih_flags & IMAGE_F_RAM_LOAD) {
/* The image has been copied to SRAM, find the vector table
* at the load address instead of image's address in flash
*/
vt = (struct arm_vector_table *)(rsp->br_hdr->ih_load_addr +
rsp->br_hdr->ih_hdr_size);
} else {
/* Using the flash address as not executing in SRAM */
vt = (struct arm_vector_table *)(flash_base +
rsp->br_image_off +
rsp->br_hdr->ih_hdr_size);
}
rc = FLASH_DEV_NAME.Uninitialize();
if(rc != ARM_DRIVER_OK) {
BOOT_LOG_ERR("Error while uninitializing Flash Interface");
}
#if MCUBOOT_LOG_LEVEL > MCUBOOT_LOG_LEVEL_OFF
stdio_uninit();
#endif
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
/* Restore the Main Stack Pointer Limit register's reset value
* before passing execution to runtime firmware to make the
* bootloader transparent to it.
*/
__set_MSPLIM(0);
#endif
__set_MSP(vt->msp);
__DSB();
__ISB();
boot_jump_to_next_image(vt->reset);
}
int main(void)
{
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
uint32_t msp_stack_bottom =
(uint32_t)&REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
#endif
struct boot_rsp rsp;
int rc;
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
__set_MSPLIM(msp_stack_bottom);
#endif
#if MCUBOOT_LOG_LEVEL > MCUBOOT_LOG_LEVEL_OFF
stdio_init();
#endif
BOOT_LOG_INF("Starting bootloader");
/* Initialise the mbedtls static memory allocator so that mbedtls allocates
* memory from the provided static buffer instead of from the heap.
*/
mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf, BL2_MBEDTLS_MEM_BUF_LEN);
#ifdef CRYPTO_HW_ACCELERATOR
rc = crypto_hw_accelerator_init();
if (rc) {
BOOT_LOG_ERR("Error while initializing cryptographic accelerator.");
while (1);
}
#endif /* CRYPTO_HW_ACCELERATOR */
rc = FLASH_DEV_NAME.Initialize(NULL);
if(rc != ARM_DRIVER_OK) {
BOOT_LOG_ERR("Error while initializing Flash Interface");
while (1)
;
}
#ifndef MCUBOOT_USE_UPSTREAM
rc = boot_nv_security_counter_init();
if (rc != 0) {
BOOT_LOG_ERR("Error while initializing the security counter");
while (1)
;
}
#endif /* !MCUBOOT_USE_UPSTREAM */
rc = boot_go(&rsp);
if (rc != 0) {
BOOT_LOG_ERR("Unable to find bootable image");
while (1)
;
}
#ifdef CRYPTO_HW_ACCELERATOR
rc = crypto_hw_accelerator_finish();
if (rc) {
BOOT_LOG_ERR("Error while uninitializing cryptographic accelerator.");
while (1);
}
#endif /* CRYPTO_HW_ACCELERATOR */
/* This is a workaround to program the TF-M related cryptographic keys
* to CC312 OTP memory. This functionality is independent from secure boot,
* this is usually done in the factory floor during chip manufacturing.
*/
#ifdef CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING
BOOT_LOG_INF("OTP provisioning started.");
rc = crypto_hw_accelerator_otp_provisioning();
if (rc) {
BOOT_LOG_ERR("OTP provisioning FAILED: 0x%X", rc);
while (1);
} else {
BOOT_LOG_INF("OTP provisioning succeeded. TF-M won't be loaded.");
/* We don't need to boot - the only aim is provisioning. */
while (1);
}
#endif /* CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING */
BOOT_LOG_INF("Bootloader chainload address offset: 0x%x",
rsp.br_image_off);
BOOT_LOG_INF("Jumping to the first image slot");
do_boot(&rsp);
BOOT_LOG_ERR("Never should get here");
while (1)
;
}