blob: bba88929f0ab64f954e58a87edac5c89f2451c62 [file] [log] [blame]
Maurus Cuelenaere72bc4e32008-08-12 16:55:59 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25#include <stdint.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29#include <fcntl.h>
30#include <errno.h>
31
32void usage()
33{
34 fprintf(stderr, "Usage: HXF2IHFS <hxf_img> <ihfs_img> [ihfs_size]\n");
35 exit(1);
36}
37
38typedef struct {
39 uint32_t signature;
40 char unknown1[4];
41 char timestamp[12];
42 uint32_t length;
43 uint32_t unknown2;
44 uint32_t unknown3;
45 char id[32];
46} hxf_header_t;
47
48int hxf_sanity(const int hxf_img)
49{
50 struct stat statbuf;
51 hxf_header_t hxf_hdr;
52 int r, len_name, len_file, pos;
53
54 printf("Starting sanity check for HXF image...\n");
55
56 lseek(hxf_img, 0, SEEK_SET);
57 read(hxf_img, &hxf_hdr, sizeof (hxf_hdr));
58
59 printf(" Checking for HXF signature...\n");
60 if (hxf_hdr.signature != 0x46444157)
61 return 1;
62
63 printf(" Checking for unknown value 1...\n");
64 if (strncmp(hxf_hdr.unknown1, "0100", 4))
65 return 1;
66
67 printf(" Checking for length...\n");
68 fstat(hxf_img, &statbuf);
69 if (hxf_hdr.length != statbuf.st_size)
70 return 1;
71
72 printf(" Checking for unknown value 3...\n");
73 if (hxf_hdr.unknown3 != 0x00000000)
74 return 1;
75
76 printf(" Checking for id...\n");
77 if (memcmp(hxf_hdr.id, "Chinachip PMP firmware V1.0\0\0\0\0\0", 32))
78 return 1;
79
80 printf(" Checking for file completeness...\n");
81 while (1) {
82 r = read(hxf_img, &len_name, 4);
83 if (r != 4)
84 return 1;
85 if (len_name == 0)
86 break;
87
88 r = lseek(hxf_img, len_name + 1, SEEK_CUR);
89 if (r < 0)
90 return 1;
91
92 r = read(hxf_img, &len_file, 4);
93 if (r != 4)
94 return 1;
95 if (len_file <= 0)
96 return 1;
97
98 r = lseek(hxf_img, len_file, SEEK_CUR);
99 if (r < 0)
100 return 1;
101 }
102 pos = lseek(hxf_img, 0, SEEK_CUR);
103 if (pos != statbuf.st_size)
104 return 1;
105
106 return 0;
107}
108
109typedef struct {
110 uint32_t signature;
111 uint32_t fslen;
112 uint32_t unknown1;
113 uint32_t unknown2;
114 char timestamp[12];
115 uint32_t numfiles;
116 char zeros[476];
117 uint32_t marker;
118} ihfs_header_t;
119
120#define MAX_FILES 2048
121#define MAX_IHFS_PATH 56
122
123typedef struct {
124 struct {
125 char fullpath[MAX_IHFS_PATH];
126 uint32_t sector;
127 uint32_t length;
128 } files[MAX_FILES];
129} ihfs_file_table_t;
130
131#define SECTOR_SIZE 512
132
133#define DEFAULT_IHFS_SIZE 65273856
134#define DEADFACE_START 0x02140000
135
136
137int hxf_ihfs_compatible(int hxf_img)
138{
139 int n, len_name, len_file;
140
141 lseek(hxf_img, sizeof (hxf_header_t), SEEK_SET);
142
143 n = 0;
144 while (1) {
145 read(hxf_img, &len_name, 4);
146 if (len_name == 0)
147 break;
148 if (len_name > MAX_IHFS_PATH)
149 return 1;
150 lseek(hxf_img, len_name + 1, SEEK_CUR);
151 read(hxf_img, &len_file, 4);
152 lseek(hxf_img, len_file, SEEK_CUR);
153 ++n;
154 }
155
156 if (n > MAX_FILES)
157 return 1;
158
159 return 0;
160}
161
162void hxf_to_ihfs(int hxf_img, int ihfs_img, int filesize)
163{
164 char buf[SECTOR_SIZE];
165 char ff[SECTOR_SIZE];
166 int i, n, rem;
167
168 n = filesize / SECTOR_SIZE;
169 rem = filesize % SECTOR_SIZE;
170
171 for (i = 0; i < n; ++i) {
172 read(hxf_img, buf, SECTOR_SIZE);
173 write(ihfs_img, buf, SECTOR_SIZE);
174 }
175
176 if (rem > 0) {
177 read(hxf_img, buf, rem);
178 write(ihfs_img, buf, rem);
179 /* pad with 0xff */
180 memset(ff, 0xff, SECTOR_SIZE-rem);
181 write(ihfs_img, ff, SECTOR_SIZE-rem);
182 }
183}
184
185int main(int argc, char **argv)
186{
187 struct stat statbuf;
188 int hxf_img;
189 hxf_header_t hxf_hdr;
190 char s[32];
191 int i, n;
192
193 int ihfs_img;
194 ihfs_header_t ihfs_hdr;
195 ihfs_file_table_t ihfs_ftbl;
196 int ihfs_len;
197 unsigned char deadface[SECTOR_SIZE];
198 char ff[SECTOR_SIZE];
199
200 int pathlen;
201 char *path;
202 char filetype;
203 int filesize;
204 int pos;
205
206 /* check the arguments */
207 if (argc != 3 && argc != 4)
208 usage();
209
210 stat(argv[1], &statbuf);
211 if (!S_ISREG(statbuf.st_mode))
212 usage();
213
214 if (argc == 3) {
215 ihfs_len = DEFAULT_IHFS_SIZE;
216 } else {
217 errno = 0;
218 ihfs_len = strtol(argv[3], NULL, 10);
219 if (errno != 0 || ihfs_len < 0 || (ihfs_len % SECTOR_SIZE) != 0)
220 usage();
221 }
222
223 /* check the file */
224
225 hxf_img = open(argv[1], O_RDONLY);
226
227 if (hxf_sanity(hxf_img)) {
228 printf("Non-HXF format!\n");
229 return 1;
230 } else {
231 printf("Sanity check OK\n");
232 }
233
234 lseek(hxf_img, 0, SEEK_SET);
235 read(hxf_img, &hxf_hdr, sizeof (hxf_hdr));
236
237 printf("HXF info:\n");
238
239 printf(" Signature: 0x%08x\n", hxf_hdr.signature);
240
241 strncpy(s, hxf_hdr.unknown1, 4);
242 s[4] = '\0';
243 printf(" Unknown1: %s\n", s);
244
245 strncpy(s, hxf_hdr.timestamp, 12);
246 s[12] = '\0';
247 printf(" Timestamp: %s\n", s);
248
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);
253
254 if (hxf_ihfs_compatible(hxf_img)) {
255 printf("This HXF image can't be converted into IHFS\n");
256 return 1;
257 } else {
258 printf("HXF can be converted into IHFS\n");
259 }
260
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;
270
271 memset(&ihfs_ftbl, 0, sizeof (ihfs_ftbl));
272
273 /* start converting */
274 lseek(hxf_img, sizeof (hxf_header_t), SEEK_SET);
275
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);
278
279 i = 0;
280 while (lseek(hxf_img, 0, SEEK_CUR) < hxf_hdr.length) {
281 read(hxf_img, &pathlen, 4);
282 if (pathlen == 0)
283 break;
284
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);
290
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;
295
296 hxf_to_ihfs(hxf_img, ihfs_img, filesize);
297
298 free(path);
299 ++i;
300 }
301 ihfs_hdr.numfiles = i;
302
303 /* finalize the ihfs image */
304
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);
308 return 1;
309 }
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;
316 }
317 if (pos < ihfs_len) {
318 for (i = 0; i < SECTOR_SIZE; i += 4) {
319 deadface[i] = 0xde;
320 deadface[i+1] = 0xad;
321 deadface[i+2] = 0xfa;
322 deadface[i+3] = 0xce;
323 }
324 n = (ihfs_len - pos) / SECTOR_SIZE;
325 for (i = 0; i < n; ++i)
326 write(ihfs_img, deadface, SECTOR_SIZE);
327 }
328
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));
336
337 /* cleanup */
338 close(hxf_img);
339 close(ihfs_img);
340
341 printf("Done!\n");
342
343 return 0;
344}