716 lines
19 KiB
C
716 lines
19 KiB
C
#include <stdlib.h>
|
||
#include <unistd.h>
|
||
|
||
#include "FreeRTOS.h"
|
||
|
||
#include "board.h"
|
||
#include "chip.h"
|
||
#include "sfud.h"
|
||
#include "romfile.h"
|
||
#include "updatefile.h"
|
||
#include "animation.h"
|
||
#include "sysinfo.h"
|
||
#include "mmcsd_core.h"
|
||
#include "ff_stdio.h"
|
||
#include "source/crc32.h"
|
||
|
||
|
||
#if DEVICE_TYPE_SELECT != EMMC_FLASH
|
||
#include "ff_sfdisk.h"
|
||
#endif
|
||
|
||
#ifdef OTA_UPDATE_SUPPORT
|
||
#include "ota_update.h"
|
||
|
||
|
||
/* 获取已升级文件位置, toburn不为0时获取升级文件要烧录的位置 */
|
||
static unsigned int get_upfile_offset(int filetype, int toburn)
|
||
{
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
|
||
if (filetype == UPFILE_TYPE_WHOLE) {
|
||
if (!toburn) return sysinfo->image_offset;
|
||
if (sysinfo->image_offset == UPDATEFILE_MEDIA_OFFSET)
|
||
return UPDATEFILE_MEDIA_B_OFFSET;
|
||
else
|
||
return UPDATEFILE_MEDIA_OFFSET;
|
||
} else if (filetype == UPFILE_TYPE_FIRSTLDR) {
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
if (!toburn) return sysinfo->loader_offset;
|
||
if (sysinfo->loader_offset == LOADER_OFFSET)
|
||
return LOADERB_OFFSET;
|
||
else
|
||
return LOADER_OFFSET;
|
||
#else
|
||
return LOADER_OFFSET;
|
||
#endif
|
||
} else if (filetype == UPFILE_TYPE_STEPLDR) {
|
||
if (!toburn) return sysinfo->stepldr_offset;
|
||
if (sysinfo->stepldr_offset == STEPLDRA_OFFSET)
|
||
return STEPLDRB_OFFSET;
|
||
else
|
||
return STEPLDRA_OFFSET;
|
||
} else if (filetype == UPFILE_TYPE_LNCHEMMC) {
|
||
return 0;
|
||
} else {
|
||
uint8_t buf[512];
|
||
UpFileHeader *header;
|
||
UpFileInfo *appfile;
|
||
unsigned int image_offset;
|
||
int i;
|
||
|
||
if (toburn) {
|
||
if (sysinfo->image_offset == UPDATEFILE_MEDIA_OFFSET)
|
||
image_offset = UPDATEFILE_MEDIA_B_OFFSET;
|
||
else
|
||
image_offset = UPDATEFILE_MEDIA_OFFSET;
|
||
} else {
|
||
image_offset = sysinfo->image_offset;
|
||
}
|
||
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(image_offset, 512, buf);
|
||
#else
|
||
sfud_flash *sflash = sfud_get_device(0);
|
||
sfud_read(sflash, image_offset, 512, buf);
|
||
#endif
|
||
header = (UpFileHeader *)buf;
|
||
if (header->magic != MKTAG('U', 'P', 'D', 'F')) {
|
||
printf("update file isn't found, can't support module update.\n");
|
||
return 0xffffffff;
|
||
}
|
||
for (i = 0; i < header->filenum; i++) {
|
||
appfile = &header->files[i];
|
||
if ((appfile->magic == UPFILE_APP_MAGIC && filetype == UPFILE_TYPE_APP) ||
|
||
(appfile->magic == MKTAG('R', 'O', 'M', 'A') && filetype == UPFILE_TYPE_RESOURCE) ||
|
||
(appfile->magic == MKTAG('B', 'A', 'N', 'I') && filetype == UPFILE_TYPE_ANIMATION)) {
|
||
if (appfile->offset & (64 - 1)) {
|
||
printf("offset isn't align to sector erase size, can't support module update.\n");
|
||
return 0xffffffff;
|
||
}
|
||
return appfile->offset + image_offset;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0xffffffff;
|
||
}
|
||
|
||
static void set_upfile_offset(SysInfo *sysinfo, int filetype, uint32_t offset)
|
||
{
|
||
if (filetype == UPFILE_TYPE_WHOLE) {
|
||
sysinfo->image_offset = offset;
|
||
} else if (filetype == UPFILE_TYPE_FIRSTLDR) {
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
sysinfo->loader_offset = offset;
|
||
#endif
|
||
} else if (filetype == UPFILE_TYPE_STEPLDR) {
|
||
sysinfo->stepldr_offset = offset;
|
||
}
|
||
}
|
||
|
||
static unsigned int get_upfile_size(int filetype)
|
||
{
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
uint32_t offset;
|
||
uint8_t buf[512];
|
||
|
||
if (filetype <= UPFILE_TYPE_ANIMATION) {
|
||
offset = get_upfile_offset(filetype, 0);
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(offset, 512, buf);
|
||
#else
|
||
sfud_flash *sflash = sfud_get_device(0);
|
||
sfud_read(sflash, offset, 512, buf);
|
||
#endif
|
||
|
||
if (filetype == UPFILE_TYPE_WHOLE) {
|
||
UpFileHeader *header = (UpFileHeader *)buf;
|
||
return header->size;
|
||
} else if (filetype == UPFILE_TYPE_RESOURCE) {
|
||
RomHeader *header = (RomHeader *)buf;
|
||
return header->romsize;
|
||
} else if (filetype == UPFILE_TYPE_ANIMATION) {
|
||
BANIHEADER *header = (BANIHEADER *)buf;
|
||
return header->aniSize;
|
||
}
|
||
} else if (filetype >= UPFILE_TYPE_APP) {
|
||
return sysinfo->app_size;
|
||
} else if (filetype == UPFILE_TYPE_FIRSTLDR) {
|
||
return sysinfo->loader_size;
|
||
} else if (filetype == UPFILE_TYPE_STEPLDR) {
|
||
return sysinfo->stepldr_size;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* 获取已升级文件校验和
|
||
filesize 0:从已升级的文件中读取该文件大小
|
||
toburn 0:获取当运行文件的校验和 1:获取要烧录位置的旧升级文件的校验和
|
||
checkmode 0:不校验 1:进行校验,校验错误返回0 2:进行校验,校验出错也返回校验值 */
|
||
static uint32_t get_upfile_checksum(int filetype, size_t filesize, int checkmode, int toburn)
|
||
{
|
||
uint32_t checksum, calc_checksum = 0xffffffff;
|
||
uint8_t *buf;
|
||
sfud_flash *sflash = sfud_get_device(0);
|
||
uint32_t fileoffset;
|
||
int off, size, leftsize;
|
||
|
||
buf = pvPortMalloc(IMAGE_RW_SIZE);
|
||
if (!buf) {
|
||
printf("%s %d malloc %d bytes fail.\n", __FUNCTION__, __LINE__, IMAGE_RW_SIZE);
|
||
return 0;
|
||
}
|
||
|
||
if (!filesize) {
|
||
filesize = get_upfile_size(filetype);
|
||
if (!filesize) {
|
||
if (!checkmode) {
|
||
filesize = IMAGE_RW_SIZE;
|
||
} else {
|
||
printf("Error, filesize is zero when needing chekced.\n");
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
fileoffset = get_upfile_offset(filetype, toburn);
|
||
size = filesize > IMAGE_RW_SIZE ? IMAGE_RW_SIZE : filesize;
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
if (filetype == UPFILE_TYPE_LNCHEMMC) {
|
||
if (!sflash->init_ok)
|
||
sfud_init();
|
||
sfud_read(sflash, fileoffset, size, buf);
|
||
} else emmc_read(fileoffset, size, buf);
|
||
#else
|
||
sfud_read(sflash, fileoffset, size, buf);
|
||
#endif
|
||
|
||
if (filetype == UPFILE_TYPE_WHOLE) {
|
||
UpFileHeader *header = (UpFileHeader *)buf;
|
||
checksum = header->checksum;
|
||
header->checksum = 0;
|
||
if (checkmode)
|
||
calc_checksum = xcrc32(buf, size, calc_checksum);
|
||
} else if (filetype == UPFILE_TYPE_RESOURCE) {
|
||
RomHeader *header = (RomHeader *)buf;
|
||
checksum = header->checksum;
|
||
header->checksum = 0;
|
||
if (checkmode)
|
||
calc_checksum = xcrc32(buf, size, calc_checksum);
|
||
} else if (filetype == UPFILE_TYPE_ANIMATION) {
|
||
BANIHEADER *header = (BANIHEADER *)buf;
|
||
checksum = header->checksum;
|
||
header->checksum = 0;
|
||
if (checkmode)
|
||
calc_checksum = xcrc32(buf, size, calc_checksum);
|
||
} else if (filetype >= UPFILE_TYPE_APP) {
|
||
checksum = *(uint32_t*)(buf + APPLDR_CHECKSUM_OFFSET);
|
||
*(uint32_t*)(buf + APPLDR_CHECKSUM_OFFSET) = 0;
|
||
if (checkmode)
|
||
calc_checksum = xcrc32(buf, size, calc_checksum);
|
||
}
|
||
|
||
if (!checkmode) {
|
||
vPortFree(buf);
|
||
return checksum;
|
||
}
|
||
|
||
off = fileoffset + IMAGE_RW_SIZE;
|
||
leftsize = filesize - size;
|
||
while (leftsize > 0) {
|
||
size = leftsize > IMAGE_RW_SIZE ? IMAGE_RW_SIZE : leftsize;
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
if (filetype == UPFILE_TYPE_LNCHEMMC)
|
||
sfud_read(sflash, off, size, buf);
|
||
else
|
||
emmc_read(off, size, buf);
|
||
#else
|
||
sfud_read(sflash, off, size, buf);
|
||
#endif
|
||
calc_checksum = xcrc32(buf, size, calc_checksum);
|
||
off += size;
|
||
leftsize -= size;
|
||
}
|
||
vPortFree(buf);
|
||
if (calc_checksum == checksum || checkmode > 1)
|
||
return calc_checksum;
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
/* 获取升级文件的校验和,bchecked不为0时表示需要校验,校验错误返回0 */
|
||
static uint32_t get_mediafile_checksum(const char *ufile, int filetype, int bchecked)
|
||
{
|
||
uint32_t checksum, calc_checksum = 0xffffffff;
|
||
FF_FILE *fp;
|
||
uint8_t *buf;
|
||
int rlen;
|
||
|
||
fp = ff_fopen(ufile, "rb");
|
||
if (!fp) {
|
||
printf("open %s fail.\n", ufile);
|
||
return 0;
|
||
}
|
||
|
||
buf = pvPortMalloc(IMAGE_RW_SIZE);
|
||
if (!buf) {
|
||
printf("%s %d malloc %d bytes fail.\n", __FUNCTION__, __LINE__, IMAGE_RW_SIZE);
|
||
ff_fclose(fp);
|
||
return 0;
|
||
}
|
||
|
||
rlen = ff_fread(buf, 1, IMAGE_RW_SIZE, fp);
|
||
if (rlen <= 0) {
|
||
printf("read %s data fail.\n", ufile);
|
||
ff_fclose(fp);
|
||
vPortFree(buf);
|
||
return 0;
|
||
}
|
||
|
||
if (filetype == UPFILE_TYPE_WHOLE) {
|
||
UpFileHeader *header = (UpFileHeader *)buf;
|
||
checksum = header->checksum;
|
||
header->checksum = 0;
|
||
if (bchecked)
|
||
calc_checksum = xcrc32(buf, rlen, calc_checksum);
|
||
} else if (filetype == UPFILE_TYPE_RESOURCE) {
|
||
RomHeader *header = (RomHeader *)buf;
|
||
checksum = header->checksum;
|
||
header->checksum = 0;
|
||
if (bchecked)
|
||
calc_checksum = xcrc32(buf, rlen, calc_checksum);
|
||
} else if (filetype == UPFILE_TYPE_ANIMATION) {
|
||
BANIHEADER *header = (BANIHEADER *)buf;
|
||
checksum = header->checksum;
|
||
header->checksum = 0;
|
||
if (bchecked)
|
||
calc_checksum = xcrc32(buf, rlen, calc_checksum);
|
||
} else if (filetype >= UPFILE_TYPE_APP) {
|
||
checksum = *(uint32_t*)(buf + APPLDR_CHECKSUM_OFFSET);
|
||
*(uint32_t*)(buf + APPLDR_CHECKSUM_OFFSET) = 0;
|
||
if (bchecked)
|
||
calc_checksum = xcrc32(buf, rlen, calc_checksum);
|
||
}
|
||
|
||
if (!bchecked) {
|
||
ff_fclose(fp);
|
||
vPortFree(buf);
|
||
return checksum;
|
||
}
|
||
|
||
while ((rlen = ff_fread(buf, 1, IMAGE_RW_SIZE, fp)) > 0)
|
||
calc_checksum = xcrc32(buf, rlen, calc_checksum);
|
||
|
||
ff_fclose(fp);
|
||
vPortFree(buf);
|
||
|
||
if (calc_checksum == checksum)
|
||
return checksum;
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
static int backup_whole_image(void)
|
||
{
|
||
uint8_t *buf;
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
uint32_t imagechecksum, imagesize, imageoff, roff, woff;
|
||
UpFileHeader *header = NULL;
|
||
int leftsize, rwsize;
|
||
int retimes = 3;
|
||
#if DEVICE_TYPE_SELECT != EMMC_FLASH
|
||
sfud_flash *sflash = sfud_get_device(0);
|
||
#endif
|
||
|
||
buf = pvPortMalloc(IMAGE_RW_SIZE);
|
||
if (!buf) {
|
||
printf("%s %d malloc %d bytes fail.\n", __FUNCTION__, __LINE__, IMAGE_RW_SIZE);
|
||
return -1;
|
||
}
|
||
|
||
if (sysinfo->image_offset == UPDATEFILE_MEDIA_OFFSET)
|
||
imageoff = UPDATEFILE_MEDIA_B_OFFSET;
|
||
else
|
||
imageoff = UPDATEFILE_MEDIA_OFFSET;
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(imageoff, IMAGE_RW_SIZE, buf);
|
||
#else
|
||
sfud_read(sflash, imageoff, IMAGE_RW_SIZE, buf);
|
||
#endif
|
||
header = (UpFileHeader*)buf;
|
||
if (header->checksum == sysinfo->app_checksum) {
|
||
if (get_upfile_checksum(UPFILE_TYPE_WHOLE, header->size, 1, 1) == sysinfo->app_checksum) {
|
||
printf("the whole images are same, no need to backup.\n");
|
||
vPortFree(buf);
|
||
return 0;
|
||
}
|
||
} else if (sysinfo->app_checksum == 0) {
|
||
uint32_t checksum = get_upfile_checksum(UPFILE_TYPE_WHOLE, header->size, 2, 1);
|
||
if (checksum && checksum == get_upfile_checksum(UPFILE_TYPE_WHOLE, header->size, 2, 0)) {
|
||
printf("the whole images are same, no need to backup.\n");
|
||
vPortFree(buf);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
printf("start backup the whole image...\n");
|
||
rewrite:
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(sysinfo->image_offset, IMAGE_RW_SIZE, buf);
|
||
emmc_write(imageoff, IMAGE_RW_SIZE, buf);
|
||
#else
|
||
sfud_read(sflash, sysinfo->image_offset, IMAGE_RW_SIZE, buf);
|
||
sfud_erase_write(sflash, imageoff, IMAGE_RW_SIZE, buf);
|
||
#endif
|
||
imagesize = header->size;
|
||
leftsize = imagesize - IMAGE_RW_SIZE;
|
||
woff = imageoff + IMAGE_RW_SIZE;
|
||
roff = sysinfo->image_offset + IMAGE_RW_SIZE;
|
||
/* 如果串口单独升级过update.bin内某一种文件的话可能导致header->checksum并不是真实的校验和 */
|
||
header->checksum = 0;
|
||
imagechecksum = xcrc32(buf, IMAGE_RW_SIZE, 0xffffffff);
|
||
while (leftsize > 0) {
|
||
rwsize = leftsize > IMAGE_RW_SIZE ? IMAGE_RW_SIZE : leftsize;
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(roff, rwsize, buf);
|
||
emmc_write(woff, rwsize, buf);
|
||
#else
|
||
sfud_read(sflash, roff, rwsize, buf);
|
||
sfud_erase_write(sflash, woff, rwsize, buf);
|
||
#endif
|
||
leftsize -= rwsize;
|
||
roff += rwsize;
|
||
woff += rwsize;
|
||
imagechecksum = xcrc32(buf, rwsize, imagechecksum);
|
||
}
|
||
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(sysinfo->image_offset, IMAGE_RW_SIZE, buf);
|
||
header->checksum = imagechecksum;
|
||
emmc_write(imageoff, IMAGE_RW_SIZE, buf);
|
||
#else
|
||
sfud_read(sflash, sysinfo->image_offset, IMAGE_RW_SIZE, buf);
|
||
header->checksum = imagechecksum;
|
||
sfud_erase_write(sflash, imageoff, IMAGE_RW_SIZE, buf);
|
||
#endif
|
||
|
||
printf("checksum after backup...\n");
|
||
if (get_upfile_checksum(UPFILE_TYPE_WHOLE, imagesize, 1, 1) == imagechecksum) {
|
||
printf("backup the whole image ok.\n");
|
||
vPortFree(buf);
|
||
return 0;
|
||
} else if (retimes-- > 0) {
|
||
printf("checksum fail, retry...\n");
|
||
goto rewrite;
|
||
} else {
|
||
printf("backup the whole image fail.\n");
|
||
}
|
||
|
||
vPortFree(buf);
|
||
return -1;
|
||
}
|
||
|
||
/* 获取app, resource, rom升级文件单独升级时能支持的最大文件大小 */
|
||
static unsigned int get_subfile_maxsize(int filetype)
|
||
{
|
||
uint8_t buf[512];
|
||
UpFileHeader *header;
|
||
UpFileInfo *appfile;
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
int i;
|
||
|
||
if (filetype < UPFILE_TYPE_RESOURCE || filetype > UPFILE_TYPE_APP)
|
||
return 0;
|
||
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
emmc_read(sysinfo->image_offset, 512, buf);
|
||
#else
|
||
sfud_flash *sflash = sfud_get_device(0);
|
||
sfud_read(sflash, sysinfo->image_offset, 512, buf);
|
||
#endif
|
||
header = (UpFileHeader *)buf;
|
||
if (header->magic != MKTAG('U', 'P', 'D', 'F'))
|
||
return 0;
|
||
for (i = 0; i < header->filenum; i++) {
|
||
appfile = &header->files[i];
|
||
if ((appfile->magic == UPFILE_APP_MAGIC && filetype == UPFILE_TYPE_APP) ||
|
||
(appfile->magic == MKTAG('R', 'O', 'M', 'A') && filetype == UPFILE_TYPE_RESOURCE) ||
|
||
(appfile->magic == MKTAG('B', 'A', 'N', 'I') && filetype == UPFILE_TYPE_ANIMATION)) {
|
||
if (i < header->filenum - 1) {
|
||
UpFileInfo *nextfile = &header->files[i + 1];
|
||
return nextfile->offset - appfile->offset;
|
||
} else {
|
||
return UPDATEFILE_MAX_SIZE - appfile->offset;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int update_from_media(char *mpath, int filetype)
|
||
{
|
||
char update_file[32];
|
||
FF_FILE *fp;
|
||
size_t filesize;
|
||
uint8_t *buf;
|
||
size_t file_offset;
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
sfud_flash *sflash = sfud_get_device(0);
|
||
int leftsize, rwoffset, rwsize;
|
||
int rlen;
|
||
uint32_t checksum;
|
||
SysInfo bak_sysinfo;
|
||
|
||
memcpy(&bak_sysinfo, sysinfo, sizeof(SysInfo));
|
||
|
||
strcpy(update_file, mpath);
|
||
strcat(update_file, "/");
|
||
strcat(update_file, g_upfilename[filetype]);
|
||
|
||
printf("%s checksum...\n", update_file);
|
||
if (!(checksum = get_mediafile_checksum(update_file, filetype, 1))) {
|
||
printf("checksum fail, don't update.\n");
|
||
return 0;
|
||
}
|
||
|
||
if (checksum == get_upfile_checksum(filetype, 0, 0, 0)) {
|
||
if (!(filetype == UPFILE_TYPE_WHOLE && sysinfo->app_checksum == 0)) {
|
||
printf("checksum is the same as now, don't update.\n");
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
fp = ff_fopen(update_file, "rb");
|
||
if (!fp) {
|
||
printf("open %s fail.\n", update_file);
|
||
return -1;
|
||
}
|
||
filesize = ff_filelength(fp);
|
||
|
||
buf = pvPortMalloc(IMAGE_RW_SIZE);
|
||
if (!buf) {
|
||
printf("%s %d malloc %d bytes fail.\n", __FUNCTION__, __LINE__, IMAGE_RW_SIZE);
|
||
ff_fclose(fp);
|
||
return -1;
|
||
}
|
||
|
||
rlen = ff_fread(buf, 1, IMAGE_RW_SIZE, fp);
|
||
if (rlen <= 0) {
|
||
printf("read %s data fail.\n", update_file);
|
||
goto end;
|
||
}
|
||
|
||
if (filetype == UPFILE_TYPE_WHOLE) {
|
||
UpFileHeader *header = (UpFileHeader *)buf;
|
||
bak_sysinfo.app_checksum = header->checksum;
|
||
bak_sysinfo.app_size = header->files[0].size;
|
||
} else if (filetype == UPFILE_TYPE_APP) {
|
||
bak_sysinfo.app_size = filesize;
|
||
} else if (filetype == UPFILE_TYPE_FIRSTLDR) {
|
||
bak_sysinfo.loader_size = filesize;
|
||
} else if (filetype == UPFILE_TYPE_STEPLDR) {
|
||
bak_sysinfo.stepldr_size = filesize;
|
||
} else if (filetype == UPFILE_TYPE_LNCHEMMC) {
|
||
if (!sflash->init_ok)
|
||
sfud_init();
|
||
}
|
||
|
||
/* 这三种文件没有备份,需要先备份整个update.bin镜像再升级备份区域 */
|
||
if (filetype >= UPFILE_TYPE_RESOURCE && filetype <= UPFILE_TYPE_APP) {
|
||
if (filesize > get_subfile_maxsize(filetype)) {
|
||
printf("Not have enough space to update subfile %s.\n", update_file);
|
||
goto end;
|
||
}
|
||
if (backup_whole_image()) {
|
||
printf("backup_whole_image fail.\n");
|
||
goto end;
|
||
}
|
||
if (sysinfo->image_offset == UPDATEFILE_MEDIA_OFFSET)
|
||
bak_sysinfo.image_offset = UPDATEFILE_MEDIA_B_OFFSET;
|
||
else
|
||
bak_sysinfo.image_offset = UPDATEFILE_MEDIA_OFFSET;
|
||
}
|
||
|
||
file_offset = get_upfile_offset(filetype, 1);
|
||
if (file_offset == 0xffffffff) {
|
||
printf("get_upfile_offset fail.\n");
|
||
goto end;
|
||
}
|
||
|
||
leftsize = filesize;
|
||
rwoffset = file_offset;
|
||
while (leftsize > 0) {
|
||
rwsize = leftsize > rlen ? rlen : leftsize;
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
if (filetype == UPFILE_TYPE_LNCHEMMC) {
|
||
if (sfud_erase_write(sflash, rwoffset, rwsize, buf) != SFUD_SUCCESS)
|
||
{
|
||
printf("burn %s data fail.\n", update_file);
|
||
goto end;
|
||
}
|
||
} else {
|
||
if (emmc_write(rwoffset, rwsize, buf))
|
||
#else
|
||
if (sfud_erase_write(sflash, rwoffset, rwsize, buf) != SFUD_SUCCESS)
|
||
#endif
|
||
{
|
||
printf("burn %s data fail.\n", update_file);
|
||
goto end;
|
||
}
|
||
#if DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
}
|
||
#endif
|
||
rwoffset += rwsize;
|
||
leftsize -= rwsize;
|
||
printf("burn %d/%d.\n", filesize - leftsize, filesize);
|
||
|
||
rlen = ff_fread(buf, 1, IMAGE_RW_SIZE, fp);
|
||
if (rlen < 0) {
|
||
printf("read %s data fail.\n", update_file);
|
||
goto end;
|
||
}
|
||
}
|
||
|
||
printf("checksum after burn...\n");
|
||
if (checksum == get_upfile_checksum(filetype, filesize, 1, 1)) {
|
||
/* 升级这三个文件app_checksum后不准确,不能再用来判断版本 */
|
||
if (filetype >= UPFILE_TYPE_RESOURCE && filetype <= UPFILE_TYPE_APP)
|
||
bak_sysinfo.app_checksum = 0;
|
||
set_upfile_offset(&bak_sysinfo, filetype, file_offset);
|
||
memcpy(sysinfo, &bak_sysinfo, sizeof(SysInfo));
|
||
SaveSysInfo();
|
||
ff_fclose(fp);
|
||
vPortFree(buf);
|
||
printf("burn %s ok.\n", update_file);
|
||
return 0;
|
||
} else {
|
||
printf("checksum after burn fail.\n");
|
||
}
|
||
|
||
end:
|
||
ff_fclose(fp);
|
||
vPortFree(buf);
|
||
return -1;
|
||
}
|
||
|
||
int save_file_to_ota(int filetype)
|
||
{
|
||
char update_file[32];
|
||
char ota_file[32];
|
||
FF_FILE *fp, *fota;
|
||
size_t filesize;
|
||
int leftsize;
|
||
uint8_t *buf = NULL;
|
||
size_t readlen;
|
||
|
||
strcpy(update_file,"/usb/");
|
||
strcat(update_file, g_upfilename[filetype]);
|
||
strcpy(ota_file, OTA_MOUNT_PATH "/");
|
||
strcat(ota_file, g_upfilename[filetype]);
|
||
|
||
if (get_mediafile_checksum(update_file, filetype, 0) ==
|
||
get_mediafile_checksum(ota_file, filetype, 0)) {
|
||
if (get_mediafile_checksum(ota_file, filetype, 1)) {
|
||
printf("%s is same with ota, not save.\n", g_upfilename[filetype]);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
fp = ff_fopen(update_file, "rb");
|
||
if (!fp) {
|
||
printf("open %s fail.\n", update_file);
|
||
return -1;
|
||
}
|
||
filesize = ff_filelength(fp);
|
||
fota = ff_fopen(ota_file, "wb");
|
||
if (!fota) {
|
||
printf("create %s in ota partition fail.\n", ota_file);
|
||
ff_fclose(fp);
|
||
return -1;
|
||
}
|
||
buf = pvPortMalloc(IMAGE_RW_SIZE);
|
||
if (!buf) {
|
||
printf("malloc IMAGE_RW_SIZE fail.\n");
|
||
ff_fclose(fota);
|
||
ff_fclose(fp);
|
||
return -1;
|
||
}
|
||
leftsize = filesize;
|
||
while (leftsize > 0) {
|
||
if (readlen = ff_fread(buf, 1, IMAGE_RW_SIZE, fp)) {
|
||
if (ff_fwrite(buf, 1, readlen, fota) != readlen) {
|
||
printf("write ota data fail.\n");
|
||
break;
|
||
} else {
|
||
printf("write ota data %d/%d.\n", filesize - leftsize + readlen, filesize);
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
leftsize -= readlen;
|
||
}
|
||
ff_fclose(fota);
|
||
ff_fclose(fp);
|
||
vPortFree(buf);
|
||
if (leftsize == 0) {
|
||
printf("save file ok.\n");
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
#ifdef WIFI_UPDATE_SUPPORT
|
||
#define USB_DEV_PLUGED 0
|
||
#define USB_DEV_UNPLUGED 1
|
||
extern int usb_wait_stor_dev_pluged(uint32_t timeout);
|
||
extern void hub_usb_dev_reset(void);
|
||
|
||
/* 用从usb读取数据来模拟wifi接收升级数据,真实的wifi接收升级文件
|
||
需要和端app适配,需要客户自己实现 */
|
||
static void wifi_update_demo_thread(void *para)
|
||
{
|
||
#if DEVICE_TYPE_SELECT != EMMC_FLASH
|
||
FF_Disk_t *sfdisk = FF_SFDiskInit(SF_MOUNT_PATH);
|
||
if (sfdisk)
|
||
#endif
|
||
{
|
||
unsigned int status;
|
||
int filetype;
|
||
|
||
for (;;) {
|
||
status = usb_wait_stor_dev_pluged(portMAX_DELAY);
|
||
if (status == USB_DEV_PLUGED) {
|
||
printf("usb dev inserted.\n");
|
||
for (filetype = UPFILE_TYPE_WHOLE; filetype <= UPFILE_TYPE_LNCHEMMC; filetype++) {
|
||
if (save_file_to_ota(filetype)) {
|
||
printf("save_file_to_ota fail.\n");
|
||
} else {
|
||
printf("start to update from ota...\n");
|
||
update_from_media(OTA_MOUNT_PATH, filetype);
|
||
}
|
||
}
|
||
} else {
|
||
printf("usb removed.\n");
|
||
}
|
||
}
|
||
}
|
||
|
||
for (;;)
|
||
vTaskDelay(portMAX_DELAY);
|
||
}
|
||
|
||
void wifi_update_demo(void)
|
||
{
|
||
if (xTaskCreate(wifi_update_demo_thread, "wifiupdate", configMINIMAL_STACK_SIZE * 16, NULL,
|
||
1, NULL) != pdPASS) {
|
||
printf("create wifi update demo task fail.\n");
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
#endif
|