freemyipod r142 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r141‎ | r142 | r143 >
Date:04:24, 15 August 2010
Author:cmwslw
Status:new
Tags:
Comment:
4G compatibility for extract2g (without the hack). Thanks user890104
Modified paths:
  • /tools/extract2g/extract2g.c (modified) (history)
  • /tools/extract2g_HACKED (deleted) (history)

Diff [purge]

Index: tools/extract2g_HACKED/extract2g.c
@@ -1,514 +0,0 @@
2 -/*
3 - This program is free software; you can redistribute it and/or modify
4 - it under the terms of the GNU General Public License version 2.1 as
5 - published by the Free Software Foundation.
6 -
7 - This program is distributed in the hope that it will be useful,
8 - but WITHOUT ANY WARRANTY; without even the implied warranty of
9 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 - GNU General Public License for more details.
11 -
12 - You should have received a copy of the GNU General Public License
13 - along with this program; if not, write to the Free Software
14 - Foundation Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
15 -*/
16 -
17 -/*
18 - $Id$
19 -
20 - Revision history:
21 - 1.0 - 2007-01-25 - Brossillon J.Damien <brossill@enseirb.fr>
22 - -- Initial version
23 -
24 - 1.1 - 2007-09-15
25 - -- Stuff added to guess the header versions.
26 -
27 - Todo list:
28 - -- Debug
29 -*/
30 -
31 -#include <stdlib.h>
32 -#include <stdio.h>
33 -#include <string.h>
34 -#include <getopt.h>
35 -#include <limits.h>
36 -
37 -#include "extract2g.h"
38 -
39 -#define VERSION_H 1
40 -#define VERSION_L 1
41 -
42 -#define B (0x0FFFFFFF)
43 -
44 -/* Change endian of a 4 bytes memory zone */
45 -void change_endian( char* buf )
46 -{
47 -
48 - char tmp[4];
49 -
50 - tmp[3] = buf[0];
51 - tmp[2] = buf[1];
52 - tmp[1] = buf[2];
53 - tmp[0] = buf[3];
54 -
55 - memcpy(buf,tmp,4*sizeof(char));
56 -
57 - return;
58 -}
59 -
60 -unsigned int hash_part(FILE* hIn, int start, int len, int header_len)
61 -{
62 - unsigned int hash = 0;
63 -
64 - fseek(hIn, start, SEEK_SET);
65 -
66 - unsigned int tmp;
67 -
68 - int pos;
69 - for(pos=0;pos<(len+header_len);pos++)
70 - {
71 - tmp = fgetc(hIn);
72 -
73 - hash = (hash*B + tmp*pos);
74 - }
75 -
76 - return hash;
77 -}
78 -
79 -void extract_part(FILE* hIn, FILE* hOut,
80 - char* name,
81 - int start, int len,
82 - int header_len)
83 -{
84 - int pos;
85 - char tmp;
86 -
87 - char* filename = NULL;
88 -
89 - // No extract name specified
90 - if( !hOut )
91 - {
92 - filename = (char*)malloc( strlen(name) + 4 );
93 -
94 - if( !filename )
95 - {
96 - fprintf(stderr, "Memory allocation failure.");
97 - exit(EXIT_FAILURE);
98 - }
99 -
100 - strcpy(filename, name);
101 - strcat(filename, ".fw");
102 -
103 - hOut = fopen(filename, "wb");
104 - }
105 -
106 - fprintf(stdout,"Extracting from 0x%8.X to 0x%8.X in %s.\n",
107 - start, start+len+header_len, filename);
108 -
109 - // Go to the beginning of the part
110 - fseek(hIn, start, SEEK_SET);
111 -
112 - // Extracting
113 - for(pos=0;pos<(len+header_len);pos++)
114 - {
115 - tmp = fgetc(hIn);
116 - fputc(tmp,hOut);
117 - }
118 -
119 - fclose(hOut);
120 -
121 - free(filename);
122 -
123 - return;
124 -}
125 -
126 -char is_valid( DIRECTORY* p_dir )
127 -{
128 - // Test if the directory contain a valid header for the part.
129 - return ( !strncmp( p_dir->dev, "NAND", 4)
130 - || !strncmp( p_dir->dev, "ATA!", 4) );
131 -}
132 -
133 -char check_header(FILE* fh, unsigned int l)
134 -{
135 - DIRECTORY dir;
136 -
137 - fseek(fh, l, SEEK_SET);
138 - fread( (void*)&dir, LEN_DIR, sizeof(char), fh);
139 -
140 - change_endian(dir.dev);
141 -
142 - return is_valid(&dir);
143 -}
144 -
145 -int guess_directory_address(FILE* fh)
146 -{
147 - // Check for 1G header
148 - if(check_header(fh,ADDR_DIR_1G))
149 - {
150 - printf("> iPod nano 1g header detected.\n");
151 - return ADDR_DIR_1G;
152 - }
153 -
154 - // Check for 2G header
155 - if(check_header(fh,ADDR_DIR_2G))
156 - {
157 - printf("> iPod nano 2g header detected.\n");
158 - return ADDR_DIR_2G;
159 - }
160 -
161 - // Check for 3G header
162 - if(check_header(fh,ADDR_DIR_3G))
163 - {
164 - printf("> iPod nano 3g header detected.\n");
165 - return ADDR_DIR_3G;
166 - }
167 -
168 - // At least try to find an header
169 - fseek(fh, 0, SEEK_SET);
170 -
171 - DIRECTORY dir;
172 -
173 - while(!feof(fh))
174 - {
175 - fread( (void*)&dir, LEN_DIR, sizeof(char), fh);
176 - change_endian(dir.dev);
177 -
178 - if(is_valid(&dir))
179 - {
180 - int addr = ftell(fh) - LEN_DIR;
181 - printf("> Unknown header found at 0x%X\n",addr);
182 - return addr;
183 - }
184 -
185 - fseek(fh, -LEN_DIR + 1, SEEK_CUR);
186 - }
187 -
188 - return ADDR_DIR_DEFAULT;
189 -}
190 -
191 -void print_directory_infos(DIRECTORY* p_dir, char extended)
192 -{
193 - if( extended )
194 - printf("dev: %.4s type: %.4s\n\
195 -id: %X\n\
196 -devOffset: %X\n\
197 -len: %X\n\
198 -addr: %X\n\
199 -entryOffset: %X\n\
200 -checksum: %X\n\
201 -version: %X\n\
202 -loadAddr: %X\n\n",
203 - p_dir->dev,
204 - p_dir->type,
205 - p_dir->id,
206 - p_dir->devOffset,
207 - p_dir->len,
208 - p_dir->addr,
209 - p_dir->entryOffset,
210 - p_dir->checksum,
211 - p_dir->version,
212 - p_dir->loadAddr );
213 -
214 - else
215 - printf("dev: %.4s type: %.4s devOffset: %X len: %X\n",
216 - p_dir->dev,
217 - p_dir->type,
218 - p_dir->devOffset,
219 - p_dir->len);
220 -
221 -}
222 -
223 -
224 -/* Display help */
225 -void usage(int status)
226 -{
227 - if (status != EXIT_SUCCESS)
228 - fputs("Try `extract_2g --help' for more information.\n", stderr);
229 - else
230 - {
231 - fputs("Usage: extract_2g [OPTION] [FILE]\n", stdout);
232 - fprintf(stdout,"Read & extract iPod Nano 2G data parts from a FILE dump.\n\
233 -\n\
234 - -l, --list only list avaible parts according to the dump directory\n\n\
235 - -H, --hash do a hash on every part of the dump\n\n\
236 - -A, --all extract ALL founded parts from dump (default names used)\n\n\
237 - -e, --extract=NAME select which part you want to extract (default none)\n\
238 - -o, --output=FILE put the extracted part into FILE (default NAME.fw)\n\n\
239 - -d, --directory-address specify the directory address (default 0x%X )\n\
240 - -a, --header-length specify the header length of each part (default 0x800)\n\n\
241 - -h, --help display this help and exit\n", ADDR_DIR_DEFAULT);
242 - }
243 -
244 - exit(status);
245 -}
246 -
247 -int main(int argc, char **argv)
248 -{
249 - FILE *file = NULL;
250 - FILE *hExtract = NULL;
251 -
252 - char str_target[32];
253 -
254 - char extract_is_set = 0;
255 - char extract_all = 0;
256 - char list_directories = 0;
257 - char is_found = 0;
258 - char hash_parts = 0;
259 -
260 - /* REMOVE */
261 - char c;
262 -
263 - int tmp;
264 -
265 - int i;
266 -
267 - int directories_size = 0;
268 - DIRECTORY* directories = NULL;
269 -
270 - int addr_directory = -1;
271 -
272 - int length_header = LEN_HEADER;
273 -
274 - /* Getopt short options */
275 - static char const short_options[] = "e:o:d:a:AHlhv";
276 -
277 - /* Getopt long options */
278 - static struct option const long_options[] = {
279 - {"extract", required_argument, NULL, 'e'},
280 - {"output", required_argument, NULL, 'o'},
281 - {"hash", no_argument, NULL, 'H'},
282 - {"list", no_argument, NULL, 'l'},
283 - {"all", no_argument, NULL, 'A'},
284 - {"directory-address", required_argument, NULL, 'd'},
285 - {"header-length", required_argument, NULL, 'a'},
286 - {"help", no_argument, NULL, 'h'},
287 - {"version", no_argument, NULL, 'v'},
288 - {NULL, 0, NULL, 0}
289 - };
290 -
291 - /* Some informations */
292 - printf("%s compiled at %s %s.\n\n",argv[0],__TIME__,__DATE__);
293 -
294 - /* Parse command line options. */
295 - while ((c = getopt_long(argc, argv,
296 - short_options, long_options, NULL)) != -1) {
297 - switch (c) {
298 - case 'o':
299 - hExtract = fopen(optarg,"wb");
300 -
301 - if(!hExtract)
302 - {
303 - fprintf(stderr,"Cannot write/create %s.\n", optarg);
304 - usage(EXIT_FAILURE);
305 - }
306 -
307 - break;
308 -
309 - case 'a':
310 - if ( (tmp = strtol(optarg, NULL, 0)) > -1 )
311 - length_header = tmp;
312 - else {
313 - fprintf(stderr, "Invalid `header-length' value `%s'.\n", optarg);
314 - usage(EXIT_FAILURE);
315 - }
316 - break;
317 -
318 - case 'd':
319 - if ( (tmp = strtol(optarg, NULL, 0)) > 0 )
320 - addr_directory = tmp;
321 - else {
322 - fprintf(stderr, "Invalid `directory-address' value `%s'.\n", optarg);
323 - usage(EXIT_FAILURE);
324 - }
325 - break;
326 -
327 - case 'e':
328 - strncpy(str_target,optarg,32);
329 - extract_is_set = 1;
330 - break;
331 -
332 - case 'H':
333 - hash_parts = 1;
334 - break;
335 -
336 - case 'l':
337 - list_directories = 1;
338 - break;
339 -
340 - case 'A':
341 - extract_all = 1;
342 - break;
343 -
344 - case 'h':
345 - usage(EXIT_SUCCESS);
346 - break;
347 -
348 - case 'v':
349 - fprintf(stdout,"extract_2g version %d.%d\n",VERSION_H,VERSION_L);
350 - fputs("Copyright (C) 2007 Brossillon J.Damien\n\
351 -This is free software. You may redistribute copies of it under the terms\n\
352 -of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n\
353 -There is NO WARRANTY, to the extent permitted by law.\n", stdout);
354 - exit(EXIT_SUCCESS);
355 - break;
356 -
357 - default:
358 - usage(EXIT_FAILURE);
359 - }
360 - }
361 -
362 - if (!argv[optind]) {
363 - fprintf(stderr,"Missing dump filename.\n");
364 - usage(EXIT_FAILURE);
365 - } else {
366 - if (!(file = fopen(argv[optind], "rb")))
367 - {
368 - fprintf(stderr,"Cannot open file `%s'.\n", argv[optind]);
369 - usage(EXIT_FAILURE);
370 - }
371 - }
372 -
373 -
374 - if( addr_directory < 0 )
375 - addr_directory = guess_directory_address(file);
376 - else
377 - addr_directory = ADDR_DIR_DEFAULT;
378 -
379 -
380 - fseek(file, addr_directory, SEEK_SET);
381 -
382 - DIRECTORY dir;
383 -
384 - // List directories
385 - while(1)
386 - {
387 - /* FIXME
388 - for(i=0;i<(int)LEN_DIR;i++)
389 - {
390 - ((char*)&dir)[i] = fgetc(file);
391 - }*/
392 - fread( (void*)&dir, LEN_DIR, sizeof(char), file);
393 -
394 - change_endian(dir.dev);
395 - change_endian(dir.type);
396 -
397 - if( is_valid(&dir) )
398 - {
399 - directories_size++;
400 - directories = (DIRECTORY*)realloc(directories,
401 - directories_size*sizeof(DIRECTORY));
402 -
403 - if(!directories)
404 - {
405 - fprintf(stderr,"Memory allocation failure.\n");
406 - exit(EXIT_FAILURE);
407 - }
408 - dir.devOffset += 4096;
409 - memcpy(directories + directories_size - 1, &dir, sizeof(DIRECTORY));
410 - }
411 - else
412 - break;
413 - }
414 -
415 - // Check if we have, at least, one valid part
416 - if( directories_size <= 0 )
417 - {
418 - fclose(file);
419 -
420 - if(directories)
421 - free(directories);
422 -
423 - fprintf(stderr, "Cannot find at least one valid part in the dump.\n");
424 - exit(EXIT_FAILURE);
425 - }
426 -
427 - // User want to hash every parts of the dump
428 - if( hash_parts )
429 - {
430 -
431 - for(i=0;i<directories_size;i++)
432 - {
433 - fprintf(stdout,"%.4s: 0x%X\n",directories[i].type,
434 - hash_part(file,
435 - directories[i].devOffset, directories[i].len,
436 - length_header) );
437 - }
438 - }
439 - else
440 - if( extract_all )
441 - {
442 - // User want to extract every part of the dump
443 - for(i=0;i<directories_size;i++)
444 - {
445 - char name[5];
446 -
447 - memcpy(name,directories[i].type,4*sizeof(char));
448 - name[4] = '\0';
449 -
450 - extract_part(file, NULL,
451 - name,
452 - directories[i].devOffset, directories[i].len,
453 - length_header);
454 - }
455 -
456 - fprintf(stdout,"Done.\n");
457 -
458 -
459 - }
460 - else
461 - {
462 - if( list_directories )
463 - {
464 - // User ask a big directory listing
465 -
466 - for(i=0;i<directories_size; i++)
467 - print_directory_infos( &(directories[i]), 1 );
468 - }
469 - else
470 - {
471 -
472 - if( extract_is_set )
473 - {
474 - is_found = 0;
475 -
476 - for(i=0;i<directories_size;i++)
477 - if( !strcmp( directories[i].type, str_target ) )
478 - { // Extract & correct part name
479 -
480 - is_found = 1;
481 -
482 - // Lock & load, got name, file, position and length !
483 - extract_part(file, hExtract,
484 - directories[i].type,
485 - directories[i].devOffset, directories[i].len,
486 - length_header);
487 -
488 - }
489 -
490 - // Wrong part name, error message & small parts list
491 - if(!is_found)
492 - {
493 - fprintf(stderr,"No part named '%s' found.\n\n",str_target);
494 -
495 - for(i=0;i<directories_size;i++)
496 - print_directory_infos( &(directories[i]), 0);
497 - }
498 -
499 - }
500 - else
501 - { // No actions, small parts list
502 -
503 - for(i=0;i<directories_size;i++)
504 - print_directory_infos( &(directories[i]), 0);
505 - }
506 -
507 - }
508 - }
509 -
510 - fclose(file);
511 -
512 - free(directories);
513 -
514 - return EXIT_SUCCESS;
515 -}
Property changes on: tools/extract2g_HACKED/extract2g.c
___________________________________________________________________
Deleted: svn:executable
## -1 +0,0 ##
516 -*
\ No newline at end of property
Index: tools/extract2g_HACKED/README
@@ -1,13 +0,0 @@
2 -This is a hacked version of the original extract2g utility to work with the
3 -Nano 4G's new firmware changes. It breaks compatibility with all other firmware.
4 -
5 -Here are the only changes made:
6 -
7 -309c309
8 -< if ( (tmp = strtol(optarg, NULL, 0)) > 0 )
9 -> if ( (tmp = strtol(optarg, NULL, 0)) > -1 )
10 -407c407
11 -<
12 -> dir.devOffset += 4096;
Index: tools/extract2g_HACKED/extract2g.h
@@ -1,27 +0,0 @@
2 -
3 -#define ADDR_DIR_DEFAULT 0x4800
4 -#define ADDR_DIR_1G 0x4200
5 -#define ADDR_DIR_2G 0x4800
6 -#define ADDR_DIR_3G 0x5000
7 -
8 -
9 -#define LEN_HEADER 0x800
10 -
11 -#define LEN_DIR sizeof(DIRECTORY)
12 -
13 -typedef struct _DIRECTORY
14 -{
15 - char dev[4];
16 - char type[4];
17 -
18 - unsigned int id;
19 - unsigned int devOffset;
20 - unsigned int len;
21 - unsigned int addr;
22 -
23 - unsigned int entryOffset;
24 - unsigned int checksum;
25 - unsigned int version;
26 - unsigned int loadAddr;
27 -
28 -}DIRECTORY;
Property changes on: tools/extract2g_HACKED/extract2g.h
___________________________________________________________________
Deleted: svn:executable
## -1 +0,0 ##
29 -*
\ No newline at end of property
Index: tools/extract2g_HACKED/Makefile
@@ -1,11 +0,0 @@
2 -CC= gcc
3 -OPTS= -Wall -g
4 -
5 -all: extract2g
6 -
7 -extract2g: extract2g.c extract2g.h
8 - $(CC) $(OPTS) $< -o $@
9 -
10 -.PHONY: clean
11 -clean:
12 - rm -f extract2g
Property changes on: tools/extract2g_HACKED/Makefile
___________________________________________________________________
Deleted: svn:executable
## -1 +0,0 ##
13 -*
\ No newline at end of property
Index: tools/extract2g/extract2g.c
@@ -23,6 +23,9 @@
2424 1.1 - 2007-09-15
2525 -- Stuff added to guess the header versions.
2626
 27+ 1.2 - 2010-08-15
 28+ -- Added Nano 4G firmware support.
 29+
2730 Todo list:
2831 -- Debug
2932 */
@@ -36,7 +39,7 @@
3740 #include "extract2g.h"
3841
3942 #define VERSION_H 1
40 -#define VERSION_L 1
 43+#define VERSION_L 2
4144
4245 #define B (0x0FFFFFFF)
4346
@@ -230,14 +233,15 @@
231234 fputs("Usage: extract_2g [OPTION] [FILE]\n", stdout);
232235 fprintf(stdout,"Read & extract iPod Nano 2G data parts from a FILE dump.\n\
233236 \n\
234 - -l, --list only list avaible parts according to the dump directory\n\n\
235 - -H, --hash do a hash on every part of the dump\n\n\
236 - -A, --all extract ALL founded parts from dump (default names used)\n\n\
237 - -e, --extract=NAME select which part you want to extract (default none)\n\
238 - -o, --output=FILE put the extracted part into FILE (default NAME.fw)\n\n\
239 - -d, --directory-address specify the directory address (default 0x%X )\n\
240 - -a, --header-length specify the header length of each part (default 0x800)\n\n\
241 - -h, --help display this help and exit\n", ADDR_DIR_DEFAULT);
 237+-l, --list only list avaible parts according to the dump directory\n\n\
 238+-H, --hash do a hash on every part of the dump\n\n\
 239+-A, --all extract ALL founded parts from dump (default names used)\n\n\
 240+-4, --nano4g-compat forces iPod Nano 3G firmwares to be recognised as iPod Nano 4G's\n\n\
 241+-e, --extract=NAME select which part you want to extract (default none)\n\
 242+-o, --output=FILE put the extracted part into FILE (default NAME.fw)\n\n\
 243+-d, --directory-address specify the directory address (default 0x%X )\n\
 244+-a, --header-length specify the header length of each part (default 0x800)\n\n\
 245+-h, --help display this help and exit\n", ADDR_DIR_DEFAULT);
242246 }
243247
244248 exit(status);
@@ -252,6 +256,7 @@
253257
254258 char extract_is_set = 0;
255259 char extract_all = 0;
 260+ char nano4g_compat = 0;
256261 char list_directories = 0;
257262 char is_found = 0;
258263 char hash_parts = 0;
@@ -271,7 +276,7 @@
272277 int length_header = LEN_HEADER;
273278
274279 /* Getopt short options */
275 - static char const short_options[] = "e:o:d:a:AHlhv";
 280+ static char const short_options[] = "e:o:d:a:AHl4hv";
276281
277282 /* Getopt long options */
278283 static struct option const long_options[] = {
@@ -282,6 +287,7 @@
283288 {"all", no_argument, NULL, 'A'},
284289 {"directory-address", required_argument, NULL, 'd'},
285290 {"header-length", required_argument, NULL, 'a'},
 291+ {"nano4g-compat", no_argument, NULL, '4'},
286292 {"help", no_argument, NULL, 'h'},
287293 {"version", no_argument, NULL, 'v'},
288294 {NULL, 0, NULL, 0}
@@ -340,6 +346,10 @@
341347 extract_all = 1;
342348 break;
343349
 350+ case '4':
 351+ nano4g_compat = 1;
 352+ break;
 353+
344354 case 'h':
345355 usage(EXIT_SUCCESS);
346356 break;
@@ -375,7 +385,10 @@
376386 else
377387 addr_directory = ADDR_DIR_DEFAULT;
378388
 389+ if (addr_directory == ADDR_DIR_3G && nano4g_compat)
 390+ printf("> iPod nano 4g compat. mode enabled\n");
379391
 392+
380393 fseek(file, addr_directory, SEEK_SET);
381394
382395 DIRECTORY dir;
@@ -404,7 +417,10 @@
405418 fprintf(stderr,"Memory allocation failure.\n");
406419 exit(EXIT_FAILURE);
407420 }
408 -
 421+
 422+ if (addr_directory == ADDR_DIR_3G && nano4g_compat)
 423+ dir.devOffset += 4096;
 424+
409425 memcpy(directories + directories_size - 1, &dir, sizeof(DIRECTORY));
410426 }
411427 else