static int image_check(HIMAGE hImage) { FILE* fp = (FILE*)hImage; unsigned int crc32 = 0; if(ImageDecoder->AmlFirmwareImg->crc==0){ fseeko(fp,0,SEEK_SET); memset(ImageDecoder->AmlFirmwareImg,0,sizeof(AmlFirmwareImg_t)); if(fread(ImageDecoder->AmlFirmwareImg,sizeof(AmlFirmwareImg_t),1, fp) != 1) { fprintf(stderr,"cannot read %u bytes [%s]\n", (unsigned)sizeof(AmlFirmwareImg_t),strerror(errno)); return -1; } } if(ImageDecoder->AmlFirmwareImg->magic != IMAGE_MAGIC){ fprintf(stderr,"the magic number is not match \n"); return -1; } crc32 = calc_img_crc(fp, ImageDecoder->AmlFirmwareImg->itemAlginSize); printf("crc32==0x%x\n",crc32); printf("ImageDecoder->AmlFirmwareImg->crc==0x%x\n",ImageDecoder->AmlFirmwareImg->crc); if(crc32!=ImageDecoder->AmlFirmwareImg->crc){ fprintf(stderr,"crc check fail !!! \n"); return -1; } return 0; }
EXPORT #endif int image_pack(const char* cfg_file, const char* src_dir ,const char* target_file) { struct stat64 s; FILE* fp_read = NULL; FILE* fp_write = NULL; char *tmp; int count = 0; size_t write_bytes = 0; ItemInfo* totalItemInfo = NULL; char *buff = NULL; int ret = 0; ItemInfo* AmlItem = NULL; if(!cfg_file||!src_dir||!target_file){ fprintf(stderr,"invalid param! \n"); return -1; } if(stat64(cfg_file, &s)){ fprintf(stderr,"could not stat '%s'\n", cfg_file); return -1; } fp_read = fopen(cfg_file, "rb"); if (fp_read == NULL){ fprintf(stderr,"failed to open canned file \n"); return -1; } tmp = (char*) malloc(s.st_size); if(tmp == NULL) { fprintf(stderr,"allocate memccpy failed at %s %d \n", __FILE__,__LINE__); free(tmp); return -1; } if(fread(tmp,1, s.st_size,fp_read) != s.st_size) { fprintf(stderr,"file read error [%s] \n", strerror(errno)); fclose(fp_read); free(tmp); return -1; } fclose(fp_read); if(image_cfg_parse(tmp,s.st_size) < 0){ fprintf(stderr,"image_cfg_parse error! \n"); free(tmp); return -1; } free(tmp); tmp = NULL; if(image_check_files(src_dir)<0){ fprintf(stderr,"image check file error! \n"); return -1; } fp_write = fopen(target_file, "wb+"); if (fp_write == NULL){ fprintf(stderr,"failed to create target file! \n"); return -1; } AmlFirmwareImg_t aAmlImage; AmlFirmwareImg_t *FirmwareImg = &aAmlImage; memset(FirmwareImg,0,sizeof(AmlFirmwareImg_t)); if(fwrite(FirmwareImg,1, sizeof(AmlFirmwareImg_t),fp_write) != sizeof(AmlFirmwareImg_t)) { fprintf(stderr,"cannot write %u bytes\n", (unsigned)sizeof(AmlFirmwareImg_t)); fclose(fp_write); return -1; } const int TotalItemCnt = ImageDecoder->gItemCount; debugP("TotalItemCnt %d\n", TotalItemCnt); totalItemInfo = new ItemInfo[TotalItemCnt]; memset(totalItemInfo,0,sizeof(ItemInfo) * TotalItemCnt); write_bytes = fwrite(totalItemInfo,1, sizeof(ItemInfo) * TotalItemCnt, fp_write); if(write_bytes != sizeof(ItemInfo)* TotalItemCnt){ fprintf(stderr,"cannot write %d bytes \n", (int)sizeof(ItemInfo)); ret = __LINE__; goto _exit; } buff = new char[RW_MAX_SIZE]; if(buff==NULL){ fprintf(stderr,"allocate memccpy failed at %s %d \n", __FILE__,__LINE__); ret = __LINE__; goto _exit; } //For each list: //1, create item info; 2,pack the item data; 3, crate verify item info; 4, pack verify data AmlItem = totalItemInfo; for(const FileList *list = ImageDecoder->gImageCfg.file_list; list; list = list->next, AmlItem++, count++) { struct stat64 info; char path[256]={0}; memset(path,0,256); strcpy(path,src_dir); strcat(path,list->name); printf("pack [%-12s, %16s] from (%s)\n", list->main_type, list->sub_type, path); fp_read = fopen(path,"rb"); if(fp_read == NULL){ fprintf(stderr,"failed to open source file : %s \n",path); ret = -1; break; } if(stat64(path,&info)<0){ fprintf(stderr,"stat %s failed!\n",path); ret = -1; break; } AmlItem->itemSz = info.st_size; AmlItem->itemId = count; AmlItem->verify = 0;//1 if a verify item strcpy(AmlItem->itemMainType,list->main_type); strcpy(AmlItem->itemSubType,list->sub_type); const ItemInfo* foundSamFileItemInfo = previous_duplicated_item_id(ImageDecoder->gImageCfg.file_list, list, totalItemInfo, AmlItem); if(foundSamFileItemInfo)//this item is source from a duplicated file item { AmlItem->offsetInImage = foundSamFileItemInfo->offsetInImage; AmlItem->fileType = foundSamFileItemInfo->fileType; AmlItem->isBackUpItem = 1; AmlItem->backUpItemId = foundSamFileItemInfo->itemId; } else { AmlItem->offsetInImage = ftello(fp_write); if(AmlItem->offsetInImage % ITEM_ALGIN){ AmlItem->offsetInImage += ITEM_ALGIN - AmlItem->offsetInImage % ITEM_ALGIN; } fseeko(fp_read,0,SEEK_SET); write_bytes = fread(buff,1,RW_MAX_SIZE,fp_read); if(optimus_simg_probe(buff,RW_HEAD_SIZE) == 0){ AmlItem->fileType = IMAGE_ITEM_TYPE_NORMAL; }else{ AmlItem->fileType = IMAGE_ITEM_TYPE_SPARSE; } //Following create the item data // fseeko(fp_write,AmlItem->offsetInImage,SEEK_SET); fseeko(fp_read,0,SEEK_SET); while((write_bytes = fread(buff,1,RW_MAX_SIZE,fp_read))>0) { if(fwrite(buff,1,write_bytes,fp_write)!=write_bytes){ fprintf(stderr,"write to image file fail! [%s] \n",strerror(errno)); ret = -1; break; } } fclose(fp_read); if(ret < 0) break; } if(list->verify) { ++count; ++AmlItem; AmlItem->itemSz = 48; AmlItem->itemId = count; strcpy(AmlItem->itemMainType,"VERIFY"); strcpy(AmlItem->itemSubType,list->sub_type); AmlItem->fileType = IMAGE_ITEM_TYPE_NORMAL; AmlItem->verify = 1; if(foundSamFileItemInfo)//the source file is already packed { const ItemInfo* verfiyItem4_foundItem = foundSamFileItemInfo + 1; //test if the next item following foundSamFileItemInfo is verify item if(!strcmp(foundSamFileItemInfo->itemSubType, verfiyItem4_foundItem->itemSubType) && !strcmp(verfiyItem4_foundItem->itemMainType, AmlItem->itemMainType))//"VERIFY" { AmlItem->offsetInImage = verfiyItem4_foundItem->offsetInImage; AmlItem->isBackUpItem = 1; AmlItem->backUpItemId = verfiyItem4_foundItem->itemId; continue;//skip followings } } AmlItem->offsetInImage = ftello(fp_write); if(AmlItem->offsetInImage % ITEM_ALGIN){ AmlItem->offsetInImage += ITEM_ALGIN - AmlItem->offsetInImage % ITEM_ALGIN; } memset(buff,0,48); gen_sha1sum_verify(path, buff); fseeko(fp_write,AmlItem->offsetInImage,SEEK_SET); if(fwrite(buff,1,48,fp_write)!=48){ fprintf(stderr,"write verify data to image file fail! [%s] \n",strerror(errno)); ret = -1; break; } } } free(buff); buff = 0; FirmwareImg->magic = IMAGE_MAGIC; FirmwareImg->version = VERSION; FirmwareImg->itemNum = count; fseeko(fp_write, 0L, SEEK_END); FirmwareImg->imageSz = ftello(fp_write); FirmwareImg->itemAlginSize = 4; fseeko(fp_write,0L,SEEK_SET); if(fwrite(FirmwareImg,1, sizeof(AmlFirmwareImg_t),fp_write) != sizeof(AmlFirmwareImg_t)) { fprintf(stderr,"cannot write %u bytes [%s] [0x%p]\n", (unsigned)sizeof(AmlFirmwareImg_t), strerror(errno), fp_write); ret = -1; } write_bytes = fwrite(totalItemInfo, 1, sizeof(ItemInfo) * TotalItemCnt, fp_write); if(write_bytes != sizeof(ItemInfo) * TotalItemCnt){ errorP("fail to update item info\n"); ret = __LINE__; goto _exit; } FirmwareImg->crc = calc_img_crc(fp_write,FirmwareImg->itemAlginSize); fseeko(fp_write,0L,SEEK_SET); if(fwrite(&(FirmwareImg->crc),1,FirmwareImg->itemAlginSize,fp_write) != FirmwareImg->itemAlginSize) { fprintf(stderr,"cannot write crc32 [0x%x] [%s] \n",FirmwareImg->crc ,strerror(errno)); ret = -1; } printf("Size=0x%llxB[%lluM], crc=0x%x, Install image[%s] OK\n", FirmwareImg->imageSz, (FirmwareImg->imageSz>>20), FirmwareImg->crc, target_file); _exit: if(fp_write)fclose(fp_write), fp_write = NULL; if(totalItemInfo)delete[] totalItemInfo, totalItemInfo = NULL; if(buff) delete[] buff, buff = NULL; return ret; }
/* * 1, */ static int _img_pack(const char** const path_src, const char* const packedImg, pFunc_getFile getFile, const int totalFileNum) { FILE *fd_src = NULL; FILE *fd_dest = NULL; unsigned int pos = 0; char file_path[MAX_PATH]; const char *filename = NULL; unsigned imageSz = 0; const unsigned BufSz = ITEM_READ_BUF_SZ; char* itemBuf = NULL; unsigned thisWriteLen = 0; unsigned actualWriteLen = 0; int ret = 0; __hdle hDir = NULL; const unsigned itemAlignSz = AML_RES_IMG_ITEM_ALIGN_SZ; const unsigned itemAlignMod = itemAlignSz - 1; const unsigned itemSzAlignMask = ~itemAlignMod; const unsigned totalItemNum = totalFileNum ? totalFileNum : get_dir_filenums(*path_src); const unsigned HeadLen = IMG_HEAD_SZ + ITEM_HEAD_SZ * totalItemNum; if(HeadLen > BufSz){ errorP("head size 0x%x > max(0x%x)\n", HeadLen, BufSz); return __LINE__; } fd_dest = fopen(packedImg, "wb+"); if(NULL == fd_dest) { fprintf(stderr,"open %s failed: %s\n", packedImg, strerror(errno)); return __LINE__; } itemBuf = new char[BufSz * 2]; if(!itemBuf){ errorP("Exception: fail to alloc buuffer\n"); fclose(fd_dest); return __LINE__; } memset(itemBuf, 0, BufSz*2); AmlResImgHead_t* const aAmlResImgHead = (AmlResImgHead_t*)(itemBuf + BufSz); actualWriteLen = fwrite(aAmlResImgHead, 1, HeadLen, fd_dest); if(actualWriteLen != HeadLen){ errorP("fail to write head, want 0x%x, but 0x%x\n", HeadLen, actualWriteLen); fclose(fd_dest); delete[] itemBuf; return __LINE__; } imageSz += HeadLen; //Increase imageSz after pack each item AmlResItemHead_t* pItemHeadInfo = (AmlResItemHead_t*)(aAmlResImgHead + 1); AmlResItemHead_t* const pFirstItemHeadInfo = pItemHeadInfo; debugP("item num %d\n", totalItemNum); //for each loop: first create item header and pack it, second pack the item data //Fill the item head, 1) magic, 2)data offset, 3)next head start offset for(unsigned itemIndex = 0; itemIndex < totalItemNum; ++itemIndex) { char filePath[MAX_PATH*2]; if(totalFileNum)//File list mode { if((*getFile)(path_src, (__hdle*)itemIndex, filePath)) { break; } } else {//file directory mode if((*getFile)(path_src, &hDir, filePath)) { break; } } const size_t itemSz = get_filesize(filePath); const char* itemName = get_filename(filePath); const unsigned itemBodyOccupySz = (itemSz & itemSzAlignMask) + itemAlignSz; const unsigned itemStuffSz = itemBodyOccupySz - itemSz; if(IH_NMLEN - 1 < strlen(itemName)){ errorP("Item name %s len %d > max(%d)\n", itemName, (int)strlen(itemName), IH_NMLEN - 1); ret = __LINE__; goto _exit; } pItemHeadInfo->magic = IH_MAGIC; pItemHeadInfo->size = itemSz; //imageSz += ITEM_HEAD_SZ;//not needed yet as all item_head moves to image header pItemHeadInfo->start = imageSz; pItemHeadInfo->next = (char*)(pItemHeadInfo + 1) - (char*)aAmlResImgHead; pItemHeadInfo->index = itemIndex; imageSz += itemBodyOccupySz; pItemHeadInfo->nums = totalItemNum; memcpy(pItemHeadInfo->name, itemName, strlen(itemName)); debugP("pack item [%s]\n", itemName); ++pItemHeadInfo;//prepare for next item fd_src = fopen(filePath, "rb"); if(!fd_src){ errorP("Fail to open file [%s], strerror[%s]\n", filePath, strerror(errno)); ret = __LINE__; goto _exit; } for(size_t itemWriteLen = 0; itemWriteLen < itemSz; itemWriteLen += thisWriteLen) { size_t leftLen = itemSz - itemWriteLen; thisWriteLen = leftLen > BufSz ? BufSz : leftLen; actualWriteLen = fread(itemBuf, 1, thisWriteLen, fd_src); if(actualWriteLen != thisWriteLen){ errorP("Want to read 0x%x but actual 0x%x, at itemWriteLen 0x%x, leftLen 0x%x\n", thisWriteLen, actualWriteLen, (unsigned)itemWriteLen, (unsigned)leftLen); ret = __LINE__; goto _exit; } actualWriteLen = fwrite(itemBuf, 1, thisWriteLen, fd_dest); if(actualWriteLen != thisWriteLen){ errorP("Want to write 0x%x but actual 0x%x\n", thisWriteLen, actualWriteLen); ret = __LINE__; goto _exit; } } fclose(fd_src), fd_src = NULL; memset(itemBuf, 0, itemStuffSz); thisWriteLen = itemStuffSz; actualWriteLen = fwrite(itemBuf, 1, thisWriteLen, fd_dest); if(actualWriteLen != thisWriteLen){ errorP("Want to write 0x%x, but 0x%x\n", thisWriteLen, actualWriteLen); ret = __LINE__; goto _exit; } } (--pItemHeadInfo)->next = 0; //Create the header aAmlResImgHead->version = AML_RES_IMG_VERSION_V2; memcpy(&aAmlResImgHead->magic[0], AML_RES_IMG_V1_MAGIC, AML_RES_IMG_V1_MAGIC_LEN); aAmlResImgHead->imgSz = imageSz; aAmlResImgHead->imgItemNum = totalItemNum; aAmlResImgHead->alignSz = itemAlignSz; aAmlResImgHead->crc = 0; // //Seek to file header to correct the header fseek(fd_dest, 0, SEEK_SET); actualWriteLen = fwrite(aAmlResImgHead, 1, HeadLen, fd_dest); if(actualWriteLen != HeadLen){ errorP("Want to write 0x%x, but 0x%x\n", HeadLen, actualWriteLen); ret = __LINE__; goto _exit; } aAmlResImgHead->crc = calc_img_crc(fd_dest, 4);//Gen crc32 fseek(fd_dest, 0, SEEK_SET); actualWriteLen = fwrite(&aAmlResImgHead->crc, 1, 4, fd_dest); if(4 != actualWriteLen){ errorP("Want to write 4, but %d\n", actualWriteLen); ret = __LINE__; goto _exit; } _exit: if(itemBuf) delete[] itemBuf, itemBuf = NULL; if(fd_src) fclose(fd_src), fd_src = NULL; if(fd_dest) fclose(fd_dest), fd_dest = NULL; return ret; }