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