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
|