279 lines
7.0 KiB
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);
|
|
}
|
|
|