doubao_chat/apps/common/update/net_update.c

401 lines
14 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "system/task.h"
#include "app_config.h"
#include "net_update.h"
#include "update/update_loader_download.h"
#include "dual_bank_updata_api.h"
#include "generic/errno-base.h"
#include "update.h"
#include "timer.h"
#include "fs/fs.h"
#include "os/os_api.h"
#include "device/device.h"
#include "asm/includes.h"
//=======================net_update==========================================================
#define NET_UPDATE_STATE_NONE 0
#define NET_UPDATE_STATE_OK 1
#define NET_UPDATE_STATE_ERR 2
#define NET_UPDATE_STATE_CLOSE 3
#define NET_UPDATE_BUF_CHECK 0x12345678 //防止写超buf检测
/* #define DUAL_BANK_VERIFY_ENABLE */ //回读flash进行校验
/* #define DATA_DOWNLOAD_VERIFY_ENABLE */ //对下载的数据进行校验
#define FLASH_SECTOR_SIZE (4*1024)
#define NET_UPDATE_BUFF_SIZE_MAX (4*1024) //缓存要>=4K,否则可能会引起在初始化时候升级失败
struct net_update {
u8 update_doing;
u8 update_state;
u8 write_to_flash;
u8 *recv_buf;
u32 recv_buf_size;
u32 offset;
u32 recv_cnt;
u32 req_seek;
OS_SEM sem;
FILE *fd;
};
#ifdef DATA_DOWNLOAD_VERIFY_ENABLE
typedef struct stJL_FILE_HEAD {
u16 u16Crc;
u16 u16DataCrc;
u32 u32Address;
u32 u32Length;
u8 u8Attribute;
u8 u8Res;
u16 u16Index;
char szFileName[16];
} JL_FILE_HEAD;
extern u16 calc_crc16_with_init_val(u16 init_crc, u8 *ptr, u16 len);
static int firstBlock = 1;
static u16 calcCrc = 0;
static JL_FILE_HEAD gUpdateHead;
#endif
static struct net_update *net_update_info = NULL;
int storage_device_ready(void);
u32 get_target_udate_addr(void);
//=======================net_update==========================================================
#ifdef DUAL_BANK_VERIFY_ENABLE
static int dual_bank_verify_hdl(int result)
{
if (result) {
printf("app core verify OK!");
//回读校验正确,更新启动信息
dual_bank_update_burn_boot_info(net_update_finish_callback);
} else if (net_update_info) {
//回读校验错误
net_update_info->update_state = NET_UPDATE_STATE_ERR;
os_sem_post(&net_update_info->sem);
printf("net_update err\n\n");
return -1;
}
return 0;
}
#endif
#ifdef DATA_DOWNLOAD_VERIFY_ENABLE
static int net_update_check(JL_FILE_HEAD *head, const u8 *buf, const u32 len)
{
int ret;
if ((32 > len) || (NULL == head)) {
return -1;
}
memcpy((u8 *)head, buf, sizeof(JL_FILE_HEAD));
ret = jl_file_head_valid_check(head);
if (ret) {
return -1;
}
if (0 == strcmp((head->szFileName), "update_data")) {
return 0;
}
printf("update file not match!\n");
return -1;
}
#endif
static void net_update_system_reset(void *priv)
{
if (get_power_keep_state() & POWER_KEEP_RTC) { //需要使用软关机唤醒的方式复位,否则系统复位会导致RTC时间掉
printf("cpu by rtc reset soft_poweroff....\n\n");
power_set_soft_poweroff(10);//first pwoer off 10ms will power on
} else {
printf("cpu system_reset ....\n\n");
system_reset();
}
}
static int net_update_doing_callback(void *result)
{
if (result) {
if (net_update_info) {
net_update_info->update_state = NET_UPDATE_STATE_ERR;
os_sem_post(&net_update_info->sem);
}
printf("net_update doing err\n\n");
}
return 0;
}
static int net_update_finish_callback(int result)
{
if (!result) {
if (net_update_info) {
net_update_info->update_state = NET_UPDATE_STATE_OK;
os_sem_post(&net_update_info->sem);
}
printf("net_update successfuly\n\n");
} else if (net_update_info) {
net_update_info->update_state = NET_UPDATE_STATE_ERR;
os_sem_post(&net_update_info->sem);
printf("net_update err\n\n");
return -1;
}
return 0;
}
int net_update_request(void)
{
if (net_update_info) {
return net_update_info->update_doing;
}
return 0;
}
void *net_fopen(char *path, char *mode)//net_fopen支持写flash固件升级和写到SD卡,当名字字符有CONFIG_UPGRADE_OTA_FILE_NAME时是固件升级
{
//防止超时时,在没退出时,客户端再次重入
int ret = net_update_request();
if (ret) {
printf("err ota update is doing !!!!!!!!!!!!!!\n");//保证FTP传输等网络升级请求需要确保传输队列只有一次OTA文件请求(否则后续无法升级)
return NULL;
}
struct net_update *net_update = zalloc(sizeof(struct net_update));
if (!net_update) {
printf("err in no mem \n\n");
goto err;
}
if (strstr(path, CONFIG_UPGRADE_OTA_FILE_NAME)) {//名字是OTA升级名字就进行写flash升级模式
net_update->recv_buf = malloc(NET_UPDATE_BUFF_SIZE_MAX + 4);
if (!net_update->recv_buf) {
goto err;
}
net_update->update_doing = true;
net_update->write_to_flash = true;
net_update->offset = 0;
net_update->req_seek = 0;
net_update->recv_cnt = 0;
net_update->update_state = NET_UPDATE_STATE_NONE;
net_update->recv_buf_size = NET_UPDATE_BUFF_SIZE_MAX;
os_sem_create(&net_update->sem, 0);
net_update_info = net_update;
u32 *check = (u32 *)(net_update->recv_buf + net_update->recv_buf_size);
*check = NET_UPDATE_BUF_CHECK;
return (void *)net_update;
} else if (storage_device_ready()) {
net_update->fd = fopen(path, mode);
if (!net_update->fd) {
goto err;
}
return (void *)net_update;
}
err:
if (net_update) {
if (net_update->recv_buf) {
free(net_update->recv_buf);
}
free(net_update);
}
net_update_info = NULL;
return NULL;
}
int net_fclose(void *fd, char is_socket_err)
{
struct net_update *net_update = (struct net_update *)fd;
int err = 0;
if (!net_update) {
net_update = net_update ? net_update : net_update_info;
printf("warnning net_fclose fd NULL \n");
}
if (net_update->write_to_flash) {
u32 *check = (u32 *)(net_update->recv_buf + net_update->recv_buf_size);
if (*check != NET_UPDATE_BUF_CHECK) {
printf("err check in %s, check = 0x%x \n\n\n", __func__, *check);
}
printf("net close %s \n", is_socket_err ? "is_socket_err" : "normal");
if (net_update->offset && net_update->update_state == NET_UPDATE_STATE_NONE && !is_socket_err) {
err = net_fwrite(net_update, NULL, net_update->offset, 1);//写剩余的缓存到flash
if (err != net_update->offset) {
err = -1;
printf("err net_fclose write = %d \n", err);
}
}
if (net_update->update_state == NET_UPDATE_STATE_NONE && !is_socket_err) {
#ifdef DATA_DOWNLOAD_VERIFY_ENABLE
if (calcCrc == gUpdateHead.u16DataCrc) {
dual_bank_update_burn_boot_info(net_update_finish_callback);
err = os_sem_pend(&net_update_info->sem, 500);
if (err) {
err = -1;
printf("net_update verify wait time out err\n\n\n\n");
}
} else {
printf("crc err, calcCrc = 0x%x, headCrc = 0x%x\n", calcCrc, gUpdateHead.u16DataCrc);
net_update->update_state == NET_UPDATE_STATE_ERR;
}
#else
#ifdef DUAL_BANK_VERIFY_ENABLE
dual_bank_update_verify(NULL, NULL, dual_bank_verify_hdl);
#else
//更新启动信息
dual_bank_update_burn_boot_info(net_update_finish_callback);
#endif //DUAL_BANK_VERIFY_ENABLE
err = os_sem_pend(&net_update_info->sem, 500);
if (err) {
err = -1;
printf("net_update verify wait time out err\n\n\n\n");
}
#endif //DATA_DOWNLOAD_VERIFY_ENABLE
}
net_update->update_doing = 0;
if (net_update->update_state == NET_UPDATE_STATE_OK) {//升级成功,2s后重启系统
sys_timeout_add_to_task("sys_timer", NULL, net_update_system_reset, 2000);
printf(">>>>>>>>>>>net_update successfuly , system will reset after 2s ...\n\n");
} else {
err = -1;
printf(">>>>>>>>>>>net_update err\n\n\n\n");
}
net_update->update_state = NET_UPDATE_STATE_CLOSE;
os_sem_del(&net_update->sem, 0);
dual_bank_passive_update_exit(NULL);
} else if (net_update->fd) {
fclose(net_update->fd);
}
if (net_update->recv_buf) {
free(net_update->recv_buf);
}
net_update_info = NULL;
free(net_update);
return err;
}
int net_flen(void *fd)
{
struct net_update *net_update = (struct net_update *)fd;
if (net_update && !net_update->write_to_flash && net_update->fd) {
return flen(net_update->fd);
}
return 0;
}
int net_fread(void *fd, char *buf, int len)
{
struct net_update *net_update = (struct net_update *)fd;
if (net_update && !net_update->write_to_flash && net_update->fd) {
return fread(buf, 1, len, net_update->fd);
}
return 0;
}
int net_fwrite(void *fd, unsigned char *buf, int len, int end)
{
struct net_update *net_update = (struct net_update *)fd;
int ret = len;
int err;
int wr_len = 0;
int wr_offset = 0;
int rd_len = 0;
int rd_offset = 0;
int buf_offset = 0;
int cp_remain = net_update->recv_buf_size;
u8 *cp_buf = (u8 *)net_update->recv_buf;
u32 *check = (u32 *)(net_update->recv_buf + net_update->recv_buf_size);
#ifdef DATA_DOWNLOAD_VERIFY_ENABLE
if (buf) {
if (firstBlock) {
err = net_update_check(&gUpdateHead, buf, len);
if (err) {
printf("net_update_check err!");
return -EINVAL;
}
calcCrc = calc_crc16_with_init_val(calcCrc, buf + 32, len - 32);
firstBlock = 0;
} else {
calcCrc = calc_crc16_with_init_val(calcCrc, buf, len);
}
}
#endif
if (net_update->write_to_flash) {
if (net_update->update_state == NET_UPDATE_STATE_OK) {
net_update->offset = 0;
return ret;
} else if (net_update->update_state == NET_UPDATE_STATE_ERR || net_update->update_state == NET_UPDATE_STATE_CLOSE) {
return -EINVAL;
}
while (len) {
if (net_update->offset < net_update->recv_buf_size && !end) {//写到缓存,直到缓存满才写flash
rd_len = MIN(net_update->recv_buf_size - net_update->offset, len);
memcpy(net_update->recv_buf + net_update->offset, buf + rd_offset, rd_len);
net_update->offset += rd_len;
rd_offset += rd_len;
len -= rd_len;
if (*check != NET_UPDATE_BUF_CHECK) {
printf("err check in %s, check = 0x%x \n\n\n", __func__, *check);
}
if (net_update->offset < net_update->recv_buf_size) {
return ret;
}
}
if (!end) {
net_update->offset = 0;
cp_remain = net_update->recv_buf_size - net_update->offset;
} else {
cp_remain = net_update->offset;
len -= cp_remain;
}
while (cp_remain) {
if (!net_update->recv_cnt) {//第一次写则初始化双备份升级
err = dual_bank_passive_update_init(0, 0, NET_UPDATE_BUFF_SIZE_MAX, NULL);
if (err || dual_bank_update_allow_check(0)) {
net_update->update_state = NET_UPDATE_STATE_ERR;
printf("net_fwrite init check err \n\n");
return err;
}
u32 target_addr = get_target_udate_addr();
u32 addr = ADDR_ALIGNE(target_addr, FLASH_SECTOR_SIZE);
u32 first_size = addr - target_addr;
if (first_size) {
//要先写前4K对齐剩下字节,否则出现数据包不完整
err = dual_bank_update_write(cp_buf, first_size, NULL);
if (err) {
net_update->update_state = NET_UPDATE_STATE_ERR;
return err;
}
memcpy(cp_buf, cp_buf + first_size, \
cp_remain > first_size ? (cp_remain - first_size) : cp_remain);
net_update->offset = (cp_remain > first_size ? (cp_remain - first_size) : cp_remain);
net_update->recv_cnt += first_size;
break;
}
}
if (net_update->update_state) {
printf("net_update update_state = %d \n\n", net_update->update_state);
net_update->offset = 0;
return net_update->update_state == NET_UPDATE_STATE_OK ? ret : -EINVAL;
}
if (*check != NET_UPDATE_BUF_CHECK) {
printf("err check in %s, check = 0x%x \n\n\n", __func__, *check);
}
//写数据到flash
err = dual_bank_update_write(cp_buf, cp_remain, net_update_doing_callback);
if (err) {
net_update->update_state = NET_UPDATE_STATE_ERR;
return err;
}
net_update->recv_cnt += cp_remain;
cp_remain -= cp_remain;
}
}
} else if (net_update->fd) {
fwrite(buf, 1, len, net_update->fd);
}
return ret;
}