diff options
Diffstat (limited to 'v4l2-apps/util')
-rw-r--r-- | v4l2-apps/util/xc3028-firmware/extract_head.h | 161 | ||||
-rw-r--r-- | v4l2-apps/util/xc3028-firmware/firmware-tool.c | 467 |
2 files changed, 545 insertions, 83 deletions
diff --git a/v4l2-apps/util/xc3028-firmware/extract_head.h b/v4l2-apps/util/xc3028-firmware/extract_head.h new file mode 100644 index 000000000..9ca83377b --- /dev/null +++ b/v4l2-apps/util/xc3028-firmware/extract_head.h @@ -0,0 +1,161 @@ +char *extract_header = "#!/usr/bin/perl\n" + "#use strict;\n" + "use IO::Handle;\n" + "\n" + "my $debug=0;\n" + "\n" + "sub verify ($$)\n" + "{\n" + " my ($filename, $hash) = @_;\n" + " my ($testhash);\n" + "\n" + " if (system(\"which md5sum > /dev/null 2>&1\")) {\n" + " die \"This firmware requires the md5sum command - see http://www.gnu.org/software/coreutils/\\n\";\n" + " }\n" + "\n" + " open(CMD, \"md5sum \".$filename.\"|\");\n" + " $testhash = <CMD>;\n" + " $testhash =~ /([a-zA-Z0-9]*)/;\n" + " $testhash = $1;\n" + " close CMD;\n" + " die \"Hash of extracted file does not match (found $testhash, expected $hash!\\n\" if ($testhash ne $hash);\n" + "}\n" + "\n" + "sub get_hunk ($$)\n" + "{\n" + " my ($offset, $length) = @_;\n" + " my ($chunklength, $buf, $rcount, $out);\n" + "\n" + " sysseek(INFILE, $offset, SEEK_SET);\n" + " while ($length > 0) {\n" + " # Calc chunk size\n" + " $chunklength = 2048;\n" + " $chunklength = $length if ($chunklength > $length);\n" + "\n" + " $rcount = sysread(INFILE, $buf, $chunklength);\n" + " die \"Ran out of data\\n\" if ($rcount != $chunklength);\n" + " $out .= $buf;\n" + " $length -= $rcount;\n" + " }\n" + " return $out;\n" + "}\n" + "\n" + "sub write_le16($)\n" + "{\n" + " my $val = shift;\n" + " my $msb = ($val >> 8) &0xff;\n" + " my $lsb = $val & 0xff;\n" + "\n" + " syswrite(OUTFILE, chr($lsb).chr($msb));\n" + "}\n" + "\n" + "sub write_le32($)\n" + "{\n" + " my $val = shift;\n" + " my $l3 = ($val >> 24) & 0xff;\n" + " my $l2 = ($val >> 16) & 0xff;\n" + " my $l1 = ($val >> 8) & 0xff;\n" + " my $l0 = $val & 0xff;\n" + "\n" + " syswrite(OUTFILE, chr($l0).chr($l1).chr($l2).chr($l3));\n" + "}\n" + "\n" + "sub write_le64($)\n" + "{\n" + " my $val = shift;\n" + " my $l7 = ($val >> 56) & 0xff;\n" + " my $l6 = ($val >> 48) & 0xff;\n" + " my $l5 = ($val >> 40) & 0xff;\n" + " my $l4 = ($val >> 32) & 0xff;\n" + " my $l3 = ($val >> 24) & 0xff;\n" + " my $l2 = ($val >> 16) & 0xff;\n" + " my $l1 = ($val >> 8) & 0xff;\n" + " my $l0 = $val & 0xff;\n" + "\n" + " syswrite(OUTFILE,\n" + " chr($l0).chr($l1).chr($l2).chr($l3).\n" + " chr($l4).chr($l5).chr($l6).chr($l7));\n" + "}\n" + "\n" + "sub write_hunk($$)\n" + "{\n" + " my ($offset, $length) = @_;\n" + " my $out = get_hunk($offset, $length);\n" + "\n" + " printf \"(len %d) \",$length if ($debug);\n" +// " write_le16($length);\n" + "\n" + " for (my $i=0;$i<$length;$i++) {\n" + " printf \"%02x \",ord(substr($out,$i,1)) if ($debug);\n" + " }\n" + " printf \"\\n\" if ($debug);\n" + "\n" + " syswrite(OUTFILE, $out);\n" + "}\n" + "\n" + "sub write_hunk_fix_endian($$)\n" + "{\n" + " my ($offset, $length) = @_;\n" + " my $out = get_hunk($offset, $length);\n" + "\n" + " printf \"(len_fix %d) \",$length if ($debug);\n" +//"syswrite(OUTFILE, \"0123456789ABCDEF\");\n" +// " write_le16($length);\n" + "\n" + " for (my $i=0;$i<$length;$i++) {\n" + " printf \"%02x \",ord(substr($out,$i,1)) if ($debug);\n" + " }\n" + " printf \"\\n\" if ($debug);\n" + "\n" + " $i=0;\n" + " while ($i<$length) {\n" + " my $size = ord(substr($out,$i,1))*256+ord(substr($out,$i+1,1));\n" + " syswrite(OUTFILE, substr($out,$i+1,1));\n" + " syswrite(OUTFILE, substr($out,$i,1));\n" + " $i+=2;\n" + " for (my $j=0;$j<$size;$j++) {\n" + " syswrite(OUTFILE, substr($out,$j+$i,1));\n" + " }\n" + " $i+=$size;\n" + " }\n" + "}\n" + "\n" + "sub main_firmware($$$$)\n" + "{\n" + " my $out;\n" + " my $j=0;\n" + " my $outfile = shift;\n" + " my $name = shift;\n" + " my $version = shift;\n" + " my $nr_desc = shift;\n" + "\n" + " for ($j = length($name); $j <32; $j++) {\n" + " $name = $name.chr(0);\n" + "}\n\n" + " open OUTFILE, \">$outfile\";\n" + " syswrite(OUTFILE, $name);\n" + " write_le16($version);\n" + " write_le16($nr_desc);\n"; + +char *write_hunk = "\twrite_hunk(%d, %d);\n"; +char *write_hunk_fix_endian = "\twrite_hunk_fix_endian(%d, %d);\n"; + +// Parameters: file windows filename, hash, outfile, version, name +char *end_extract = "}\n\nsub extract_firmware {\n" + " my $sourcefile = \"%s\";\n" + " my $hash = \"%s\";\n" + " my $outfile = \"%s\";\n" + " my $name = \"%s\";\n" + " my $version = %d;\n" + " my $nr_desc = %d;\n" + " my $out;\n" + "\n" + " verify($sourcefile, $hash);\n" + "\n" + " open INFILE, \"<$sourcefile\";\n" + " main_firmware($outfile, $name, $version, $nr_desc);\n" + " close INFILE;\n" + "}\n" + "\n" + "extract_firmware;\n" + "printf \"Firmwares generated.\\n\";\n"; diff --git a/v4l2-apps/util/xc3028-firmware/firmware-tool.c b/v4l2-apps/util/xc3028-firmware/firmware-tool.c index a8e6d0c01..c0003ddff 100644 --- a/v4l2-apps/util/xc3028-firmware/firmware-tool.c +++ b/v4l2-apps/util/xc3028-firmware/firmware-tool.c @@ -31,6 +31,7 @@ #include "../../../linux/drivers/media/video/tuner-xc2028-types.h" #include "../../../linux/include/linux/videodev2.h" +#include "extract_head.h" #include "standards.h" #define LIST_ACTION (1<<0) @@ -38,6 +39,7 @@ #define DELETE_ACTION (1<<2) #define SET_TYPE_ACTION (1<<3) #define SET_ID_ACTION (1<<4) +#define SEEK_FIRM_ACTION (1<<5) struct firmware_description { __u32 type; @@ -287,74 +289,74 @@ void write_firmware_file(const char* filename, struct firmware *f) { close(fd); } -void dump_firm_type(unsigned int type) +void dump_firm_type(FILE *fp, unsigned int type) { if (type & SCODE) - printf("SCODE FW "); + fprintf(fp, "SCODE FW "); else if (type & BASE) - printf("BASE FW "); + fprintf(fp, "BASE FW "); else - printf("STD FW "); + fprintf(fp, "STD FW "); if (type & F8MHZ) - printf("F8MHZ "); + fprintf(fp, "F8MHZ "); if (type & MTS) - printf("MTS "); + fprintf(fp, "MTS "); if (type & D2620) - printf("D2620 "); + fprintf(fp, "D2620 "); if (type & D2633) - printf("D2633 "); + fprintf(fp, "D2633 "); if (type & DTV6) - printf("DTV6 "); + fprintf(fp, "DTV6 "); if (type & QAM) - printf("QAM "); + fprintf(fp, "QAM "); if (type & DTV7) - printf("DTV7 "); + fprintf(fp, "DTV7 "); if (type & DTV78) - printf("DTV78 "); + fprintf(fp, "DTV78 "); if (type & DTV8) - printf("DTV8 "); + fprintf(fp, "DTV8 "); if (type & FM) - printf("FM "); + fprintf(fp, "FM "); if (type & INPUT1) - printf("INPUT1 "); + fprintf(fp, "INPUT1 "); if (type & LCD) - printf("LCD "); + fprintf(fp, "LCD "); if (type & NOGD) - printf("NOGD "); + fprintf(fp, "NOGD "); if (type & MONO) - printf("MONO "); + fprintf(fp, "MONO "); if (type & ATSC) - printf("ATSC "); + fprintf(fp, "ATSC "); if (type & IF) - printf("IF "); + fprintf(fp, "IF "); if (type & LG60) - printf("LG60 "); + fprintf(fp, "LG60 "); if (type & ATI638) - printf("ATI638 "); + fprintf(fp, "ATI638 "); if (type & OREN538) - printf("OREN538 "); + fprintf(fp, "OREN538 "); if (type & OREN36) - printf("OREN36 "); + fprintf(fp, "OREN36 "); if (type & TOYOTA388) - printf("TOYOTA388 "); + fprintf(fp, "TOYOTA388 "); if (type & TOYOTA794) - printf("TOYOTA794 "); + fprintf(fp, "TOYOTA794 "); if (type & DIBCOM52) - printf("DIBCOM52 "); + fprintf(fp, "DIBCOM52 "); if (type & ZARLINK456) - printf("ZARLINK456 "); + fprintf(fp, "ZARLINK456 "); if (type & CHINA) - printf("CHINA "); + fprintf(fp, "CHINA "); if (type & F6MHZ) - printf("F6MHZ "); + fprintf(fp, "F6MHZ "); if (type & INPUT2) - printf("INPUT2 "); + fprintf(fp, "INPUT2 "); if (type & HAS_IF) - printf("HAS IF "); + fprintf(fp, "HAS IF "); } -void dump_firm_std(v4l2_std_id id) +void dump_firm_std(FILE *fp, v4l2_std_id id) { v4l2_std_id old=-1, curr_id; @@ -362,127 +364,127 @@ void dump_firm_std(v4l2_std_id id) while (old!=id) { old=id; if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { - printf ("PAL "); + fprintf (fp, "PAL "); curr_id = V4L2_STD_PAL; } else if ( (id & V4L2_STD_MN) == V4L2_STD_MN) { - printf ("NTSC PAL/M PAL/N "); + fprintf (fp, "NTSC PAL/M PAL/N "); curr_id = V4L2_STD_PAL; } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { - printf ("PAL/BG "); + fprintf (fp, "PAL/BG "); curr_id = V4L2_STD_PAL_BG; } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { - printf ("PAL/DK "); + fprintf (fp, "PAL/DK "); curr_id = V4L2_STD_PAL_DK; } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { - printf ("PAL/B "); + fprintf (fp, "PAL/B "); curr_id = V4L2_STD_PAL_B; } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { - printf ("PAL/B1 "); + fprintf (fp, "PAL/B1 "); curr_id = V4L2_STD_PAL_B1; } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { - printf ("PAL/G "); + fprintf (fp, "PAL/G "); curr_id = V4L2_STD_PAL_G; } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { - printf ("PAL/H "); + fprintf (fp, "PAL/H "); curr_id = V4L2_STD_PAL_H; } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { - printf ("PAL/I "); + fprintf (fp, "PAL/I "); curr_id = V4L2_STD_PAL_I; } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { - printf ("PAL/D "); + fprintf (fp, "PAL/D "); curr_id = V4L2_STD_PAL_D; } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { - printf ("PAL/D1 "); + fprintf (fp, "PAL/D1 "); curr_id = V4L2_STD_PAL_D1; } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { - printf ("PAL/K "); + fprintf (fp, "PAL/K "); curr_id = V4L2_STD_PAL_K; } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { - printf ("PAL/M "); + fprintf (fp, "PAL/M "); curr_id = V4L2_STD_PAL_M; } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { - printf ("PAL/N "); + fprintf (fp, "PAL/N "); curr_id = V4L2_STD_PAL_N; } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { - printf ("PAL/Nc "); + fprintf (fp, "PAL/Nc "); curr_id = V4L2_STD_PAL_Nc; } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { - printf ("PAL/60 "); + fprintf (fp, "PAL/60 "); curr_id = V4L2_STD_PAL_60; } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { - printf ("NTSC "); + fprintf (fp, "NTSC "); curr_id = V4L2_STD_NTSC; } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { - printf ("NTSC/M "); + fprintf (fp, "NTSC/M "); curr_id = V4L2_STD_NTSC_M; } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { - printf ("NTSC/M Jp "); + fprintf (fp, "NTSC/M Jp "); curr_id = V4L2_STD_NTSC_M_JP; } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { - printf ("NTSC 443 "); + fprintf (fp, "NTSC 443 "); curr_id = V4L2_STD_NTSC_443; } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { - printf ("NTSC/M Kr "); + fprintf (fp, "NTSC/M Kr "); curr_id = V4L2_STD_NTSC_M_KR; } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { - printf ("SECAM "); + fprintf (fp, "SECAM "); curr_id = V4L2_STD_SECAM; } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { - printf ("SECAM/DK "); + fprintf (fp, "SECAM/DK "); curr_id = V4L2_STD_SECAM_DK; } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { - printf ("SECAM/B "); + fprintf (fp, "SECAM/B "); curr_id = V4L2_STD_SECAM_B; } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { - printf ("SECAM/D "); + fprintf (fp, "SECAM/D "); curr_id = V4L2_STD_SECAM_D; } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { - printf ("SECAM/G "); + fprintf (fp, "SECAM/G "); curr_id = V4L2_STD_SECAM_G; } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { - printf ("SECAM/H "); + fprintf (fp, "SECAM/H "); curr_id = V4L2_STD_SECAM_H; } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { - printf ("SECAM/K "); + fprintf (fp, "SECAM/K "); curr_id = V4L2_STD_SECAM_K; } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { - printf ("SECAM/K1 "); + fprintf (fp, "SECAM/K1 "); curr_id = V4L2_STD_SECAM_K1; } else if ( (id & V4L2_STD_SECAM_K3) == V4L2_STD_SECAM_K3) { - printf ("SECAM/K3 "); + fprintf (fp, "SECAM/K3 "); curr_id = V4L2_STD_SECAM_K3; } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { - printf ("SECAM/L "); + fprintf (fp, "SECAM/L "); curr_id = V4L2_STD_SECAM_L; } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { - printf ("SECAM/Lc "); + fprintf (fp, "SECAM/Lc "); curr_id = V4L2_STD_SECAM_LC; } else if ( (id & V4L2_STD_A2) == V4L2_STD_A2) { - printf ("A2 "); + fprintf (fp, "A2 "); curr_id = V4L2_STD_A2; } else if ( (id & V4L2_STD_A2_A) == V4L2_STD_A2_A) { - printf ("A2/A "); + fprintf (fp, "A2/A "); curr_id = V4L2_STD_A2_A; } else if ( (id & V4L2_STD_A2_B) == V4L2_STD_A2_B) { - printf ("A2/B "); + fprintf (fp, "A2/B "); curr_id = V4L2_STD_A2_B; } else if ( (id & V4L2_STD_NICAM) == V4L2_STD_NICAM) { - printf ("NICAM "); + fprintf (fp, "NICAM "); curr_id = V4L2_STD_NICAM; } else if ( (id & V4L2_STD_NICAM_A) == V4L2_STD_NICAM_A) { - printf ("NICAM/A "); + fprintf (fp, "NICAM/A "); curr_id = V4L2_STD_NICAM_A; } else if ( (id & V4L2_STD_NICAM_B) == V4L2_STD_NICAM_B) { - printf ("NICAM/B "); + fprintf (fp, "NICAM/B "); curr_id = V4L2_STD_NICAM_B; } else if ( (id & V4L2_STD_AM) == V4L2_STD_AM) { - printf ("AM "); + fprintf (fp, "AM "); curr_id = V4L2_STD_AM; } else if ( (id & V4L2_STD_BTSC) == V4L2_STD_BTSC) { - printf ("BTSC "); + fprintf (fp, "BTSC "); curr_id = V4L2_STD_BTSC; } else if ( (id & V4L2_STD_EIAJ) == V4L2_STD_EIAJ) { - printf ("EIAJ "); + fprintf (fp, "EIAJ "); curr_id = V4L2_STD_EIAJ; } else { curr_id = 0; @@ -492,6 +494,19 @@ void dump_firm_std(v4l2_std_id id) } } +void list_firmware_desc(FILE *fp, struct firmware_description *desc) +{ + fprintf(fp, "type: "); + dump_firm_type(fp, desc->type); + fprintf(fp, "(0x%08x), ", desc->type); + if (desc->type & HAS_IF) + fprintf(fp, "IF = %.2f MHz ", desc->int_freq/1000.0); + fprintf(fp, "id: "); + dump_firm_std(fp, desc->id); + fprintf(fp, "(%016llx), ", desc->id); + fprintf(fp, "size: %u\n", desc->size); +} + void list_firmware(struct firmware *f) { unsigned int i = 0; @@ -501,15 +516,7 @@ void list_firmware(struct firmware *f) { printf("standards:\t%u\n", f->nr_desc); for(i = 0; i < f->nr_desc; ++i) { printf("Firmware %2u, ", i); - printf("type: "); - dump_firm_type(f->desc[i].type); - printf("(0x%08x), ", f->desc[i].type); - if (f->desc[i].type & HAS_IF) - printf("IF = %.2f MHz ", f->desc[i].int_freq/1000.0); - printf("id: "); - dump_firm_std(f->desc[i].id); - printf("(%016llx), ", f->desc[i].id); - printf("size: %u\n", f->desc[i].size); + list_firmware_desc(stdout, &f->desc[i]); } } @@ -552,6 +559,285 @@ void set_standard_id(struct firmware* f, char* firmware_file, __u16 i, __u32 id) write_firmware_file(firmware_file, f); } +struct chunk_hunk; + +struct chunk_hunk { + unsigned char *data; + long pos; + int size; + int need_fix_endian; + struct chunk_hunk *next; +}; + +int seek_chunks(struct chunk_hunk *hunk, + unsigned char *seek, unsigned char *endp, /* File to seek */ + unsigned char *fdata, unsigned char *endf) /* Firmware */ +{ + unsigned char *fpos, *p, *p2, *lastp; + int rc, fsize; + unsigned char *temp_data; + + /* Method 1a: Seek for a complete firmware */ + for (p = seek; p < endp; p++) { + fpos = p; + for (p2 = fdata; p2 < endf; p2++, fpos++) { + if (*fpos != *p2) + break; + } + if (p2 == endf) { + printf("Firmware found at %ld\n", p - seek); + hunk->data = NULL; + hunk->pos = p - seek; + hunk->size = endf - fdata; + hunk->next = NULL; + hunk->need_fix_endian = 0; + + return 1; + } + } + + fsize = endf - fdata; + temp_data = malloc(fsize); + memcpy(temp_data, fdata, fsize); + + /* Try again, changing endian */ + for (p2 = temp_data; p2 < temp_data + fsize; p2++) { + int size = *p2 + (*(p2 + 1) << 8); + if ((size > 0) && (size < 0x8000)) { + unsigned char c = *p2; + *p2 = *(p2 + 1); + *(p2 + 1) = c; + p2 += size + 1; + + } + } + + /* Method 1b: Seek for a complete firmware with changed endians */ + for (p = seek; p < endp; p++) { + fpos = p; + for (p2 = temp_data; p2 < temp_data + fsize; p2++, fpos++) { + if (*fpos != *p2) + break; + } + if (p2 == temp_data + fsize) { + printf("Firmware found at %ld (fix_endian)\n", + p - seek); + hunk->data = NULL; + hunk->pos = p - seek; + hunk->size = endf - fdata; + hunk->next = NULL; + hunk->need_fix_endian = 1; + return 1; + } + } + + free(temp_data); + + /* Method 2: Seek for each firmware chunk */ + p = seek; + for (p2 = fdata; p2 < endf;) { + int size = *p2 + (*(p2 + 1) << 8); + + /* Encode size/reset/sleep directly */ + hunk->size = 2; + hunk->data = malloc(hunk->size); + memcpy(hunk->data, p2, hunk->size); + hunk->pos = -1; + hunk->next = calloc(1, sizeof(hunk)); + hunk->need_fix_endian = 0; + hunk = hunk->next; + p2 += 2; + + if ((size > 0) && (size < 0x8000)) { + unsigned char *ep; + int found = 0; + ep = p2 + size; + /////////////////// + for (; p < endp; p++) { + unsigned char *p3; + fpos = p; + for (p3 = p2; p3 < ep; p3++, fpos++) + if (*fpos != *p3) + break; + if (p3 == ep) { + found = 1; + hunk->pos = p - seek; + hunk->size = size; + hunk->next = calloc(1, sizeof(hunk)); + hunk->need_fix_endian = 0; + hunk = hunk->next; + printf("Firmware hunk found at %ld \n", + p - seek); + + break; + } + } + if (!found) { + goto not_found; + } + p2 += size; + } + } + + printf ("Firmware found by using method 3\n"); + return 1; + +not_found: + printf("method 2 couldn't find firmware\n"); +return 0; + + /* Method 3: Seek for first firmware chunks */ + +seek_next: + for (p = seek; p < endp; p++) { + fpos = p; + for (p2 = fdata; p2 < endf; p2++, fpos++) { + if (*fpos != *p2) + break; + } + if (p2 > fdata + 2) { + int i = 0; + printf("Found %ld equal bytes at %ld:\n", + p2 - fdata, p - seek); + fpos = p; + lastp = fpos; + for (p2 = fdata; p2 < endf; p2++, fpos++) { + if (*fpos != *p2) + break; + printf("%02x ",*p2); + } + for (i=0; p2 < endf && i <5 ; p2++, fpos++, i++) { + printf("%02x(%02x) ",*p2 , *fpos); + } + printf("\n"); + /* Seek for the next chunk */ + fdata = p2; + + if (fdata == endf) { + printf ("Found all chunks.\n"); + return 1; + } + } + } + + printf ("NOT FOUND: %02x\n", *fdata); + fdata++; + goto seek_next; +} + +void seek_firmware(struct firmware *f, char *seek_file, char *write_file) { + unsigned int i = 0, nfound = 0; + long size, rd = 0; + unsigned char *seek, *p, *endp, *p2, *endp2, *fpos; + /*FIXME: Calculate it, instead of using a hardcode value */ + char *md5 = "0e44dbf63bb0169d57446aec21881ff2"; + FILE *fp; + + struct chunk_hunk hunks[f->nr_desc]; + memset (hunks, 0, sizeof(hunks)); + + fp=fopen(seek_file, "r"); + if (!fp) { + perror("Opening seek file"); + exit(-1); + } + fseek(fp, 0L, SEEK_END); + size = ftell(fp); + rewind(fp); + seek = malloc(size); + p = seek; + + do { + i = fread(p, 1, 16768, fp); + if (i > 0) { + rd += i; + p += i; + } + } while (i > 0); + + fclose(fp); + + if (rd != size) { + fprintf(stderr, "Error while reading the seek file: " + "should read %ld, instead of %ld ", size, rd); + exit (-1); + } + endp = p; + + printf("firmware name:\t%s\n", f->name); + printf("version:\t%d.%d (%u)\n", f->version >> 8, f->version & 0xff, + f->version); + printf("number of standards:\t%u\n", f->nr_desc); + for(i = 0; i < f->nr_desc; ++i) { + int found; + + endp2 = f->desc[i].data + f->desc[i].size; + + found = seek_chunks (&hunks[i], + seek, endp, f->desc[i].data, endp2); + + if (!found) { + printf("Firmware %d Not found: ", i); + list_firmware_desc(stdout, &f->desc[i]); + } + + nfound += found; + } + printf ("Found %d complete firmwares\n", nfound); + + if (!write_file) + return; + + fp = fopen(write_file, "w"); + if (!fp) { + perror("Writing firmware file"); + exit(-1); + } + + fprintf(fp, "%s", extract_header); + for (i = 0; i < f->nr_desc; ++i) { + struct chunk_hunk *hunk = &hunks[i]; + + fprintf(fp, "\n\t#\n\t# Firmware %d, ", i); + list_firmware_desc(fp, &f->desc[i]); + fprintf(fp, "\t#\n\n"); + + fprintf(fp, "\twrite_le32(%d);\n", f->desc[i].type); + fprintf(fp, "\twrite_le64(%Ld);\n", f->desc[i].id); + if (f->desc[i].type & HAS_IF) + fprintf(fp, "\twrite_le16(%d);\n", + f->desc[i].int_freq); + fprintf(fp, "\twrite_le32(%d);\n", f->desc[i].size); + + while (hunk) { + if (hunk->data) { + int j; + fprintf(fp, "\tsyswrite(OUTFILE, "); + for (j = 0; j < hunk->size; j++) { + fprintf(fp, "chr(%d)", hunk->data[j]); + if (j < hunk->size-1) + fprintf(fp,"."); + } + fprintf(fp,");\n"); + } else { + if (!hunk->size) + break; + + if (hunk->need_fix_endian) + fprintf(fp, write_hunk_fix_endian, + hunk->pos, hunk->size); + else + fprintf(fp, write_hunk, + hunk->pos, hunk->size); + } + hunk = hunk->next; + } + } + + fprintf(fp, end_extract, seek_file, md5, "xc3028-v27.fw", + f->name, f->version, f->nr_desc); +} + void print_usage(void) { printf("firmware-tool usage:\n"); @@ -560,6 +846,7 @@ void print_usage(void) printf("\t firmware-tool --delete <index> <firmware-file>\n"); printf("\t firmware-tool --type <type> --index <i> <firmware-file>\n"); printf("\t firmware-tool --id <type> --index <i> <firmware-file>\n"); + printf("\t firmware-tool --seek <seek-file> [--write <write-file>] <firmware-file>\n"); } int main(int argc, char* argv[]) @@ -568,6 +855,7 @@ int main(int argc, char* argv[]) int nr_args; unsigned int action = 0; char* firmware_file, *file = NULL, *nr_str = NULL, *index_str = NULL; + char *seek_file = NULL, *write_file = NULL; struct firmware *f; __u64 nr; @@ -579,6 +867,8 @@ int main(int argc, char* argv[]) {"type", required_argument, 0, 't'}, {"id", required_argument, 0, 's'}, {"index", required_argument, 0, 'i'}, + {"seek", required_argument, 0, 'k'}, + {"write", required_argument , 0, 'w'}, {0, 0, 0, 0} }; int option_index = 0; @@ -632,6 +922,14 @@ int main(int argc, char* argv[]) case 'i': index_str = optarg; break; + case 'k': + puts("seek firmwares\n"); + action = SEEK_FIRM_ACTION; + seek_file = optarg; + break; + case 'w': + write_file = optarg; + break; default: print_usage(); return 0; @@ -680,6 +978,9 @@ int main(int argc, char* argv[]) case SET_ID_ACTION: set_standard_id(f, firmware_file, strtoul(index_str, NULL, 10), strtoul(nr_str, NULL, 10)); + + case SEEK_FIRM_ACTION: + seek_firmware(f, seek_file, write_file); break; } return 0; |