781 lines
22 KiB
C
Executable File
781 lines
22 KiB
C
Executable File
/*
|
||
* 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);
|
||
}
|