1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h> /* for strcmp() */
4
5
6 #define IMG_SIZE 0x3e0000
7
8 #define KERNEL_START 0x020000
9 #define KERNEL_SIZE 0x0b0000
10
11 #define ROOTFS_START 0x0d0000
12 #define ROOTFS_SIZE 0x30ffb2
13
14 char* app_name;
15
16
17
18
print_usage(void)19 void print_usage(void)
20 {
21 fprintf(stderr, "usage: dgfirmware [<opts>] <img>\n");
22 fprintf(stderr, " <img> firmware image filename\n");
23 fprintf(stderr, " <opts> -h print this message\n");
24 fprintf(stderr, " -f fix the checksum\n");
25 fprintf(stderr, " -x <file> extract the rootfs file to <file>\n");
26 fprintf(stderr, " -xk <file> extract the kernel to <file>\n");
27 fprintf(stderr, " -m <file> merge in rootfs fil\e from <file>\n");
28 fprintf(stderr, " -k <file> merge in kernel from <file>\n");
29 fprintf(stderr, " -w <file> write back the modified firmware\n");
30 }
31
32
read_img(const char * fname)33 unsigned char* read_img(const char *fname)
34 {
35 FILE *fp;
36 int size;
37 unsigned char *img;
38
39 fp = fopen(fname, "rb");
40 if (fp == NULL) {
41 perror(app_name);
42 exit(-1);
43 }
44
45 fseek(fp, 0, SEEK_END);
46 size = ftell(fp);
47
48 if (size != IMG_SIZE) {
49 fprintf(stderr, "%s: image file has wrong size\n", app_name);
50 fclose(fp);
51 exit(-1);
52 }
53
54 rewind(fp);
55
56 img = malloc(IMG_SIZE);
57 if (img == NULL) {
58 perror(app_name);
59 fclose(fp);
60 exit(-1);
61 }
62
63 if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
64 fprintf(stderr, "%s: can't read image file\n", app_name);
65 fclose(fp);
66 exit(-1);
67 }
68
69 fclose(fp);
70 return img;
71 }
72
73
write_img(unsigned char * img,const char * fname)74 void write_img(unsigned char* img, const char *fname)
75 {
76 FILE *fp;
77
78 fp = fopen(fname, "wb");
79 if (fp == NULL) {
80 perror(app_name);
81 exit(-1);
82 }
83
84 if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
85 fprintf(stderr, "%s: can't write image file\n", app_name);
86 fclose(fp);
87 exit(-1);
88 }
89 }
90
91
write_rootfs(unsigned char * img,const char * fname)92 void write_rootfs(unsigned char* img, const char *fname)
93 {
94 FILE *fp;
95
96 fp = fopen(fname, "wb");
97 if (fp == NULL) {
98 perror(app_name);
99 exit(-1);
100 }
101
102 if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) {
103 fprintf(stderr, "%s: can't write image file\n", app_name);
104 fclose(fp);
105 exit(-1);
106 }
107 }
108
109
write_kernel(unsigned char * img,const char * fname)110 void write_kernel(unsigned char* img, const char *fname)
111 {
112 FILE *fp;
113
114 fp = fopen(fname, "wb");
115 if (fp == NULL) {
116 perror(app_name);
117 exit(-1);
118 }
119
120 if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) {
121 fprintf(stderr, "%s: can't write kernel file\n", app_name);
122 fclose(fp);
123 exit(-1);
124 }
125 }
126
127
read_rootfs(unsigned char * img,const char * fname)128 unsigned char* read_rootfs(unsigned char* img, const char *fname)
129 {
130 FILE *fp;
131 int size;
132 int i;
133
134 for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++)
135 img[i] = 0xff;
136
137 fp = fopen(fname, "rb");
138 if (fp == NULL) {
139 perror(app_name);
140 exit(-1);
141 }
142
143 fseek(fp, 0, SEEK_END);
144 size = ftell(fp);
145
146 if (size > ROOTFS_SIZE) {
147 fprintf(stderr, "%s: rootfs image file is too big\n", app_name);
148 fclose(fp);
149 exit(-1);
150 }
151
152 rewind(fp);
153
154 if (fread(img+ROOTFS_START, 1, size, fp) != size) {
155 fprintf(stderr, "%s: can't read rootfs image file\n", app_name);
156 fclose(fp);
157 exit(-1);
158 }
159
160 fclose(fp);
161 return img;
162 }
163
164
read_kernel(unsigned char * img,const char * fname)165 unsigned char* read_kernel(unsigned char* img, const char *fname)
166 {
167 FILE *fp;
168 int size;
169 int i;
170
171 for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++)
172 img[i] = 0xff;
173
174 fp = fopen(fname, "rb");
175 if (fp == NULL) {
176 perror(app_name);
177 exit(-1);
178 }
179
180 fseek(fp, 0, SEEK_END);
181 size = ftell(fp);
182
183 if (size > KERNEL_SIZE) {
184 fprintf(stderr, "%s: kernel binary file is too big\n", app_name);
185 fclose(fp);
186 exit(-1);
187 }
188
189 rewind(fp);
190
191 if (fread(img+KERNEL_START, 1, size, fp) != size) {
192 fprintf(stderr, "%s: can't read kernel file\n", app_name);
193 fclose(fp);
194 exit(-1);
195 }
196
197 fclose(fp);
198 return img;
199 }
200
201
get_checksum(unsigned char * img)202 int get_checksum(unsigned char* img)
203 {
204 short unsigned s;
205
206 s = img[0x3dfffc] + (img[0x3dfffd]<<8);
207
208 return s;
209 }
210
211
set_checksum(unsigned char * img,unsigned short sum)212 void set_checksum(unsigned char*img, unsigned short sum)
213 {
214 img[0x3dfffc] = sum & 0xff;
215 img[0x3dfffd] = (sum>>8) & 0xff;
216 }
217
218
compute_checksum(unsigned char * img)219 int compute_checksum(unsigned char* img)
220 {
221 int i;
222 short s=0;
223
224 for (i=0; i<0x3dfffc; i++)
225 s += img[i];
226
227 return s;
228 }
229
230
main(int argc,char * argv[])231 int main(int argc, char* argv[])
232 {
233 char *img_fname = NULL;
234 char *rootfs_fname = NULL;
235 char *kernel_fname = NULL;
236 char *new_img_fname = NULL;
237
238 int do_fix_checksum = 0;
239 int do_write = 0;
240 int do_write_rootfs = 0;
241 int do_read_rootfs = 0;
242 int do_write_kernel = 0;
243 int do_read_kernel = 0;
244
245 int i;
246 unsigned char *img;
247 unsigned short img_checksum;
248 unsigned short real_checksum;
249
250 app_name = argv[0];
251
252 for (i=1; i<argc; i++) {
253 if (!strcmp(argv[i], "-h")) {
254 print_usage();
255 return 0;
256 }
257 else if (!strcmp(argv[i], "-f")) {
258 do_fix_checksum = 1;
259 }
260 else if (!strcmp(argv[i], "-x")) {
261 if (i+1 >= argc) {
262 fprintf(stderr, "%s: missing argument\n", app_name);
263 return -1;
264 }
265 do_write_rootfs = 1;
266 rootfs_fname = argv[i+1];
267 i++;
268 }
269 else if (!strcmp(argv[i], "-xk")) {
270 if (i+1 >= argc) {
271 fprintf(stderr, "%s: missing argument\n", app_name);
272 return -1;
273 }
274 do_write_kernel = 1;
275 kernel_fname = argv[i+1];
276 i++;
277 }
278 else if (!strcmp(argv[i], "-m")) {
279 if (i+1 >= argc) {
280 fprintf(stderr, "%s: missing argument\n", app_name);
281 return -1;
282 }
283 do_read_rootfs = 1;
284 rootfs_fname = argv[i+1];
285 i++;
286 }
287 else if (!strcmp(argv[i], "-k")) {
288 if (i+1 >= argc) {
289 fprintf(stderr, "%s: missing argument\n", app_name);
290 return -1;
291 }
292 do_read_kernel = 1;
293 kernel_fname = argv[i+1];
294 i++;
295 }
296 else if (!strcmp(argv[i], "-w")) {
297 if (i+1 >= argc) {
298 fprintf(stderr, "%s: missing argument\n", app_name);
299 return -1;
300 }
301 do_write = 1;
302 new_img_fname = argv[i+1];
303 i++;
304 }
305 else if (img_fname != 0) {
306 fprintf(stderr, "%s: too many arguments\n", app_name);
307 return -1;
308 }
309 else {
310 img_fname = argv[i];
311 }
312 }
313
314 if (img_fname == NULL) {
315 fprintf(stderr, "%s: missing argument\n", app_name);
316 return -1;
317 }
318
319 if ((do_read_rootfs && do_write_rootfs) ||
320 (do_read_kernel && do_write_kernel)) {
321 fprintf(stderr, "%s: conflictuous options\n", app_name);
322 return -1;
323 }
324
325 printf ("** Read firmware file\n");
326 img = read_img(img_fname);
327
328 printf ("Firmware product: %s\n", img+0x3dffbd);
329 printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]);
330
331 if (do_write_rootfs) {
332 printf ("** Write rootfs file\n");
333 write_rootfs(img, rootfs_fname);
334 }
335
336 if (do_write_kernel) {
337 printf ("** Write kernel file\n");
338 write_kernel(img, kernel_fname);
339 }
340
341 if (do_read_rootfs) {
342 printf ("** Read rootfs file\n");
343 read_rootfs(img, rootfs_fname);
344 do_fix_checksum = 1;
345 }
346
347 if (do_read_kernel) {
348 printf ("** Read kernel file\n");
349 read_kernel(img, kernel_fname);
350 do_fix_checksum = 1;
351 }
352
353 img_checksum = get_checksum(img);
354 real_checksum = compute_checksum(img);
355
356 printf ("image checksum = %04x\n", img_checksum);
357 printf ("real checksum = %04x\n", real_checksum);
358
359 if (do_fix_checksum) {
360 if (img_checksum != real_checksum) {
361 printf ("** Bad Checksum, fix it\n");
362 set_checksum(img, real_checksum);
363 }
364 else {
365 printf ("** Checksum is correct, good\n");
366 }
367 }
368
369 if (do_write) {
370 printf ("** Write image file\n");
371 write_img(img, new_img_fname);
372 }
373
374 free(img);
375 return 0;
376 }
377
378