tools: otrx: allow own magic
[project/firmware-utils.git] / src / dgfirmware.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
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
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
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
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 fclose(fp);
91 }
92
93
94 void write_rootfs(unsigned char* img, const char *fname)
95 {
96 FILE *fp;
97
98 fp = fopen(fname, "wb");
99 if (fp == NULL) {
100 perror(app_name);
101 exit(-1);
102 }
103
104 if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) {
105 fprintf(stderr, "%s: can't write image file\n", app_name);
106 fclose(fp);
107 exit(-1);
108 }
109
110 fclose(fp);
111 }
112
113
114 void write_kernel(unsigned char* img, const char *fname)
115 {
116 FILE *fp;
117
118 fp = fopen(fname, "wb");
119 if (fp == NULL) {
120 perror(app_name);
121 exit(-1);
122 }
123
124 if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) {
125 fprintf(stderr, "%s: can't write kernel file\n", app_name);
126 fclose(fp);
127 exit(-1);
128 }
129
130 fclose(fp);
131 }
132
133
134 unsigned char* read_rootfs(unsigned char* img, const char *fname)
135 {
136 FILE *fp;
137 int size;
138 int i;
139
140 for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++)
141 img[i] = 0xff;
142
143 fp = fopen(fname, "rb");
144 if (fp == NULL) {
145 perror(app_name);
146 exit(-1);
147 }
148
149 fseek(fp, 0, SEEK_END);
150 size = ftell(fp);
151
152 if (size > ROOTFS_SIZE) {
153 fprintf(stderr, "%s: rootfs image file is too big\n", app_name);
154 fclose(fp);
155 exit(-1);
156 }
157
158 rewind(fp);
159
160 if (fread(img+ROOTFS_START, 1, size, fp) != size) {
161 fprintf(stderr, "%s: can't read rootfs image file\n", app_name);
162 fclose(fp);
163 exit(-1);
164 }
165
166 fclose(fp);
167 return img;
168 }
169
170
171 unsigned char* read_kernel(unsigned char* img, const char *fname)
172 {
173 FILE *fp;
174 int size;
175 int i;
176
177 for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++)
178 img[i] = 0xff;
179
180 fp = fopen(fname, "rb");
181 if (fp == NULL) {
182 perror(app_name);
183 exit(-1);
184 }
185
186 fseek(fp, 0, SEEK_END);
187 size = ftell(fp);
188
189 if (size > KERNEL_SIZE) {
190 fprintf(stderr, "%s: kernel binary file is too big\n", app_name);
191 fclose(fp);
192 exit(-1);
193 }
194
195 rewind(fp);
196
197 if (fread(img+KERNEL_START, 1, size, fp) != size) {
198 fprintf(stderr, "%s: can't read kernel file\n", app_name);
199 fclose(fp);
200 exit(-1);
201 }
202
203 fclose(fp);
204 return img;
205 }
206
207
208 int get_checksum(unsigned char* img)
209 {
210 short unsigned s;
211
212 s = img[0x3dfffc] + (img[0x3dfffd]<<8);
213
214 return s;
215 }
216
217
218 void set_checksum(unsigned char*img, unsigned short sum)
219 {
220 img[0x3dfffc] = sum & 0xff;
221 img[0x3dfffd] = (sum>>8) & 0xff;
222 }
223
224
225 int compute_checksum(unsigned char* img)
226 {
227 int i;
228 short s=0;
229
230 for (i=0; i<0x3dfffc; i++)
231 s += img[i];
232
233 return s;
234 }
235
236
237 int main(int argc, char* argv[])
238 {
239 char *img_fname = NULL;
240 char *rootfs_fname = NULL;
241 char *kernel_fname = NULL;
242 char *new_img_fname = NULL;
243
244 int do_fix_checksum = 0;
245 int do_write = 0;
246 int do_write_rootfs = 0;
247 int do_read_rootfs = 0;
248 int do_write_kernel = 0;
249 int do_read_kernel = 0;
250
251 int i;
252 unsigned char *img;
253 unsigned short img_checksum;
254 unsigned short real_checksum;
255
256 app_name = argv[0];
257
258 for (i=1; i<argc; i++) {
259 if (!strcmp(argv[i], "-h")) {
260 print_usage();
261 return 0;
262 }
263 else if (!strcmp(argv[i], "-f")) {
264 do_fix_checksum = 1;
265 }
266 else if (!strcmp(argv[i], "-x")) {
267 if (i+1 >= argc) {
268 fprintf(stderr, "%s: missing argument\n", app_name);
269 return -1;
270 }
271 do_write_rootfs = 1;
272 rootfs_fname = argv[i+1];
273 i++;
274 }
275 else if (!strcmp(argv[i], "-xk")) {
276 if (i+1 >= argc) {
277 fprintf(stderr, "%s: missing argument\n", app_name);
278 return -1;
279 }
280 do_write_kernel = 1;
281 kernel_fname = argv[i+1];
282 i++;
283 }
284 else if (!strcmp(argv[i], "-m")) {
285 if (i+1 >= argc) {
286 fprintf(stderr, "%s: missing argument\n", app_name);
287 return -1;
288 }
289 do_read_rootfs = 1;
290 rootfs_fname = argv[i+1];
291 i++;
292 }
293 else if (!strcmp(argv[i], "-k")) {
294 if (i+1 >= argc) {
295 fprintf(stderr, "%s: missing argument\n", app_name);
296 return -1;
297 }
298 do_read_kernel = 1;
299 kernel_fname = argv[i+1];
300 i++;
301 }
302 else if (!strcmp(argv[i], "-w")) {
303 if (i+1 >= argc) {
304 fprintf(stderr, "%s: missing argument\n", app_name);
305 return -1;
306 }
307 do_write = 1;
308 new_img_fname = argv[i+1];
309 i++;
310 }
311 else if (img_fname != 0) {
312 fprintf(stderr, "%s: too many arguments\n", app_name);
313 return -1;
314 }
315 else {
316 img_fname = argv[i];
317 }
318 }
319
320 if (img_fname == NULL) {
321 fprintf(stderr, "%s: missing argument\n", app_name);
322 return -1;
323 }
324
325 if ((do_read_rootfs && do_write_rootfs) ||
326 (do_read_kernel && do_write_kernel)) {
327 fprintf(stderr, "%s: conflictuous options\n", app_name);
328 return -1;
329 }
330
331 printf ("** Read firmware file\n");
332 img = read_img(img_fname);
333
334 printf ("Firmware product: %s\n", img+0x3dffbd);
335 printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]);
336
337 if (do_write_rootfs) {
338 printf ("** Write rootfs file\n");
339 write_rootfs(img, rootfs_fname);
340 }
341
342 if (do_write_kernel) {
343 printf ("** Write kernel file\n");
344 write_kernel(img, kernel_fname);
345 }
346
347 if (do_read_rootfs) {
348 printf ("** Read rootfs file\n");
349 read_rootfs(img, rootfs_fname);
350 do_fix_checksum = 1;
351 }
352
353 if (do_read_kernel) {
354 printf ("** Read kernel file\n");
355 read_kernel(img, kernel_fname);
356 do_fix_checksum = 1;
357 }
358
359 img_checksum = get_checksum(img);
360 real_checksum = compute_checksum(img);
361
362 printf ("image checksum = %04x\n", img_checksum);
363 printf ("real checksum = %04x\n", real_checksum);
364
365 if (do_fix_checksum) {
366 if (img_checksum != real_checksum) {
367 printf ("** Bad Checksum, fix it\n");
368 set_checksum(img, real_checksum);
369 }
370 else {
371 printf ("** Checksum is correct, good\n");
372 }
373 }
374
375 if (do_write) {
376 printf ("** Write image file\n");
377 write_img(img, new_img_fname);
378 }
379
380 free(img);
381 return 0;
382 }
383