401 lines
14 KiB
C
401 lines
14 KiB
C
#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;
|
||
}
|
||
|
||
|