435 lines
13 KiB
C
435 lines
13 KiB
C
#ifdef SUPPORT_MS_EXTENSIONS
|
|
#pragma bss_seg(".reusable_update.data.bss")
|
|
#pragma data_seg(".reusable_update.data")
|
|
#pragma const_seg(".reusable_update.text.const")
|
|
#pragma code_seg(".reusable_update.text")
|
|
#endif
|
|
|
|
#include "update.h"
|
|
#include "update_loader_download.h"
|
|
#include "app_config.h"
|
|
#include "cpu.h"
|
|
#include "system/includes.h"
|
|
#include "app_main.h"
|
|
#include "fs/sdfile.h"
|
|
#include "norflash.h"
|
|
#include "rec_nor/nor_interface.h"
|
|
#include "user_cfg_id.h"
|
|
|
|
#if TCFG_UPDATE_ENABLE
|
|
|
|
#define LOG_TAG "[REUSABLE-UPDATE]"
|
|
#define LOG_INFO_ENABLE
|
|
#define LOG_ERROR_ENABLE
|
|
#include "debug.h"
|
|
|
|
/*
|
|
REUSABLE RESERVED AREA
|
|
#-----------------------------------------------------------------+ ->4KB aligned
|
|
# |
|
|
# EXIF (4KB) |
|
|
# |
|
|
#-----------------------------------------------------------------| ->4KB aligned
|
|
# |
|
|
# loader.bin |
|
|
# vm bak |
|
|
# update_param |
|
|
# |
|
|
#-----------------------------------------------------------------+ ->end
|
|
*/
|
|
|
|
#define SECTOR_SIZE 4096
|
|
#define ALIGN_SECTOR(x) (((x + SECTOR_SIZE - 1) / SECTOR_SIZE) * SECTOR_SIZE)
|
|
|
|
#define LOADER_RESERVE_SIZE (100) // 单位是K
|
|
|
|
#define REUSABLE_RESERVED "REUSABLE"
|
|
#define SDFILE_EXT_RESERVED_ROOT_PATH "mnt/sdfile/EXT_RESERVED/"
|
|
|
|
struct reuable_info_record {
|
|
union {
|
|
struct {
|
|
u32 reserve;
|
|
};
|
|
struct {
|
|
u8 app_update_flag;
|
|
};
|
|
};
|
|
u32 update_again_flag;
|
|
};
|
|
|
|
struct reusable_reserv {
|
|
u8 init_flag;
|
|
|
|
u32 base_addr;
|
|
u32 total_size;
|
|
|
|
u32 exif_addr;
|
|
u32 exif_size;
|
|
|
|
u32 loader_addr;
|
|
u32 loader_size;
|
|
};
|
|
struct reusable_reserv reusable_region = {0};
|
|
|
|
#define __this (&reusable_region)
|
|
|
|
static u8 new_sdk_update_again_flag = 0;
|
|
|
|
static void reusable_param_dump(void)
|
|
{
|
|
printf("init_flag = %d\n", __this->init_flag);
|
|
printf("base_addr = 0x%x\n", __this->base_addr);
|
|
printf("total_size = 0x%x\n", __this->total_size);
|
|
printf("exif_addr = 0x%x\n", __this->exif_addr);
|
|
printf("exif_size = 0x%x\n", __this->exif_size);
|
|
printf("loader_addr = 0x%x\n", __this->loader_addr);
|
|
printf("loader_size = 0x%x\n", __this->loader_size);
|
|
}
|
|
|
|
|
|
|
|
extern u32 sfc_read(u8 *buf, u32 addr, u32 len);
|
|
extern u32 sfc_write(const u8 *buf, u32 addr, u32 len);
|
|
extern bool sfc_erase(int cmd, u32 addr);
|
|
extern bool reserved_area_special_handle(u8 opt);
|
|
extern const int support_reusable_special_update;
|
|
extern u32 config_update_features;
|
|
extern char *watch_get_root_path();
|
|
|
|
static u32 reusable_region_write(const u8 *buf, u32 addr, u32 len)
|
|
{
|
|
if (__this->init_flag == 0) {
|
|
return 0;
|
|
}
|
|
return sfc_write(buf, addr, len);
|
|
}
|
|
|
|
static u32 reusable_region_read(u8 *buf, u32 addr, u32 len)
|
|
{
|
|
if (__this->init_flag == 0) {
|
|
return 0;
|
|
}
|
|
return sfc_read(buf, addr, len);
|
|
}
|
|
|
|
static bool reusable_region_erase(int cmd, u32 addr)
|
|
{
|
|
if (__this->init_flag == 0) {
|
|
return false;
|
|
}
|
|
return sfc_erase(cmd, addr);
|
|
}
|
|
|
|
|
|
int reusable_region_init(void)
|
|
{
|
|
int ret;
|
|
FILE *fp = NULL;
|
|
struct vfs_attr file_attr;
|
|
const char *fpth = SDFILE_EXT_RESERVED_ROOT_PATH;
|
|
|
|
u8 file_path_len = sizeof(SDFILE_EXT_RESERVED_ROOT_PATH) + strlen((const char *)REUSABLE_RESERVED);
|
|
u8 *file_path = zalloc(file_path_len);
|
|
if (NULL == file_path) {
|
|
log_error("%s, alloc fail\n", __func__);
|
|
ret = -1;
|
|
goto err1;
|
|
}
|
|
|
|
// 如果SDFILE_APP_ROOT_PATH + REUSABLE_RESERVED不行,则还需要尝试打开扩展预留区域(mnt/sdfile/EXT_RESERVED)
|
|
memcpy(file_path, SDFILE_APP_ROOT_PATH, strlen(SDFILE_APP_ROOT_PATH));
|
|
memcpy(file_path + strlen(SDFILE_APP_ROOT_PATH), REUSABLE_RESERVED, strlen((const char *)REUSABLE_RESERVED));
|
|
fp = fopen((const char *)file_path, "r");
|
|
|
|
if (!fp) {
|
|
memset((void *)file_path, 0, file_path_len);
|
|
memcpy((void *)file_path, SDFILE_EXT_RESERVED_ROOT_PATH, strlen(SDFILE_EXT_RESERVED_ROOT_PATH));
|
|
memcpy((void *)(file_path + strlen(SDFILE_EXT_RESERVED_ROOT_PATH)), REUSABLE_RESERVED, strlen((const char *)REUSABLE_RESERVED));
|
|
fp = fopen((const char *)file_path, "r");
|
|
}
|
|
|
|
if (!fp) {
|
|
log_error("open %s fail\n", fpth);
|
|
ret = -2;
|
|
goto err2;
|
|
}
|
|
|
|
fget_attrs(fp, &file_attr);
|
|
__this->base_addr = sdfile_cpu_addr2flash_addr(file_attr.sclust);
|
|
__this->total_size = file_attr.fsize;
|
|
|
|
__this->exif_addr = ALIGN_SECTOR(__this->base_addr);
|
|
__this->exif_size = SECTOR_SIZE;
|
|
__this->loader_addr = __this->exif_addr + __this->exif_size;
|
|
__this->loader_size = __this->base_addr + __this->total_size - __this->loader_addr;
|
|
__this->loader_size = __this->loader_size / SECTOR_SIZE * SECTOR_SIZE;
|
|
|
|
if (__this->loader_size < SECTOR_SIZE) {
|
|
log_error("loader region too small\n");
|
|
ret = -3;
|
|
goto err2;
|
|
}
|
|
|
|
__this->init_flag = 1;
|
|
|
|
reusable_param_dump();
|
|
free(file_path);
|
|
|
|
return 0;
|
|
|
|
err2:
|
|
free(file_path);
|
|
err1:
|
|
__this->init_flag = 0;
|
|
return ret;
|
|
}
|
|
|
|
static bool reusable_update_flag_handle(u32 *value, u8 type, u8 dir)
|
|
{
|
|
struct reuable_info_record reuable_info = {0};
|
|
// 先读
|
|
bool ret = (sizeof(reuable_info) == syscfg_read(VM_REUSABLE_SPECIAL_UPDATE_INFO, &reuable_info, sizeof(reuable_info)));
|
|
if (dir) {
|
|
// 写前判断当前值是否一致
|
|
switch (type) {
|
|
case 0: // 对app下发的标志位进行操作
|
|
u8 app_update_flag = ((u8 *)value)[0];
|
|
if (ret && reuable_info.app_update_flag == app_update_flag) {
|
|
break;
|
|
}
|
|
reuable_info.app_update_flag = app_update_flag;
|
|
syscfg_write(VM_REUSABLE_SPECIAL_UPDATE_INFO, &reuable_info, sizeof(reuable_info));
|
|
break;
|
|
case 1: // 对升级标志位进行操作
|
|
u32 update_again_flag = *value;
|
|
if (ret && reuable_info.update_again_flag == update_again_flag) {
|
|
break;
|
|
}
|
|
reuable_info.update_again_flag = update_again_flag;
|
|
syscfg_write(VM_REUSABLE_SPECIAL_UPDATE_INFO, &reuable_info, sizeof(reuable_info));
|
|
break;
|
|
}
|
|
} else {
|
|
switch (type) {
|
|
case 0:
|
|
if (ret) {
|
|
((u8 *)value)[0] = reuable_info.app_update_flag;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (ret) {
|
|
*value = reuable_info.update_again_flag;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static bool reusable_update_is_push_loader_only(void)
|
|
{
|
|
bool ret = reusable_update_flag_handle(&config_update_features, 1, 0);
|
|
if (ret) {
|
|
ret = (~BIT(CONFIG_UPDATE_FEATRUES_CONTENT_COMPARE_EN) & config_update_features) == BIT(CONFIG_UPDATE_FEATRUES_PUSH_LOADER_ONLY_EN);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int reusable_update_specail_handle(int update_type)
|
|
{
|
|
if (0 == reserved_area_special_handle(0)) {
|
|
// 如果蓝牙升级,则必须带资源
|
|
if (BT_UPDATA == update_type || BLE_TEST_UPDATA == update_type) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (reusable_update_is_push_loader_only()) {
|
|
config_update_features |= BIT(CONFIG_UPDATE_FEATRUES_UPDATE_RES_ONLY_EN);
|
|
config_update_features &= ~BIT(CONFIG_UPDATE_FEATRUES_PUSH_LOADER_ONLY_EN);
|
|
} else if (0 == (~BIT(CONFIG_UPDATE_FEATRUES_CONTENT_COMPARE_EN) & config_update_features)) {
|
|
config_update_features |= BIT(CONFIG_UPDATE_FEATRUES_PUSH_LOADER_ONLY_EN);
|
|
config_update_features &= ~BIT(CONFIG_UPDATE_FEATRUES_UPDATE_RES_ONLY_EN);
|
|
reserved_area_special_handle(1);
|
|
new_sdk_update_again_flag = 3;
|
|
}
|
|
|
|
reusable_update_flag_handle(&config_update_features, 1, 1);
|
|
return 0;
|
|
}
|
|
|
|
bool reusable_update_result_deal(bool result)
|
|
{
|
|
if (result) {
|
|
if (reusable_update_flag_handle(&config_update_features, 1, 0) &&
|
|
config_update_features & BIT(CONFIG_UPDATE_FEATRUES_UPDATE_RES_ONLY_EN)) {
|
|
u8 state = 0;
|
|
reusable_update_flag_handle((u32 *)&state, 0, 1);
|
|
}
|
|
config_update_features = 0;
|
|
reusable_update_flag_handle(&config_update_features, 1, 1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int reusable_loader_region(loader_area_t *loader_area)
|
|
{
|
|
int ret;
|
|
int update_type = 0;
|
|
|
|
if (loader_area == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
update_type = loader_area->type;
|
|
|
|
if (__this->init_flag == 0) {
|
|
ret = reusable_region_init();
|
|
if (ret) {
|
|
ret = -2;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
|
|
loader_area->type = 0;
|
|
loader_area->start_addr = __this->loader_addr;
|
|
loader_area->usable_size = __this->loader_size;
|
|
loader_area->write_hdl = (void *)reusable_region_write;
|
|
loader_area->read_hdl = (void *)reusable_region_read;
|
|
loader_area->erase_hdl = (void *)reusable_region_erase;
|
|
|
|
if (support_reusable_special_update) {
|
|
loader_area->result = reusable_update_specail_handle(update_type);
|
|
}
|
|
|
|
return 0;
|
|
|
|
end:
|
|
return ret;
|
|
}
|
|
|
|
int reusable_exif_region(u32 *base, u32 *len)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (__this->init_flag == 0) {
|
|
ret = reusable_region_init();
|
|
if (ret) {
|
|
ret = -1;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
if (base != NULL) {
|
|
*base = __this->exif_addr;
|
|
}
|
|
if (len != NULL) {
|
|
*len = __this->exif_size;
|
|
}
|
|
|
|
end:
|
|
return ret;
|
|
}
|
|
|
|
u8 new_sdk_update_again_flag_get(void)
|
|
{
|
|
return new_sdk_update_again_flag;
|
|
}
|
|
|
|
void reusable_update_flag_clear(void)
|
|
{
|
|
if (__this->loader_size && reusable_update_is_push_loader_only()) {
|
|
reusable_update_result_deal(true);
|
|
}
|
|
memset(__this, 0, sizeof(struct reusable_reserv));
|
|
new_sdk_update_again_flag = 0;
|
|
}
|
|
|
|
u8 reusable_update_app_flag_handle(u8 state, u8 opt)
|
|
{
|
|
u8 ret = 0;
|
|
if (opt) {
|
|
// 写入
|
|
if (2 == state || 0 == state) {
|
|
if (state) {
|
|
new_sdk_update_again_flag = 2;
|
|
}
|
|
reusable_update_flag_handle((u32 *)&state, 0, 1);
|
|
}
|
|
} else {
|
|
// 从vm中获取对标志位,结合升级标志位确定返回值
|
|
u32 update_flag = 0;
|
|
if (reusable_update_flag_handle(&update_flag, 1, 0) &&
|
|
((update_flag & BIT(CONFIG_UPDATE_FEATRUES_PUSH_LOADER_ONLY_EN)) || (update_flag & BIT(CONFIG_UPDATE_FEATRUES_UPDATE_RES_ONLY_EN)))) {
|
|
ret = 3;
|
|
} else if (reusable_update_flag_handle((u32 *)&state, 0, 0)) {
|
|
ret = state;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
u32 reusable_area_flash_space(u32 *start_addr, u32 *free_space)
|
|
{
|
|
u32 size = 0;
|
|
FILE *fp = NULL;
|
|
struct vfs_attr file_attr;
|
|
const char *fpth = SDFILE_EXT_RESERVED_ROOT_PATH;
|
|
|
|
u8 file_path_len = 0;
|
|
u8 *file_path = NULL;
|
|
|
|
if (!support_reusable_special_update) {
|
|
goto _ERR_RET;
|
|
}
|
|
file_path_len = sizeof(SDFILE_EXT_RESERVED_ROOT_PATH) + strlen((const char *)REUSABLE_RESERVED);
|
|
file_path = zalloc(file_path_len);
|
|
if (NULL == file_path) {
|
|
log_error("%s, alloc fail\n", __func__);
|
|
goto _ERR_RET;
|
|
}
|
|
|
|
// 如果SDFILE_APP_ROOT_PATH + REUSABLE_RESERVED不行,则还需要尝试打开扩展预留区域(mnt/sdfile/EXT_RESERVED)
|
|
memcpy(file_path, SDFILE_APP_ROOT_PATH, strlen(SDFILE_APP_ROOT_PATH));
|
|
memcpy(file_path + strlen(SDFILE_APP_ROOT_PATH), REUSABLE_RESERVED, strlen((const char *)REUSABLE_RESERVED));
|
|
|
|
u32 space = 0;
|
|
fget_free_space(watch_get_root_path(), &space);
|
|
fp = fopen((const char *)file_path, "r");
|
|
|
|
if (!fp) {
|
|
memset((void *)file_path, 0, file_path_len);
|
|
memcpy((void *)file_path, SDFILE_EXT_RESERVED_ROOT_PATH, strlen(SDFILE_EXT_RESERVED_ROOT_PATH));
|
|
memcpy((void *)(file_path + strlen(SDFILE_EXT_RESERVED_ROOT_PATH)), REUSABLE_RESERVED, strlen((const char *)REUSABLE_RESERVED));
|
|
fp = fopen((const char *)file_path, "r");
|
|
}
|
|
|
|
if (!fp) {
|
|
log_error("%s, open %s fail\n", __func__, fpth);
|
|
goto _ERR_RET;
|
|
}
|
|
|
|
fget_attrs(fp, &file_attr);
|
|
if (start_addr) {
|
|
*start_addr = sdfile_cpu_addr2flash_addr(file_attr.sclust);
|
|
}
|
|
if (free_space) {
|
|
*free_space = space > LOADER_RESERVE_SIZE ? (space - LOADER_RESERVE_SIZE) : 0;
|
|
}
|
|
size = file_attr.fsize / 1024;
|
|
_ERR_RET:
|
|
if (file_path) {
|
|
free(file_path);
|
|
}
|
|
if (fp) {
|
|
fclose(fp);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
#endif // TCFG_UPDATE_ENABLE
|
|
|