mcu_hi3321_watch/middleware/utils/bootloader/private/bootloader_utils.c
2025-05-26 20:15:20 +08:00

311 lines
9.8 KiB
C

/*
* Copyright (c) CompanyNameMagicTag 2018-2020. All rights reserved.
* Description:BT BOOTLOADER UTILS
* Author:
* Create: 2018-10-15
*/
#include "sha256.h"
#ifdef SECURITY_ROM
#include "memory_config.h"
#else
#include "flash.h"
#include "application_version.h"
#endif
#include "memory_core.h"
#ifdef EFUSE_INTERFACE_REPLACE
#include "efuse.h"
#else
#include "otp.h"
#endif
#include "build_version.h"
#include "securec.h"
#include "otp_map.h"
#include "panic.h"
#include "uart.h"
#include "arch_barrier.h"
#include "bootloader_utils.h"
#if (!(defined BUILD_APPLICATION_ROM))
#define SECURE_BOOT_CORE_STR_SECURE "Boot: Signed\r\n"
#define SECURE_BOOT_CORE_STR_INSECURE "Boot: Unsigned\r\n"
#define CRLF_STR "\r\n"
#endif
#define SSB_RAM_START APP_ITCM_ORIGIN
#define CRC_MASK 0xff000000
#define CRC_RIGHT_SHIFT_BIT 24
#define SSB_LENGTH_MASK 0xffffff
#ifndef SHA256_SIGNATURE_LEN
#define SHA256_SIGNATURE_LEN 32
#endif
#ifndef SHA_BLOCK_SIZE
#define SHA_BLOCK_SIZE 256
#endif
#define SSB_IAMGE_MIN_LEN FLASH_PAGE_SIZE
/** Vector active mask for the ICSR register */
#if CHIP_SOCMN1 || CHIP_BS25 || CHIP_WS63 || CHIP_BS21 || CHIP_WS53
#define ICSR_VECTACTIVE_MASK 0x62
#elif (CHIP_BRANDY == 1)
#define ICSR_VECTACTIVE_MASK 0x21
#else
#error "ICSR_VECTACTIVE_MASK not defined"
#endif
/** Vector key for the AIRCR register */
#define AIRCR_VECTKEY 0x5FA
#define SSB_SHA256_CRC_START_BYTE_LEN 1
/* Sets the cpu in a known state before continuing */
void bootloader_utils_cpu_init(void)
{
#if (ARCH == CM3) || (ARCH == CM7)
// Disable SysTick interrupt
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
// Reset if it is in interrupt context
if ((SCB->ICSR & ICSR_VECTACTIVE_MASK) != 0) {
dsb();
SCB->AIRCR = ((AIRCR_VECTKEY << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
dsb();
}
// Disable the maskable interrupts and enable global interrupts
NVIC->ICER[0] = 0xffffffff;
/* enable global interrupts */
__set_PRIMASK(0);
#endif
}
void bootloader_utils_print_boot_message(uart_bus_t uart_bus)
{
#if (!(defined BUILD_APPLICATION_ROM) && !(defined UNIT_TEST))
if (uart_bus != UART_BUS_NONE) {
uapi_uart_write(uart_bus, (uint8_t *)CRLF_STR, (uint16_t)strlen(CRLF_STR), 0);
uapi_uart_write(uart_bus, (uint8_t *)SECURE_BOOT_CORE_STR_INSECURE,
(uint16_t)strlen(SECURE_BOOT_CORE_STR_INSECURE), 0);
}
#else
UNUSED(uart_bus);
#endif
}
void bootloader_utils_init_modules(void)
{
}
bool bootloader_utils_core_has_code(core_images_e cimage)
{
memory_map *mem_map;
mem_map = memory_get_cached_core_map(cimage);
if (mem_map == NULL) {
panic(PANIC_CODELOADER, __LINE__);
return false; //lint !e527 unreachable code
}
return *((uint32_t *)(uintptr_t)(mem_map->code_addr)) != 0xFFFFFFFF;
}
uint32_t bootloader_utils_get_rom_version(void)
{
build_version_info_rom *version_info;
uint32_t version_location = ROM_START + VERSION_INFORMATION_OFFSET;
version_info = (build_version_info_rom *)((uintptr_t)version_location);
return version_info->version;
}
#if defined(BUILD_APPLICATION_SSB)
uint32_t bootloader_utils_get_ssb_version(void)
{
build_version_info *version_info = NULL;
uint32_t version_location = APP_ITCM_ORIGIN + VERSION_INFORMATION_OFFSET;
version_info = (build_version_info *)((uintptr_t)version_location);
return version_info->version;
}
#endif
uint32_t bootloader_utils_get_flash_version(void)
{
build_version_info *version_info = NULL;
uint32_t version_location;
memory_map *map = memory_get_cached_core_map(CORE_IMAGES_BT);
if (map == NULL) {
return 0;
}
version_location = map->code_addr + VERSION_INFORMATION_OFFSET;
version_info = (build_version_info *)((uintptr_t)version_location);
return version_info->version;
}
bool bootloader_utils_is_code_in_flash(void)
{
#ifndef SECURITY_ROM
build_version_info *version_info = (build_version_info *)VERSION_INFORMATION_OFFSET;
return ((version_info->version & APPLICATION_CORE_FLASH_BUILD) == APPLICATION_CORE_FLASH_BUILD);
#else
return true;
#endif
}
bool bootloader_utils_ssb_get_length(uint32_t *length)
{
uint8_t ssb_length_crc;
uint8_t calc_crc = 0;
bool valid_ssb_length = false;
uint32_t ssb_length = 0;
*length = 0;
#if CORE == MASTER_BY_ALL
uint32_t ssb_len_otp_addr = OTP_SSB_CODE_SIZE_START;
#elif CORE == SECURITY
uint32_t ssb_len_otp_addr = OTP_SEC_SSB_CODE_SIZE_START;
#endif
// Check that the SSB length CRC matches SSB length
#ifdef EFUSE_INTERFACE_REPLACE
if (uapi_efuse_read_buffer((uint8_t *)&ssb_length, ssb_len_otp_addr, sizeof(uint32_t)) == ERRCODE_SUCC) {
ssb_length_crc = (ssb_length & CRC_MASK) >> CRC_RIGHT_SHIFT_BIT; // mask off CRC byte, top 8 bits, and shift
ssb_length &= SSB_LENGTH_MASK; // mask out CRC byte
if (uapi_efuse_calc_crc((uint8_t *)&ssb_length, OTP_SSB_CODE_SIZE_LENGTH, &calc_crc) == ERRCODE_SUCC) {
if ((uint8_t)ssb_length_crc == calc_crc) {
valid_ssb_length = true;
*length = ssb_length;
}
}
}
#else
if (otp_read_buffer((uint8_t *)&ssb_length, ssb_len_otp_addr, sizeof(uint32_t)) == OTP_RET_SUCC) {
ssb_length_crc = (ssb_length & CRC_MASK) >> CRC_RIGHT_SHIFT_BIT; // mask off CRC byte, top 8 bits, and shift
ssb_length &= SSB_LENGTH_MASK; // mask out CRC byte
if (otp_calc_crc((uint8_t *)&ssb_length, OTP_SSB_CODE_SIZE_LENGTH, &calc_crc) == OTP_RET_SUCC) {
if ((uint8_t)ssb_length_crc == calc_crc) {
valid_ssb_length = true;
*length = ssb_length;
}
}
}
#endif
return valid_ssb_length;
}
bool bootloader_utils_ssb_get_sha(uint8_t *sha, const uint8_t max_sha_len)
{
bool valid_sha = false;
uint8_t sha_crc = 0;
uint8_t calc_crc = 0;
UNUSED(max_sha_len);
#if CORE == MASTER_BY_ALL
uint32_t ssb_sha256_start = OTP_SSB_SHA256_START;
uint32_t ssb_sha256_crc_start = OTP_SSB_SHA256_CRC;
#elif CORE == SECURITY
uint32_t ssb_sha256_start = OTP_SEC_SSB_SHA256_START;
uint32_t ssb_sha256_crc_start = OTP_SEC_SSB_SHA256_CRC;
#endif
// Get SHA & SHA CRC and compare
#ifdef EFUSE_INTERFACE_REPLACE
if (uapi_efuse_read_buffer(sha, ssb_sha256_start, OTP_SSB_SHA256_LENGTH) == ERRCODE_SUCC) {
if (uapi_efuse_read_buffer(&sha_crc, ssb_sha256_crc_start, SSB_SHA256_CRC_START_BYTE_LEN) == ERRCODE_SUCC) {
if (uapi_efuse_calc_crc(sha, OTP_SSB_SHA256_LENGTH, &calc_crc) != ERRCODE_SUCC) {
return valid_sha;
}
if (calc_crc == sha_crc) {
valid_sha = true;
}
}
}
#else
if (otp_read_buffer(sha, ssb_sha256_start, OTP_SSB_SHA256_LENGTH) == OTP_RET_SUCC) {
if (otp_read_byte(&sha_crc, ssb_sha256_crc_start) == OTP_RET_SUCC) {
if (otp_calc_crc(sha, OTP_SSB_SHA256_LENGTH, &calc_crc) != OTP_RET_SUCC) {
return valid_sha;
}
if (calc_crc == sha_crc) {
valid_sha = true;
}
}
}
#endif
return valid_sha;
}
static bool iflash_core_check_sha256_region(const uint8_t *stored_sha256, uint32_t buffer_len,
uint32_t start, uint32_t length)
{
errcode_t ret;
bool valid_sha = false;
uint8_t result[SHA256_HASH_SIZE] = { 0 };
ret = uapi_drv_cipher_sha256((uint8_t*)(uintptr_t)start, length, result, sizeof(result));
if (ret != ERRCODE_SUCC) {
return false;
}
if (memcmp(result, stored_sha256, SHA256_HASH_SIZE) == 0) {
valid_sha = true;
}
UNUSED(buffer_len);
return valid_sha;
}
/*
* 1. Check that the SSB length CRC matches SSB length
* 2. Check that the SHA CRC matches the SHA. Not set will always fail.
* 3. Then check that the SHA matches the image.
*/
bool bootloader_utils_ssb_sha256_validate(void)
{
uint32_t ssb_length;
uint8_t stored_sha256[OTP_SSB_SHA256_LENGTH];
bool ssb_valid = false;
bool ssb_valid_length;
ssb_valid_length = bootloader_utils_ssb_get_length(&ssb_length);
if (!ssb_valid_length) { return false; }
#ifndef SECURITY_ROM
if (ssb_length > SSB_FLASH_REGION_LENGTH) { return false; }
#else
if (ssb_length > SEC_SSB_FLASH_REGION_LENGTH) { return false; }
#endif
if (ssb_length < SSB_IAMGE_MIN_LEN) { return false; }
// get sha and if valid, check image
if (bootloader_utils_ssb_get_sha(stored_sha256, sizeof(stored_sha256))) {
// check ram code
#ifndef SECURITY_ROM
if (iflash_core_check_sha256_region(stored_sha256, sizeof(stored_sha256), SSB_RAM_START, ssb_length)) {
// the ssb image content of the max length was read before, so here we need to clear unsafe redundant info
memset_s((uint8_t *)(uintptr_t)(SSB_RAM_START + ssb_length),
(uint32_t)(SSB_FLASH_REGION_LENGTH - ssb_length),
0,
(uint32_t)(SSB_FLASH_REGION_LENGTH - ssb_length));
ssb_valid = true;
}
#else
errcode_t ret;
uint8_t sha256[SHA256_HASH_SIZE] = { 0 };
ret = uapi_drv_cipher_sha256((uint8_t*)(uintptr_t)SEC_RAM_ORIGIN, ssb_length, sha256, sizeof(sha256));
if (ret != ERRCODE_SUCC) {
return false;
}
if (memcmp(sha256, stored_sha256, SHA256_HASH_SIZE) == 0) {
PRINT("SSB sha256 check success!" NEWLINE);
// the ssb image content of the max length was read before, so here we need to clear unsafe redundant info
memset_s((uint8_t *)(uintptr_t)(SEC_RAM_ORIGIN + ssb_length),
(uint32_t)(SEC_SSB_FLASH_REGION_LENGTH - ssb_length),
0,
(uint32_t)(SEC_SSB_FLASH_REGION_LENGTH - ssb_length));
ssb_valid = true;
}
#endif
}
return ssb_valid;
}