//Get the item header info //If the @imgVersion is V2, the item header already stored in @pImgHead, if @imgVersion is V2 or old, also read it into 64K size pImgHead static const AmlResItemHead_t* _img_unpack_get_item_header(const int imgVersion, const AmlResImgHead_t* pImgHead, int itemIndex, FILE* fdResImg) { const AmlResItemHead_t* pItemNext = NULL; AmlResItemHead_t* tmpItem = NULL; tmpItem = (AmlResItemHead_t*)(pImgHead + 1); tmpItem += itemIndex; switch(imgVersion) { case AML_RES_IMG_VERSION_V2: pItemNext = tmpItem; break; case AML_RES_IMG_VERSION_V1: case 0: { const unsigned readSz = fread(tmpItem, 1, ITEM_HEAD_SZ, fdResImg); if(ITEM_HEAD_SZ != readSz){ errorP("Fail to read item head\n"); return NULL; } pItemNext = tmpItem; } break; default: break; } if(IH_MAGIC != pItemNext->magic){ errorP("Item magic error.\n"); return NULL; } return pItemNext; }
static int _img_unpack_check_img_header(const AmlResImgHead_t* pImgHead, int* imgVersion, unsigned* imgHeadSz) { int rc = 0; rc = memcmp(pImgHead->magic, AML_RES_IMG_V1_MAGIC, AML_RES_IMG_V1_MAGIC_LEN); if(rc) { const AmlResItemHead_t* pItemHead = (AmlResItemHead_t*)pImgHead; if(IH_MAGIC != pItemHead->magic){ errorP("magic of oldest img not item header!\n"); return __LINE__; } *imgVersion = 0; *imgHeadSz = 0; } else { if(AML_RES_IMG_VERSION_V2 < pImgHead->version){ errorP("res-img ver %d not supported\n", pImgHead->version); return __LINE__; } *imgVersion = pImgHead->version; *imgHeadSz = sizeof(AmlResImgHead_t); /* *if(AML_RES_IMG_VERSION_V2 == pImgHead->version){ * *imgHeadSz += pImgHead->imgItemNum * sizeof(AmlResItemHead_t); *} */ } return 0; }
/* * duplicated item like this, which source is the same file 'boot.PARTITION' but sub_type.main_type are different *file="boot.PARTITION" main_type="PARTITION" sub_type="boot" *file="boot.PARTITION" main_type="PARTITION" sub_type="bootbak" */ static const ItemInfo* previous_duplicated_item_id(const FileList* headFileList, const FileList* const curFileList, const ItemInfo* headItemInfo, const ItemInfo* curItemInfo) { int itemId = -1; int i = 0; for(;headFileList != curFileList && headFileList->next; headFileList = headFileList->next) { int rc = strcmp(curFileList->name, headFileList->name); if(!rc)//the file of headFileList is duplicated { for(; headItemInfo < curItemInfo; headItemInfo++) { if(!strcmp(headItemInfo->itemMainType, headFileList->main_type) && !strcmp(headItemInfo->itemSubType, headFileList->sub_type)) { return headItemInfo; } } errorP("find duplicated file(%s) but previous item not found\n", curFileList->name); return NULL; } } return NULL; }
static int image_get_next_item(HIMAGE hImage,unsigned int iItem, char* maintype, char* subtype) { FILE* fp = (FILE*)hImage; unsigned int nItem = 0; if(ImageDecoder->AmlFirmwareImg->crc==0){ memset(ImageDecoder->AmlFirmwareImg,0,sizeof(AmlFirmwareImg_t)); fseeko(fp,0,SEEK_SET); if(fread(ImageDecoder->AmlFirmwareImg,1, sizeof(AmlFirmwareImg_t),fp) != sizeof(AmlFirmwareImg_t)) { fprintf(stderr,"cannot read %u bytes", (unsigned)sizeof(AmlFirmwareImg_t)); return -1; } } if(iItem >= ImageDecoder->AmlFirmwareImg->itemNum){ errorP("Item index %u > max %u\n", iItem, ImageDecoder->AmlFirmwareImg->itemNum - 1); return -1; } fseeko(fp,sizeof(AmlFirmwareImg_t)+iItem*sizeof(ItemInfo),SEEK_SET); ItemInfo AmlItem; memset(&AmlItem,0,sizeof(ItemInfo)); if(fread(&AmlItem,sizeof(ItemInfo), 1,fp) != 1) { fprintf(stderr,"image_get_next_item:Read Err [%s]", strerror(errno)); return -1; } strncpy(maintype,AmlItem.itemMainType,32); strncpy(subtype,AmlItem.itemSubType,32); /*debugP("[%s, %s] verify = %d\n", maintype, subtype, AmlItem.verify);*/ return 0; }
static __hdle _find_first_file(const char* const dirPath, WIN32_FIND_DATA& findFileData) { HANDLE hdle = INVALID_HANDLE_VALUE; TCHAR szDir[MAX_PATH]; size_t length_of_arg; // Check that the input path plus 3 is not longer than MAX_PATH. // Three characters are for the "\*" plus NULL appended below. StringCchLength(dirPath, MAX_PATH, &length_of_arg); if (length_of_arg > (MAX_PATH - 3)) { _tprintf(TEXT("\nDirectory path is too long.\n")); return NULL; } _tprintf(TEXT("\nTarget directory is %s\n\n"), dirPath); // Prepare string for use with FindFile functions. First, copy the // string to a buffer, then append '\*' to the directory name. StringCchCopy(szDir, MAX_PATH, dirPath); StringCchCat(szDir, MAX_PATH, TEXT("\\*")); hdle = FindFirstFile(szDir, &findFileData); if(INVALID_HANDLE_VALUE == hdle){ errorP("Fail to open dir\n"); return NULL; } return hdle; }
int traverse_dir(const char** const dirPath, __hdle *hdle, char* filePath) { DIR* hDir = (DIR*)*hdle; const char* fileName = NULL; if(!hDir) { hDir = opendir(*dirPath); if(!hDir){ errorP("Fail to open dir(%s), strerror(%s)\n", *dirPath, strerror(errno)); return __LINE__; } *hdle = hDir; } do{ struct dirent* dirEntry = NULL; dirEntry = readdir(hDir); if(!dirEntry){ debugP("travese end.\n"); closedir(hDir); return __LINE__; } fileName = dirEntry->d_name; }while(!strcmp(".", fileName) || !strcmp("..", fileName)); sprintf(filePath, "%s/%s", *dirPath, fileName); return 0; }
int get_dir_filenums(const char * const dirPath) { WIN32_FIND_DATA findFileData; HANDLE hdle = INVALID_HANDLE_VALUE; int fileNum = 0; int ret = 0; TCHAR szDir[MAX_PATH]; size_t length_of_arg; hdle = _find_first_file(dirPath, findFileData); if(INVALID_HANDLE_VALUE == hdle){ errorP("Fail to open dir %s\n", szDir); return __LINE__; } do { if(strcmp(findFileData.cFileName, ".") && strcmp(findFileData.cFileName, "..")) { ++fileNum; } } while (FindNextFile(hdle, &findFileData)); _ok: if(INVALID_HANDLE_VALUE != hdle)FindClose(hdle); return fileNum; }
static int do_unpackimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { void *addr; __u32 pos = 0; const AmlResItemHead_t *pack_header_p = NULL; char env_name[IH_NMLEN*2]; char env_data[IH_NMLEN*2]; AmlResImgHead_t* pImgHead = NULL; int rc = 0; int imgVersion = -1; if (argc < 2) { cmd_usage(cmdtp); return __LINE__; } addr = (void *)simple_strtoul (argv[1], NULL, 16); pImgHead = (AmlResImgHead_t*)addr; rc = _img_unpack_check_img_header(pImgHead, &imgVersion, &pos); if(rc){ errorP("Err res header.\n"); return __LINE__; } MsgP("ver=%d\n", imgVersion); do{ pack_header_p = (AmlResItemHead_t*)(addr + pos); if(IH_MAGIC != pack_header_p->magic){ errorP("Item magic error.\n"); return __LINE__; } sprintf(env_name, "%s_offset", pack_header_p->name); sprintf(env_data, "0x%x", (unsigned int)(addr+pack_header_p->start)); setenv(env_name, env_data); sprintf(env_name, "%s_size", pack_header_p->name); sprintf(env_data, "0x%x", pack_header_p->size); setenv(env_name, env_data); }while(pos = pack_header_p->next); return 0; }
//is the item source is duplicated with other item //i.e, item data is empty //return value: 0/1 is ok, <0 is failed static int is_item_backup_for_other_item(HIMAGEITEM hItem, int* backItemId) { ItemInfo *item = (ItemInfo*)hItem; if(!hItem){ errorP("NULL item handle\n"); return -1; } *backItemId = item->backUpItemId; return item->isBackUpItem; }
//@imgVersion: if success, then 0--> oldest version; 1-->img header + n * (item header + item body); 2 --> img header + n * item header + n * item body static int _img_unpack_check_img_header(FILE* fdResImg, const char* const path_src, int needCheckCrc, AmlResImgHead_t* pImgHead, int* imgVersion) { int ret = 0; const unsigned ImgFileSz = get_filesize(path_src); if(ImgFileSz <= IMG_HEAD_SZ){ errorP("file size 0x%x too small\n", ImgFileSz); return __LINE__; } unsigned thisReadSz = ITEM_READ_BUF_SZ > ImgFileSz ? ImgFileSz : ITEM_READ_BUF_SZ; unsigned actualReadSz = 0; actualReadSz = fread(pImgHead, 1, thisReadSz, fdResImg); if(actualReadSz != thisReadSz){ errorP("Want to read 0x%x, but only read 0x%x\n", thisReadSz, actualReadSz); return __LINE__; } if(!strncmp(AML_RES_IMG_V1_MAGIC, (char*)pImgHead->magic, AML_RES_IMG_V1_MAGIC_LEN)) {//new version magic matched if(ImgFileSz != pImgHead->imgSz){ errorP("error, image size in head 0x%x != fileSz 0x%x\n", pImgHead->imgSz, ImgFileSz); return __LINE__; } if(AML_RES_IMG_VERSION_V2 < pImgHead->version){ errorP("Error, version 0x%x not supported\n", pImgHead->version); return __LINE__; } *imgVersion = pImgHead->version; if(needCheckCrc) { ret = check_img_crc(fdResImg, 4, pImgHead->crc); if(ret){ errorP("Error when check crc\n"); return __LINE__; } } unsigned ImgHeadSz = IMG_HEAD_SZ; if(AML_RES_IMG_VERSION_V2 == pImgHead->version) ImgHeadSz += pImgHead->imgItemNum * ITEM_HEAD_SZ; fseek(fdResImg, ImgHeadSz, SEEK_SET);//seek escape the image header to prepare for reading item header } else { AmlResItemHead_t* pItemHeadInfo = (AmlResItemHead_t*)pImgHead; debugP("magic error, try old version image.\n"); if(IH_MAGIC != pItemHeadInfo->magic){ errorP("magic err, old version image header not item header!\n"); return __LINE__; } *imgVersion = 0; fseek(fdResImg, 0, SEEK_SET);//seek escape the image header to prepare for reading item header } debugP("res-img ver is 0x%x\n", *imgVersion); return 0; }
int traverse_dir(const char** const dirPath, __hdle *hDir, char* filePath) { WIN32_FIND_DATA findFileData; HANDLE hdle = INVALID_HANDLE_VALUE; int ret = 0; if (!*hDir)//not open yet! { hdle = _find_first_file(*dirPath, findFileData); if(INVALID_HANDLE_VALUE == hdle){ errorP("Fail to find first file in dir(%s)\n", *dirPath); return __LINE__; } *hDir = hdle; if(strcmp(".", findFileData.cFileName) && strcmp("..", findFileData.cFileName))goto _ok; } hdle = *hDir; do { ret = !FindNextFile(hdle, &findFileData); if(ret){ debugP("Find end.\n"); FindClose(hdle); return __LINE__; } } while(!strcmp(".", findFileData.cFileName) || !strcmp("..", findFileData.cFileName) ); _ok: //debugP("file %s\n", findFileData.cFileName); if(MAX_PATH < strlen(findFileData.cFileName)){ errorP("Buffer samll\n"); FindClose(hdle); return __LINE__; } sprintf(filePath, "%s\\%s", *dirPath, findFileData.cFileName); return ret; }
EXPORT #endif int image_unpack(const char* imagefile,const char *outpath) { int ret = 0; unsigned int itemCountTotal = 0; unsigned int nItem = 0; unsigned int write_bytes = 0; char main_type[32] = {0}; char sub_type[32] = {0}; char outfile[512] = {0}; char cfgfile[128] = {0}; char buff[256] = {0}; #ifdef BUILD_DLL if(ImageDecoder->AmlFirmwareImg == NULL){ ImageDecoder->AmlFirmwareImg = (AmlFirmwareImg_t*)malloc(sizeof(AmlFirmwareImg_t)); if(ImageDecoder->AmlFirmwareImg == NULL){ fprintf(stderr,"not enough memory\n"); return -1; } } #endif if(outpath){ strcpy(outfile,outpath); strcat(outfile,"\\"); strcpy(cfgfile,outfile); } strcat(cfgfile,"image.cfg"); HIMAGE hImage = image_open(imagefile); if(image_check(hImage) < 0){ fprintf(stderr,"the image check fail!!\n"); return -1; }else{ printf("the image check ok!\n"); } itemCountTotal = image_get_item_count(hImage,NULL); const unsigned itemCountVerify = image_get_item_count(hImage, "VERIFY"); const unsigned itemCountNormal = itemCountTotal - itemCountVerify * 2; debugP("item cnt:total[%u], normal[%u], verify[%u]\n", itemCountTotal, itemCountNormal, itemCountVerify); char *unPackBuf = (char*)malloc(RW_MAX_SIZE); if(unPackBuf==NULL){ fprintf(stderr,"allocate memccpy failed at %s %d \n", __FILE__,__LINE__); return __LINE__; } FILE *fp_cfg = fopen(cfgfile,"wb+"); if(fp_cfg==NULL){ fprintf(stderr,"create image.cfg failed ! [%s] \n",strerror(errno)); return __LINE__; } fwrite(TAG_NORMALLIST,1,strlen(TAG_NORMALLIST), fp_cfg); fwrite("\r\n", 1, 2, fp_cfg); for(nItem = 0; nItem < itemCountTotal; ++nItem) { if(image_get_next_item(hImage,nItem,main_type,sub_type) < 0){ ret = -1; break; } if(!strcmp("VERIFY", main_type)) { continue;//skip verify item } if(nItem == itemCountNormal)//[List_normal]ends, [List_verify] starts { fwrite("\r\n", 1, 2, fp_cfg); fwrite(TAG_VERIFYLIST,1,strlen(TAG_VERIFYLIST), fp_cfg); fwrite("\r\n", 1, 2, fp_cfg); } memset(outfile,0,64); if(outpath){ strcpy(outfile,outpath); strcat(outfile,"/"); } strcat(outfile,sub_type); strcat(outfile,"."); strcat(outfile,main_type); debugP("out file: %s \n",outfile);//sub_type.main_type HIMAGEITEM hItem = image_open_item(hImage,main_type,sub_type); if(hItem == NULL){ fprintf(stderr,"open item[%s, %s] failed!\n", main_type, sub_type); ret = -1; break; } int backUpItemId = 0; int itemIsBacked = is_item_backup_for_other_item(hItem, &backUpItemId); if(itemIsBacked < 0){ errorP("Fail to in test is_item_backup_for_other_item\n"); ret = __LINE__; break; } if(itemIsBacked)//item is back item { char* CfgLine = (char*)unPackBuf; char srcBackItemMainType[32]; char srcBackItemSubType[32]; if(image_get_next_item(hImage, backUpItemId, srcBackItemMainType, srcBackItemSubType)){ errorP("Fail to get the backui item head\n"); ret = __LINE__; break; } sprintf(CfgLine, IMG_CFG_LINE, srcBackItemSubType, srcBackItemMainType, main_type, sub_type); fwrite(CfgLine,1,strlen(CfgLine), fp_cfg); continue; } FILE *fp_out = fopen(outfile,"wb+"); if(fp_out == NULL){ fprintf(stderr,"failed to create out file : %s \n",outfile); ret = -1; break; } while((write_bytes = image_read_item_data(hImage, hItem, unPackBuf, RW_MAX_SIZE))>0) { if(fwrite(unPackBuf,1,write_bytes,fp_out)!=write_bytes){ fprintf(stderr,"write to image file fail! [%s] \n",strerror(errno)); ret = -1; break; } } fclose(fp_out); image_close_item(hItem); char* CfgLine = (char*)unPackBuf; sprintf(CfgLine, IMG_CFG_LINE, sub_type, main_type, main_type, sub_type); fwrite(CfgLine,1,strlen(CfgLine), fp_cfg); } free(unPackBuf); fclose(fp_cfg); fp_cfg = NULL; #ifdef BUILD_DLL if(ImageDecoder->AmlFirmwareImg){ free(ImageDecoder->AmlFirmwareImg); ImageDecoder->AmlFirmwareImg = NULL; } #endif return ret; }
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; }
DLL_API #endif// #ifdef BUILD_DLL int res_img_unpack(const char* const path_src, const char* const unPackDirPath, int needCheckCrc) { char* itemReadBuf = NULL; FILE* fdResImg = NULL; int ret = 0; AmlResImgHead_t* pImgHead = NULL; int imgVersion = -1; fdResImg = fopen(path_src, "rb"); if(!fdResImg){ errorP("Fail to open res image at path %s\n", path_src); return __LINE__; } itemReadBuf = new char[ITEM_READ_BUF_SZ * 2]; if(!itemReadBuf){ errorP("Fail to new buffer at size 0x%x\n", ITEM_READ_BUF_SZ*2); fclose(fdResImg), fdResImg = NULL; return __LINE__; } pImgHead = (AmlResImgHead_t*)(itemReadBuf + ITEM_READ_BUF_SZ); ret = _img_unpack_check_img_header(fdResImg, path_src, needCheckCrc, pImgHead, &imgVersion); if(ret){ errorP("Fail at check image header\n"); delete[] itemReadBuf, itemReadBuf = NULL; fclose(fdResImg), fdResImg = NULL; return __LINE__; } //for each loop: // 1, read item body and save as file; // 2, get next item head const unsigned itemAlignSz = AML_RES_IMG_ITEM_ALIGN_SZ; const unsigned itemAlignMod = itemAlignSz - 1; const unsigned itemSzAlignMask = ~itemAlignMod; unsigned totalReadItemNum = 0; const AmlResItemHead_t* pItemHead = NULL; do{ char itemFullPath[MAX_PATH*2];//TODO:512 is enough ?? FILE* fp_item = NULL; pItemHead = _img_unpack_get_item_header(imgVersion, pImgHead, totalReadItemNum++, fdResImg); if(!pItemHead){ errorP("Fail to get item header at index %d\n", totalReadItemNum - 1); goto _exit; } sprintf(itemFullPath, "%s/%s", unPackDirPath, pItemHead->name); debugP("item %s\n", itemFullPath); fp_item = fopen(itemFullPath, "wb"); if(!fp_item){ errorP("Fail to create file %s, strerror(%s)\n", itemFullPath, strerror(errno)); ret = __LINE__; goto _exit; } const unsigned thisItemBodySz = pItemHead->size; const unsigned thisItemBodyOccupySz = (thisItemBodySz & itemSzAlignMask) + itemAlignSz; const unsigned stuffLen = thisItemBodyOccupySz - thisItemBodySz; for(unsigned itemTotalReadLen = 0; itemTotalReadLen < thisItemBodyOccupySz; ) { const unsigned leftLen = thisItemBodyOccupySz - itemTotalReadLen; const unsigned thisReadSz = min(leftLen, ITEM_READ_BUF_SZ); unsigned actualReadSz = fread(itemReadBuf, 1, thisReadSz, fdResImg); if(thisReadSz != actualReadSz){ errorP("thisReadSz 0x%x != actualReadSz 0x%x\n", thisReadSz, actualReadSz); ret = __LINE__;goto _exit; } itemTotalReadLen += thisReadSz; const unsigned thisWriteSz = itemTotalReadLen < thisItemBodySz ? thisReadSz : (thisReadSz - stuffLen); actualReadSz = fwrite(itemReadBuf, 1, thisWriteSz, fp_item); if(thisWriteSz != actualReadSz){ errorP("want write 0x%x, but 0x%x\n", thisWriteSz, actualReadSz); ret = __LINE__;goto _exit; } } fclose(fp_item), fp_item = NULL; }while(pItemHead->next); _exit: if(itemReadBuf)delete[] itemReadBuf, itemReadBuf = NULL; if(fdResImg)fclose(fdResImg), fdResImg = NULL; return ret; }