酷派CPB升级文件封包解包

原帖:http://my.oschina.net/osbin/blog/266431

解包recovery:点这里

此前入手了部酷派8730L,无奈搜遍整个互联网寻求ROOT的方法以及用了各种ROOT工具均以失败告终。于是决定研究下酷派的CPB升级文件:4.3.066.P3.140417.8730L.CPB。以为解包出来改改某个文件再封包,然后刷机可以解决ROOT的问题(后来事实证明太天真啦,CDS这个升级工具根本就没法用,让我机器变砖头的机会都不给),于是下载个cpb解包封包工具试下,没想到又失败了。没办法只能参考找到的部分cpb文件格式资料,自己写解包封包工具。OD动态调试CDS升级工具(版本:V4.29_140116_01),发现cpb文件验证过程在dChkData.dll中完成,研究一番,写了个自己的CPB解包封包工具,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <stddef.h>
 
typedef char int8 ;
typedef unsigned char uint8 ;
typedef short int16 ;
typedef unsigned short uint16 ;
typedef int int32 ;
typedef unsigned int uint32 ;
typedef __int64 int64 ;
typedef unsigned __int64 uint64 ;
 
typedef struct tagCPBHEADER
{
    char cp_magic[2] ;      //'CP'
    uint8 cp_version[2] ;   //CPB文件版本
    uint16 correct[6] ;     //12字节校正用 
    uint8 unknown[32] ;     //未知32字节
    char model[32] ;        //适用的手机型号,如"8730L" 
    char hardVersion[16] ;  //适用的硬件版本号,如"P3"
    char version[64] ;      //适用的版本号,如"4.3.066.P3.140417.8730L"
    char romFrom[256] ;     //
    uint32 imgHdrEndPos ;   //Image Header停止的位置,这样就能确定Image Header大小
    uint8 reverse[128] ;    //保留
    uint32 checkSum ;       //校验和(CRC16) 
}CPBHEADER, *LPCPBHEADER ;
 
typedef struct tagIMAGEHEADER
{
    char fileName[64] ;
    uint32 imageOffset ;
    uint32 imageSize ;
    uint32 checkSum ;//CRC16
}IMAGEHEADER, *LPIMAGEHEADER;
 
const uint16 CRC16Tab[256] =
{
    0x0000L, 0x1021L, 0x2042L, 0x3063L,
    0x4084L, 0x50a5L, 0x60c6L, 0x70e7L,
    0x8108L, 0x9129L, 0xa14aL, 0xb16bL,
    0xc18cL, 0xd1adL, 0xe1ceL, 0xf1efL,
    0x1231L, 0x0210L, 0x3273L, 0x2252L,
    0x52b5L, 0x4294L, 0x72f7L, 0x62d6L,
    0x9339L, 0x8318L, 0xb37bL, 0xa35aL,
    0xd3bdL, 0xc39cL, 0xf3ffL, 0xe3deL,
    0x2462L, 0x3443L, 0x0420L, 0x1401L,
    0x64e6L, 0x74c7L, 0x44a4L, 0x5485L,
    0xa56aL, 0xb54bL, 0x8528L, 0x9509L,
    0xe5eeL, 0xf5cfL, 0xc5acL, 0xd58dL,
    0x3653L, 0x2672L, 0x1611L, 0x0630L,
    0x76d7L, 0x66f6L, 0x5695L, 0x46b4L,
    0xb75bL, 0xa77aL, 0x9719L, 0x8738L,
    0xf7dfL, 0xe7feL, 0xd79dL, 0xc7bcL,
    0x48c4L, 0x58e5L, 0x6886L, 0x78a7L,
    0x0840L, 0x1861L, 0x2802L, 0x3823L,
    0xc9ccL, 0xd9edL, 0xe98eL, 0xf9afL,
    0x8948L, 0x9969L, 0xa90aL, 0xb92bL,
    0x5af5L, 0x4ad4L, 0x7ab7L, 0x6a96L,
    0x1a71L, 0x0a50L, 0x3a33L, 0x2a12L,
    0xdbfdL, 0xcbdcL, 0xfbbfL, 0xeb9eL,
    0x9b79L, 0x8b58L, 0xbb3bL, 0xab1aL,
    0x6ca6L, 0x7c87L, 0x4ce4L, 0x5cc5L,
    0x2c22L, 0x3c03L, 0x0c60L, 0x1c41L,
    0xedaeL, 0xfd8fL, 0xcdecL, 0xddcdL,
    0xad2aL, 0xbd0bL, 0x8d68L, 0x9d49L,
    0x7e97L, 0x6eb6L, 0x5ed5L, 0x4ef4L,
    0x3e13L, 0x2e32L, 0x1e51L, 0x0e70L,
    0xff9fL, 0xefbeL, 0xdfddL, 0xcffcL,
    0xbf1bL, 0xaf3aL, 0x9f59L, 0x8f78L,
    0x9188L, 0x81a9L, 0xb1caL, 0xa1ebL,
    0xd10cL, 0xc12dL, 0xf14eL, 0xe16fL,
    0x1080L, 0x00a1L, 0x30c2L, 0x20e3L,
    0x5004L, 0x4025L, 0x7046L, 0x6067L,
    0x83b9L, 0x9398L, 0xa3fbL, 0xb3daL,
    0xc33dL, 0xd31cL, 0xe37fL, 0xf35eL,
    0x02b1L, 0x1290L, 0x22f3L, 0x32d2L,
    0x4235L, 0x5214L, 0x6277L, 0x7256L,
    0xb5eaL, 0xa5cbL, 0x95a8L, 0x8589L,
    0xf56eL, 0xe54fL, 0xd52cL, 0xc50dL,
    0x34e2L, 0x24c3L, 0x14a0L, 0x0481L,
    0x7466L, 0x6447L, 0x5424L, 0x4405L,
    0xa7dbL, 0xb7faL, 0x8799L, 0x97b8L,
    0xe75fL, 0xf77eL, 0xc71dL, 0xd73cL,
    0x26d3L, 0x36f2L, 0x0691L, 0x16b0L,
    0x6657L, 0x7676L, 0x4615L, 0x5634L,
    0xd94cL, 0xc96dL, 0xf90eL, 0xe92fL,
    0x99c8L, 0x89e9L, 0xb98aL, 0xa9abL,
    0x5844L, 0x4865L, 0x7806L, 0x6827L,
    0x18c0L, 0x08e1L, 0x3882L, 0x28a3L,
    0xcb7dL, 0xdb5cL, 0xeb3fL, 0xfb1eL,
    0x8bf9L, 0x9bd8L, 0xabbbL, 0xbb9aL,
    0x4a75L, 0x5a54L, 0x6a37L, 0x7a16L,
    0x0af1L, 0x1ad0L, 0x2ab3L, 0x3a92L,
    0xfd2eL, 0xed0fL, 0xdd6cL, 0xcd4dL,
    0xbdaaL, 0xad8bL, 0x9de8L, 0x8dc9L,
    0x7c26L, 0x6c07L, 0x5c64L, 0x4c45L,
    0x3ca2L, 0x2c83L, 0x1ce0L, 0x0cc1L,
    0xef1fL, 0xff3eL, 0xcf5dL, 0xdf7cL,
    0xaf9bL, 0xbfbaL, 0x8fd9L, 0x9ff8L,
    0x6e17L, 0x7e36L, 0x4e55L, 0x5e74L,
    0x2e93L, 0x3eb2L, 0x0ed1L, 0x1ef0L
};
 
uint32 CRC16(const uint8 *pData, uint32 nSize, uint32 uiCrc)
{
    uint32 i;
 
    for (i=0; i<nSize; i++)
        uiCrc = (uiCrc << 8) ^ (uint16)CRC16Tab[(uint8)(uiCrc >> 8) ^ pData[i]];
    return uiCrc ;
}
 
int32 MkdirRecursive( char* path )
{
    char *p, ch;
    if( access( path, 0 ) == 0 )
        return 0;
    for( p=path; *p; p++ )
    {
        if( p>path && ((*p == '/') || (*p == '\\')) )
        {
            ch = *p ;
            *p = 0;
            if( access( path, 0 ) != 0 )
            {
                if( mkdir( path ) != 0 )
                    return -1;
            }
            *p = ch ;
        }
    }
    return mkdir( path );
}
 
void usage(void)
{
    printf("本工具限用于酷派CPB1.7版本。即cpb文件头4字节为\"CP\\x01\\x07\"。\n") ;
    printf("usage: cpbtool.exe\n"
        "  [-l <CPB文件> <列表文件>]\n\t#列出CPB的所有文件为列表文件。\n"
        "  [-u <CPB文件> <路径>]\n\t#解压CPB文件到指定目录。\n"
        "  [-p <型号> <硬件版本> <版本号> <路径> <列表文件> <CPB文件>]\n\t#打包指定目录下的文件为CPB包。\n"
    ) ;
    printf("Ex: cpbtool.exe -l ex.cpb list.txt\n") ;
    printf("    cpbtool.exe -u ex.cpb .\\8730L\n") ;
    printf("    cpbtool.exe -p 8730L P3 4.3.066.P3.140417.8730L .\\8730L list.txt new.cpb\n") ;
}
 
void PrintCpbHeader(LPCPBHEADER pHdr)
{
    char buf[512] ;
    printf("CPB文件版本:%d.%d\n", pHdr->cp_version[0], pHdr->cp_version[1]) ;
    strncpy(buf, pHdr->model, sizeof(buf)) ;
    printf("适用的手机型号:%s\n", buf) ;
    strncpy(buf, pHdr->hardVersion, sizeof(buf)) ;
    printf("适用的硬件版本号:%s\n", buf) ;
    strncpy(buf, pHdr->version, sizeof(buf)) ;
    printf("适用的版本号:%s\n", buf) ;
    printf("映像文件头大小:%u,每个76字节,共%u个。\n", 
        pHdr->imgHdrEndPos-sizeof(CPBHEADER), (pHdr->imgHdrEndPos-sizeof(CPBHEADER)) / sizeof(IMAGEHEADER)) ;
    printf("校验和:0x%08X\n\n", pHdr->checkSum) ;
}
 
void CreateListFile(const char *lpszCpb, const char *lpszList)
{
    FILE *fcpb = NULL ;
    FILE *flst = NULL ;
    CPBHEADER cpbHdr ;
    LPIMAGEHEADER pImgHdr = NULL ;
    size_t sz ;
    uint32 nImgSize, nImgCount, i ;
     
    fcpb = fopen(lpszCpb, "rb") ;
    if (fcpb == NULL)
    {
        printf("打开文件“%s”失败!\n", lpszCpb) ;
        return 0 ;
    }
    sz = fread(&cpbHdr, sizeof(cpbHdr), 1, fcpb);
    if(sz != 1 || cpbHdr.cp_magic[0] != 'C' || cpbHdr.cp_magic[1] != 'P' ||
        cpbHdr.imgHdrEndPos < sizeof(cpbHdr))
    {
        fclose(fcpb) ;
        printf("不是有效的CPB文件!\n") ;
        return 0;
    }
    if(cpbHdr.cp_version[0] != 0x01 || cpbHdr.cp_version[1] != 0x07)
    {
        printf("本工具限用于酷派CPB1.7版本。即cpb文件头4字节为\"CP\\x01\\x07\"。\n") ;
        return ;
    }
    PrintCpbHeader(&cpbHdr) ;
    nImgSize = cpbHdr.imgHdrEndPos - sizeof(CPBHEADER) ;
    nImgCount = (cpbHdr.imgHdrEndPos - sizeof(CPBHEADER)) / sizeof(IMAGEHEADER) ;
    pImgHdr = (LPIMAGEHEADER)malloc(nImgSize) ;
    if(pImgHdr == NULL)
    {
        fclose(fcpb) ;
        printf("分配内存%u字节失败,可能是文件不合法!\n", nImgSize) ;
        return 0 ;
    }
    sz = fread(pImgHdr, nImgSize, 1, fcpb) ;
    if(sz != 1)
    {
        free(pImgHdr) ;
        fclose(fcpb) ;
        printf("不是有效的CPB文件!\n") ;
        return 0 ;
    }
    flst = fopen(lpszList, "w") ;
    if(flst != NULL)
    {
        for(i=0; i<nImgCount; i++)
            fprintf(flst, "%s\n", pImgHdr[i].fileName) ;
        fclose(flst) ;
        printf("列表文件‘%s’创建成功!\n", lpszList) ;
    }
    else
        printf("列表文件‘%s’创建失败!\n", lpszList) ;
    free(pImgHdr) ;
    fclose(fcpb) ;
    return 0 ;
}
 
void PrintfImageHeader(LPIMAGEHEADER pImgHdr)
{
    char buf[128] ;
    strncpy(buf, pImgHdr->fileName, sizeof(buf)) ;
    printf("文件名:%s\n", buf) ;
    printf("偏移:0x%08X\n", pImgHdr->imageOffset) ;
    printf("大小:0x%08X(%u)\n", pImgHdr->imageSize, pImgHdr->imageSize) ;
    printf("校验和:0x%08X\n", pImgHdr->checkSum) ;
}
 
void ImageHeaderCorrectPosSize(LPIMAGEHEADER pImgHdr, int32 idx, uint32 uiCorrect)
{
    uint32 iPos, nSize, iTemp ;
    uint8 bt1, bt2, bt3, bt4 ;
    bt1 = (uint8)idx + (uint8)uiCorrect ;
    bt2 = (uint8)idx + (uint8)(uiCorrect >> 8) ;
    bt3 = (uint8)idx + (uint8)(uiCorrect >> 16) ;
    bt4 = (uint8)idx + (uint8)(uiCorrect >> 24) ;
    iPos = pImgHdr->imageOffset ;
    nSize = pImgHdr->imageSize ;
    iPos = (uint8)(bt3 ^ iPos) | 
        (uint16)((uint8)(bt4 ^ (uint8)(iPos >> 8)) << 8) | 
        (((uint8)(bt1 ^ ((uint32)iPos >> 16)) | 
        (uint16)((uint8)(bt2 ^ (uint8)(iPos >> 24)) << 8)) << 16);
    iTemp = (uint8)(bt3 ^ nSize);
    nSize = iTemp | (uint16)((uint8)(bt4 ^ (uint8)(nSize >> 8)) << 8) | 
        (((uint8)(bt1 ^ ((uint32)nSize >> 16)) | 
        (uint16)((uint8)(bt2 ^ (uint8)(nSize >> 24)) << 8)) << 16);
    pImgHdr->imageOffset = iPos ;
    pImgHdr->imageSize = nSize ;
}
 
void DumpFile(FILE *fcpb, const char *lpszPath, LPIMAGEHEADER pImgHdrs, uint32 nImgCount)
{
    FILE *fImg ;
    char szFile[512] ;
    uint8 *pBuf ;
    uint32 i, iBufSize, nLen, uiCrc = 0;
    if(pImgHdrs == NULL) return ;
    iBufSize = 1024 * 1024 ; //1MiB
    pBuf = (uint8 *)malloc(iBufSize) ;
    if(pBuf == NULL)
    {
        printf("DumpFile 分配内存失败!\n") ;
        return ;
    }
    for(i=0; i<nImgCount; i++)
    {
        PrintfImageHeader(&pImgHdrs[i]) ;
        if(pImgHdrs[i].imageSize == 0) continue ;
        if(fseek(fcpb, pImgHdrs[i].imageOffset, SEEK_SET) != 0)
        {
            printf("生成文件“%s”失败!原CPB文件无法定位到:0x%08X\n\n", 
                pImgHdrs[i].fileName, pImgHdrs[i].imageOffset) ;
            continue ;
        }
        sprintf(szFile, "%s%s", lpszPath, pImgHdrs[i].fileName) ;
        fImg = fopen(szFile, "wb") ;
        if(fImg == NULL)
        {
            printf("创建文件‘%s’失败!\n", szFile) ;
            continue ;
        }
        for(nLen=0, uiCrc=0; (nLen+iBufSize)<=pImgHdrs[i].imageSize; nLen+=iBufSize)
        {
            if(fread(pBuf, iBufSize, 1, fcpb) != 1)
            {
                printf("生成文件“%s”失败!原CPB文件有误!\n\n", pImgHdrs[i].fileName) ;
                break ;
            }
            uiCrc = CRC16(pBuf, iBufSize, uiCrc) ;
            fwrite(pBuf, iBufSize, 1, fImg) ;
        }
        nLen = pImgHdrs[i].imageSize - nLen ;
        if(nLen > 0)
        {
            if(fread(pBuf, nLen, 1, fcpb) == 1)
            {
                uiCrc = CRC16(pBuf, nLen, uiCrc) ;
                fwrite(pBuf, nLen, 1, fImg) ;
            }
            else
                printf("生成文件“%s”失败!原CPB文件有误!\n\n", pImgHdrs[i].fileName) ;
        }
        fclose(fImg) ;
        if(uiCrc != pImgHdrs[i].checkSum)
            printf("校验失败!生成的文件“%s”非法!原CPB文件有误!\n\n", pImgHdrs[i].fileName) ;
        else
            printf("文件“%s”创建成功!\n\n", pImgHdrs[i].fileName) ;
    }
    free(pBuf) ;
}
 
void UnpackCpb(const char *lpszCpb, const char *lpszPath)
{
    FILE *fcpb = NULL;
    CPBHEADER cpbHdr ;
    LPIMAGEHEADER pImgHdr = NULL ;
    size_t sz ;
    uint32 nImgSize, nImgCount, i, uiCrc, uiCorrect ;
    uint64 uiVal64 ;
    char szPath[264] ;
     
    if(lpszPath == NULL || lpszPath[0]=='\0')
    {
        printf("无效目录!\n") ;
        return ;
    }
    strncpy(szPath, lpszPath, sizeof(szPath)) ;
    if(MkdirRecursive(szPath) != 0)
    {
        printf("创建目录‘%s’失败!\n", lpszPath) ;
        return ;
    }
    sz = strlen(szPath) ;
    if(szPath[sz-1] != '/' && szPath[sz-1] != '\\')
    {
        szPath[sz] = '\\' ;
        szPath[sz+1] = '\0' ;
    }
     
    fcpb = fopen(lpszCpb, "rb") ;
    if (fcpb == NULL)
    {
        printf("打开文件“%s”失败!\n", lpszCpb) ;
        return ;
    }
    sz = fread(&cpbHdr, sizeof(cpbHdr), 1, fcpb);
    if(sz != 1 || cpbHdr.cp_magic[0] != 'C' || cpbHdr.cp_magic[1] != 'P' ||
        cpbHdr.imgHdrEndPos < sizeof(cpbHdr))
    {
        fclose(fcpb) ;
        printf("不是有效的CPB文件!\n") ;
        return ;
    }
    if(cpbHdr.cp_version[0] != 0x01 || cpbHdr.cp_version[1] != 0x07)
    {
        printf("本工具限用于酷派CPB1.7版本。即cpb文件头4字节为\"CP\\x01\\x07\"。\n") ;
        return ;
    }
    uiCorrect = 0 ;
    for(i=0; i<6; i++)
        uiCorrect += cpbHdr.correct[i] ;
    uiVal64 = (uint64)0x66666667 * uiCorrect ;
    uiCorrect = (uint32)((int32)(uiVal64 >> 32)) >> 1 ;
    uiCorrect = (uint16)((uiCorrect >> 31) + uiCorrect) ;
    uiCorrect = (uiCorrect-cpbHdr.correct[3]) | ((uiCorrect-cpbHdr.correct[4]) << 16) ;
    uiCrc = CRC16((uint8 *)&cpbHdr, sizeof(cpbHdr)-4, 0) ;
    PrintCpbHeader(&cpbHdr) ;
    nImgSize = cpbHdr.imgHdrEndPos - sizeof(CPBHEADER) ;
    nImgCount = (cpbHdr.imgHdrEndPos - sizeof(CPBHEADER)) / sizeof(IMAGEHEADER) ;
    pImgHdr = (LPIMAGEHEADER)malloc(nImgSize) ;
    if(pImgHdr == NULL)
    {
        fclose(fcpb) ;
        printf("分配内存%u字节失败,可能是文件不合法!\n", nImgSize) ;
        return ;
    }
    sz = fread(pImgHdr, nImgSize, 1, fcpb) ;
    if(sz != 1)
    {
        free(pImgHdr) ;
        fclose(fcpb) ;
        printf("不是有效的CPB文件!\n") ;
        return ;
    }
    for(i=0; i<nImgCount; i++)
    {
        ImageHeaderCorrectPosSize(&pImgHdr[i], i, uiCorrect);
        uiCrc = CRC16((uint8 *)&pImgHdr[i], sizeof(IMAGEHEADER), uiCrc) ;
    }
    uiCrc += cpbHdr.cp_version[1] ;
    if(uiCrc != cpbHdr.checkSum)
    {
        free(pImgHdr) ;
        fclose(fcpb) ;
        printf("校验失败!期望的CPB校验值:0x%.8X,实际值:0x%.8X\n",
            cpbHdr.checkSum, uiCrc) ;
        return ;
    }
    DumpFile(fcpb, szPath, pImgHdr, nImgCount) ;
    free(pImgHdr) ;
    fclose(fcpb) ;
    return ;
}
 
void TrimCRLF(char *str)
{
    int32 nLen ;
    nLen = strlen(str) - 1 ;
    for(; nLen>=0; nLen--)
    {
        if(str[nLen]=='\r' || str[nLen]=='\n')
            str[nLen] = '\0' ;
        else
            break ;
    }
}
 
void InitCpbHeader(LPCPBHEADER pCpbHdr, const char *lpszModel, const char *lpszHardVer,
    const char *lpszVersion, const char *lpszFrom)
{
    uint16 arrCorrect[6] = {0x005C, 0x0836, 0x0828, 0x083A, 0x0809, 0x0825} ;
    uint8 unknown[33] = "\x55\x35\x25\x27\x28\x59\x2D\x11\x32\x2D\x24\x3D\x5B\x2B\x3F\x11"
                        "\x0C\x16\x07\x01\x11\x16\x10\x03\x06\x13\x03\x1C\x01\x06\x00\x00" ;
    memset(pCpbHdr, 0, sizeof(CPBHEADER)) ;
    pCpbHdr->cp_magic[0] = 'C' ;
    pCpbHdr->cp_magic[1] = 'P' ;
    pCpbHdr->cp_version[0] = 0x01 ;
    pCpbHdr->cp_version[1] = 0x07 ;
    memcpy(pCpbHdr->correct, arrCorrect, sizeof(arrCorrect)) ;
    memcpy(pCpbHdr->unknown, unknown, sizeof(pCpbHdr->unknown)) ;
    strncpy(pCpbHdr->model, lpszModel, sizeof(pCpbHdr->model)) ;
    strncpy(pCpbHdr->hardVersion, lpszHardVer, sizeof(pCpbHdr->hardVersion)) ;
    strncpy(pCpbHdr->version, lpszVersion, sizeof(pCpbHdr->version)) ;
    strncpy(pCpbHdr->romFrom, lpszFrom, sizeof(pCpbHdr->romFrom)) ;
}
 
uint32 WriteImageHeaders(FILE *fcpb, LPIMAGEHEADER pImgHdrs, int32 nCount, uint32 uiCorrect, uint32 uiCrc)
{
    uint32 uiOffset, uiSize ;
    int32 i ;
    for(i=0; i<nCount; i++)
    {
        uiOffset = pImgHdrs[i].imageOffset ;
        uiSize = pImgHdrs[i].imageSize ;
        uiCrc = CRC16(&pImgHdrs[i], sizeof(IMAGEHEADER), uiCrc) ;
        ImageHeaderCorrectPosSize(&pImgHdrs[i], i, uiCorrect) ;
        fwrite(&pImgHdrs[i], sizeof(IMAGEHEADER), 1, fcpb) ;
        pImgHdrs[i].imageOffset = uiOffset ;
        pImgHdrs[i].imageSize = uiSize ;
    }
    return uiCrc ;
}
 
void WriteImages(FILE *fcpb, FILE *fImgs[], LPIMAGEHEADER pImgHdrs, int32 nCount)
{
    int32 i ;
    uint32 iBufSize, nLen, uiCrc ;
    uint8 *pBuf ;
    iBufSize = 1024 * 1024 ; //1MiB
    pBuf = (uint8 *)malloc(iBufSize) ;
    if(pBuf == NULL)
    {
        printf("写入映像文件时,申请1MiB内存失败!\n") ;
        exit(1) ;
        return ;
    }
    for(i=0; i<nCount; i++)
    {
        printf("写入‘%s’文件...\n", pImgHdrs[i].fileName) ;
        uiCrc = 0 ;
        for(nLen=0; (nLen+iBufSize)<=pImgHdrs[i].imageSize; nLen+=iBufSize)
        {
            fread(pBuf, iBufSize, 1, fImgs[i]) ;
            uiCrc = CRC16(pBuf, iBufSize, uiCrc) ;
            fwrite(pBuf, iBufSize, 1, fcpb) ;
        }
        nLen = pImgHdrs[i].imageSize - nLen ;
        if(nLen > 0)
        {
            fread(pBuf, nLen, 1, fImgs[i]) ;
            uiCrc = CRC16(pBuf, nLen, uiCrc) ;
            fwrite(pBuf, nLen, 1, fcpb) ;
        }
        pImgHdrs[i].checkSum = uiCrc ;
    }
    free(pBuf) ;
}
 
void PackCpb(LPCPBHEADER pCpbHdr, const char *lpszPath, const char *lpszList, const char *lpszCpb)
{
#define MAX_IMG 500
    FILE *flst = NULL ;
    FILE *fcpb = NULL ;
    FILE *fImgs[MAX_IMG] ;
    char szPath[260], szFile[512] ;
    LPIMAGEHEADER pImgHdr = NULL ;
    int32 i, nCount ;
    uint32 uiCrc, uiCorrect, uiSize ;
    uint64 uiVal64 ;
     
    if(lpszPath == NULL || lpszPath[0]=='\0' || access(lpszPath, 0) != 0)
    {
        printf("‘%s’无效目录!\n", lpszPath) ;
        return ;
    }
    strncpy(szPath, lpszPath, sizeof(szPath)) ;
    uiSize = strlen(szPath) ;
    if(szPath[uiSize-1] != '/' && szPath[uiSize-1] != '\\')
    {
        szPath[uiSize] = '\\' ;
        szPath[uiSize+1] = '\0' ;
    }
    //在此之前确保已经调用InitCpbHeader函数 
    uiCorrect = 0 ;
    for(i=0; i<6; i++)
        uiCorrect += pCpbHdr->correct[i] ;
    uiVal64 = (uint64)0x66666667 * uiCorrect ;
    uiCorrect = (uint32)((int32)(uiVal64 >> 32)) >> 1 ;
    uiCorrect = (uint16)((uiCorrect >> 31) + uiCorrect) ;
    uiCorrect = (uiCorrect-pCpbHdr->correct[3]) | ((uiCorrect-pCpbHdr->correct[4]) << 16) ;
     
    if(access( lpszPath, 0 ) != 0)
    {
        printf("路径‘%s’无法访问!\n", lpszPath) ;
        return ;
    }
    flst = fopen(lpszList, "r") ;
    if(flst == NULL)
    {
        printf("列表文件‘%s’打开失败!\n", lpszList) ;
        return ;
    }
    fcpb = fopen(lpszCpb, "wb") ;
    if(fcpb == NULL)
    {
        fclose(flst) ;
        printf("创建文件‘%s’失败!\n", lpszCpb) ;
        return ;
    }
    pImgHdr = malloc(sizeof(IMAGEHEADER) * MAX_IMG) ;
    if(pImgHdr == NULL)
    {
        fclose(flst) ;
        fclose(fcpb) ;
        printf("申请映像头内存失败!\n") ;
        return ;
    }
     
    for(nCount=0; nCount<MAX_IMG && fgets(pImgHdr[nCount].fileName, sizeof(pImgHdr[nCount].fileName)-1, flst); )
    {
        TrimCRLF(pImgHdr[nCount].fileName) ;
        sprintf(szFile, "%s%s", szPath, pImgHdr[nCount].fileName) ;
        fImgs[nCount] = fopen(szFile, "rb") ;
        if(fImgs[nCount])
        {
            if(fseek(fImgs[nCount], 0, SEEK_END) != 0)
            {
                printf("文件‘%s’定位失败!\n", szFile) ;
                continue ;
            }
            pImgHdr[nCount].imageOffset += sizeof(IMAGEHEADER) ;
            pImgHdr[nCount].imageSize = ftell(fImgs[nCount]) ;
            if((int32)pImgHdr[nCount].imageSize == -1)
            {
                printf("获取文件‘%s’大小失败!\n", szFile) ;
                continue ;
            }
            fseek(fImgs[nCount], 0, SEEK_SET) ;
            nCount++ ;
        }
        else printf("文件‘%s’打开失败!\n", szFile) ;
    }
    pCpbHdr->imgHdrEndPos = sizeof(CPBHEADER) + nCount * sizeof(IMAGEHEADER) ;
    uiCrc = CRC16((uint8 *)pCpbHdr, sizeof(CPBHEADER)-4, 0) ;
    fwrite(pCpbHdr, sizeof(CPBHEADER), 1, fcpb) ; //写入头
    fwrite(pImgHdr, sizeof(IMAGEHEADER)*nCount, 1, fcpb) ; //写入映像文件头 
    WriteImages(fcpb, fImgs, pImgHdr, nCount) ;
    fseek(fcpb, sizeof(CPBHEADER), SEEK_SET) ;
    uiCrc = WriteImageHeaders(fcpb, pImgHdr, nCount, uiCorrect, uiCrc) ;
    uiCrc += pCpbHdr->cp_version[1] ;
    fseek(fcpb, offsetof(CPBHEADER, checkSum), SEEK_SET) ;
    fwrite(&uiCrc, 4, 1, fcpb) ;
    for(i=0; i<nCount; i++)
        fclose(fImgs[i]) ;
    free(pImgHdr) ;
    fclose(flst) ;
    fclose(fcpb) ;
}
 
int main(int argc, char *argv[])
{
    char *lpszCpb = NULL ;
    char *lpszPath = NULL ;
    char *lpszList = NULL ;
    char *lpszModel = NULL ;
    char *lpszHardVer = NULL ;
    char *lpszVersion = NULL ;
    CPBHEADER cpbHdr ;
     
    if(argc < 4)
    {
        usage() ;
        return 0 ;
    }
    switch(argv[1][1])
    {
    case 'l':
    case 'L':
        lpszCpb = argv[2] ;
        lpszList = argv[3] ;
        CreateListFile(lpszCpb, lpszList) ;
        break ;
         
    case 'u':
    case 'U':
        lpszCpb = argv[2] ;
        lpszPath = argv[3] ;
        UnpackCpb(lpszCpb, lpszPath) ;
        break ;
         
    case 'p':
    case 'P':
        if(argc < 8)
        {
            usage() ;
            return 0 ;
        }
        lpszModel = argv[2] ;
        lpszHardVer = argv[3] ;
        lpszVersion = argv[4] ;
        lpszPath = argv[5] ;
        lpszList = argv[6] ;
        lpszCpb = argv[7] ;
        InitCpbHeader(&cpbHdr, lpszModel, lpszHardVer, lpszVersion, "D:\\image") ;
        PackCpb(&cpbHdr, lpszPath, lpszList, lpszCpb) ;
        break ;
         
    default:
        usage() ;
        return 0 ;
    }
    return 0 ;
}



酷派CPB升级文件封包解包

完整的下载地址:这里

你可能感兴趣的:(酷派CPB升级文件封包解包)