• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 
usage(const char * s)8 static void usage(const char *s)
9 {
10 	printf("%s <rom file>\n", s);
11 	exit(1);
12 }
13 
FseekEnd(FILE * fp,long o)14 static void FseekEnd(FILE *fp, long o)
15 {
16 	if (fseek(fp, o, SEEK_END) != 0) {
17 		puts("fseek() error!\n");
18 		exit(1);
19 	}
20 }
21 
dump_fw(FILE * dst,FILE * src,long offset)22 void dump_fw(FILE *dst, FILE *src, long offset)
23 {
24 	static unsigned char buf[65536];
25 
26 	if (offset > 0)
27 		offset -= 0x1000000;
28 
29 	printf("Dumping firmware at -0x%lx...", -offset);
30 
31 	FseekEnd(src, offset);
32 	unsigned short len;
33 	unsigned short cksum;
34 	unsigned short _cksum = 0;
35 	fread(&len, 2, 1, src);
36 	fread(&cksum, 2, 1, src);
37 	fread(buf, len, 1, src);
38 
39 	for (size_t i = 0; i < len; i++)
40 		_cksum += buf[i];
41 
42 	if (_cksum == cksum) {
43 		puts("checksum ok");
44 	} else {
45 		puts("checksum fail");
46 		exit(1);
47 	}
48 
49 	fwrite(&len, 2, 1, dst);
50 	fwrite(&cksum, 2, 1, dst);
51 	fwrite(buf, len, 1, dst);
52 }
53 
main(int argc,char * argv[])54 int main(int argc, char *argv[])
55 {
56 	if (argc != 2)
57 		usage(argv[0]);
58 
59 	FILE *fp = fopen(argv[1], "rb");
60 
61 	if (fp == NULL) {
62 		puts("Error opening file!");
63 		exit(1);
64 	}
65 
66 	char *basename = strrchr(argv[1], '/');
67 	if (basename == NULL)
68 		basename = argv[1];
69 	else
70 		basename = basename + 1;
71 
72 	int len = strlen(basename);
73 	char fn1[len + 5], fn2[len + 5];
74 	strcpy(fn1, basename);
75 	strcpy(fn2, basename);
76 	strcat(fn1, ".fw1");
77 	strcat(fn2, ".fw2");
78 
79 	FILE *fw1 = fopen(fn1, "wb");
80 	FILE *fw2 = fopen(fn2, "wb");
81 
82 	long romsz;
83 	FseekEnd(fp, -1);
84 	romsz = ftell(fp) + 1;
85 	printf("size of %s: 0x%lx\n", argv[1], romsz);
86 
87 	if (romsz & 0xff) {
88 		puts("The ROM size must be multiple of 0x100");
89 		exit(1);
90 	}
91 
92 	/* read offset of fw1 and fw2 */
93 	unsigned char offs[8];
94 	FseekEnd(fp, -0x100);
95 	fread(offs, 8, 1, fp);
96 
97 	assert(offs[0] + offs[2] == 0xff);
98 	assert(offs[1] + offs[3] == 0xff);
99 	assert(offs[4] + offs[6] == 0xff);
100 	assert(offs[5] + offs[7] == 0xff);
101 	long offw1 = (offs[0] << 16) | (offs[1] << 8);
102 	long offw2 = (offs[4] << 16) | (offs[5] << 8);
103 
104 	dump_fw(fw1, fp, offw1);
105 	dump_fw(fw2, fp, offw2);
106 
107 	fclose(fp);
108 	fclose(fw1);
109 	fclose(fw2);
110 	return 0;
111 }
112