• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    Xceive XC2028/3028 tuner module firmware manipulation tool
3 
4    Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
5 
6    Copyright (C) 2007, 2008 Mauro Carvalho Chehab <mchehab@kernel.org>
7 	- Improve --list command
8 	- Add --seek command
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation version 2
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <getopt.h>
29 #include <string.h>
30 #include <unistd.h>
31 
32 #include <asm/byteorder.h>
33 #include <asm/types.h>
34 
35 #include "xc2028-types.h"
36 #include "linux/videodev2.h"
37 
38 #include "extract_head.h"
39 #include "standards.h"
40 
41 #define LIST_ACTION		(1<<0)
42 #define ADD_ACTION		(1<<1)
43 #define DELETE_ACTION		(1<<2)
44 #define SET_TYPE_ACTION		(1<<3)
45 #define SET_ID_ACTION		(1<<4)
46 #define SEEK_FIRM_ACTION	(1<<5)
47 
48 struct firmware_description {
49 	__u32 type;
50 	__u64 id;
51 	unsigned char *data;
52 	__u16 int_freq;
53 	__u32 size;
54 };
55 
56 struct firmware {
57 	char* name;
58 	struct firmware_description* desc;
59 	__u16 version;
60 	__u16 nr_desc;
61 };
62 
63 #if 0
64 static struct firmware_description* alloc_firmware_description(void) {
65 	struct firmware_description *d = malloc(sizeof(*d));
66 	d->type = 0;
67 	d->id = 0;
68 	d->data = NULL;
69 	d->size = 0;
70 	return d;
71 }
72 
73 static void free_firmware_description(struct firmware_description *d) {
74 	free(d->data);
75 	free(d);
76 }
77 #endif
78 
alloc_firmware(void)79 static struct firmware* alloc_firmware(void) {
80 	struct firmware *f = malloc(sizeof(*f));
81 	f->name = NULL;
82 	f->desc = NULL;
83 	f->nr_desc = 0;
84 	return f;
85 }
86 
free_firmware(struct firmware * f)87 static void free_firmware(struct firmware *f) {
88 	free(f->name);
89 	if(f->desc) {
90 		unsigned int i = 0;
91 		for(i = 0; i < f->nr_desc; ++ i) {
92 			free(f->desc[i].data);
93 		}
94 	}
95 	free(f->desc);
96 	free(f);
97 }
98 
add_firmware_description(struct firmware * f,struct firmware_description * d)99 static void add_firmware_description(struct firmware *f,
100 			      struct firmware_description *d) {
101 	struct firmware_description* new_desc;
102 
103 	new_desc = malloc((f->nr_desc + 1) * sizeof(*new_desc));
104 	memcpy(new_desc, f->desc, f->nr_desc * sizeof(*new_desc));
105 	memcpy(new_desc + f->nr_desc, d, sizeof(*d));
106 	free(f->desc);
107 	f->desc = new_desc;
108 	++f->nr_desc;
109 }
110 
delete_firmware_description(struct firmware * f,__u16 i)111 static void delete_firmware_description(struct firmware *f, __u16 i) {
112 	struct firmware_description* new_desc;
113 
114 	if(f->nr_desc == 0 || i >= f->nr_desc) {
115 		return;
116 	}
117 
118 	new_desc = malloc((f->nr_desc - 1) * sizeof(*new_desc));
119 	memcpy(new_desc, f->desc, i * sizeof(*f->desc));
120 	memcpy(new_desc + i, f->desc + i + 1, (f->nr_desc - i - 1) * sizeof(*f->desc));
121 	free(f->desc);
122 	f->desc = new_desc;
123 	--f->nr_desc;
124 }
125 
126 /* name[32] + version[2] + nr_desc[2] */
127 #define HEADER_LENGTH (32 + 2 + 2)
128 /* description header: 4 + 8 + 4.*/
129 #define DESC_HEADER_LENGTH (4 + 8 + 4)
130 
read_firmware(unsigned char * data,off_t size,struct firmware ** f_res)131 static int read_firmware(unsigned char* data, off_t size, struct firmware** f_res) {
132 	char *name = malloc(33);
133 	unsigned char *p = data;
134 	struct firmware* f = alloc_firmware();
135 	unsigned int i;
136 
137 	if(size < HEADER_LENGTH) {
138 		printf("Invalid firmware header length.\n");
139 		free_firmware(f);
140 		return -1;
141 	}
142 	name[32] = 0;
143 	memcpy(name, data, 32);
144 	f->name = name;
145 	p += 32;
146 	f->version = __le16_to_cpu(*(__u16*)p);
147 	p += sizeof(f->version);
148 	f->nr_desc = __le16_to_cpu(*(__u16*)p);
149 	p += sizeof(f->nr_desc);
150 	f->desc = malloc(f->nr_desc * sizeof(*(f->desc)));
151 
152 	for(i = 0; i < f->nr_desc; ++i) {
153 		if(p + DESC_HEADER_LENGTH > data + size) {
154 			printf("Invalid description header length.\n");
155 			free_firmware(f);
156 			return -1;
157 		}
158 		f->desc[i].type = __le32_to_cpu(*(__u32*) p);
159 		p += sizeof(f->desc[i].type);
160 		f->desc[i].id = __le64_to_cpu(*(__u64*) p);
161 		p += sizeof(f->desc[i].id);
162 
163 		if (f->desc[i].type & HAS_IF) {
164 			f->desc[i].int_freq = __le16_to_cpu(*(__u16 *) p);
165 			p += sizeof(f->desc[i].int_freq);
166 		}
167 
168 		f->desc[i].size = __le32_to_cpu(*(__u32*) p);
169 		p += sizeof(f->desc[i].size);
170 
171 		if(p + f->desc[i].size > data + size) {
172 			printf("Invalid firmware standard length.\n");
173 			f->nr_desc = (f->nr_desc == 0) ? 0 : f->nr_desc -1;
174 			free_firmware(f);
175 			return -1;
176 		}
177 
178 		f->desc[i].data = malloc(f->desc[i].size);
179 		memcpy(f->desc[i].data, p, f->desc[i].size);
180 
181 		p += f->desc[i].size;
182 	}
183 
184 	*f_res = f;
185 	return 0;
186 }
187 
write_firmware(struct firmware * f,unsigned char ** r_data,off_t * r_size)188 static void write_firmware(struct firmware *f, unsigned char** r_data, off_t *r_size) {
189 	off_t size;
190 	unsigned int i = 0;
191 	unsigned char* data;
192 	unsigned char* p;
193 
194 	size = HEADER_LENGTH + f->nr_desc * DESC_HEADER_LENGTH;
195 	for(i = 0; i < f->nr_desc; ++i) {
196 		size += f->desc[i].size;
197 	}
198 
199 	data = malloc(size);
200 	p = data;
201 
202 	memcpy(p, f->name, 32);
203 	p += 32;
204 
205 	*(__u16*)p = __cpu_to_le16(f->version);
206 	p += sizeof(f->version);
207 
208 	*(__u16*)p = __cpu_to_le16(f->nr_desc);
209 	p += sizeof(f->nr_desc);
210 
211 	for(i = 0; i < f->nr_desc; ++i) {
212 		*(__u32*) p = __cpu_to_le32(f->desc[i].type);
213 		p += sizeof(f->desc[i].type);
214 
215 		*(__u64*) p = __cpu_to_le64(f->desc[i].id);
216 		p += sizeof(f->desc[i].id);
217 
218 		*(__u32*) p = __cpu_to_le32(f->desc[i].size);
219 		p += sizeof(f->desc[i].size);
220 
221 		memcpy(p, f->desc[i].data, f->desc[i].size);
222 		p += f->desc[i].size;
223 	}
224 
225 	*r_data = data;
226 	*r_size = size;
227 }
228 
read_firmware_file(const char * filename)229 static struct firmware* read_firmware_file(const char* filename) {
230 	struct stat buf;
231 	unsigned char *ptr;
232 	struct firmware *f;
233 	int fd;
234 
235 	if(stat(filename, &buf) < 0) {
236 		perror("Error during stat");
237 		return NULL;
238 	}
239 
240 	fd = open(filename, O_RDONLY);
241 	if(fd < 0) {
242 		perror("Error while opening the firmware file");
243 		return NULL;
244 	}
245 
246 	/* allocate firmware buffer*/
247 	ptr = malloc(buf.st_size);
248 
249 	if(read(fd, ptr, buf.st_size) < 0) {
250 		perror("Error while reading the firmware file");
251 		free(ptr);
252 		close(fd);
253 		return NULL;
254 	}
255 
256 	if(read_firmware(ptr, buf.st_size, &f) < 0) {
257 		printf("Invalid firmware file!\n");
258 		free(ptr);
259 		close(fd);
260 		return NULL;
261 	}
262 
263 	close(fd);
264 	free(ptr);
265 	return f;
266 }
267 
write_firmware_file(const char * filename,struct firmware * f)268 static void write_firmware_file(const char* filename, struct firmware *f) {
269 	int fd;
270 	unsigned char* data;
271 	off_t size = 0;
272 
273 	fd = open(filename, O_WRONLY | O_CREAT, 0644);
274 	if(fd < 0) {
275 		perror("Error while opening the firmware file");
276 		return;
277 	}
278 
279 	if(ftruncate(fd, 0) < 0) {
280 		perror("Error while deleting the firmware file");
281 		close(fd);
282 		return;
283 	}
284 
285 	write_firmware(f, &data, &size);
286 
287 	if(write(fd, data, size) < 0) {
288 		perror("Error while writing the firmware file");
289 		close(fd);
290 		return;
291 	}
292 
293 	free(data);
294 	close(fd);
295 }
296 
dump_firm_type(FILE * fp,unsigned int type)297 static void dump_firm_type(FILE *fp, unsigned int type)
298 {
299 	if (type & SCODE)
300 		fprintf(fp, "SCODE FW  ");
301 	else if (type & BASE)
302 		fprintf(fp, "BASE FW   ");
303 	else
304 		fprintf(fp, "STD FW    ");
305 
306 	if (type & F8MHZ)
307 		fprintf(fp, "F8MHZ ");
308 	if (type & MTS)
309 		fprintf(fp, "MTS ");
310 	if (type & D2620)
311 		fprintf(fp, "D2620 ");
312 	if (type & D2633)
313 		fprintf(fp, "D2633 ");
314 	if (type & DTV6)
315 		fprintf(fp, "DTV6 ");
316 	if (type & QAM)
317 		fprintf(fp, "QAM ");
318 	if (type & DTV7)
319 		fprintf(fp, "DTV7 ");
320 	if (type & DTV78)
321 		fprintf(fp, "DTV78 ");
322 	if (type & DTV8)
323 		fprintf(fp, "DTV8 ");
324 	if (type & FM)
325 		fprintf(fp, "FM ");
326 	if (type & INPUT1)
327 		fprintf(fp, "INPUT1 ");
328 	if (type & LCD)
329 		fprintf(fp, "LCD ");
330 	if (type & NOGD)
331 		fprintf(fp, "NOGD ");
332 	if (type & MONO)
333 		fprintf(fp, "MONO ");
334 	if (type & ATSC)
335 		fprintf(fp, "ATSC ");
336 	if (type & IF)
337 		fprintf(fp, "IF ");
338 	if (type & LG60)
339 		fprintf(fp, "LG60 ");
340 	if (type & ATI638)
341 		fprintf(fp, "ATI638 ");
342 	if (type & OREN538)
343 		fprintf(fp, "OREN538 ");
344 	if (type & OREN36)
345 		fprintf(fp, "OREN36 ");
346 	if (type & TOYOTA388)
347 		fprintf(fp, "TOYOTA388 ");
348 	if (type & TOYOTA794)
349 		fprintf(fp, "TOYOTA794 ");
350 	if (type & DIBCOM52)
351 		fprintf(fp, "DIBCOM52 ");
352 	if (type & ZARLINK456)
353 		fprintf(fp, "ZARLINK456 ");
354 	if (type & CHINA)
355 		fprintf(fp, "CHINA ");
356 	if (type & F6MHZ)
357 		fprintf(fp, "F6MHZ ");
358 	if (type & INPUT2)
359 		fprintf(fp, "INPUT2 ");
360 	if (type & HAS_IF)
361 		fprintf(fp, "HAS IF ");
362 }
363 
dump_firm_std(FILE * fp,v4l2_std_id id)364 static void dump_firm_std(FILE *fp, v4l2_std_id id)
365 {
366 	v4l2_std_id old=-1, curr_id;
367 
368 	/* Dumps video standards */
369 	while (old!=id) {
370 		old=id;
371 		if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
372 			fprintf (fp, "PAL ");
373 			curr_id = V4L2_STD_PAL;
374 		} else if ( (id & V4L2_STD_MN) == V4L2_STD_MN) {
375 			fprintf (fp, "NTSC PAL/M PAL/N ");
376 			curr_id = V4L2_STD_PAL;
377 		} else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
378 			fprintf (fp, "PAL/BG ");
379 			curr_id = V4L2_STD_PAL_BG;
380 		} else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
381 			fprintf (fp, "PAL/DK ");
382 			curr_id = V4L2_STD_PAL_DK;
383 		} else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
384 			fprintf (fp, "PAL/B ");
385 			curr_id = V4L2_STD_PAL_B;
386 		} else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
387 			fprintf (fp, "PAL/B1 ");
388 			curr_id = V4L2_STD_PAL_B1;
389 		} else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
390 			fprintf (fp, "PAL/G ");
391 			curr_id = V4L2_STD_PAL_G;
392 		} else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
393 			fprintf (fp, "PAL/H ");
394 			curr_id = V4L2_STD_PAL_H;
395 		} else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
396 			fprintf (fp, "PAL/I ");
397 			curr_id = V4L2_STD_PAL_I;
398 		} else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
399 			fprintf (fp, "PAL/D ");
400 			curr_id = V4L2_STD_PAL_D;
401 		} else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
402 			fprintf (fp, "PAL/D1 ");
403 			curr_id = V4L2_STD_PAL_D1;
404 		} else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
405 			fprintf (fp, "PAL/K ");
406 			curr_id = V4L2_STD_PAL_K;
407 		} else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
408 			fprintf (fp, "PAL/M ");
409 			curr_id = V4L2_STD_PAL_M;
410 		} else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
411 			fprintf (fp, "PAL/N ");
412 			curr_id = V4L2_STD_PAL_N;
413 		} else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
414 			fprintf (fp, "PAL/Nc ");
415 			curr_id = V4L2_STD_PAL_Nc;
416 		} else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
417 			fprintf (fp, "PAL/60 ");
418 			curr_id = V4L2_STD_PAL_60;
419 		} else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
420 			fprintf (fp, "NTSC ");
421 			curr_id = V4L2_STD_NTSC;
422 		} else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
423 			fprintf (fp, "NTSC/M ");
424 			curr_id = V4L2_STD_NTSC_M;
425 		} else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
426 			fprintf (fp, "NTSC/M Jp ");
427 			curr_id = V4L2_STD_NTSC_M_JP;
428 		} else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
429 			fprintf (fp, "NTSC 443 ");
430 			curr_id = V4L2_STD_NTSC_443;
431 		} else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
432 			fprintf (fp, "NTSC/M Kr ");
433 			curr_id = V4L2_STD_NTSC_M_KR;
434 		} else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
435 			fprintf (fp, "SECAM ");
436 			curr_id = V4L2_STD_SECAM;
437 		} else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
438 			fprintf (fp, "SECAM/DK ");
439 			curr_id = V4L2_STD_SECAM_DK;
440 		} else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
441 			fprintf (fp, "SECAM/B ");
442 			curr_id = V4L2_STD_SECAM_B;
443 		} else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
444 			fprintf (fp, "SECAM/D ");
445 			curr_id = V4L2_STD_SECAM_D;
446 		} else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
447 			fprintf (fp, "SECAM/G ");
448 			curr_id = V4L2_STD_SECAM_G;
449 		} else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
450 			fprintf (fp, "SECAM/H ");
451 			curr_id = V4L2_STD_SECAM_H;
452 		} else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
453 			fprintf (fp, "SECAM/K ");
454 			curr_id = V4L2_STD_SECAM_K;
455 		} else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
456 			fprintf (fp, "SECAM/K1 ");
457 			curr_id = V4L2_STD_SECAM_K1;
458 		} else if ( (id & V4L2_STD_SECAM_K3) == V4L2_STD_SECAM_K3) {
459 			fprintf (fp, "SECAM/K3 ");
460 			curr_id = V4L2_STD_SECAM_K3;
461 		} else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
462 			fprintf (fp, "SECAM/L ");
463 			curr_id = V4L2_STD_SECAM_L;
464 		} else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
465 			fprintf (fp, "SECAM/Lc ");
466 			curr_id = V4L2_STD_SECAM_LC;
467 		} else if ( (id & V4L2_STD_A2) == V4L2_STD_A2) {
468 			fprintf (fp, "A2 ");
469 			curr_id = V4L2_STD_A2;
470 		} else if ( (id & V4L2_STD_A2_A) == V4L2_STD_A2_A) {
471 			fprintf (fp, "A2/A ");
472 			curr_id = V4L2_STD_A2_A;
473 		} else if ( (id & V4L2_STD_A2_B) == V4L2_STD_A2_B) {
474 			fprintf (fp, "A2/B ");
475 			curr_id = V4L2_STD_A2_B;
476 		} else if ( (id & V4L2_STD_NICAM) == V4L2_STD_NICAM) {
477 			fprintf (fp, "NICAM ");
478 			curr_id = V4L2_STD_NICAM;
479 		} else if ( (id & V4L2_STD_NICAM_A) == V4L2_STD_NICAM_A) {
480 			fprintf (fp, "NICAM/A ");
481 			curr_id = V4L2_STD_NICAM_A;
482 		} else if ( (id & V4L2_STD_NICAM_B) == V4L2_STD_NICAM_B) {
483 			fprintf (fp, "NICAM/B ");
484 			curr_id = V4L2_STD_NICAM_B;
485 		} else if ( (id & V4L2_STD_AM) == V4L2_STD_AM) {
486 			fprintf (fp, "AM ");
487 			curr_id = V4L2_STD_AM;
488 		} else if ( (id & V4L2_STD_BTSC) == V4L2_STD_BTSC) {
489 			fprintf (fp, "BTSC ");
490 			curr_id = V4L2_STD_BTSC;
491 		} else if ( (id & V4L2_STD_EIAJ) == V4L2_STD_EIAJ) {
492 			fprintf (fp, "EIAJ ");
493 			curr_id = V4L2_STD_EIAJ;
494 		} else {
495 			curr_id = 0;
496 			break;
497 		}
498 		id &= ~curr_id;
499 	}
500 }
501 
list_firmware_desc(FILE * fp,struct firmware_description * desc)502 static void list_firmware_desc(FILE *fp, struct firmware_description *desc)
503 {
504 	fprintf(fp, "type: ");
505 	dump_firm_type(fp, desc->type);
506 	fprintf(fp, "(0x%08x), ", desc->type);
507 	if (desc->type & HAS_IF)
508 		fprintf(fp, "IF = %.2f MHz ", desc->int_freq/1000.0);
509 	fprintf(fp, "id: ");
510 	dump_firm_std(fp, desc->id);
511 	fprintf(fp, "(%016llx), ", desc->id);
512 	fprintf(fp, "size: %u\n", desc->size);
513 }
514 
list_firmware(struct firmware * f,unsigned int dump,char * binfile)515 static void list_firmware(struct firmware *f, unsigned int dump, char *binfile)
516 {
517 	unsigned int i = 0;
518 
519 	printf("firmware name:\t%s\n", f->name);
520 	printf("version:\t%d.%d (%u)\n", f->version >> 8, f->version & 0xff,
521 					  f->version);
522 	printf("standards:\t%u\n", f->nr_desc);
523 	for(i = 0; i < f->nr_desc; ++i) {
524 		printf("Firmware %2u, ", i);
525 		list_firmware_desc(stdout, &f->desc[i]);
526 		if (dump) {
527 			printf("\t");
528 			unsigned j, k = 0;
529 			for (j = 0; j < f->desc[i].size; j++) {
530 				printf("%02x", f->desc[i].data[j]);
531 
532 				k++;
533 				if (k >= 32) {
534 					printf("\n\t");
535 					k = 0;
536 				} else if (!(k % 2))
537 					printf(" ");
538 			}
539 			printf("\n");
540 		}
541 		if (binfile) {
542 			char name[strlen(binfile)+4], *p;
543 			p = strrchr(binfile,'.');
544 			if (p) {
545 				int n = p - binfile;
546 				strncpy(name, binfile, n);
547 				sprintf(name + n, "%03i", i);
548 				strcat(name, p);
549 			} else {
550 				strcpy(name, binfile);
551 				sprintf(name + strlen(name), "%03i", i);
552 			}
553 			FILE *fp;
554 
555 			fp = fopen(name,"w");
556 			if (!fp) {
557 				perror("Opening file to write");
558 				return;
559 			}
560 			fwrite(f->desc[i].data, f->desc[i].size, 1, fp);
561 			fclose(fp);
562 		}
563 	}
564 }
565 
add_standard(struct firmware * f,char * firmware_file,char * standard_file)566 static void add_standard(struct firmware* f, char* firmware_file, char* standard_file) {
567 	unsigned char* standard_data;
568 	unsigned int len;
569 	struct firmware_description desc;
570 
571 	create_standard_data(standard_file, &standard_data, &len);
572 	if(!standard_data) {
573 		fprintf(stderr, "Couldn't create the firmware standard data.\n");
574 		return;
575 	}
576 	desc.id = 0;
577 	desc.type = 0;
578 	desc.size = len;
579 	desc.data = standard_data;
580 	add_firmware_description(f, &desc);
581 	write_firmware_file(firmware_file, f);
582 }
583 
delete_standard(struct firmware * f,char * firmware_file,__u16 i)584 static void delete_standard(struct firmware* f, char* firmware_file, __u16 i) {
585 	delete_firmware_description(f, i);
586 	write_firmware_file(firmware_file, f);
587 }
588 
set_standard_type(struct firmware * f,char * firmware_file,__u16 i,__u32 type)589 static void set_standard_type(struct firmware* f, char* firmware_file, __u16 i, __u32 type) {
590 	if(i > f->nr_desc) {
591 		return;
592 	}
593 	f->desc[i].type = type;
594 	write_firmware_file(firmware_file, f);
595 }
596 
set_standard_id(struct firmware * f,char * firmware_file,__u16 i,__u32 id)597 static void set_standard_id(struct firmware* f, char* firmware_file, __u16 i, __u32 id) {
598 	if(i > f->nr_desc) {
599 		return;
600 	}
601 	f->desc[i].id = id;
602 	write_firmware_file(firmware_file, f);
603 }
604 
605 struct chunk_hunk;
606 
607 struct chunk_hunk {
608 	unsigned char *data;
609 	long pos;
610 	int size;
611 	int need_fix_endian;
612 	int hint_method;
613 	struct chunk_hunk *next;
614 };
615 
seek_chunks(struct chunk_hunk * fhunk,unsigned char * seek,unsigned char * endp,unsigned char * fdata,unsigned char * endf)616 static int seek_chunks(struct chunk_hunk *fhunk,
617 		unsigned char *seek, unsigned char *endp,	/* File to seek */
618 		unsigned char *fdata, unsigned char *endf)	/* Firmware */
619 {
620 	unsigned char *fpos, *p, *p2;
621 	int fsize;
622 	unsigned char *temp_data;
623 	struct chunk_hunk *hunk = fhunk;
624 	/* Method 3 vars */
625 	static unsigned char *base_start = 0;
626 	int ini_sig = 8, sig_len = 14, end_sig = 8;
627 
628 	/* Method 1a: Seek for a complete firmware */
629 	for (p = seek; p < endp; p++) {
630 		fpos = p;
631 		for (p2 = fdata; p2 < endf; p2++, fpos++) {
632 			if (*fpos != *p2)
633 				break;
634 		}
635 		if (p2 == endf) {
636 			hunk->data = NULL;
637 			hunk->pos = p - seek;
638 			hunk->size = endf - fdata;
639 			hunk->next = NULL;
640 			hunk->need_fix_endian = 0;
641 			hunk->hint_method = 0;
642 			return 1;
643 		}
644 	}
645 
646 	fsize = endf - fdata;
647 	temp_data = malloc(fsize);
648 	memcpy(temp_data, fdata, fsize);
649 
650 	/* Try again, changing endian */
651 	for (p2 = temp_data; p2 < temp_data + fsize;) {
652 		unsigned char c;
653 		int size = *p2 + (*(p2 + 1) << 8);
654 		c = *p2;
655 		*p2 = *(p2 + 1);
656 		*(p2 + 1) = c;
657 		p2+=2;
658 		if ((size > 0) && (size < 0x8000))
659 			p2 += size;
660 	}
661 
662 	/* Method 1b: Seek for a complete firmware with changed endians */
663 	for (p = seek; p < endp; p++) {
664 		fpos = p;
665 		for (p2 = temp_data; p2 < temp_data + fsize; p2++, fpos++) {
666 			if (*fpos != *p2)
667 				break;
668 		}
669 		if (p2 == temp_data + fsize) {
670 			hunk->data = NULL;
671 			hunk->pos = p - seek;
672 			hunk->size = endf - fdata;
673 			hunk->next = NULL;
674 			hunk->need_fix_endian = 1;
675 			hunk->hint_method = 0;
676 			return 1;
677 		}
678 	}
679 
680 	/* Method 2: seek for base firmware */
681 	if (!base_start)
682 		base_start = seek;
683 
684 	/* Skip if firmware is not a base firmware */
685 	if (endf - fdata < 1000)
686 		goto method3;
687 
688 	for (p = base_start; p < endp; p++) {
689 		fpos = p;
690 		for (p2 = fdata + ini_sig;
691 		     p2 < fdata + ini_sig + sig_len; p2++,
692 		     fpos++) {
693 			if (*fpos != *p2)
694 				break;
695 		}
696 		if (p2 == fdata + ini_sig + sig_len) {
697 			base_start = p - ini_sig;
698 
699 			p = memmem (base_start, endp-base_start,
700 				temp_data + fsize - end_sig, end_sig);
701 
702 			if (p)
703 				p = memmem (p + end_sig, endp-base_start,
704 					temp_data + fsize - end_sig, end_sig);
705 
706 			if (!p) {
707 				printf("Found something that looks like a firmware start at %lx\n",
708 					(long)(base_start - seek));
709 
710 				base_start += ini_sig + sig_len;
711 				goto method3;
712 			}
713 
714 			p += end_sig;
715 
716 			printf("Found firmware at %lx, size = %ld\n",
717 				(long)(base_start - seek),
718 				(long)(p - base_start));
719 
720 			hunk->data = NULL;
721 			hunk->pos = base_start - seek;
722 			hunk->size = p - base_start;
723 			hunk->next = NULL;
724 			hunk->need_fix_endian = 1;
725 			hunk->hint_method = 3;
726 
727 			base_start = p;
728 
729 			free(temp_data);
730 
731 			return 2;
732 		}
733 	}
734 
735 method3:
736 #if 0
737 	/* Method 3: Seek for each firmware chunk */
738 	p = seek;
739 	for (p2 = fdata; p2 < endf;) {
740 		int size = *p2 + (*(p2 + 1) << 8);
741 
742 		/* Encode size/reset/sleep directly */
743 		hunk->size = 2;
744 		hunk->data = malloc(hunk->size);
745 		memcpy(hunk->data, p2, hunk->size);
746 		hunk->pos = -1;
747 		hunk->next = calloc(1, sizeof(hunk));
748 		hunk->need_fix_endian = 0;
749 		hunk->hint_method = 0;
750 
751 		hunk = hunk->next;
752 		p2 += 2;
753 
754 		if ((size > 0) && (size < 0x8000)) {
755 			unsigned char *ep;
756 			int	found = 0;
757 			ep = p2 + size;
758 			///////////////////
759 			for (; p < endp; p++) {
760 				unsigned char *p3;
761 				fpos = p;
762 				for (p3 = p2; p3 < ep; p3++, fpos++)
763 					if (*fpos != *p3)
764 						break;
765 				if (p3 == ep) {
766 					found = 1;
767 					hunk->pos = p - seek;
768 					hunk->size = size;
769 					hunk->next = calloc(1, sizeof(hunk));
770 					hunk->need_fix_endian = 0;
771 					hunk->hint_method = 0;
772 
773 					hunk = hunk->next;
774 					break;
775 				}
776 			}
777 			if (!found) {
778 				goto not_found;
779 			}
780 			p2 += size;
781 		}
782 	}
783 	return 3;
784 not_found:
785 #endif
786 	memset(fhunk, 0, sizeof(struct chunk_hunk));
787 	printf("Couldn't find firmware\n");
788 
789 	free(temp_data);
790 	return 0;
791 
792 	/* Method 4: Seek for first firmware chunks */
793 #if 0
794 seek_next:
795 	for (p = seek; p < endp; p++) {
796 		fpos = p;
797 		for (p2 = fdata; p2 < endf; p2++, fpos++) {
798 			if (*fpos != *p2)
799 				break;
800 		}
801 		if (p2 > fdata + 3) {
802 			int i = 0;
803 			unsigned char *lastp;
804 			printf("Found %ld equal bytes at %06x:\n",
805 				p2 - fdata, p - seek);
806 			fpos = p;
807 			lastp = fpos;
808 			for (p2 = fdata; p2 < endf; p2++, fpos++) {
809 				if (*fpos != *p2)
810 					break;
811 				printf("%02x ",*p2);
812 			}
813 			for (i=0; p2 < endf && i <5 ; p2++, fpos++, i++) {
814 				printf("%02x(%02x) ",*p2 , *fpos);
815 			}
816 			printf("\n");
817 			/* Seek for the next chunk */
818 			fdata = p2;
819 
820 			if (fdata == endf) {
821 				printf ("Found all chunks.\n");
822 				return 4;
823 			}
824 		}
825 	}
826 
827 	printf ("NOT FOUND: %02x\n", *fdata);
828 	fdata++;
829 	goto seek_next;
830 #endif
831 }
832 
seek_firmware(struct firmware * f,char * seek_file,char * write_file)833 static void seek_firmware(struct firmware *f, char *seek_file, char *write_file) {
834 	unsigned int i = 0, j, nfound = 0;
835 	long size, rd = 0;
836 	unsigned char *seek, *p, *endp, *endp2;
837 	/*FIXME: Calculate it, instead of using a hardcode value */
838 	char *md5 = "0e44dbf63bb0169d57446aec21881ff2";
839 	FILE *fp;
840 
841 	struct chunk_hunk hunks[f->nr_desc];
842 	memset (hunks, 0, sizeof(struct chunk_hunk) * f->nr_desc);
843 
844 	fp=fopen(seek_file, "r");
845 	if (!fp) {
846 		perror("Opening seek file");
847 		exit(-1);
848 	}
849 	fseek(fp, 0L, SEEK_END);
850 	size = ftell(fp);
851 	rewind(fp);
852 	seek = malloc(size);
853 	p = seek;
854 
855 	do {
856 		i = fread(p, 1, 16768, fp);
857 		if (i > 0) {
858 			rd += i;
859 			p += i;
860 		}
861 	} while (i > 0);
862 
863 	fclose(fp);
864 
865 	if (rd != size) {
866 		fprintf(stderr, "Error while reading the seek file: "
867 				"should read %ld, instead of %ld ", size, rd);
868 		exit (-1);
869 	}
870 	endp = p;
871 
872 	printf("firmware name:\t%s\n", f->name);
873 	printf("version:\t%d.%d (%u)\n", f->version >> 8, f->version & 0xff,
874 					  f->version);
875 	printf("number of standards:\t%u\n", f->nr_desc);
876 	for(i = 0; i < f->nr_desc; ++i) {
877 		int found;
878 
879 		endp2 = f->desc[i].data + f->desc[i].size;
880 
881 		found = seek_chunks (&hunks[i],
882 			     seek, endp, f->desc[i].data, endp2);
883 
884 		if (!found) {
885 			printf("NOT FOUND: Firmware %d ", i);
886 			list_firmware_desc(stdout, &f->desc[i]);
887 		} else {
888 			nfound++;
889 			printf("Found with method %d: Firmware %d ", found, i);
890 			if (found == 2)
891 				f->desc[i].size = hunks[i].size;
892 			list_firmware_desc(stdout, &f->desc[i]);
893 		}
894 	}
895 	printf ("Found %d complete firmwares\n", nfound);
896 
897 	if (!write_file)
898 		return;
899 
900 	fp = fopen(write_file, "w");
901 	if (!fp) {
902 		perror("Writing firmware file");
903 		exit(-1);
904 	}
905 
906 	fprintf(fp, "%s", extract_header);
907 	for (i = 0, j = -1; i < f->nr_desc; i++) {
908 		struct chunk_hunk *hunk = &hunks[i];
909 
910 		if (!hunk->size)
911 			continue;
912 		j++;
913 
914 		if (hunk->hint_method)
915 			fprintf(fp, "\n\t#\n\t# Guessed format ");
916 
917 		fprintf(fp, "\n\t#\n\t# Firmware %d, ", j);
918 		list_firmware_desc(fp, &f->desc[i]);
919 		fprintf(fp, "\t#\n\n");
920 
921 		fprintf(fp, "\twrite_le32(0x%08x);\t\t\t# Type\n",
922 			f->desc[i].type);
923 		fprintf(fp, "\twrite_le64(0x%08Lx, 0x%08Lx);\t# ID\n",
924 			f->desc[i].id>>32, f->desc[i].id & 0xffffffff);
925 		if (f->desc[i].type & HAS_IF)
926 			fprintf(fp, "\twrite_le16(%d);\t\t\t# IF\n",
927 				f->desc[i].int_freq);
928 		fprintf(fp, "\twrite_le32(%d);\t\t\t# Size\n",
929 			f->desc[i].size);
930 		while (hunk) {
931 			if (hunk->data) {
932 				int k;
933 				fprintf(fp, "\tsyswrite(OUTFILE, ");
934 				for (k = 0; k < hunk->size; k++) {
935 					fprintf(fp, "chr(%d)", hunk->data[k]);
936 					if (k < hunk->size-1)
937 						fprintf(fp,".");
938 				}
939 				fprintf(fp,");\n");
940 			} else {
941 				if (!hunk->size)
942 					break;
943 
944 				if (hunk->need_fix_endian)
945 					fprintf(fp, write_hunk_fix_endian,
946 						hunk->pos, hunk->size);
947 				else
948 					fprintf(fp, write_hunk,
949 						hunk->pos, hunk->size);
950 			}
951 			hunk = hunk->next;
952 		}
953 	}
954 
955 	fprintf(fp, end_extract, seek_file, md5, "xc3028-v27.fw",
956 		f->name, f->version, nfound);
957 }
958 
print_usage(void)959 static void print_usage(void)
960 {
961 	printf("firmware-tool usage:\n");
962 	printf("\t firmware-tool --list [--dump] [--write <bin-file>] <firmware-file>\n");
963 	printf("\t firmware-tool --add <firmware-dump> <firmware-file>\n");
964 	printf("\t firmware-tool --delete <index> <firmware-file>\n");
965 	printf("\t firmware-tool --type <type> --index <i> <firmware-file>\n");
966 	printf("\t firmware-tool --id <type> --index <i> <firmware-file>\n");
967 	printf("\t firmware-tool --seek <seek-file> [--write <write-file>] <firmware-file>\n");
968 }
969 
main(int argc,char * argv[])970 int main(int argc, char* argv[])
971 {
972 	int c;
973 	int nr_args;
974 	unsigned int action = 0, dump = 0;
975 	char* firmware_file, *file = NULL, *nr_str = NULL, *index_str = NULL;
976 	char *seek_file = NULL, *write_file = NULL;
977 	struct firmware *f;
978 
979 	while(1) {
980 		static struct option long_options[] = {
981 			{"list",     no_argument,      0, 'l'},
982 			{"add",     required_argument, 0, 'a'},
983 			{"delete",  required_argument, 0, 'd'},
984 			{"type",  required_argument, 0, 't'},
985 			{"id",  required_argument, 0, 's'},
986 			{"index",  required_argument, 0, 'i'},
987 			{"seek", required_argument, 0, 'k'},
988 			{"write", required_argument , 0, 'w'},
989 			{"dump", no_argument, 0, 'm'},
990 			{0, 0, 0, 0}
991 		};
992 		int option_index = 0;
993 
994 		c = getopt_long(argc, argv, "", long_options, &option_index);
995 
996 		if (c == -1) {
997 			break;
998 		}
999 
1000 		switch(c) {
1001 			case 'l':
1002 				puts("list action\n");
1003 				if(action != 0) {
1004 					printf("Please specify only one action.\n");
1005 				}
1006 				action |= LIST_ACTION;
1007 				break;
1008 			case 'm':
1009 				dump = 1;
1010 				break;
1011 			case 'a':
1012 				puts("add action\n");
1013 				if(action != 0) {
1014 					printf("Please specify only one action.\n");
1015 				}
1016 				action |= ADD_ACTION;
1017 				file = optarg;
1018 				break;
1019 			case 'd':
1020 				puts("delete action\n");
1021 				if(action != 0) {
1022 					printf("Please specify only one action.\n");
1023 				}
1024 				action |= DELETE_ACTION;
1025 				nr_str = optarg;
1026 				break;
1027 			case 't':
1028 				puts("set-type action\n");
1029 				if(action != 0) {
1030 					printf("Please specify only one action.\n");
1031 				}
1032 				action |= SET_TYPE_ACTION;
1033 				nr_str = optarg;
1034 				break;
1035 			case 's':
1036 				puts("set-id action\n");
1037 				if(action != 0) {
1038 					printf("Please specify only one action.\n");
1039 				}
1040 				action |= SET_ID_ACTION;
1041 				nr_str = optarg;
1042 				break;
1043 			case 'i':
1044 				index_str = optarg;
1045 				break;
1046 			case 'k':
1047 				puts("seek firmwares\n");
1048 				action = SEEK_FIRM_ACTION;
1049 				seek_file = optarg;
1050 				break;
1051 			case 'w':
1052 				write_file = optarg;
1053 				break;
1054 			default:
1055 				print_usage();
1056 				return 0;
1057 		}
1058 	}
1059 
1060 	nr_args = (action == LIST_ACTION) ? 1 : 1;
1061 	if(!(optind + nr_args == argc)) {
1062 		printf("Wrong number of arguments!\n\n");
1063 		print_usage();
1064 		return -1;
1065 	}
1066 
1067 	if(!action) {
1068 		printf("Please specify an action!\n\n");
1069 		print_usage();
1070 		return -1;
1071 	}
1072 
1073 	firmware_file = argv[optind];
1074 
1075 	printf("firmware file name: %s\n", firmware_file);
1076 
1077 	f = read_firmware_file(firmware_file);
1078 	if(!f) {
1079 		printf("Couldn't read the firmware file!\n");
1080 		return -1;
1081 	}
1082 
1083 	switch(action) {
1084 		case LIST_ACTION:
1085 			list_firmware(f, dump, write_file);
1086 		break;
1087 
1088 		case ADD_ACTION:
1089 			add_standard(f, firmware_file, file);
1090 		break;
1091 
1092 		case DELETE_ACTION:
1093 			delete_standard(f, firmware_file, strtoul(nr_str, NULL, 10));
1094 		break;
1095 
1096 		case SET_TYPE_ACTION:
1097 			set_standard_type(f, firmware_file, strtoul(index_str, NULL, 10), strtoul(nr_str, NULL, 10));
1098 		break;
1099 
1100 		case SET_ID_ACTION:
1101 			set_standard_id(f, firmware_file, strtoul(index_str, NULL, 10), strtoul(nr_str, NULL, 10));
1102 
1103 		case SEEK_FIRM_ACTION:
1104 			seek_firmware(f, seek_file, write_file);
1105 		break;
1106 	}
1107 	return 0;
1108 }
1109