/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_sprite_download_mbr(void *buffer, uint buffer_size) { int ret; if(buffer_size != (SUNXI_MBR_SIZE * SUNXI_MBR_COPY_NUM)) { printf("the mbr size is bad\n"); return -1; } if(sunxi_sprite_init(0)) { printf("sunxi sprite init fail when downlaod mbr\n"); return -1; } if(sunxi_sprite_write(0, buffer_size/512, buffer) == (buffer_size/512)) { debug("mbr write ok\n"); ret = 0; } else { debug("mbr write fail\n"); ret = -1; } if(uboot_spare_head.boot_data.storage_type == 2) { printf("begin to write standard mbr\n"); if(card_download_standard_mbr(buffer)) { printf("write standard mbr err\n"); return -1; } printf("successed to write standard mbr\n"); } if(sunxi_sprite_exit(0)) { printf("sunxi sprite exit fail when downlaod mbr\n"); return -1; } return ret; }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_sprite_erase_private_key(void *buffer) { int count = 0; int flash_start = 0 , flash_sectors = 0; int i = 0 , len = 1024 * 1024; sunxi_mbr_t *mbr = (sunxi_mbr_t *)buffer; char *fill_zero = NULL; for(i=0;i<mbr->PartCount;i++) { if( (!strcmp((const char *)mbr->array[i].name, SUNXI_SPRITE_PROTECT_PART)) || (mbr->array[i].keydata == 0x8000)) { printf("private part exist\n"); count = mbr->array[i].lenlo / 2048; flash_start = mbr->array[i].addrlo; break; } } if(i >= mbr->PartCount) { printf("private part is not exit \n"); return -1; } fill_zero = (char *)malloc(len); if(fill_zero == NULL) { printf("no enough memory to malloc \n"); return -1; } memset(fill_zero , 0x0, len); flash_sectors = len / 512; for(i = 0; i < count ; i++) { if(!sunxi_sprite_write(flash_start + i * flash_sectors, flash_sectors, (void *)fill_zero)) { printf("sunxi_sprite_erase_private_key err: write flash from 0x%x, sectors 0x%x failed\n", flash_start + i * flash_sectors, flash_sectors); return -1; } } printf("erase key successed \n"); return 0; }
/* ************************************************************************************************************ * * 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; } } }
/* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int sunxi_sprite_restore_part_data(void *buffer) { int i, j; int ret = -1; uint down_sectors; sunxi_mbr_t *mbr = (sunxi_mbr_t *)buffer; j = 0; while(part_info[j].part_buf) { for(i=0;i<mbr->PartCount;i++) { if(!strcmp(part_info[j].part_name, (const char*)mbr->array[i].name)) { if(part_info[j].part_sectors > mbr->array[i].lenlo) { printf("origin sectors 0x%x, new part sectors 0x%x\n", part_info[j].part_sectors, mbr->array[i].lenlo); printf("fix it, only store less sectors\n"); down_sectors = mbr->array[i].lenlo; } else { down_sectors = part_info[j].part_sectors; } printf("keypart write start: 0x%x, sectors 0x%x\n", mbr->array[i].addrlo, down_sectors); if(!sunxi_sprite_write(mbr->array[i].addrlo, down_sectors, (void *)part_info[j].part_buf)) { printf("sunxi sprite error : write private data error\n"); goto __sunxi_sprite_restore_part_data_fail; } printf("keypart write end: 0x%x, sectors 0x%x\n", mbr->array[i].addrlo, down_sectors); break; } } j ++; } if(!j) { printf("there is no private part need rewrite\n"); } ret = 0; __sunxi_sprite_restore_part_data_fail: for(i=0;i<j;i++) { if(part_info[i].part_buf) { free(part_info[i].part_buf); } else { break; } } return ret; }