应用固件校验跳转运行
当不存在应用固件OTA拷贝升级任务时,Second Boot会对该应用固件进行有效性检查并跳转至该应用固件中运行。
路径:工程目录下的user_app\user_boot.c
名称:is_jump_user_fw();
is_jump_user_fw()函数用于跳转到应用固件运行前的检查。
在is_jump_user_fw()函数中,通过读取APP Image Info的comments和实际应用固件的comments(USER_FW_COMMENTS)进行对比,判断两者comments是否相同,相同说明Bank0中存在应用固件,进一步校验APP Image Info有效性,有效性通过则可跳转到该应用固件运行。
如comments不相同,说明Bank0中不存在应用固件,此时可通过读取SCA区域索引到的应用固件Image Info的comments,和USER_FW_COMMENTS对比,如两者comments相同,再校验该SCA中应用固件Image Info有效性,有效性通过,会将SCA中的应用固件Image Info更新至APP Image Info;如两者comments不同,或者有效性不通过,则不能跳转。
static bool is_jump_user_fw(void)
{
memset((uint8_t*)&app_img_info, 0, sizeof(img_info_t));
hal_flash_read_judge_security(IMG_INFO_APP_ADDR, (uint8_t*)&app_img_info,
sizeof(img_info_t));
if ((app_img_info.pattern == 0x4744) &&\
(0 == memcmp(app_img_info.comments, USER_FW_COMMENTS, strlen(USER_FW_COMMENTS))))
{
APP_LOG_DEBUG("found APP img info.");
log_boot_info(&app_img_info.boot_info);
if (boot_fw_valid_check(app_img_info.boot_info.load_addr, &app_img_info.boot_info))
{
APP_LOG_DEBUG("check APP img valid.");
return true;
}
}
APP_LOG_DEBUG("Not found APP img info on the third page,continue to search on the first
page");
img_info_t img_info_main;
for (uint8_t i = 0; i < IMG_INFO_SAVE_NUM_MAX; i++)
{
fw_img_info_get(BOOT_INFO_ADDR + 0x40, i, &img_info_main);
if (0 == memcmp(img_info_main.comments, USER_FW_COMMENTS, strlen(USER_FW_COMMENTS)))
{
if (boot_fw_valid_check(img_info_main.boot_info.load_addr,
&img_info_main.boot_info))
{
user_img_info_update(&img_info_main);
memcpy(&app_img_info, &img_info_main, sizeof(img_info_t));
APP_LOG_DEBUG("Found the APP firmware on the first page");
return true;
}
}
}
APP_LOG_DEBUG("Not found APP FW image info.");
return false;
}
路径:工程目录下的user_app\user_boot.c
名称1:jump_user_fw();
名称2:sec_boot_jump();
跳转前需更新热启动Boot Info、设置MSP、重定位向量表。
static void jump_user_fw(void)
{
APP_LOG_DEBUG("Jump to APP FW.");
APP_LOG_DEBUG("---------------------------------------------------------------");
sec_boot_jump(&app_img_info.boot_info);
}
static void sec_boot_jump(boot_info_t *p_boot_info)
{
extern void rom_init(void);
extern void jump_app(uint32_t addr);
extern boot_info_t bl1_boot_info;
extern void bl_xip_dis(void);
uint16_t enc_mode = *(uint16_t*)0x30000020;
bool mirror_mode = false;
if(p_boot_info->run_addr != p_boot_info->load_addr)//mirror mode
{
mirror_mode = true;
if(!enc_mode)
SET_CODE_LOAD_FLAG();
memcpy((uint8_t*)p_boot_info->run_addr, (uint8_t*)p_boot_info->load_addr,
p_boot_info->bin_size);
}
if(enc_mode)
{
REG(0xA000C578UL) &= ~0xFFFFFC00;
REG(0xA000C578UL) |= (p_boot_info->run_addr & 0xFFFFFC00);
}
rom_init();
__disable_irq();
SysTick->CTRL = 0;
__enable_irq();
memcpy(&bl1_boot_info, p_boot_info, sizeof(boot_info_t));
if(mirror_mode)
{
if(enc_mode)
{
REG(0xa000d470) = ENCRY_CTRL_DISABLE;
}
}
jump_app(p_boot_info->run_addr);
}
为了在睡眠唤醒后热启动时,可直接跳转至应用固件,需先将应用固件boot info赋值给全局变量bl1_boot_info,即memcpy(&bl1_boot_info, p_boot_info, sizeof(boot_info_t));,此处切勿改动 。