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