doubao_chat/apps/common/update/ex_flash_file_download.c

279 lines
7.0 KiB
C

#include "app_config.h"
#include "typedef.h"
#include "fs.h"
#include "norflash.h"
#include "spi/nor_fs.h"
#include "rec_nor/nor_interface.h"
#include "update_loader_download.h"
#define LOG_TAG "[UP_FILE_DNLD]"
#define LOG_INFO_ENABLE
#define LOG_ERROR_ENABLE
#include "system/debug.h"
#define EX_FLASH_FILE_NAME "res.bin"
#define ONCE_REQ_SIZE (0x200)
typedef struct _resource_update_info_t {
user_chip_update_info_t info;
void *dev_hdl;
update_op_api_t *file_ops;
u32 buf[ONCE_REQ_SIZE / 4];
} res_update_info_t;
static res_update_info_t *res_info = NULL;
#define __this (res_info)
static int norflash_f_open(u32 file_len)
{
int ret = 0;
if (__this) {
__this->dev_hdl = dev_open("res_nor", NULL);
if (__this->dev_hdl) {
log_info("open dev succ 0x%x", __this->dev_hdl);
} else {
log_error("open dev fail");
ret = -1;
}
} else {
ret = -2;
}
return ret;
}
static u16 norflash_f_read(void *buf, u32 addr, u32 len)
{
int rlen = 0;
if (__this && __this->dev_hdl) {
wdt_clear();
//printf("%s: addr = 0x%x, rlen = 0x%x", __func__, addr, len);
rlen = dev_bulk_read(__this->dev_hdl, buf, addr, len);
//put_buf(buff, 128);
}
return rlen;
}
typedef enum _FLASH_ERASER {
CHIP_ERASER,
BLOCK_ERASER,
SECTOR_ERASER,
PAGE_ERASER,
} FLASH_ERASER;
static u16 norflash_f_erase(u32 cmd, u32 addr)
{
u32 type = 0;
switch (cmd) {
case BLOCK_ERASER:
type = IOCTL_ERASE_BLOCK;
break;
case SECTOR_ERASER:
type = IOCTL_ERASE_SECTOR;
break;
}
if (__this && __this->dev_hdl && type) {
wdt_clear();
dev_ioctl(__this->dev_hdl, type, addr);
} else {
log_error("f_erase parm err\n");
}
return 0;
}
static u16 norflash_f_write(void *buf, u32 addr, u32 len)
{
int rlen = 0;
if (__this && __this->dev_hdl) {
wdt_clear();
//printf("%s: addr = 0x%x, rlen = 0x%x", __func__, addr, len);
rlen = dev_bulk_write(__this->dev_hdl, buf, addr, len);
//put_buf(buff, 128);
}
return rlen;
}
static int ex_flash_update_file_init(void *priv, update_op_api_t *file_ops)
{
int ret = 0;
user_chip_update_info_t *info = (user_chip_update_info_t *)priv;
if (priv && file_ops) {
__this = malloc(sizeof(res_update_info_t));
if (!__this) {
ret = -1;
goto _ERR_RET;
}
memset((u8 *)__this, 0x00, sizeof(res_update_info_t));
memcpy((u8 *)&__this->info, (u8 *)info, sizeof(user_chip_update_info_t));
__this->file_ops = file_ops;
log_info("ADDR:%x LEN:%x CRC:%x dev_addr:%x\n", __this->info.addr, __this->info.len, __this->info.crc, __this->info.dev_addr);
if (norflash_f_open(__this->info.len)) {
ret = -3;
}
} else {
log_error("not find target file :%s\n", EX_FLASH_FILE_NAME);
ret = -2;
goto _ERR_RET;
}
_ERR_RET:
return ret;
}
static int ex_flash_update_file_get_len(void)
{
if (__this) {
return __this->info.len;
} else {
return 0;
}
}
typedef struct _program_info_t {
u32 remote_file_begin;
u32 remote_file_length;
u32 local_program_addr;
u32(*remote_file_read)(void *buf, u32 addr, u32 len);
u32(*local_write_hdl)(void *buf, u32 addr, u32 len);
u32(*local_erase_hdl)(u32 cmd, u32 addr);
u8 *buf;
} program_info_t;
static u32 remote_file_read(void *buf, u32 addr, u32 len)
{
u32 ret = 0;
if (__this && __this->file_ops) {
putchar('%');
__this->file_ops->f_seek(NULL, SEEK_SET, addr);
if ((u16) - 1 == __this->file_ops->f_read(NULL, buf, len)) {
ret = (u32) - 1;
}
}
return ret;
}
#define FLASH_SECTOR_SIZE (4096L)
#define __SECTOR_4K_ALIGN(len) (((len) + FLASH_SECTOR_SIZE -1 )/FLASH_SECTOR_SIZE * FLASH_SECTOR_SIZE)
extern void flash_erase_by_blcok_n_sector(u32 start_addr, u32 len, int (*erase_hdl)(int cmd, u32 addr));
static int ex_flash_program_loop(program_info_t *info)
{
int ret = 0;
u32 remain_len;
u32 remote_addr;
u32 local_addr;
if (info->local_erase_hdl) {
remain_len = __SECTOR_4K_ALIGN(info->remote_file_length);
local_addr = __SECTOR_4K_ALIGN(info->local_program_addr);
flash_erase_by_blcok_n_sector(local_addr, remain_len, info->local_erase_hdl);
}
remain_len = info->remote_file_length;
remote_addr = info->remote_file_begin;
local_addr = info->local_program_addr;
u16 r_len = 0;
do {
r_len = (remain_len % ONCE_REQ_SIZE) ? (remain_len % ONCE_REQ_SIZE) : ONCE_REQ_SIZE;
remain_len -= r_len;
if (info->remote_file_read && info->buf) {
ret = info->remote_file_read(info->buf, remote_addr + remain_len, r_len);
if (ret != 0) {
log_error("read addr:%x len:%x err\n", remote_addr + remain_len, r_len);
ret = -1;
break;
}
}
if (info->local_write_hdl && info->buf) {
if (r_len != info->local_write_hdl(info->buf, local_addr + remain_len, r_len)) {
log_error("write addr:%x len:%x err\n", local_addr + remain_len, r_len);
ret = -2;
break;
}
}
} while (remain_len);
return ret;
}
extern u16 calc_crc16_with_init_val(u16 init_crc, u8 *ptr, u16 len);
static u16 ex_flash_local_file_verify(u8 *buf, u32 addr, u32 len, u32(*read_func)(u8 *buf, u32 addr, u32 len))
{
u16 crc_temp = 0;
u16 r_len;
log_info("verify-addr:%x len:%x\n", addr, len);
while (len) {
r_len = (len > ONCE_REQ_SIZE) ? ONCE_REQ_SIZE : len;
if (read_func) {
read_func(buf, addr, r_len);
}
crc_temp = calc_crc16_with_init_val(crc_temp, buf, r_len);
addr += r_len;
len -= r_len;
}
return crc_temp;
}
static int ex_flash_file_download_loop(void)
{
int ret = 0;
program_info_t info = {
.remote_file_begin = __this->info.addr,
.remote_file_length = __this->info.len,
.local_program_addr = __this->info.dev_addr,
.remote_file_read = remote_file_read,
.local_write_hdl = norflash_f_write,
.local_erase_hdl = norflash_f_erase,
.buf = __this->buf,
};
ret = ex_flash_program_loop(&info);
if (ret) {
ret = -1;
goto _ERR_RET;
}
if (__this->info.crc != \
ex_flash_local_file_verify(__this->buf, __this->info.dev_addr, __this->info.len, norflash_f_read)) {
log_error("update crc verify err\n");
ret = -2;
} else {
log_info("update crc verify succ\n");
}
_ERR_RET:
return ret;
}
const static user_chip_update_t ex_flash_update_ins = {
.file_name = EX_FLASH_FILE_NAME,
.update_init = ex_flash_update_file_init,
.update_get_len = ex_flash_update_file_get_len,
.update_loop = ex_flash_file_download_loop,
};
void ex_flash_file_download_init(void)
{
register_user_chip_update_handle(&ex_flash_update_ins);
}