sdk-hwV1.3/lichee/brandy-2.0/u-boot-2018/sprite/sprite_auto_update.c

1048 lines
28 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
/* uboot/sprite/sprite_auto_update.c
*
* Copyright (c) 2016 Allwinnertech Co., Ltd.
* Author: zhouhuacai <zhouhuacai@allwinnertech.com>
*
* Update firmware with sdcard storage
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <common.h>
#include <malloc.h>
#include <sprite.h>
#include <sunxi_mbr.h>
#include <sunxi_nand.h>
#include <private_toc.h>
#include <private_boot0.h>
#include <sunxi_board.h>
#include <spare_head.h>
#include "sprite_card.h"
#include "sparse/sparse.h"
#include "sprite_verify.h"
#include "firmware/imgdecode.h"
#include <fs.h>
#include "sys_config.h"
#include "sprite_auto_update.h"
#include <usb.h>
#include "./cartoon/sprite_cartoon.h"
#include "fdt_support.h"
DECLARE_GLOBAL_DATA_PTR;
#define SCRIPT_FILE_COMMENT '#' // symbol for comment
#define SCRIPT_FILE_END '%' // symbol for file end
#define MAX_LINE_SIZE 8000
#define MAX_FILE_SIZE (0x800000)
#define IS_COMMENT(x) (SCRIPT_FILE_COMMENT == (x))
#define IS_FILE_END(x) (SCRIPT_FILE_END == (x))
#define IS_LINE_END(x) ('\r' == (x) || '\n' == (x))
#define AU_HEAD_BUFF (32 * 1024)
#if defined(CONFIG_SUNXI_SPINOR)
#define AU_ONCE_DATA_DEAL (2 * 1024 * 1024)
#else
#define AU_ONCE_DATA_DEAL (3 * 1024 * 1024)
#endif
#define AU_ONCE_SECTOR_DEAL (AU_ONCE_DATA_DEAL / 512)
#define IMG_NAME "update/FIRMWARE.bin"
typedef struct _uboot_command {
char argv[8][64];
} uboot_command;
static char *firmware_path = IMG_NAME;
static void *imghd;
static void *imgitemhd;
static char *imgname;
char interface[8] = "usb";
extern int do_card0_probe(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[]);
extern void __dump_mbr(sunxi_mbr_t *mbr_info);
extern void __dump_dlmap(sunxi_download_info *dl_info);
extern int sunxi_sprite_verify_dlmap(void *buffer);
extern int unsparse_probe(char *source, uint length,
uint android_format_flash_start);
extern void dump_dram_para(void *dram, uint size);
extern int sunxi_set_secure_mode(void);
extern int sunxi_sprite_download_boot0(void *buffer, int production_media);
extern int sunxi_sprite_download_uboot(void *buffer, int production_media,
int generate_checksum);
static int auto_update_firmware_probe(char *name);
int __attribute__((weak)) nand_get_mbr(char *buffer, uint len)
{
return -1;
}
static int auto_update_firmware_probe(char *name)
{
imghd = Img_Fat_Open(name);
if (!imghd) {
return -1;
}
return 0;
}
loff_t fat_fs_read(const char *filename, void *buf, int offset, int len)
{
loff_t len_read;
if (!buf || !filename)
return -1;
if (fs_set_blk_dev(interface, "0", FS_TYPE_FAT))
return -1;
if (fs_read(filename, (ulong)buf, offset, len, &len_read))
return -1;
return len_read;
}
static int auto_update_fetch_download_map(sunxi_download_info *dl_map)
{
imgitemhd = Img_OpenItem(imghd, "12345678", "1234567890DLINFO");
if (!imgitemhd) {
return -1;
}
if (!Img_Fat_ReadItem(imghd, imgitemhd, imgname, (void *)dl_map,
sizeof(sunxi_download_info))) {
printf("sunxi sprite error : read dl map failed\n");
return -1;
}
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
return sunxi_sprite_verify_dlmap(dl_map);
}
static int auto_update_fetch_mbr(void *img_mbr)
{
int mbr_num = SUNXI_MBR_COPY_NUM;
if (get_boot_storage_type() == STORAGE_NOR) {
mbr_num = 1;
}
imgitemhd = Img_OpenItem(imghd, "12345678", "1234567890___MBR");
if (!imgitemhd) {
return -1;
}
if (!Img_Fat_ReadItem(imghd, imgitemhd, imgname, img_mbr,
sizeof(sunxi_mbr_t) * mbr_num)) {
printf("sunxi sprite error : read mbr failed\n");
return -1;
}
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
return sunxi_sprite_verify_mbr(img_mbr);
}
static int __download_normal_part(dl_one_part_info *part_info,
uchar *source_buff)
{
int ret = -1;
uint partstart_by_sector;
uint tmp_partstart_by_sector;
s64 partsize_by_byte;
s64 partdata_by_byte;
s64 tmp_partdata_by_bytes;
uint onetime_read_sectors;
uint first_write_bytes;
uint imgfile_start;
uint tmp_imgfile_start;
int partdata_format;
uint active_verify;
uint origin_verify;
uchar verify_data[1024];
uint *tmp;
u8 *down_buffer = source_buff + AU_HEAD_BUFF;
tmp_partstart_by_sector = partstart_by_sector = part_info->addrlo;
partsize_by_byte = part_info->lenlo;
partsize_by_byte <<= 9;
imgitemhd =
Img_OpenItem(imghd, "RFSFAT16", (char *)part_info->dl_filename);
if (!imgitemhd) {
printf("sunxi sprite error: open part %s failed\n",
part_info->dl_filename);
return -1;
}
partdata_by_byte = Img_GetItemSize(imghd, imgitemhd);
if (partdata_by_byte <= 0) {
printf("sunxi sprite error: fetch part len %s failed\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
printf("partdata hi 0x%x\n", (uint)(partdata_by_byte >> 32));
printf("partdata lo 0x%x\n", (uint)partdata_by_byte);
if (partdata_by_byte > partsize_by_byte) {
printf("sunxi sprite: data size 0x%x is larger than part %s size 0x%x\n",
(uint)(partdata_by_byte / 512), part_info->dl_filename,
(uint)(partsize_by_byte / 512));
goto __download_normal_part_err1;
}
tmp_partdata_by_bytes = partdata_by_byte;
if (tmp_partdata_by_bytes >= AU_ONCE_DATA_DEAL) {
onetime_read_sectors = AU_ONCE_SECTOR_DEAL;
first_write_bytes = AU_ONCE_DATA_DEAL;
} else {
onetime_read_sectors = (tmp_partdata_by_bytes + 511) >> 9;
first_write_bytes = (uint)tmp_partdata_by_bytes;
}
imgfile_start = Img_GetItemOffset(imghd, imgitemhd);
if (!imgfile_start) {
printf("sunxi sprite err : cant get part data imgfile_start %s\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
tmp_imgfile_start = imgfile_start;
if (fat_fs_read(imgname, down_buffer, imgfile_start,
onetime_read_sectors * 512) !=
onetime_read_sectors * 512) {
printf("sunxi sprite error : read sdcard start %d, total %d failed\n",
tmp_imgfile_start, onetime_read_sectors);
goto __download_normal_part_err1;
}
/* position of next data to be read*/
tmp_imgfile_start += onetime_read_sectors * 512;
/* check sparse format or not */
partdata_format = unsparse_probe((char *)down_buffer, first_write_bytes,
partstart_by_sector);
if (partdata_format != ANDROID_FORMAT_DETECT) {
if (sunxi_sprite_write(tmp_partstart_by_sector,
onetime_read_sectors,
down_buffer) != onetime_read_sectors) {
printf("sunxi sprite error: download rawdata error %s\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
tmp_partdata_by_bytes -= first_write_bytes;
tmp_partstart_by_sector += onetime_read_sectors;
while (tmp_partdata_by_bytes >= AU_ONCE_DATA_DEAL) {
/* continue read partition data from img*/
if (fat_fs_read(imgname, down_buffer, tmp_imgfile_start,
AU_ONCE_DATA_DEAL) !=
AU_ONCE_DATA_DEAL) {
printf("sunxi sprite error : read sdcard start %d, total %d failed\n",
tmp_imgfile_start, AU_ONCE_DATA_DEAL);
goto __download_normal_part_err1;
}
if (sunxi_sprite_write(tmp_partstart_by_sector,
AU_ONCE_SECTOR_DEAL,
down_buffer) !=
AU_ONCE_SECTOR_DEAL) {
printf("sunxi sprite error: download rawdata error %s, start 0x%x, sectors 0x%x\n",
part_info->dl_filename,
tmp_partstart_by_sector,
AU_ONCE_SECTOR_DEAL);
goto __download_normal_part_err1;
}
tmp_imgfile_start += AU_ONCE_SECTOR_DEAL * 512;
tmp_partdata_by_bytes -= AU_ONCE_DATA_DEAL;
tmp_partstart_by_sector += AU_ONCE_SECTOR_DEAL;
}
if (tmp_partdata_by_bytes > 0) {
uint rest_sectors = (tmp_partdata_by_bytes + 511) >> 9;
if (fat_fs_read(imgname, down_buffer, tmp_imgfile_start,
rest_sectors * 512) !=
rest_sectors * 512) {
printf("sunxi sprite error : read sdcard start %d, total %d failed\n",
tmp_imgfile_start, rest_sectors * 512);
goto __download_normal_part_err1;
}
if (sunxi_sprite_write(tmp_partstart_by_sector,
rest_sectors,
down_buffer) != rest_sectors) {
printf("sunxi sprite error: download rawdata error %s, start 0x%x, sectors 0x%x\n",
part_info->dl_filename,
tmp_partstart_by_sector, rest_sectors);
goto __download_normal_part_err1;
}
}
} else {
if (unsparse_direct_write(down_buffer, first_write_bytes)) {
printf("sunxi sprite error: download sparse error %s\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
tmp_partdata_by_bytes -= first_write_bytes;
while (tmp_partdata_by_bytes >= AU_ONCE_DATA_DEAL) {
if (fat_fs_read(imgname, down_buffer, tmp_imgfile_start,
AU_ONCE_DATA_DEAL) !=
AU_ONCE_DATA_DEAL) {
printf("sunxi sprite error : read sdcard start 0x%x, total 0x%x failed\n",
tmp_imgfile_start, AU_ONCE_DATA_DEAL);
goto __download_normal_part_err1;
}
if (unsparse_direct_write(down_buffer,
AU_ONCE_DATA_DEAL)) {
printf("sunxi sprite error: download sparse error %s\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
tmp_imgfile_start += AU_ONCE_SECTOR_DEAL * 512;
tmp_partdata_by_bytes -= AU_ONCE_DATA_DEAL;
}
if (tmp_partdata_by_bytes > 0) {
uint rest_sectors = (tmp_partdata_by_bytes + 511) >> 9;
if (fat_fs_read(imgname, down_buffer, tmp_imgfile_start,
rest_sectors * 512) !=
rest_sectors * 512) {
printf("sunxi sprite error : read sdcard start 0x%x, total 0x%x failed\n",
tmp_imgfile_start, rest_sectors * 512);
goto __download_normal_part_err1;
}
if (unsparse_direct_write(down_buffer,
tmp_partdata_by_bytes)) {
printf("sunxi sprite error: download sparse error %s\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
}
}
sunxi_flash_flush();
tick_printf("successed in writting part %s\n", part_info->name);
ret = 0;
if (imgitemhd) {
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
}
/* verify */
if (part_info->verify) {
ret = -1;
if (part_info->vf_filename[0]) {
imgitemhd =
Img_OpenItem(imghd, "RFSFAT16",
(char *)part_info->vf_filename);
if (!imgitemhd) {
printf("sprite update warning: open part %s failed\n",
part_info->vf_filename);
goto __download_normal_part_err1;
}
if (!Img_Fat_ReadItem(imghd, imgitemhd, imgname,
(void *)verify_data, 1024)) {
printf("sprite update warning: fail to read data from %s\n",
part_info->vf_filename);
goto __download_normal_part_err1;
}
if (partdata_format == ANDROID_FORMAT_DETECT) {
active_verify =
sunxi_sprite_part_sparsedata_verify();
} else {
active_verify =
sunxi_sprite_part_rawdata_verify(
partstart_by_sector,
partdata_by_byte);
}
tmp = (uint *)verify_data;
origin_verify = *tmp;
printf("origin_verify value = %x, active_verify value = %x\n",
origin_verify, active_verify);
if (origin_verify != active_verify) {
printf("origin checksum=%x, active checksum=%x\n",
origin_verify, active_verify);
printf("sunxi sprite: part %s verify error\n",
part_info->dl_filename);
goto __download_normal_part_err1;
}
ret = 0;
} else {
printf("sunxi sprite err: part %s unablt to find verify file\n",
part_info->dl_filename);
}
tick_printf("successed in verify part %s\n", part_info->name);
} else {
printf("sunxi sprite err: part %s not need to verify\n",
part_info->dl_filename);
}
__download_normal_part_err1:
if (imgitemhd) {
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
}
return ret;
}
static int __download_udisk(dl_one_part_info *part_info, uchar *source_buff)
{
HIMAGEITEM imgitemhd = NULL;
u32 flash_sector;
s64 packet_len;
s32 ret = -1, ret1;
imgitemhd =
Img_OpenItem(imghd, "RFSFAT16", (char *)part_info->dl_filename);
if (!imgitemhd) {
printf("sunxi sprite error: open part %s failed\n",
part_info->dl_filename);
return -1;
}
packet_len = Img_GetItemSize(imghd, imgitemhd);
if (packet_len <= 0) {
printf("sunxi sprite error: fetch part len %s failed\n",
part_info->dl_filename);
goto __download_udisk_err1;
}
if (packet_len <= CONFIG_FW_BURN_UDISK_MIN_SIZE) {
printf("download UDISK: the data length of udisk is too small, ignore it\n");
ret = 1;
goto __download_udisk_err1;
}
flash_sector = sunxi_sprite_size();
if (!flash_sector) {
printf("sunxi sprite error: download_udisk, the flash size is invalid(0)\n");
goto __download_udisk_err1;
}
printf("the flash size is %d MB\n", flash_sector / 2 / 1024);
part_info->lenlo = flash_sector - part_info->addrlo;
part_info->lenhi = 0;
printf("UDISK low is 0x%x Sectors\n", part_info->lenlo);
printf("UDISK high is 0x%x Sectors\n", part_info->lenhi);
ret = __download_normal_part(part_info, source_buff);
__download_udisk_err1:
ret1 = Img_CloseItem(imghd, imgitemhd);
if (ret1 != 0) {
printf("sunxi sprite error: __download_udisk, close udisk image failed\n");
return -1;
}
return ret;
}
static int __download_sysrecover_part(dl_one_part_info *part_info,
uchar *source_buff)
{
uint partstart_by_sector;
uint tmp_partstart_by_sector;
s64 partsize_by_byte;
s64 partdata_by_byte;
s64 tmp_partdata_by_bytes;
uint onetime_read_sectors;
uint tmp_imgfile_start = 0;
u8 *down_buffer = source_buff + AU_HEAD_BUFF;
int ret = -1;
tmp_partstart_by_sector = partstart_by_sector = part_info->addrlo;
partsize_by_byte = part_info->lenlo;
partsize_by_byte <<= 9;
partdata_by_byte = Img_GetSize(imghd);
if (partdata_by_byte <= 0) {
printf("sunxi sprite error: fetch part len %s failed\n",
part_info->dl_filename);
goto __download_sysrecover_part_err1;
}
if (partdata_by_byte > partsize_by_byte) {
printf("sunxi sprite: data size 0x%x is larger than part %s size 0x%x\n",
(uint)(partdata_by_byte / 512), part_info->dl_filename,
(uint)(partsize_by_byte / 512));
goto __download_sysrecover_part_err1;
}
tmp_partdata_by_bytes = partdata_by_byte;
if (tmp_partdata_by_bytes >= AU_ONCE_DATA_DEAL) {
onetime_read_sectors = AU_ONCE_SECTOR_DEAL;
} else {
onetime_read_sectors = (tmp_partdata_by_bytes + 511) >> 9;
}
while (tmp_partdata_by_bytes >= AU_ONCE_DATA_DEAL) {
if (fat_fs_read(imgname, down_buffer, 0,
onetime_read_sectors * 512) !=
onetime_read_sectors * 512) {
printf("sunxi sprite error : read sdcard start %d, total %d failed\n",
tmp_imgfile_start, onetime_read_sectors * 512);
goto __download_sysrecover_part_err1;
}
if (sunxi_sprite_write(tmp_partstart_by_sector,
onetime_read_sectors,
down_buffer) != onetime_read_sectors) {
printf("sunxi sprite error: download rawdata error %s, start 0x%x, sectors 0x%x\n",
part_info->dl_filename, tmp_partstart_by_sector,
onetime_read_sectors);
goto __download_sysrecover_part_err1;
}
tmp_imgfile_start += onetime_read_sectors * 512;
tmp_partdata_by_bytes -= onetime_read_sectors * 512;
tmp_partstart_by_sector += onetime_read_sectors;
}
if (tmp_partdata_by_bytes > 0) {
uint rest_sectors = (tmp_partdata_by_bytes + 511) / 512;
if (fat_fs_read(imgname, down_buffer, tmp_imgfile_start,
rest_sectors * 512) != rest_sectors * 512) {
printf("sunxi sprite error : read sdcard start %d, total %d failed\n",
tmp_imgfile_start, rest_sectors * 512);
goto __download_sysrecover_part_err1;
}
if (sunxi_sprite_write(tmp_partstart_by_sector, rest_sectors,
down_buffer) != rest_sectors) {
printf("sunxi sprite error: download rawdata error %s, start 0x%x, sectors 0x%x\n",
part_info->dl_filename, tmp_partstart_by_sector,
rest_sectors);
goto __download_sysrecover_part_err1;
}
}
ret = 0;
__download_sysrecover_part_err1:
if (imgitemhd) {
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
}
return ret;
}
static int auto_update_deal_part(sunxi_download_info *dl_map)
{
dl_one_part_info *part_info;
int ret = -1;
int ret1;
int i = 0;
uchar *down_buff = NULL;
__maybe_unused int rate;
if (!dl_map->download_count) {
printf("sunxi sprite: no part need to write\n");
return 0;
}
rate = (70 - 10) / dl_map->download_count;
down_buff = (uchar *)memalign(CONFIG_SYS_CACHELINE_SIZE,
AU_ONCE_DATA_DEAL + AU_HEAD_BUFF);
if (!down_buff) {
printf("sunxi sprite err: unable to malloc memory for sunxi_sprite_deal_part\n");
goto __auto_update_deal_part_err1;
}
for (part_info = dl_map->one_part_info, i = 0;
i < dl_map->download_count; i++, part_info++) {
tick_printf("begin to download part %s\n", part_info->name);
if (!strncmp("UDISK", (char *)part_info->name,
strlen("UDISK"))) {
ret1 = __download_udisk(part_info, down_buff);
if (ret1 < 0) {
printf("sunxi sprite err: sunxi_sprite_deal_part, download_udisk failed\n");
goto __auto_update_deal_part_err1;
} else if (ret1 > 0) {
printf("do NOT need download UDISK\n");
}
}
/* sysrecovery partition: burn the whole img*/
else if (!strncmp("sysrecovery", (char *)part_info->name,
strlen("sysrecovery"))) {
ret1 = __download_sysrecover_part(part_info, down_buff);
if (ret1 != 0) {
printf("sunxi sprite err: sunxi_sprite_deal_part, download sysrecovery failed\n");
goto __auto_update_deal_part_err1;
}
}
/*private partition: check if need to burn private data*/
else if (!strncmp("private", (char *)part_info->name,
strlen("private"))) {
if (1) {
/*need to burn private part*/
printf("NEED down private part\n");
ret1 = __download_normal_part(part_info,
down_buff);
if (ret1 != 0) {
printf("sunxi sprite err: sunxi_sprite_deal_part, download private failed\n");
goto __auto_update_deal_part_err1;
}
} else {
printf("IGNORE private part\n");
}
} else {
ret1 = __download_normal_part(part_info, down_buff);
if (ret1 != 0) {
printf("sunxi sprite err: sunxi_sprite_deal_part, download normal failed\n");
goto __auto_update_deal_part_err1;
}
}
//sprite_cartoon_upgrade(10 + rate * (i + 1));
tick_printf("successed in download part %s\n", part_info->name);
}
ret = 0;
__auto_update_deal_part_err1:
if (down_buff) {
free(down_buff);
}
return ret;
}
static int auto_update_deal_boot0(int production_media)
{
int ret = 0;
char *buffer = memalign(CONFIG_SYS_CACHELINE_SIZE, 1 * 1024 * 1024);
uint item_original_size;
if (gd->bootfile_mode == SUNXI_BOOT_FILE_NORMAL ||
gd->bootfile_mode == SUNXI_BOOT_FILE_PKG) {
if (production_media == STORAGE_NAND) {
imgitemhd = Img_OpenItem(imghd, "BOOT ",
"BOOT0_0000000000");
} else if (production_media == STORAGE_NOR) {
imgitemhd = Img_OpenItem(imghd, "12345678",
"1234567890BNOR_0");
} else {
imgitemhd = Img_OpenItem(imghd, "12345678",
"1234567890BOOT_0");
}
} else {
imgitemhd = Img_OpenItem(imghd, "12345678", "TOC0_00000000000");
}
if (!imgitemhd) {
printf("sprite update error: fail to open boot0 item\n");
ret = -1;
goto out;
}
/*get boot0 size*/
item_original_size = Img_GetItemSize(imghd, imgitemhd);
if (!item_original_size) {
printf("sprite update error: fail to get boot0 item size\n");
ret = -1;
goto out;
}
/* read boot0 */
if (!Img_Fat_ReadItem(imghd, imgitemhd, imgname, (void *)buffer,
1 * 1024 * 1024)) {
printf("update error: fail to read data from for boot0\n");
ret = -1;
goto out;
}
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
if (sunxi_sprite_download_boot0(buffer, production_media)) {
printf("update error: fail to write boot0\n");
ret = -1;
goto out;
}
out:
if (buffer) {
free(buffer);
}
return ret;
}
int auto_update_deal_uboot(int production_media)
{
int ret = 0;
char *buffer = memalign(CONFIG_SYS_CACHELINE_SIZE, 4 * 1024 * 1024);
uint item_original_size;
if (gd->bootfile_mode == SUNXI_BOOT_FILE_NORMAL) {
imgitemhd = Img_OpenItem(imghd, "12345678", "UBOOT_0000000000");
} else if (gd->bootfile_mode == SUNXI_BOOT_FILE_PKG) {
if (production_media == STORAGE_NOR)
imgitemhd = Img_OpenItem(imghd, "12345678",
"BOOTPKG-NOR00000");
else
imgitemhd = Img_OpenItem(imghd, "12345678",
"BOOTPKG-00000000");
} else {
imgitemhd = Img_OpenItem(imghd, "12345678", "TOC1_00000000000");
}
if (!imgitemhd) {
printf("sprite update error: fail to open uboot item\n");
ret = -1;
goto out;
}
/* get uboot size */
item_original_size = Img_GetItemSize(imghd, imgitemhd);
if (!item_original_size) {
printf("sprite update error: fail to get uboot item size\n");
ret = -1;
goto out;
}
/* read uboot */
if (!Img_Fat_ReadItem(imghd, imgitemhd, imgname, (void *)buffer,
4 * 1024 * 1024)) {
printf("update error: fail to read data from for uboot\n");
ret = -1;
goto out;
}
Img_CloseItem(imghd, imgitemhd);
imgitemhd = NULL;
if (sunxi_sprite_download_uboot(buffer, production_media, 0)) {
printf("update error: fail to write uboot\n");
ret = -1;
goto out;
}
printf("sunxi_sprite_deal_uboot ok\n");
out:
if (buffer) {
free(buffer);
}
return ret;
}
int sunxi_auto_update_main(void)
{
int ret = 0;
int production_media;
/* uchar img_mbr[1024 * 1024]; */
uchar *img_mbr = memalign(CONFIG_SYS_CACHELINE_SIZE, 1024 * 1024);
sunxi_download_info *dl_map;
dl_map = (sunxi_download_info *)memalign(CONFIG_SYS_CACHELINE_SIZE,
sizeof(sunxi_download_info));
int mbr_num = SUNXI_MBR_COPY_NUM;
int nodeoffset;
int processbar_direct = 0;
tick_printf("sunxi update begin\n");
nodeoffset = fdt_path_offset(working_fdt, FDT_PATH_CARD_BOOT);
if (nodeoffset >= 0) {
if (fdt_getprop_u32(working_fdt, nodeoffset,
"processbar_direct",
(uint32_t *)&processbar_direct) < 0)
processbar_direct = 0;
}
production_media = get_boot_storage_type();
imgname =
memalign(CONFIG_SYS_CACHELINE_SIZE, strlen(firmware_path) + 1);
if (imgname == NULL) {
printf("imgname : null\n");
ret = -1;
goto out;
}
strcpy(imgname, firmware_path);
//sprite_cartoon_create(processbar_direct);
if (auto_update_firmware_probe(imgname)) {
printf("sunxi sprite firmware probe fail\n");
ret = -1;
goto out;
}
//sprite_cartoon_upgrade(5);
/* download dlmap file to get the download files*/
tick_printf("fetch download map\n");
if (auto_update_fetch_download_map(dl_map)) {
printf("sunxi sprite error : fetch download map error\n");
ret = -1;
goto out;
}
__dump_dlmap(dl_map);
//fetch mbr iterm
tick_printf("fetch mbr\n");
if (auto_update_fetch_mbr(img_mbr)) {
printf("sunxi sprite error : fetch mbr error\n");
ret = -1;
goto out;
}
/* according to the mbr,erase or protect data*/
tick_printf("begin to erase flash\n");
nand_get_mbr((char *)img_mbr, 16 * 1024);
tick_printf("nand_get_mbr finish\n");
if (sunxi_sprite_erase_flash(img_mbr)) {
printf("sunxi sprite error: erase flash err\n");
ret = -1;
goto out;
}
tick_printf("successed in erasing flash\n");
if (production_media == STORAGE_NOR) {
mbr_num = 1;
}
if (sunxi_sprite_download_mbr(img_mbr, sizeof(sunxi_mbr_t) * mbr_num)) {
printf("sunxi sprite error: download mbr err\n");
ret = -1;
goto out;
}
//sprite_cartoon_upgrade(10);
tick_printf("begin to download part\n");
/* start burning partition data*/
if (auto_update_deal_part(dl_map)) {
printf("sunxi sprite error : download part error\n");
ret = -1;
goto out;
}
tick_printf("successed in downloading part\n");
//sprite_cartoon_upgrade(80);
/* sunxi_sprite_exit(1); */
if (auto_update_deal_uboot(production_media)) {
printf("sunxi sprite error : download uboot error\n");
ret = -1;
goto out;
}
tick_printf("successed in downloading uboot\n");
//sprite_cartoon_upgrade(90);
if (auto_update_deal_boot0(production_media)) {
printf("sunxi sprite error : download boot0 error\n");
ret = -1;
goto out;
}
tick_printf("successed in downloading boot0\n");
//sprite_cartoon_upgrade(100);
//sprite_uichar_printf("CARD OK\n");
tick_printf("update firmware success \n");
mdelay(3000);
out:
if (dl_map) {
free(dl_map);
dl_map = NULL;
}
if (img_mbr) {
free(img_mbr);
img_mbr = NULL;
}
return ret;
}
static uboot_command *get_script_next_line(char *line_buf_ptr, int *arg_max)
{
char *line_buf;
static uboot_command *next_line;
int i, j, k, flag;
static int argv_max;
line_buf = line_buf_ptr;
for (i = 0, flag = 0; (*line_buf) != 0; line_buf++) {
if (IS_LINE_END(*line_buf) && flag == 0) {
continue;
} else if (IS_LINE_END(*line_buf) && flag == 1) {
i++;
flag = 0;
} else if (*line_buf == '#') {
line_buf = strstr(line_buf, "\n");
} else if (*line_buf == '%') {
break;
} else {
flag = 1;
}
}
if (argv_max != i) {
if (next_line != NULL) {
free(next_line);
}
next_line = (uboot_command *)memalign(
CONFIG_SYS_CACHELINE_SIZE, sizeof(uboot_command) * i);
if (next_line == NULL)
return NULL;
*arg_max = argv_max = i;
}
memset((char *)next_line, 0, sizeof(uboot_command) * i);
line_buf = line_buf_ptr;
for (i = 0, j = 0, k = 0, flag = 0; (*line_buf) != 0; line_buf++) {
if (IS_LINE_END(*line_buf) && flag == 0) {
continue;
} else if (IS_LINE_END(*line_buf) && flag == 1) {
next_line[i].argv[j][k] = 0;
i++;
k = 0;
j = 0;
flag = 0;
} else if (*line_buf == '#') {
line_buf = strstr(line_buf, "\n");
} else if (*line_buf == '%') {
break;
} else {
flag = 1;
if (*line_buf != ' ') {
next_line[i].argv[j][k++] = *line_buf;
} else {
next_line[i].argv[j][k] = 0;
j++;
k = 0;
}
}
}
*arg_max = argv_max;
return next_line;
}
int do_auto_update_check(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
int arg_max = 0, i;
u32 file_size, file_offset, len = 0;
uboot_command *commands;
char temp_buf[256] = { 0 };
char *file_buff = (char *)0x45000000;
char *file_p = file_buff;
int inited = 0;
if (!run_command("sunxi_card0_probe", 0)) {
inited = 1;
strncpy(interface, "mmc", sizeof("usb"));
} else if (!run_command("usb reset", 0)) {
inited = 1;
strncpy(interface, "usb", sizeof("usb"));
} else {
return 0;
}
if (simple_strtoul(argv[1], NULL, 16) == 1) {
return sunxi_auto_update_main();
} else if (inited == 1) {
file_size = 0;
file_offset = 0;
fat_fs_read("scripts/auto_update.txt", (void *)file_p,
file_offset, file_size);
commands = get_script_next_line(file_buff, &arg_max);
for (i = 0; i < arg_max; i++) {
if (!strncmp(commands[i].argv[3], "firmware",
sizeof("firmware"))) {
firmware_path = commands[i].argv[2];
sunxi_auto_update_main();
sunxi_flash_write_end();
sunxi_flash_flush();
goto out;
}
}
for (i = 0; i < arg_max; i++) {
sprintf(temp_buf, "fatsize %s 0 %s", interface,
commands[i].argv[2]);
run_command(temp_buf, 0);
file_size = env_get_hex("filesize", 0);
printf("file_size:0x%x temp_buf:%s from:%s\n", file_size,
temp_buf, commands[i].argv[2]);
file_p = file_buff;
if (file_size < MAX_FILE_SIZE) {
memset(file_buff, 0, MAX_FILE_SIZE);
file_offset = 0;
fat_fs_read(commands[i].argv[2], (void *)file_buff,
file_offset, file_size);
sprintf(temp_buf, "%s %s 0x%lx %s 0x%x",
commands[i].argv[0],
commands[i].argv[1],
(unsigned long)file_buff,
commands[i].argv[3], file_size);
pr_debug("temp_buf:%s\n", temp_buf);
run_command(temp_buf, 0);
mdelay(10);
} else {
file_offset = 0;
memset(file_buff, 0, file_size);
len = file_size;
while (file_size) {
if (file_size >= MAX_FILE_SIZE) {
fat_fs_read(commands[i].argv[2],
(void *)file_p, file_offset,
MAX_FILE_SIZE);
mdelay(10);
file_size -= MAX_FILE_SIZE;
file_offset += MAX_FILE_SIZE;
file_p += MAX_FILE_SIZE;
} else {
fat_fs_read(commands[i].argv[2],
(void *)file_p, file_offset,
file_size);
mdelay(10);
memset(temp_buf, 0, 256);
sprintf(temp_buf,
"%s %s 0x%lx %s 0x%x",
commands[i].argv[0],
commands[i].argv[1],
(unsigned long)file_buff,
commands[i].argv[3], len);
run_command(temp_buf, 0);
mdelay(10);
file_size -= file_size;
file_offset += file_size;
file_p += file_size;
}
}
}
}
sunxi_flash_write_end();
sunxi_flash_flush();
}
out:
return 0;
}
U_BOOT_CMD(auto_update_check, CONFIG_SYS_MAXARGS, 1, do_auto_update_check,
"auto_update_v2 - Do TFCard of Udisk update\n",
"\nnote:\n"
" - The auto_update.txt configuration file must be\n"
" added to the scripts directory of the U disk.\n"
" - The command after # will be considered as a comment.\n"
" - All text & commands after % are invalid\n"
" auto_update.txt format:\n"
" sunxi_flash write <file path> <load partition>\n"
" exp:\n"
" sunxi_flash write update/boot.fex boot\n"
" sunxi_flash write update/boot_package.fex boot_package\n");