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 "tuner-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 	uint32_t type;
50 	uint64_t id;
51 	unsigned char *data;
52 	uint16_t int_freq;
53 	uint32_t size;
54 };
55 
56 struct firmware {
57 	char* name;
58 	struct firmware_description* desc;
59 	uint16_t version;
60 	uint16_t 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,uint16_t i)111 static void delete_firmware_description(struct firmware *f, uint16_t 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 = letoh16(*(uint16_t*)p);
147 	p += sizeof(f->version);
148 	f->nr_desc = letoh16(*(uint16_t*)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 = letoh32(*(uint32_t*) p);
159 		p += sizeof(f->desc[i].type);
160 		f->desc[i].id = letoh64(*(uint64_t*) p);
161 		p += sizeof(f->desc[i].id);
162 
163 		if (f->desc[i].type & HAS_IF) {
164 			f->desc[i].int_freq = letoh16(*(uint16_t *) p);
165 			p += sizeof(f->desc[i].int_freq);
166 		}
167 
168 		f->desc[i].size = letoh32(*(uint32_t*) 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 	*(uint16_t*)p = __cpu_to_le16(f->version);
206 	p += sizeof(f->version);
207 
208 	*(uint16_t*)p = __cpu_to_le16(f->nr_desc);
209 	p += sizeof(f->nr_desc);
210 
211 	for(i = 0; i < f->nr_desc; ++i) {
212 		*(uint32_t*) p = __cpu_to_le32(f->desc[i].type);
213 		p += sizeof(f->desc[i].type);
214 
215 		*(uint64_t*) p = __cpu_to_le64(f->desc[i].id);
216 		p += sizeof(f->desc[i].id);
217 
218 		*(uint32_t*) 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,uint16_t i)584 static void delete_standard(struct firmware* f, char* firmware_file, uint16_t 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,uint16_t i,uint32_t type)589 static void set_standard_type(struct firmware* f, char* firmware_file, uint16_t i, uint32_t 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,uint16_t i,uint32_t id)597 static void set_standard_id(struct firmware* f, char* firmware_file, uint16_t i, uint32_t 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 	free(temp_data);
681 
682 	/* Method 2: seek for base firmware */
683 	if (!base_start)
684 		base_start = seek;
685 
686 	/* Skip if firmware is not a base firmware */
687 	if (endf - fdata < 1000)
688 		goto method3;
689 
690 	for (p = base_start; p < endp; p++) {
691 		fpos = p;
692 		for (p2 = fdata + ini_sig;
693 		     p2 < fdata + ini_sig + sig_len; p2++,
694 		     fpos++) {
695 			if (*fpos != *p2)
696 				break;
697 		}
698 		if (p2 == fdata + ini_sig + sig_len) {
699 			base_start = p - ini_sig;
700 
701 			p = memmem (base_start, endp-base_start,
702 				temp_data + fsize - end_sig, end_sig);
703 
704 			if (p)
705 				p = memmem (p + end_sig, endp-base_start,
706 					temp_data + fsize - end_sig, end_sig);
707 
708 			if (!p) {
709 				printf("Found something that looks like a firmware start at %lx\n",
710 					(long)(base_start - seek));
711 
712 				base_start += ini_sig + sig_len;
713 				goto method3;
714 			}
715 
716 			p += end_sig;
717 
718 			printf("Found firmware at %lx, size = %ld\n",
719 				(long)(base_start - seek),
720 				(long)(p - base_start));
721 
722 			hunk->data = NULL;
723 			hunk->pos = base_start - seek;
724 			hunk->size = p - base_start;
725 			hunk->next = NULL;
726 			hunk->need_fix_endian = 1;
727 			hunk->hint_method = 3;
728 
729 			base_start = p;
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 	return 0;
789 
790 	/* Method 4: Seek for first firmware chunks */
791 #if 0
792 seek_next:
793 	for (p = seek; p < endp; p++) {
794 		fpos = p;
795 		for (p2 = fdata; p2 < endf; p2++, fpos++) {
796 			if (*fpos != *p2)
797 				break;
798 		}
799 		if (p2 > fdata + 3) {
800 			int i = 0;
801 			unsigned char *lastp;
802 			printf("Found %ld equal bytes at %06x:\n",
803 				p2 - fdata, p - seek);
804 			fpos = p;
805 			lastp = fpos;
806 			for (p2 = fdata; p2 < endf; p2++, fpos++) {
807 				if (*fpos != *p2)
808 					break;
809 				printf("%02x ",*p2);
810 			}
811 			for (i=0; p2 < endf && i <5 ; p2++, fpos++, i++) {
812 				printf("%02x(%02x) ",*p2 , *fpos);
813 			}
814 			printf("\n");
815 			/* Seek for the next chunk */
816 			fdata = p2;
817 
818 			if (fdata == endf) {
819 				printf ("Found all chunks.\n");
820 				return 4;
821 			}
822 		}
823 	}
824 
825 	printf ("NOT FOUND: %02x\n", *fdata);
826 	fdata++;
827 	goto seek_next;
828 #endif
829 }
830 
seek_firmware(struct firmware * f,char * seek_file,char * write_file)831 static void seek_firmware(struct firmware *f, char *seek_file, char *write_file) {
832 	unsigned int i = 0, j, nfound = 0;
833 	long size, rd = 0;
834 	unsigned char *seek, *p, *endp, *endp2;
835 	/*FIXME: Calculate it, instead of using a hardcode value */
836 	char *md5 = "0e44dbf63bb0169d57446aec21881ff2";
837 	FILE *fp;
838 
839 	struct chunk_hunk hunks[f->nr_desc];
840 	memset (hunks, 0, sizeof(struct chunk_hunk) * f->nr_desc);
841 
842 	fp=fopen(seek_file, "r");
843 	if (!fp) {
844 		perror("Opening seek file");
845 		exit(-1);
846 	}
847 	fseek(fp, 0L, SEEK_END);
848 	size = ftell(fp);
849 	rewind(fp);
850 	seek = malloc(size);
851 	p = seek;
852 
853 	do {
854 		i = fread(p, 1, 16768, fp);
855 		if (i > 0) {
856 			rd += i;
857 			p += i;
858 		}
859 	} while (i > 0);
860 
861 	fclose(fp);
862 
863 	if (rd != size) {
864 		fprintf(stderr, "Error while reading the seek file: "
865 				"should read %ld, instead of %ld ", size, rd);
866 		exit (-1);
867 	}
868 	endp = p;
869 
870 	printf("firmware name:\t%s\n", f->name);
871 	printf("version:\t%d.%d (%u)\n", f->version >> 8, f->version & 0xff,
872 					  f->version);
873 	printf("number of standards:\t%u\n", f->nr_desc);
874 	for(i = 0; i < f->nr_desc; ++i) {
875 		int found;
876 
877 		endp2 = f->desc[i].data + f->desc[i].size;
878 
879 		found = seek_chunks (&hunks[i],
880 			     seek, endp, f->desc[i].data, endp2);
881 
882 		if (!found) {
883 			printf("NOT FOUND: Firmware %d ", i);
884 			list_firmware_desc(stdout, &f->desc[i]);
885 		} else {
886 			nfound++;
887 			printf("Found with method %d: Firmware %d ", found, i);
888 			if (found == 2)
889 				f->desc[i].size = hunks[i].size;
890 			list_firmware_desc(stdout, &f->desc[i]);
891 		}
892 	}
893 	printf ("Found %d complete firmwares\n", nfound);
894 
895 	if (!write_file)
896 		return;
897 
898 	fp = fopen(write_file, "w");
899 	if (!fp) {
900 		perror("Writing firmware file");
901 		exit(-1);
902 	}
903 
904 	fprintf(fp, "%s", extract_header);
905 	for (i = 0, j = -1; i < f->nr_desc; i++) {
906 		struct chunk_hunk *hunk = &hunks[i];
907 
908 		if (!hunk->size)
909 			continue;
910 		j++;
911 
912 		if (hunk->hint_method)
913 			fprintf(fp, "\n\t#\n\t# Guessed format ");
914 
915 		fprintf(fp, "\n\t#\n\t# Firmware %d, ", j);
916 		list_firmware_desc(fp, &f->desc[i]);
917 		fprintf(fp, "\t#\n\n");
918 
919 		fprintf(fp, "\twrite_le32(0x%08x);\t\t\t# Type\n",
920 			f->desc[i].type);
921 		fprintf(fp, "\twrite_le64(0x%08Lx, 0x%08Lx);\t# ID\n",
922 			f->desc[i].id>>32, f->desc[i].id & 0xffffffff);
923 		if (f->desc[i].type & HAS_IF)
924 			fprintf(fp, "\twrite_le16(%d);\t\t\t# IF\n",
925 				f->desc[i].int_freq);
926 		fprintf(fp, "\twrite_le32(%d);\t\t\t# Size\n",
927 			f->desc[i].size);
928 		while (hunk) {
929 			if (hunk->data) {
930 				int k;
931 				fprintf(fp, "\tsyswrite(OUTFILE, ");
932 				for (k = 0; k < hunk->size; k++) {
933 					fprintf(fp, "chr(%d)", hunk->data[k]);
934 					if (k < hunk->size-1)
935 						fprintf(fp,".");
936 				}
937 				fprintf(fp,");\n");
938 			} else {
939 				if (!hunk->size)
940 					break;
941 
942 				if (hunk->need_fix_endian)
943 					fprintf(fp, write_hunk_fix_endian,
944 						hunk->pos, hunk->size);
945 				else
946 					fprintf(fp, write_hunk,
947 						hunk->pos, hunk->size);
948 			}
949 			hunk = hunk->next;
950 		}
951 	}
952 
953 	fprintf(fp, end_extract, seek_file, md5, "xc3028-v27.fw",
954 		f->name, f->version, nfound);
955 }
956 
print_usage(void)957 static void print_usage(void)
958 {
959 	printf("firmware-tool usage:\n");
960 	printf("\t firmware-tool --list [--dump] [--write <bin-file>] <firmware-file>\n");
961 	printf("\t firmware-tool --add <firmware-dump> <firmware-file>\n");
962 	printf("\t firmware-tool --delete <index> <firmware-file>\n");
963 	printf("\t firmware-tool --type <type> --index <i> <firmware-file>\n");
964 	printf("\t firmware-tool --id <type> --index <i> <firmware-file>\n");
965 	printf("\t firmware-tool --seek <seek-file> [--write <write-file>] <firmware-file>\n");
966 }
967 
main(int argc,char * argv[])968 int main(int argc, char* argv[])
969 {
970 	int c;
971 	int nr_args;
972 	unsigned int action = 0, dump = 0;
973 	char* firmware_file, *file = NULL, *nr_str = NULL, *index_str = NULL;
974 	char *seek_file = NULL, *write_file = NULL;
975 	struct firmware *f;
976 
977 	while(1) {
978 		static struct option long_options[] = {
979 			{"list",     no_argument,      0, 'l'},
980 			{"add",     required_argument, 0, 'a'},
981 			{"delete",  required_argument, 0, 'd'},
982 			{"type",  required_argument, 0, 't'},
983 			{"id",  required_argument, 0, 's'},
984 			{"index",  required_argument, 0, 'i'},
985 			{"seek", required_argument, 0, 'k'},
986 			{"write", required_argument , 0, 'w'},
987 			{"dump", no_argument, 0, 'm'},
988 			{0, 0, 0, 0}
989 		};
990 		int option_index = 0;
991 
992 		c = getopt_long(argc, argv, "", long_options, &option_index);
993 
994 		if (c == -1) {
995 			break;
996 		}
997 
998 		switch(c) {
999 			case 'l':
1000 				puts("list action\n");
1001 				if(action != 0) {
1002 					printf("Please specify only one action.\n");
1003 				}
1004 				action |= LIST_ACTION;
1005 				break;
1006 			case 'm':
1007 				dump = 1;
1008 				break;
1009 			case 'a':
1010 				puts("add action\n");
1011 				if(action != 0) {
1012 					printf("Please specify only one action.\n");
1013 				}
1014 				action |= ADD_ACTION;
1015 				file = optarg;
1016 				break;
1017 			case 'd':
1018 				puts("delete action\n");
1019 				if(action != 0) {
1020 					printf("Please specify only one action.\n");
1021 				}
1022 				action |= DELETE_ACTION;
1023 				nr_str = optarg;
1024 				break;
1025 			case 't':
1026 				puts("set-type action\n");
1027 				if(action != 0) {
1028 					printf("Please specify only one action.\n");
1029 				}
1030 				action |= SET_TYPE_ACTION;
1031 				nr_str = optarg;
1032 				break;
1033 			case 's':
1034 				puts("set-id action\n");
1035 				if(action != 0) {
1036 					printf("Please specify only one action.\n");
1037 				}
1038 				action |= SET_ID_ACTION;
1039 				nr_str = optarg;
1040 				break;
1041 			case 'i':
1042 				index_str = optarg;
1043 				break;
1044 			case 'k':
1045 				puts("seek firmwares\n");
1046 				action = SEEK_FIRM_ACTION;
1047 				seek_file = optarg;
1048 				break;
1049 			case 'w':
1050 				write_file = optarg;
1051 				break;
1052 			default:
1053 				print_usage();
1054 				return 0;
1055 		}
1056 	}
1057 
1058 	nr_args = (action == LIST_ACTION) ? 1 : 1;
1059 	if(!(optind + nr_args == argc)) {
1060 		printf("Wrong number of arguments!\n\n");
1061 		print_usage();
1062 		return -1;
1063 	}
1064 
1065 	if(!action) {
1066 		printf("Please specify an action!\n\n");
1067 		print_usage();
1068 		return -1;
1069 	}
1070 
1071 	firmware_file = argv[optind];
1072 
1073 	printf("firmware file name: %s\n", firmware_file);
1074 
1075 	f = read_firmware_file(firmware_file);
1076 	if(!f) {
1077 		printf("Couldn't read the firmware file!\n");
1078 		return -1;
1079 	}
1080 
1081 	switch(action) {
1082 		case LIST_ACTION:
1083 			list_firmware(f, dump, write_file);
1084 		break;
1085 
1086 		case ADD_ACTION:
1087 			add_standard(f, firmware_file, file);
1088 		break;
1089 
1090 		case DELETE_ACTION:
1091 			delete_standard(f, firmware_file, strtoul(nr_str, NULL, 10));
1092 		break;
1093 
1094 		case SET_TYPE_ACTION:
1095 			set_standard_type(f, firmware_file, strtoul(index_str, NULL, 10), strtoul(nr_str, NULL, 10));
1096 		break;
1097 
1098 		case SET_ID_ACTION:
1099 			set_standard_id(f, firmware_file, strtoul(index_str, NULL, 10), strtoul(nr_str, NULL, 10));
1100 
1101 		case SEEK_FIRM_ACTION:
1102 			seek_firmware(f, seek_file, write_file);
1103 		break;
1104 	}
1105 	return 0;
1106 }
1107