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