1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include <sys/types.h>
34 fprintf(stderr
, "Usage: HXF2IHFS <hxf_img> <ihfs_img> [ihfs_size]\n");
48 int hxf_sanity(const int hxf_img
)
52 int r
, len_name
, len_file
, pos
;
54 printf("Starting sanity check for HXF image...\n");
56 lseek(hxf_img
, 0, SEEK_SET
);
57 read(hxf_img
, &hxf_hdr
, sizeof (hxf_hdr
));
59 printf(" Checking for HXF signature...\n");
60 if (hxf_hdr
.signature
!= 0x46444157)
63 printf(" Checking for unknown value 1...\n");
64 if (strncmp(hxf_hdr
.unknown1
, "0100", 4))
67 printf(" Checking for length...\n");
68 fstat(hxf_img
, &statbuf
);
69 if (hxf_hdr
.length
!= statbuf
.st_size
)
72 printf(" Checking for unknown value 3...\n");
73 if (hxf_hdr
.unknown3
!= 0x00000000)
76 printf(" Checking for id...\n");
77 if (memcmp(hxf_hdr
.id
, "Chinachip PMP firmware V1.0\0\0\0\0\0", 32))
80 printf(" Checking for file completeness...\n");
82 r
= read(hxf_img
, &len_name
, 4);
88 r
= lseek(hxf_img
, len_name
+ 1, SEEK_CUR
);
92 r
= read(hxf_img
, &len_file
, 4);
98 r
= lseek(hxf_img
, len_file
, SEEK_CUR
);
102 pos
= lseek(hxf_img
, 0, SEEK_CUR
);
103 if (pos
!= statbuf
.st_size
)
120 #define MAX_FILES 2048
121 #define MAX_IHFS_PATH 56
125 char fullpath
[MAX_IHFS_PATH
];
131 #define SECTOR_SIZE 512
133 #define DEFAULT_IHFS_SIZE 65273856
134 #define DEADFACE_START 0x02140000
137 int hxf_ihfs_compatible(int hxf_img
)
139 int n
, len_name
, len_file
;
141 lseek(hxf_img
, sizeof (hxf_header_t
), SEEK_SET
);
145 read(hxf_img
, &len_name
, 4);
148 if (len_name
> MAX_IHFS_PATH
)
150 lseek(hxf_img
, len_name
+ 1, SEEK_CUR
);
151 read(hxf_img
, &len_file
, 4);
152 lseek(hxf_img
, len_file
, SEEK_CUR
);
162 void hxf_to_ihfs(int hxf_img
, int ihfs_img
, int filesize
)
164 char buf
[SECTOR_SIZE
];
165 char ff
[SECTOR_SIZE
];
168 n
= filesize
/ SECTOR_SIZE
;
169 rem
= filesize
% SECTOR_SIZE
;
171 for (i
= 0; i
< n
; ++i
) {
172 read(hxf_img
, buf
, SECTOR_SIZE
);
173 write(ihfs_img
, buf
, SECTOR_SIZE
);
177 read(hxf_img
, buf
, rem
);
178 write(ihfs_img
, buf
, rem
);
180 memset(ff
, 0xff, SECTOR_SIZE
-rem
);
181 write(ihfs_img
, ff
, SECTOR_SIZE
-rem
);
185 int main(int argc
, char **argv
)
189 hxf_header_t hxf_hdr
;
194 ihfs_header_t ihfs_hdr
;
195 ihfs_file_table_t ihfs_ftbl
;
197 unsigned char deadface
[SECTOR_SIZE
];
198 char ff
[SECTOR_SIZE
];
206 /* check the arguments */
207 if (argc
!= 3 && argc
!= 4)
210 stat(argv
[1], &statbuf
);
211 if (!S_ISREG(statbuf
.st_mode
))
215 ihfs_len
= DEFAULT_IHFS_SIZE
;
218 ihfs_len
= strtol(argv
[3], NULL
, 10);
219 if (errno
!= 0 || ihfs_len
< 0 || (ihfs_len
% SECTOR_SIZE
) != 0)
225 hxf_img
= open(argv
[1], O_RDONLY
);
227 if (hxf_sanity(hxf_img
)) {
228 printf("Non-HXF format!\n");
231 printf("Sanity check OK\n");
234 lseek(hxf_img
, 0, SEEK_SET
);
235 read(hxf_img
, &hxf_hdr
, sizeof (hxf_hdr
));
237 printf("HXF info:\n");
239 printf(" Signature: 0x%08x\n", hxf_hdr
.signature
);
241 strncpy(s
, hxf_hdr
.unknown1
, 4);
243 printf(" Unknown1: %s\n", s
);
245 strncpy(s
, hxf_hdr
.timestamp
, 12);
247 printf(" Timestamp: %s\n", s
);
249 printf(" File size: %d bytes\n", hxf_hdr
.length
);
250 printf(" Unknown2: 0x%08x\n", hxf_hdr
.unknown2
);
251 printf(" Unknown3: 0x%08x\n", hxf_hdr
.unknown3
);
252 printf(" Identifier: %s\n", hxf_hdr
.id
);
254 if (hxf_ihfs_compatible(hxf_img
)) {
255 printf("This HXF image can't be converted into IHFS\n");
258 printf("HXF can be converted into IHFS\n");
261 /* initialize IHFS structures */
262 ihfs_hdr
.signature
= 0x49484653;
263 ihfs_hdr
.fslen
= ihfs_len
/ SECTOR_SIZE
;
264 ihfs_hdr
.unknown1
= 0x00000004;
265 ihfs_hdr
.unknown2
= 0xfffff000;
266 memcpy(ihfs_hdr
.timestamp
, hxf_hdr
.timestamp
, 12);
267 ihfs_hdr
.numfiles
= 0;
268 memset(ihfs_hdr
.zeros
, 0, 476);
269 ihfs_hdr
.marker
= 0x55aa55aa;
271 memset(&ihfs_ftbl
, 0, sizeof (ihfs_ftbl
));
273 /* start converting */
274 lseek(hxf_img
, sizeof (hxf_header_t
), SEEK_SET
);
276 ihfs_img
= open(argv
[2], O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
277 lseek(ihfs_img
, sizeof (ihfs_header_t
) + 3 * SECTOR_SIZE
+ sizeof (ihfs_file_table_t
), SEEK_SET
);
280 while (lseek(hxf_img
, 0, SEEK_CUR
) < hxf_hdr
.length
) {
281 read(hxf_img
, &pathlen
, 4);
285 path
= malloc(pathlen
+ 1);
286 read(hxf_img
, path
, pathlen
);
287 path
[pathlen
] = '\0';
288 read(hxf_img
, &filetype
, 1);
289 read(hxf_img
, &filesize
, 4);
291 /* update the file table and copy the data */
292 strncpy(ihfs_ftbl
.files
[i
].fullpath
, path
, MAX_IHFS_PATH
);
293 ihfs_ftbl
.files
[i
].sector
= lseek(ihfs_img
, 0, SEEK_CUR
) / 512;
294 ihfs_ftbl
.files
[i
].length
= filesize
;
296 hxf_to_ihfs(hxf_img
, ihfs_img
, filesize
);
301 ihfs_hdr
.numfiles
= i
;
303 /* finalize the ihfs image */
305 pos
= lseek(ihfs_img
, 0, SEEK_CUR
);
306 if ((pos
% SECTOR_SIZE
) != 0) {
307 printf("Something wrong happened during IHFS image creation at %d\n", pos
);
310 if (pos
< ihfs_len
&& pos
< DEADFACE_START
) {
311 memset(ff
, 0xff, SECTOR_SIZE
);
312 n
= (DEADFACE_START
- pos
) / SECTOR_SIZE
;
313 for (i
= 0; i
< n
; ++i
)
314 write(ihfs_img
, ff
, SECTOR_SIZE
);
315 pos
= DEADFACE_START
;
317 if (pos
< ihfs_len
) {
318 for (i
= 0; i
< SECTOR_SIZE
; i
+= 4) {
320 deadface
[i
+1] = 0xad;
321 deadface
[i
+2] = 0xfa;
322 deadface
[i
+3] = 0xce;
324 n
= (ihfs_len
- pos
) / SECTOR_SIZE
;
325 for (i
= 0; i
< n
; ++i
)
326 write(ihfs_img
, deadface
, SECTOR_SIZE
);
329 lseek(ihfs_img
, 0, SEEK_SET
);
330 write(ihfs_img
, &ihfs_hdr
, sizeof (ihfs_hdr
));
331 memset(ff
, 0xff, SECTOR_SIZE
);
332 write(ihfs_img
, ff
, SECTOR_SIZE
);
333 write(ihfs_img
, ff
, SECTOR_SIZE
);
334 write(ihfs_img
, ff
, SECTOR_SIZE
);
335 write(ihfs_img
, &ihfs_ftbl
, sizeof (ihfs_ftbl
));