📄 firmware-tool.c
字号:
fp = fopen(name,"w"); if (!fp) { perror("Opening file to write"); return; } fwrite(f->desc[i].data, f->desc[i].size, 1, fp); fclose(fp); } }}void add_standard(struct firmware* f, char* firmware_file, char* standard_file) { unsigned char* standard_data; unsigned int len, i; struct firmware_description desc; create_standard_data(standard_file, &standard_data, &len); if(!standard_data) { fprintf(stderr, "Couldn't create the firmware standard data.\n"); return; } desc.id = 0; desc.type = 0; desc.size = len; desc.data = standard_data; add_firmware_description(f, &desc); write_firmware_file(firmware_file, f);}void delete_standard(struct firmware* f, char* firmware_file, __u16 i) { delete_firmware_description(f, i); write_firmware_file(firmware_file, f);}void set_standard_type(struct firmware* f, char* firmware_file, __u16 i, __u32 type) { if(i > f->nr_desc) { return; } f->desc[i].type = type; write_firmware_file(firmware_file, f);}void set_standard_id(struct firmware* f, char* firmware_file, __u16 i, __u32 id) { if(i > f->nr_desc) { return; } f->desc[i].id = id; write_firmware_file(firmware_file, f);}struct chunk_hunk;struct chunk_hunk { unsigned char *data; long pos; int size; int need_fix_endian; int hint_method; struct chunk_hunk *next;};int seek_chunks(struct chunk_hunk *fhunk, 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; struct chunk_hunk *hunk = fhunk; /* Method 3 vars */ static unsigned char *base_start = 0; int ini_sig = 8, sig_len = 14, end_sig = 8; /* 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) { hunk->data = NULL; hunk->pos = p - seek; hunk->size = endf - fdata; hunk->next = NULL; hunk->need_fix_endian = 0; hunk->hint_method = 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;) { unsigned char c; int size = *p2 + (*(p2 + 1) << 8); c = *p2; *p2 = *(p2 + 1); *(p2 + 1) = c; p2+=2; if ((size > 0) && (size < 0x8000)) p2 += size; } /* 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) { hunk->data = NULL; hunk->pos = p - seek; hunk->size = endf - fdata; hunk->next = NULL; hunk->need_fix_endian = 1; hunk->hint_method = 0; return 1; } } free(temp_data); /* Method 2: seek for base firmware */ if (!base_start) base_start = seek; /* Skip if firmware is not a base firmware */ if (endf - fdata < 1000) goto method3; for (p = base_start; p < endp; p++) { fpos = p; for (p2 = fdata + ini_sig; p2 < fdata + ini_sig + sig_len; p2++, fpos++) { if (*fpos != *p2) break; } if (p2 == fdata + ini_sig + sig_len) { base_start = p - ini_sig; p = memmem (base_start, endp-base_start, temp_data + fsize - end_sig, end_sig); if (p) p = memmem (p + end_sig, endp-base_start, temp_data + fsize - end_sig, end_sig); if (!p) { printf("Found something that looks like a firmware start at %x\n", base_start - seek); base_start += ini_sig + sig_len; goto method3; } p += end_sig; printf("Found firmware at %x, size = %d\n", base_start - seek, p - base_start); hunk->data = NULL; hunk->pos = base_start - seek; hunk->size = p - base_start; hunk->next = NULL; hunk->need_fix_endian = 1; hunk->hint_method = 3; base_start = p; return 2; } }method3:#if 0 /* Method 3: 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->hint_method = 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->hint_method = 0; hunk = hunk->next; break; } } if (!found) { goto not_found; } p2 += size; } } return 3;#endifnot_found: memset(fhunk, 0, sizeof(struct chunk_hunk)); printf("Couldn't find firmware\n"); return 0; /* Method 4: Seek for first firmware chunks */#if 0seek_next: for (p = seek; p < endp; p++) { fpos = p; for (p2 = fdata; p2 < endf; p2++, fpos++) { if (*fpos != *p2) break; } if (p2 > fdata + 3) { int i = 0; printf("Found %ld equal bytes at %06x:\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 4; } } } printf ("NOT FOUND: %02x\n", *fdata); fdata++; goto seek_next;#endif}void seek_firmware(struct firmware *f, char *seek_file, char *write_file) { unsigned int i = 0, j, 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(struct chunk_hunk) * f->nr_desc); 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("NOT FOUND: Firmware %d ", i); list_firmware_desc(stdout, &f->desc[i]); } else { nfound++; printf("Found with method %d: Firmware %d ", found, i); if (found == 2) f->desc[i].size = hunks[i].size; list_firmware_desc(stdout, &f->desc[i]); } } 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, j = -1; i < f->nr_desc; i++) { struct chunk_hunk *hunk = &hunks[i]; if (!hunk->size) continue; j++; if (hunk->hint_method) fprintf(fp, "\n\t#\n\t# Guessed format "); fprintf(fp, "\n\t#\n\t# Firmware %d, ", j); list_firmware_desc(fp, &f->desc[i]); fprintf(fp, "\t#\n\n"); fprintf(fp, "\twrite_le32(0x%08x);\t\t\t# Type\n", f->desc[i].type); fprintf(fp, "\twrite_le64(0x%08Lx, 0x%08Lx);\t# ID\n", f->desc[i].id>>32, f->desc[i].id & 0xffffffff); if (f->desc[i].type & HAS_IF) fprintf(fp, "\twrite_le16(%d);\t\t\t# IF\n", f->desc[i].int_freq); fprintf(fp, "\twrite_le32(%d);\t\t\t# Size\n", f->desc[i].size); while (hunk) { if (hunk->data) { int k; fprintf(fp, "\tsyswrite(OUTFILE, "); for (k = 0; k < hunk->size; k++) { fprintf(fp, "chr(%d)", hunk->data[k]); if (k < 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, nfound);}void print_usage(void){ printf("firmware-tool usage:\n"); printf("\t firmware-tool --list [--dump] [--write <bin-file>] <firmware-file>\n"); printf("\t firmware-tool --add <firmware-dump> <firmware-file>\n"); 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[]){ int c; int nr_args; unsigned int action = 0, dump = 0; char* firmware_file, *file = NULL, *nr_str = NULL, *index_str = NULL; char *seek_file = NULL, *write_file = NULL; struct firmware *f; __u64 nr; while(1) { static struct option long_options[] = { {"list", no_argument, 0, 'l'}, {"add", required_argument, 0, 'a'}, {"delete", required_argument, 0, 'd'}, {"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'}, {"dump", no_argument, 0, 'm'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "", long_options, &option_index); if (c == -1) { break; } switch(c) { case 'l': puts("list action\n"); if(action != 0) { printf("Please specify only one action.\n"); } action |= LIST_ACTION; break; case 'm': dump = 1; break; case 'a': puts("add action\n"); if(action != 0) { printf("Please specify only one action.\n"); } action |= ADD_ACTION; file = optarg; break; case 'd': puts("delete action\n"); if(action != 0) { printf("Please specify only one action.\n"); } action |= DELETE_ACTION; nr_str = optarg; break; case 't': puts("set-type action\n"); if(action != 0) { printf("Please specify only one action.\n"); } action |= SET_TYPE_ACTION; nr_str = optarg; break; case 's': puts("set-id action\n"); if(action != 0) { printf("Please specify only one action.\n"); } action |= SET_ID_ACTION; nr_str = optarg; break; 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; } } nr_args = (action == LIST_ACTION) ? 1 : 1; if(!(optind + nr_args == argc)) { printf("Wrong number of arguments!\n\n"); print_usage(); return -1; } if(!action) { printf("Please specify an action!\n\n"); print_usage(); return -1; } firmware_file = argv[optind]; printf("firmware file name: %s\n", firmware_file); f = read_firmware_file(firmware_file); if(!f) { printf("Couldn't read the firmware file!\n"); return -1; } switch(action) { case LIST_ACTION: list_firmware(f, dump, write_file); break; case ADD_ACTION: add_standard(f, firmware_file, file); break; case DELETE_ACTION: delete_standard(f, firmware_file, strtoul(nr_str, NULL, 10)); break; case SET_TYPE_ACTION: set_standard_type(f, firmware_file, strtoul(index_str, NULL, 10), strtoul(nr_str, NULL, 10)); break; 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -