⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 firmware-tool.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
			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 + -