/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2008 by Maurus Cuelenaere * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include #include #include #include #include #include #define VERSION "0.2" struct header{ char main_header[20]; unsigned int size; unsigned int checksum; unsigned int unknown; char other_header[32]; }; static char* basepath(char* path) { static char tmp[255]; char *ptr, *ptr2, *ptr3; ptr = path; ptr2 = (char*)tmp; #ifdef _WIN32 ptr3 = strrchr(path, 0x5C); #else ptr3 = strrchr(path, 0x2F); #endif while((int)ptr < (int)ptr3) { *ptr2 = *ptr; ptr++; ptr2++; } #ifdef _WIN32 *ptr2 = 0x5C; #else *ptr2 = 0x2F; #endif ptr2++; *ptr2 = 0; return (char*)tmp; } #ifndef _WIN32 static void replace(char* str) { char *ptr = str; while(*ptr != 0) { if(*ptr == 0x5C) /* \ */ *ptr = 0x2F; /* / */ ptr++; } } #endif static unsigned int le2int(unsigned char* buf) { unsigned int res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; return res; } #ifdef _WIN32 #define PATH_SEPARATOR '\\' #else #define PATH_SEPARATOR '/' #endif static unsigned int __mkdir(const char *path) { char opath[256]; char *p; size_t len; strncpy(opath, path, sizeof(opath)); len = strlen(opath); if(opath[len - 1] == PATH_SEPARATOR) opath[len - 1] = '\0'; for(p = opath; *p; p++) if(*p == PATH_SEPARATOR) { *p = '\0'; if(access(opath, F_OK)) #ifdef _WIN32 mkdir(opath); #else mkdir(opath, S_IRWXU); #endif *p = PATH_SEPARATOR; } if(access(opath, F_OK)) #ifdef _WIN32 return mkdir(opath); #else return mkdir(opath, S_IRWXU); #endif else return -1; } #if 0 static bool dir_exists(const char *dir) { struct stat buf; memset(&buf, 0, sizeof(struct stat)); printf("start: %s\n", dir); char *dir_cpy = (char*)malloc(strlen(dir)); strcpy(dir_cpy, dir); printf("%s\n", dir_cpy); int tmp = (int)dir_cpy; while(*dir_cpy != 0) { dir_cpy++; if(*dir_cpy == PATH_SEPARATOR && *(dir_cpy+1) == 0) *dir_cpy = 0; } printf("while_done\n"); dir_cpy = (char*)tmp; printf("statting %s...\n", dir_cpy); tmp = stat(dir_cpy, &buf); printf("chk_dir(%s) = %d\n", dir_cpy, tmp); free(dir_cpy); return tmp == 0; } #endif static bool file_exists(const char *file) { struct stat buf; return stat(file, &buf) == 0; } static int split_hxf(const unsigned char* infile, unsigned int size, const char* outpath) { FILE *outfile; char *filename; unsigned int filenamesize, filesize; while(size > 0) { filenamesize = le2int((unsigned char*)infile); infile += 4; size -= 4; if(size > 0) { filename = (char*)calloc(1, filenamesize+1+strlen(outpath)); memcpy(filename, outpath, strlen(outpath)); memcpy(&filename[strlen(outpath)], infile, filenamesize); #ifndef _WIN32 replace(filename); #endif infile += filenamesize + 1; /* + padding */ size -= filenamesize + 1; filesize = le2int((unsigned char*)infile); infile += 4; size -= 4; #if 0 if(!dir_exists(basepath(filename))) #endif { printf("[INFO] %s\n", basepath(filename)); if(__mkdir(basepath(filename)) != 0) { #if 0 fprintf(stderr, "[ERR] Error creating directory %s\n", basepath(filename)); return -3; #endif } } if(!file_exists(filename)) { printf("[INFO] %s: %d bytes\n", filename, filesize); if((outfile = fopen(filename, "wb")) == NULL) { fprintf(stderr, "[ERR] Error opening file %s\n", filename); return -1; } if(filesize>0) { if(fwrite(infile, filesize, 1, outfile) != 1) { fclose(outfile); fprintf(stderr, "[ERR] Error writing to file %s\n", filename); return -2; } } fclose(outfile); } infile += filesize; size -= filesize; } } return 0; } static void print_usage(void) { #ifdef _WIN32 fprintf(stderr, "Usage: hxfsplit.exe [FW] [OUTPUT_DIR]\n\n"); fprintf(stderr, "Example: hxfsplit.exe VX747.HXF VX747_extracted\\\n\n"); #else fprintf(stderr, "Usage: HXFsplit [FW] [OUTPUT_DIR]\n\n"); fprintf(stderr, "Example: HXFsplit VX747.HXF VX747_extracted/\n\n"); #endif } int main(int argc, char *argv[]) { FILE *infile; struct header hdr; unsigned char *inbuffer; fprintf(stderr, "HXFsplit v" VERSION " - (C) 2008 Maurus Cuelenaere\n"); fprintf(stderr, "This is free software; see the source for copying conditions. There is NO\n"); fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); if(argc != 3) { print_usage(); return 1; } #ifdef _WIN32 if(strcmp((char*)(argv[2]+strlen(argv[2])-1), "\\") != 0) { fprintf(stderr, "[ERR] Output path must end with a \\\n"); #else if(strcmp((char*)(argv[2]+strlen(argv[2])-1), "/") != 0) { fprintf(stderr, "[ERR] Output path must end with a /\n"); #endif return 2; } if((infile = fopen(argv[1], "rb")) == NULL) { fprintf(stderr, "[ERR] Cannot open %s\n", argv[1]); return 3; } if((inbuffer = (unsigned char*)malloc(sizeof(struct header))) == NULL) { fclose(infile); fprintf(stderr, "[ERR] Error allocating %d bytes buffer\n", sizeof(struct header)); return 4; } if(fread(inbuffer, sizeof(struct header), 1, infile) != 1) { fclose(infile); fprintf(stderr, "Cannot read header of %s\n", argv[1]); return 5; } memcpy(hdr.main_header, inbuffer, 20); hdr.size = le2int(&inbuffer[20]); hdr.checksum = le2int(&inbuffer[24]); hdr.unknown = le2int(&inbuffer[28]); memcpy(hdr.other_header, &inbuffer[32], 32); free(inbuffer); if(strcmp(hdr.other_header, "Chinachip PMP firmware V1.0") != 0) { fclose(infile); fprintf(stderr, "[ERR] Header doesn't match\n"); return 6; } if((inbuffer = (unsigned char*)malloc(hdr.size)) == NULL) { fclose(infile); fprintf(stderr, "[ERR] Error allocating %d bytes buffer\n", hdr.size); return 7; } fseek(infile, sizeof(struct header), SEEK_SET); if(fread(inbuffer, hdr.size-sizeof(struct header), 1, infile) != 1) { fclose(infile); free(inbuffer); fprintf(stderr, "[ERR] Cannot read file in buffer\n"); return 8; } fclose(infile); split_hxf(inbuffer, hdr.size-sizeof(struct header), argv[2]); free(inbuffer); return 0; }