first commit

This commit is contained in:
2025-07-03 23:58:20 +08:00
commit ce2b3cdfd4
444 changed files with 65256 additions and 0 deletions

15
bootloader/CMakeLists.txt Executable file
View File

@ -0,0 +1,15 @@
#===============================================================================
# @brief cmake file
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved.
#===============================================================================
add_subdirectory_if_exist(bootrom)
add_subdirectory_if_exist(flashboot)
add_subdirectory_if_exist(provision)
if ((${CHIP} STREQUAL "bs21") OR (${CHIP} STREQUAL "bs21a") OR (${CHIP} STREQUAL "ws63") OR (${CHIP} STREQUAL "sw39") OR (${CHIP} STREQUAL "sw21"))
add_subdirectory_if_exist(commonboot)
endif()
add_subdirectory_if_exist(provision_${CHIP})
add_subdirectory_if_exist(flashboot_${CHIP})
add_subdirectory_if_exist(bootrom_${CHIP})

81
bootloader/Kconfig Executable file
View File

@ -0,0 +1,81 @@
#===============================================================================
# @brief Kconfig file.
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2023. All rights reserved.
#===============================================================================
config BOOT_SUPPORT_SEC
bool
prompt "BOOT SEC"
default n
help
This option means boot support sec.
if BOOT_SUPPORT_SEC
menu "Boot Sec Configuration"
comment "Boot hash"
osource "bootloader/commonboot/Kconfig"
endmenu
endif
config BOOT_SUPPORT_SECURE_VERIFY
bool
prompt "BOOT VERIFY"
default n
help
This option means boot support secure verify.
if BOOT_SUPPORT_SECURE_VERIFY
menu "Boot Secure Verify Configuration"
comment "Boot secure verify"
osource "bootloader/commonboot/Kconfig"
endmenu
endif
config BOOT_SUPPORT_PARTITION
bool
prompt "BOOT PARTITION"
default n
help
This option means boot support partition.
config LOADERBOOT_SUPPORT_EFUSE_BURN
bool
prompt "LOADERBOOT EFUSE BURN"
default n
help
This option means loaderboot support efuse burn.
config LOADERBOOT_SUPPORT_FLASH_CHIP_ERASE
bool
prompt "LOADERBOOT FLASH CHIP ERASE"
default n
help
This option means loaderboot support flash chip erase.
if LOADERBOOT_SUPPORT_EFUSE_BURN
menu "Loaderboot Hash Configuration"
comment "Boot hash"
osource "bootloader/commonboot/Kconfig"
endmenu
endif
config LOADERBOOT_SUPPORT_UPLOAD_DATA
bool
prompt "LOADERBOOT UPLOAD DATA"
default n
help
This option means loaderboot support data upload.
config LOADERBOOT_SUPPORT_READ_VERSION
bool
prompt "LOADERBOOT READ VERSION"
default n
help
This option means loaderboot support version read.
config LOADERBOOT_SUPPORT_SET_BUADRATE
bool
prompt "LOADERBOOT SET BUADRATE"
default n
help
This option means loaderboot support set baudrate.

View File

@ -0,0 +1,123 @@
#===============================================================================
# @brief cmake file
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2023. All rights reserved.
#===============================================================================
add_subdirectory_if_exist(libc)
set(COMPONENT_NAME "common_boot")
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_reset.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_flash.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_debug.c
)
if(${APPLICATION} STREQUAL "romboot")
set(SOURCES
${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_uart_auth.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_verify.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_ymodem.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_load.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_jump.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_crc16.c
)
endif()
if(${APPLICATION} STREQUAL "loaderboot")
set(SOURCES
${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_transfer.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_cmd_loop.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_ymodem.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_crc16.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_load.c
)
if(DEFINED CONFIG_LOADERBOOT_SUPPORT_EFUSE_BURN)
list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/boot_efuse_opt.c")
endif()
endif()
if(${APPLICATION} STREQUAL "flashboot")
set(SOURCES
${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_jump.c
)
endif()
set(PUBLIC_HEADER
${CMAKE_CURRENT_SOURCE_DIR}/include
)
set(PRIVATE_HEADER
)
set(PRIVATE_DEFINES
)
set(PUBLIC_DEFINES
)
# use this when you want to add ccflags like -include xxx
set(COMPONENT_PUBLIC_CCFLAGS
)
if (${CHIP} STREQUAL "sw39" OR ${CHIP} STREQUAL "sw21")
set(COMPONENT_CCFLAGS
)
else()
set(COMPONENT_CCFLAGS
)
endif()
set(WHOLE_LINK
true
)
set(MAIN_COMPONENT
false
)
build_component()
set(COMPONENT_NAME "flashboot_with_loadboot")
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_transfer.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_cmd_loop.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_ymodem.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_crc16.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_load.c
${CMAKE_CURRENT_SOURCE_DIR}/src/boot_uart_auth.c
)
set(PUBLIC_HEADER
)
set(PRIVATE_HEADER
)
set(PRIVATE_DEFINES
)
set(PUBLIC_DEFINES
)
# use this when you want to add ccflags like -include xxx
set(COMPONENT_PUBLIC_CCFLAGS
)
set(COMPONENT_CCFLAGS
)
set(WHOLE_LINK
true
)
set(MAIN_COMPONENT
false
)
build_component()

101
bootloader/commonboot/Kconfig Executable file
View File

@ -0,0 +1,101 @@
#===============================================================================
# @brief Kconfig file.
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2023. All rights reserved.
#===============================================================================
config BOOT_SUPPORT_HASH
bool
prompt "Hash"
default n
depends on BOOT_SUPPORT_SEC
help
This option means boot support hash check.
config BOOT_SUPPORT_ECC_VERIFY
bool
prompt "Ecc Verify"
default n
depends on BOOT_SUPPORT_SECURE_VERIFY
help
This option means boot support ecc verify.
config BOOT_SUPPORT_SM2_VERIFY
bool
prompt "Sm2 Verify"
default n
depends on BOOT_SUPPORT_SECURE_VERIFY
help
This option means boot support sm2 verify.
config BOOT_SUPPORT_RSA3072_VERIFY
bool
prompt "Rsa3072 Verify"
default n
depends on BOOT_SUPPORT_SECURE_VERIFY
help
This option means boot support rsa3072 verify.
config BOOT_SUPPORT_RSA4096_VERIFY
bool
prompt "Rsa4096 Verify"
default n
depends on BOOT_SUPPORT_SECURE_VERIFY
help
This option means boot support rsa4096 verify.
config BOOT_SUPPORT_SOFT_VERIFY
bool
prompt "Soft Verify"
default n
depends on BOOT_SUPPORT_SECURE_VERIFY
help
This option means boot support soft verify.
config FLASH_BOOT_SUPPORT_ROM_API
bool
prompt "flashboot support rom API"
default n
depends on BOOT_SUPPORT_SECURE_VERIFY
help
This option means flashboot support rom API.
if CHIP_WS63 || CHIP_WS53
config ROM_EXPEND_SUPPORT_NOT_ALIGNED
bool
prompt "expand rom sha256 API to support data_length not 64 bytes aligned. only need by ws63 & ws53."
default n
depends on FLASH_BOOT_SUPPORT_ROM_API
help
This option means the sha256 data_length support not 64 bytes aligned.
endif
config LOADERBOOT_SUPPORT_SW_HASH
bool
prompt "Loaderboot Support Software Hash"
default n
depends on LOADERBOOT_SUPPORT_EFUSE_BURN
help
This option means flashboot support software hash.
config LOADERBOOT_SUPPORT_DYNAMIC_PACKET_SIZE
bool
prompt "Loaderboot Support Dynamic Download Packet Size."
default n
help
This option means loaderboot support dynamic packet size.
config YMODEM_PACKET_BUFFER_SZIE
int
prompt "ymodem buffer size in loaderboot."
depends on LOADERBOOT_SUPPORT_DYNAMIC_PACKET_SIZE
default 1024
help
This option means the max buffer size to store ymodem packet.
config FLASH_WRITE_SIZE
int
prompt "flash write size for one time in loaderboot."
depends on LOADERBOOT_SUPPORT_DYNAMIC_PACKET_SIZE
default 1024
help
This option means write flash size for one time.

View File

@ -0,0 +1,44 @@
#===============================================================================
# @brief cmake file
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2023. All rights reserved.
#===============================================================================
set(COMPONENT_NAME "common_boot_libc")
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/string/memset.c
${CMAKE_CURRENT_SOURCE_DIR}/src/string/memcpy.c
${CMAKE_CURRENT_SOURCE_DIR}/src/string/memcmp.c
${CMAKE_CURRENT_SOURCE_DIR}/src/string/strcmp.c
${CMAKE_CURRENT_SOURCE_DIR}/src/string/strlen.c
${CMAKE_CURRENT_SOURCE_DIR}/src/string/memmove.c
)
set(PUBLIC_HEADER
${CMAKE_CURRENT_SOURCE_DIR}/include
)
set(PRIVATE_HEADER
)
set(PRIVATE_DEFINES
)
set(PUBLIC_DEFINES
)
# use this when you want to add ccflags like -include xxx
set(COMPONENT_PUBLIC_CCFLAGS
)
set(COMPONENT_CCFLAGS
)
set(WHOLE_LINK
true
)
set(MAIN_COMPONENT
false
)
build_component()

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2012-2019. All rights reserved.
* Description: Boot string function implementation.
*
* Create: 2012-12-22
*/
/**
* memcmp - Compare two areas of memory
* @cs: One area of memory
* @ct: Another area of memory
* @count: The size of the area.
*/
int memcmp(const void *cs, const void *ct, unsigned int count)
{
unsigned int cnt = count;
const unsigned char *l = cs;
const unsigned char *r = ct;
for (; (cnt != 0) && (*l == *r); cnt--, l++, r++) {
};
return (cnt != 0) ? *l - *r : 0;
}

View File

@ -0,0 +1,183 @@
#include <string.h>
#include <stdint.h>
#include <endian.h>
#ifdef __GNUC__
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LS >>
#define RS <<
#else
#define LS <<
#define RS >>
#endif
#define MEMCPY_BYTE_BITS 8
#define MEMCPY_ALIGH_UNIT_BYTES_4 4
#define MEMCPY_FAST_COPY_UNIT_NUM_4 4
#define MEMCPY_FAST_COPY_UNIT_BYTES (MEMCPY_ALIGH_UNIT_BYTES_4 * MEMCPY_FAST_COPY_UNIT_NUM_4)
#define MEMCPY_ALIGH_UNIT_BITS (MEMCPY_BYTE_BITS * MEMCPY_ALIGH_UNIT_BYTES_4)
#define MEMCPY_FAST_COPY_OFFSET_UNIT_0 (MEMCPY_ALIGH_UNIT_BYTES_4 * 0)
#define MEMCPY_FAST_COPY_OFFSET_UNIT_1 (MEMCPY_ALIGH_UNIT_BYTES_4 * 1)
#define MEMCPY_FAST_COPY_OFFSET_UNIT_2 (MEMCPY_ALIGH_UNIT_BYTES_4 * 2)
#define MEMCPY_FAST_COPY_OFFSET_UNIT_3 (MEMCPY_ALIGH_UNIT_BYTES_4 * 3)
#define MEMCPY_NOT_ALIGN_FAST_COPY_THRESHOLD (MEMCPY_FAST_COPY_UNIT_BYTES * 2)
#define MEMCPY_OFFSET_BYTES_1 1
#define MEMCPY_ALIGH_OFFSET_BYTES_1 (MEMCPY_ALIGH_UNIT_BYTES_4 - MEMCPY_OFFSET_BYTES_1)
#define MEMCPY_OFFSET_BITS_1 (MEMCPY_BYTE_BITS * MEMCPY_OFFSET_BYTES_1)
#define MEMCPY_OFFSET_ALIGN_BITS_1 (MEMCPY_BYTE_BITS * MEMCPY_ALIGH_OFFSET_BYTES_1)
#define MEMCPY_OFFSET_BYTES_2 2
#define MEMCPY_ALIGH_OFFSET_BYTES_2 (MEMCPY_ALIGH_UNIT_BYTES_4 - MEMCPY_OFFSET_BYTES_2)
#define MEMCPY_OFFSET_BITS_2 (MEMCPY_BYTE_BITS * MEMCPY_OFFSET_BYTES_2)
#define MEMCPY_OFFSET_ALIGN_BITS_2 (MEMCPY_BYTE_BITS * MEMCPY_ALIGH_OFFSET_BYTES_2)
#define MEMCPY_OFFSET_BYTES_3 3
#define MEMCPY_ALIGH_OFFSET_BYTES_3 (MEMCPY_ALIGH_UNIT_BYTES_4 - MEMCPY_OFFSET_BYTES_3)
#define MEMCPY_OFFSET_BITS_3 (MEMCPY_BYTE_BITS * MEMCPY_OFFSET_BYTES_3)
#define MEMCPY_OFFSET_ALIGN_BITS_3 (MEMCPY_BYTE_BITS * MEMCPY_ALIGH_OFFSET_BYTES_3)
#define MEMCPY_BYTE_CHECK_NUM_1 0x01
#define MEMCPY_BYTE_CHECK_NUM_2 0x02
#define MEMCPY_BYTE_CHECK_NUM_4 0x04
#define MEMCPY_BYTE_CHECK_NUM_8 0x08
#define MEMCPY_BYTE_CHECK_NUM_16 0x10
#endif
void *memcpy(void *restrict dest, const void *restrict src, size_t num)
{
unsigned char *d = dest;
const unsigned char *s = src;
size_t n = num;
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) u32;
uint32_t w, x;
for (; (uintptr_t)s % MEMCPY_ALIGH_UNIT_BYTES_4 && n; n--) {
*d++ = *s++;
}
if ((uintptr_t)d % MEMCPY_ALIGH_UNIT_BYTES_4 == 0) {
for (; n >= MEMCPY_FAST_COPY_UNIT_BYTES; s += MEMCPY_FAST_COPY_UNIT_BYTES,
d += MEMCPY_FAST_COPY_UNIT_BYTES, n -= MEMCPY_FAST_COPY_UNIT_BYTES) {
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_0) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_0);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_1) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_1);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_2) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_2);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_3) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_3);
}
if (n & MEMCPY_FAST_COPY_OFFSET_UNIT_2) {
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_0) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_0);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_1) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_1);
d += MEMCPY_FAST_COPY_OFFSET_UNIT_2;
s += MEMCPY_FAST_COPY_OFFSET_UNIT_2;
}
if (n & MEMCPY_FAST_COPY_OFFSET_UNIT_1) {
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_0) = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_0);
d += MEMCPY_FAST_COPY_OFFSET_UNIT_1;
s += MEMCPY_FAST_COPY_OFFSET_UNIT_1;
}
if (n & MEMCPY_BYTE_CHECK_NUM_2) {
*d++ = *s++; *d++ = *s++;
}
if (n & MEMCPY_BYTE_CHECK_NUM_1) {
*d = *s;
}
return dest;
}
if (n >= MEMCPY_NOT_ALIGN_FAST_COPY_THRESHOLD) {
switch ((uintptr_t)d % MEMCPY_ALIGH_UNIT_BYTES_4) {
case MEMCPY_OFFSET_BYTES_1:
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
n -= MEMCPY_ALIGH_OFFSET_BYTES_1;
for (; n >= MEMCPY_FAST_COPY_UNIT_BYTES + MEMCPY_OFFSET_BYTES_1; s += MEMCPY_FAST_COPY_UNIT_BYTES,
d += MEMCPY_FAST_COPY_UNIT_BYTES, n -= MEMCPY_FAST_COPY_UNIT_BYTES) {
x = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_0 + MEMCPY_OFFSET_BYTES_1);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_0) =
(w LS MEMCPY_OFFSET_ALIGN_BITS_1) | (x RS MEMCPY_OFFSET_BITS_1);
w = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_1 + MEMCPY_OFFSET_BYTES_1);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_1) =
(x LS MEMCPY_OFFSET_ALIGN_BITS_1) | (w RS MEMCPY_OFFSET_BITS_1);
x = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_2 + MEMCPY_OFFSET_BYTES_1);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_2) =
(w LS MEMCPY_OFFSET_ALIGN_BITS_1) | (x RS MEMCPY_OFFSET_BITS_1);
w = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_3 + MEMCPY_OFFSET_BYTES_1);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_3) =
(x LS MEMCPY_OFFSET_ALIGN_BITS_1) | (w RS MEMCPY_OFFSET_BITS_1);
}
break;
case MEMCPY_OFFSET_BYTES_2:
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
n -= MEMCPY_ALIGH_OFFSET_BYTES_2;
for (; n >= MEMCPY_FAST_COPY_UNIT_BYTES + MEMCPY_OFFSET_BYTES_2; s += MEMCPY_FAST_COPY_UNIT_BYTES,
d += MEMCPY_FAST_COPY_UNIT_BYTES, n -= MEMCPY_FAST_COPY_UNIT_BYTES) {
x = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_0 + MEMCPY_OFFSET_BYTES_2);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_0) =
(w LS MEMCPY_OFFSET_ALIGN_BITS_2) | (x RS MEMCPY_OFFSET_BITS_2);
w = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_1 + MEMCPY_OFFSET_BYTES_2);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_1) =
(x LS MEMCPY_OFFSET_ALIGN_BITS_2) | (w RS MEMCPY_OFFSET_BITS_2);
x = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_2 + MEMCPY_OFFSET_BYTES_2);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_2) =
(w LS MEMCPY_OFFSET_ALIGN_BITS_2) | (x RS MEMCPY_OFFSET_BITS_2);
w = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_3 + MEMCPY_OFFSET_BYTES_2);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_3) =
(x LS MEMCPY_OFFSET_ALIGN_BITS_2) | (w RS MEMCPY_OFFSET_BITS_2);
}
break;
case MEMCPY_OFFSET_BYTES_3:
w = *(u32 *)s;
*d++ = *s++;
n -= MEMCPY_ALIGH_OFFSET_BYTES_3;
for (; n >= MEMCPY_FAST_COPY_UNIT_BYTES + MEMCPY_OFFSET_BYTES_3; s += MEMCPY_FAST_COPY_UNIT_BYTES,
d += MEMCPY_FAST_COPY_UNIT_BYTES, n -= MEMCPY_FAST_COPY_UNIT_BYTES) {
x = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_0 + MEMCPY_OFFSET_BYTES_3);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_0) =
(w LS MEMCPY_OFFSET_ALIGN_BITS_3) | (x RS MEMCPY_OFFSET_BITS_3);
w = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_1 + MEMCPY_OFFSET_BYTES_3);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_1) =
(x LS MEMCPY_OFFSET_ALIGN_BITS_3) | (w RS MEMCPY_OFFSET_BITS_3);
x = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_2 + MEMCPY_OFFSET_BYTES_3);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_2) =
(w LS MEMCPY_OFFSET_ALIGN_BITS_3) | (x RS MEMCPY_OFFSET_BITS_3);
w = *(u32 *)(s + MEMCPY_FAST_COPY_OFFSET_UNIT_3 + MEMCPY_OFFSET_BYTES_3);
*(u32 *)(d + MEMCPY_FAST_COPY_OFFSET_UNIT_3) =
(x LS MEMCPY_OFFSET_ALIGN_BITS_3) | (w RS MEMCPY_OFFSET_BITS_3);
}
break;
}
}
if (n & MEMCPY_BYTE_CHECK_NUM_16) {
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
}
if (n & MEMCPY_BYTE_CHECK_NUM_8) {
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
}
if (n & MEMCPY_BYTE_CHECK_NUM_4) {
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
}
if (n & MEMCPY_BYTE_CHECK_NUM_2) {
*d++ = *s++; *d++ = *s++;
}
if (n & MEMCPY_BYTE_CHECK_NUM_1) {
*d = *s;
}
return dest;
#endif
for (; n; n--) *d++ = *s++;
return dest;
}

View File

@ -0,0 +1,60 @@
#include <string.h>
#include <stdint.h>
#ifdef __GNUC__
typedef __attribute__((__may_alias__)) size_t WT;
#define WS (sizeof(WT))
#endif
void *memmove(void *dest, const void *src, size_t size)
{
char *d = dest;
const char *s = src;
if (d == s) {
return d;
}
if ((uintptr_t)s-(uintptr_t)d-size <= -2*size) {
return memcpy(d, s, size);
}
if (d < s) {
#ifdef __GNUC__
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
while ((uintptr_t)d % WS) {
if (!size--) {
return dest;
}
*d++ = *s++;
}
for (; size>=WS; size-=WS, d+=WS, s+=WS) {
*(WT *)d = *(WT *)s;
}
}
#endif
for (; size; size--) {
*d++ = *s++;
}
} else {
#ifdef __GNUC__
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
while ((uintptr_t)(d+size) % WS) {
if (!size--) {
return dest;
}
d[size] = s[size];
}
while (size>=WS) {
size-=WS, *(WT *)(d+size) = *(WT *)(s+size);
}
}
#endif
while (size) {
size--, d[size] = s[size];
}
}
return dest;
}

View File

@ -0,0 +1,99 @@
#include <string.h>
#include <stdint.h>
#if defined(__LITEOS__) && defined(LOSCFG_BASE_MEM_NODE_SIZE_CHECK)
#include "los_memory.h"
static int __memset_check(void *dest, unsigned int nodeLength)
{
unsigned int ret;
unsigned int totalSize = 0;
unsigned int availSize = 0;
unsigned char *pool = m_aucSysMem1;
ret = LOS_MemNodeSizeCheck(pool, dest, &totalSize, &availSize);
if ((ret == 0) && (nodeLength > availSize)) {
return -1;
}
return 0;
}
#endif
void *memset(void *dest, int c, size_t n)
{
typedef uint32_t __attribute__((__may_alias__)) u32;
typedef uint64_t __attribute__((__may_alias__)) u64;
unsigned char *s = dest;
if (!n) {
return dest;
}
s[0] = c;
s[n-1] = c;
if (n <= 2) { // 2 bytes mem
return dest;
}
s[1] = c;
s[2] = c;
s[n-2] = c;
s[n-3] = c;
if (n <= 6) { // 6 bytes mem
return dest;
}
s[3] = c;
s[n-4] = c;
if (n <= 8) { // 8 bytes mem
return dest;
}
size_t k = -(uintptr_t)s & 3; // 3 : 4-byte boundary process
s += k;
n -= k;
n &= -4;
u32 c32 = ((u32)-1) / 255 * (unsigned char)c;
*(u32 *)(s + 0) = c32;
*(u32 *)(s + n - 4) = c32;
if (n <= 8) {
return dest;
}
*(u32 *)(s + 4) = c32;
*(u32 *)(s + 8) = c32;
*(u32 *)(s + n - 12) = c32;
*(u32 *)(s + n - 8) = c32;
if (n <= 24) { // 24 bytes mem
return dest;
}
*(u32 *)(s + 12) = c32;
*(u32 *)(s + 16) = c32;
*(u32 *)(s + 20) = c32;
*(u32 *)(s + 24) = c32;
*(u32 *)(s + n - 28) = c32;
*(u32 *)(s + n - 24) = c32;
*(u32 *)(s + n - 20) = c32;
*(u32 *)(s + n - 16) = c32;
k = 24 + ((uintptr_t)s & 4);
s += k;
n -= k;
u64 c64 = c32 | ((u64)c32 << 32);
for (; n >= 32; n -= 32, s += 32) {
*(u64 *)(s + 0) = c64;
*(u64 *)(s + 8) = c64;
*(u64 *)(s + 16) = c64;
*(u64 *)(s + 24) = c64;
}
return dest;
}

View File

@ -0,0 +1,7 @@
#include <string.h>
int strcmp(const char *l, const char *r)
{
for (; *l==*r && *l; l++, r++);
return *(unsigned char *)l - *(unsigned char *)r;
}

View File

@ -0,0 +1,25 @@
#include <string.h>
#include <stdint.h>
#include <limits.h>
#ifdef __LITEOS__
#undef ALIGN
#endif
#define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS)
size_t strlen(const char *s)
{
const char *a = s;
#ifdef __GNUC__
typedef size_t __attribute__((__may_alias__)) word;
const word *w;
for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
for (w = (const void *)s; !HASZERO(*w); w++);
s = (const void *)w;
#endif
for (; *s; s++);
return s-a;
}

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: boot Cmd
*
* Create: 2023-01-09
*/
#include "boot_def.h"
#include "boot_watchdog.h"
#include "boot_transfer.h"
#include "boot_delay.h"
#include "boot_reset.h"
#include "boot_ymodem.h"
#include "boot_load.h"
#include "boot_crc.h"
#include "securec.h"
#include "boot_cmd_loop.h"
#ifdef CONFIG_LOADERBOOT_SUPPORT_READ_VERSION
#include "boot_init.h"
#endif
#ifdef CONFIG_LOADERBOOT_SUPPORT_EFUSE_BURN
#include "boot_efuse_opt.h"
#endif
#ifdef CONFIG_LOADERBOOT_SUPPORT_FLASH_CHIP_ERASE
#include "boot_flash.h"
#include "boot_erase.h"
#include "sfc_porting.h"
#endif
#define CMD_RX_DELAY_MS 100 /* 100ms */
#define US_PER_MS 1000
#define CMD_FRAME_TIMEOUT 2000 /* 2 s */
#define CMD_ABNORMAL_MAX 100
#define CHECKSUM_SIZE 2
#define ACK_LEN 0x0C
#define BIT_U8 8
typedef enum {
CMD_RX_STATUS_WAIT_START_0,
CMD_RX_STATUS_WAIT_START_1,
CMD_RX_STATUS_WAIT_START_2,
CMD_RX_STATUS_WAIT_START_3,
CMD_RX_STATUS_WAIT_SIZE_0,
CMD_RX_STATUS_WAIT_SIZE_1,
CMD_RX_STATUS_WAIT_TYPE,
CMD_RX_STATUS_WAIT_PAD,
CMD_RX_STATUS_WAIT_DATA,
CMD_RX_STATUS_WAIT_CS_0,
CMD_RX_STATUS_WAIT_CS_1,
} cmd_rx_status;
typedef uint32_t(*cmd_func) (const uart_ctx *cmd_ctx);
typedef struct {
uint8_t cmd_type;
cmd_func cmdfunc;
} loader_cmd;
const loader_cmd g_loader_cmdtable[] = {
{ CMD_DL_IMAGE, loader_download_image },
{ CMD_RESET, loader_reset },
{ CMD_FACTORY_IMAGE, loader_download_image },
#ifdef CONFIG_LOADERBOOT_SUPPORT_EFUSE_BURN
{ CMD_BURN_EFUSE, loader_burn_efuse },
{ CMD_READ_EFUSE, loader_read_efuse },
#endif
#ifdef CONFIG_LOADERBOOT_SUPPORT_UPLOAD_DATA
{ CMD_UL_DATA, loader_upload_data },
#endif
#ifdef CONFIG_LOADERBOOT_SUPPORT_READ_VERSION
{ CMD_VERSION, loader_read_ver },
#endif
#ifdef CONFIG_LOADERBOOT_SUPPORT_SET_BUADRATE
{ CMD_SET_BUADRATE, loader_set_baudrate },
#endif
};
uint32_t loader_reset(const uart_ctx *cmd_ctx)
{
unused(cmd_ctx);
boot_msg0("\nReset device...\n");
loader_ack(ACK_SUCCESS);
mdelay(5); /* delay 5ms */
reset();
return ERRCODE_SUCC;
}
uint32_t loader_download_image(const uart_ctx *cmd_ctx)
{
uint32_t flash_size = FLASH_MEM_SIZE;
uint32_t download_addr = *(uint32_t *)(&cmd_ctx->packet.payload[0]);
uint32_t file_len = *(uint32_t *)(&cmd_ctx->packet.payload[4]); /* offset 4 is file length */
uint32_t erase_size = *(uint32_t *)(&cmd_ctx->packet.payload[8]); /* offset 8 is erase size */
uint8_t burn_efuse = cmd_ctx->packet.payload[12]; /* offset 12 is burn efuse flag */
#ifdef CONFIG_LOADERBOOT_SUPPORT_FLASH_CHIP_ERASE
uint32_t ret;
bool write_flash = false;
ret = loader_erase_all_process(cmd_ctx, &write_flash);
if (ret != ERRCODE_SUCC) {
boot_msg1("Chip Erase failure!", ret);
return ret;
}
if (!write_flash) {
// erase all only, no need to write flash, return.
return ERRCODE_SUCC;
}
#endif
if (file_len == 0 || (erase_size != 0 && erase_size < file_len) || (file_len > flash_size)) {
boot_msg0("Invalid params");
serial_puts("download_addr ");
serial_puthex(download_addr, 1);
serial_puts(" file_len ");
serial_puthex(file_len, 1);
serial_puts(" erase_size ");
serial_puthex(erase_size, 1);
serial_puts("\r\n");
return ERRCODE_FAIL;
}
if (cmd_ctx->packet.head.type == CMD_FACTORY_IMAGE) {
return download_factory_image(download_addr, erase_size, flash_size, burn_efuse);
}
return download_image(download_addr, erase_size, flash_size, burn_efuse);
}
#ifdef CONFIG_LOADERBOOT_SUPPORT_UPLOAD_DATA
uint32_t loader_upload_data(const uart_ctx *cmd_ctx)
{
uint32_t file_len = *(uint32_t *)(&cmd_ctx->packet.payload[0]);
uint32_t upload_addr = *(uint32_t *)(&cmd_ctx->packet.payload[4]); /* offset 4 is read addr */
if (file_len == 0 || file_len > FLASH_MEM_SIZE) {
boot_msg0("Upload length error");
return ERRCODE_FAIL;
}
if ((upload_addr & 0x3) != 0) {
boot_msg0("Upload addr error");
return ERRCODE_FAIL;
}
if ((upload_addr + file_len) > FLASH_MEM_SIZE) {
boot_msg0("Upload addr exceeds flash capacity");
return ERRCODE_FAIL;
}
return upload_data(upload_addr, file_len);
}
#endif
#ifdef CONFIG_LOADERBOOT_SUPPORT_READ_VERSION
uint32_t loader_read_ver(const uart_ctx *cmd_ctx)
{
unused(cmd_ctx);
errno_t ret;
uint8_t version[VERSION_STR_LEN] = { 0 };
ret = memcpy_s(version, VERSION_STR_LEN, (const void *)VERSION_STR_ADDR, VERSION_STR_LEN);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
serial_put_buf((const char *)version, VERSION_STR_LEN);
return ERRCODE_SUCC;
}
#endif
static uint32_t loader_frame_head_rx(uart_ctx *ctx)
{
uint8_t ch;
bool reset_flag = false;
uint16_t rcv = 0;
packet_data_head *head = &ctx->packet.head;
uint8_t *payload = (uint8_t *)head;
while (rcv <= CMD_ABNORMAL_MAX) {
boot_wdt_kick();
uint32_t ret = serial_getc_timeout(CMD_FRAME_TIMEOUT * US_PER_MS, &ch); /* read timeout < wdt timeout */
if (ret != ERRCODE_SUCC) {
continue;
}
rcv++;
if (reset_flag == true) {
reset_flag = false;
head->start_flag = 0;
ctx->status = CMD_RX_STATUS_WAIT_START_0;
}
if (ctx->status <= CMD_RX_STATUS_WAIT_START_3) {
uint32_t start_flag = UART_PACKET_START_FLAG;
uint8_t *start_byte = (uint8_t *)&start_flag;
if (ch == start_byte[ctx->status]) {
payload[ctx->status] = ch;
ctx->status++;
continue;
} else if (ch == 0xEF) {
payload[CMD_RX_STATUS_WAIT_START_0] = ch;
ctx->status = CMD_RX_STATUS_WAIT_START_1;
continue;
}
reset_flag = true;
continue;
} else {
payload[ctx->status] = ch;
if (ctx->status >= CMD_RX_STATUS_WAIT_START_1 && (head->packet_size > UART_PACKET_PAYLOAD_MAX)) {
reset_flag = true;
continue;
}
ctx->status++;
if (ctx->status >= CMD_RX_STATUS_WAIT_DATA) {
return ERRCODE_SUCC;
}
}
}
return ERRCODE_FAIL;
}
static uint32_t loader_frame_data_rx(uart_ctx *ctx)
{
uint8_t ch;
uint32_t ret;
ctx->received = 0;
packet_data_head *head = &ctx->packet.head;
uint8_t *payload = ctx->packet.payload;
while (ctx->received < (head->packet_size - sizeof(packet_data_head))) {
ret = serial_getc_timeout(CMD_RX_DELAY_MS * US_PER_MS, &ch);
if (ret == ERRCODE_SUCC) {
payload[ctx->received++] = ch;
continue;
}
return ERRCODE_FAIL;
}
ctx->packet.check_sum = (payload[head->packet_size - 9] << 8) | payload[head->packet_size - 10]; /* 8,9,10: sub */
payload[head->packet_size - 9] = 0; /* 9: sub 9 */
payload[head->packet_size - 10] = 0; /* 10: sub 10 */
if (ctx->received == (head->packet_size - sizeof(packet_data_head))) {
return ERRCODE_SUCC;
}
return ERRCODE_FAIL;
}
#ifdef CONFIG_LOADERBOOT_SUPPORT_SET_BUADRATE
uint32_t loader_set_baudrate(const uart_ctx *cmd_ctx)
{
uart_param_stru *uart;
uart = uart_baudrate_rcv(cmd_ctx);
if (uart == NULL) {
return ERRCODE_FAIL;
}
return serial_port_set_baudrate(uart);
}
#endif
void loader_ack(uint8_t err_code)
{
uart_ctx ctx = { 0 };
packet_data_head *head = &ctx.packet.head;
head->start_flag = UART_PACKET_START_FLAG;
head->type = CMD_ACK;
head->pad = (uint8_t)(~(CMD_ACK));
head->packet_size = ACK_LEN;
ctx.packet.payload[0] = err_code;
ctx.packet.payload[1] = ~err_code;
ctx.packet.check_sum = crc16_ccitt(0, (uint8_t *)&(ctx.packet), head->packet_size - CHECKSUM_SIZE);
serial_put_buf((const char *)&(ctx.packet), (int)(head->packet_size - CHECKSUM_SIZE));
serial_put_buf((const char *)&(ctx.packet.check_sum), CHECKSUM_SIZE);
}
static uint32_t loader_read_frame(uart_ctx *ctx)
{
packet_data_info *packet = &ctx->packet;
packet_data_head *head = &packet->head;
uint32_t ret;
/* Reset receiving status.CNcomment:复位接收状态 */
ctx->status = CMD_RX_STATUS_WAIT_START_0;
ctx->received = 0;
if (memset_s(packet, sizeof(packet_data_info), 0, sizeof(packet_data_info)) != EOK) {
return ERRCODE_FAIL;
}
ret = loader_frame_head_rx(ctx);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
ret = loader_frame_data_rx(ctx);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
uint16_t cs = crc16_ccitt(0, (uint8_t *)packet, head->packet_size - CHECKSUM_SIZE);
if (cs == packet->check_sum) {
return ERRCODE_SUCC;
}
return ERRCODE_FAIL;
}
static uint32_t loader_exe_cmd(uart_ctx *ctx)
{
uint32_t i;
packet_data_info *packet = &ctx->packet;
packet_data_head *head = &packet->head;
for (i = 0; i < sizeof(g_loader_cmdtable) / sizeof(g_loader_cmdtable[0]); i++) {
if (head->type == g_loader_cmdtable[i].cmd_type) {
if (g_loader_cmdtable[i].cmdfunc != NULL) {
return g_loader_cmdtable[i].cmdfunc(ctx);
}
}
}
boot_msg1("Unsupport CMD:", head->type);
return ERRCODE_FAIL;
}
void cmd_loop(uart_ctx *ctx)
{
uint32_t ret;
for (;;) {
ret = loader_read_frame(ctx);
if (ret != ERRCODE_SUCC) {
loader_ack(ACK_FAILURE);
continue;
}
ret = loader_exe_cmd(ctx);
if (ret != ERRCODE_SUCC) {
loader_ack(ACK_FAILURE);
continue;
}
boot_wdt_kick();
loader_ack(ACK_SUCCESS);
boot_msg0("Execution Successful");
boot_msg0("=========================");
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: CRC
*
* Create: 2023-01-09
*/
#include "boot_crc.h"
#include "boot_def.h"
/* Table of CRC constants - implements x^16+x^12+x^5+1 */
const uint16_t g_crc16_tab[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
};
uint16_t crc16_ccitt(uint16_t crc_start, uint8_t *buf, uint32_t len)
{
uint32_t i;
uint16_t cksum;
uint8_t *input_buf = buf;
if ((input_buf == NULL) || (len == 0)) {
return 0;
}
cksum = crc_start;
for (i = 0; i < len; i++) {
cksum = g_crc16_tab[((cksum >> 8) ^ *input_buf++) & 0xff] ^ (cksum << 8); /* 8 : shift move left or right */
}
return cksum;
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: debug
*
* Create: 2023-01-09
*/
#include "boot_debug.h"
#include "boot_def.h"
#include "boot_init.h"
void set_boot_status(hi_boot_start_status status)
{
uapi_reg_write16(STATUS_DEBUG_REG_ADDR, status);
}
uint16_t get_boot_status(void)
{
return uapi_reg_read_val16(STATUS_DEBUG_REG_ADDR);
}

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
* Description: boot Cmd
*
* Create: 2024-01-15
*/
#if defined(CONFIG_LOADERBOOT_SUPPORT_SW_HASH)
#include "sha256/sha256.h"
#else
#include "drv_rom_cipher.h"
#endif
#include "efuse_porting.h"
#include "efuse.h"
#include "boot_serial.h"
#include "string.h"
#include "soc_errno.h"
#include "boot_cmd_loop.h"
#include "boot_load.h"
#define SHA_256_LENGTH 32
#define THREE_BITS_OFFSET 3
typedef struct {
uint8_t hash[SHA_256_LENGTH]; /* hash of configuration file. */
uint8_t stru_ver; /* default 0. */
uint8_t stru_size; /* sizeof(struct otp_config_header). */
uint16_t number; /* Item number to be burn. */
uint32_t file_size; /* Configuration file size. */
uint32_t reserved[2]; /* Reserved 2 u32. */
uint8_t data[0]; /* Item: size = file_size - stru_size. */
} efuse_config_header;
typedef struct {
uint8_t stru_ver; /* default 0. */
uint8_t stru_size; /* sizeof(struct otp_config_item) */
uint16_t start_bit; /* Start bit of OTP */
uint16_t bit_width; /* Bit width */
uint16_t value_len; /* Length of value Byte(s), 4-byte-aligned. */
uint8_t value[0]; /* Item, offset: stru_size. */
} efuse_config_item;
static uint32_t efuse_cfg_verify(uintptr_t file_addr, uint32_t file_len)
{
uint8_t hash[SHA_256_LENGTH] = {0};
efuse_config_header *header = (efuse_config_header *)file_addr;
#if defined(CONFIG_LOADERBOOT_SUPPORT_SW_HASH)
sha256_context_t md;
(void)sha256_init(&md);
(void)SHA256Update(&md, (unsigned char *)((uintptr_t)&(header->stru_ver)), (file_len - SHA_256_LENGTH));
(void)sha256_final(&md, (unsigned char *)hash, SHA256_HASH_SIZE);
#else
uint32_t ret = (uint32_t)drv_rom_cipher_init();
if (ret != ERRCODE_SUCC) {
boot_msg1("drv_rom_cipher_init !!! ret = ", ret);
return ERRCODE_FAIL;
}
ret = (uint32_t)drv_rom_cipher_sha256(&(header->stru_ver), file_len - SHA_256_LENGTH, hash, SHA_256_LENGTH);
if (ret != ERRCODE_SUCC) {
boot_msg1("drv_rom_cipher_sha256 !!! ret = ", ret);
return ERRCODE_FAIL;
}
ret = (uint32_t)drv_rom_cipher_deinit();
if (ret != ERRCODE_SUCC) {
boot_msg1("drv_rom_cipher_deinit !!! ret = ", ret);
return ERRCODE_FAIL;
}
#endif
if (memcmp(header->hash, hash, SHA_256_LENGTH) != EOK) {
boot_msg0("hash commpare fail!!!");
return ERRCODE_FAIL;
}
if (header->number > (EFUSE_IDX_MAX)) {
boot_msg0("exceed efuse index!!!");
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
static uint32_t efuse_write_bits(uint16_t start_bit, uint16_t size, const uint8_t *key_data)
{
uint16_t i;
uint16_t j;
uint16_t a;
uint16_t b;
uint32_t ret;
uint16_t zero_count = 0;
/* j: the current bit offset of key_data. */
for (i = start_bit, j = 0; i < (start_bit + size); i++, j++) {
a = j >> THREE_BITS_OFFSET; /* subscript of receive array. */
b = j & 0x7; /* bit offset in one byte. */
if ((key_data[a] & (uint8_t)(1 << b)) != 0) {
ret = uapi_efuse_write_bit((i >> THREE_BITS_OFFSET), (i & 0x7));
if (ret != ERRCODE_SUCC) {
return ret;
}
} else {
zero_count++;
}
}
return ERRCODE_SUCC;
}
static uint32_t efuse_burn(uintptr_t file_addr, uint32_t file_len)
{
uint32_t ret = efuse_cfg_verify(file_addr, file_len);
if (ret != ERRCODE_SUCC) {
boot_msg0("Efuse config file invalid");
return ERRCODE_FAIL;
}
efuse_config_header *header = (efuse_config_header *)file_addr;
efuse_config_item *item = (efuse_config_item *)(file_addr + header->stru_size);
for (uint8_t i = 0; i < header->number; i++) {
if (item == NULL) {
return ERRCODE_FAIL;
}
ret = efuse_write_bits(item->start_bit, item->bit_width, item->value);
if (ret != ERRCODE_SUCC) {
boot_msg1("efuse write error, index:", i);
serial_puts("Start bit: ");
serial_puthex(item->start_bit, 1);
serial_puts(" len(bits)=");
serial_puthex(item->bit_width, 1);
serial_puts("\n");
}
item = (efuse_config_item *)((uintptr_t)item + item->stru_size + item->value_len);
}
return ERRCODE_SUCC;
}
static uint32_t loady_file(uintptr_t ram_addr)
{
uint32_t ret;
loader_ack(ACK_SUCCESS);
ret = loader_serial_ymodem(ram_addr, 0, sizeof(efuse_config_header), EFUSE_CFG_MAX_LEN);
return ret;
}
uint32_t loader_burn_efuse(const uart_ctx *cmd_ctx)
{
uint32_t ret;
uint32_t file_len = *(uint32_t *)(&cmd_ctx->packet.payload[0]);
if (file_len <= EFUSE_CFG_MIN_LEN || file_len > EFUSE_CFG_MAX_LEN) {
boot_msg1("File length error : ", file_len);
return ERRCODE_FAIL;
}
ret = loady_file((uintptr_t)BURN_EFUSE_BIN_ADDR);
if (ret != ERRCODE_SUCC) {
boot_msg1("Loady efuse file failed:", ret);
return ret;
}
ret = efuse_burn((uintptr_t)BURN_EFUSE_BIN_ADDR, file_len);
if (ret != ERRCODE_SUCC) {
return ret;
}
return ERRCODE_SUCC;
}
uint32_t loader_read_efuse(const uart_ctx *cmd_ctx)
{
uint32_t ret;
uint16_t efuse_id = *(uint16_t *)(&cmd_ctx->packet.payload[0]);
uint8_t data[EFUSE_READ_MAX_BYTE] = { 0 };
boot_msg0("Efuse read");
serial_puts("Start bit: ");
serial_puthex(efuse_id, 1);
serial_puts("\r\n");
if (efuse_id >= EFUSE_IDX_MAX) {
boot_msg0("Params err");
return ERRCODE_FAIL;
}
ret = efuse_read_item(efuse_id, data, EFUSE_READ_MAX_BYTE);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
for (uint8_t i = 0; i < EFUSE_READ_MAX_BYTE; i++) {
serial_puthex(data[i], 1);
serial_puts(" ");
}
return ERRCODE_SUCC;
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: boot erase
*
* Create: 2023-01-09
*/
#include "boot_def.h"
#include "boot_watchdog.h"
#include "boot_transfer.h"
#include "boot_delay.h"
#include "securec.h"
#include "boot_flash.h"
#include "sfc_porting.h"
#include "boot_cmd_loop.h"
#include "boot_erase.h"
static bool g_flash_all_erased = false;
bool loader_download_is_flash_all_erased(void)
{
return g_flash_all_erased;
}
void loader_download_set_flash_all_erase(bool all_erased)
{
g_flash_all_erased = all_erased;
}
static uint32_t loader_get_erasing_writing(const uart_ctx *cmd_ctx, bool *need_erase_all, bool *need_write)
{
uint32_t file_len = *(uint32_t *)(&cmd_ctx->packet.payload[4]); /* offset 4 is file length */
uint32_t erase_size = *(uint32_t *)(&cmd_ctx->packet.payload[8]); /* offset 8 is erase size */
if (cmd_ctx->packet.head.type != CMD_DL_IMAGE) {
return ERRCODE_FAIL;
}
*need_erase_all = false;
*need_write = false;
if (erase_size == FLASH_CHIP_ERASE_SIZE) {
*need_erase_all = true;
}
if (file_len != FLASH_CHIP_ERASE_FILE_LEN) {
*need_write = true;
}
return ERRCODE_SUCC;
}
uint32_t loader_erase_all_process(const uart_ctx *cmd_ctx, bool *write_flash)
{
uint32_t ret;
bool need_erase_all = false;
bool need_write = false;
ret = loader_get_erasing_writing(cmd_ctx, &need_erase_all, &need_write);
if (ret != ERRCODE_SUCC) {
return ret;
}
if (need_erase_all) {
flash_cmd_func *flash = boot_get_flash_funcs();
if (flash == NULL) {
return ERRCODE_FAIL;
}
boot_wdt_kick();
ret = flash->erase(0, FLASH_CHIP_ERASE_SIZE);
if (ret != ERRCODE_SUCC) {
return ret;
}
loader_download_set_flash_all_erase(true);
}
*write_flash = need_write;
return ERRCODE_SUCC;
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: flash
*
* Create: 2023-01-09
*/
#include "boot_errcode.h"
#include "securec.h"
#include "boot_flash.h"
static flash_cmd_func g_flash_cmd_funcs;
flash_cmd_func *boot_get_flash_funcs(void)
{
return &g_flash_cmd_funcs;
}
uint32_t boot_regist_flash_cmd(const flash_cmd_func *funcs)
{
if (memcpy_s(&g_flash_cmd_funcs, sizeof(flash_cmd_func), funcs, sizeof(flash_cmd_func)) != EOK) {
return ERRCODE_MEMCPY;
}
return ERRCODE_SUCC;
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: jump
*
* Create: 2023-01-09
*/
#include "boot_jump.h"
#include "boot_reset.h"
void jump_to_execute_addr(uint32_t addr)
{
void (*entry)(void) = (void*)(uintptr_t)(addr);
entry();
boot_fail();
}

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: load
*
* Create: 2023-01-09
*/
#include "boot_def.h"
#include "boot_ymodem.h"
#include "boot_serial.h"
#include "boot_flash.h"
#include "boot_watchdog.h"
#include "securec.h"
#ifdef PROVISION_WRITE_WITH_CMD
#include "boot_flash.h"
#endif
#include "boot_load.h"
static uint8_t g_ymodem_buf[READ_SIZE] = { 0 };
static uint32_t receive_file(uint32_t length, uint32_t erased_size, uintptr_t addr, uint32_t *size)
{
uint32_t read_len;
uint32_t file_length = length;
uintptr_t store_addr = addr;
while (file_length > 0) {
uint32_t read_size = (uint32_t)min(file_length, READ_SIZE);
read_len = ymodem_read(g_ymodem_buf, read_size);
if (read_len == 0 || file_length < read_len) {
return ERRCODE_FAIL;
}
#ifdef PROVISION_WRITE_WITH_INTERFACE
unused(erased_size);
flash_cmd_func *flash_ctr = boot_get_flash_funcs();
uint32_t ret = flash_ctr->write(store_addr - FLASH_START, read_len, g_ymodem_buf, 0);
if (ret != ERRCODE_SUCC) {
boot_msg1("flash write fail", ret);
return ERRCODE_FAIL;
}
#else
if (erased_size == 0) {
if (memcpy_s((void *)store_addr, (uint32_t)file_length, g_ymodem_buf, read_len) != EOK) {
return ERRCODE_FAIL;
}
} else {
if (memcpy_s((void *)store_addr, (uint32_t)file_length, g_ymodem_buf, read_len) != EOK) {
boot_msg0("flash write fail");
return ERRCODE_FAIL;
}
}
#endif
file_length -= read_len;
(*size) += read_len;
store_addr += (uint32_t)read_len;
boot_wdt_kick();
}
(void)ymodem_read(g_ymodem_buf, READ_SIZE);
return ERRCODE_SUCC;
}
uint32_t loader_serial_ymodem(uint32_t offset, uint32_t erased_size, uint32_t min, uint32_t max)
{
uint32_t size = 0;
uintptr_t store_addr = offset;
uint32_t file_length, ret;
ret = ymodem_open();
if (ret != ERRCODE_SUCC) {
goto err;
}
file_length = ymodem_get_length();
if (file_length <= min || file_length > max) {
boot_msg1("file length err : ", file_length);
goto err;
}
if ((erased_size != 0) && (erased_size < file_length)) {
boot_msg0("file_size > erase_size");
goto err;
}
if (receive_file(file_length, erased_size, store_addr, &size) != ERRCODE_SUCC) {
goto err;
}
if ((uint32_t)size == file_length) {
boot_msg1("total size:", (uint32_t)size);
ymodem_close();
return ERRCODE_SUCC;
}
err:
ymodem_close();
return ERRCODE_FAIL;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: reset
*
* Create: 2023-01-09
*/
#include "boot_reset.h"
#include "boot_def.h"
#include "boot_init.h"
#include "non_os.h"
#ifdef SUPPORT_GPIO
#include "hal_gpio.h"
#endif
void reset(void)
{
update_reset_count();
uapi_reg_write16(BOOT_PORTING_RESET_REG, BOOT_PORTING_RESET_VALUE);
for (;;) { }
}
void boot_fail(void)
{
/* wait for it... */
for (;;) { }
}

View File

@ -0,0 +1,346 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: transfer
*
* Create: 2023-01-09
*/
#include "boot_def.h"
#include "boot_serial.h"
#include "boot_load.h"
#include "boot_cmd_loop.h"
#include "boot_crc.h"
#include "boot_flash.h"
#include "boot_delay.h"
#include "boot_watchdog.h"
#include "boot_transfer.h"
#ifdef CONFIG_LOADERBOOT_SUPPORT_UPLOAD_DATA
#include "boot_malloc.h"
#endif
#include "boot_erase.h"
#ifdef CONFIG_LOADERBOOT_SUPPORT_UPLOAD_DATA
upload_context *g_upload_ctx = NULL;
#endif
static uint32_t download_to_flash(uint32_t flash_offset, uint32_t erase_size, uint32_t flash_size)
{
uint32_t size = erase_size;
uint32_t ret = ERRCODE_FAIL;
flash_cmd_func *flash_ctr = boot_get_flash_funcs();
boot_wdt_kick();
#ifdef CONFIG_LOADERBOOT_SUPPORT_FLASH_CHIP_ERASE
if ((size == FLASH_CHIP_ERASE_SIZE) && !loader_download_is_flash_all_erased()) {
#else
if (size == FLASH_CHIP_ERASE_SIZE) {
#endif
ret = flash_ctr->erase(0, FLASH_CHIP_ERASE_SIZE);
if (ret != ERRCODE_SUCC) {
boot_put_errno(ERRCODE_BOOT_FLASH_ERASE_ERR);
return ERRCODE_FAIL;
}
} else if (size != 0) {
ret = flash_ctr->erase(flash_offset, size);
if (ret != ERRCODE_SUCC) {
boot_put_errno(ERRCODE_BOOT_FLASH_ERASE_ERR);
return ERRCODE_FAIL;
}
} else { /* 0x0 indicates not erase */
size = FLASH_CHIP_ERASE_SIZE;
}
boot_wdt_kick();
boot_msg0("Ready for download");
loader_ack(ACK_SUCCESS);
ret = loader_serial_ymodem(flash_offset, size, 0, flash_size);
return ret;
}
uint32_t download_image(uint32_t addr, uint32_t erase_size, uint32_t flash_size, uint8_t burn_efuse)
{
uint32_t ret;
unused(burn_efuse);
ret = download_to_flash(addr, erase_size, flash_size);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
uint32_t download_factory_image(uint32_t addr, uint32_t erase_size, uint32_t flash_size, uint8_t burn_efuse)
{
uint32_t ret;
unused(burn_efuse);
ret = download_to_flash(addr, erase_size, flash_size);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
#ifdef CONFIG_LOADERBOOT_SUPPORT_UPLOAD_DATA
static uint32_t upload_malloc_init(void)
{
if (g_upload_ctx == NULL) {
g_upload_ctx = (upload_context *)boot_malloc(sizeof(upload_context));
}
if (g_upload_ctx == NULL) {
return ERRCODE_FAIL;
}
(void)memset_s(g_upload_ctx, sizeof(upload_context), 0, sizeof(upload_context));
return ERRCODE_SUCC;
}
static uint32_t upload_malloc_deinit(void)
{
return ERRCODE_SUCC;
}
static void upload_send_file_info(void)
{
upload_context *ctx = g_upload_ctx;
uint8_t name_length = UPLOAD_FILE_NAME_LEN;
uint8_t *data = NULL;
int32_t temp_length = (int32_t)ctx->file_length;
int32_t count = 0;
uint8_t temp_char;
uint16_t crc;
int32_t i;
if (ctx->retry > 0) {
serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
return;
}
(void)memset_s(ctx->buffer, sizeof(ctx->buffer), 0, sizeof(ctx->buffer));
ctx->buffer[0] = MODEM_SOH;
ctx->buffer[1] = ctx->seq;
ctx->buffer[2] = (uint8_t)~ctx->buffer[1]; /* buffer[2] is buffer[1] invert val */
if (memcpy_s(ctx->buffer + MSG_START_LEN, SOH_MSG_LEN, ctx->file_name, name_length) != EOK) {
return;
}
data = ctx->buffer + MSG_START_LEN + name_length;
while (temp_length > 0) {
data[count++] = (uint8_t)((uint8_t)'0' + (temp_length % DECIMAL));
temp_length /= DECIMAL;
}
/* 64 bytes, enough for storing 32-bit decimal digits
CNcomment:64字节足够存放32位10进制数 */
for (i = 0; i < count / 2; i++) { /* count should be divided by 2 */
temp_char = data[i];
data[i] = data[count - i - 1];
data[count - i - 1] = temp_char;
}
crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, SOH_MSG_LEN);
ctx->buffer[131] = (uint8_t)(crc >> 8); /* buffer[131] is crc high 8 bit */
ctx->buffer[132] = (uint8_t)crc; /* buffer[132] is crc low 8 bit */
serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
ctx->status = UPLOAD_WAIT_INIT_ACK;
}
static void upload_send_data(void)
{
upload_context *ctx = g_upload_ctx;
uint32_t remain = ctx->file_length - ctx->offset;
uint16_t crc;
if (ctx->retry > 0) {
if (ctx->buffer[0] == MODEM_SOH) {
serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
} else {
serial_put_buf((const char *)ctx->buffer, UPLOAD_BUFF_LEN);
}
return;
}
ctx->status = UPLOAD_WAIT_FINAL_ACK;
(void)memset_s(ctx->buffer, sizeof(ctx->buffer), MODEM_EOF, sizeof(ctx->buffer));
ctx->buffer[0] = MODEM_STX;
ctx->buffer[1] = ++ctx->seq;
ctx->buffer[2] = (uint8_t)~ctx->buffer[1]; /* buffer[2] is buffer[1] invert val */
if (remain <= SOH_MSG_LEN) {
ctx->buffer[0] = MODEM_SOH;
if (memcpy_s(ctx->buffer + MSG_START_LEN, SOH_MSG_LEN,
(const void *)(uintptr_t)(ctx->file_addr + ctx->offset), remain) != EOK) {
return;
}
crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, SOH_MSG_LEN);
ctx->buffer[131] = (uint8_t)(crc >> 8); /* buffer[131] is crc high 8 bit */
ctx->buffer[132] = (uint8_t)crc; /* buffer[132] is crc low 8 bit */
serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
} else {
if (remain > UPLOAD_DATA_SIZE) {
remain = UPLOAD_DATA_SIZE;
ctx->status = UPLOAD_WAIT_INTER_ACK;
}
if (memcpy_s(ctx->buffer + MSG_START_LEN, UPLOAD_DATA_SIZE,
(const void *)(uintptr_t)(ctx->file_addr + ctx->offset), remain) != EOK) {
return;
}
crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, UPLOAD_DATA_SIZE);
ctx->buffer[1027] = (uint8_t)(crc >> 8); /* buffer[1027] is crc high 8 bit */
ctx->buffer[1028] = (uint8_t)crc; /* buffer[1028] is crc low 8 bit */
serial_put_buf((const char *)ctx->buffer, UPLOAD_BUFF_LEN);
}
ctx->offset += remain;
boot_wdt_kick();
}
static void upload_send_null_info(void)
{
upload_context *ctx = g_upload_ctx;
uint16_t crc;
(void)memset_s(ctx->buffer, sizeof(ctx->buffer), 0, SOH_MSG_LEN);
ctx->buffer[0] = MODEM_SOH;
ctx->buffer[1] = 0;
ctx->buffer[2] = 0xFF; /* buffer[2] is buffer[1] invert val */
crc = crc16_ccitt(0, ctx->buffer + MSG_START_LEN, SOH_MSG_LEN);
ctx->buffer[131] = (uint8_t)(crc >> 8); /* buffer[131] is crc high 8 bit */
ctx->buffer[132] = (uint8_t)crc; /* buffer[132] is crc low 8 bit */
serial_put_buf((const char *)ctx->buffer, SOH_MSG_TOTAL_LEN);
ctx->status = UPLOAD_WAIT_ZERO_ACK;
}
static int32_t upload_modem_nak_step(uint8_t *status, uint32_t *timeout)
{
switch (*status) {
case UPLOAD_WAIT_INIT_ACK:
*timeout = UPLOAD_WAIT_START_C_TIME;
upload_send_file_info();
return 1;
case UPLOAD_WAIT_INTER_ACK:
case UPLOAD_WAIT_FINAL_ACK:
upload_send_data();
return 1;
case UPLOAD_WAIT_EOT_C:
serial_putc(MODEM_EOT);
*status = UPLOAD_WAIT_EOT_C;
return 1;
case UPLOAD_WAIT_ZERO_ACK:
upload_send_null_info();
return 1;
default:
return 0;
}
}
static uint32_t upload_modem_c_step(uint8_t status)
{
switch (status) {
case UPLOAD_WAIT_START_C:
upload_send_file_info();
return 1;
case UPLOAD_WAIT_TRANS_C:
upload_send_data();
return 1;
case UPLOAD_WAIT_EOT_C:
upload_send_null_info();
return 1;
default:
return 0;
}
}
static int32_t upload_modem_ack_step(uint8_t *status, uint32_t *timeout)
{
switch (*status) {
case UPLOAD_WAIT_INIT_ACK:
*timeout = UPLOAD_WAIT_DEFAULT_TIME;
*status = UPLOAD_WAIT_TRANS_C;
return 1;
case UPLOAD_WAIT_INTER_ACK:
upload_send_data();
return 1;
case UPLOAD_WAIT_FINAL_ACK:
serial_putc(MODEM_EOT);
*status = UPLOAD_WAIT_EOT_C;
return 1;
default:
return 0;
}
}
static uint32_t upload_serial_ymodem(void)
{
upload_context *ctx = g_upload_ctx;
uint8_t ch;
uint32_t timeout = UPLOAD_WAIT_START_C_TIME;
for (;;) {
uint32_t ret = serial_getc_timeout(timeout, &ch);
if (ret != ERRCODE_SUCC) {
continue;
}
if (ch == MODEM_C) {
ctx->can_cnt = 0;
ctx->retry = 0;
if (upload_modem_c_step(ctx->status) == 1) {
continue;
}
} else if (ch == MODEM_ACK) {
ctx->can_cnt = 0;
ctx->retry = 0;
if (ctx->status == UPLOAD_WAIT_ZERO_ACK) {
mdelay(WAIT_ZERO_ACK_DELAY);
return ERRCODE_SUCC;
}
if (upload_modem_ack_step(&ctx->status, (uint32_t *)&timeout) == 1) {
continue;
}
} else if (ch == MODEM_NAK) {
ctx->can_cnt = 0;
if (++ctx->retry == RETRY_COUNT) {
return ERRCODE_FAIL;
}
if (upload_modem_nak_step(&ctx->status, &timeout) == 1) {
continue;
}
} else if (ch == MODEM_CAN) {
ctx->retry = 0;
if (++ctx->can_cnt == CAN_COUNT) {
return ERRCODE_FAIL;
}
continue;
}
}
}
uint32_t upload_data(uint32_t addr, uint32_t length)
{
if (upload_malloc_init() != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
g_upload_ctx->file_addr = addr + FLASH_ADDR_OFFSET;
g_upload_ctx->file_length = length;
g_upload_ctx->file_name = UPLOAD_FILE_NAME;
g_upload_ctx->status = UPLOAD_WAIT_START_C;
loader_ack(ACK_SUCCESS);
if (upload_serial_ymodem() == ERRCODE_SUCC) {
return ERRCODE_SUCC;
}
upload_malloc_deinit();
return ERRCODE_FAIL;
}
#endif

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: uart auth
*
* Create: 2023-01-09
*/
#include "boot_uart_auth.h"
#include "boot_crc.h"
#include "boot_delay.h"
#include "boot_debug.h"
#include "boot_watchdog.h"
#include "securec.h"
#include "boot_cmd_loop.h"
#define UART_RX_DELAY_MS 100 /* 100ms */
#define US_PER_MS 1000
#define UTM_DISABLE 1
#define SDC_DISABLE 0
#define UART_ABNORMAL_MAX 32
#define RANDOM_RETRY_MAX 100
#define CHECKSUM_SIZE 2
#define UART_CFG_LEN 8
#define INTER_DATA_LEN 0x12
#define ACK_LEN 0x0C
#define ACK_SUCCESS 0x5A
#define ACK_FAILURE 0xA5
typedef enum {
RX_STATUS_WAIT_START_0,
RX_STATUS_WAIT_START_1,
RX_STATUS_WAIT_START_2,
RX_STATUS_WAIT_START_3,
RX_STATUS_WAIT_SIZE_0,
RX_STATUS_WAIT_SIZE_1,
RX_STATUS_WAIT_TYPE,
RX_STATUS_WAIT_PAD,
RX_STATUS_WAIT_DATA,
RX_STATUS_WAIT_CS_0,
RX_STATUS_WAIT_CS_1,
} rx_status;
uart_param_stru g_uart_param = { 0 };
static uint32_t g_uart_int_type = UART_TYPE_ROMBOOT_HANDSHAKE;
static uint8_t g_encrypt_flag = 0;
static uint32_t uart_frame_rx(uart_ctx *ctx, uint32_t first_byte_timeout_ms);
static uint32_t uart_frame_head_rx(uart_ctx *ctx, uint32_t first_byte_timeout_ms);
static uint32_t uart_frame_data_rx(uart_ctx *ctx);
static uint32_t uart_wait_usr_interrupt(uart_ctx *ctx, uint32_t interrupt_timeout_ms);
static uint32_t uart_usr_interrupt_verify(uart_ctx *ctx);
static uint32_t uart_frame_rx(uart_ctx *ctx, uint32_t first_byte_timeout_ms)
{
packet_data_info *packet = &ctx->packet;
packet_data_head *head = &packet->head;
uint32_t ret = ERRCODE_FAIL;
/* 复位接收状态 */
ctx->status = RX_STATUS_WAIT_START_0;
ctx->received = 0;
(void)memset_s(packet, sizeof(packet_data_info), 0, sizeof(packet_data_info));
ret = uart_frame_head_rx(ctx, first_byte_timeout_ms);
if (ret != ERRCODE_SUCC) {
return ret;
}
ret = uart_frame_data_rx(ctx);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
uint32_t cs = crc16_ccitt(0, (uint8_t *)packet, head->packet_size - CHECKSUM_SIZE);
if (cs == packet->check_sum) {
return ERRCODE_SUCC;
}
return ERRCODE_FAIL;
}
static uint32_t uart_frame_head_rx(uart_ctx *ctx, uint32_t first_byte_timeout_ms)
{
uint8_t ch;
bool reset_flag = false;
uint16_t rcv = 0;
uint32_t ret = ERRCODE_FAIL;
packet_data_head *head = &ctx->packet.head;
uint8_t *payload = (uint8_t *)head;
while (rcv <= UART_ABNORMAL_MAX) {
if (ctx->status == RX_STATUS_WAIT_START_0) {
ret = serial_getc_timeout(first_byte_timeout_ms * US_PER_MS, &ch);
} else {
ret = serial_getc_timeout(UART_RX_DELAY_MS * US_PER_MS, &ch);
}
if (ret != ERRCODE_SUCC) {
return (ctx->status == RX_STATUS_WAIT_START_0) ? UART_FIRST_CHAR_TIMEOUT : ERRCODE_FAIL;
}
rcv++;
if (reset_flag == true) {
reset_flag = false;
head->start_flag = 0;
ctx->status = RX_STATUS_WAIT_START_0;
}
if (ctx->status <= RX_STATUS_WAIT_START_3) {
uint32_t start_flag = UART_PACKET_START_FLAG;
uint8_t *start_byte = (uint8_t *)&start_flag;
if (ch == start_byte[ctx->status]) {
payload[ctx->status] = ch;
ctx->status++;
continue;
} else if (ch == 0xEF) {
payload[RX_STATUS_WAIT_START_0] = ch;
ctx->status = RX_STATUS_WAIT_START_1;
continue;
}
reset_flag = true;
continue;
} else {
payload[ctx->status] = ch;
if (ctx->status >= RX_STATUS_WAIT_SIZE_1 && (head->packet_size > UART_PACKET_PAYLOAD_MAX)) {
reset_flag = true;
continue;
}
ctx->status++;
if (ctx->status >= RX_STATUS_WAIT_DATA) {
return ERRCODE_SUCC;
}
}
boot_wdt_kick();
}
return ERRCODE_FAIL;
}
static uint32_t uart_frame_data_rx(uart_ctx *ctx)
{
uint8_t ch;
ctx->received = 0;
uint32_t ret = ERRCODE_FAIL;
packet_data_head *head = &ctx->packet.head;
uint8_t *payload = ctx->packet.payload;
while (ctx->received < (head->packet_size - sizeof(packet_data_head))) {
ret = serial_getc_timeout(UART_RX_DELAY_MS * US_PER_MS, &ch);
if (ret == ERRCODE_SUCC) {
payload[ctx->received++] = ch;
continue;
}
return ERRCODE_FAIL;
}
ctx->packet.check_sum = (payload[head->packet_size - 9] << 8) | payload[head->packet_size - 10]; /* 8,9,10: sub */
payload[head->packet_size - 9] = 0; /* 9: sub 9 */
payload[head->packet_size - 10] = 0; /* 10: sub 10 */
if (ctx->received == (head->packet_size - sizeof(packet_data_head))) {
return ERRCODE_SUCC;
}
return ERRCODE_FAIL;
}
static void uart_ack(uart_ctx *ctx)
{
packet_data_head *head = &ctx->packet.head;
head->start_flag = UART_PACKET_START_FLAG;
head->type = UART_TYPE_ACK;
head->pad = (uint8_t)(~(UART_TYPE_ACK));
head->packet_size = ACK_LEN;
ctx->packet.payload[0] = ACK_SUCCESS;
ctx->packet.payload[1] = g_encrypt_flag;
ctx->packet.check_sum = crc16_ccitt(0, (uint8_t *)&(ctx->packet), head->packet_size - CHECKSUM_SIZE);
serial_put_buf ((const char *)&(ctx->packet), (int)(head->packet_size - CHECKSUM_SIZE));
serial_put_buf ((const char *)&(ctx->packet.check_sum), CHECKSUM_SIZE);
}
uint32_t uart_process(uint32_t interrupt_timeout_ms)
{
uart_ctx uart_ctx = { 0 };
set_boot_status(HI_BOOT_WAIT_UART_INTERRUPT);
if (uart_wait_usr_interrupt(&uart_ctx, interrupt_timeout_ms) != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
uart_ack(&uart_ctx);
uart_ack(&uart_ctx);
uart_ack(&uart_ctx);
/* wait transmit ok */
mdelay(5); /* 5: wait 5 ms */
return ERRCODE_SUCC;
}
static uint32_t uart_wait_usr_interrupt(uart_ctx *ctx, uint32_t interrupt_timeout_ms)
{
volatile uint32_t ret = ERRCODE_FAIL;
ret = uart_frame_rx(ctx, interrupt_timeout_ms);
if (ret != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
return uart_usr_interrupt_verify(ctx);
}
static uint32_t uart_usr_interrupt_verify(uart_ctx *ctx)
{
packet_data_head *head = &ctx->packet.head;
if ((head->packet_size == INTER_DATA_LEN) && (g_uart_int_type == head->type)) {
if (head->type == UART_TYPE_ROMBOOT_HANDSHAKE) {
(void)memcpy_s((void *)&g_uart_param, sizeof(uart_param_stru),
(void *)(ctx->packet.payload), UART_CFG_LEN);
}
return ERRCODE_SUCC;
}
return ERRCODE_FAIL;
}
#ifdef CONFIG_LOADERBOOT_SUPPORT_SET_BUADRATE
uart_param_stru* uart_baudrate_rcv(const uart_ctx *ctx)
{
uart_ctx uart = { 0 };
packet_data_head *head = &(((uart_ctx*)ctx)->packet.head);
if ((head->packet_size != INTER_DATA_LEN) || (head->type != CMD_SET_BUADRATE)) {
return NULL;
}
(void)memcpy_s((void *)&g_uart_param, sizeof(uart_param_stru), (void *)(ctx->packet.payload), UART_CFG_LEN);
uart_ack(&uart);
mdelay(5); /* 5: wait 5 ms for transmit ok */
return &g_uart_param;
}
#endif

View File

@ -0,0 +1,416 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: ymodem
*
* Create: 2023-01-09
*/
#include "boot_errcode.h"
#include "boot_def.h"
#include "boot_crc.h"
#include "boot_delay.h"
#include "boot_serial.h"
#include "boot_watchdog.h"
#include "securec.h"
#include "boot_ymodem.h"
#ifndef CONFIG_LOADERBOOT_SUPPORT_DYNAMIC_PACKET_SIZE
#define YMODEM_PACKET_SIZE 1024 /* packet size: 1024 Bytes */
#else
#define YMODEM_PACKET_SIZE CONFIG_YMODEM_PACKET_BUFFER_SZIE
#endif
#define YMODEM_SOH 0x01 /* start packet, size 128 Bytes */
#define YMODEM_STX 0x02 /* data packet, size 1024 Bytes */
#define YMODEM_EOT 0x04 /* End of transfer */
#define YMODEM_ACK 0x06 /* receive success */
#define YMODEM_STX_A 0x0a
#define YMODEM_STX_B 0x0b
#define YMODEM_STX_C 0x0c
#define YMODEM_CAN 0x18 /* receiver cancel */
#define YMODEM_C 0x43 /* asscii 'C' */
#define YMODEM_MAX_RETRIES 20
#define YMODEM_CAN_MAX 3
#define YMODEM_LEN_SHORT 128
#define YMODEM_LEN_1K 1024
#define YMODEM_LEN_2K 2048
#define YMODEM_LEN_4K 4096
#define YMODEM_LEN_8K 8192
#define YMODEM_DELAY 20 /* 20 us */
#define YMODEM_DELAY_MAX 1000000 /* 50000 * 20us value 1s */
typedef struct {
uint32_t packet_len;
uint8_t packet[YMODEM_PACKET_SIZE];
bool rx_eof;
bool tx_ack;
uint8_t blk;
uint8_t expected_blk;
uint32_t file_length;
uint32_t read_length;
} ymodem_context;
static ymodem_context g_ymodem;
static uint32_t ymodem_get_packet(void);
static int32_t ymodem_getc(void);
static uint32_t ymodem_getc_timeout(uint8_t *ch);
static void ymodem_flush(void);
static uint32_t ymodem_parse_length(const uint8_t *buffer, uint32_t *length, uint32_t parse_max);
static uint32_t is_hex(int8_t ch)
{
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'A') && (ch <= 'F')) ||
((ch >= 'a') && (ch <= 'f'))) {
return ERRCODE_SUCC;
}
return ERRCODE_FAIL;
}
static uint32_t convert_hex(int8_t ch)
{
uint32_t val = 0;
if ((ch >= '0') && (ch <= '9')) {
val = (uint32_t)(int32_t)(ch - '0');
} else if ((ch >= 'a') && (ch <= 'f')) {
val = (uint32_t)(int32_t)(ch - 'a' + 10); /* 10: add 10 */
} else if ((ch >= 'A') && (ch <= 'F')) {
val = (uint32_t)(int32_t)(ch - 'A' + 10); /* 10: add 10 */
}
return val;
}
int32_t ymodem_getc(void)
{
if (uapi_uart_rx_fifo_is_empty(g_hiburn_uart) == false) {
return serial_getc();
}
return -1;
}
uint32_t ymodem_getc_timeout(uint8_t *ch)
{
return serial_getc_timeout(YMODEM_DELAY_MAX, ch);
}
static uint32_t ymodem_get_head_process(void)
{
uint32_t ret = ERRCODE_FAIL, hdr_ch_cnt = 0, can_count = 0;
uint8_t ch = 0xff; /* set to invalid value 0xff. */
bool hdr_flag = false;
while (hdr_flag == false) {
ret = ymodem_getc_timeout(&ch);
if (ret != ERRCODE_SUCC) {
ymodem_flush();
mdelay(20); /* delay 20 ms. */
return ERRCODE_BOOT_YMODEM_TIMEOUT;
}
hdr_ch_cnt++;
switch (ch) {
case YMODEM_SOH:
hdr_flag = true;
g_ymodem.packet_len = YMODEM_LEN_SHORT;
break;
case YMODEM_STX:
hdr_flag = true;
g_ymodem.packet_len = YMODEM_LEN_1K;
break;
case YMODEM_STX_A:
hdr_flag = true;
g_ymodem.packet_len = YMODEM_LEN_2K;
break;
case YMODEM_STX_B:
hdr_flag = true;
g_ymodem.packet_len = YMODEM_LEN_4K;
break;
case YMODEM_STX_C:
hdr_flag = true;
g_ymodem.packet_len = YMODEM_LEN_8K;
break;
case YMODEM_CAN:
if (++can_count == YMODEM_CAN_MAX) {
return ERRCODE_BOOT_YMODEM_CANCEL;
}
/* wait for more CAN */
break;
case YMODEM_EOT:
if (hdr_ch_cnt == 1) {
serial_putc(YMODEM_ACK);
return ERRCODE_BOOT_YMODEM_EOT;
}
break;
default:
break;
}
}
return ERRCODE_SUCC;
}
uint32_t ymodem_get_packet(void)
{
uint8_t crc_lo = 0xff; /* set to invalid value 0xff. */
uint8_t crc_hi = 0xff; /* set to invalid value 0xff. */
uint8_t blk = 0xff; /* set to invalid value 0xff. */
uint8_t cblk = 0xff; /* set to invalid value 0xff. */
uint32_t ret = ERRCODE_FAIL;
uint32_t i = 0;
if (g_ymodem.tx_ack == true) {
serial_putc(YMODEM_ACK);
g_ymodem.tx_ack = false;
}
ret = ymodem_get_head_process();
if (ret != ERRCODE_SUCC) {
return ret;
}
/* header found, start read data */
ret = ymodem_getc_timeout(&blk);
if (ret == ERRCODE_FAIL) {
return ERRCODE_BOOT_YMODEM_TIMEOUT;
}
ret = ymodem_getc_timeout(&cblk);
if (ret == ERRCODE_FAIL) {
return ERRCODE_BOOT_YMODEM_TIMEOUT;
}
udelay(3); /* delay 3 us. */
for (i = 0; i < g_ymodem.packet_len; i++) {
ret = ymodem_getc_timeout(&g_ymodem.packet[i]);
if (ret == ERRCODE_FAIL) {
return ret;
}
}
ret = ymodem_getc_timeout(&crc_hi);
if (ret == ERRCODE_FAIL) {
return ERRCODE_BOOT_YMODEM_TIMEOUT;
}
ret = ymodem_getc_timeout(&crc_lo);
if (ret == ERRCODE_FAIL) {
return ERRCODE_BOOT_YMODEM_TIMEOUT;
}
/* verify the packet */
if ((blk ^ cblk) != 0xFF) {
return ERRCODE_BOOT_YMODEM_FRAME;
}
uint16_t cs = crc16_ccitt(0, g_ymodem.packet, g_ymodem.packet_len);
if (cs != makeu16(crc_lo, crc_hi)) {
return ERRCODE_BOOT_YMODEM_CS;
}
g_ymodem.blk = (uint8_t)blk;
return ERRCODE_SUCC;
}
static uint32_t ymodem_get_info(void)
{
if (g_ymodem.blk == 0) {
udelay(3); /* delay 3 us. */
uint8_t *buffer = g_ymodem.packet;
uint32_t counter_times = YMODEM_LEN_SHORT;
/* skip file name */
while (*buffer++ != '\0') {
if (counter_times-- <= 0) {
break;
}
}
/* get file length */
if (ymodem_parse_length((const uint8_t *)buffer, &g_ymodem.file_length, YMODEM_LEN_SHORT) != ERRCODE_SUCC) {
return ERRCODE_FAIL;
}
if (g_ymodem.file_length < LOAD_MIN_SIZE || g_ymodem.file_length > LOAD_MAX_SIZE) {
return ERRCODE_BOOT_YMODEM_LENTH;
}
g_ymodem.tx_ack = true;
}
g_ymodem.expected_blk = 1;
g_ymodem.packet_len = 0;
return ERRCODE_SUCC;
}
uint32_t ymodem_open(void)
{
g_ymodem.packet_len = 0;
g_ymodem.file_length = 0;
g_ymodem.read_length = 0;
g_ymodem.tx_ack = false;
g_ymodem.rx_eof = false;
serial_putc(YMODEM_C);
int32_t retries = YMODEM_MAX_RETRIES;
boot_wdt_kick();
uint32_t ret = 0;
while (retries-- > 0) {
ret = ymodem_get_packet();
if (ret == ERRCODE_SUCC) {
return ymodem_get_info();
}
if (ret == ERRCODE_BOOT_YMODEM_CANCEL) {
break;
}
if (ret == ERRCODE_BOOT_YMODEM_TIMEOUT) {
if (retries < 0) {
return ERRCODE_BOOT_YMODEM_TIMEOUT;
}
boot_wdt_kick();
mdelay(20); /* delay 20 ms */
serial_putc(YMODEM_C);
}
}
return ERRCODE_FAIL;
}
void ymodem_close(void)
{
for (;;) {
if (ymodem_getc() < 0) {
break;
}
}
}
static void get_packet_len(void)
{
g_ymodem.tx_ack = true;
g_ymodem.expected_blk = (g_ymodem.expected_blk + 1) & 0xff;
g_ymodem.read_length += (uint32_t)g_ymodem.packet_len;
if (g_ymodem.read_length > g_ymodem.file_length) {
g_ymodem.packet_len -= (uint32_t)(g_ymodem.read_length - g_ymodem.file_length);
}
return;
}
static uint32_t ymodem_check_packet(void)
{
uint32_t ret = ERRCODE_FAIL;
int32_t retries = YMODEM_MAX_RETRIES;
while (retries-- > 0) {
ret = ymodem_get_packet();
if (ret == ERRCODE_SUCC) {
if (g_ymodem.blk == g_ymodem.expected_blk) {
get_packet_len();
break;
} else if (g_ymodem.blk == ((g_ymodem.expected_blk - 1) & 0xff)) {
serial_putc(YMODEM_ACK);
continue;
} else {
ret = ERRCODE_BOOT_YMODEM_SEQ;
}
}
if (ret == ERRCODE_BOOT_YMODEM_CANCEL) {
break;
}
if (ret == ERRCODE_BOOT_YMODEM_EOT) {
serial_putc(YMODEM_ACK);
serial_putc(YMODEM_C);
ret = ymodem_get_packet();
serial_putc(YMODEM_ACK);
g_ymodem.rx_eof = true;
break;
}
ymodem_flush();
serial_putc(YMODEM_C);
boot_wdt_kick();
}
return ret;
}
uint32_t ymodem_read(uint8_t* buf, uint32_t size)
{
uint8_t* read_buf = buf;
uint32_t read_size = size;
uint32_t rx_total = 0;
/* read 'read_size' bytes into 'buf' */
while ((g_ymodem.rx_eof == false) && (read_size > 0)) {
if (g_ymodem.packet_len == 0) {
if (ymodem_check_packet() != ERRCODE_SUCC) {
return rx_total;
}
}
if (g_ymodem.rx_eof == false) {
uint32_t length = min(read_size, g_ymodem.packet_len);
errcode_t ret = memcpy_s(read_buf, (uint32_t)read_size, g_ymodem.packet, length);
if (ret != EOK) {
return ERRCODE_FAIL;
}
read_size -= length;
read_buf += length;
rx_total += length;
g_ymodem.packet_len = 0;
}
}
return rx_total;
}
uint32_t ymodem_parse_length(const uint8_t *buffer, uint32_t *length, uint32_t parse_max)
{
const uint8_t *read_buffer = buffer;
uint32_t value = 0;
uint32_t radix = DECIMAL;
uint32_t count = parse_max;
if (read_buffer == NULL || length == NULL) {
return ERRCODE_FAIL;
}
/* skip 'space' */
while (*read_buffer == ' ' && count > 0) {
read_buffer++;
count--;
}
/* 1: makesure >= 2 */
if ((read_buffer[0] == '0') && ((read_buffer[1] == 'x') || (read_buffer[1] == 'X')) && count > 1) {
radix = HEXADECIMAL;
read_buffer += 2; /* 2: add 2 */
count -= 2; /* 2: sub 2 */
}
while (*read_buffer != '\0' && count > 0) {
int8_t ch = (int8_t)*read_buffer++;
if (is_hex(ch) == ERRCODE_FAIL) {
return ERRCODE_FAIL;
}
uint32_t tmp = convert_hex(ch);
if (tmp <= radix) {
value *= radix;
value += tmp;
}
}
*length = value;
return ERRCODE_SUCC;
}
uint32_t ymodem_get_length(void)
{
return g_ymodem.file_length;
}
void ymodem_flush(void)
{
for (;;) {
uint8_t ch = 0xff;
uint32_t ret = ymodem_getc_timeout(&ch);
if (ret == ERRCODE_FAIL) {
return;
}
}
}

View File

@ -0,0 +1,741 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
* Description: Secure Verify for Loaderboot and Flashboot
*
* Create: 2023-03-09
*/
#include "boot_serial.h"
#include "securec.h"
#include "efuse_wrap.h"
#include "drv_rom_cipher.h"
#include "boot_errcode.h"
#include "secure_verify_boot.h"
#define MAINTENANCE_MODE_EN 0x2A13C812
#define OEM_ROOT_PUBLIC_KEY_IMAGE_ID 0x4BA5C31E
#define PROVISION_KEY_AREA_IMAGE_ID 0x4BD2F01E
#define PROVISION_CODE_INFO_IMAGE_ID 0x4BD2F02D
#define PARAMS_KEY_AREA_IMAGE_ID 0x4B87A51E
#define PARAMS_AREA_INFO_IMAGE_ID 0x4B87A52D
#define PARAMS_AREA_IMAGE_ID 0x4B87A54B
#define FLASHBOOT_KEY_AREA_IMAGE_ID 0x4B1E3C1E
#define FLASHBOOT_CODE_INFO_IMAGE_ID 0x4B1E3C2D
#define FLASHBOOT_BACKUP_KEY_AREA_IMAGE_ID 0x4B69871E
#define FLASHBOOT_BACKUP_CODE_INFO_IMAGE_ID 0x4B69872D
#define APPBOOT_KEY_AREA_IMAGE_ID 0x4B0F2D1E
#define APPBOOT_CODE_INFO_IMAGE_ID 0x4B0F2D2D
#define boot_array_size(arr) (sizeof(arr) / sizeof((arr)[0]))
typedef struct {
image_type_t image_type;
area_type_t erea_type;
uint32_t image_id;
efuse_idx efuse_type;
} verify_table_item_t;
uint32_t g_rootkey_status = 0;
static verify_table_item_t g_verify_table[] = {
{
.image_type = LOADER_BOOT_TYPE, .erea_type = KEY_EREA_TYPE,
.image_id = PROVISION_KEY_AREA_IMAGE_ID
},
{
.image_type = LOADER_BOOT_TYPE, .erea_type = CODE_INFO_TYPE,
.image_id = PROVISION_CODE_INFO_IMAGE_ID
},
{
.image_type = FLASH_BOOT_TYPE, .erea_type = KEY_EREA_TYPE,
.image_id = FLASHBOOT_KEY_AREA_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = FLASH_BOOT_TYPE, .erea_type = CODE_INFO_TYPE,
.image_id = FLASHBOOT_CODE_INFO_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = FLASH_BOOT_BACK_UP_TYPE, .erea_type = KEY_EREA_TYPE,
.image_id = FLASHBOOT_BACKUP_KEY_AREA_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = FLASH_BOOT_BACK_UP_TYPE, .erea_type = CODE_INFO_TYPE,
.image_id = FLASHBOOT_BACKUP_CODE_INFO_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = SECOND_FLASH_BOOT_TYPE, .erea_type = KEY_EREA_TYPE,
.image_id = FLASHBOOT_KEY_AREA_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = SECOND_FLASH_BOOT_TYPE, .erea_type = CODE_INFO_TYPE,
.image_id = FLASHBOOT_CODE_INFO_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = SECOND_FLASH_BOOT_BACK_UP_TYPE, .erea_type = KEY_EREA_TYPE,
.image_id = FLASHBOOT_BACKUP_KEY_AREA_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = SECOND_FLASH_BOOT_BACK_UP_TYPE, .erea_type = CODE_INFO_TYPE,
.image_id = FLASHBOOT_BACKUP_CODE_INFO_IMAGE_ID,
.efuse_type = EFUSE_FLASHBOOT_VER_ID
},
{
.image_type = PARAMS_BOOT_TYPE, .erea_type = PARAMS_KEY_AREA_TYPE,
.image_id = PARAMS_KEY_AREA_IMAGE_ID,
.efuse_type = EFUSE_PARAMS_VER_ID
},
{
.image_type = PARAMS_BOOT_TYPE, .erea_type = PARAMS_AREA_INFO_TYPE,
.image_id = PARAMS_AREA_INFO_IMAGE_ID,
.efuse_type = EFUSE_PARAMS_VER_ID
},
{
.image_type = APP_BOOT_TYPE, .erea_type = KEY_EREA_TYPE,
.image_id = APPBOOT_KEY_AREA_IMAGE_ID,
.efuse_type = EFUSE_MCU_VER_ID
},
{
.image_type = APP_BOOT_TYPE, .erea_type = CODE_INFO_TYPE,
.image_id = APPBOOT_CODE_INFO_IMAGE_ID,
.efuse_type = EFUSE_MCU_VER_ID
},
};
static errcode_t check_image_id(image_type_t image_type, area_type_t erea_type, uint32_t image_id)
{
uint32_t image_id_check = 0;
for (uint32_t i = 0; i < boot_array_size(g_verify_table); i++) {
if (image_type == g_verify_table[i].image_type && erea_type == g_verify_table[i].erea_type) {
image_id_check = g_verify_table[i].image_id;
break;
}
if (i == boot_array_size(g_verify_table)) {
boot_msg0("get key erea iamge id failed!");
return ERRCODE_FAIL;
}
}
if (image_id != image_id_check) {
boot_msg0("image id error!");
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
static uint32_t count_bit_num(uint32_t input)
{
uint32_t count = 0; /* count accumulates the total bits set in input */
uint32_t input_copy = input;
for (count = 0; input_copy >= 1; count++) {
input_copy &= input_copy - 1; /* clear the least significant bit set */
}
return count;
}
static errcode_t check_version(image_type_t image_type, uint32_t version, uint32_t version_mask)
{
uint32_t efuse_version = 0;
uint32_t efuse_idx = 0;
uint32_t ret = 0;
for (uint32_t i = 0; i < boot_array_size(g_verify_table); i++) {
if (image_type == g_verify_table[i].image_type) {
efuse_idx = g_verify_table[i].efuse_type;
break;
}
if (i == boot_array_size(g_verify_table)) {
boot_msg0("get key erea iamge id failed!");
return ERRCODE_FAIL;
}
}
/* read otp version */
/* sizeof(efuse_version) = 4 */
ret = efuse_read_item(efuse_idx, (uint8_t *)&efuse_version, (uint16_t)sizeof(efuse_version));
if (ret != ERRCODE_SUCC) {
boot_msg0("version efuse_read_item fail!");
return ERRCODE_FAIL;
}
if (count_bit_num(version & version_mask) < count_bit_num(efuse_version & version_mask)) {
boot_msg0("version compare fail!");
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
static errcode_t check_msid(uint32_t msid, uint32_t msid_mask)
{
uint32_t efuse_msid = 0;
uint32_t ret = 0;
/* sizeof(efuse_msid) = 4 */
ret = efuse_read_item(EFUSE_MSID_ID, (uint8_t *)&efuse_msid, (uint16_t)sizeof(efuse_msid));
if (ret != ERRCODE_SUCC) {
boot_msg0("version efuse_read_item fail!");
return ERRCODE_FAIL;
}
if ((msid & msid_mask) != (efuse_msid & msid_mask)) {
boot_msg0("msid compare fail!");
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
static errcode_t check_die_id(uint8_t *die_id, uint32_t die_id_length)
{
uint8_t efuse_die_id[DIE_ID_LEN] = { 0 };
uint32_t ret = 0;
if (die_id_length != DIE_ID_LEN) {
return ERRCODE_FAIL;
}
/* sizeof(efuse_die_id) = 16 */
ret = efuse_read_item(EFUSE_DIE_ID, (uint8_t *)efuse_die_id, (uint16_t)sizeof(efuse_die_id));
if (ret != ERRCODE_SUCC) {
boot_msg0("die_id efuse_read_item fail!");
return ERRCODE_FAIL;
}
ret = memcmp(efuse_die_id, die_id, die_id_length);
if (ret != 0) {
boot_msg0("die id memcmp fail!");
return ERRCODE_FAIL;
}
return ret;
}
static errcode_t check_verify_enable(void)
{
uint32_t ret = 0;
uint8_t verify_enable = 0xff;
/* sizeof(verify_enable) = 1 */
ret = efuse_read_item(EFUSE_SEC_VERIFY_ENABLE, &verify_enable, (uint16_t)sizeof(verify_enable));
if (ret != ERRCODE_SUCC) {
boot_msg0("efuse_read_item verify enable fail!");
return ERRCODE_FAIL;
}
if (verify_enable == 0) {
return ERRCODE_NOT_SUPPORT;
}
return ERRCODE_SUCC;
}
#if defined(CONFIG_BOOT_SUPPORT_ECC_VERIFY)
static errcode_t secure_authenticate(const uint8_t *key, const uint8_t *data, uint32_t data_length,
const uint8_t *sign_buff, uint32_t sign_length)
{
uint8_t hash_result[HASH_LEN];
drv_rom_cipher_ecc_point input_pub_key = { 0 };
drv_rom_cipher_data input_hash = { 0 };
drv_rom_cipher_ecc_sig input_sig = { 0 };
uint32_t ret = 0;
ret = drv_rom_cipher_sha256(data, data_length, hash_result, (uint32_t)HASH_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("secure_authenticate drv_rom_cipher_sha256 fail!");
return ERRCODE_FAIL;
}
input_pub_key.x = (uint8_t *)key;
input_pub_key.y = (uint8_t *)(key + 32); /* 32 is ecc bp256 key length */
input_pub_key.length = 32; /* 32 is ecc bp256 key length */
input_hash.data = hash_result;
input_hash.length = HASH_LEN;
input_sig.r = (uint8_t *)sign_buff;
input_sig.s = (uint8_t *)(sign_buff + sign_length / 2); /* 2: sign = r + s */
input_sig.length = sign_length / 2; /* 2: sign = r + s */
ret = (uint32_t)drv_rom_cipher_pke_bp256r_verify(&input_pub_key, &input_hash, &input_sig);
if (ret != ERRCODE_SUCC) {
boot_msg0("secure_authenticate drv_rom_cipher_pke_bp256r_verify fail!");
return ERRCODE_FAIL;
}
return ret;
}
#endif
#if defined(CONFIG_BOOT_SUPPORT_SM2_VERIFY)
static errcode_t secure_authenticate(const uint8_t *key, const uint8_t *data, uint32_t data_length,
const uint8_t *sign_buff, uint32_t sign_length)
{
uint8_t hash_result[HASH_LEN] = { 0 };
drv_rom_cipher_ecc_point input_pub_key = { 0 };
drv_rom_cipher_pke_msg input_msg = { 0 };
drv_rom_cipher_data input_hash = { 0 };
drv_rom_cipher_ecc_sig input_sig = { 0 };
uint8_t sm2_id[18] = "\x42\x4c\x49\x43\x45\x31\x32\x33\x40\x59\x41\x48\x4f\x4f\x2\x43\x4f\x11";
uint32_t ret = 0;
input_pub_key.x = (uint8_t *)key;
input_pub_key.y = (uint8_t *)(key + 32); /* 32 is sm2 key length */
input_pub_key.length = 32; /* 32 is sm2 key length */
input_msg.data = (uint8_t *)data;
input_msg.length = data_length;
input_hash.data = hash_result;
input_hash.length = sizeof(hash_result);
ret = drv_rom_cipher_pke_sm2_dsa_hash(sm2_id, &input_pub_key, &input_msg, &input_hash);
if (ret != ERRCODE_SUCC) {
boot_msg0("secure_authenticate drv_rom_cipher_pke_sm2_dsa_hash fail!");
return ERRCODE_FAIL;
}
input_sig.r = (uint8_t *)sign_buff;
input_sig.s = (uint8_t *)(sign_buff + sign_length / 2); /* 2: sign = r + s */
input_sig.length = sign_length / 2; /* 2: sign = r + s */
ret = drv_rom_cipher_pke_sm2_verify(input_pub_key, input_hash, input_sig);
if (ret != ERRCODE_SUCC) {
boot_msg0("secure_authenticate drv_rom_cipher_pke_sm2_verify fail!");
return ERRCODE_FAIL;
}
return ret;
}
#endif
static errcode_t verify_params_key_area(const params_key_area_t *key_area, const uint8_t *public_key)
{
uint32_t ret = 0;
/* check verify enable */
ret = check_verify_enable();
if (ret == ERRCODE_NOT_SUPPORT) {
return ERRCODE_SUCC;
} else if (ret == ERRCODE_FAIL) {
boot_msg0("verify_params_key_area secure verify error!");
return ERRCODE_BOOT_VERIFY_CHECK_ENABLE;
}
if (g_rootkey_status != 0x5) {
boot_msg0("verify_params_key_area rootkey_status invalid!");
return ERRCODE_BOOT_VERIFY_INVALID_ROOT_KEY;
}
/* check image id */
ret = check_image_id(PARAMS_BOOT_TYPE, PARAMS_KEY_AREA_TYPE, key_area->image_id);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_key_area image id error!");
return ERRCODE_BOOT_VERIFY_INVALID_IMAGE_ID;
}
/* verify key area with rootkey */
ret = secure_authenticate(public_key, (uint8_t *)key_area, KEY_AREA_STRUCTURE_LENGTH - BOOT_SIG_LEN,
key_area->sig_params_key_area, BOOT_PUBLIC_KEY_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_key_area secure_authenticate fail!");
return ERRCODE_BOOT_VERIFY_PKE_VERIFY;
}
/* check key version ext */
ret = check_version(PARAMS_BOOT_TYPE,
key_area->params_key_version_ext, key_area->mask_params_key_version_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_key_area key version error!");
return ERRCODE_BOOT_VERIFY_INVALID_VERSION;
}
/* check key msid */
ret = check_msid(key_area->msid_ext, key_area->mask_msid_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_key_area msid error!");
return ERRCODE_BOOT_VERIFY_INVALID_MSID;
}
/* check maintention mode */
if (key_area->maintenance_mode == MAINTENANCE_MODE_EN) {
ret = check_die_id((uint8_t *)key_area->die_id, DIE_ID_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_key_area die id error!");
return ERRCODE_BOOT_VERIFY_INVALID_DIE_ID;
}
}
return ret;
}
static errcode_t verify_params_area_info(const params_area_info_t *area_info, const uint8_t *public_key)
{
uint32_t ret = 0;
/* check verify enable */
ret = check_verify_enable();
if (ret == ERRCODE_NOT_SUPPORT) {
return ERRCODE_SUCC;
} else if (ret == ERRCODE_FAIL) {
boot_msg0("verify_params_area_info secure verify error!");
return ERRCODE_BOOT_VERIFY_CHECK_ENABLE;
}
/* check image id */
ret = check_image_id(PARAMS_BOOT_TYPE, PARAMS_AREA_INFO_TYPE, area_info->image_id);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area_info image id error!");
return ERRCODE_BOOT_VERIFY_INVALID_IMAGE_ID;
}
/* verify code info with external public key */
ret = secure_authenticate(public_key, (uint8_t *)area_info,
CODE_INFO_STRUCTURE_LENGTH - BOOT_SIG_LEN - BOOT_EXT_SIG_LEN, area_info->sig_params_info, BOOT_PUBLIC_KEY_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area_info secure_authenticate fail!");
return ERRCODE_BOOT_VERIFY_PKE_VERIFY;
}
/* check version ext */
ret = check_version(PARAMS_BOOT_TYPE,
area_info->params_version_ext, area_info->mask_params_version_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area_info key version error!");
return ERRCODE_BOOT_VERIFY_INVALID_VERSION;
}
/* check msid */
ret = check_msid(area_info->msid_ext, area_info->mask_msid_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area_info msid error!");
return ERRCODE_BOOT_VERIFY_INVALID_MSID;
}
return ret;
}
static errcode_t verify_params_area(const params_area_info_t *area_info, const uint8_t *area_addr)
{
uint32_t area_length = 0;
uint8_t hash_result[HASH_LEN] = { 0 };
uint32_t ret = 0;
/* caculate code area hash */
area_length = area_info->params_area_len;
ret = drv_rom_cipher_sha256((unsigned char *)(uintptr_t)area_addr, area_length, hash_result, (uint32_t)HASH_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area drv_rom_cipher_sha256 fail!");
return ERRCODE_BOOT_VERIFY_HASH_CALCULATION;
}
ret = memcmp(hash_result, area_info->params_area_hash, (uint32_t)HASH_LEN);
if (ret != 0) {
boot_msg0("verify_params_area hash memcmp fail!");
return ERRCODE_BOOT_VERIFY_INVALID_HASH_RESULT;
}
return ret;
}
static errcode_t verify_image_key_area(image_type_t image_type, area_type_t erea_type,
const image_key_area_t *key_area, const uint8_t *public_key)
{
uint32_t ret = 0;
/* check verify enable */
ret = check_verify_enable();
if (ret == ERRCODE_NOT_SUPPORT) {
boot_msg0("verify_image_key_area secure verify disable!");
return ERRCODE_SUCC;
} else if (ret == ERRCODE_FAIL) {
boot_msg0("verify_image_key_area secure verify error!");
return ERRCODE_BOOT_VERIFY_CHECK_ENABLE;
}
if ((image_type == LOADER_BOOT_TYPE) || (image_type == FLASH_BOOT_TYPE) ||
(image_type == FLASH_BOOT_BACK_UP_TYPE)) {
if (g_rootkey_status != 0x5) {
boot_msg0("verify_image_key_area rootkey_status invalid!");
return ERRCODE_BOOT_VERIFY_INVALID_ROOT_KEY;
}
}
/* check image id */
ret = check_image_id(image_type, erea_type, key_area->image_id);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_key_area image id error!");
return ERRCODE_BOOT_VERIFY_INVALID_IMAGE_ID;
}
/* verify key area with rootkey */
ret = secure_authenticate(public_key, (uint8_t *)key_area, KEY_AREA_STRUCTURE_LENGTH - BOOT_SIG_LEN,
key_area->sig_key_area, BOOT_PUBLIC_KEY_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_key_area secure_authenticate!");
return ERRCODE_BOOT_VERIFY_PKE_VERIFY;
}
/* check key version ext */
if (image_type != LOADER_BOOT_TYPE) {
ret = check_version(image_type, key_area->key_version_ext, key_area->mask_key_version_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_key_area key version error!");
return ERRCODE_BOOT_VERIFY_INVALID_VERSION;
}
}
/* check key msid */
ret = check_msid(key_area->msid_ext, key_area->mask_msid_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_key_area msid error!");
return ERRCODE_BOOT_VERIFY_INVALID_MSID;
}
/* check maintention mode */
if (key_area->maintenance_mode == MAINTENANCE_MODE_EN) {
ret = check_die_id((uint8_t *)key_area->die_id, DIE_ID_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_key_area die id error!");
return ERRCODE_BOOT_VERIFY_INVALID_DIE_ID;
}
}
return ret;
}
static errcode_t verify_image_code_info(image_type_t image_type, area_type_t erea_type,
const image_code_info_t *code_info, const uint8_t *public_key)
{
uint32_t ret = 0;
/* check verify enable */
ret = check_verify_enable();
if (ret == ERRCODE_NOT_SUPPORT) {
boot_msg0("verify_image_code_info secure verify disable!");
return ERRCODE_SUCC;
} else if (ret == ERRCODE_FAIL) {
boot_msg0("verify_image_code_info secure verify error!");
return ERRCODE_BOOT_VERIFY_CHECK_ENABLE;
}
/* check image id */
ret = check_image_id(image_type, erea_type, code_info->image_id);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_info image id error!");
return ERRCODE_BOOT_VERIFY_INVALID_IMAGE_ID;
}
/* verify code info with external public key */
ret = secure_authenticate(public_key, (uint8_t *)code_info,
CODE_INFO_STRUCTURE_LENGTH - BOOT_SIG_LEN - BOOT_EXT_SIG_LEN, code_info->sig_code_info, BOOT_PUBLIC_KEY_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_info secure_authenticate!");
return ERRCODE_BOOT_VERIFY_PKE_VERIFY;
}
/* check version ext */
if (image_type != LOADER_BOOT_TYPE) {
ret = check_version(image_type, code_info->version_ext, code_info->mask_version_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_info key version error!");
return ERRCODE_BOOT_VERIFY_INVALID_VERSION;
}
}
/* check msid */
ret = check_msid(code_info->msid_ext, code_info->mask_msid_ext);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_info msid error!");
return ERRCODE_BOOT_VERIFY_INVALID_MSID;
}
return ret;
}
static errcode_t verify_image_code_area(const image_code_info_t *code_info, const uint8_t *code_addr)
{
uint32_t code_length = 0;
uint8_t hash_result[HASH_LEN] = { 0 };
uint32_t ret = 0;
/* caculate code area hash */
code_length = code_info->code_area_len;
ret = drv_rom_cipher_sha256((unsigned char *)(uintptr_t)code_addr, code_length, hash_result, (uint32_t)HASH_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_area drv_rom_cipher_sha256!");
return ERRCODE_BOOT_VERIFY_HASH_CALCULATION;
}
ret = memcmp(hash_result, code_info->code_area_hash, (uint32_t)HASH_LEN);
if (ret != 0) {
boot_msg0("verify_image_code_area hash memcmp fail!");
return ERRCODE_BOOT_VERIFY_INVALID_HASH_RESULT;
}
return ret;
}
errcode_t verify_public_rootkey(uint32_t rootkey_buff_addr)
{
uint8_t hash_result[HASH_LEN] = { 0 };
uint8_t hash_from_otp[HASH_LEN] = { 0 };
uint32_t ret = ERRCODE_SUCC;
const root_public_key_area_t *rootkey_buff = (root_public_key_area_t *)(uintptr_t)rootkey_buff_addr;
if (rootkey_buff == NULL) {
return ERRCODE_BOOT_VERIFY_PARAM_NULL;
}
g_rootkey_status = 0xA;
/* check verify enable */
ret = check_verify_enable();
if (ret == ERRCODE_NOT_SUPPORT) {
return ERRCODE_SUCC;
} else if (ret == ERRCODE_FAIL) {
boot_msg0("verify_public_rootkey secure verify error!");
return ERRCODE_BOOT_VERIFY_CHECK_ENABLE;
}
boot_msg0("secure boot.");
/* check rootkey_buff->image_id */
if (rootkey_buff->image_id != OEM_ROOT_PUBLIC_KEY_IMAGE_ID) {
boot_msg0("verify_public_rootkey image id error!");
return ERRCODE_BOOT_VERIFY_INVALID_IMAGE_ID;
}
/* caculate rootkey hash */
ret = drv_rom_cipher_sha256((unsigned char *)rootkey_buff, ROOT_PUBLIC_KEY_STRUCTURE_LENGTH,
hash_result, (uint32_t)HASH_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_public_rootkey drv_rom_cipher_sha256 fail!");
return ERRCODE_BOOT_VERIFY_HASH_CALCULATION;
}
/* read efuse rootkey hash */
/* sizeof(hash_from_otp) = 32 */
ret = efuse_read_item(EFUSE_HASH_ROOT_PUBLIC_KEY_ID, hash_from_otp, (uint16_t)sizeof(hash_from_otp));
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_public_rootkey efuse_read_item fail!");
return ERRCODE_BOOT_VERIFY_EFUSE_READ;
}
/* check hash */
ret = memcmp(hash_from_otp, hash_result, (uint32_t)HASH_LEN);
if (ret != 0) {
boot_msg0("verify_public_rootkey hash memcmp fail!");
return ERRCODE_BOOT_VERIFY_INVALID_HASH_RESULT;
}
g_rootkey_status = 0x5;
return ret;
}
errcode_t verify_image_head(image_type_t image_type, uint32_t public_key_addr, uint32_t boot_head_addr)
{
uint32_t ret = 0;
image_key_area_t *key_area = (image_key_area_t *)(uintptr_t)boot_head_addr;
image_code_info_t *code_info = (image_code_info_t *)(uintptr_t)((uintptr_t)key_area + KEY_AREA_STRUCTURE_LENGTH);
if (key_area == NULL || code_info == NULL) {
return ERRCODE_BOOT_VERIFY_PARAM_NULL;
}
ret = verify_image_key_area(image_type, KEY_EREA_TYPE, key_area, (uint8_t *)(uintptr_t)public_key_addr);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_key_area fail!");
return ret;
}
ret = verify_image_code_info(image_type, CODE_INFO_TYPE, code_info, key_area->ext_pulic_key_area);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_info fail!");
return ret;
}
return ret;
}
errcode_t verify_image_body(uint32_t boot_head_addr, uint32_t boot_body_addr)
{
uint32_t ret = 0;
const image_code_info_t *code_info = (image_code_info_t *)(uintptr_t)(boot_head_addr + KEY_AREA_STRUCTURE_LENGTH);
const uint8_t *code_addr = (uint8_t *)(uintptr_t)boot_body_addr;
if (code_info == NULL || code_addr == NULL) {
return ERRCODE_BOOT_VERIFY_PARAM_NULL;
}
ret = verify_image_code_area(code_info, code_addr);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_image_code_area fail!");
return ret;
}
return ret;
}
errcode_t verify_params_head(uint32_t root_public_key_addr, uint32_t params_head_addr)
{
uint32_t ret = 0;
root_public_key_area_t *public_rootkey = (root_public_key_area_t *)(uintptr_t)root_public_key_addr;
params_key_area_t *key_area = (params_key_area_t *)(uintptr_t)params_head_addr;
params_area_info_t *area_info = (params_area_info_t *)(uintptr_t)((uintptr_t)key_area + KEY_AREA_STRUCTURE_LENGTH);
if (public_rootkey == NULL || key_area == NULL || area_info == NULL) {
return ERRCODE_BOOT_VERIFY_PARAM_NULL;
}
ret = verify_params_key_area(key_area, public_rootkey->root_key_area);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_key_area fail!");
return ret;
}
ret = verify_params_area_info(area_info, key_area->params_ext_key_area);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area_info fail!");
return ret;
}
return ret;
}
errcode_t verify_params_body(uint32_t params_head_addr, uint32_t params_body_addr)
{
uint32_t ret = 0;
const params_area_info_t *area_info =
(params_area_info_t *)(uintptr_t)(params_head_addr + KEY_AREA_STRUCTURE_LENGTH);
const uint8_t *area_addr = (uint8_t *)(uintptr_t)params_body_addr;
if (area_info == NULL || area_addr == NULL) {
return ERRCODE_BOOT_VERIFY_PARAM_NULL;
}
ret = verify_params_area(area_info, area_addr);
if (ret != ERRCODE_SUCC) {
boot_msg0("verify_params_area fail!");
return ret;
}
return ret;
}

View File

@ -0,0 +1,55 @@
#===============================================================================
# @brief cmake file
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved.
#===============================================================================
set(COMPONENT_NAME "flashboot_common")
if("flashboot" IN_LIST BIN_NAME)
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/startup/main.c
${CMAKE_CURRENT_SOURCE_DIR}/startup/main.c
${CMAKE_CURRENT_SOURCE_DIR}/startup/riscv_init.S
${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/src/secure_verify_boot.c
)
set(PUBLIC_HEADER
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/include
)
elseif ("ssb" IN_LIST BIN_NAME)
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/ssb/main.c
${CMAKE_CURRENT_SOURCE_DIR}/ssb/riscv_init.S
${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/src/secure_verify_boot.c
)
set(PUBLIC_HEADER
${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/include
)
endif()
set(PRIVATE_HEADER
)
set(PRIVATE_DEFINES
)
set(PUBLIC_DEFINES
)
# use this when you want to add ccflags like -include xxx
set(COMPONENT_PUBLIC_CCFLAGS
)
set(COMPONENT_CCFLAGS
)
set(WHOLE_LINK
true
)
set(MAIN_COMPONENT
false
)
build_component()

View File

@ -0,0 +1,780 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2021. All rights reserved.
* Description: main
*
* Create: 2021-03-09
*/
#include "boot_serial.h"
#include "boot_init.h"
#include "boot_reset.h"
#include "boot_verify.h"
#include "secure_verify_boot.h"
#include "efuse.h"
#include "efuse_porting.h"
#include "chip_io.h"
#include "pinctrl.h"
#include "boot_flash.h"
#include "sfc.h"
#include "boot_delay.h"
#include "boot_jump.h"
#include "tcxo.h"
#include "watchdog.h"
#include "drv_pmp.h"
#include "pmp_cfg.h"
#include "malloc_porting.h"
#include "upg_porting.h"
#include "upg_common.h"
#include "upg_alloc.h"
#include "soc_porting.h"
#include "drv_flashboot_cipher.h"
#ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB
#include "upg_ab.h"
#endif
#include "factory.h"
#include "sfc_protect.h"
#include "reset_porting.h"
#define FLASHBOOT_UART_DEFAULT_PARAM {115200, 8, 1, 0, 0, 2, 1, 4, 0}
#define APP_START_INSTRUCTION 0x40006f
#define DELAY_100MS 100
#define REG_CMU_CFG0 0x40003408
#define APP_IMAGE_HEADER_LEN ((KEY_AREA_STRUCTURE_LENGTH) + (CODE_INFO_STRUCTURE_LENGTH))
#define BOOT_WATCH_DOG_TIMOUT 7 // 7s
#define FLASH_KEY_SALT_LEN 28
#define FLASH_ENCRY_ADDR_ALINE 256
#define FLASH_NO_ENCRY_FLAG 0x3C7896E1
#define FLASHBOOT_RAM_ADDR 0xA28000
#define FLASH_BOOT_TYPE_REG 0x40000024
#define FLASH_BOOT_TYPE_REG_MAIN 0xA5A5A5A5
#define FLASH_BOOT_TYPE_REG_BKUP 0x5A5A5A5A
const sfc_flash_config_t sfc_cfg = {
.read_type = FAST_READ_QUAD_OUTPUT,
.write_type = PAGE_PROGRAM,
.mapping_addr = 0x200000,
.mapping_size = 0x800000,
};
#if 1 //ADD LYL 2024 1122 --------
#define USERPAGE 0x003F2000 //AT参数存储区
#define BLE_CONKEYLEN 16
#pragma pack(push)
#pragma pack(1)
typedef struct
{
int8_t updateflag; //update flag
int8_t validflag; //valid flag
int8_t tmode_mode;
int8_t wmode_mode;
//STA, 140 bytes
uint8_t sta_ssid[33];
uint8_t sta_key[65];
int8_t wsauth;
int8_t wsencry;
uint8_t wslko;
uint8_t pmk_av;
uint8_t sta_padding[6];
uint8_t pmk[32];
//AP, 144 bytes
int8_t wap_mode;
int8_t wap_channel;
int8_t waauth;
int8_t waencry;
uint8_t walk_led;
uint8_t max_sta_num;
uint8_t ap_enable_hide;
uint8_t ap_ssid[33];
uint8_t ap_key[65];
uint8_t ap_pmk_av;
uint8_t ap_pmk[32];
uint8_t ap_padding[6];
//UART, 20 bytes
int8_t baudrate;
int8_t data_bits;
int8_t stop_bits;
int8_t parity;
int8_t ctsrts;
int8_t uart1_baudrate;
int8_t uart1_data_bits;
int8_t uart1_stop_bits;
int8_t uart1_parity;
int8_t uart1_debug;
int8_t uartfable;
int8_t fuartte_mode;
uint16_t uarttm;
uint16_t uartbuf;
uint8_t uart_padding[4];
//NETP, 108 bytes
int8_t protocol;
int8_t app_mode;
uint8_t maxsocket;
char cipadd[101];
uint16_t pro_port;
uint16_t tcpto;
//SOCKB, 112 bytes
uint16_t sockb_port;
uint16_t sockb_tcpto;
int8_t sockb_pro;
char sockb_cipadd[101];
int8_t tcpdis;
int8_t tcpdisb;
uint16_t udp_localporta;
uint16_t udp_localportb;
//NETWORK, 108 bytes
char wann_ipaddr[16];
char wann_mask[16];
char wann_gateway[16];
char lann_ipaddr[16];
char lann_mask[16];
uint8_t wann_mode;
uint8_t network_padding[2];
uint8_t domain_name[21];
uint32_t dns_addr;
//UTILS, 124 bytes
int8_t echo;
int8_t rlden;
uint8_t debug_level;
char wel_msg[11];
uint8_t event_onoff;
uint8_t noise_filter;
uint8_t wifi_switch;
uint8_t sta_dtim;
uint8_t utils_padding[40];
uint8_t dis_power_saving;
int8_t modechange;
uint8_t ps_interval;
uint8_t mid[21];
uint8_t aswd[21];
uint8_t cmdpw[21];
//HTTPD, 36 bytes
char user_name[16];
char user_password[16];
int8_t web_switch;
uint8_t web_language;
uint8_t web_encode_format;
uint8_t httpd_padding;
//DHCPD, 4 bytes
int8_t dhcpsw;
uint8_t dhcpd_addr_start;
uint8_t dhcpd_addr_end;
uint8_t dhcpd_padding;
//UPDATE, 124 bytes
char update_url[101];
char update_file[21];
uint8_t update_padding[2];
//NTP, 8 bytes
uint8_t ntp_time;
uint8_t ntp_enable;
uint8_t ntp_padding;
int8_t time_zone;
uint32_t ntpserver;
//SMTLK, 16 bytes
uint32_t smtlk_sign;
uint8_t smtlk_mode;
uint8_t smtlk_protocol;
uint8_t smtlk_rtype;
uint8_t smtlk_ak_random;
uint8_t connect_flag;
uint8_t sta_channel;
uint8_t sta_bssid[6];
//SMARTAPLINK, 44 bytes
uint8_t smartaplink_enable;
uint8_t smartaplink_padding;
uint8_t smartaplink_prefix[21];
uint8_t smartaplink_key[21];
//NETPID, 24 bytes
uint8_t netpa_iden;
char netpa_id[11];
uint8_t netpb_iden;
char netpb_id[11];
//NETPREG, 264 bytes
uint8_t netpa_regen;
uint8_t netpa_regtype;
uint8_t netpa_reg_padding;
char netpa_regdata[129];
uint8_t netpb_regen;
uint8_t netpb_regtype;
uint8_t netpb_reg_padding;
char netpb_regdata[129];
//HEART, 124 bytes
uint16_t heart_netp_time;
uint16_t heart_sockb_time;
uint16_t heart_uart_time;
char heart_netp_data[39];
char heart_sockb_data[39];
char heart_uart_data[39];
uint8_t heart_padding;
//HTTP, 236 bytes
uint8_t http_type;
uint8_t http_version;
uint8_t http_connect_type;
uint8_t http_recv_time;
char http_url[51];
char http_header[181];
//MQTT, 224 bytes
char mqtt_username[33];
char mqtt_password[33];
char mqtt_clientid[33];
char mqtt_pub_topic[61];
char mqtt_sub_topic[61];
uint8_t mqtt_qos;
uint16_t mqtt_heart_time;
//BLE, 188 bytes
uint16_t conn_min;
uint16_t conn_max;
uint16_t conn_latency;
uint16_t supervisionTO;
uint16_t adver_min;
uint16_t adver_max;
uint8_t ble_name[27]; //BLE广播名
uint8_t ble_dms_name[27]; //BLE配网名
uint8_t ble_adver_data[27];
uint8_t ble_adver_data_len;
uint8_t ble_switch;
uint8_t ble_uuid_server;
uint8_t dms_type;
uint8_t ble_padding;
uint8_t uuid_ntf_server[17];
uint8_t uuid_ntf_read[17];
uint8_t uuid_ntf_write[17];
uint8_t uuid_ind_server[17];
uint8_t uuid_ind_read[17];
uint8_t uuid_ind_write[17];
uint8_t adver_type;
uint8_t adver_channel;
uint8_t ble_ind;
uint8_t smartconfiglink;
uint8_t ble_conenable;
uint8_t ble_conkey[BLE_CONKEYLEN];
uint8_t ble_contimeout;
uint8_t netpc_iden;
char netpc_id[11];
uint8_t netpc_idflag;
uint8_t ble_padding2[17];
uint8_t mqtt_tls;
uint8_t mqtt_padding[3];
char iot_productkey[12];
char iot_devicename[48];
char iot_devicesecret[48];
char iot_pubtopic[96];
char iot_subtopic[96];
char iot_mode;
char iot_padding[3];
uint8_t product_mode;
int8_t ctsrts_pin;
char instance_flag;
char instance_id[32];
char ntp_domain_server[33];
int8_t smk_find;
uint32_t mcu_ota_size;
uint8_t scan_ch14;
uint32_t module_reset_reason;
uint8_t reserved1[60+512-4];
uint8_t validflag_magic;
int8_t validflag_end; //valid flag
}HF_CONFIG_FILE;
#pragma pack(pop)
HF_CONFIG_FILE g_hf_config_file_boot = {0};
int hfdbg_get_sw(void)
{
if(g_hf_config_file_boot.debug_level > 0 && g_hf_config_file_boot.debug_level<=20) //1~20允许打印
return 0;
if(g_hf_config_file_boot.uart1_debug == 1) //1允许打印
return 1;
return 0;
}
#endif
static uint32_t sfc_flash_init(void)
{
return uapi_sfc_init((sfc_flash_config_t *)&sfc_cfg);
}
static uint32_t sfc_flash_read(uint32_t flash_addr, uint32_t read_size, uint8_t *read_buffer)
{
return uapi_sfc_reg_read(flash_addr, read_buffer, read_size);
}
static uint32_t sfc_flash_write(uint32_t flash_addr, uint32_t flash_write_size, const uint8_t *p_flash_write_data,
bool do_erase)
{
unused(do_erase);
return uapi_sfc_reg_write(flash_addr, (uint8_t *)p_flash_write_data, flash_write_size);
}
static uint32_t sfc_flash_erase(uint32_t flash_addr, uint32_t flash_erase_size)
{
return uapi_sfc_reg_erase(flash_addr - sfc_cfg.mapping_addr, flash_erase_size);
}
static void boot_flash_init(void)
{
flash_cmd_func flash_funcs = {0};
flash_funcs.init = sfc_flash_init;
flash_funcs.read = sfc_flash_read;
flash_funcs.write = sfc_flash_write;
flash_funcs.erase = sfc_flash_erase;
boot_regist_flash_cmd(&flash_funcs);
uint32_t ret = sfc_flash_init();
if (ret != ERRCODE_SUCC) {
boot_msg1("Flash Init Fail! ret = ", ret);
} else {
uapi_sfc_reg_read(USERPAGE, (unsigned char *)&g_hf_config_file_boot, sizeof(HF_CONFIG_FILE));
boot_msg0("Flash Init Succ!");
}
hf_boot_msg1("BootLoader debug_level = ", g_hf_config_file_boot.debug_level);
switch_flash_clock_to_pll();
config_sfc_ctrl_ds();
}
#define FAMA_REMAP_SRC_BASE_ADDR 0x44007800
#define FAMA_REMAP_LEN_BASE_ADDR 0x44007820
#define FAMA_REMAP_DST_BASE_ADDR 0x44007840
#define FAMA_REMAP_REGION_OFFSET 0x4
#define FAMA_REMAP_LOW_BITS 12
static void dmmu_set(uint32_t src_start_addr, uint32_t src_end_addr, uint32_t dst_start_addr, uint32_t region)
{
uint32_t src_reg_addr = FAMA_REMAP_SRC_BASE_ADDR + region * FAMA_REMAP_REGION_OFFSET;
uint32_t len_reg_addr = FAMA_REMAP_LEN_BASE_ADDR + region * FAMA_REMAP_REGION_OFFSET;
uint32_t dst_reg_addr = FAMA_REMAP_DST_BASE_ADDR + region * FAMA_REMAP_REGION_OFFSET;
uint32_t src_start_align_addr = src_start_addr >> FAMA_REMAP_LOW_BITS;
uint32_t src_end_align_addr = src_end_addr >> FAMA_REMAP_LOW_BITS;
uint32_t dst_start_align_addr = dst_start_addr >> FAMA_REMAP_LOW_BITS;
uint32_t dst_src_offset = 0;
if (region >= FAMA_REMAP_LOW_BITS) {
return ;
}
writel(src_reg_addr, src_start_align_addr);
writel(len_reg_addr, src_end_align_addr);
if (src_start_align_addr > dst_start_align_addr) {
dst_src_offset = src_start_align_addr - dst_start_align_addr;
dst_src_offset = ~dst_src_offset;
dst_src_offset = dst_src_offset + 1;
} else {
dst_src_offset = dst_start_align_addr - src_start_align_addr;
}
writel(dst_reg_addr, dst_src_offset);
}
static bool flashboot_need_recovery(void)
{
uint32_t reg = readl(FLASH_BOOT_TYPE_REG);
writel(FLASH_BOOT_TYPE_REG, 0);
return (reg == FLASH_BOOT_TYPE_REG_BKUP) ? true : false;
}
static void ws63_flashboot_recovery(void)
{
if (!flashboot_need_recovery()) {
return;
}
uapi_watchdog_kick();
boot_msg0("Flashboot backup is working!");
partition_information_t src_img_info = {0};
partition_information_t dst_img_info = {0};
errcode_t ret;
ret = uapi_partition_get_info(PARTITION_FLASH_BOOT_IMAGE_BACKUP, &src_img_info);
ret |= uapi_partition_get_info(PARTITION_FLASH_BOOT_IMAGE, &dst_img_info);
if (ret != ERRCODE_SUCC) {
boot_msg0("Flashboot partition info get fail!");
return;
}
ret = uapi_sfc_reg_erase(dst_img_info.part_info.addr_info.addr, dst_img_info.part_info.addr_info.size);
if (ret != ERRCODE_SUCC) {
boot_msg1("flashboot recovery erase failed!! ret = ", ret);
}
ret = uapi_sfc_reg_write(dst_img_info.part_info.addr_info.addr,
(uint8_t *)(uintptr_t)(src_img_info.part_info.addr_info.addr + FLASH_START),
src_img_info.part_info.addr_info.size);
if (ret != ERRCODE_SUCC) {
boot_msg1("flashboot recovery write failed!! ret = ", ret);
}
boot_msg0("Flashboot fix ok!");
}
#define UPG_FIX_RETRY_CNT_REG RESET_COUNT_REG
#define VERIFY_RETRY_CNT_THRES 0x3
#define UPG_FIX_RETRY_CNT_THRES (VERIFY_RETRY_CNT_THRES + 0x3)
#define UPG_AB_RETRY_CNT_THRES (VERIFY_RETRY_CNT_THRES + 0x3)
static uint8_t ws63_get_try_fix_cnt(void)
{
gp_reg1_union gp;
gp.u32 = readl(UPG_FIX_RETRY_CNT_REG);
return gp.bits.fota_fix_app_cnt;
}
static void ws63_set_try_fix_cnt(uint8_t cnt)
{
gp_reg1_union gp;
gp.u32 = readl(UPG_FIX_RETRY_CNT_REG);
gp.bits.fota_fix_app_cnt = cnt & 0xF;
writel(UPG_FIX_RETRY_CNT_REG, gp.u32);
}
#ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB
static void ws63_try_fix_app(void)
{
uint8_t try_cnt = ws63_get_try_fix_cnt() + 1;
ws63_set_try_fix_cnt(try_cnt);
/* 启动分区连续验签失败次数等于阈值倍数时,切换启动分区 */
if (try_cnt % VERIFY_RETRY_CNT_THRES) { // 1 2 4 5 7 8 a b d e
return;
} else { // 3 6 9 c f
boot_msg0("switch booting");
upg_set_run_region(upg_get_upg_region());
return;
}
}
#else // 压缩
/* 尝试ota修复运行区镜像 */
static void ws63_try_fix_app(void)
{
uint8_t try_cnt = ws63_get_try_fix_cnt();
/* 连续验签失败次数小于阈值不做处理 */
if (try_cnt < VERIFY_RETRY_CNT_THRES) {
ws63_set_try_fix_cnt(try_cnt + 1);
return;
}
/* 修复app超次数阈值后不再尝试 */
if (try_cnt >= UPG_FIX_RETRY_CNT_THRES) {
return;
}
ws63_set_try_fix_cnt(try_cnt + 1);
/* 重置升级标记 */
errcode_t ret = uapi_upg_reset_upgrade_flag();
if (ret != ERRCODE_SUCC) {
boot_msg1("reset_upgrade_flag fail, ret = ", ret);
return;
}
/* 请求升级 */
ret = uapi_upg_request_upgrade(false);
if (ret != ERRCODE_SUCC) {
boot_msg0("request_upgrade fail, fota_pkt_not_exit.");
return;
}
boot_msg0("fota_pkt exit, try_fota_fix_app.");
}
#endif
static bool ws63_upg_need_upgrade(void)
{
uint32_t fota_address = 0;
partition_information_t info;
errcode_t ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
if (ret_val != ERRCODE_SUCC || info.type != PARTITION_BY_ADDRESS) {
boot_msg1("uapi_partition_get_info failed ", __LINE__);
return false;
}
upg_get_upgrade_flag_flash_start_addr(&fota_address);
fota_upgrade_flag_area_t upg_flag_info;
ret_val = upg_flash_read(fota_address, sizeof(fota_upgrade_flag_area_t), (uint8_t *)(&upg_flag_info));
if (ret_val != ERRCODE_SUCC) {
boot_msg1("upg_flash_read failed ", ret_val);
return false;
}
if (!(upg_flag_info.head_magic == UPG_HEAD_MAGIC &&
upg_flag_info.head_end_magic == UPG_END_MAGIC &&
upg_flag_info.complete_flag != 0)) {
/* 不需要升级直接返回 */
boot_msg0("No need to upgrade...");
return false;
}
return true;
}
static void ws63_upg_check(void)
{
(void)ws63_upg_init();
#ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB
return;
#endif
if (ws63_upg_need_upgrade()) {
boot_msg0("need upgrade");
errcode_t ret = uapi_upg_start();
// 1, 没有升级包、或者升级标记区结果已经设置的情况不需要重启
// 2, 升级模块没有初始化不需要重启
// 3, 升级成功需要重启
// 4, 升级失败的时候需要重启重新进入升级流程尝试三次未成功后会变为1的情况
if (!(ret == ERRCODE_UPG_NOT_NEED_TO_UPDATE || ret == ERRCODE_UPG_NOT_INIT || ret == ERRCODE_SUCC)) {
boot_msg0("--------------------------");
boot_msg0("upgrade failed, reset now");
} else {
// 升级后重启
boot_msg0("--------------------------");
boot_msg0("upgrade success, reset now");
}
reset();
}
}
#define PMU_CMU_CTL_POC_COEX 0x40003238
#define RG_POC_SEL_SW_MODE 0x2
#define PMU_VDD_FLAG_3V3 0
#define POC_SEL_SW_MODE 1
#define POC_VALUE_3V3 0
#define LEVEL_3V3 0x33
#define LEVEL_1V8 0x18
typedef union {
struct {
uint32_t rg_poc_value : 1; /* [0] */
uint32_t rg_poc_sel : 1; /* [1] */
uint32_t pmu_vdd3318_flag : 1; /* [2] */
uint32_t ms1c : 1; /* [3] */
uint32_t rsv : 28; /* [31:4] */
} bits;
uint32_t u32;
} u_poc_coex;
static void fix_io_level(void)
{
u_poc_coex poc_coex = {0};
poc_coex.u32 = readl(PMU_CMU_CTL_POC_COEX);
if (poc_coex.bits.ms1c == poc_coex.bits.pmu_vdd3318_flag) {
return;
}
if (poc_coex.bits.pmu_vdd3318_flag != PMU_VDD_FLAG_3V3) {
return;
}
poc_coex.bits.rg_poc_value = POC_VALUE_3V3;
poc_coex.bits.rg_poc_sel = POC_SEL_SW_MODE;
writel(PMU_CMU_CTL_POC_COEX, poc_coex.u32);
}
static void dump_io_level(void)
{
u_poc_coex poc_coex = {0};
uint32_t chip_level = LEVEL_3V3;
uint32_t sw_level = LEVEL_3V3;
poc_coex.u32 = readl(PMU_CMU_CTL_POC_COEX);
if (poc_coex.bits.rg_poc_sel == POC_SEL_SW_MODE) {
sw_level = (poc_coex.bits.rg_poc_value == POC_VALUE_3V3) ? LEVEL_3V3 : LEVEL_1V8;
chip_level = (poc_coex.bits.ms1c == POC_VALUE_3V3) ? LEVEL_3V3 : LEVEL_1V8;
boot_msg2("io level work in sw mode, level[sw:chip]:", sw_level, chip_level);
} else {
chip_level = (poc_coex.bits.ms1c == POC_VALUE_3V3) ? LEVEL_3V3 : LEVEL_1V8;
boot_msg1("io level work in hw mode, level[chip]:", chip_level);
}
}
static uint32_t ws63_flashboot_init(void)
{
errcode_t err;
uart_param_stru uart_param = FLASHBOOT_UART_DEFAULT_PARAM;
uapi_tcxo_init();
hiburn_uart_init(uart_param, HIBURN_CODELOADER_UART);
boot_msg0("Flashboot Uart Init Succ!");
uapi_partition_init();
pmp_enable();
malloc_port_init();
boot_flash_init();
boot_msg0("Flashboot Uart Init Succ!");
boot_msg0("Flashboot Malloc Init Succ!");
err = sfc_port_fix_sr();
if (err != ERRCODE_SUCC) {
boot_msg1("SFC fix SR ret =", err);
}
dump_io_level();
print_str("flashboot version : %s\r\n", SDK_VERSION);
return 0;
}
static errcode_t ws63_verify_app(uint32_t addr)
{
errcode_t ret = ERRCODE_SUCC;
image_key_area_t *flashboot_key_area = (image_key_area_t *)(FLASHBOOT_RAM_ADDR);
ret = verify_image_head(APP_BOOT_TYPE, (uint32_t)(uintptr_t)flashboot_key_area->ext_pulic_key_area, addr);
if (ret != ERRCODE_SUCC) {
boot_msg1("flashboot verify_image_app_head failed!! ret = ", ret);
return ret;
}
ret = verify_image_body(addr, addr + APP_IMAGE_HEADER_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg1("verify_image_app_body failed!! ret = ", ret);
return ret;
}
return ERRCODE_SUCC;
}
static void ws63_verify_app_handle(uint32_t addr)
{
errcode_t ret = ws63_verify_app(addr);
if (ret != ERRCODE_SUCC) {
ws63_try_fix_app();
reset();
}
set_reset_count(0);
ws63_set_try_fix_cnt(0);
}
static void ws63_flash_encrypt_config(uint32_t image_addr, uint32_t image_size)
{
image_code_info_t *img_info = (image_code_info_t *)(uintptr_t)(image_addr + sizeof(image_key_area_t));
crypto_klad_effective_key flash_key = {0};
uint32_t start_addr = image_addr + APP_IMAGE_HEADER_LEN;
uint32_t end_addr = image_addr + image_size;
int32_t ret = ERRCODE_SUCC;
if (img_info->code_enc_flag == FLASH_NO_ENCRY_FLAG) {
boot_msg0("flash_encrypt disable.");
return;
}
if (start_addr % FLASH_ENCRY_ADDR_ALINE != 0 || end_addr % FLASH_ENCRY_ADDR_ALINE != 0) {
boot_msg2("app_image start or end addr err, must 256byte alignment ", image_addr, end_addr);
reset();
}
boot_msg0("flash_encrypt enable.");
flash_key.kdf_hard_alg = CRYPTO_KDF_HARD_ALG_SHA256;
flash_key.key_parity = TD_FALSE;
flash_key.key_size = CRYPTO_KLAD_KEY_SIZE_128BIT;
flash_key.salt = img_info->protection_key_l1;
flash_key.salt_length = FLASH_KEY_SALT_LEN;
flash_key.oneway = TD_TRUE;
ret = drv_rom_cipher_config_odrk1(flash_key);
if (ret != ERRCODE_SUCC) {
boot_msg1("fapc_set_config drv_rom_cipher_config_odrk1 err = ", (uint32_t)ret);
reset();
}
ret = drv_rom_cipher_fapc_config(0, start_addr, end_addr, img_info->iv, IV_LEN);
if (ret != ERRCODE_SUCC) {
boot_msg1("fapc_set_config drv_rom_cipher_fapc_config err = ", (uint32_t)ret);
reset();
}
ret = drv_rom_cipher_fapc_bypass_config(1, end_addr, FLASH_MAX_END, TD_TRUE);
if (ret != ERRCODE_SUCC) {
boot_msg1("fapc_set_config drv_rom_cipher_fapc_bypass_config err = ", (uint32_t)ret);
reset();
}
}
static uint32_t ws63_ftm_mode_init(uint32_t image_addr)
{
uint32_t image_size = 0;
uint32_t jump_addr = 0;
mfg_factory_config_t mfg_factory_cfg = {0};
uint32_t run_region = mfg_get_ftm_run_region(&mfg_factory_cfg);
if (run_region == FTM_REGION_SERVICE) {
return 0;
}
jump_addr = mfg_factory_cfg.factory_addr_start;
image_size = mfg_factory_cfg.factory_size;
image_key_area_t *mfg_key_area = (image_key_area_t *)(uintptr_t)(jump_addr);
if (mfg_key_area->image_id == FACTORYBOOT_KEY_AREA_IMAGE_ID && mfg_factory_cfg.factory_valid == MFG_FACTORY_VALID) {
dmmu_set(image_addr, image_addr + image_size, jump_addr, 0);
}
return 0;
}
/* the entry of C. */
void start_fastboot(void)
{
partition_information_t img_info = {0};
uint32_t image_addr = 0;
uint32_t image_size = 0;
errcode_t err;
fix_io_level();
// 关闭CMU假负载
uapi_reg_setbits(REG_CMU_CFG0, 3, 3, 0x7); // 0x7 -> 0x40003408 bit 5:3 (3 bits)
boot_clock_adapt();
dmmu_set(0, 0, 0, FAMA_REMAP_LOW_BITS);
uapi_watchdog_init(BOOT_WATCH_DOG_TIMOUT);
uapi_watchdog_enable(WDT_MODE_RESET);
ws63_flashboot_init();
set_efuse_period();
uapi_efuse_init();
ws63_upg_check(); // 升级模式判断
err = uapi_partition_get_info(PARTITION_APP_IMAGE, &img_info);
if (err != ERRCODE_SUCC) {
boot_msg0("Flashboot get app partition failed!, boot abort!");
reset();
}
image_addr = img_info.part_info.addr_info.addr + FLASH_START;
image_size = img_info.part_info.addr_info.size;
#ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB
char *boot_str = "A";
uint32_t jump_addr = upg_get_region_addr(upg_get_run_region()) + FLASH_START;
*boot_str = (image_addr == jump_addr) ? 'A' : 'B';
boot_msg0(boot_str);
ws63_flash_encrypt_config(jump_addr, image_size); // flash在线加解密配置
ws63_verify_app_handle(jump_addr); // A/B验签
if (image_addr != jump_addr) {
// 0x1000: dmmu配置都是闭区间且需要是4K对齐的地址, 0: 第0组dmmu配置
dmmu_set(image_addr, image_addr + image_size - 0x1000, jump_addr, 0);
// 0x1000: dmmu配置都是闭区间且需要是4K对齐的地址, 1: 第1组dmmu配置
dmmu_set(jump_addr, jump_addr + image_size - 0x1000, image_addr, 1);
}
#else // 压缩
ws63_flash_encrypt_config(image_addr, image_size); // flash在线加解密配置
ws63_verify_app_handle(image_addr); // app验签
#endif
ws63_ftm_mode_init(image_addr);
ws63_flashboot_recovery();
uapi_watchdog_kick();
jump_to_execute_addr(image_addr + APP_IMAGE_HEADER_LEN);
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2021. All rights reserved.
* Description: main
*
* Create: 2021-03-09
*/
.section .text.entry
.global _start
.option norvc
_start:
j Reset_Handler
Reset_Handler:
li t0,0x0
csrw pmpcfg0,t0
li t0,0x0
csrw pmpcfg1,t0
li t0,0x0
csrw pmpcfg2,t0
li t0,0x0
csrw pmpcfg3,t0
li t0,0x0
csrw 0x7d9,t0
la t0, __flash_boot_flag_begin__
mv t1, a0
lw t3, (t1)
sw t3, (t0)
la t0, trap_vector
addi t0, t0, 1
csrw mtvec, t0
csrwi mstatus, 0
csrwi mie, 0
# initialize global pointer
la gp, _gp_
# initialize stack pointer
la sp, __stack_top__
/* init stack */
la t0, g_system_stack_begin
la t1, g_system_stack_end
beq t0, t1, end_set_stack_loop
li t2, 0xefbeadde
set_stack_loop:
sw t2, (t0)
addi t0, t0, 4
blt t0, t1, set_stack_loop
end_set_stack_loop:
/* clear reg */
li ra, 0
li tp, 0
li s0, 0
li s1, 0
li a0, 0
li a1, 0
li a2, 0
li a3, 0
li a4, 0
li a5, 0
li a6, 0
li a7, 0
li s2, 0
li s3, 0
li s4, 0
li s5, 0
li s6, 0
li s7, 0
li s8, 0
li s9, 0
li s10, 0
li s11, 0
li t3, 0
li t4, 0
li t5, 0
li t6, 0
/* clear bss section */
la t0, __bss_begin__
la t1, __bss_end__
beq t0, t1, end_clear_bss_loop
li t2, 0x00000000
clear_bss_loop:
sw t2, (t0)
addi t0, t0, 4
blt t0, t1, clear_bss_loop
end_clear_bss_loop:
j start_fastboot

View File

@ -0,0 +1,45 @@
#===============================================================================
# @brief cmake file
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved.
#===============================================================================
set(COMPONENT_NAME "loaderboot_common")
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/startup/main.c
${CMAKE_CURRENT_SOURCE_DIR}/startup/riscv_init.S
${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/src/boot_uart_auth.c
)
if(DEFINED CONFIG_LOADERBOOT_SUPPORT_FLASH_CHIP_ERASE)
list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/src/boot_erase.c")
endif()
set(PUBLIC_HEADER
${CMAKE_CURRENT_SOURCE_DIR}/include
)
set(PRIVATE_HEADER
)
set(PRIVATE_DEFINES
)
set(PUBLIC_DEFINES
)
# use this when you want to add ccflags like -include xxx
set(COMPONENT_PUBLIC_CCFLAGS
)
set(COMPONENT_CCFLAGS
)
set(WHOLE_LINK
true
)
set(MAIN_COMPONENT
false
)
build_component()

View File

@ -0,0 +1,423 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2021. All rights reserved.
* Description: main
*
* Create: 2021-03-09
*/
#include "boot_cmd_loop.h"
#include "boot_serial.h"
#include "boot_flash.h"
#include "sfc.h"
#include "chip_io.h"
#include "pinctrl.h"
#include "boot_delay.h"
#include "tcxo.h"
#include "watchdog.h"
#include "soc_porting.h"
#include "efuse.h"
#include "efuse_porting.h"
#include "boot_malloc.h"
#include "boot_erase.h"
#include "sfc_protect.h"
#define DELAY_100MS 100
__attribute__((section("BOOT_UART"))) uart_param_stru g_uart_prag;
const sfc_flash_config_t sfc_cfg = {
.read_type = FAST_READ_QUAD_OUTPUT,
.write_type = PAGE_PROGRAM,
.mapping_addr = 0x200000,
.mapping_size = 0x800000,
};
#if 1 //ADD LYL 2024 1122 --------
#define USERPAGE 0x003F2000 //AT参数存储区
#define BLE_CONKEYLEN 16
#pragma pack(push)
#pragma pack(1)
typedef struct
{
int8_t updateflag; //update flag
int8_t validflag; //valid flag
int8_t tmode_mode;
int8_t wmode_mode;
//STA, 140 bytes
uint8_t sta_ssid[33];
uint8_t sta_key[65];
int8_t wsauth;
int8_t wsencry;
uint8_t wslko;
uint8_t pmk_av;
uint8_t sta_padding[6];
uint8_t pmk[32];
//AP, 144 bytes
int8_t wap_mode;
int8_t wap_channel;
int8_t waauth;
int8_t waencry;
uint8_t walk_led;
uint8_t max_sta_num;
uint8_t ap_enable_hide;
uint8_t ap_ssid[33];
uint8_t ap_key[65];
uint8_t ap_pmk_av;
uint8_t ap_pmk[32];
uint8_t ap_padding[6];
//UART, 20 bytes
int8_t baudrate;
int8_t data_bits;
int8_t stop_bits;
int8_t parity;
int8_t ctsrts;
int8_t uart1_baudrate;
int8_t uart1_data_bits;
int8_t uart1_stop_bits;
int8_t uart1_parity;
int8_t uart1_debug;
int8_t uartfable;
int8_t fuartte_mode;
uint16_t uarttm;
uint16_t uartbuf;
uint8_t uart_padding[4];
//NETP, 108 bytes
int8_t protocol;
int8_t app_mode;
uint8_t maxsocket;
char cipadd[101];
uint16_t pro_port;
uint16_t tcpto;
//SOCKB, 112 bytes
uint16_t sockb_port;
uint16_t sockb_tcpto;
int8_t sockb_pro;
char sockb_cipadd[101];
int8_t tcpdis;
int8_t tcpdisb;
uint16_t udp_localporta;
uint16_t udp_localportb;
//NETWORK, 108 bytes
char wann_ipaddr[16];
char wann_mask[16];
char wann_gateway[16];
char lann_ipaddr[16];
char lann_mask[16];
uint8_t wann_mode;
uint8_t network_padding[2];
uint8_t domain_name[21];
uint32_t dns_addr;
//UTILS, 124 bytes
int8_t echo;
int8_t rlden;
uint8_t debug_level;
char wel_msg[11];
uint8_t event_onoff;
uint8_t noise_filter;
uint8_t wifi_switch;
uint8_t sta_dtim;
uint8_t utils_padding[40];
uint8_t dis_power_saving;
int8_t modechange;
uint8_t ps_interval;
uint8_t mid[21];
uint8_t aswd[21];
uint8_t cmdpw[21];
//HTTPD, 36 bytes
char user_name[16];
char user_password[16];
int8_t web_switch;
uint8_t web_language;
uint8_t web_encode_format;
uint8_t httpd_padding;
//DHCPD, 4 bytes
int8_t dhcpsw;
uint8_t dhcpd_addr_start;
uint8_t dhcpd_addr_end;
uint8_t dhcpd_padding;
//UPDATE, 124 bytes
char update_url[101];
char update_file[21];
uint8_t update_padding[2];
//NTP, 8 bytes
uint8_t ntp_time;
uint8_t ntp_enable;
uint8_t ntp_padding;
int8_t time_zone;
uint32_t ntpserver;
//SMTLK, 16 bytes
uint32_t smtlk_sign;
uint8_t smtlk_mode;
uint8_t smtlk_protocol;
uint8_t smtlk_rtype;
uint8_t smtlk_ak_random;
uint8_t connect_flag;
uint8_t sta_channel;
uint8_t sta_bssid[6];
//SMARTAPLINK, 44 bytes
uint8_t smartaplink_enable;
uint8_t smartaplink_padding;
uint8_t smartaplink_prefix[21];
uint8_t smartaplink_key[21];
//NETPID, 24 bytes
uint8_t netpa_iden;
char netpa_id[11];
uint8_t netpb_iden;
char netpb_id[11];
//NETPREG, 264 bytes
uint8_t netpa_regen;
uint8_t netpa_regtype;
uint8_t netpa_reg_padding;
char netpa_regdata[129];
uint8_t netpb_regen;
uint8_t netpb_regtype;
uint8_t netpb_reg_padding;
char netpb_regdata[129];
//HEART, 124 bytes
uint16_t heart_netp_time;
uint16_t heart_sockb_time;
uint16_t heart_uart_time;
char heart_netp_data[39];
char heart_sockb_data[39];
char heart_uart_data[39];
uint8_t heart_padding;
//HTTP, 236 bytes
uint8_t http_type;
uint8_t http_version;
uint8_t http_connect_type;
uint8_t http_recv_time;
char http_url[51];
char http_header[181];
//MQTT, 224 bytes
char mqtt_username[33];
char mqtt_password[33];
char mqtt_clientid[33];
char mqtt_pub_topic[61];
char mqtt_sub_topic[61];
uint8_t mqtt_qos;
uint16_t mqtt_heart_time;
//BLE, 188 bytes
uint16_t conn_min;
uint16_t conn_max;
uint16_t conn_latency;
uint16_t supervisionTO;
uint16_t adver_min;
uint16_t adver_max;
uint8_t ble_name[27]; //BLE广播名
uint8_t ble_dms_name[27]; //BLE配网名
uint8_t ble_adver_data[27];
uint8_t ble_adver_data_len;
uint8_t ble_switch;
uint8_t ble_uuid_server;
uint8_t dms_type;
uint8_t ble_padding;
uint8_t uuid_ntf_server[17];
uint8_t uuid_ntf_read[17];
uint8_t uuid_ntf_write[17];
uint8_t uuid_ind_server[17];
uint8_t uuid_ind_read[17];
uint8_t uuid_ind_write[17];
uint8_t adver_type;
uint8_t adver_channel;
uint8_t ble_ind;
uint8_t smartconfiglink;
uint8_t ble_conenable;
uint8_t ble_conkey[BLE_CONKEYLEN];
uint8_t ble_contimeout;
uint8_t netpc_iden;
char netpc_id[11];
uint8_t netpc_idflag;
uint8_t ble_padding2[17];
uint8_t mqtt_tls;
uint8_t mqtt_padding[3];
char iot_productkey[12];
char iot_devicename[48];
char iot_devicesecret[48];
char iot_pubtopic[96];
char iot_subtopic[96];
char iot_mode;
char iot_padding[3];
uint8_t product_mode;
int8_t ctsrts_pin;
char instance_flag;
char instance_id[32];
char ntp_domain_server[33];
int8_t smk_find;
uint32_t mcu_ota_size;
uint8_t scan_ch14;
uint32_t module_reset_reason;
uint8_t reserved1[60+512-4];
uint8_t validflag_magic;
int8_t validflag_end; //valid flag
}HF_CONFIG_FILE;
#pragma pack(pop)
HF_CONFIG_FILE g_hf_config_file_boot = {0};
int hfdbg_get_sw(void)
{
if(g_hf_config_file_boot.debug_level > 0 && g_hf_config_file_boot.debug_level<=20) //1~20允许打印
return 0;
if(g_hf_config_file_boot.uart1_debug == 1) //1允许打印
return 1;
return 0;
}
#endif
static uint32_t sfc_flash_init(void)
{
return uapi_sfc_init((sfc_flash_config_t *)&sfc_cfg);
}
static uint32_t sfc_flash_read(uint32_t flash_addr, uint32_t read_size, uint8_t *read_buffer)
{
return uapi_sfc_reg_read(flash_addr, read_buffer, read_size);
}
// addr 不是总线地址,没有 FLASH_START 偏移
static bool is_flash_addr(uint32_t addr, uint32_t size)
{
return ((addr >= 0) && (addr + size < FLASH_LEN));
}
static uint32_t sfc_flash_write(uint32_t flash_addr, uint32_t flash_write_size, const uint8_t *p_flash_write_data,
bool do_erase)
{
unused(do_erase);
if (is_flash_addr(flash_addr, flash_write_size)) {
return uapi_sfc_reg_write(flash_addr, (uint8_t *)p_flash_write_data, flash_write_size);
}
// 使用memcpy_s时操作的是总线地址需要加回偏移FLASH_START
uintptr_t store_addr = (uintptr_t)((int)flash_addr + (int)FLASH_START);
if (memcpy_s((void *)store_addr, flash_write_size, p_flash_write_data, flash_write_size) != EOK) {
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
static uint32_t sfc_flash_erase(uint32_t flash_addr, uint32_t flash_erase_size)
{
if (flash_erase_size == FLASH_CHIP_ERASE_SIZE) {
return uapi_sfc_reg_erase_chip();
}
return uapi_sfc_reg_erase(flash_addr - sfc_cfg.mapping_addr, flash_erase_size);
}
static void boot_flash_init(void)
{
flash_cmd_func flash_funcs = {0};
flash_funcs.init = sfc_flash_init;
flash_funcs.read = sfc_flash_read;
flash_funcs.write = sfc_flash_write;
flash_funcs.erase = sfc_flash_erase;
boot_regist_flash_cmd(&flash_funcs);
#define REG_PMU_CMU_CTL_PMU_SIG 0x40003154
#define PMU_FLASH_SW_EN_BIT 24
#define DELAY_5MS 5
reg32_setbit(REG_PMU_CMU_CTL_PMU_SIG, PMU_FLASH_SW_EN_BIT);
mdelay(DELAY_5MS);
uint32_t ret = sfc_flash_init();
if (ret != ERRCODE_SUCC) {
boot_msg1("Flash Init Fail! ret = ", ret);
} else {
boot_msg0("Flash Init Succ!");
}
switch_flash_clock_to_pll();
config_sfc_ctrl_ds();
}
static uint32_t ws63_loaderboot_init(void)
{
errcode_t err;
uapi_tcxo_init();
hiburn_uart_init(g_uart_prag, HIBURN_CODELOADER_UART);
boot_msg0("Loadboot Uart Init Succ!");
boot_flash_init();
err = sfc_port_fix_sr();
if (err != ERRCODE_SUCC) {
boot_msg1("SFC fix SR ret =", err);
}
set_efuse_period();
uapi_efuse_init(); // efuse函数初始化
boot_malloc_init();
return 0;
}
#define BOOT_WATCH_DOG_TIMOUT 15 // 15s
/* the entry of C. */
void start_loaderboot(void)
{
uart_ctx cmd_ctx = { 0 };
boot_clock_adapt();
uapi_watchdog_init(BOOT_WATCH_DOG_TIMOUT);
uapi_watchdog_enable(WDT_MODE_RESET);
ws63_loaderboot_init();
/* Enter the waiting command cycle. */
loader_ack(ACK_SUCCESS);
boot_msg0("================ Load Cmd Loop ================\r\n");
cmd_loop(&cmd_ctx);
while (1) {}
}
#ifdef CONFIG_LOADERBOOT_SUPPORT_SET_BUADRATE
uint32_t serial_port_set_baudrate(const uart_param_stru *uart)
{
#define CLDO_CRG_CLK_SEL 0x44001134
#define CLDO_SUB_CRG_CKEN_CTL1 0x44001104
#define UART_PLL_CLOCK 160000000
hiburn_uart_deinit();
// 切uart时钟
reg_clrbit(CLDO_SUB_CRG_CKEN_CTL1, 0, POS_18); // close uart clock
reg_setbit(CLDO_CRG_CLK_SEL, 0, POS_1); // switch uart clock to pll
reg_setbit(CLDO_SUB_CRG_CKEN_CTL1, 0, POS_18); // open uart clock
uart_port_set_clock_value(UART_BUS_0, UART_PLL_CLOCK);
hiburn_uart_init(*uart, HIBURN_CODELOADER_UART);
return ERRCODE_SUCC;
}
#endif

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2021. All rights reserved.
* Description: main
*
* Create: 2021-03-09
*/
.section .text.entry
.global _start
.option norvc
_start:
j Reset_Handler
Reset_Handler:
la t0, __boot_uart_begin__
mv t1, a0
mv t2, a1
set_arg_loop:
lw t3, (t1)
sw t3, (t0)
addi t0, t0, 4
addi t1, t1, 4
addi t2, t2, -4
blt x0, t2, set_arg_loop
la t0, trap_vector
addi t0, t0, 1
csrw mtvec, t0
csrwi mstatus, 0
csrwi mie, 0
# initialize global pointer
la gp, _gp_
# initialize stack pointer
la sp, __stack_top__
/* init stack */
la t0, g_system_stack_begin
la t1, g_system_stack_end
beq t0, t1, end_set_stack_loop
li t2, 0xefbeadde
set_stack_loop:
sw t2, (t0)
addi t0, t0, 4
blt t0, t1, set_stack_loop
end_set_stack_loop:
/* clear reg */
li ra, 0
li tp, 0
li s0, 0
li s1, 0
li a0, 0
li a1, 0
li a2, 0
li a3, 0
li a4, 0
li a5, 0
li a6, 0
li a7, 0
li s2, 0
li s3, 0
li s4, 0
li s5, 0
li s6, 0
li s7, 0
li s8, 0
li s9, 0
li s10, 0
li s11, 0
li t3, 0
li t4, 0
li t5, 0
li t6, 0
/* set data section */
la t0, __data_begin__
la t1, __data_load__
la t2, __data_size__
beq t2, x0, end_set_data_loop
set_data_loop:
lw t3, (t1)
sw t3, (t0)
addi t0, t0, 4
addi t1, t1, 4
addi t2, t2, -4
blt x0, t2, set_data_loop
end_set_data_loop:
/* clear bss section */
la t0, __bss_begin__
la t1, __bss_end__
beq t0, t1, end_clear_bss_loop
li t2, 0x00000000
clear_bss_loop:
sw t2, (t0)
addi t0, t0, 4
blt t0, t1, clear_bss_loop
end_clear_bss_loop:
j start_loaderboot