/* * (C) Copyright 2007-2013 * Allwinner Technology Co., Ltd. * Jerry Wang * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include "sparse/sparse.h" #include #include #include #include #include #include #include "encrypt/encrypt.h" #include "sprite_queue.h" #include "sprite_download.h" #include "sprite_verify.h" #include "firmware/imgdecode.h" #include "dos_part.h" #include #include #include #include #include #define SPRITE_CARD_HEAD_BUFF (32 * 1024) #if defined (CONFIG_SUNXI_SPINOR) #define SPRITE_CARD_ONCE_DATA_DEAL (2 * 1024 * 1024) #else #define SPRITE_CARD_ONCE_DATA_DEAL (16 * 1024 * 1024) #endif #define SPRITE_CARD_ONCE_SECTOR_DEAL (SPRITE_CARD_ONCE_DATA_DEAL/512) static void *imghd = NULL; static void *imgitemhd = NULL; DECLARE_GLOBAL_DATA_PTR; //extern int sunxi_flash_mmc_phywipe(unsigned long start_block, unsigned long nblock, unsigned long *skip); static int __download_normal_part(dl_one_part_info *part_info, uchar *source_buff); /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ uint sprite_card_firmware_start(void) { return sunxi_partition_get_offset(1); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sprite_card_firmware_probe(char *name) { debug("firmware name %s\n", name); imghd = Img_Open(name); if(!imghd) { return -1; } return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sprite_card_fetch_download_map(sunxi_download_info *dl_map) { imgitemhd = Img_OpenItem(imghd, "12345678", "1234567890DLINFO"); if(!imgitemhd) { return -1; } debug("try to read item dl map\n"); if(!Img_ReadItem(imghd, imgitemhd, (void *)dl_map, sizeof(sunxi_download_info))) { printf("sunxi sprite error : read dl map failed\n"); return -1; } Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; //检查获取的dlinfo是否正确 return sunxi_sprite_verify_dlmap(dl_map); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sprite_card_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; } debug("try to read item mbr\n"); if(!Img_ReadItem(imghd, imgitemhd, 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); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ 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 <= 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); //计算出M单位 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; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static int __download_normal_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 first_write_bytes; uint imgfile_start; //分区数据所在的扇区 uint tmp_imgfile_start; u8 *down_buffer = source_buff + SPRITE_CARD_HEAD_BUFF; int partdata_format; int ret = -1; //******************************************************************* //获取分区起始扇区 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 >= SPRITE_CARD_ONCE_DATA_DEAL) { onetime_read_sectors = SPRITE_CARD_ONCE_SECTOR_DEAL; first_write_bytes = SPRITE_CARD_ONCE_DATA_DEAL; } else { onetime_read_sectors = (tmp_partdata_by_bytes + 511)>>9; first_write_bytes = (uint)tmp_partdata_by_bytes; } //开始获取分区数据 imgfile_start = Img_GetItemStart(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; //读出第一笔固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, onetime_read_sectors, down_buffer) != onetime_read_sectors) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, onetime_read_sectors); goto __download_normal_part_err1; } //下一个要读出的数据 tmp_imgfile_start += onetime_read_sectors; //尝试查看是否sparse格式 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 >= SPRITE_CARD_ONCE_DATA_DEAL) { //继续读出固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, SPRITE_CARD_ONCE_SECTOR_DEAL, down_buffer) != SPRITE_CARD_ONCE_SECTOR_DEAL) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, SPRITE_CARD_ONCE_SECTOR_DEAL); goto __download_normal_part_err1; } //写入flash if(sunxi_sprite_write(tmp_partstart_by_sector, SPRITE_CARD_ONCE_SECTOR_DEAL, down_buffer) != SPRITE_CARD_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, SPRITE_CARD_ONCE_SECTOR_DEAL); goto __download_normal_part_err1; } tmp_imgfile_start += SPRITE_CARD_ONCE_SECTOR_DEAL; tmp_partdata_by_bytes -= SPRITE_CARD_ONCE_DATA_DEAL; tmp_partstart_by_sector += SPRITE_CARD_ONCE_SECTOR_DEAL; } if(tmp_partdata_by_bytes > 0) { uint rest_sectors = (tmp_partdata_by_bytes + 511)>>9; //继续读出固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, rest_sectors, down_buffer) != rest_sectors) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, rest_sectors); goto __download_normal_part_err1; } //写入flash 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 >= SPRITE_CARD_ONCE_DATA_DEAL) { //继续读出固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, SPRITE_CARD_ONCE_SECTOR_DEAL, down_buffer) != SPRITE_CARD_ONCE_SECTOR_DEAL) { printf("sunxi sprite error : read sdcard block 0x%x, total 0x%x failed\n", tmp_imgfile_start, SPRITE_CARD_ONCE_SECTOR_DEAL); goto __download_normal_part_err1; } //写入flash if(unsparse_direct_write(down_buffer, SPRITE_CARD_ONCE_DATA_DEAL)) { printf("sunxi sprite error: download sparse error %s\n", part_info->dl_filename); goto __download_normal_part_err1; } tmp_imgfile_start += SPRITE_CARD_ONCE_SECTOR_DEAL; tmp_partdata_by_bytes -= SPRITE_CARD_ONCE_DATA_DEAL; } if(tmp_partdata_by_bytes > 0) { uint rest_sectors = (tmp_partdata_by_bytes + 511)>>9; //继续读出固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, rest_sectors, down_buffer) != rest_sectors) { printf("sunxi sprite error : read sdcard block 0x%x, total 0x%x failed\n", tmp_imgfile_start, rest_sectors); goto __download_normal_part_err1; } //写入flash 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; } } } tick_printf("successed in writting part %s\n", part_info->name); ret = 0; if(imgitemhd) { Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; } //判断是否需要进行校验 if(part_info->verify) { uint active_verify; uint origin_verify; uchar verify_data[1024]; 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_ReadItem(imghd, imgitemhd, (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); } { uint *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; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ 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 imgfile_start; //分区数据所在的扇区 uint tmp_imgfile_start; u8 *down_buffer = source_buff + SPRITE_CARD_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 >= SPRITE_CARD_ONCE_DATA_DEAL) { onetime_read_sectors = SPRITE_CARD_ONCE_SECTOR_DEAL; } else { onetime_read_sectors = (tmp_partdata_by_bytes + 511)>>9; } //开始获取分区数据 imgfile_start = sprite_card_firmware_start(); if(!imgfile_start) { printf("sunxi sprite err : cant get part data imgfile_start %s\n", part_info->dl_filename); goto __download_sysrecover_part_err1; } tmp_imgfile_start = imgfile_start; while(tmp_partdata_by_bytes >= SPRITE_CARD_ONCE_DATA_DEAL) { //继续读出固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, onetime_read_sectors, down_buffer) != onetime_read_sectors) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, onetime_read_sectors); goto __download_sysrecover_part_err1; } //写入flash 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; 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; //继续读出固件中的分区数据,大小为buffer字节数 if(sunxi_flash_read(tmp_imgfile_start, rest_sectors, down_buffer) != rest_sectors) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, rest_sectors); goto __download_sysrecover_part_err1; } //写入flash 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; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_sprite_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; 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; //初始化flash,nand或者mmc if(sunxi_sprite_init(1)) { printf("sunxi sprite err: init flash err\n"); return -1; } //申请内存 down_buff = (uchar *)malloc(SPRITE_CARD_ONCE_DATA_DEAL + SPRITE_CARD_HEAD_BUFF); if(!down_buff) { printf("sunxi sprite err: unable to malloc memory for sunxi_sprite_deal_part\n"); goto __sunxi_sprite_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 __sunxi_sprite_deal_part_err2; } else if(ret1 > 0) { printf("do NOT need download UDISK\n"); } }//如果是sysrecovery分区,烧录完整分区镜像 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 __sunxi_sprite_deal_part_err2; } }//如果是private分区,检查是否需要烧录 else if(!strncmp("private", (char*)part_info->name, strlen("private"))) { if(1) { //需要烧录此分区 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 __sunxi_sprite_deal_part_err2; } } 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 __sunxi_sprite_deal_part_err2; } } sprite_cartoon_upgrade(10 + rate * (i+1)); tick_printf("successed in download part %s\n", part_info->name); } ret = 0; __sunxi_sprite_deal_part_err1: sunxi_sprite_exit(1); __sunxi_sprite_deal_part_err2: if(down_buff) { free(down_buff); } return ret; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_sprite_deal_uboot(int production_media) { char buffer[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 (get_boot_storage_type() != STORAGE_NOR) { imgitemhd = Img_OpenItem(imghd, "12345678", "BOOTPKG-00000000"); } else { imgitemhd = Img_OpenItem(imghd, "12345678", "BOOTPKG-NOR00000"); } } else { imgitemhd = Img_OpenItem(imghd, "12345678", "TOC1_00000000000"); } if(!imgitemhd) { printf("sprite update error: fail to open uboot item\n"); return -1; } //uboot长度 item_original_size = Img_GetItemSize(imghd, imgitemhd); if(!item_original_size) { printf("sprite update error: fail to get uboot item size\n"); return -1; } /*获取uboot的数据*/ if(!Img_ReadItem(imghd, imgitemhd, (void *)buffer, 4 * 1024 * 1024)) { printf("update error: fail to read data from for uboot\n"); return -1; } Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; if(sunxi_sprite_download_uboot(buffer, production_media, 0)) { printf("update error: fail to write uboot\n"); return -1; } printf("sunxi_sprite_deal_uboot ok\n"); return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_sprite_deal_boot0(int production_media) { char buffer[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"); return -1; } //boot0长度 item_original_size = Img_GetItemSize(imghd, imgitemhd); if(!item_original_size) { printf("sprite update error: fail to get boot0 item size\n"); return -1; } /*获取boot0的数据*/ if(!Img_ReadItem(imghd, imgitemhd, (void *)buffer, 1 * 1024 * 1024)) { printf("update error: fail to read data from for boot0\n"); return -1; } Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; if(sunxi_sprite_download_boot0(buffer, production_media)) { printf("update error: fail to write boot0\n"); return -1; } return 0; } int sunxi_sprite_deal_recorvery_boot(int production_media) { char buffer_uboot[4 * 1024 * 1024]; char buffer_boot0[1 *1024 * 1024]; uint item_size_uboot; uint item_size_boot0; if(gd->bootfile_mode == SUNXI_BOOT_FILE_NORMAL ) { imgitemhd = Img_OpenItem(imghd, "12345678", "UBOOT_0000000000"); } else if(gd->bootfile_mode == SUNXI_BOOT_FILE_PKG) { 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"); return -1; } item_size_uboot = Img_GetItemSize(imghd, imgitemhd); if(!item_size_uboot) { printf("sprite update error: fail to get uboot item size\n"); return -1; } if(!Img_ReadItem(imghd, imgitemhd, (void *)buffer_uboot, 4 * 1024 * 1024)) { printf("update error: fail to read data from for uboot\n"); return -1; } Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; if(gd->bootfile_mode == SUNXI_BOOT_FILE_NORMAL || gd->bootfile_mode == SUNXI_BOOT_FILE_PKG) { if(production_media == 0) { imgitemhd = Img_OpenItem(imghd, "BOOT ", "BOOT0_0000000000"); } 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"); return -1; } item_size_boot0 = Img_GetItemSize(imghd, imgitemhd); if(!item_size_boot0) { printf("sprite update error: fail to get boot0 item size\n"); return -1; } if(!Img_ReadItem(imghd, imgitemhd, (void *)buffer_boot0, 1 * 1024 * 1024)) { printf("update error: fail to read data from for boot0\n"); return -1; } Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; /*write boot data*/ if(sunxi_sprite_download_uboot(buffer_uboot, production_media, 0)) { printf("update error: fail to write uboot\n"); return -1; } tick_printf("successed in downloading uboot\n"); if(sunxi_sprite_download_boot0(buffer_boot0, production_media)) { printf("update error: fail to write boot0\n"); return -1; } tick_printf("successed in downloading boot0\n"); printf("sunxi_sprite_deal_recorvery_boot ok\n"); return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int card_verify_uboot(uint start_block, uint length) { int ret = 0; char *buffer = NULL; buffer = (char *)malloc(length); if (!buffer) { printf("%s: malloc %d byte memory fail\n", __func__, length); return -1; } memset(buffer, 0, length); ret = sunxi_sprite_phyread(start_block, length/512, buffer); if (!ret) { printf("%s: write boot0 from %d fail\n", __func__, start_block); goto ERR_OUT; } if (gd->bootfile_mode == SUNXI_BOOT_FILE_NORMAL) { struct spare_boot_head_t *uboot = (struct spare_boot_head_t *)buffer; printf("uboot magic %.*s\n", MAGIC_SIZE, uboot->boot_head.magic); if (strncmp((const char *)uboot->boot_head.magic, UBOOT_MAGIC, MAGIC_SIZE)) { printf("sunxi sprite: uboot magic is error\n"); return -1; } length = uboot->boot_head.length; if (sunxi_sprite_verify_checksum(buffer, uboot->boot_head.length, uboot->boot_head.check_sum)) { printf("sunxi sprite: boot0 checksum is error flash_sum=0x%x\n", uboot->boot_head.check_sum); goto ERR_OUT; } ret = 1; } else { sbrom_toc1_head_info_t *toc1 = (sbrom_toc1_head_info_t *)buffer; if (gd->bootfile_mode == SUNXI_BOOT_FILE_PKG) { printf("uboot_pkg magic 0x%x\n", toc1->magic); } else { printf("toc magic 0x%x\n", toc1->magic); } if (toc1->magic != TOC_MAIN_INFO_MAGIC) { printf("sunxi sprite: toc magic is error\n"); return -1; } length = toc1->valid_len; if (sunxi_sprite_verify_checksum(buffer, toc1->valid_len, toc1->add_sum)) { printf("sunxi sprite: toc1 checksum is error flash_sum=0x%x\n", toc1->add_sum); goto ERR_OUT; } ret = 1; } ERR_OUT: if (buffer != NULL) free(buffer); if (!ret) return -1; else return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int card_download_uboot(uint length, void *buffer) { int ret; ret = sunxi_sprite_phywrite(UBOOT_START_SECTOR_IN_SDMMC, length/512, buffer); if(!ret) { printf("%s: write uboot from %d fail\n", __func__, UBOOT_START_SECTOR_IN_SDMMC); return -1; } ret = card_verify_uboot(UBOOT_START_SECTOR_IN_SDMMC, length); if (ret < 0) { printf("%s: verify uboot checksum from %d fail\n", __func__, UBOOT_START_SECTOR_IN_SDMMC); return -1; } ret = sunxi_sprite_phywrite(UBOOT_BACKUP_START_SECTOR_IN_SDMMC, length/512, buffer); if(!ret) { printf("%s: write uboot from %d fail\n", __func__, UBOOT_BACKUP_START_SECTOR_IN_SDMMC); return -1; } return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int card_verify_boot0(uint start_block, uint length) { int ret = 0; char *buffer = NULL; buffer = (char *)malloc(length); if (!buffer) { printf("%s: malloc %d byte memory fail\n", __func__, length); return -1; } memset(buffer, 0, length); ret = sunxi_sprite_phyread(start_block, length/512, buffer); if (!ret) { printf("%s: write boot0 from %d fail\n", __func__, start_block); goto ERR_OUT; } if (gd->bootfile_mode == SUNXI_BOOT_FILE_NORMAL || gd->bootfile_mode == SUNXI_BOOT_FILE_PKG) { boot0_file_head_t *boot0 = (boot0_file_head_t *)buffer; debug("%.*s\n", MAGIC_SIZE, boot0->boot_head.magic); if (strncmp((const char *)boot0->boot_head.magic, BOOT0_MAGIC, MAGIC_SIZE)) { printf("sunxi sprite: boot0 magic is error\n"); goto ERR_OUT; } if (sunxi_sprite_verify_checksum(buffer, boot0->boot_head.length, boot0->boot_head.check_sum)) { printf("sunxi sprite: boot0 checksum is error flash_check_sum=0x%x\n", boot0->boot_head.check_sum); goto ERR_OUT; } ret = 1; } else { toc0_private_head_t *toc0 = (toc0_private_head_t *)buffer; debug("%s\n", (char *)toc0->name); if (strncmp((const char *)toc0->name, TOC0_MAGIC, MAGIC_SIZE)) { printf("sunxi sprite: toc0 magic is error\n"); goto ERR_OUT; } if (sunxi_sprite_verify_checksum(buffer, toc0->length, toc0->check_sum)) { printf("sunxi sprite: toc0 checksum is error flash_check_sum=0x%x\n", toc0->check_sum); goto ERR_OUT; } ret = 1; } ERR_OUT: if (buffer != NULL) free(buffer); if (!ret) return -1; else return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int card_download_boot0(uint length, void *buffer, uint storage_type) { int ret = 0; char *erase_buffer = NULL; erase_buffer = (char *)malloc(length); if (!erase_buffer) { printf("%s: malloc %d byte memory fail\n", __func__, length); return -1; } memset(erase_buffer, 0, length); //for card2 if (storage_type == STORAGE_EMMC) { printf("card2 download boot0\n"); //write boot0 bankup copy firstly ret = sunxi_sprite_phywrite(BOOT0_SDMMC_BACKUP_START_ADDR, length/512, buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_SDMMC_BACKUP_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_SDMMC_START_ADDR, length/512, buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_SDMMC_START_ADDR); goto ERR_OUT; } if (card_verify_boot0(BOOT0_SDMMC_START_ADDR, length) < 0) { printf("%s: verify boot0 checksum from %d fail\n", __func__, BOOT0_SDMMC_START_ADDR); goto ERR_OUT; } #ifdef PLATFORM_SUPPORT_EMMC3 ret = sunxi_sprite_phywrite(BOOT0_EMMC3_START_ADDR, length/512, erase_buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_EMMC3_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_EMMC3_BACKUP_START_ADDR, length/512, erase_buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_EMMC3_BACKUP_START_ADDR); goto ERR_OUT; } #endif } else if (storage_type == STORAGE_SD1) { printf("card1 download boot0\n"); //write boot0 bankup copy firstly ret = sunxi_sprite_phywrite(BOOT0_SDMMC_BACKUP_START_ADDR, length/512, buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_SDMMC_BACKUP_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_SDMMC_START_ADDR, length/512, buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_SDMMC_START_ADDR); goto ERR_OUT; } #ifdef PLATFORM_SUPPORT_EMMC3 ret = sunxi_sprite_phywrite(BOOT0_EMMC3_START_ADDR, length/512, erase_buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_EMMC3_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_EMMC3_BACKUP_START_ADDR, length/512, erase_buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_EMMC3_BACKUP_START_ADDR); goto ERR_OUT; } #endif } else //for card3 { #ifdef PLATFORM_SUPPORT_EMMC3 printf("card3 download boot0\n"); //write boot0 bankup copy firstly ret = sunxi_sprite_phywrite(BOOT0_EMMC3_BACKUP_START_ADDR, length/512, buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_EMMC3_BACKUP_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_EMMC3_START_ADDR, length/512, buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_EMMC3_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_SDMMC_START_ADDR, length/512, erase_buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_SDMMC_START_ADDR); goto ERR_OUT; } ret = sunxi_sprite_phywrite(BOOT0_SDMMC_BACKUP_START_ADDR, length/512, erase_buffer); if(!ret) { printf("%s: write boot0 from %d fail\n", __func__, BOOT0_SDMMC_BACKUP_START_ADDR); goto ERR_OUT; } #endif } ERR_OUT: if (erase_buffer != NULL) free(erase_buffer); if (!ret) return -1; else return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ //static void buffer_dump(void *buffer, int len) //{ // int i; // char *data = (char *)buffer; // // for(i=0;iPartCount-1;i++) { memset(mbr_bufst, 0, 512); mbrst = (mbr_stand *)mbr_bufst; sectors += mbr->array[i].lenlo; mbrst->part_info[0].part_type = 0x83; mbrst->part_info[0].start_sectorl = ((mbr->array[i].addrlo - i + 20 * 1024 * 1024/512 ) & 0x0000ffff) >> 0; mbrst->part_info[0].start_sectorh = ((mbr->array[i].addrlo - i + 20 * 1024 * 1024/512 ) & 0xffff0000) >> 16; mbrst->part_info[0].total_sectorsl = ( mbr->array[i].lenlo & 0x0000ffff) >> 0; mbrst->part_info[0].total_sectorsh = ( mbr->array[i].lenlo & 0xffff0000) >> 16; if(i != mbr->PartCount-2) { mbrst->part_info[1].part_type = 0x05; mbrst->part_info[1].start_sectorl = i; mbrst->part_info[1].start_sectorh = 0; mbrst->part_info[1].total_sectorsl = (mbr->array[i].lenlo & 0x0000ffff) >> 0; mbrst->part_info[1].total_sectorsh = (mbr->array[i].lenlo & 0xffff0000) >> 16; } mbrst->end_flag = 0xAA55; if(!sunxi_sprite_phywrite(i, 1, mbr_bufst)) { printf("write standard mbr %d failed\n", i); return -1; } } memset(mbr_bufst, 0, 512); mbrst = (mbr_stand *)mbr_bufst; unusd_sectors = sunxi_sprite_size() - 20 * 1024 * 1024/512 - sectors; mbrst->part_info[0].indicator = 0x80; mbrst->part_info[0].part_type = 0x0B; mbrst->part_info[0].start_sectorl = ((mbr->array[mbr->PartCount-1].addrlo + 20 * 1024 * 1024/512 ) & 0x0000ffff) >> 0; mbrst->part_info[0].start_sectorh = ((mbr->array[mbr->PartCount-1].addrlo + 20 * 1024 * 1024/512 ) & 0xffff0000) >> 16; mbrst->part_info[0].total_sectorsl = ( unusd_sectors & 0x0000ffff) >> 0; mbrst->part_info[0].total_sectorsh = ( unusd_sectors & 0xffff0000) >> 16; mbrst->part_info[1].part_type = 0x06; mbrst->part_info[1].start_sectorl = ((mbr->array[0].addrlo + 20 * 1024 * 1024/512) & 0x0000ffff) >> 0; mbrst->part_info[1].start_sectorh = ((mbr->array[0].addrlo + 20 * 1024 * 1024/512) & 0xffff0000) >> 16; mbrst->part_info[1].total_sectorsl = (mbr->array[0].lenlo & 0x0000ffff) >> 0; mbrst->part_info[1].total_sectorsh = (mbr->array[0].lenlo & 0xffff0000) >> 16; mbrst->part_info[2].part_type = 0x05; mbrst->part_info[2].start_sectorl = 1; mbrst->part_info[2].start_sectorh = 0; mbrst->part_info[2].total_sectorsl = (sectors & 0x0000ffff) >> 0; mbrst->part_info[2].total_sectorsh = (sectors & 0xffff0000) >> 16; mbrst->end_flag = 0xAA55; if(!sunxi_sprite_phywrite(0, 1, mbr_bufst)) { printf("write standard mbr 0 failed\n"); return -1; } return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ #define CARD_ERASE_BLOCK_BYTES (8 * 1024 * 1024) #define CARD_ERASE_BLOCK_SECTORS (CARD_ERASE_BLOCK_BYTES/512) int card_erase(int erase, void *mbr_buffer) { char *erase_buffer; sunxi_mbr_t *mbr = (sunxi_mbr_t *)mbr_buffer; unsigned int erase_head_sectors; unsigned int erase_head_addr; unsigned int erase_tail_sectors; unsigned int erase_tail_addr; unsigned int skip_space[1+2*2]={0}; unsigned int from, nr; int k, ret = 0; int i; //tick_printf("erase all part start\n"); if(!erase) { return 0; } erase_buffer = (char *)malloc(CARD_ERASE_BLOCK_BYTES); if(!erase_buffer) { printf("card erase fail: unable to malloc memory for card erase\n"); return -1; } memset(erase_buffer, 0, CARD_ERASE_BLOCK_BYTES); //erase boot0,write 0x00 card_download_boot0(32 * 1024, erase_buffer, get_boot_storage_type()); printf("erase boot0, size:32k, write 0x00\n"); for(i=1;iPartCount;i++) { printf("erase %s part\n", mbr->array[i].name); if (mbr->array[i].lenlo > CARD_ERASE_BLOCK_SECTORS * 2) // part > 16M { erase_head_sectors = CARD_ERASE_BLOCK_SECTORS; erase_head_addr = mbr->array[i].addrlo; //erase_tail_sectors = CARD_ERASE_BLOCK_SECTORS; erase_tail_sectors = 2 * 1024 * 1024 / 512; erase_tail_addr = mbr->array[i].addrlo + mbr->array[i].lenlo - CARD_ERASE_BLOCK_SECTORS; } else if (mbr->array[i].lenlo > CARD_ERASE_BLOCK_SECTORS) // 8M < part <= 16M { erase_head_sectors = CARD_ERASE_BLOCK_SECTORS; erase_head_addr = mbr->array[i].addrlo; //erase_tail_sectors = mbr->array[i].lenlo - CARD_ERASE_BLOCK_SECTORS; erase_tail_sectors = 2 * 1024 * 1024 / 512; erase_tail_addr = mbr->array[i].addrlo + mbr->array[i].lenlo - erase_tail_sectors; } else if (mbr->array[i].lenlo > 0) // 0 < part <= 8M { erase_head_sectors = mbr->array[i].lenlo; erase_head_addr = mbr->array[i].addrlo; erase_tail_sectors = 0; erase_tail_addr = mbr->array[i].addrlo; } else { //printf("don't deal prat's length is 0 (%s)\n", mbr->array[i].name); //break; erase_head_sectors = CARD_ERASE_BLOCK_SECTORS; erase_head_addr = mbr->array[i].addrlo; erase_tail_sectors = 0; erase_tail_addr = mbr->array[i].addrlo; } from = mbr->array[i].addrlo + CONFIG_MMC_LOGICAL_OFFSET; nr = mbr->array[i].lenlo; ret = sunxi_sprite_mmc_phyerase(from, nr, skip_space); if (ret == 0) { //printf("erase part from sector 0x%x to 0x%x ok\n", from, (from+nr-1)); } else if (ret == 1) { for (k=0; k<2; k++) { if (skip_space[0] & (1<array[i].name); free(erase_buffer); return -1; } } } } else if (ret == -1) { // erase head for partition if(!sunxi_sprite_write(erase_head_addr, erase_head_sectors, erase_buffer)) { printf("card erase fail in erasing part %s\n", mbr->array[i].name); free(erase_buffer); return -1; } printf("erase prat's head from sector 0x%x to 0x%x\n", erase_head_addr, erase_head_addr + erase_head_sectors); // erase tail for partition if (erase_tail_sectors) { if(!sunxi_sprite_write(erase_tail_addr, erase_tail_sectors, erase_buffer)) { printf("card erase fail in erasing part %s\n", mbr->array[i].name); free(erase_buffer); return -1; } printf("erase part's tail from sector 0x%x to 0x%x\n", erase_tail_addr, erase_tail_addr + erase_tail_sectors); } } } printf("card erase all\n"); free(erase_buffer); //while((*(volatile unsigned int *)0) != 1); //tick_printf("erase all part end\n"); return 0; } #define BOOT0_MAX_SIZE (32 * 1024) int sunxi_card_fill_boot0_magic(void) { uchar buffer[BOOT0_MAX_SIZE]; boot0_file_head_t *boot0_head; uint src_sum, cal_sum; struct mmc *mmc0; char debug_info[1024]; int ret = -1; puts("probe mmc0 if exist\n"); memset(debug_info, 0, 1024); board_mmc_pre_init(0); mmc0 = find_mmc_device(0); if(!mmc0) { strcpy(debug_info, "fail to find mmc0"); goto __sunxi_card_fill_boot0_magic_exit; } printf("try to init mmc0\n"); if (mmc_init(mmc0)) { strcpy(debug_info, "MMC0 init failed"); goto __sunxi_card_fill_boot0_magic_exit; } memset(buffer, 0, BOOT0_MAX_SIZE); if(mmc0->block_dev.block_read_mass_pro(mmc0->block_dev.dev, 16, BOOT0_MAX_SIZE/512, buffer) != BOOT0_MAX_SIZE/512) { strcpy(debug_info, "read mmc boot0 failed"); goto __sunxi_card_fill_boot0_magic_exit; } //compare data boot0_head = (boot0_file_head_t *)buffer; //fill boot0 magic memcpy((char *)boot0_head->boot_head.magic, BOOT0_MAGIC,8); printf("boot0_head->boot_head.magic == %.*s\n", MAGIC_SIZE, (char*)boot0_head->boot_head.magic); src_sum = boot0_head->boot_head.check_sum; printf("src_sum = %x\n" ,src_sum); //boot0_head->boot_head.check_sum = STAMP_VALUE; printf("boot0_head->boot_head.length = %d\n",boot0_head->boot_head.length); boot0_head->boot_head.check_sum = STAMP_VALUE; cal_sum = add_sum(buffer, boot0_head->boot_head.length); if(src_sum != cal_sum) { puts("boot0 addsum error\n"); return ret; } boot0_head->boot_head.check_sum = src_sum; flush_cache((ulong)buffer,BOOT0_MAX_SIZE); if(mmc0->block_dev.block_write_mass_pro(mmc0->block_dev.dev, 16, BOOT0_MAX_SIZE/512, buffer) != BOOT0_MAX_SIZE/512) { strcpy(debug_info, "write mmc boot0 failed"); goto __sunxi_card_fill_boot0_magic_exit; } ret = 0; return ret ; __sunxi_card_fill_boot0_magic_exit: printf("%s\n", debug_info); return ret ; } int sunxi_sprite_deal_part_from_sysrevoery(sunxi_download_info *dl_map) { dl_one_part_info *part_info; int ret = -1; int ret1; int i = 0; uchar *down_buff = NULL; int rate; if(!dl_map->download_count) { printf("sunxi sprite: no part need to write\n"); return 0; } rate = (80)/(dl_map->download_count+1); down_buff = (uchar *)malloc(SPRITE_CARD_ONCE_DATA_DEAL + SPRITE_CARD_HEAD_BUFF); if(!down_buff) { printf("sunxi sprite err: unable to malloc memory for sunxi_sprite_deal_part\n"); goto __sunxi_sprite_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 (!strcmp("env", (const char *)part_info->name)) { printf("env part do not need to rewrite\n"); sprite_cartoon_upgrade(20 + rate * (i+1)); continue; } else if (!strcmp("sysrecovery", (const char *)part_info->name)) { printf("THIS_IMG_SELF_00 do not need to rewrite\n"); sprite_cartoon_upgrade(20 + rate * (i+1)); continue; } else if (!strcmp("UDISK", (const char *)part_info->name)) { printf("UDISK do not need to rewrite\n"); sprite_cartoon_upgrade(20 + rate * (i+1)); continue; } else if (!strcmp("private", (const char *)part_info->name)) { printf("private do not need to rewrite\n"); sprite_cartoon_upgrade(20 + rate * (i+1)); continue; } 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 __sunxi_sprite_deal_part_err2; } } sprite_cartoon_upgrade(20 + rate * (i+1)); tick_printf("successed in download part %s\n", part_info->name); } ret = 0; __sunxi_sprite_deal_part_err1: sunxi_sprite_exit(1); __sunxi_sprite_deal_part_err2: if(down_buff) { free(down_buff); } return ret; } int __imagehd(HIMAGE tmp_himage) { imghd = tmp_himage; if (imghd) { return 0; } return -1; } #ifdef CONFIG_SUNXI_SPINOR extern int sunxi_sprite_setdata_finish(void); static int __download_fullimg_part(uchar *source_buff) { uint tmp_partstart_by_sector; s64 partdata_by_byte; s64 tmp_partdata_by_bytes; uint onetime_read_sectors; uint first_write_bytes; uint imgfile_start; uint tmp_imgfile_start; u8 *down_buffer = source_buff + SPRITE_CARD_HEAD_BUFF; int ret = -1; tmp_partstart_by_sector = 0; imgitemhd = Img_OpenItem(imghd, "12345678", "FULLIMG_00000000"); if(!imgitemhd) { printf("sunxi sprite error: open part FULLIMG failed\n"); return -1; } partdata_by_byte = Img_GetItemSize(imghd, imgitemhd); if (partdata_by_byte <= 0) { printf("sunxi sprite error: fetch part len FULLIMG failed\n"); goto __download_fullimg_part_err1; } printf("partdata hi 0x%x\n", (uint)(partdata_by_byte>>32)); printf("partdata lo 0x%x\n", (uint)partdata_by_byte); tmp_partdata_by_bytes = partdata_by_byte; if(tmp_partdata_by_bytes >= SPRITE_CARD_ONCE_DATA_DEAL) { onetime_read_sectors = SPRITE_CARD_ONCE_SECTOR_DEAL; first_write_bytes = SPRITE_CARD_ONCE_DATA_DEAL; } else { onetime_read_sectors = (tmp_partdata_by_bytes + 511)>>9; first_write_bytes = (uint)tmp_partdata_by_bytes; } imgfile_start = Img_GetItemStart(imghd, imgitemhd); if(!imgfile_start) { printf("sunxi sprite err : cant get part data imgfile_start FULLIMG\n"); goto __download_fullimg_part_err1; } tmp_imgfile_start = imgfile_start; if(sunxi_flash_read(tmp_imgfile_start, onetime_read_sectors, down_buffer) != onetime_read_sectors) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, onetime_read_sectors); goto __download_fullimg_part_err1; } tmp_imgfile_start += onetime_read_sectors; if(sunxi_sprite_write(tmp_partstart_by_sector, onetime_read_sectors, down_buffer) != onetime_read_sectors) { printf("sunxi sprite error: download rawdata error FULLIMG\n"); goto __download_fullimg_part_err1; } tmp_partdata_by_bytes -= first_write_bytes; tmp_partstart_by_sector += onetime_read_sectors; while(tmp_partdata_by_bytes >= SPRITE_CARD_ONCE_DATA_DEAL) { if(sunxi_flash_read(tmp_imgfile_start, SPRITE_CARD_ONCE_SECTOR_DEAL, down_buffer) != SPRITE_CARD_ONCE_SECTOR_DEAL) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, SPRITE_CARD_ONCE_SECTOR_DEAL); goto __download_fullimg_part_err1; } //D′è?flash if(sunxi_sprite_write(tmp_partstart_by_sector, SPRITE_CARD_ONCE_SECTOR_DEAL, down_buffer) != SPRITE_CARD_ONCE_SECTOR_DEAL) { printf("sunxi sprite error: download rawdata error FULLIMG, start 0x%x, sectors 0x%x\n", tmp_partstart_by_sector, SPRITE_CARD_ONCE_SECTOR_DEAL); goto __download_fullimg_part_err1; } tmp_imgfile_start += SPRITE_CARD_ONCE_SECTOR_DEAL; tmp_partdata_by_bytes -= SPRITE_CARD_ONCE_DATA_DEAL; tmp_partstart_by_sector += SPRITE_CARD_ONCE_SECTOR_DEAL; } if(tmp_partdata_by_bytes > 0) { uint rest_sectors = (tmp_partdata_by_bytes + 511)>>9; if(sunxi_flash_read(tmp_imgfile_start, rest_sectors, down_buffer) != rest_sectors) { printf("sunxi sprite error : read sdcard block %d, total %d failed\n", tmp_imgfile_start, rest_sectors); goto __download_fullimg_part_err1; } if(sunxi_sprite_write(tmp_partstart_by_sector, rest_sectors, down_buffer) != rest_sectors) { printf("sunxi sprite error: download rawdata error FULLIMG, start 0x%x, sectors 0x%x\n", tmp_partstart_by_sector, rest_sectors); goto __download_fullimg_part_err1; } } printf("successed in writting part FULLIMG\n"); ret = 0; __download_fullimg_part_err1: if(imgitemhd) { Img_CloseItem(imghd, imgitemhd); imgitemhd = NULL; } return ret; } int sunxi_sprite_deal_fullimg(void) { int ret = -1; int ret1; uchar *down_buff = NULL; if(sunxi_sprite_init(1)) { printf("sunxi sprite err: init flash err\n"); return -1; } down_buff = (uchar *)malloc(SPRITE_CARD_ONCE_DATA_DEAL + SPRITE_CARD_HEAD_BUFF); if(!down_buff) { printf("sunxi sprite err: unable to malloc memory for sunxi_sprite_deal_part\n"); goto __sunxi_sprite_deal_fullimg_err1; } ret1 = __download_fullimg_part(down_buff); if(ret1 != 0) { printf("sunxi sprite err: sunxi_sprite_deal_part, download normal failed\n"); goto __sunxi_sprite_deal_fullimg_err2; } //while(*(volatile uint *)0 != 0x12); sunxi_sprite_setdata_finish(); printf("sunxi card sprite trans finish\n"); ret = 0; __sunxi_sprite_deal_fullimg_err1: sunxi_sprite_exit(1); __sunxi_sprite_deal_fullimg_err2: if(down_buff) { free(down_buff); } return ret; } #endif