diff options
Diffstat (limited to 'utils/ipod/flashsplit/flashsplit.c')
-rw-r--r-- | utils/ipod/flashsplit/flashsplit.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/utils/ipod/flashsplit/flashsplit.c b/utils/ipod/flashsplit/flashsplit.c new file mode 100644 index 0000000000..c4bb3b4255 --- /dev/null +++ b/utils/ipod/flashsplit/flashsplit.c | |||
@@ -0,0 +1,230 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Dave Chapman | ||
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 | |||
22 | #include <stdio.h> | ||
23 | #include <fcntl.h> | ||
24 | #include <unistd.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | static void int2be(unsigned int val, unsigned char* addr) | ||
28 | { | ||
29 | addr[0] = (val >> 24) & 0xff; | ||
30 | addr[1] = (val >> 16) & 0xff; | ||
31 | addr[2] = (val >> 8) & 0xff; | ||
32 | addr[3] = val & 0xFF; | ||
33 | } | ||
34 | |||
35 | static int le2int(unsigned char* buf) | ||
36 | { | ||
37 | int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
38 | |||
39 | return res; | ||
40 | } | ||
41 | |||
42 | static char* get_modelname(int version) | ||
43 | { | ||
44 | |||
45 | switch (version >> 8) { | ||
46 | case 0x01: | ||
47 | return "1g2g"; | ||
48 | break; | ||
49 | case 0x02: | ||
50 | return "ip3g"; | ||
51 | break; | ||
52 | case 0x40: | ||
53 | return "mini"; | ||
54 | break; | ||
55 | case 0x50: | ||
56 | return "ip4g"; | ||
57 | break; | ||
58 | case 0x60: | ||
59 | return "ipco"; | ||
60 | break; | ||
61 | case 0x70: | ||
62 | return "mn2g"; | ||
63 | break; | ||
64 | case 0xc0: | ||
65 | return "nano"; | ||
66 | break; | ||
67 | case 0xb0: | ||
68 | return "ipvd"; | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | return NULL; | ||
73 | } | ||
74 | |||
75 | static int get_modelnum(int version) | ||
76 | { | ||
77 | |||
78 | switch (version >> 8) { | ||
79 | case 0x01: | ||
80 | return 19; // "1g2g"; | ||
81 | break; | ||
82 | case 0x02: | ||
83 | return 7; // "ip3g"; | ||
84 | break; | ||
85 | case 0x40: | ||
86 | return 9; // "mini"; | ||
87 | break; | ||
88 | case 0x50: | ||
89 | return 8; // "ip4g"; | ||
90 | break; | ||
91 | case 0x60: | ||
92 | return 3; // "ipco"; | ||
93 | break; | ||
94 | case 0x70: | ||
95 | return 11; // "mn2g"; | ||
96 | break; | ||
97 | case 0xc0: | ||
98 | return 4; // "nano"; | ||
99 | break; | ||
100 | case 0xb0: | ||
101 | return 5; // "ipvd"; | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | return -1; | ||
106 | } | ||
107 | |||
108 | |||
109 | static void dump_app(char* name, unsigned char* p, unsigned char* flash) | ||
110 | { | ||
111 | char filename[64]; | ||
112 | unsigned char header[8]; | ||
113 | unsigned int i; | ||
114 | unsigned int sum; | ||
115 | int outfile; | ||
116 | |||
117 | unsigned int unknown1; | ||
118 | unsigned int offset; | ||
119 | unsigned int length; | ||
120 | unsigned int loadaddr; | ||
121 | unsigned int unknown2; | ||
122 | unsigned int checksum; | ||
123 | unsigned int version; | ||
124 | unsigned int unknown3; | ||
125 | char* modelname; | ||
126 | |||
127 | /* Extract variables from header */ | ||
128 | unknown1 = le2int(p+0x08); | ||
129 | offset = le2int(p+0x0c); | ||
130 | length = le2int(p+0x10); | ||
131 | loadaddr = le2int(p+0x14); | ||
132 | unknown2 = le2int(p+0x18); | ||
133 | checksum = le2int(p+0x1c); | ||
134 | version = le2int(p+0x20); | ||
135 | unknown3 = le2int(p+0x24); | ||
136 | |||
137 | modelname = get_modelname(version); | ||
138 | sum = 0; | ||
139 | |||
140 | for (i = offset; i < offset+length ; i++) { | ||
141 | sum += flash[i]; | ||
142 | } | ||
143 | |||
144 | /* Display information: */ | ||
145 | printf("Image: %s\n",name); | ||
146 | printf("unknown1: %08x\n",unknown1); | ||
147 | printf("offset: %08x\n",offset); | ||
148 | printf("length: %08x\n",length); | ||
149 | printf("loadaddr: %08x\n",loadaddr); | ||
150 | printf("unknown2: %08x\n",unknown2); | ||
151 | printf("checksum: %08x (flashsplit sum: %08x)\n",checksum,sum); | ||
152 | printf("version: %08x (ipod model: %s)\n",version,modelname); | ||
153 | printf("unknown3: %08x\n",unknown3); | ||
154 | printf("\n"); | ||
155 | |||
156 | if (modelname == NULL) { | ||
157 | printf("Unknown version, not exporting to .ipod file\n"); | ||
158 | return; | ||
159 | } else if (checksum != sum) { | ||
160 | printf("Checksum mismatch, not exporting to .ipod file\n"); | ||
161 | } else { | ||
162 | sum += get_modelnum(version); | ||
163 | int2be(sum,header); | ||
164 | memcpy(header+4,modelname,4); | ||
165 | |||
166 | sprintf(filename,"%s.ipod",name); | ||
167 | outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY,0666); | ||
168 | if (outfile < 0) { | ||
169 | fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); | ||
170 | return; | ||
171 | } | ||
172 | |||
173 | write(outfile,header,8); | ||
174 | write(outfile,flash+offset,length); | ||
175 | close(outfile); | ||
176 | } | ||
177 | |||
178 | sprintf(filename,"%s.bin",name); | ||
179 | outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY,0666); | ||
180 | if (outfile < 0) { | ||
181 | fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | write(outfile,flash+offset,length); | ||
186 | close(outfile); | ||
187 | } | ||
188 | |||
189 | int main(int argc,char* argv[]) | ||
190 | { | ||
191 | int fd; | ||
192 | unsigned char buf[1024*1024]; | ||
193 | unsigned char* p; | ||
194 | |||
195 | if (argc != 2) { | ||
196 | fprintf(stderr,"Usage: flashsplit flash.bin\n"); | ||
197 | return 1; | ||
198 | } | ||
199 | |||
200 | fd=open(argv[1],O_RDONLY); | ||
201 | if (fd < 0) { | ||
202 | fprintf(stderr,"Can not open %s\n",argv[1]); | ||
203 | return 1; | ||
204 | } | ||
205 | |||
206 | read(fd,buf,sizeof(buf)); | ||
207 | close(fd); | ||
208 | |||
209 | |||
210 | p = buf + 0xffe00; /* Start of flash directory */ | ||
211 | |||
212 | while (le2int(p) != 0) { | ||
213 | if (memcmp(p,"hslfksid",8)==0) { | ||
214 | dump_app("diskmode",p,buf); | ||
215 | } else if (memcmp(p,"hslfgaid",8)==0) { | ||
216 | dump_app("diagmode",p,buf); | ||
217 | } else if (memcmp(p,"hslfogol",8)==0) { | ||
218 | dump_app("logo",p,buf); | ||
219 | } else if (memcmp(p,"hslfnacs",8)==0) { | ||
220 | dump_app("diskscan",p,buf); | ||
221 | } else if (memcmp(p,"hslfscmv",8)==0) { | ||
222 | dump_app("vmcs",p,buf); | ||
223 | } else { | ||
224 | printf("Unknown image type - %c%c%c%c%c%c%c%c\n",p[3],p[2],p[1],p[0],p[7],p[6],p[5],p[4]); | ||
225 | } | ||
226 | p += 0x28; | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||