diff --git a/utils/jz4740_tools/HXF2IHFS.c b/utils/jz4740_tools/HXF2IHFS.c new file mode 100644 index 0000000000..bba88929f0 --- /dev/null +++ b/utils/jz4740_tools/HXF2IHFS.c @@ -0,0 +1,344 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno + * + * 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 +#include +#include + +void usage() +{ + fprintf(stderr, "Usage: HXF2IHFS [ihfs_size]\n"); + exit(1); +} + +typedef struct { + uint32_t signature; + char unknown1[4]; + char timestamp[12]; + uint32_t length; + uint32_t unknown2; + uint32_t unknown3; + char id[32]; +} hxf_header_t; + +int hxf_sanity(const int hxf_img) +{ + struct stat statbuf; + hxf_header_t hxf_hdr; + int r, len_name, len_file, pos; + + printf("Starting sanity check for HXF image...\n"); + + lseek(hxf_img, 0, SEEK_SET); + read(hxf_img, &hxf_hdr, sizeof (hxf_hdr)); + + printf(" Checking for HXF signature...\n"); + if (hxf_hdr.signature != 0x46444157) + return 1; + + printf(" Checking for unknown value 1...\n"); + if (strncmp(hxf_hdr.unknown1, "0100", 4)) + return 1; + + printf(" Checking for length...\n"); + fstat(hxf_img, &statbuf); + if (hxf_hdr.length != statbuf.st_size) + return 1; + + printf(" Checking for unknown value 3...\n"); + if (hxf_hdr.unknown3 != 0x00000000) + return 1; + + printf(" Checking for id...\n"); + if (memcmp(hxf_hdr.id, "Chinachip PMP firmware V1.0\0\0\0\0\0", 32)) + return 1; + + printf(" Checking for file completeness...\n"); + while (1) { + r = read(hxf_img, &len_name, 4); + if (r != 4) + return 1; + if (len_name == 0) + break; + + r = lseek(hxf_img, len_name + 1, SEEK_CUR); + if (r < 0) + return 1; + + r = read(hxf_img, &len_file, 4); + if (r != 4) + return 1; + if (len_file <= 0) + return 1; + + r = lseek(hxf_img, len_file, SEEK_CUR); + if (r < 0) + return 1; + } + pos = lseek(hxf_img, 0, SEEK_CUR); + if (pos != statbuf.st_size) + return 1; + + return 0; +} + +typedef struct { + uint32_t signature; + uint32_t fslen; + uint32_t unknown1; + uint32_t unknown2; + char timestamp[12]; + uint32_t numfiles; + char zeros[476]; + uint32_t marker; +} ihfs_header_t; + +#define MAX_FILES 2048 +#define MAX_IHFS_PATH 56 + +typedef struct { + struct { + char fullpath[MAX_IHFS_PATH]; + uint32_t sector; + uint32_t length; + } files[MAX_FILES]; +} ihfs_file_table_t; + +#define SECTOR_SIZE 512 + +#define DEFAULT_IHFS_SIZE 65273856 +#define DEADFACE_START 0x02140000 + + +int hxf_ihfs_compatible(int hxf_img) +{ + int n, len_name, len_file; + + lseek(hxf_img, sizeof (hxf_header_t), SEEK_SET); + + n = 0; + while (1) { + read(hxf_img, &len_name, 4); + if (len_name == 0) + break; + if (len_name > MAX_IHFS_PATH) + return 1; + lseek(hxf_img, len_name + 1, SEEK_CUR); + read(hxf_img, &len_file, 4); + lseek(hxf_img, len_file, SEEK_CUR); + ++n; + } + + if (n > MAX_FILES) + return 1; + + return 0; +} + +void hxf_to_ihfs(int hxf_img, int ihfs_img, int filesize) +{ + char buf[SECTOR_SIZE]; + char ff[SECTOR_SIZE]; + int i, n, rem; + + n = filesize / SECTOR_SIZE; + rem = filesize % SECTOR_SIZE; + + for (i = 0; i < n; ++i) { + read(hxf_img, buf, SECTOR_SIZE); + write(ihfs_img, buf, SECTOR_SIZE); + } + + if (rem > 0) { + read(hxf_img, buf, rem); + write(ihfs_img, buf, rem); + /* pad with 0xff */ + memset(ff, 0xff, SECTOR_SIZE-rem); + write(ihfs_img, ff, SECTOR_SIZE-rem); + } +} + +int main(int argc, char **argv) +{ + struct stat statbuf; + int hxf_img; + hxf_header_t hxf_hdr; + char s[32]; + int i, n; + + int ihfs_img; + ihfs_header_t ihfs_hdr; + ihfs_file_table_t ihfs_ftbl; + int ihfs_len; + unsigned char deadface[SECTOR_SIZE]; + char ff[SECTOR_SIZE]; + + int pathlen; + char *path; + char filetype; + int filesize; + int pos; + + /* check the arguments */ + if (argc != 3 && argc != 4) + usage(); + + stat(argv[1], &statbuf); + if (!S_ISREG(statbuf.st_mode)) + usage(); + + if (argc == 3) { + ihfs_len = DEFAULT_IHFS_SIZE; + } else { + errno = 0; + ihfs_len = strtol(argv[3], NULL, 10); + if (errno != 0 || ihfs_len < 0 || (ihfs_len % SECTOR_SIZE) != 0) + usage(); + } + + /* check the file */ + + hxf_img = open(argv[1], O_RDONLY); + + if (hxf_sanity(hxf_img)) { + printf("Non-HXF format!\n"); + return 1; + } else { + printf("Sanity check OK\n"); + } + + lseek(hxf_img, 0, SEEK_SET); + read(hxf_img, &hxf_hdr, sizeof (hxf_hdr)); + + printf("HXF info:\n"); + + printf(" Signature: 0x%08x\n", hxf_hdr.signature); + + strncpy(s, hxf_hdr.unknown1, 4); + s[4] = '\0'; + printf(" Unknown1: %s\n", s); + + strncpy(s, hxf_hdr.timestamp, 12); + s[12] = '\0'; + printf(" Timestamp: %s\n", s); + + printf(" File size: %d bytes\n", hxf_hdr.length); + printf(" Unknown2: 0x%08x\n", hxf_hdr.unknown2); + printf(" Unknown3: 0x%08x\n", hxf_hdr.unknown3); + printf(" Identifier: %s\n", hxf_hdr.id); + + if (hxf_ihfs_compatible(hxf_img)) { + printf("This HXF image can't be converted into IHFS\n"); + return 1; + } else { + printf("HXF can be converted into IHFS\n"); + } + + /* initialize IHFS structures */ + ihfs_hdr.signature = 0x49484653; + ihfs_hdr.fslen = ihfs_len / SECTOR_SIZE; + ihfs_hdr.unknown1 = 0x00000004; + ihfs_hdr.unknown2 = 0xfffff000; + memcpy(ihfs_hdr.timestamp, hxf_hdr.timestamp, 12); + ihfs_hdr.numfiles = 0; + memset(ihfs_hdr.zeros, 0, 476); + ihfs_hdr.marker = 0x55aa55aa; + + memset(&ihfs_ftbl, 0, sizeof (ihfs_ftbl)); + + /* start converting */ + lseek(hxf_img, sizeof (hxf_header_t), SEEK_SET); + + ihfs_img = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644); + lseek(ihfs_img, sizeof (ihfs_header_t) + 3 * SECTOR_SIZE + sizeof (ihfs_file_table_t), SEEK_SET); + + i = 0; + while (lseek(hxf_img, 0, SEEK_CUR) < hxf_hdr.length) { + read(hxf_img, &pathlen, 4); + if (pathlen == 0) + break; + + path = malloc(pathlen + 1); + read(hxf_img, path, pathlen); + path[pathlen] = '\0'; + read(hxf_img, &filetype, 1); + read(hxf_img, &filesize, 4); + + /* update the file table and copy the data */ + strncpy(ihfs_ftbl.files[i].fullpath, path, MAX_IHFS_PATH); + ihfs_ftbl.files[i].sector = lseek(ihfs_img, 0, SEEK_CUR) / 512; + ihfs_ftbl.files[i].length = filesize; + + hxf_to_ihfs(hxf_img, ihfs_img, filesize); + + free(path); + ++i; + } + ihfs_hdr.numfiles = i; + + /* finalize the ihfs image */ + + pos = lseek(ihfs_img, 0, SEEK_CUR); + if ((pos % SECTOR_SIZE) != 0) { + printf("Something wrong happened during IHFS image creation at %d\n", pos); + return 1; + } + if (pos < ihfs_len && pos < DEADFACE_START) { + memset(ff, 0xff, SECTOR_SIZE); + n = (DEADFACE_START - pos) / SECTOR_SIZE; + for (i = 0; i < n; ++i) + write(ihfs_img, ff, SECTOR_SIZE); + pos = DEADFACE_START; + } + if (pos < ihfs_len) { + for (i = 0; i < SECTOR_SIZE; i += 4) { + deadface[i] = 0xde; + deadface[i+1] = 0xad; + deadface[i+2] = 0xfa; + deadface[i+3] = 0xce; + } + n = (ihfs_len - pos) / SECTOR_SIZE; + for (i = 0; i < n; ++i) + write(ihfs_img, deadface, SECTOR_SIZE); + } + + lseek(ihfs_img, 0, SEEK_SET); + write(ihfs_img, &ihfs_hdr, sizeof (ihfs_hdr)); + memset(ff, 0xff, SECTOR_SIZE); + write(ihfs_img, ff, SECTOR_SIZE); + write(ihfs_img, ff, SECTOR_SIZE); + write(ihfs_img, ff, SECTOR_SIZE); + write(ihfs_img, &ihfs_ftbl, sizeof (ihfs_ftbl)); + + /* cleanup */ + close(hxf_img); + close(ihfs_img); + + printf("Done!\n"); + + return 0; +} diff --git a/utils/jz4740_tools/IHFSsplit.c b/utils/jz4740_tools/IHFSsplit.c index 1f90a50007..84ba9a790d 100644 --- a/utils/jz4740_tools/IHFSsplit.c +++ b/utils/jz4740_tools/IHFSsplit.c @@ -192,4 +192,4 @@ int main(int argc, char **argv) close(ihfs_img); return 0; -} \ No newline at end of file +} diff --git a/utils/jz4740_tools/Makefile b/utils/jz4740_tools/Makefile index c99e40d7a7..fe062e885e 100644 --- a/utils/jz4740_tools/Makefile +++ b/utils/jz4740_tools/Makefile @@ -4,8 +4,8 @@ WIN_LIBUSB_LIB_DIR = "$(WIN_DRIVERS_LIBUSB_DIR)\lib\gcc" CFLAGS=-Wall -linux: usbtool HXFmerge HXFreplace HXFsplit IHFSsplit -win: usbtool_win HXFmerge_win HXFsplit_win HXFreplace_win IHFSsplit_win +linux: usbtool HXFmerge HXFreplace HXFsplit IHFSsplit HXF2IHFS +win: usbtool_win HXFmerge_win HXFsplit_win HXFreplace_win IHFSsplit_win HXF2IHFS_win usbtool: $(CC) $(CFLAGS) -o usbtool jz4740_usbtool.c -lusb @@ -20,6 +20,8 @@ HXFsplit: $(CC) $(CFLAGS) -o HXFsplit HXFsplit.c IHFSsplit: $(CC) $(CFLAGS) -o IHFSsplit IHFSsplit.c +HXF2IHFS: + $(CC) $(CFLAGS) -o HXF2IHFS HXF2IHFS.c HXFmerge_win: $(CC) $(CFLAGS) -o HXFmerge.exe HXFmerge.c @@ -29,8 +31,10 @@ HXFsplit_win: $(CC) $(CFLAGS) -o HXFsplit.exe HXFsplit.c IHFSsplit_win: $(CC) $(CFLAGS) -o IHFSsplit.exe IHFSsplit.c +HXF2IHFS_win: + $(CC) $(CFLAGS) -o HXF2IHFS.exe HXF2IHFS.c clean-linux: - rm HXFmerge HXFreplace HXFsplit usbtool + rm HXFmerge HXFreplace HXFsplit usbtool IHFSsplit HXF2IHFS clean-win: - del HXFmerge.exe HXFreplace.exe HXFsplit.exe usbtool.exe + del HXFmerge.exe HXFreplace.exe HXFsplit.exe usbtool.exe IHFSsplit.exe HXF2IHFS.exe diff --git a/utils/jz4740_tools/jz4740_usbtool.c b/utils/jz4740_tools/jz4740_usbtool.c index 14fed4c878..5667579f57 100644 --- a/utils/jz4740_tools/jz4740_usbtool.c +++ b/utils/jz4740_tools/jz4740_usbtool.c @@ -561,6 +561,8 @@ found: return -5; } +/* usb_set_configuration() calls are already done in Linux */ +#ifdef _WIN32 err = usb_set_configuration(dh, 1); if (err < 0) @@ -569,6 +571,7 @@ found: usb_close(dh); return -6; } +#endif /* "must be called" written in the libusb documentation */ err = usb_claim_interface(dh, 0);