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
13char* app_name;
14
15
16
17
18void 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
32unsigned 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
73void 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
91void 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
109void 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
127unsigned 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
164unsigned 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
201int 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
211void set_checksum(unsigned char*img, unsigned short sum)
212{
213  img[0x3dfffc] = sum & 0xff;
214  img[0x3dfffd] = (sum>>8) & 0xff;
215}
216
217
218int 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
230int 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
377