OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #include <stdio.h> |
2 | #include <string.h> |
||
3 | #include <stdlib.h> |
||
4 | #include <sys/types.h> |
||
5 | #include <unistd.h> |
||
6 | #include <byteswap.h> |
||
7 | #include <endian.h> |
||
8 | #include <getopt.h> |
||
9 | |||
10 | #if !defined(__BYTE_ORDER) |
||
11 | #error "Unknown byte order" |
||
12 | #endif |
||
13 | |||
14 | #if __BYTE_ORDER == __BIG_ENDIAN |
||
15 | #define cpu_to_be32(x) (x) |
||
16 | #elif __BYTE_ORDER == __LITTLE_ENDIAN |
||
17 | #define cpu_to_be32(x) bswap_32(x) |
||
18 | #else |
||
19 | #error "Unsupported endianness" |
||
20 | #endif |
||
21 | |||
22 | /* #define DEBUG 1 */ |
||
23 | |||
24 | #ifdef DEBUG |
||
25 | #define DBG(...) {printf(__VA_ARGS__); } |
||
26 | #else |
||
27 | #define DBG(...) {} |
||
28 | #endif |
||
29 | |||
30 | #define ERR(...) {printf(__VA_ARGS__); } |
||
31 | |||
32 | /* |
||
33 | * Fw Header Layout for Netgear / Sercomm devices (bytes) |
||
34 | * |
||
35 | * Size : 512 bytes + zipped image size |
||
36 | * |
||
37 | * Locations: |
||
38 | * magic : 0-6 ASCII |
||
39 | * version: 7-11 fixed |
||
40 | * hwID : 11-44 ASCII |
||
41 | * hwVer : 45-54 ASCII |
||
42 | * swVer : 55-62 uint32_t in BE |
||
43 | * magic : 63-69 ASCII |
||
44 | * ChkSum : 511 Inverse value of the full image checksum while this location is 0x00 |
||
45 | */ |
||
46 | static const char* magic = "sErCoMm"; /* 7 */ |
||
47 | static const unsigned char version[4] = { 0x00, 0x01, 0x00, 0x00 }; |
||
48 | static const int header_sz = 512; |
||
49 | static const int footer_sz = 71; |
||
50 | |||
51 | static int is_header = 1; |
||
52 | |||
53 | struct file_info { |
||
54 | char* file_name; /* name of the file */ |
||
55 | char* file_data; /* data of the file in memory */ |
||
56 | u_int32_t file_size; /* length of the file */ |
||
57 | }; |
||
58 | |||
59 | static u_int8_t getCheckSum(char* data, int len) { |
||
60 | u_int8_t new = 0; |
||
61 | int i; |
||
62 | |||
63 | if (!data) { |
||
64 | ERR("Invalid pointer provided!\n"); |
||
65 | return 0; |
||
66 | } |
||
67 | |||
68 | for (i = 0; i < len; i++) { |
||
69 | new += data[i]; |
||
70 | } |
||
71 | |||
72 | return new; |
||
73 | } |
||
74 | |||
75 | /* |
||
76 | * read file into buffer |
||
77 | * add space for header/footer |
||
78 | */ |
||
79 | static int copyToOutputBuf(struct file_info* finfo) { |
||
80 | FILE* fp = NULL; |
||
81 | |||
82 | int file_sz = 0; |
||
83 | int extra_sz; |
||
84 | int hdr_pos; |
||
85 | int img_pos; |
||
86 | |||
87 | if (!finfo || !finfo->file_name) { |
||
88 | ERR("Invalid pointer provided!\n"); |
||
89 | return -1; |
||
90 | } |
||
91 | |||
92 | DBG("Opening file: %s\n", finfo->file_name); |
||
93 | |||
94 | if (!(fp = fopen(finfo->file_name, "rb"))) { |
||
95 | ERR("Error opening file: %s\n", finfo->file_name); |
||
96 | return -1; |
||
97 | } |
||
98 | |||
99 | /* Get filesize */ |
||
100 | rewind(fp); |
||
101 | fseek(fp, 0L, SEEK_END); |
||
102 | file_sz = ftell(fp); |
||
103 | rewind(fp); |
||
104 | |||
105 | if (file_sz < 1) { |
||
106 | ERR("Error getting filesize: %s\n", finfo->file_name); |
||
107 | fclose(fp); |
||
108 | return -1; |
||
109 | } |
||
110 | |||
111 | if (is_header) { |
||
112 | extra_sz = header_sz; |
||
113 | hdr_pos = 0; |
||
114 | img_pos = header_sz; |
||
115 | } else { |
||
116 | extra_sz = footer_sz; |
||
117 | hdr_pos = file_sz; |
||
118 | img_pos = 0; |
||
119 | } |
||
120 | |||
121 | DBG("Filesize: %i\n", file_sz); |
||
122 | finfo->file_size = file_sz + extra_sz; |
||
123 | |||
124 | if (!(finfo->file_data = malloc(finfo->file_size))) { |
||
125 | ERR("Out of memory!\n"); |
||
126 | fclose(fp); |
||
127 | return -1; |
||
128 | } |
||
129 | |||
130 | /* init header/footer bytes */ |
||
131 | memset(finfo->file_data + hdr_pos, 0, extra_sz); |
||
132 | |||
133 | /* read file and take care of leading header if exists */ |
||
134 | if (fread(finfo->file_data + img_pos, 1, file_sz, fp) != file_sz) { |
||
135 | ERR("Error reading file %s\n", finfo->file_name); |
||
136 | fclose(fp); |
||
137 | return -1; |
||
138 | } |
||
139 | |||
140 | DBG("File: read successful\n"); |
||
141 | fclose(fp); |
||
142 | |||
143 | return hdr_pos; |
||
144 | } |
||
145 | |||
146 | static int writeFile(struct file_info* finfo) { |
||
147 | FILE* fp; |
||
148 | |||
149 | if (!finfo || !finfo->file_name) { |
||
150 | ERR("Invalid pointer provided!\n"); |
||
151 | return -1; |
||
152 | } |
||
153 | |||
154 | DBG("Opening file: %s\n", finfo->file_name); |
||
155 | |||
156 | if (!(fp = fopen(finfo->file_name, "w"))) { |
||
157 | ERR("Error opening file: %s\n", finfo->file_name); |
||
158 | return -1; |
||
159 | } |
||
160 | |||
161 | DBG("Writing file: %s\n", finfo->file_name); |
||
162 | |||
163 | if (fwrite(finfo->file_data, 1, finfo->file_size, fp) != finfo->file_size) { |
||
164 | ERR("Wanted to write, but something went wrong!\n"); |
||
165 | fclose(fp); |
||
166 | return -1; |
||
167 | } |
||
168 | |||
169 | fclose(fp); |
||
170 | return 0; |
||
171 | } |
||
172 | |||
173 | static void usage(char* argv[]) { |
||
174 | printf("Usage: %s [OPTIONS...]\n" |
||
175 | "\n" |
||
176 | "Options:\n" |
||
177 | " -f add sercom footer (if absent, header)\n" |
||
178 | " -b <hwid> use hardware id specified with <hwid> (ASCII)\n" |
||
179 | " -r <hwrev> use hardware revision specified with <hwrev> (ASCII)\n" |
||
180 | " -v <version> set image version to <version> (decimal, hex or octal notation)\n" |
||
181 | " -i <file> input file\n" |
||
182 | , argv[0]); |
||
183 | } |
||
184 | |||
185 | int main(int argc, char* argv[]) { |
||
186 | struct file_info image = { 0 }; |
||
187 | |||
188 | char* hwID = NULL; |
||
189 | char* hwVer = NULL; |
||
190 | u_int32_t swVer = 0; |
||
191 | u_int8_t chkSum; |
||
192 | int hdr_offset; |
||
193 | |||
194 | while ( 1 ) { |
||
195 | int c; |
||
196 | |||
197 | c = getopt(argc, argv, "b:i:r:v:f"); |
||
198 | if (c == -1) |
||
199 | break; |
||
200 | |||
201 | switch (c) { |
||
202 | case 'b': |
||
203 | hwID = optarg; |
||
204 | break; |
||
205 | case 'f': |
||
206 | is_header = 0; |
||
207 | break; |
||
208 | case 'i': |
||
209 | image.file_name = optarg; |
||
210 | break; |
||
211 | case 'r': |
||
212 | hwVer = optarg; |
||
213 | break; |
||
214 | case 'v': |
||
215 | swVer = (u_int32_t) strtol(optarg, NULL, 0); |
||
216 | swVer = cpu_to_be32(swVer); |
||
217 | break; |
||
218 | default: |
||
219 | usage(argv); |
||
220 | return EXIT_FAILURE; |
||
221 | } |
||
222 | } |
||
223 | |||
224 | if (!hwID || !hwVer || !image.file_name) { |
||
225 | usage(argv); |
||
226 | return EXIT_FAILURE; |
||
227 | } |
||
228 | |||
229 | /* |
||
230 | * copy input to buffer, add extra space for header/footer and return |
||
231 | * header position |
||
232 | */ |
||
233 | hdr_offset = copyToOutputBuf(&image); |
||
234 | if (hdr_offset < 0) |
||
235 | return EXIT_FAILURE; |
||
236 | |||
237 | DBG("Filling header: %s %s %2X %s\n", hwID, hwVer, swVer, magic); |
||
238 | |||
239 | strncpy(image.file_data + hdr_offset + 0, magic, 7); |
||
240 | memcpy(image.file_data + hdr_offset + 7, version, sizeof(version)); |
||
241 | strncpy(image.file_data + hdr_offset + 11, hwID, 34); |
||
242 | strncpy(image.file_data + hdr_offset + 45, hwVer, 10); |
||
243 | memcpy(image.file_data + hdr_offset + 55, &swVer, sizeof(swVer)); |
||
244 | strncpy(image.file_data + hdr_offset + 63, magic, 7); |
||
245 | |||
246 | /* calculate checksum and invert checksum */ |
||
247 | if (is_header) { |
||
248 | chkSum = getCheckSum(image.file_data, image.file_size); |
||
249 | chkSum = (chkSum ^ 0xFF) + 1; |
||
250 | DBG("Checksum for Image: %hhX\n", chkSum); |
||
251 | |||
252 | /* write checksum to header */ |
||
253 | image.file_data[511] = (char) chkSum; |
||
254 | } |
||
255 | |||
256 | /* overwrite input file */ |
||
257 | if (writeFile(&image)) |
||
258 | return EXIT_FAILURE; |
||
259 | |||
260 | return EXIT_SUCCESS; |
||
261 | } |