386 lines
12 KiB
C
386 lines
12 KiB
C
#include "app_config.h"
|
|
#include "typedef.h"
|
|
#include "fs.h"
|
|
#include "update_loader_download.h"
|
|
#include "update.h"
|
|
|
|
#if TCFG_COMPELTE_UFW_LC_EN
|
|
typedef struct _lcflash_update_info_parm {
|
|
u32 src_file_addr;
|
|
u32 src_file_len;
|
|
} lcflash_update_info_parm;
|
|
|
|
static lcflash_update_info_parm lc_flash_update_info;
|
|
static void *update_fp = NULL;
|
|
|
|
/* #define SDFILE_EXT_RES_ROOT_PATH SDFILE_MOUNT_PATH"/EXT_RESERVED/" //拓展预留区域分区路径 */
|
|
#define SDFILE_EXT_RES_ROOT_PATH SDFILE_MOUNT_PATH"/app/" //普通预留区域分区路径
|
|
|
|
//=============================================================//
|
|
// 内置LOCAL Flash升级V2版本 //
|
|
/* APP LOCAL Flash 升级模型(APP_LC_FLASH_UFW_UPDATA)
|
|
________ ________ ________
|
|
| | | | | |
|
|
| | (1) | | (2) | |
|
|
| APP | ---------> |LC_Flash| --------> | CHIP |
|
|
| | lc_flash_update.ufw | | lc_flash_update.ufw | |
|
|
|________| |________| |________|
|
|
|
|
NOTE:
|
|
关于流程(1): 该流程为从远端获取升级文件(lc_flash_update.ufw)写到内置flash预留区域中, lc_flash_update.ufw文件在内置flash中需要保证在预留足够空间且物理空间连续, 注意该流程为用户在自己定义的ota中完成, 不在本文件流程中, 需要用户自己开发;
|
|
关于流程(2): 该流程为本文件实现的升级流程, 在用户完成流程(1)后(lc_flash_update.ufw已存在内置flash中), 可随时调用lc_flash_update_ufw_init函数启动升级;
|
|
|
|
*/
|
|
//============================================================//
|
|
|
|
#define LC_FLASH_UFW_UPDATE_VERIFY_ALL_FILE 1 //1: 进升级前校验用户写到内置flash的lc_flash_update.ufw文件; 0: 不校验
|
|
|
|
extern const int support_lc_flash_ufw_update_en;
|
|
extern const int support_norflash_update_loader_only;
|
|
|
|
extern void wdt_clear(void);
|
|
|
|
//=========================================================//
|
|
// lc_flash 操作接口
|
|
//=========================================================//
|
|
|
|
static u32 user_remote_base_addr = 0; //
|
|
static u32 user_remote_cur_offset = 0;
|
|
static void *dev_ptr = NULL;
|
|
static char *path = NULL;
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 获取升级文件在内置flash中存放位置和长度
|
|
@param buf, 结构为lc_flash_update_info
|
|
@return void
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void get_lc_flash_update_info_param(void *buf)
|
|
{
|
|
if (buf) {
|
|
printf("src_file_addr = 0x%x", lc_flash_update_info.src_file_addr); //存放升级文件物理地址
|
|
printf("src_file_len = 0x%x", lc_flash_update_info.src_file_len); //存放升级文件物理地址
|
|
memcpy(buf, (u8 *)&lc_flash_update_info, sizeof(lc_flash_update_info));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static u32 user_remote_device_get_cur_addr(void)
|
|
{
|
|
return (user_remote_base_addr + user_remote_cur_offset);
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 打开升级文件所在flash的预留区域
|
|
@param void
|
|
@return 0: 打开错误;
|
|
非0: 打开成功
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
extern u32 sdfile_cpu_addr2flash_addr(u32 offset);
|
|
static u16 lc_flash_ufw_update_f_open(void)
|
|
{
|
|
if (dev_ptr) {
|
|
fseek((FILE *)dev_ptr, 0, SEEK_SET);
|
|
return 1;
|
|
}
|
|
dev_ptr = (void *)fopen(path, "r");
|
|
if (dev_ptr) {
|
|
struct vfs_attr attr;
|
|
fget_attrs((FILE *)dev_ptr, &attr);
|
|
user_remote_base_addr = sdfile_cpu_addr2flash_addr(attr.sclust);
|
|
lc_flash_update_info.src_file_addr = user_remote_base_addr;
|
|
printf("open %s file succ 0x%x, 0x%x", path, (u32)dev_ptr, user_remote_base_addr);
|
|
return 1;
|
|
} else {
|
|
printf("open %s file fail", path);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 读取预留区域升级文件内容
|
|
@param fp: NULL, 保留
|
|
@param buff: 读取数据buf
|
|
@param len: 读取数据长度
|
|
@return len: 读取成功
|
|
(-1): 读取出错
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static u16 lc_flash_ufw_update_f_read(void *fp, u8 *buff, u16 len)
|
|
{
|
|
//TODO:
|
|
int rlen = 0;
|
|
if (dev_ptr) {
|
|
wdt_clear();
|
|
rlen = fread(buff, len, 1, (FILE *)dev_ptr);
|
|
}
|
|
return (u16)rlen;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 偏移升级文件地址
|
|
@param fp: NULL, 保留
|
|
@param type: SEEK_SET, SEEK_CUR, SEEK_END
|
|
@param offset: 偏移长度
|
|
@return 0: 操作成功
|
|
非0: 操作出错
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static int lc_flash_ufw_update_f_seek(void *fp, u8 type, u32 offset)
|
|
{
|
|
//TODO:
|
|
int ret = 0;
|
|
if (dev_ptr) {
|
|
ret = fseek((FILE *)dev_ptr, (int)offset, (int)type);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 关闭预留区域读操作
|
|
@param err: 传入升级状态
|
|
@return 0: 操作成功
|
|
非0: 操作出错
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static u16 lc_flash_ufw_update_f_stop(u8 err)
|
|
{
|
|
//TODO:
|
|
printf("%s, err = 0x%x", __func__, err);
|
|
if (dev_ptr) {
|
|
fclose((FILE *)dev_ptr);
|
|
dev_ptr = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 通知升级文件大小
|
|
@param priv: NULL, 保留
|
|
@param size: 待升级文件大小
|
|
@return 0: 操作成功
|
|
非0: 操作出错
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static int lc_flash_ufw_update_notify_update_content_size(void *priv, u32 size)
|
|
{
|
|
//TODO:
|
|
printf("%s: size: 0x%x", __func__, size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static const update_op_api_t lc_flash_ufw_update_op_api = {
|
|
.ch_init = NULL,
|
|
.f_open = lc_flash_ufw_update_f_open,
|
|
.f_read = lc_flash_ufw_update_f_read,
|
|
.f_seek = lc_flash_ufw_update_f_seek,
|
|
.f_stop = lc_flash_ufw_update_f_stop,
|
|
.notify_update_content_size = lc_flash_ufw_update_notify_update_content_size,
|
|
};
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief flash升级文件校验完成, 会调用该函数
|
|
@param priv: 回调传入参数
|
|
@param type: 升级模式
|
|
@param cmd: 1) UPDATE_LOADER_OK flash升级文件校验成功, cpu复位, 启动固件升级流程
|
|
2) UPDATE_LOADER_ERR flash升级文件校验失败
|
|
@return
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void lc_flash_ufw_update_end_callback(void *priv, int type, u8 cmd)
|
|
{
|
|
//TODO:
|
|
printf("%s: type: 0x%x, cmd = 0x%x", __func__, type, cmd);
|
|
|
|
if (type == USER_LC_FLASH_UFW_UPDATA) {
|
|
if (cmd == UPDATE_LOADER_OK) {
|
|
printf("soft reset to update >>>");
|
|
cpu_reset(); //复位让主控进入升级内置flash
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 填充升级结构体私有参数
|
|
@param p: 升级结构体指针(UPDATA_PARM)
|
|
@return void
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void lc_flash_ufw_update_private_param_fill(UPDATA_PARM *p)
|
|
{
|
|
get_lc_flash_update_info_param(p->parm_priv);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 固件升级校验流程完成, cpu reset跳转升级新的固件
|
|
@param type: 升级类型
|
|
@return void
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void lc_flash_ufw_update_before_jump_handle(int type)
|
|
{
|
|
printf("soft reset to update >>>");
|
|
cpu_reset(); //复位让主控进入升级内置flash
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 内置flash升级流程状态处理
|
|
@param type: 升级类型
|
|
@param state: 当前升级状态
|
|
@param priv: 跟状态相关的私有参数指针
|
|
@return void
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void lc_flash_ufw_update_state_cbk(int type, u32 state, void *priv)
|
|
{
|
|
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
|
|
if (ret_code) {
|
|
printf("state:%x err:%x\n", ret_code->stu, ret_code->err_code);
|
|
}
|
|
|
|
switch (state) {
|
|
case UPDATE_CH_EXIT:
|
|
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
|
|
//update_mode_api(BT_UPDATA);
|
|
update_mode_api_v2(USER_LC_FLASH_UFW_UPDATA,
|
|
lc_flash_ufw_update_private_param_fill,
|
|
lc_flash_ufw_update_before_jump_handle);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 通过地址读取升级文件内容
|
|
@param buf, 读取数据缓存
|
|
@param addr, 读取预留区域数据的地址
|
|
@param len, 读取预留区域数据的长度
|
|
@return u16 读取长度
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static s32 lc_flash_update_file_read(void *buf, u32 addr, u32 len)
|
|
{
|
|
int rlen = 0;
|
|
|
|
if (dev_ptr) {
|
|
wdt_clear();
|
|
fseek((FILE *)dev_ptr, (int)(addr - user_remote_base_addr), SEEK_SET);
|
|
rlen = fread(buf, len, 1, (FILE *)dev_ptr);
|
|
}
|
|
return (u32)rlen;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 启动内置flash升级接口, 该接口为用户在保证将lc_flash_update.ufw烧写到内置flash预留区域之后, 调用该接口进行程序升级
|
|
@param reserved_area_name: 升级文件所在的预留区域名字
|
|
@return void
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
//使用ufw文件格式
|
|
void lc_flash_update_ufw_init(char *reserved_area_name)
|
|
{
|
|
if (support_lc_flash_ufw_update_en == 0) {
|
|
goto _ERR_RET;
|
|
}
|
|
|
|
if (NULL == path) {
|
|
path = zalloc(sizeof(SDFILE_EXT_RES_ROOT_PATH) + strlen(reserved_area_name));
|
|
if (NULL == path) {
|
|
printf("err: alloc lc flash ufw path fail\n");
|
|
goto _ERR_RET;
|
|
}
|
|
strcat(path, SDFILE_EXT_RES_ROOT_PATH);
|
|
strcat(path, reserved_area_name);
|
|
}
|
|
|
|
#if LC_FLASH_UFW_UPDATE_VERIFY_ALL_FILE
|
|
if (lc_flash_ufw_update_f_open()) {
|
|
if (update_file_verify(user_remote_base_addr, lc_flash_update_file_read) != 0) {
|
|
//校验失败
|
|
goto _ERR_RET;
|
|
}
|
|
} else {
|
|
goto _ERR_RET;
|
|
}
|
|
#endif /* #if LC_FLASH_UFW_UPDATE_VERIFY_ALL_FILE */
|
|
|
|
update_mode_info_t lc_flash_ufw_update_info = {
|
|
.type = USER_LC_FLASH_UFW_UPDATA,
|
|
.state_cbk = lc_flash_ufw_update_state_cbk,
|
|
.p_op_api = &lc_flash_ufw_update_op_api,
|
|
.task_en = 1,
|
|
};
|
|
|
|
app_active_update_task_init(&lc_flash_ufw_update_info);
|
|
|
|
_ERR_RET:
|
|
if (path) {
|
|
free(path);
|
|
path = NULL;
|
|
}
|
|
}
|
|
|
|
void lc_flash_update_loader_only_init(char *reserved_area_name)
|
|
{
|
|
if (support_norflash_update_loader_only == 0) {
|
|
goto _ERR_RET;
|
|
}
|
|
printf("%s, %d, %s\n", __func__, __LINE__, reserved_area_name);
|
|
if (NULL == path) {
|
|
path = zalloc(sizeof(SDFILE_EXT_RES_ROOT_PATH) + strlen(reserved_area_name));
|
|
if (NULL == path) {
|
|
printf("err: alloc lc flash ufw path fail\n");
|
|
goto _ERR_RET;
|
|
}
|
|
strcat(path, SDFILE_EXT_RES_ROOT_PATH);
|
|
strcat(path, reserved_area_name);
|
|
}
|
|
|
|
update_mode_info_t lc_flash_ufw_update_info = {
|
|
.type = USER_LC_FLASH_UFW_UPDATA,
|
|
.state_cbk = lc_flash_ufw_update_state_cbk,
|
|
.p_op_api = &lc_flash_ufw_update_op_api,
|
|
.task_en = 1,
|
|
};
|
|
|
|
exflash_move_loader_task_init(&lc_flash_ufw_update_info);
|
|
|
|
_ERR_RET:
|
|
if (path) {
|
|
free(path);
|
|
path = NULL;
|
|
}
|
|
}
|
|
#else // TCFG_COMPELTE_UFW_LC_EN
|
|
|
|
void lc_flash_update_ufw_init(char *reserved_area_name)
|
|
{
|
|
|
|
}
|
|
|
|
void lc_flash_update_loader_only_init(char *reserved_area_name)
|
|
{
|
|
|
|
}
|
|
#endif // TCFG_COMPELTE_UFW_LC_EN
|
|
|