/* * dlftool.c (c) 2004 Kai Gossner (xyphro@gmx.net) * * This program is free software; you can redistribute it and/or modify * it under the tems of the GNU General Public License version 2 as * published by the Free Software Foundation. * * create: dlftool -c signaturestring * unpack: dlftool -x * show info: dlftool -i * * Created using CYGwin and compiled it with the command line: * gcc -Wall dlftool.c -o dlftool -Xlinker /usr/lib/libz.a * * To compile on a unix machine install zlib-devel and do: * gcc -Wall dlftool.c -o dlftool -lz */ #include #include #include #include // Maybe you need to update header information here: #define HDR_SIGNATURFILLBYTE 0xcc #define HDR_UNKNOWBYTE 0x08 // Size of buffer used for decompression. As the header of a dlf file // does not contain the decompressed file size i use a value that should be // large enough #define MAX_DECOMPRESSED_SIZE 8192*1024 #define CMD_UNPACKDLF 1 #define CMD_PACKDLF 2 #define CMD_SHOWINFO 3 #define CMD_HELP 4 typedef struct _DLF_HEADER { unsigned long compressiontype; unsigned long compressedlength; unsigned long compressedchksum; char signature[64]; unsigned long hdrchksum; } dlf_header; int parse_command_line(int argc, char **argv) { if ( argc > 1 ) { if ( !strcmp(argv[1], "-c") && (argc == 5) ) { return CMD_PACKDLF; } if ( !strcmp(argv[1], "-x") && (argc == 4) ) { return CMD_UNPACKDLF; } if ( !strcmp(argv[1], "-i") && (argc == 3) ) { return CMD_SHOWINFO; } } return CMD_HELP; } unsigned long getcrc(unsigned char *pdat, int len) { unsigned long crc = 0; while ( len-- ) crc += *pdat++; return crc; } int checkdlfheader(dlf_header *pdlfheader, unsigned long filesize) { unsigned char nullterminated = 0; unsigned long calccrc; int i, ok = 1; printf("Header informations:\n\n"); printf(" compression type: %ld\n", pdlfheader->compressiontype); if ( pdlfheader->compressiontype != 2 ) { printf(" -> only compression type 2 is supported!\n"); ok = 0; } printf(" size of compressed data: %ld\n", pdlfheader->compressedlength); // check compressedlength field if ( pdlfheader->compressedlength != (filesize-sizeof(dlf_header)) ) { printf(" -> compressed data size mismatch!\n"); ok = 0; } // check if the signature is null terminated i = 0; while ( (i < 64) && !nullterminated) { if ( !pdlfheader->signature[i] ) { nullterminated = 1; // Null termination present } i++; } if ( nullterminated ) printf(" signature: %s\n", (char*)&pdlfheader->signature); else { printf(" signature lacks of null termination\n"); ok = 0; } printf(" Header-checksum: %ld", pdlfheader->hdrchksum); calccrc = getcrc( (unsigned char*) pdlfheader, sizeof(dlf_header)-4 ); if ( calccrc != pdlfheader->hdrchksum ) { printf(" -> wrong checksum. Real chksum is %ld\n", calccrc); ok = 0; } printf("\n"); return ok; } void cmd_packdlf(char *infilename, char *outfilename, char *signature) { FILE *dlffile, *binfile; dlf_header dlfheader; unsigned long compressedsize, decompressedsize; unsigned char unknownbyte; unsigned char *pcompresseddata, *pdecompresseddata; int zliberr; printf("Generating dlf file...\n"); if ( strlen(signature) > 63 ) { printf("ERROR: signature is longer than 63 bytes\n"); exit(1); } if ( (binfile=fopen(infilename, "r")) == NULL ) { printf("ERROR: Unable to open file \"%s\"\n", infilename); exit (1); } fseek(binfile, 0, SEEK_END); decompressedsize = ftell(binfile); fseek(binfile, 0, SEEK_SET); if ( (pdecompresseddata = malloc(decompressedsize)) == NULL ) { printf("malloc failed\n"); fclose(binfile); exit(1); } if ( fread( pdecompresseddata, decompressedsize, 1, binfile ) != 1 ) { printf("ERROR: Unable to read data from file\n"); fclose(binfile); exit(1); } fclose(binfile); // allocate memory for compressed data // i assume, that the compressed data is smaller... if ( (pcompresseddata = malloc(decompressedsize)) == NULL ) { printf("malloc failed\n"); } compressedsize = decompressedsize; zliberr = compress( pcompresseddata, &compressedsize, pdecompresseddata, decompressedsize); free( pdecompresseddata ); // don't need decompressed source file any more... if ( zliberr != Z_OK ) { printf("failed to compress data. error=%d\n", zliberr); free( pcompresseddata ); exit(1); } // fill header data dlfheader.compressiontype = 0x02; dlfheader.compressedlength = compressedsize+1; dlfheader.compressedchksum = HDR_UNKNOWBYTE+getcrc((unsigned char*)pcompresseddata, compressedsize ); memset(&dlfheader.signature, HDR_SIGNATURFILLBYTE, sizeof(dlfheader.signature)); strcpy((char*)&dlfheader.signature, signature); dlfheader.hdrchksum = getcrc((unsigned char*)&dlfheader, sizeof(dlfheader)-4); // print header data. The check is not needed... checkdlfheader(&dlfheader, compressedsize+1+sizeof(dlfheader)); // write target dlf file if ( (dlffile=fopen(outfilename, "w+")) == NULL ) { printf("ERROR: Unable to open file \"%s\"\n", outfilename); free( pcompresseddata ); exit (1); } unknownbyte = HDR_UNKNOWBYTE; fwrite( &dlfheader, sizeof(dlf_header), 1, dlffile ); fwrite( &unknownbyte, 1, 1, dlffile ); fwrite( pcompresseddata, compressedsize, 1, dlffile ); fclose(dlffile); free(pcompresseddata); printf("...done!\n"); } void cmd_unpackdlf(char *infilename, char *outfilename) { FILE *dlffile, *binfile; dlf_header dlfheader; unsigned long dlfsize, compressedsize, decompressedsize; unsigned char unknownbyte; unsigned char *pcompresseddata, *pdecompresseddata; int zliberr; printf("Unpacking dlf file...\n"); if ( (dlffile=fopen(infilename, "r")) == NULL ) { printf("ERROR: Unable to open file \"%s\"\n", infilename); exit (1); } if ( fread( &dlfheader, sizeof( dlfheader ), 1, dlffile ) != 1 ) { printf("ERROR: Unable to read header data from file\n"); exit(1); } fseek(dlffile, 0, SEEK_END); dlfsize = ftell(dlffile); fseek(dlffile, sizeof(dlfheader), SEEK_SET); if ( !checkdlfheader(&dlfheader, dlfsize) ) { printf("This file is unsupported\n"); exit(1); } if ( outfilename != NULL ) { fread( &unknownbyte, 1, 1, dlffile ); printf("unknown byte is 0x%02x\n", unknownbyte); printf("Decompressing data...\n"); // read compressed data to memory compressedsize = dlfheader.compressedlength-1; if ( (pcompresseddata = malloc(compressedsize)) == NULL ) { printf("Failed to allocate memory\n"); exit(1); } if ( fread( pcompresseddata, compressedsize, 1, dlffile) != 1 ) { printf("ERROR: Unable to data from file\n"); exit(1); } fclose(dlffile); // get memory for decompressed data // in know this is not nice... if ( (pdecompresseddata = malloc(MAX_DECOMPRESSED_SIZE)) == NULL ) { printf("Failed to allocate memory\n"); exit(1); } // decompress zlib data decompressedsize = MAX_DECOMPRESSED_SIZE; zliberr = uncompress(pdecompresseddata, &decompressedsize, pcompresseddata, compressedsize); free( pcompresseddata ); if ( zliberr != Z_OK ) { printf("Failed to uncompress data. Error=%d\n", zliberr); free( pdecompresseddata ); exit(1); } printf("Decompressed data size = %ld Bytes\n", decompressedsize); if ( (binfile=fopen(outfilename, "w+")) == NULL ) { printf("ERROR: Unable to open file \"%s\"\n", outfilename); free( pdecompresseddata ); exit (1); } fwrite( pdecompresseddata, decompressedsize, 1, binfile ); fclose(binfile); free( pdecompresseddata ); } printf("...done!\n"); } void cmd_showinfo(char *infilename) { cmd_unpackdlf(infilename, NULL); } void cmd_help(void) { printf( "dlftool creates or extracts a DLF firmware image\n\n" "Usage:\n" " * dlftool -c \n" " compresses the to . The string\n" " will be put to the header as signature string\n" " * dlftool -x \n" " extracts the to \n" " * dlftool -i \n" " shows information retrieved from the \n\n" ); exit(0); } int main(int argc, char **argv) { switch ( parse_command_line(argc, argv) ) { case CMD_PACKDLF: cmd_packdlf( argv[2], argv[3], argv[4] ); break; case CMD_UNPACKDLF: cmd_unpackdlf( argv[2], argv[3] ); break; case CMD_SHOWINFO: cmd_showinfo( argv[2] ); break; case CMD_HELP: cmd_help(); break; } return 0; }