zoukankan      html  css  js  c++  java
  • [C语言] 联想手机szb格式的制作工具,部分开源代码(仅提供程序思想);

    /*
     * =====================================================================================
     *
     *       Filename:  szbtool.c
     *
     *    Description:  联想手机szb格式的制作工具,部分开源代码(仅提供程序思想);
     *
     *        Version:  1.0
     *        Created:  2013年03月25日 01时46分16秒
     *       Revision:  none
     *       Compiler:  gcc
     *
     *         Author:  linkscue (scue), 
     *   Organization:  
     *
     * =====================================================================================
     */
    #include    <stdlib.h>
    #include    <stdio.h>
    #include    <string.h>
    #include    <unistd.h>
    #include    <fcntl.h>
    #include    <time.h>
    
    extern char *optarg;
    extern int optind;
    extern int opterr;
    extern int optopt;
    
    #define u8 unsigned char
    #define u32 unsigned int
    #define u16 unsigned short
    #define INFOSIZE 256
    #define BUFFER_SIZE 1024
    
    typedef struct {
    /* 
     * 保密信息:szb文件0~12字节
     * */
    }szb_header_t;
    
    typedef struct {
    /* 
     * 保密信息:szb文件12~256字节
     */
    }szb_head_t;
    
    typedef struct {
    /*
     * 保密信息:szb文件的结构体
     */
    }szb_info;
    
    typedef struct{
    /* 
     *保密信息:存放image信息的结构体
     * */
    }szb_images_t;
    
    
    /*获取文件长度*/
    long getSize( FILE *fp )
    {
        long int save_pos;                          /* 保存当前文件指针 */
        long size_of_file;                          /* 保存文件的大小 */
        save_pos = ftell( fp );                     /* 暂存当前文件指针位置 */
        fseek( fp, 0L, SEEK_END );                  /* 从文件开始位置移动至文件结尾 */
        size_of_file = ftell( fp );                 /* 获取文件指针位置 */
        fseek( fp, save_pos, SEEK_SET );            /* 还原之前的文件指针位置 */
        return( size_of_file );                     /* 返回文件大小数值 */
    }
    
    
    unsigned int getSzbSum(char *file){
    /* 
     *保密信息:获取szb文件校验码
     * */
        return sum;                    
    
    }
    
    /*计算一个文件的CRC校验*/
    unsigned int getSum(FILE *fp)
    {
    /* 
     *保密信息:获取image文件校验码
     * */
        return sum;                                 /* 这里的检验和的值是正确的 */
    }
    
    /* 分解szb函数 */
    void splitFile(char *file){
    
        FILE *fd = NULL;
        FILE *ft = NULL;
        int i;
        get_szb_info(file);                         /* 显示szb文件信息 */
        if ( (fd=fopen(file,"rb")) == NULL ) {      /* 打开文件进行操作 */
            printf ( "Extract szb file, open %s failure!\n", file );
            exit(1);
        }
        fseek( fd, 0, SEEK_SET );                   /* 重新定向文件指针位置 */
        u32 imagecount = 0;
        fseek( fd, 84, SEEK_SET );                  /* 略过前边的84字节 */
        fscanf( fd,"%4c", &imagecount );            /* 获取镜像文件个数 */
        fseek( fd, 168, SEEK_CUR );                 /* 总共略过前边的256字节的Header信息 */
        szb_images_t images[10];
        memset(images,0x00,sizeof(images));
        for ( i=0; i < imagecount ; i++ ){          
        fscanf(fd,"%64c",&images[i].filename);      /* 获取得文件名称 */
        fscanf(fd,"%32c",&images[i].partname);
        fscanf(fd,"%4c",&images[i].checksum);
        fscanf(fd,"%4c",&images[i].timestamp);
        fscanf(fd,"%4c",&images[i].imageoffset);    /* 获取偏移位置 */
        fscanf(fd,"%4c",&images[i].imagesize);      /* 获取镜像文件的大小 */
        fscanf(fd,"%4c",&images[i].eraseflag);
        fscanf(fd,"%4c",&images[i].writeflag);
        fscanf(fd,"%136c",&images[i].reserve);
        }
        //开始分解数据;
        int size,n,offset,fp_local,end;
        unsigned char imagename[32]="";
        unsigned char buffer[BUFFER_SIZE];              /* 创建缓冲区 */
        strncpy(buffer,"",sizeof(buffer));              /* 清空缓冲区内容 */
        for( i=0; i < imagecount ; i++ ){
            strncpy(imagename, images[i].filename, sizeof(imagename));
            offset=images[i].imageoffset;
            size=images[i].imagesize;
            end=(offset+size);
            if ( size != 0 ) {
                if ( ( ft=fopen(imagename,"wb") ) == NULL ){
                    printf("Extract szb file, open %s failure!\n",imagename);
                }
                fseek( fd, offset, SEEK_SET);                /* 跳转至数据段 */
                printf("Extract %s..\n",imagename);
                while ( fp_local !=  end )  {
                    n  = fread(buffer,1, sizeof(buffer), fd);
                    fwrite(buffer, n, 1, ft);
                    fp_local=ftell(fd);
                }
            }
        }
        fclose(fd);
        printf("Extract szb file done!\n");
    }
    
    
    /* 在尾部追加二进制文件(cat a >> b) */
    void appendFile(char *fp, char *body) { 
        int n=0;
        FILE *in,*out;
        u8 buffer[BUFFER_SIZE];
        if ( (in = fopen(fp, "rb")) == NULL){
            printf ( "Open in file failure!\n" );
            exit(1);
        }
        if ( (out=fopen( body , "ab")) == NULL ){
            printf ( "Open out file failure!\n" );
            exit(1);
        }
        while (!feof(in)) {
            n = fread(buffer, 1, BUFFER_SIZE, in);
            fwrite(buffer, 1, n, out);
        }
        fclose(in);
        fclose(out);
    }
    
    /* 复制一个文件至另一个文件位置 */
    //void copyFile(char *from, char *to){
    //    FILE * outfile, *infile;
    //    infile = fopen(from, "rb");
    //    outfile = fopen(to, "wb" );
    //    unsigned char buf[BUFFER_SIZE];
    //    if( outfile == NULL || infile == NULL )
    //    {
    //        printf("Copy file failure!");
    //        exit(1);
    //    }   
    //    int rc;
    //    while( (rc = fread(buf,sizeof(unsigned char), BUFFER_SIZE ,infile)) != 0 )
    //    {
    //        fwrite( buf, sizeof( unsigned char ), rc, outfile );
    //    } 
    ////    sleep(0.1);
    //    fclose(infile);
    //    fclose(outfile);
    //}
    
    /* 合并两个文件至一个文件 (cat a b > c) */
    //void mergeFile(char *fp1,char *fp2,char *name){
    //    FILE *fd1,*fd2,*fp3;
    //    unsigned char buf[BUFFER_SIZE];
    //    char filename[100];
    //    strncpy(filename,name,sizeof(filename));
    //    int rc1,rc2;
    //    fd1 = fopen(fp1,"rb");
    //    fd2 = fopen(fp2,"rb");
    //    fp3 = fopen(filename, "wb" );
    //    while( (rc1 = fread(buf,sizeof(unsigned char), BUFFER_SIZE,fd1)) != 0 )
    //    {
    //        fwrite( buf, sizeof( unsigned char ), rc1, fp3 );
    //    } 
    //    while( (rc2 = fread(buf,sizeof(unsigned char), BUFFER_SIZE,fd2)) != 0 )
    //    {
    //        fwrite( buf, sizeof( unsigned char ), rc2, fp3 );
    //    } 
    //    sleep(0.1);
    //    fclose(fd1);
    //    fclose(fd2);
    //    fclose(fp3);
    //}
    
    /* appendImage(szb文件, image文件,文件名称,分区位置,偏移量,索引位置) */
    u32 appendImage(char *szb, char *file, char *filename, char *partname, u32 offset, int index){
        FILE *fp,*fb;
        if((fp=fopen(file,"rb")) == NULL){
            printf ( "Open %s failure!\n",filename );
            exit(1);
        }
        szb_images_t image;
        strncpy(image.filename, filename, sizeof(image.filename));
        strncpy(image.partname, partname, sizeof(image.partname));
        strncpy(image.reserve, "", sizeof(image.reserve));
        time(&image.timestamp);
        image.imageoffset=offset;
        image.imagesize=getSize(fp);
        image.checksum=getSum(fp);
        image.eraseflag=1;
        image.writeflag=1;
        fclose(fp);
        printf("Adding: %-12sOffset: 0x%08x Checksum: 0x%08x\n",image.partname, image.imageoffset, image.checksum);
        if ( (fb=fopen(szb, "rb+")) == NULL) {
            printf(" append %s to szb file, open szb file failure!\n", file);
            exit(1);
        }
        fseek( fb, ( index * INFOSIZE ), SEEK_SET );     /* 移动文件指针的位置 */
        fwrite(&image.filename, sizeof(image.filename), 1, fb);           /* 向szb文件写入Image的相关信息 */
        fwrite(&image.partname, sizeof(image.partname), 1, fb);           /* 向szb文件写入Image的相关信息 */
        fwrite(&image.checksum, sizeof(image.checksum), 1, fb);           /* 向szb文件写入Image的相关信息 */
        fwrite(&image.timestamp, sizeof(image.timestamp), 1, fb);         /* 向szb文件写入Image的相关信息 */
        fwrite(&image.imageoffset, sizeof(image.imageoffset), 1, fb);     /* 向szb文件写入Image的相关信息 */
        fwrite(&image.imagesize, sizeof(image.imagesize), 1, fb);         /* 向szb文件写入Image的相关信息 */
        fwrite(&image.eraseflag, sizeof(image.eraseflag), 1, fb);         /* 向szb文件写入Image的相关信息 */
        fwrite(&image.writeflag, sizeof(image.writeflag), 1, fb);         /* 向szb文件写入Image的相关信息 */
        fwrite(&image.reserve, sizeof(image.reserve), 1, fb);             /* 向szb文件写入Image的相关信息 */
        fclose(fb);                                   /* 向szb文件写完Image信息后关闭 */
        appendFile(file, szb);                        /* 向szb文件的尾部添加image数据 */
        return (image.imagesize+image.imageoffset);   /* 返回一个偏移数据,方便之后的判断 */
    }
    
    void get_szb_info(char *file){
        FILE *fp;
        int i,count;
        szb_info info;
        if ( (fp=fopen(file, "rb"))  == NULL ) {
            /* code */
        }
        fscanf(fp,"%8c",&info.magic);
        /* 
         *保密信息: 获取szb头部信息
         * */
        fscanf(fp,"%136c",&info.reserve);
        u8 magic[]="LmSzBfMt";
        if ( strstr(info.magic,magic) == NULL ){
            printf ( "This file not in szb format, abort!\n" );
            exit(1);
        }
        struct tm *ptr;                             /* 格式化时间输出 */
        time_t lt;
        unsigned int times=info.timestamp;
        char str[80];
        lt=times;
        ptr=localtime(&lt);
        strftime(str,100,"%F%X",ptr);
        printf ( "\n" );
        printf ( "Header:\n" );
        printf ( "Checksum:\t0x%08x\n",info.checksum );
        printf ( "Size:\t\t0x%08x\n",info.filesize );
        printf ( "Author:\t\t%s\n",info.author );
        printf ( "Version:\t%s\n",info.version );
        printf ( "Times:\t\t%s\n",str );
        printf ( "Counts:\t\t0x%x\n",info.imagecount );
    
        count=info.imagecount;
        szb_images_t images[10];
        printf ( "\n" );
        printf ( "Images:\n" );
        for ( i=0; i < info.imagecount ; i++ ){
        fscanf(fp,"%64c",&images[i].filename);
        fscanf(fp,"%32c",&images[i].partname);
        fscanf(fp,"%4c",&images[i].checksum);
        fscanf(fp,"%4c",&images[i].timestamp);
        fscanf(fp,"%4c",&images[i].imageoffset);
        fscanf(fp,"%4c",&images[i].imagesize);
        fscanf(fp,"%4c",&images[i].eraseflag);
        fscanf(fp,"%4c",&images[i].writeflag);
        fscanf(fp,"%136c",&images[i].reserve);
        if ( strlen(images[i].filename) != 0 ){
            printf ( "Position: %-10sOffset: 0x%08x  Checksum: 0x%08x\n",images[i].partname,  images[i].imageoffset, images[i].checksum );}
        else{
            printf ( "Earse:    %-10sCaution!\n",images[i].partname);
        }
        }
        printf ( "\n" );
        fclose(fp);
    }
    
    /* 显示szbtool作者信息 */
    void author_info(){  
        printf ( "\n" );
        printf ( "===============================================================\n" );
        printf ( "          Welcome to use Lenovo K860/K860i szbtool!    \n" );
        printf ( "\n" );
        printf ( "                                    -- version: 0.14       \n" );
        printf ( "                                    -- author:  linkscue   \n" );
        printf ( "===============================================================\n" );
    }
    /* 显示使用帮助 */
    void usage(){  
        printf ( "\n" );
        printf ( "---------------------------------------------------------------\n" );
        printf ( "usage:\n" );
        printf ( "szbtool -b uboot      # add uboot.bin\n" );
        printf ( "szbtool -k boot       # add boot.img\n" );
        printf ( "szbtool -r recovery   # add recovery.img\n" );
        printf ( "szbtool -s system     # add system.img\n" );
        printf ( "szbtool -c cpimage    # add cpimage.img\n" );
        printf ( "szbtool -p preload    # add preload.img\n" );
        printf ( "szbtool -d userdata   # add userdata.img\n" );
        printf ( "szbtool -e erase      # erase data & cache space\n" );
        printf ( "szbtool -a author     # specify author\n" );
        printf ( "szbtool -v version    # specify version\n" );
        printf ( "szbtool -i szb        # szb information\n" );
        printf ( "szbtool -x szb        # extract szb \n" );
        printf ( "szbtool -h            # help\n" );
        printf ( "---------------------------------------------------------------\n" );
        printf ( "e.g. szbtool -k boot.img -s system.img -a scue@Link -v Link.szb\n" );
        printf ( "\n" );
    }
    
    /*主函数*/
    int main ( int argc, char *argv[] )
    {
        FILE *fp,*fp1,*fp2,*fd1,*fd2,*sub_image;
        char *file=NULL;
        u8 magic[8];
        u8 imagename[64];
        u8 partname[32];
        u8 version[32];
        u8 author[32];
        u32 filesize;
        u32 offset=8192;                            /* 初始的偏移量 */
        char opt;                                   /* 获取输入的选项 */
        int index=0;                                /* 判断szb中的分区索引数量 */
        int DO_NOTHING=0;                           /* 依据此变量判断是否执行 */
        int ERASE_DATA=0;                           /* 依据此变量判断是否擦除数据 */
        
        //清空变量
        memset(version,0x00,sizeof(version));
        memset(imagename,0x00,sizeof(imagename));
        memset(partname,0x00,sizeof(partname));
        strncpy(author,"scue@Link",sizeof(author));
    
        //显示作者信息
        author_info();
    
        //检测输入参数
        if(argc == 1)
        {
            usage();                                /* 显示使用手册 */
            exit(0);
        }
    
        //判断选项中是否有版本
        int i;
        char tmp1[32]="";
        char tmp2[32]="";
        strncpy(tmp2,"-v",sizeof(tmp2));
        for (i = 0; i < argc; i++) {
            strncpy(tmp1,argv[i],sizeof(tmp1));
            if ( strcmp(tmp1,tmp2) == 0 ) {
                strncpy(version,argv[i+1],sizeof(version));
            }
            if ( strcmp(tmp1,"-x") == 0 || strcmp(tmp1,"-i")==0 ) { 
                DO_NOTHING = 1;
            }
        }
        if ( strlen(version) == 0 && DO_NOTHING !=1 ){
            printf ( "\n" );
            printf ( "Please use -v to specify a version name!\n" );
            usage();
            exit(1);
        }
    
        if (DO_NOTHING != 1) {                      /* 当发现有事可做的时候... */
            //创建文件
            remove(version);                            /* delete the old szb file */
            if ( (fp=fopen(version,"wb+")) == NULL ) {
                printf ( "Create version file %s failure!\n",version);
                exit(1);
            }   
            u8 header_buffer[INFOSIZE*32];
            strncpy(header_buffer, "LmSzBfMt", sizeof(header_buffer));
            fwrite(header_buffer,  sizeof(header_buffer) , 1, fp); /* 向其中写8192字节后退出 */
            index++;
            fclose(fp);
        }
    
        //开始获取选项信息
        opterr=0;                                   /* 不显示错误的选项信息 */
        while ((opt = getopt(argc, argv, "b:k:r:s:c:p:d:x:i:v:a:e")) != -1)
          switch (opt) {
          case 'v':
                strncpy(version,optarg,sizeof(version));
                break;
          case 'b':
                file=optarg;
                strncpy(partname,"bootloader",sizeof(partname));
                strncpy(imagename,"uboot.bin",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 'k':
                file=optarg;
                strncpy(partname,"boot",sizeof(partname));
                strncpy(imagename,"boot.img",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 'r':
                file=optarg;
                strncpy(partname,"recovery",sizeof(partname));
                strncpy(imagename,"recovery.img",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 's':
                file=optarg;
                strncpy(partname,"system",sizeof(partname));
                strncpy(imagename,"system.img",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 'c':
                file=optarg;
                strncpy(partname,"cpimage",sizeof(partname));
                strncpy(imagename,"cpimage.img",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 'p':
                file=optarg;
                strncpy(partname,"preload",sizeof(partname));
                strncpy(imagename,"preload.img",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 'd':
                file=optarg;
                strncpy(partname,"userdata",sizeof(partname));
                strncpy(imagename,"userdata.img",sizeof(imagename));
                offset=appendImage(version, file, imagename, partname, offset, index);
                index++;
                break;
          case 'e':
                ERASE_DATA=1;
                break;
          case 'a':
                strncpy(author,optarg,sizeof(author));
                break;
          case 'x':
                DO_NOTHING=1;
                file=optarg; 
                splitFile(file);
                break;
          case 'i':
                DO_NOTHING=1;
                file=optarg;
                get_szb_info(file);
                break;
          default:
                DO_NOTHING=1;
                usage();
          }
        argv += optind; 
    
    
        //开始执行制作szb文件
        if ( DO_NOTHING != 1 ){
        //检查是否输入格式名    
        if ( strlen(version) == 0 ){
            DO_NOTHING = 1;
            printf ( "\n" );
            printf ( "Please use -v to specify a version name!\n" );
            usage();
            exit(1);
        }
        // 双清功能
        if ( ERASE_DATA == 1) {                     /* 判断是否有“双清功能” */
            u8 erase_data[32];
            u8 erase_cache[32];
            strncpy(erase_data, "userdata", sizeof(erase_data));
            strncpy(erase_cache, "cache", sizeof(erase_data));
            if ( (fp=fopen(version, "rb+")) == NULL ) {
                printf("Add erase features, open file %s failure!\n", version);
                exit(1);
            }
            fseek( fp, (INFOSIZE * index + 64 ), SEEK_SET ); /* erase userdata */
            fwrite(erase_data, sizeof(erase_data), 1, fp);
            index++;
            fseek( fp, (INFOSIZE * index + 64 ), SEEK_SET ); /* erase cache */
            fwrite(erase_cache, sizeof(erase_cache), 1, fp);
            index++;
            fclose(fp);
    
        }
    
        //制作SZB格式文件头部(256-12)部分
        szb_head_t head;
        if ( (fp=fopen(version,"rb+")) ==NULL ){
            printf("Calculate file size, open file %s failure!\n", version);
            exit(1);
        }
        head.filesize=getSize(fp);                          /* get szb file size */
        /* 
         * 保密信息:向szb文件写入数据
         * */
        time(&head.timestamp);                              /* 写入时间信息 */
        /* 
         * 保密信息:向szb文件写入数据
         * */
        fseek( fp, 12, SEEK_SET );
        fwrite(&head,sizeof(szb_head_t),1,fp);              /* 写入256-12字节部分 */
        fclose(fp);
    
        u32 szb_checksum;
        szb_checksum=getSzbSum(version);
        if ( (fp=fopen(version,"rb+")) ==NULL ){
            printf("Calculate file size, open file %s failure!\n", version);
            exit(1);
        }
        fseek(fp, 8, SEEK_SET);
        fwrite(&szb_checksum,sizeof(szb_checksum),1,fp);     /* 写入总的验证码字节部分 */
        fclose(fp);
        get_szb_info(version);
        printf ( ">> Congratulations! The Official ROM %s done!\n",version);
        printf ( "\n" );
        }
        return 0;
    }
    ------------
    微博:http://weibo.com/scue
    Github:http://github.com/scue
  • 相关阅读:
    Redis集群的搭建
    CAS部署在Windows上
    Loadrunner中Error-26612HTTP Status-Cod
    Coneroller执行时候的-26374及-26377错误
    Loadrunner 26377错误
    歌名也好笑
    loadrunner 中Error和failed transaction 的区别
    loadrunner 性能测试报error-27796的解决
    lr11.0负载测试 real-world schedule 与basic schedule的区别是什么
    LR中错误代号为27796的一个解决方法
  • 原文地址:https://www.cnblogs.com/scue/p/2987723.html
Copyright © 2011-2022 走看看