tplink-safeloader: expand support list for TP-Link CPE210 v3
[openwrt/staging/stintel.git] / tools / firmware-utils / src / tplink-safeloader.c
1 /*
2 Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26
27 /*
28 tplink-safeloader
29
30 Image generation tool for the TP-LINK SafeLoader as seen on
31 TP-LINK Pharos devices (CPE210/220/510/520)
32 */
33
34
35 #include <assert.h>
36 #include <errno.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <unistd.h>
44
45 #include <arpa/inet.h>
46
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <limits.h>
50
51 #include "md5.h"
52
53
54 #define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
55
56
57 #define MAX_PARTITIONS 32
58
59 /** An image partition table entry */
60 struct image_partition_entry {
61 const char *name;
62 size_t size;
63 uint8_t *data;
64 };
65
66 /** A flash partition table entry */
67 struct flash_partition_entry {
68 char *name;
69 uint32_t base;
70 uint32_t size;
71 };
72
73 /** Firmware layout description */
74 struct device_info {
75 const char *id;
76 const char *vendor;
77 const char *support_list;
78 char support_trail;
79 const char *soft_ver;
80 struct flash_partition_entry partitions[MAX_PARTITIONS+1];
81 const char *first_sysupgrade_partition;
82 const char *last_sysupgrade_partition;
83 };
84
85 /** The content of the soft-version structure */
86 struct __attribute__((__packed__)) soft_version {
87 uint32_t magic;
88 uint32_t zero;
89 uint8_t pad1;
90 uint8_t version_major;
91 uint8_t version_minor;
92 uint8_t version_patch;
93 uint8_t year_hi;
94 uint8_t year_lo;
95 uint8_t month;
96 uint8_t day;
97 uint32_t rev;
98 uint8_t pad2;
99 };
100
101
102 static const uint8_t jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
103
104
105 /**
106 Salt for the MD5 hash
107
108 Fortunately, TP-LINK seems to use the same salt for most devices which use
109 the new image format.
110 */
111 static const uint8_t md5_salt[16] = {
112 0x7a, 0x2b, 0x15, 0xed,
113 0x9b, 0x98, 0x59, 0x6d,
114 0xe5, 0x04, 0xab, 0x44,
115 0xac, 0x2a, 0x9f, 0x4e,
116 };
117
118
119 /** Firmware layout table */
120 static struct device_info boards[] = {
121 /** Firmware layout for the CPE210/220 V1 */
122 {
123 .id = "CPE210",
124 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
125 .support_list =
126 "SupportList:\r\n"
127 "CPE210(TP-LINK|UN|N300-2):1.0\r\n"
128 "CPE210(TP-LINK|UN|N300-2):1.1\r\n"
129 "CPE210(TP-LINK|US|N300-2):1.1\r\n"
130 "CPE210(TP-LINK|EU|N300-2):1.1\r\n"
131 "CPE220(TP-LINK|UN|N300-2):1.1\r\n"
132 "CPE220(TP-LINK|US|N300-2):1.1\r\n"
133 "CPE220(TP-LINK|EU|N300-2):1.1\r\n",
134 .support_trail = '\xff',
135 .soft_ver = NULL,
136
137 .partitions = {
138 {"fs-uboot", 0x00000, 0x20000},
139 {"partition-table", 0x20000, 0x02000},
140 {"default-mac", 0x30000, 0x00020},
141 {"product-info", 0x31100, 0x00100},
142 {"signature", 0x32000, 0x00400},
143 {"os-image", 0x40000, 0x200000},
144 {"file-system", 0x240000, 0x570000},
145 {"soft-version", 0x7b0000, 0x00100},
146 {"support-list", 0x7b1000, 0x00400},
147 {"user-config", 0x7c0000, 0x10000},
148 {"default-config", 0x7d0000, 0x10000},
149 {"log", 0x7e0000, 0x10000},
150 {"radio", 0x7f0000, 0x10000},
151 {NULL, 0, 0}
152 },
153
154 .first_sysupgrade_partition = "os-image",
155 .last_sysupgrade_partition = "support-list",
156 },
157
158 /** Firmware layout for the CPE210 V2 */
159 {
160 .id = "CPE210V2",
161 .vendor = "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n",
162 .support_list =
163 "SupportList:\r\n"
164 "CPE210(TP-LINK|EU|N300-2|00000000):2.0\r\n"
165 "CPE210(TP-LINK|EU|N300-2|45550000):2.0\r\n"
166 "CPE210(TP-LINK|EU|N300-2|55530000):2.0\r\n"
167 "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n"
168 "CPE210(TP-LINK|UN|N300-2|45550000):2.0\r\n"
169 "CPE210(TP-LINK|UN|N300-2|55530000):2.0\r\n"
170 "CPE210(TP-LINK|US|N300-2|55530000):2.0\r\n"
171 "CPE210(TP-LINK|UN|N300-2):2.0\r\n"
172 "CPE210(TP-LINK|EU|N300-2):2.0\r\n"
173 "CPE210(TP-LINK|US|N300-2):2.0\r\n",
174 .support_trail = '\xff',
175 .soft_ver = NULL,
176
177 .partitions = {
178 {"fs-uboot", 0x00000, 0x20000},
179 {"partition-table", 0x20000, 0x02000},
180 {"default-mac", 0x30000, 0x00020},
181 {"product-info", 0x31100, 0x00100},
182 {"device-info", 0x31400, 0x00400},
183 {"signature", 0x32000, 0x00400},
184 {"device-id", 0x33000, 0x00100},
185 {"firmware", 0x40000, 0x770000},
186 {"soft-version", 0x7b0000, 0x00100},
187 {"support-list", 0x7b1000, 0x01000},
188 {"user-config", 0x7c0000, 0x10000},
189 {"default-config", 0x7d0000, 0x10000},
190 {"log", 0x7e0000, 0x10000},
191 {"radio", 0x7f0000, 0x10000},
192 {NULL, 0, 0}
193 },
194
195 .first_sysupgrade_partition = "os-image",
196 .last_sysupgrade_partition = "support-list",
197 },
198
199 /** Firmware layout for the CPE210 V3 */
200 {
201 .id = "CPE210V3",
202 .vendor = "CPE210(TP-LINK|UN|N300-2|00000000):3.0\r\n",
203 .support_list =
204 "SupportList:\r\n"
205 "CPE210(TP-LINK|EU|N300-2|45550000):3.0\r\n"
206 "CPE210(TP-LINK|UN|N300-2|00000000):3.0\r\n"
207 "CPE210(TP-LINK|US|N300-2|55530000):3.0\r\n"
208 "CPE210(TP-LINK|UN|N300-2):3.0\r\n"
209 "CPE210(TP-LINK|EU|N300-2):3.0\r\n"
210 "CPE210(TP-LINK|EU|N300-2|45550000):3.1\r\n"
211 "CPE210(TP-LINK|UN|N300-2|00000000):3.1\r\n"
212 "CPE210(TP-LINK|US|N300-2|55530000):3.1\r\n"
213 "CPE210(TP-LINK|EU|N300-2|45550000):3.20\r\n"
214 "CPE210(TP-LINK|UN|N300-2|00000000):3.20\r\n"
215 "CPE210(TP-LINK|US|N300-2|55530000):3.20\r\n",
216 .support_trail = '\xff',
217 .soft_ver = NULL,
218
219 .partitions = {
220 {"fs-uboot", 0x00000, 0x20000},
221 {"partition-table", 0x20000, 0x01000},
222 {"default-mac", 0x30000, 0x00020},
223 {"product-info", 0x31100, 0x00100},
224 {"device-info", 0x31400, 0x00400},
225 {"signature", 0x32000, 0x00400},
226 {"device-id", 0x33000, 0x00100},
227 {"firmware", 0x40000, 0x770000},
228 {"soft-version", 0x7b0000, 0x00100},
229 {"support-list", 0x7b1000, 0x01000},
230 {"user-config", 0x7c0000, 0x10000},
231 {"default-config", 0x7d0000, 0x10000},
232 {"log", 0x7e0000, 0x10000},
233 {"radio", 0x7f0000, 0x10000},
234 {NULL, 0, 0}
235 },
236
237 .first_sysupgrade_partition = "os-image",
238 .last_sysupgrade_partition = "support-list",
239 },
240
241 /** Firmware layout for the CPE220 V2 */
242 {
243 .id = "CPE220V2",
244 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
245 .support_list =
246 "SupportList:\r\n"
247 "CPE220(TP-LINK|EU|N300-2|00000000):2.0\r\n"
248 "CPE220(TP-LINK|EU|N300-2|45550000):2.0\r\n"
249 "CPE220(TP-LINK|EU|N300-2|55530000):2.0\r\n"
250 "CPE220(TP-LINK|UN|N300-2|00000000):2.0\r\n"
251 "CPE220(TP-LINK|UN|N300-2|45550000):2.0\r\n"
252 "CPE220(TP-LINK|UN|N300-2|55530000):2.0\r\n"
253 "CPE220(TP-LINK|US|N300-2|55530000):2.0\r\n"
254 "CPE220(TP-LINK|UN|N300-2):2.0\r\n"
255 "CPE220(TP-LINK|EU|N300-2):2.0\r\n"
256 "CPE220(TP-LINK|US|N300-2):2.0\r\n",
257 .support_trail = '\xff',
258 .soft_ver = NULL,
259
260 .partitions = {
261 {"fs-uboot", 0x00000, 0x20000},
262 {"partition-table", 0x20000, 0x02000},
263 {"default-mac", 0x30000, 0x00020},
264 {"product-info", 0x31100, 0x00100},
265 {"signature", 0x32000, 0x00400},
266 {"os-image", 0x40000, 0x200000},
267 {"file-system", 0x240000, 0x570000},
268 {"soft-version", 0x7b0000, 0x00100},
269 {"support-list", 0x7b1000, 0x00400},
270 {"user-config", 0x7c0000, 0x10000},
271 {"default-config", 0x7d0000, 0x10000},
272 {"log", 0x7e0000, 0x10000},
273 {"radio", 0x7f0000, 0x10000},
274 {NULL, 0, 0}
275 },
276
277 .first_sysupgrade_partition = "os-image",
278 .last_sysupgrade_partition = "support-list",
279 },
280
281 /** Firmware layout for the CPE220 V3 */
282 {
283 .id = "CPE220V3",
284 .vendor = "CPE220(TP-LINK|UN|N300-2|00000000):3.0\r\n",
285 .support_list =
286 "SupportList:\r\n"
287 "CPE220(TP-LINK|EU|N300-2|00000000):3.0\r\n"
288 "CPE220(TP-LINK|EU|N300-2|45550000):3.0\r\n"
289 "CPE220(TP-LINK|EU|N300-2|55530000):3.0\r\n"
290 "CPE220(TP-LINK|UN|N300-2|00000000):3.0\r\n"
291 "CPE220(TP-LINK|UN|N300-2|45550000):3.0\r\n"
292 "CPE220(TP-LINK|UN|N300-2|55530000):3.0\r\n"
293 "CPE220(TP-LINK|US|N300-2|55530000):3.0\r\n"
294 "CPE220(TP-LINK|UN|N300-2):3.0\r\n"
295 "CPE220(TP-LINK|EU|N300-2):3.0\r\n"
296 "CPE220(TP-LINK|US|N300-2):3.0\r\n",
297 .support_trail = '\xff',
298 .soft_ver = NULL,
299
300 .partitions = {
301 {"fs-uboot", 0x00000, 0x20000},
302 {"partition-table", 0x20000, 0x02000},
303 {"default-mac", 0x30000, 0x00020},
304 {"product-info", 0x31100, 0x00100},
305 {"device-info", 0x31400, 0x00400},
306 {"signature", 0x32000, 0x00400},
307 {"device-id", 0x33000, 0x00100},
308 {"firmware", 0x40000, 0x770000},
309 {"soft-version", 0x7b0000, 0x00100},
310 {"support-list", 0x7b1000, 0x01000},
311 {"user-config", 0x7c0000, 0x10000},
312 {"default-config", 0x7d0000, 0x10000},
313 {"log", 0x7e0000, 0x10000},
314 {"radio", 0x7f0000, 0x10000},
315 {NULL, 0, 0}
316 },
317
318 .first_sysupgrade_partition = "os-image",
319 .last_sysupgrade_partition = "support-list",
320 },
321
322 /** Firmware layout for the CPE510/520 V1 */
323 {
324 .id = "CPE510",
325 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
326 .support_list =
327 "SupportList:\r\n"
328 "CPE510(TP-LINK|UN|N300-5):1.0\r\n"
329 "CPE510(TP-LINK|UN|N300-5):1.1\r\n"
330 "CPE510(TP-LINK|UN|N300-5):1.1\r\n"
331 "CPE510(TP-LINK|US|N300-5):1.1\r\n"
332 "CPE510(TP-LINK|EU|N300-5):1.1\r\n"
333 "CPE520(TP-LINK|UN|N300-5):1.1\r\n"
334 "CPE520(TP-LINK|US|N300-5):1.1\r\n"
335 "CPE520(TP-LINK|EU|N300-5):1.1\r\n",
336 .support_trail = '\xff',
337 .soft_ver = NULL,
338
339 .partitions = {
340 {"fs-uboot", 0x00000, 0x20000},
341 {"partition-table", 0x20000, 0x02000},
342 {"default-mac", 0x30000, 0x00020},
343 {"product-info", 0x31100, 0x00100},
344 {"signature", 0x32000, 0x00400},
345 {"os-image", 0x40000, 0x200000},
346 {"file-system", 0x240000, 0x570000},
347 {"soft-version", 0x7b0000, 0x00100},
348 {"support-list", 0x7b1000, 0x00400},
349 {"user-config", 0x7c0000, 0x10000},
350 {"default-config", 0x7d0000, 0x10000},
351 {"log", 0x7e0000, 0x10000},
352 {"radio", 0x7f0000, 0x10000},
353 {NULL, 0, 0}
354 },
355
356 .first_sysupgrade_partition = "os-image",
357 .last_sysupgrade_partition = "support-list",
358 },
359
360 /** Firmware layout for the CPE510 V2 */
361 {
362 .id = "CPE510V2",
363 .vendor = "CPE510(TP-LINK|UN|N300-5):2.0\r\n",
364 .support_list =
365 "SupportList:\r\n"
366 "CPE510(TP-LINK|EU|N300-5|00000000):2.0\r\n"
367 "CPE510(TP-LINK|EU|N300-5|45550000):2.0\r\n"
368 "CPE510(TP-LINK|EU|N300-5|55530000):2.0\r\n"
369 "CPE510(TP-LINK|UN|N300-5|00000000):2.0\r\n"
370 "CPE510(TP-LINK|UN|N300-5|45550000):2.0\r\n"
371 "CPE510(TP-LINK|UN|N300-5|55530000):2.0\r\n"
372 "CPE510(TP-LINK|US|N300-5|00000000):2.0\r\n"
373 "CPE510(TP-LINK|US|N300-5|45550000):2.0\r\n"
374 "CPE510(TP-LINK|US|N300-5|55530000):2.0\r\n"
375 "CPE510(TP-LINK|UN|N300-5):2.0\r\n"
376 "CPE510(TP-LINK|EU|N300-5):2.0\r\n"
377 "CPE510(TP-LINK|US|N300-5):2.0\r\n",
378 .support_trail = '\xff',
379 .soft_ver = NULL,
380
381 .partitions = {
382 {"fs-uboot", 0x00000, 0x20000},
383 {"partition-table", 0x20000, 0x02000},
384 {"default-mac", 0x30000, 0x00020},
385 {"product-info", 0x31100, 0x00100},
386 {"signature", 0x32000, 0x00400},
387 {"os-image", 0x40000, 0x200000},
388 {"file-system", 0x240000, 0x570000},
389 {"soft-version", 0x7b0000, 0x00100},
390 {"support-list", 0x7b1000, 0x00400},
391 {"user-config", 0x7c0000, 0x10000},
392 {"default-config", 0x7d0000, 0x10000},
393 {"log", 0x7e0000, 0x10000},
394 {"radio", 0x7f0000, 0x10000},
395 {NULL, 0, 0}
396 },
397
398 .first_sysupgrade_partition = "os-image",
399 .last_sysupgrade_partition = "support-list",
400 },
401
402 /** Firmware layout for the CPE510 V3 */
403 {
404 .id = "CPE510V3",
405 .vendor = "CPE510(TP-LINK|UN|N300-5):3.0\r\n",
406 .support_list =
407 "SupportList:\r\n"
408 "CPE510(TP-LINK|EU|N300-5|00000000):3.0\r\n"
409 "CPE510(TP-LINK|EU|N300-5|45550000):3.0\r\n"
410 "CPE510(TP-LINK|EU|N300-5|55530000):3.0\r\n"
411 "CPE510(TP-LINK|UN|N300-5|00000000):3.0\r\n"
412 "CPE510(TP-LINK|UN|N300-5|45550000):3.0\r\n"
413 "CPE510(TP-LINK|UN|N300-5|55530000):3.0\r\n"
414 "CPE510(TP-LINK|US|N300-5|00000000):3.0\r\n"
415 "CPE510(TP-LINK|US|N300-5|45550000):3.0\r\n"
416 "CPE510(TP-LINK|US|N300-5|55530000):3.0\r\n"
417 "CPE510(TP-LINK|UN|N300-5):3.0\r\n"
418 "CPE510(TP-LINK|EU|N300-5):3.0\r\n"
419 "CPE510(TP-LINK|US|N300-5):3.0\r\n",
420 .support_trail = '\xff',
421 .soft_ver = NULL,
422
423 .partitions = {
424 {"fs-uboot", 0x00000, 0x20000},
425 {"partition-table", 0x20000, 0x02000},
426 {"default-mac", 0x30000, 0x00020},
427 {"product-info", 0x31100, 0x00100},
428 {"signature", 0x32000, 0x00400},
429 {"os-image", 0x40000, 0x200000},
430 {"file-system", 0x240000, 0x570000},
431 {"soft-version", 0x7b0000, 0x00100},
432 {"support-list", 0x7b1000, 0x00400},
433 {"user-config", 0x7c0000, 0x10000},
434 {"default-config", 0x7d0000, 0x10000},
435 {"log", 0x7e0000, 0x10000},
436 {"radio", 0x7f0000, 0x10000},
437 {NULL, 0, 0}
438 },
439
440 .first_sysupgrade_partition = "os-image",
441 .last_sysupgrade_partition = "support-list",
442 },
443
444 /** Firmware layout for the CPE610V1 */
445 {
446 .id = "CPE610V1",
447 .vendor = "CPE610(TP-LINK|UN|N300-5|00000000):1.0\r\n",
448 .support_list =
449 "SupportList:\r\n"
450 "CPE610(TP-LINK|EU|N300-5|00000000):1.0\r\n"
451 "CPE610(TP-LINK|EU|N300-5|45550000):1.0\r\n"
452 "CPE610(TP-LINK|EU|N300-5|55530000):1.0\r\n"
453 "CPE610(TP-LINK|UN|N300-5|00000000):1.0\r\n"
454 "CPE610(TP-LINK|UN|N300-5|45550000):1.0\r\n"
455 "CPE610(TP-LINK|UN|N300-5|55530000):1.0\r\n"
456 "CPE610(TP-LINK|US|N300-5|55530000):1.0\r\n"
457 "CPE610(TP-LINK|UN|N300-5):1.0\r\n"
458 "CPE610(TP-LINK|EU|N300-5):1.0\r\n"
459 "CPE610(TP-LINK|US|N300-5):1.0\r\n",
460 .support_trail = '\xff',
461 .soft_ver = NULL,
462
463 .partitions = {
464 {"fs-uboot", 0x00000, 0x20000},
465 {"partition-table", 0x20000, 0x02000},
466 {"default-mac", 0x30000, 0x00020},
467 {"product-info", 0x31100, 0x00100},
468 {"signature", 0x32000, 0x00400},
469 {"os-image", 0x40000, 0x200000},
470 {"file-system", 0x240000, 0x570000},
471 {"soft-version", 0x7b0000, 0x00100},
472 {"support-list", 0x7b1000, 0x00400},
473 {"user-config", 0x7c0000, 0x10000},
474 {"default-config", 0x7d0000, 0x10000},
475 {"log", 0x7e0000, 0x10000},
476 {"radio", 0x7f0000, 0x10000},
477 {NULL, 0, 0}
478 },
479
480 .first_sysupgrade_partition = "os-image",
481 .last_sysupgrade_partition = "support-list",
482 },
483
484 /** Firmware layout for the CPE610V2 */
485 {
486 .id = "CPE610V2",
487 .vendor = "CPE610(TP-LINK|UN|N300-5|00000000):2.0\r\n",
488 .support_list =
489 "SupportList:\r\n"
490 "CPE610(TP-LINK|EU|N300-5|00000000):2.0\r\n"
491 "CPE610(TP-LINK|EU|N300-5|45550000):2.0\r\n"
492 "CPE610(TP-LINK|EU|N300-5|55530000):2.0\r\n"
493 "CPE610(TP-LINK|UN|N300-5|00000000):2.0\r\n"
494 "CPE610(TP-LINK|UN|N300-5|45550000):2.0\r\n"
495 "CPE610(TP-LINK|UN|N300-5|55530000):2.0\r\n"
496 "CPE610(TP-LINK|US|N300-5|55530000):2.0\r\n"
497 "CPE610(TP-LINK|UN|N300-5):2.0\r\n"
498 "CPE610(TP-LINK|EU|N300-5):2.0\r\n"
499 "CPE610(TP-LINK|US|N300-5):2.0\r\n",
500 .support_trail = '\xff',
501 .soft_ver = NULL,
502
503 .partitions = {
504 {"fs-uboot", 0x00000, 0x20000},
505 {"partition-table", 0x20000, 0x02000},
506 {"default-mac", 0x30000, 0x00020},
507 {"product-info", 0x31100, 0x00100},
508 {"signature", 0x32000, 0x00400},
509 {"os-image", 0x40000, 0x200000},
510 {"file-system", 0x240000, 0x570000},
511 {"soft-version", 0x7b0000, 0x00100},
512 {"support-list", 0x7b1000, 0x00400},
513 {"user-config", 0x7c0000, 0x10000},
514 {"default-config", 0x7d0000, 0x10000},
515 {"log", 0x7e0000, 0x10000},
516 {"radio", 0x7f0000, 0x10000},
517 {NULL, 0, 0}
518 },
519
520 .first_sysupgrade_partition = "os-image",
521 .last_sysupgrade_partition = "support-list",
522 },
523
524 {
525 .id = "WBS210",
526 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
527 .support_list =
528 "SupportList:\r\n"
529 "WBS210(TP-LINK|UN|N300-2):1.20\r\n"
530 "WBS210(TP-LINK|US|N300-2):1.20\r\n"
531 "WBS210(TP-LINK|EU|N300-2):1.20\r\n",
532 .support_trail = '\xff',
533 .soft_ver = NULL,
534
535 .partitions = {
536 {"fs-uboot", 0x00000, 0x20000},
537 {"partition-table", 0x20000, 0x02000},
538 {"default-mac", 0x30000, 0x00020},
539 {"product-info", 0x31100, 0x00100},
540 {"signature", 0x32000, 0x00400},
541 {"os-image", 0x40000, 0x200000},
542 {"file-system", 0x240000, 0x570000},
543 {"soft-version", 0x7b0000, 0x00100},
544 {"support-list", 0x7b1000, 0x00400},
545 {"user-config", 0x7c0000, 0x10000},
546 {"default-config", 0x7d0000, 0x10000},
547 {"log", 0x7e0000, 0x10000},
548 {"radio", 0x7f0000, 0x10000},
549 {NULL, 0, 0}
550 },
551
552 .first_sysupgrade_partition = "os-image",
553 .last_sysupgrade_partition = "support-list",
554 },
555
556 {
557 .id = "WBS210V2",
558 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
559 .support_list =
560 "SupportList:\r\n"
561 "WBS210(TP-LINK|UN|N300-2|00000000):2.0\r\n"
562 "WBS210(TP-LINK|US|N300-2|55530000):2.0\r\n"
563 "WBS210(TP-LINK|EU|N300-2|45550000):2.0\r\n",
564 .support_trail = '\xff',
565 .soft_ver = NULL,
566
567 .partitions = {
568 {"fs-uboot", 0x00000, 0x20000},
569 {"partition-table", 0x20000, 0x02000},
570 {"default-mac", 0x30000, 0x00020},
571 {"product-info", 0x31100, 0x00100},
572 {"signature", 0x32000, 0x00400},
573 {"os-image", 0x40000, 0x200000},
574 {"file-system", 0x240000, 0x570000},
575 {"soft-version", 0x7b0000, 0x00100},
576 {"support-list", 0x7b1000, 0x00400},
577 {"user-config", 0x7c0000, 0x10000},
578 {"default-config", 0x7d0000, 0x10000},
579 {"log", 0x7e0000, 0x10000},
580 {"radio", 0x7f0000, 0x10000},
581 {NULL, 0, 0}
582 },
583
584 .first_sysupgrade_partition = "os-image",
585 .last_sysupgrade_partition = "support-list",
586 },
587
588 {
589 .id = "WBS510",
590 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
591 .support_list =
592 "SupportList:\r\n"
593 "WBS510(TP-LINK|UN|N300-5):1.20\r\n"
594 "WBS510(TP-LINK|US|N300-5):1.20\r\n"
595 "WBS510(TP-LINK|EU|N300-5):1.20\r\n"
596 "WBS510(TP-LINK|CA|N300-5):1.20\r\n",
597 .support_trail = '\xff',
598 .soft_ver = NULL,
599
600 .partitions = {
601 {"fs-uboot", 0x00000, 0x20000},
602 {"partition-table", 0x20000, 0x02000},
603 {"default-mac", 0x30000, 0x00020},
604 {"product-info", 0x31100, 0x00100},
605 {"signature", 0x32000, 0x00400},
606 {"os-image", 0x40000, 0x200000},
607 {"file-system", 0x240000, 0x570000},
608 {"soft-version", 0x7b0000, 0x00100},
609 {"support-list", 0x7b1000, 0x00400},
610 {"user-config", 0x7c0000, 0x10000},
611 {"default-config", 0x7d0000, 0x10000},
612 {"log", 0x7e0000, 0x10000},
613 {"radio", 0x7f0000, 0x10000},
614 {NULL, 0, 0}
615 },
616
617 .first_sysupgrade_partition = "os-image",
618 .last_sysupgrade_partition = "support-list",
619 },
620
621 {
622 .id = "WBS510V2",
623 .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
624 .support_list =
625 "SupportList:\r\n"
626 "WBS510(TP-LINK|UN|N300-5|00000000):2.0\r\n"
627 "WBS510(TP-LINK|US|N300-5|55530000):2.0\r\n"
628 "WBS510(TP-LINK|EU|N300-5|45550000):2.0\r\n"
629 "WBS510(TP-LINK|CA|N300-5|43410000):2.0\r\n",
630 .support_trail = '\xff',
631 .soft_ver = NULL,
632
633 .partitions = {
634 {"fs-uboot", 0x00000, 0x20000},
635 {"partition-table", 0x20000, 0x02000},
636 {"default-mac", 0x30000, 0x00020},
637 {"product-info", 0x31100, 0x00100},
638 {"signature", 0x32000, 0x00400},
639 {"os-image", 0x40000, 0x200000},
640 {"file-system", 0x240000, 0x570000},
641 {"soft-version", 0x7b0000, 0x00100},
642 {"support-list", 0x7b1000, 0x00400},
643 {"user-config", 0x7c0000, 0x10000},
644 {"default-config", 0x7d0000, 0x10000},
645 {"log", 0x7e0000, 0x10000},
646 {"radio", 0x7f0000, 0x10000},
647 {NULL, 0, 0}
648 },
649
650 .first_sysupgrade_partition = "os-image",
651 .last_sysupgrade_partition = "support-list",
652 },
653
654 /** Firmware layout for the C2600 */
655 {
656 .id = "C2600",
657 .vendor = "",
658 .support_list =
659 "SupportList:\r\n"
660 "{product_name:Archer C2600,product_ver:1.0.0,special_id:00000000}\r\n",
661 .support_trail = '\x00',
662 .soft_ver = NULL,
663
664 /**
665 We use a bigger os-image partition than the stock images (and thus
666 smaller file-system), as our kernel doesn't fit in the stock firmware's
667 2 MB os-image since kernel 4.14.
668 */
669 .partitions = {
670 {"SBL1", 0x00000, 0x20000},
671 {"MIBIB", 0x20000, 0x20000},
672 {"SBL2", 0x40000, 0x20000},
673 {"SBL3", 0x60000, 0x30000},
674 {"DDRCONFIG", 0x90000, 0x10000},
675 {"SSD", 0xa0000, 0x10000},
676 {"TZ", 0xb0000, 0x30000},
677 {"RPM", 0xe0000, 0x20000},
678 {"fs-uboot", 0x100000, 0x70000},
679 {"uboot-env", 0x170000, 0x40000},
680 {"radio", 0x1b0000, 0x40000},
681 {"os-image", 0x1f0000, 0x400000}, /* Stock: base 0x1f0000 size 0x200000 */
682 {"file-system", 0x5f0000, 0x1900000}, /* Stock: base 0x3f0000 size 0x1b00000 */
683 {"default-mac", 0x1ef0000, 0x00200},
684 {"pin", 0x1ef0200, 0x00200},
685 {"product-info", 0x1ef0400, 0x0fc00},
686 {"partition-table", 0x1f00000, 0x10000},
687 {"soft-version", 0x1f10000, 0x10000},
688 {"support-list", 0x1f20000, 0x10000},
689 {"profile", 0x1f30000, 0x10000},
690 {"default-config", 0x1f40000, 0x10000},
691 {"user-config", 0x1f50000, 0x40000},
692 {"qos-db", 0x1f90000, 0x40000},
693 {"usb-config", 0x1fd0000, 0x10000},
694 {"log", 0x1fe0000, 0x20000},
695 {NULL, 0, 0}
696 },
697
698 .first_sysupgrade_partition = "os-image",
699 .last_sysupgrade_partition = "file-system"
700 },
701
702 /** Firmware layout for the A7-V5 */
703 {
704 .id = "ARCHER-A7-V5",
705 .support_list =
706 "SupportList:\n"
707 "{product_name:Archer A7,product_ver:5.0.0,special_id:45550000}\n"
708 "{product_name:Archer A7,product_ver:5.0.0,special_id:55530000}\n"
709 "{product_name:Archer A7,product_ver:5.0.0,special_id:43410000}\n"
710 "{product_name:Archer A7,product_ver:5.0.0,special_id:4A500000}\n"
711 "{product_name:Archer A7,product_ver:5.0.0,special_id:54570000}\n",
712 .support_trail = '\x00',
713 .soft_ver = "soft_ver:1.0.0\n",
714
715 /* We're using a dynamic kernel/rootfs split here */
716 .partitions = {
717 {"factory-boot", 0x00000, 0x20000},
718 {"fs-uboot", 0x20000, 0x20000},
719 {"firmware", 0x40000, 0xec0000}, /* Stock: name os-image base 0x40000 size 0x120000 */
720 /* Stock: name file-system base 0x160000 size 0xda0000 */
721 {"default-mac", 0xf40000, 0x00200},
722 {"pin", 0xf40200, 0x00200},
723 {"device-id", 0xf40400, 0x00100},
724 {"product-info", 0xf40500, 0x0fb00},
725 {"soft-version", 0xf50000, 0x00100},
726 {"extra-para", 0xf51000, 0x01000},
727 {"support-list", 0xf52000, 0x0a000},
728 {"profile", 0xf5c000, 0x04000},
729 {"default-config", 0xf60000, 0x10000},
730 {"user-config", 0xf70000, 0x40000},
731 {"certificate", 0xfb0000, 0x10000},
732 {"partition-table", 0xfc0000, 0x10000},
733 {"log", 0xfd0000, 0x20000},
734 {"radio", 0xff0000, 0x10000},
735 {NULL, 0, 0}
736 },
737
738 .first_sysupgrade_partition = "os-image",
739 .last_sysupgrade_partition = "file-system",
740 },
741
742 /** Firmware layout for the C2v3 */
743 {
744 .id = "ARCHER-C2-V3",
745 .support_list =
746 "SupportList:\n"
747 "{product_name:ArcherC2,product_ver:3.0.0,special_id:00000000}\n"
748 "{product_name:ArcherC2,product_ver:3.0.0,special_id:55530000}\n"
749 "{product_name:ArcherC2,product_ver:3.0.0,special_id:45550000}\n",
750 .support_trail = '\x00',
751 .soft_ver = "soft_ver:3.0.1\n",
752
753 /** We're using a dynamic kernel/rootfs split here */
754
755 .partitions = {
756 {"factory-boot", 0x00000, 0x20000},
757 {"fs-uboot", 0x20000, 0x10000},
758 {"firmware", 0x30000, 0x7a0000},
759 {"user-config", 0x7d0000, 0x04000},
760 {"default-mac", 0x7e0000, 0x00100},
761 {"device-id", 0x7e0100, 0x00100},
762 {"extra-para", 0x7e0200, 0x00100},
763 {"pin", 0x7e0300, 0x00100},
764 {"support-list", 0x7e0400, 0x00400},
765 {"soft-version", 0x7e0800, 0x00400},
766 {"product-info", 0x7e0c00, 0x01400},
767 {"partition-table", 0x7e2000, 0x01000},
768 {"profile", 0x7e3000, 0x01000},
769 {"default-config", 0x7e4000, 0x04000},
770 {"merge-config", 0x7ec000, 0x02000},
771 {"qos-db", 0x7ee000, 0x02000},
772 {"radio", 0x7f0000, 0x10000},
773 {NULL, 0, 0}
774 },
775
776 .first_sysupgrade_partition = "os-image",
777 .last_sysupgrade_partition = "file-system",
778 },
779
780 /** Firmware layout for the C25v1 */
781 {
782 .id = "ARCHER-C25-V1",
783 .support_list =
784 "SupportList:\n"
785 "{product_name:ArcherC25,product_ver:1.0.0,special_id:00000000}\n"
786 "{product_name:ArcherC25,product_ver:1.0.0,special_id:55530000}\n"
787 "{product_name:ArcherC25,product_ver:1.0.0,special_id:45550000}\n",
788 .support_trail = '\x00',
789 .soft_ver = "soft_ver:1.0.0\n",
790
791 /* We're using a dynamic kernel/rootfs split here */
792 .partitions = {
793 {"factory-boot", 0x00000, 0x20000},
794 {"fs-uboot", 0x20000, 0x10000},
795 {"firmware", 0x30000, 0x7a0000}, /* Stock: name os-image base 0x30000 size 0x100000 */
796 /* Stock: name file-system base 0x130000 size 0x6a0000 */
797 {"user-config", 0x7d0000, 0x04000},
798 {"default-mac", 0x7e0000, 0x00100},
799 {"device-id", 0x7e0100, 0x00100},
800 {"extra-para", 0x7e0200, 0x00100},
801 {"pin", 0x7e0300, 0x00100},
802 {"support-list", 0x7e0400, 0x00400},
803 {"soft-version", 0x7e0800, 0x00400},
804 {"product-info", 0x7e0c00, 0x01400},
805 {"partition-table", 0x7e2000, 0x01000},
806 {"profile", 0x7e3000, 0x01000},
807 {"default-config", 0x7e4000, 0x04000},
808 {"merge-config", 0x7ec000, 0x02000},
809 {"qos-db", 0x7ee000, 0x02000},
810 {"radio", 0x7f0000, 0x10000},
811 {NULL, 0, 0}
812 },
813
814 .first_sysupgrade_partition = "os-image",
815 .last_sysupgrade_partition = "file-system",
816 },
817
818 /** Firmware layout for the C58v1 */
819 {
820 .id = "ARCHER-C58-V1",
821 .vendor = "",
822 .support_list =
823 "SupportList:\r\n"
824 "{product_name:Archer C58,product_ver:1.0.0,special_id:00000000}\r\n"
825 "{product_name:Archer C58,product_ver:1.0.0,special_id:45550000}\r\n"
826 "{product_name:Archer C58,product_ver:1.0.0,special_id:55530000}\r\n",
827 .support_trail = '\x00',
828 .soft_ver = "soft_ver:1.0.0\n",
829
830 .partitions = {
831 {"fs-uboot", 0x00000, 0x10000},
832 {"default-mac", 0x10000, 0x00200},
833 {"pin", 0x10200, 0x00200},
834 {"product-info", 0x10400, 0x00100},
835 {"partition-table", 0x10500, 0x00800},
836 {"soft-version", 0x11300, 0x00200},
837 {"support-list", 0x11500, 0x00100},
838 {"device-id", 0x11600, 0x00100},
839 {"profile", 0x11700, 0x03900},
840 {"default-config", 0x15000, 0x04000},
841 {"user-config", 0x19000, 0x04000},
842 {"firmware", 0x20000, 0x7c8000},
843 {"certyficate", 0x7e8000, 0x08000},
844 {"radio", 0x7f0000, 0x10000},
845 {NULL, 0, 0}
846 },
847
848 .first_sysupgrade_partition = "os-image",
849 .last_sysupgrade_partition = "file-system",
850 },
851
852 /** Firmware layout for the C59v1 */
853 {
854 .id = "ARCHER-C59-V1",
855 .vendor = "",
856 .support_list =
857 "SupportList:\r\n"
858 "{product_name:Archer C59,product_ver:1.0.0,special_id:00000000}\r\n"
859 "{product_name:Archer C59,product_ver:1.0.0,special_id:45550000}\r\n"
860 "{product_name:Archer C59,product_ver:1.0.0,special_id:52550000}\r\n"
861 "{product_name:Archer C59,product_ver:1.0.0,special_id:55530000}\r\n",
862 .support_trail = '\x00',
863 .soft_ver = "soft_ver:1.0.0\n",
864
865 /* We're using a dynamic kernel/rootfs split here */
866 .partitions = {
867 {"fs-uboot", 0x00000, 0x10000},
868 {"default-mac", 0x10000, 0x00200},
869 {"pin", 0x10200, 0x00200},
870 {"device-id", 0x10400, 0x00100},
871 {"product-info", 0x10500, 0x0fb00},
872 {"firmware", 0x20000, 0xe30000},
873 {"partition-table", 0xe50000, 0x10000},
874 {"soft-version", 0xe60000, 0x10000},
875 {"support-list", 0xe70000, 0x10000},
876 {"profile", 0xe80000, 0x10000},
877 {"default-config", 0xe90000, 0x10000},
878 {"user-config", 0xea0000, 0x40000},
879 {"usb-config", 0xee0000, 0x10000},
880 {"certificate", 0xef0000, 0x10000},
881 {"qos-db", 0xf00000, 0x40000},
882 {"log", 0xfe0000, 0x10000},
883 {"radio", 0xff0000, 0x10000},
884 {NULL, 0, 0}
885 },
886
887 .first_sysupgrade_partition = "os-image",
888 .last_sysupgrade_partition = "file-system",
889 },
890
891 /** Firmware layout for the C59v2 */
892 {
893 .id = "ARCHER-C59-V2",
894 .vendor = "",
895 .support_list =
896 "SupportList:\r\n"
897 "{product_name:Archer C59,product_ver:2.0.0,special_id:00000000}\r\n"
898 "{product_name:Archer C59,product_ver:2.0.0,special_id:45550000}\r\n"
899 "{product_name:Archer C59,product_ver:2.0.0,special_id:55530000}\r\n",
900 .support_trail = '\x00',
901 .soft_ver = "soft_ver:2.0.0 Build 20161206 rel.7303\n",
902
903 /** We're using a dynamic kernel/rootfs split here */
904 .partitions = {
905 {"factory-boot", 0x00000, 0x20000},
906 {"fs-uboot", 0x20000, 0x10000},
907 {"default-mac", 0x30000, 0x00200},
908 {"pin", 0x30200, 0x00200},
909 {"device-id", 0x30400, 0x00100},
910 {"product-info", 0x30500, 0x0fb00},
911 {"firmware", 0x40000, 0xe10000},
912 {"partition-table", 0xe50000, 0x10000},
913 {"soft-version", 0xe60000, 0x10000},
914 {"support-list", 0xe70000, 0x10000},
915 {"profile", 0xe80000, 0x10000},
916 {"default-config", 0xe90000, 0x10000},
917 {"user-config", 0xea0000, 0x40000},
918 {"usb-config", 0xee0000, 0x10000},
919 {"certificate", 0xef0000, 0x10000},
920 {"extra-para", 0xf00000, 0x10000},
921 {"qos-db", 0xf10000, 0x30000},
922 {"log", 0xfe0000, 0x10000},
923 {"radio", 0xff0000, 0x10000},
924 {NULL, 0, 0}
925 },
926
927 .first_sysupgrade_partition = "os-image",
928 .last_sysupgrade_partition = "file-system",
929 },
930
931 /** Firmware layout for the Archer C6 v2 (EU/RU/JP) */
932 {
933 .id = "ARCHER-C6-V2",
934 .vendor = "",
935 .support_list =
936 "SupportList:\r\n"
937 "{product_name:Archer C6,product_ver:2.0.0,special_id:45550000}\r\n"
938 "{product_name:Archer C6,product_ver:2.0.0,special_id:52550000}\r\n"
939 "{product_name:Archer C6,product_ver:2.0.0,special_id:4A500000}\r\n",
940 .support_trail = '\x00',
941 .soft_ver = "soft_ver:1.2.1\n",
942
943 .partitions = {
944 {"fs-uboot", 0x00000, 0x20000},
945 {"default-mac", 0x20000, 0x00200},
946 {"pin", 0x20200, 0x00100},
947 {"product-info", 0x20300, 0x00200},
948 {"device-id", 0x20500, 0x0fb00},
949 {"firmware", 0x30000, 0x7a9400},
950 {"soft-version", 0x7d9400, 0x00100},
951 {"extra-para", 0x7d9500, 0x00100},
952 {"support-list", 0x7d9600, 0x00200},
953 {"profile", 0x7d9800, 0x03000},
954 {"default-config", 0x7dc800, 0x03000},
955 {"partition-table", 0x7df800, 0x00800},
956 {"user-config", 0x7e0000, 0x0c000},
957 {"certificate", 0x7ec000, 0x04000},
958 {"radio", 0x7f0000, 0x10000},
959 {NULL, 0, 0}
960 },
961
962 .first_sysupgrade_partition = "os-image",
963 .last_sysupgrade_partition = "file-system",
964 },
965
966 /** Firmware layout for the Archer C6 v2 (US) and A6 v2 (US/TW) */
967 {
968 .id = "ARCHER-C6-V2-US",
969 .vendor = "",
970 .support_list =
971 "SupportList:\n"
972 "{product_name:Archer A6,product_ver:2.0.0,special_id:55530000}\n"
973 "{product_name:Archer A6,product_ver:2.0.0,special_id:54570000}\n"
974 "{product_name:Archer C6,product_ver:2.0.0,special_id:55530000}\n",
975 .support_trail = '\x00',
976 .soft_ver = "soft_ver:1.1.1\n",
977
978 .partitions = {
979 {"factory-boot", 0x00000, 0x20000},
980 {"default-mac", 0x20000, 0x00200},
981 {"pin", 0x20200, 0x00100},
982 {"product-info", 0x20300, 0x00200},
983 {"device-id", 0x20500, 0x0fb00},
984 {"fs-uboot", 0x30000, 0x20000},
985 {"firmware", 0x50000, 0xf89400},
986 {"soft-version", 0xfd9400, 0x00100},
987 {"extra-para", 0xfd9500, 0x00100},
988 {"support-list", 0xfd9600, 0x00200},
989 {"profile", 0xfd9800, 0x03000},
990 {"default-config", 0xfdc800, 0x03000},
991 {"partition-table", 0xfdf800, 0x00800},
992 {"user-config", 0xfe0000, 0x0c000},
993 {"certificate", 0xfec000, 0x04000},
994 {"radio", 0xff0000, 0x10000},
995 {NULL, 0, 0}
996 },
997 .first_sysupgrade_partition = "os-image",
998 .last_sysupgrade_partition = "file-system",
999 },
1000
1001 /** Firmware layout for the C60v1 */
1002 {
1003 .id = "ARCHER-C60-V1",
1004 .vendor = "",
1005 .support_list =
1006 "SupportList:\r\n"
1007 "{product_name:Archer C60,product_ver:1.0.0,special_id:00000000}\r\n"
1008 "{product_name:Archer C60,product_ver:1.0.0,special_id:45550000}\r\n"
1009 "{product_name:Archer C60,product_ver:1.0.0,special_id:55530000}\r\n",
1010 .support_trail = '\x00',
1011 .soft_ver = "soft_ver:1.0.0\n",
1012
1013 .partitions = {
1014 {"fs-uboot", 0x00000, 0x10000},
1015 {"default-mac", 0x10000, 0x00200},
1016 {"pin", 0x10200, 0x00200},
1017 {"product-info", 0x10400, 0x00100},
1018 {"partition-table", 0x10500, 0x00800},
1019 {"soft-version", 0x11300, 0x00200},
1020 {"support-list", 0x11500, 0x00100},
1021 {"device-id", 0x11600, 0x00100},
1022 {"profile", 0x11700, 0x03900},
1023 {"default-config", 0x15000, 0x04000},
1024 {"user-config", 0x19000, 0x04000},
1025 {"firmware", 0x20000, 0x7c8000},
1026 {"certyficate", 0x7e8000, 0x08000},
1027 {"radio", 0x7f0000, 0x10000},
1028 {NULL, 0, 0}
1029 },
1030
1031 .first_sysupgrade_partition = "os-image",
1032 .last_sysupgrade_partition = "file-system",
1033 },
1034
1035 /** Firmware layout for the C60v2 */
1036 {
1037 .id = "ARCHER-C60-V2",
1038 .vendor = "",
1039 .support_list =
1040 "SupportList:\r\n"
1041 "{product_name:Archer C60,product_ver:2.0.0,special_id:42520000}\r\n"
1042 "{product_name:Archer C60,product_ver:2.0.0,special_id:45550000}\r\n"
1043 "{product_name:Archer C60,product_ver:2.0.0,special_id:55530000}\r\n",
1044 .support_trail = '\x00',
1045 .soft_ver = "soft_ver:2.0.0\n",
1046
1047 .partitions = {
1048 {"factory-boot", 0x00000, 0x1fb00},
1049 {"default-mac", 0x1fb00, 0x00200},
1050 {"pin", 0x1fd00, 0x00100},
1051 {"product-info", 0x1fe00, 0x00100},
1052 {"device-id", 0x1ff00, 0x00100},
1053 {"fs-uboot", 0x20000, 0x10000},
1054 {"firmware", 0x30000, 0x7a0000},
1055 {"soft-version", 0x7d9500, 0x00100},
1056 {"support-list", 0x7d9600, 0x00100},
1057 {"extra-para", 0x7d9700, 0x00100},
1058 {"profile", 0x7d9800, 0x03000},
1059 {"default-config", 0x7dc800, 0x03000},
1060 {"partition-table", 0x7df800, 0x00800},
1061 {"user-config", 0x7e0000, 0x0c000},
1062 {"certificate", 0x7ec000, 0x04000},
1063 {"radio", 0x7f0000, 0x10000},
1064 {NULL, 0, 0}
1065 },
1066
1067 .first_sysupgrade_partition = "os-image",
1068 .last_sysupgrade_partition = "file-system",
1069 },
1070
1071 /** Firmware layout for the C60v3 */
1072 {
1073 .id = "ARCHER-C60-V3",
1074 .vendor = "",
1075 .support_list =
1076 "SupportList:\r\n"
1077 "{product_name:Archer C60,product_ver:3.0.0,special_id:42520000}\r\n"
1078 "{product_name:Archer C60,product_ver:3.0.0,special_id:45550000}\r\n"
1079 "{product_name:Archer C60,product_ver:3.0.0,special_id:55530000}\r\n",
1080 .support_trail = '\x00',
1081 .soft_ver = "soft_ver:3.0.0\n",
1082
1083 .partitions = {
1084 {"factory-boot", 0x00000, 0x1fb00},
1085 {"default-mac", 0x1fb00, 0x00200},
1086 {"pin", 0x1fd00, 0x00100},
1087 {"product-info", 0x1fe00, 0x00100},
1088 {"device-id", 0x1ff00, 0x00100},
1089 {"fs-uboot", 0x20000, 0x10000},
1090 {"firmware", 0x30000, 0x7a0000},
1091 {"soft-version", 0x7d9500, 0x00100},
1092 {"support-list", 0x7d9600, 0x00100},
1093 {"extra-para", 0x7d9700, 0x00100},
1094 {"profile", 0x7d9800, 0x03000},
1095 {"default-config", 0x7dc800, 0x03000},
1096 {"partition-table", 0x7df800, 0x00800},
1097 {"user-config", 0x7e0000, 0x0c000},
1098 {"certificate", 0x7ec000, 0x04000},
1099 {"radio", 0x7f0000, 0x10000},
1100 {NULL, 0, 0}
1101 },
1102
1103 .first_sysupgrade_partition = "os-image",
1104 .last_sysupgrade_partition = "file-system",
1105 },
1106
1107 /** Firmware layout for the C5 */
1108 {
1109 .id = "ARCHER-C5-V2",
1110 .vendor = "",
1111 .support_list =
1112 "SupportList:\r\n"
1113 "{product_name:ArcherC5,product_ver:2.0.0,special_id:00000000}\r\n"
1114 "{product_name:ArcherC5,product_ver:2.0.0,special_id:55530000}\r\n"
1115 "{product_name:ArcherC5,product_ver:2.0.0,special_id:4A500000}\r\n", /* JP version */
1116 .support_trail = '\x00',
1117 .soft_ver = NULL,
1118
1119 .partitions = {
1120 {"fs-uboot", 0x00000, 0x40000},
1121 {"os-image", 0x40000, 0x200000},
1122 {"file-system", 0x240000, 0xc00000},
1123 {"default-mac", 0xe40000, 0x00200},
1124 {"pin", 0xe40200, 0x00200},
1125 {"product-info", 0xe40400, 0x00200},
1126 {"partition-table", 0xe50000, 0x10000},
1127 {"soft-version", 0xe60000, 0x00200},
1128 {"support-list", 0xe61000, 0x0f000},
1129 {"profile", 0xe70000, 0x10000},
1130 {"default-config", 0xe80000, 0x10000},
1131 {"user-config", 0xe90000, 0x50000},
1132 {"log", 0xee0000, 0x100000},
1133 {"radio_bk", 0xfe0000, 0x10000},
1134 {"radio", 0xff0000, 0x10000},
1135 {NULL, 0, 0}
1136 },
1137
1138 .first_sysupgrade_partition = "os-image",
1139 .last_sysupgrade_partition = "file-system"
1140 },
1141
1142 /** Firmware layout for the C7 */
1143 {
1144 .id = "ARCHER-C7-V4",
1145 .support_list =
1146 "SupportList:\n"
1147 "{product_name:Archer C7,product_ver:4.0.0,special_id:00000000}\n"
1148 "{product_name:Archer C7,product_ver:4.0.0,special_id:41550000}\n"
1149 "{product_name:Archer C7,product_ver:4.0.0,special_id:45550000}\n"
1150 "{product_name:Archer C7,product_ver:4.0.0,special_id:4B520000}\n"
1151 "{product_name:Archer C7,product_ver:4.0.0,special_id:42520000}\n"
1152 "{product_name:Archer C7,product_ver:4.0.0,special_id:4A500000}\n"
1153 "{product_name:Archer C7,product_ver:4.0.0,special_id:52550000}\n"
1154 "{product_name:Archer C7,product_ver:4.0.0,special_id:54570000}\n"
1155 "{product_name:Archer C7,product_ver:4.0.0,special_id:55530000}\n"
1156 "{product_name:Archer C7,product_ver:4.0.0,special_id:43410000}\n",
1157 .support_trail = '\x00',
1158 .soft_ver = "soft_ver:1.0.0\n",
1159
1160 /* We're using a dynamic kernel/rootfs split here */
1161 .partitions = {
1162 {"factory-boot", 0x00000, 0x20000},
1163 {"fs-uboot", 0x20000, 0x20000},
1164 {"firmware", 0x40000, 0xEC0000}, /* Stock: name os-image base 0x40000 size 0x120000 */
1165 /* Stock: name file-system base 0x160000 size 0xda0000 */
1166 {"default-mac", 0xf00000, 0x00200},
1167 {"pin", 0xf00200, 0x00200},
1168 {"device-id", 0xf00400, 0x00100},
1169 {"product-info", 0xf00500, 0x0fb00},
1170 {"soft-version", 0xf10000, 0x00100},
1171 {"extra-para", 0xf11000, 0x01000},
1172 {"support-list", 0xf12000, 0x0a000},
1173 {"profile", 0xf1c000, 0x04000},
1174 {"default-config", 0xf20000, 0x10000},
1175 {"user-config", 0xf30000, 0x40000},
1176 {"qos-db", 0xf70000, 0x40000},
1177 {"certificate", 0xfb0000, 0x10000},
1178 {"partition-table", 0xfc0000, 0x10000},
1179 {"log", 0xfd0000, 0x20000},
1180 {"radio", 0xff0000, 0x10000},
1181 {NULL, 0, 0}
1182 },
1183
1184 .first_sysupgrade_partition = "os-image",
1185 .last_sysupgrade_partition = "file-system",
1186 },
1187
1188 /** Firmware layout for the C7 v5*/
1189 {
1190 .id = "ARCHER-C7-V5",
1191 .support_list =
1192 "SupportList:\n"
1193 "{product_name:Archer C7,product_ver:5.0.0,special_id:00000000}\n"
1194 "{product_name:Archer C7,product_ver:5.0.0,special_id:45550000}\n"
1195 "{product_name:Archer C7,product_ver:5.0.0,special_id:55530000}\n"
1196 "{product_name:Archer C7,product_ver:5.0.0,special_id:43410000}\n"
1197 "{product_name:Archer C7,product_ver:5.0.0,special_id:4A500000}\n"
1198 "{product_name:Archer C7,product_ver:5.0.0,special_id:54570000}\n"
1199 "{product_name:Archer C7,product_ver:5.0.0,special_id:52550000}\n"
1200 "{product_name:Archer C7,product_ver:5.0.0,special_id:4B520000}\n",
1201
1202 .support_trail = '\x00',
1203 .soft_ver = "soft_ver:1.0.0\n",
1204
1205 /* We're using a dynamic kernel/rootfs split here */
1206 .partitions = {
1207 {"factory-boot", 0x00000, 0x20000},
1208 {"fs-uboot", 0x20000, 0x20000},
1209 {"partition-table", 0x40000, 0x10000},
1210 {"radio", 0x50000, 0x10000},
1211 {"default-mac", 0x60000, 0x00200},
1212 {"pin", 0x60200, 0x00200},
1213 {"device-id", 0x60400, 0x00100},
1214 {"product-info", 0x60500, 0x0fb00},
1215 {"soft-version", 0x70000, 0x01000},
1216 {"extra-para", 0x71000, 0x01000},
1217 {"support-list", 0x72000, 0x0a000},
1218 {"profile", 0x7c000, 0x04000},
1219 {"user-config", 0x80000, 0x40000},
1220
1221
1222 {"firmware", 0xc0000, 0xf00000}, /* Stock: name os-image base 0xc0000 size 0x120000 */
1223 /* Stock: name file-system base 0x1e0000 size 0xde0000 */
1224
1225 {"log", 0xfc0000, 0x20000},
1226 {"certificate", 0xfe0000, 0x10000},
1227 {"default-config", 0xff0000, 0x10000},
1228 {NULL, 0, 0}
1229
1230 },
1231
1232 .first_sysupgrade_partition = "os-image",
1233 .last_sysupgrade_partition = "file-system",
1234 },
1235
1236 /** Firmware layout for the C9 */
1237 {
1238 .id = "ARCHERC9",
1239 .vendor = "",
1240 .support_list =
1241 "SupportList:\n"
1242 "{product_name:ArcherC9,"
1243 "product_ver:1.0.0,"
1244 "special_id:00000000}\n",
1245 .support_trail = '\x00',
1246 .soft_ver = NULL,
1247
1248 .partitions = {
1249 {"fs-uboot", 0x00000, 0x40000},
1250 {"os-image", 0x40000, 0x200000},
1251 {"file-system", 0x240000, 0xc00000},
1252 {"default-mac", 0xe40000, 0x00200},
1253 {"pin", 0xe40200, 0x00200},
1254 {"product-info", 0xe40400, 0x00200},
1255 {"partition-table", 0xe50000, 0x10000},
1256 {"soft-version", 0xe60000, 0x00200},
1257 {"support-list", 0xe61000, 0x0f000},
1258 {"profile", 0xe70000, 0x10000},
1259 {"default-config", 0xe80000, 0x10000},
1260 {"user-config", 0xe90000, 0x50000},
1261 {"log", 0xee0000, 0x100000},
1262 {"radio_bk", 0xfe0000, 0x10000},
1263 {"radio", 0xff0000, 0x10000},
1264 {NULL, 0, 0}
1265 },
1266
1267 .first_sysupgrade_partition = "os-image",
1268 .last_sysupgrade_partition = "file-system"
1269 },
1270
1271 /** Firmware layout for the EAP120 */
1272 {
1273 .id = "EAP120",
1274 .vendor = "EAP120(TP-LINK|UN|N300-2):1.0\r\n",
1275 .support_list =
1276 "SupportList:\r\n"
1277 "EAP120(TP-LINK|UN|N300-2):1.0\r\n",
1278 .support_trail = '\xff',
1279 .soft_ver = NULL,
1280
1281 .partitions = {
1282 {"fs-uboot", 0x00000, 0x20000},
1283 {"partition-table", 0x20000, 0x02000},
1284 {"default-mac", 0x30000, 0x00020},
1285 {"support-list", 0x31000, 0x00100},
1286 {"product-info", 0x31100, 0x00100},
1287 {"soft-version", 0x32000, 0x00100},
1288 {"os-image", 0x40000, 0x180000},
1289 {"file-system", 0x1c0000, 0x600000},
1290 {"user-config", 0x7c0000, 0x10000},
1291 {"backup-config", 0x7d0000, 0x10000},
1292 {"log", 0x7e0000, 0x10000},
1293 {"radio", 0x7f0000, 0x10000},
1294 {NULL, 0, 0}
1295 },
1296
1297 .first_sysupgrade_partition = "os-image",
1298 .last_sysupgrade_partition = "file-system"
1299 },
1300
1301 /** Firmware layout for the TL-WA850RE v2 */
1302 {
1303 .id = "TLWA850REV2",
1304 .vendor = "",
1305 .support_list =
1306 "SupportList:\n"
1307 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:55530000}\n"
1308 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:00000000}\n"
1309 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:55534100}\n"
1310 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:45550000}\n"
1311 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:4B520000}\n"
1312 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:42520000}\n"
1313 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:4A500000}\n"
1314 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:43410000}\n"
1315 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:41550000}\n"
1316 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:52550000}\n",
1317 .support_trail = '\x00',
1318 .soft_ver = NULL,
1319
1320 /**
1321 576KB were moved from file-system to os-image
1322 in comparison to the stock image
1323 */
1324 .partitions = {
1325 {"fs-uboot", 0x00000, 0x20000},
1326 {"firmware", 0x20000, 0x390000},
1327 {"partition-table", 0x3b0000, 0x02000},
1328 {"default-mac", 0x3c0000, 0x00020},
1329 {"pin", 0x3c0100, 0x00020},
1330 {"product-info", 0x3c1000, 0x01000},
1331 {"soft-version", 0x3c2000, 0x00100},
1332 {"support-list", 0x3c3000, 0x01000},
1333 {"profile", 0x3c4000, 0x08000},
1334 {"user-config", 0x3d0000, 0x10000},
1335 {"default-config", 0x3e0000, 0x10000},
1336 {"radio", 0x3f0000, 0x10000},
1337 {NULL, 0, 0}
1338 },
1339
1340 .first_sysupgrade_partition = "os-image",
1341 .last_sysupgrade_partition = "file-system"
1342 },
1343
1344 /** Firmware layout for the TL-WA855RE v1 */
1345 {
1346 .id = "TLWA855REV1",
1347 .vendor = "",
1348 .support_list =
1349 "SupportList:\n"
1350 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:00000000}\n"
1351 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:55530000}\n"
1352 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:45550000}\n"
1353 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:4B520000}\n"
1354 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:42520000}\n"
1355 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:4A500000}\n"
1356 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:43410000}\n"
1357 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:41550000}\n"
1358 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:52550000}\n",
1359 .support_trail = '\x00',
1360 .soft_ver = NULL,
1361
1362 .partitions = {
1363 {"fs-uboot", 0x00000, 0x20000},
1364 {"os-image", 0x20000, 0x150000},
1365 {"file-system", 0x170000, 0x240000},
1366 {"partition-table", 0x3b0000, 0x02000},
1367 {"default-mac", 0x3c0000, 0x00020},
1368 {"pin", 0x3c0100, 0x00020},
1369 {"product-info", 0x3c1000, 0x01000},
1370 {"soft-version", 0x3c2000, 0x00100},
1371 {"support-list", 0x3c3000, 0x01000},
1372 {"profile", 0x3c4000, 0x08000},
1373 {"user-config", 0x3d0000, 0x10000},
1374 {"default-config", 0x3e0000, 0x10000},
1375 {"radio", 0x3f0000, 0x10000},
1376 {NULL, 0, 0}
1377 },
1378
1379 .first_sysupgrade_partition = "os-image",
1380 .last_sysupgrade_partition = "file-system"
1381 },
1382
1383 /** Firmware layout for the TL-WR1043 v5 */
1384 {
1385 .id = "TLWR1043NV5",
1386 .vendor = "",
1387 .support_list =
1388 "SupportList:\n"
1389 "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:45550000}\n"
1390 "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:55530000}\n",
1391 .support_trail = '\x00',
1392 .soft_ver = "soft_ver:1.0.0\n",
1393 .partitions = {
1394 {"factory-boot", 0x00000, 0x20000},
1395 {"fs-uboot", 0x20000, 0x20000},
1396 {"firmware", 0x40000, 0xec0000},
1397 {"default-mac", 0xf00000, 0x00200},
1398 {"pin", 0xf00200, 0x00200},
1399 {"device-id", 0xf00400, 0x00100},
1400 {"product-info", 0xf00500, 0x0fb00},
1401 {"soft-version", 0xf10000, 0x01000},
1402 {"extra-para", 0xf11000, 0x01000},
1403 {"support-list", 0xf12000, 0x0a000},
1404 {"profile", 0xf1c000, 0x04000},
1405 {"default-config", 0xf20000, 0x10000},
1406 {"user-config", 0xf30000, 0x40000},
1407 {"qos-db", 0xf70000, 0x40000},
1408 {"certificate", 0xfb0000, 0x10000},
1409 {"partition-table", 0xfc0000, 0x10000},
1410 {"log", 0xfd0000, 0x20000},
1411 {"radio", 0xff0000, 0x10000},
1412 {NULL, 0, 0}
1413 },
1414 .first_sysupgrade_partition = "os-image",
1415 .last_sysupgrade_partition = "file-system"
1416 },
1417
1418 /** Firmware layout for the TL-WR1043 v4 */
1419 {
1420 .id = "TLWR1043NDV4",
1421 .vendor = "",
1422 .support_list =
1423 "SupportList:\n"
1424 "{product_name:TL-WR1043ND,product_ver:4.0.0,special_id:45550000}\n",
1425 .support_trail = '\x00',
1426 .soft_ver = NULL,
1427
1428 /* We're using a dynamic kernel/rootfs split here */
1429 .partitions = {
1430 {"fs-uboot", 0x00000, 0x20000},
1431 {"firmware", 0x20000, 0xf30000},
1432 {"default-mac", 0xf50000, 0x00200},
1433 {"pin", 0xf50200, 0x00200},
1434 {"product-info", 0xf50400, 0x0fc00},
1435 {"soft-version", 0xf60000, 0x0b000},
1436 {"support-list", 0xf6b000, 0x04000},
1437 {"profile", 0xf70000, 0x04000},
1438 {"default-config", 0xf74000, 0x0b000},
1439 {"user-config", 0xf80000, 0x40000},
1440 {"partition-table", 0xfc0000, 0x10000},
1441 {"log", 0xfd0000, 0x20000},
1442 {"radio", 0xff0000, 0x10000},
1443 {NULL, 0, 0}
1444 },
1445
1446 .first_sysupgrade_partition = "os-image",
1447 .last_sysupgrade_partition = "file-system"
1448 },
1449
1450 /** Firmware layout for the TL-WR902AC v1 */
1451 {
1452 .id = "TL-WR902AC-V1",
1453 .vendor = "",
1454 .support_list =
1455 "SupportList:\n"
1456 "{product_name:TL-WR902AC,product_ver:1.0.0,special_id:45550000}\n"
1457 "{product_name:TL-WR902AC,product_ver:1.0.0,special_id:55530000}\n",
1458 .support_trail = '\x00',
1459 .soft_ver = NULL,
1460
1461 /**
1462 384KB were moved from file-system to os-image
1463 in comparison to the stock image
1464 */
1465 .partitions = {
1466 {"fs-uboot", 0x00000, 0x20000},
1467 {"firmware", 0x20000, 0x730000},
1468 {"default-mac", 0x750000, 0x00200},
1469 {"pin", 0x750200, 0x00200},
1470 {"product-info", 0x750400, 0x0fc00},
1471 {"soft-version", 0x760000, 0x0b000},
1472 {"support-list", 0x76b000, 0x04000},
1473 {"profile", 0x770000, 0x04000},
1474 {"default-config", 0x774000, 0x0b000},
1475 {"user-config", 0x780000, 0x40000},
1476 {"partition-table", 0x7c0000, 0x10000},
1477 {"log", 0x7d0000, 0x20000},
1478 {"radio", 0x7f0000, 0x10000},
1479 {NULL, 0, 0}
1480 },
1481
1482 .first_sysupgrade_partition = "os-image",
1483 .last_sysupgrade_partition = "file-system",
1484 },
1485
1486 /** Firmware layout for the TL-WR942N V1 */
1487 {
1488 .id = "TLWR942NV1",
1489 .vendor = "",
1490 .support_list =
1491 "SupportList:\r\n"
1492 "{product_name:TL-WR942N,product_ver:1.0.0,special_id:00000000}\r\n"
1493 "{product_name:TL-WR942N,product_ver:1.0.0,special_id:52550000}\r\n",
1494 .support_trail = '\x00',
1495 .soft_ver = NULL,
1496
1497 .partitions = {
1498 {"fs-uboot", 0x00000, 0x20000},
1499 {"firmware", 0x20000, 0xe20000},
1500 {"default-mac", 0xe40000, 0x00200},
1501 {"pin", 0xe40200, 0x00200},
1502 {"product-info", 0xe40400, 0x0fc00},
1503 {"partition-table", 0xe50000, 0x10000},
1504 {"soft-version", 0xe60000, 0x10000},
1505 {"support-list", 0xe70000, 0x10000},
1506 {"profile", 0xe80000, 0x10000},
1507 {"default-config", 0xe90000, 0x10000},
1508 {"user-config", 0xea0000, 0x40000},
1509 {"qos-db", 0xee0000, 0x40000},
1510 {"certificate", 0xf20000, 0x10000},
1511 {"usb-config", 0xfb0000, 0x10000},
1512 {"log", 0xfc0000, 0x20000},
1513 {"radio-bk", 0xfe0000, 0x10000},
1514 {"radio", 0xff0000, 0x10000},
1515 {NULL, 0, 0}
1516 },
1517
1518 .first_sysupgrade_partition = "os-image",
1519 .last_sysupgrade_partition = "file-system",
1520 },
1521
1522 /** Firmware layout for the RE200 v2 */
1523 {
1524 .id = "RE200-V2",
1525 .vendor = "",
1526 .support_list =
1527 "SupportList:\n"
1528 "{product_name:RE200,product_ver:2.0.0,special_id:00000000}\n"
1529 "{product_name:RE200,product_ver:2.0.0,special_id:41520000}\n"
1530 "{product_name:RE200,product_ver:2.0.0,special_id:41550000}\n"
1531 "{product_name:RE200,product_ver:2.0.0,special_id:42520000}\n"
1532 "{product_name:RE200,product_ver:2.0.0,special_id:43410000}\n"
1533 "{product_name:RE200,product_ver:2.0.0,special_id:45530000}\n"
1534 "{product_name:RE200,product_ver:2.0.0,special_id:45550000}\n"
1535 "{product_name:RE200,product_ver:2.0.0,special_id:49440000}\n"
1536 "{product_name:RE200,product_ver:2.0.0,special_id:4a500000}\n"
1537 "{product_name:RE200,product_ver:2.0.0,special_id:4b520000}\n"
1538 "{product_name:RE200,product_ver:2.0.0,special_id:52550000}\n"
1539 "{product_name:RE200,product_ver:2.0.0,special_id:54570000}\n"
1540 "{product_name:RE200,product_ver:2.0.0,special_id:55530000}\n",
1541 .support_trail = '\x00',
1542 .soft_ver = NULL,
1543
1544 .partitions = {
1545 {"fs-uboot", 0x00000, 0x20000},
1546 {"firmware", 0x20000, 0x7a0000},
1547 {"partition-table", 0x7c0000, 0x02000},
1548 {"default-mac", 0x7c2000, 0x00020},
1549 {"pin", 0x7c2100, 0x00020},
1550 {"product-info", 0x7c3100, 0x01000},
1551 {"soft-version", 0x7c4200, 0x01000},
1552 {"support-list", 0x7c5200, 0x01000},
1553 {"profile", 0x7c6200, 0x08000},
1554 {"config-info", 0x7ce200, 0x00400},
1555 {"user-config", 0x7d0000, 0x10000},
1556 {"default-config", 0x7e0000, 0x10000},
1557 {"radio", 0x7f0000, 0x10000},
1558 {NULL, 0, 0}
1559 },
1560
1561 .first_sysupgrade_partition = "os-image",
1562 .last_sysupgrade_partition = "file-system"
1563 },
1564
1565 /** Firmware layout for the RE220 v2 */
1566 {
1567 .id = "RE220-V2",
1568 .vendor = "",
1569 .support_list =
1570 "SupportList:\n"
1571 "{product_name:RE220,product_ver:2.0.0,special_id:00000000}\n"
1572 "{product_name:RE220,product_ver:2.0.0,special_id:41520000}\n"
1573 "{product_name:RE220,product_ver:2.0.0,special_id:41550000}\n"
1574 "{product_name:RE220,product_ver:2.0.0,special_id:42520000}\n"
1575 "{product_name:RE220,product_ver:2.0.0,special_id:43410000}\n"
1576 "{product_name:RE220,product_ver:2.0.0,special_id:45530000}\n"
1577 "{product_name:RE220,product_ver:2.0.0,special_id:45550000}\n"
1578 "{product_name:RE220,product_ver:2.0.0,special_id:49440000}\n"
1579 "{product_name:RE220,product_ver:2.0.0,special_id:4a500000}\n"
1580 "{product_name:RE220,product_ver:2.0.0,special_id:4b520000}\n"
1581 "{product_name:RE220,product_ver:2.0.0,special_id:52550000}\n"
1582 "{product_name:RE220,product_ver:2.0.0,special_id:54570000}\n"
1583 "{product_name:RE220,product_ver:2.0.0,special_id:55530000}\n",
1584 .support_trail = '\x00',
1585 .soft_ver = NULL,
1586
1587 .partitions = {
1588 {"fs-uboot", 0x00000, 0x20000},
1589 {"firmware", 0x20000, 0x7a0000},
1590 {"partition-table", 0x7c0000, 0x02000},
1591 {"default-mac", 0x7c2000, 0x00020},
1592 {"pin", 0x7c2100, 0x00020},
1593 {"product-info", 0x7c3100, 0x01000},
1594 {"soft-version", 0x7c4200, 0x01000},
1595 {"support-list", 0x7c5200, 0x01000},
1596 {"profile", 0x7c6200, 0x08000},
1597 {"config-info", 0x7ce200, 0x00400},
1598 {"user-config", 0x7d0000, 0x10000},
1599 {"default-config", 0x7e0000, 0x10000},
1600 {"radio", 0x7f0000, 0x10000},
1601 {NULL, 0, 0}
1602 },
1603
1604 .first_sysupgrade_partition = "os-image",
1605 .last_sysupgrade_partition = "file-system"
1606 },
1607
1608 /** Firmware layout for the RE305 v1 */
1609 {
1610 .id = "RE305-V1",
1611 .vendor = "",
1612 .support_list =
1613 "SupportList:\n"
1614 "{product_name:RE305,product_ver:1.0.0,special_id:45550000}\n"
1615 "{product_name:RE305,product_ver:1.0.0,special_id:55530000}\n"
1616 "{product_name:RE305,product_ver:1.0.0,special_id:4a500000}\n"
1617 "{product_name:RE305,product_ver:1.0.0,special_id:42520000}\n"
1618 "{product_name:RE305,product_ver:1.0.0,special_id:4b520000}\n"
1619 "{product_name:RE305,product_ver:1.0.0,special_id:41550000}\n"
1620 "{product_name:RE305,product_ver:1.0.0,special_id:43410000}\n",
1621 .support_trail = '\x00',
1622 .soft_ver = NULL,
1623
1624 .partitions = {
1625 {"fs-uboot", 0x00000, 0x20000},
1626 {"firmware", 0x20000, 0x5e0000},
1627 {"partition-table", 0x600000, 0x02000},
1628 {"default-mac", 0x610000, 0x00020},
1629 {"pin", 0x610100, 0x00020},
1630 {"product-info", 0x611100, 0x01000},
1631 {"soft-version", 0x620000, 0x01000},
1632 {"support-list", 0x621000, 0x01000},
1633 {"profile", 0x622000, 0x08000},
1634 {"user-config", 0x630000, 0x10000},
1635 {"default-config", 0x640000, 0x10000},
1636 {"radio", 0x7f0000, 0x10000},
1637 {NULL, 0, 0}
1638 },
1639
1640 .first_sysupgrade_partition = "os-image",
1641 .last_sysupgrade_partition = "file-system"
1642 },
1643
1644 /** Firmware layout for the RE350 v1 */
1645 {
1646 .id = "RE350-V1",
1647 .vendor = "",
1648 .support_list =
1649 "SupportList:\n"
1650 "{product_name:RE350,product_ver:1.0.0,special_id:45550000}\n"
1651 "{product_name:RE350,product_ver:1.0.0,special_id:00000000}\n"
1652 "{product_name:RE350,product_ver:1.0.0,special_id:41550000}\n"
1653 "{product_name:RE350,product_ver:1.0.0,special_id:55530000}\n"
1654 "{product_name:RE350,product_ver:1.0.0,special_id:43410000}\n"
1655 "{product_name:RE350,product_ver:1.0.0,special_id:4b520000}\n"
1656 "{product_name:RE350,product_ver:1.0.0,special_id:4a500000}\n",
1657 .support_trail = '\x00',
1658 .soft_ver = NULL,
1659
1660 /** We're using a dynamic kernel/rootfs split here */
1661 .partitions = {
1662 {"fs-uboot", 0x00000, 0x20000},
1663 {"firmware", 0x20000, 0x5e0000},
1664 {"partition-table", 0x600000, 0x02000},
1665 {"default-mac", 0x610000, 0x00020},
1666 {"pin", 0x610100, 0x00020},
1667 {"product-info", 0x611100, 0x01000},
1668 {"soft-version", 0x620000, 0x01000},
1669 {"support-list", 0x621000, 0x01000},
1670 {"profile", 0x622000, 0x08000},
1671 {"user-config", 0x630000, 0x10000},
1672 {"default-config", 0x640000, 0x10000},
1673 {"radio", 0x7f0000, 0x10000},
1674 {NULL, 0, 0}
1675 },
1676
1677 .first_sysupgrade_partition = "os-image",
1678 .last_sysupgrade_partition = "file-system"
1679 },
1680
1681 /** Firmware layout for the RE350K v1 */
1682 {
1683 .id = "RE350K-V1",
1684 .vendor = "",
1685 .support_list =
1686 "SupportList:\n"
1687 "{product_name:RE350K,product_ver:1.0.0,special_id:00000000,product_region:US}\n",
1688 .support_trail = '\x00',
1689 .soft_ver = NULL,
1690
1691 /** We're using a dynamic kernel/rootfs split here */
1692 .partitions = {
1693 {"fs-uboot", 0x00000, 0x20000},
1694 {"firmware", 0x20000, 0xd70000},
1695 {"partition-table", 0xd90000, 0x02000},
1696 {"default-mac", 0xda0000, 0x00020},
1697 {"pin", 0xda0100, 0x00020},
1698 {"product-info", 0xda1100, 0x01000},
1699 {"soft-version", 0xdb0000, 0x01000},
1700 {"support-list", 0xdb1000, 0x01000},
1701 {"profile", 0xdb2000, 0x08000},
1702 {"user-config", 0xdc0000, 0x10000},
1703 {"default-config", 0xdd0000, 0x10000},
1704 {"device-id", 0xde0000, 0x00108},
1705 {"radio", 0xff0000, 0x10000},
1706 {NULL, 0, 0}
1707 },
1708
1709 .first_sysupgrade_partition = "os-image",
1710 .last_sysupgrade_partition = "file-system"
1711 },
1712
1713 /** Firmware layout for the RE355 */
1714 {
1715 .id = "RE355",
1716 .vendor = "",
1717 .support_list =
1718 "SupportList:\r\n"
1719 "{product_name:RE355,product_ver:1.0.0,special_id:00000000}\r\n"
1720 "{product_name:RE355,product_ver:1.0.0,special_id:55530000}\r\n"
1721 "{product_name:RE355,product_ver:1.0.0,special_id:45550000}\r\n"
1722 "{product_name:RE355,product_ver:1.0.0,special_id:4A500000}\r\n"
1723 "{product_name:RE355,product_ver:1.0.0,special_id:43410000}\r\n"
1724 "{product_name:RE355,product_ver:1.0.0,special_id:41550000}\r\n"
1725 "{product_name:RE355,product_ver:1.0.0,special_id:4B520000}\r\n"
1726 "{product_name:RE355,product_ver:1.0.0,special_id:55534100}\r\n",
1727 .support_trail = '\x00',
1728 .soft_ver = NULL,
1729
1730 /* We're using a dynamic kernel/rootfs split here */
1731 .partitions = {
1732 {"fs-uboot", 0x00000, 0x20000},
1733 {"firmware", 0x20000, 0x5e0000},
1734 {"partition-table", 0x600000, 0x02000},
1735 {"default-mac", 0x610000, 0x00020},
1736 {"pin", 0x610100, 0x00020},
1737 {"product-info", 0x611100, 0x01000},
1738 {"soft-version", 0x620000, 0x01000},
1739 {"support-list", 0x621000, 0x01000},
1740 {"profile", 0x622000, 0x08000},
1741 {"user-config", 0x630000, 0x10000},
1742 {"default-config", 0x640000, 0x10000},
1743 {"radio", 0x7f0000, 0x10000},
1744 {NULL, 0, 0}
1745 },
1746
1747 .first_sysupgrade_partition = "os-image",
1748 .last_sysupgrade_partition = "file-system"
1749 },
1750
1751 /** Firmware layout for the RE450 */
1752 {
1753 .id = "RE450",
1754 .vendor = "",
1755 .support_list =
1756 "SupportList:\r\n"
1757 "{product_name:RE450,product_ver:1.0.0,special_id:00000000}\r\n"
1758 "{product_name:RE450,product_ver:1.0.0,special_id:55530000}\r\n"
1759 "{product_name:RE450,product_ver:1.0.0,special_id:45550000}\r\n"
1760 "{product_name:RE450,product_ver:1.0.0,special_id:4A500000}\r\n"
1761 "{product_name:RE450,product_ver:1.0.0,special_id:43410000}\r\n"
1762 "{product_name:RE450,product_ver:1.0.0,special_id:41550000}\r\n"
1763 "{product_name:RE450,product_ver:1.0.0,special_id:4B520000}\r\n"
1764 "{product_name:RE450,product_ver:1.0.0,special_id:55534100}\r\n",
1765 .support_trail = '\x00',
1766 .soft_ver = NULL,
1767
1768 /** We're using a dynamic kernel/rootfs split here */
1769 .partitions = {
1770 {"fs-uboot", 0x00000, 0x20000},
1771 {"firmware", 0x20000, 0x5e0000},
1772 {"partition-table", 0x600000, 0x02000},
1773 {"default-mac", 0x610000, 0x00020},
1774 {"pin", 0x610100, 0x00020},
1775 {"product-info", 0x611100, 0x01000},
1776 {"soft-version", 0x620000, 0x01000},
1777 {"support-list", 0x621000, 0x01000},
1778 {"profile", 0x622000, 0x08000},
1779 {"user-config", 0x630000, 0x10000},
1780 {"default-config", 0x640000, 0x10000},
1781 {"radio", 0x7f0000, 0x10000},
1782 {NULL, 0, 0}
1783 },
1784
1785 .first_sysupgrade_partition = "os-image",
1786 .last_sysupgrade_partition = "file-system"
1787 },
1788
1789 /** Firmware layout for the RE450 v2 */
1790 {
1791 .id = "RE450-V2",
1792 .vendor = "",
1793 .support_list =
1794 "SupportList:\r\n"
1795 "{product_name:RE450,product_ver:2.0.0,special_id:00000000}\r\n"
1796 "{product_name:RE450,product_ver:2.0.0,special_id:55530000}\r\n"
1797 "{product_name:RE450,product_ver:2.0.0,special_id:45550000}\r\n"
1798 "{product_name:RE450,product_ver:2.0.0,special_id:4A500000}\r\n"
1799 "{product_name:RE450,product_ver:2.0.0,special_id:43410000}\r\n"
1800 "{product_name:RE450,product_ver:2.0.0,special_id:41550000}\r\n"
1801 "{product_name:RE450,product_ver:2.0.0,special_id:41530000}\r\n"
1802 "{product_name:RE450,product_ver:2.0.0,special_id:4B520000}\r\n"
1803 "{product_name:RE450,product_ver:2.0.0,special_id:42520000}\r\n",
1804 .support_trail = '\x00',
1805 .soft_ver = NULL,
1806
1807 /* We're using a dynamic kernel/rootfs split here */
1808 .partitions = {
1809 {"fs-uboot", 0x00000, 0x20000},
1810 {"firmware", 0x20000, 0x5e0000},
1811 {"partition-table", 0x600000, 0x02000},
1812 {"default-mac", 0x610000, 0x00020},
1813 {"pin", 0x610100, 0x00020},
1814 {"product-info", 0x611100, 0x01000},
1815 {"soft-version", 0x620000, 0x01000},
1816 {"support-list", 0x621000, 0x01000},
1817 {"profile", 0x622000, 0x08000},
1818 {"user-config", 0x630000, 0x10000},
1819 {"default-config", 0x640000, 0x10000},
1820 {"radio", 0x7f0000, 0x10000},
1821 {NULL, 0, 0}
1822 },
1823
1824 .first_sysupgrade_partition = "os-image",
1825 .last_sysupgrade_partition = "file-system"
1826 },
1827
1828 /** Firmware layout for the RE450 v3 */
1829 {
1830 .id = "RE450-V3",
1831 .vendor = "",
1832 .support_list =
1833 "SupportList:\r\n"
1834 "{product_name:RE450,product_ver:3.0.0,special_id:00000000}\r\n"
1835 "{product_name:RE450,product_ver:3.0.0,special_id:55530000}\r\n"
1836 "{product_name:RE450,product_ver:3.0.0,special_id:45550000}\r\n"
1837 "{product_name:RE450,product_ver:3.0.0,special_id:4A500000}\r\n"
1838 "{product_name:RE450,product_ver:3.0.0,special_id:43410000}\r\n"
1839 "{product_name:RE450,product_ver:3.0.0,special_id:41550000}\r\n"
1840 "{product_name:RE450,product_ver:3.0.0,special_id:41530000}\r\n"
1841 "{product_name:RE450,product_ver:3.0.0,special_id:4B520000}\r\n"
1842 "{product_name:RE450,product_ver:3.0.0,special_id:42520000}\r\n",
1843 .support_trail = '\x00',
1844 .soft_ver = NULL,
1845
1846 /* We're using a dynamic kernel/rootfs split here */
1847 .partitions = {
1848 {"fs-uboot", 0x00000, 0x20000},
1849 {"default-mac", 0x20000, 0x00020},
1850 {"pin", 0x20020, 0x00020},
1851 {"product-info", 0x21000, 0x01000},
1852 {"partition-table", 0x22000, 0x02000},
1853 {"soft-version", 0x24000, 0x01000},
1854 {"support-list", 0x25000, 0x01000},
1855 {"profile", 0x26000, 0x08000},
1856 {"user-config", 0x2e000, 0x10000},
1857 {"default-config", 0x3e000, 0x10000},
1858 {"config-info", 0x4e000, 0x00400},
1859 {"firmware", 0x50000, 0x7a0000},
1860 {"radio", 0x7f0000, 0x10000},
1861 {NULL, 0, 0}
1862 },
1863
1864 .first_sysupgrade_partition = "os-image",
1865 .last_sysupgrade_partition = "file-system"
1866 },
1867
1868 /** Firmware layout for the RE500 */
1869 {
1870 .id = "RE500-V1",
1871 .vendor = "",
1872 .support_list =
1873 "SupportList:\r\n"
1874 "{product_name:RE500,product_ver:1.0.0,special_id:00000000}\r\n"
1875 "{product_name:RE500,product_ver:1.0.0,special_id:55530000}\r\n"
1876 "{product_name:RE500,product_ver:1.0.0,special_id:45550000}\r\n"
1877 "{product_name:RE500,product_ver:1.0.0,special_id:4A500000}\r\n"
1878 "{product_name:RE500,product_ver:1.0.0,special_id:43410000}\r\n"
1879 "{product_name:RE500,product_ver:1.0.0,special_id:41550000}\r\n"
1880 "{product_name:RE500,product_ver:1.0.0,special_id:41530000}\r\n",
1881 .support_trail = '\x00',
1882 .soft_ver = NULL,
1883
1884 /* We're using a dynamic kernel/rootfs split here */
1885 .partitions = {
1886 {"fs-uboot", 0x00000, 0x20000},
1887 {"firmware", 0x20000, 0xde0000},
1888 {"partition-table", 0xe00000, 0x02000},
1889 {"default-mac", 0xe10000, 0x00020},
1890 {"pin", 0xe10100, 0x00020},
1891 {"product-info", 0xe11100, 0x01000},
1892 {"soft-version", 0xe20000, 0x01000},
1893 {"support-list", 0xe21000, 0x01000},
1894 {"profile", 0xe22000, 0x08000},
1895 {"user-config", 0xe30000, 0x10000},
1896 {"default-config", 0xe40000, 0x10000},
1897 {"radio", 0xff0000, 0x10000},
1898 {NULL, 0, 0}
1899 },
1900
1901 .first_sysupgrade_partition = "os-image",
1902 .last_sysupgrade_partition = "file-system"
1903 },
1904
1905 /** Firmware layout for the RE650 */
1906 {
1907 .id = "RE650-V1",
1908 .vendor = "",
1909 .support_list =
1910 "SupportList:\r\n"
1911 "{product_name:RE650,product_ver:1.0.0,special_id:00000000}\r\n"
1912 "{product_name:RE650,product_ver:1.0.0,special_id:55530000}\r\n"
1913 "{product_name:RE650,product_ver:1.0.0,special_id:45550000}\r\n"
1914 "{product_name:RE650,product_ver:1.0.0,special_id:4A500000}\r\n"
1915 "{product_name:RE650,product_ver:1.0.0,special_id:43410000}\r\n"
1916 "{product_name:RE650,product_ver:1.0.0,special_id:41550000}\r\n"
1917 "{product_name:RE650,product_ver:1.0.0,special_id:41530000}\r\n",
1918 .support_trail = '\x00',
1919 .soft_ver = NULL,
1920
1921 /* We're using a dynamic kernel/rootfs split here */
1922 .partitions = {
1923 {"fs-uboot", 0x00000, 0x20000},
1924 {"firmware", 0x20000, 0xde0000},
1925 {"partition-table", 0xe00000, 0x02000},
1926 {"default-mac", 0xe10000, 0x00020},
1927 {"pin", 0xe10100, 0x00020},
1928 {"product-info", 0xe11100, 0x01000},
1929 {"soft-version", 0xe20000, 0x01000},
1930 {"support-list", 0xe21000, 0x01000},
1931 {"profile", 0xe22000, 0x08000},
1932 {"user-config", 0xe30000, 0x10000},
1933 {"default-config", 0xe40000, 0x10000},
1934 {"radio", 0xff0000, 0x10000},
1935 {NULL, 0, 0}
1936 },
1937
1938 .first_sysupgrade_partition = "os-image",
1939 .last_sysupgrade_partition = "file-system"
1940 },
1941
1942 {}
1943 };
1944
1945 #define error(_ret, _errno, _str, ...) \
1946 do { \
1947 fprintf(stderr, _str ": %s\n", ## __VA_ARGS__, \
1948 strerror(_errno)); \
1949 if (_ret) \
1950 exit(_ret); \
1951 } while (0)
1952
1953
1954 /** Stores a uint32 as big endian */
1955 static inline void put32(uint8_t *buf, uint32_t val) {
1956 buf[0] = val >> 24;
1957 buf[1] = val >> 16;
1958 buf[2] = val >> 8;
1959 buf[3] = val;
1960 }
1961
1962 /** Allocates a new image partition */
1963 static struct image_partition_entry alloc_image_partition(const char *name, size_t len) {
1964 struct image_partition_entry entry = {name, len, malloc(len)};
1965 if (!entry.data)
1966 error(1, errno, "malloc");
1967
1968 return entry;
1969 }
1970
1971 /** Frees an image partition */
1972 static void free_image_partition(struct image_partition_entry entry) {
1973 free(entry.data);
1974 }
1975
1976 static time_t source_date_epoch = -1;
1977 static void set_source_date_epoch() {
1978 char *env = getenv("SOURCE_DATE_EPOCH");
1979 char *endptr = env;
1980 errno = 0;
1981 if (env && *env) {
1982 source_date_epoch = strtoull(env, &endptr, 10);
1983 if (errno || (endptr && *endptr != '\0')) {
1984 fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
1985 exit(1);
1986 }
1987 }
1988 }
1989
1990 /** Generates the partition-table partition */
1991 static struct image_partition_entry make_partition_table(const struct flash_partition_entry *p) {
1992 struct image_partition_entry entry = alloc_image_partition("partition-table", 0x800);
1993
1994 char *s = (char *)entry.data, *end = (char *)(s+entry.size);
1995
1996 *(s++) = 0x00;
1997 *(s++) = 0x04;
1998 *(s++) = 0x00;
1999 *(s++) = 0x00;
2000
2001 size_t i;
2002 for (i = 0; p[i].name; i++) {
2003 size_t len = end-s;
2004 size_t w = snprintf(s, len, "partition %s base 0x%05x size 0x%05x\n", p[i].name, p[i].base, p[i].size);
2005
2006 if (w > len-1)
2007 error(1, 0, "flash partition table overflow?");
2008
2009 s += w;
2010 }
2011
2012 s++;
2013
2014 memset(s, 0xff, end-s);
2015
2016 return entry;
2017 }
2018
2019
2020 /** Generates a binary-coded decimal representation of an integer in the range [0, 99] */
2021 static inline uint8_t bcd(uint8_t v) {
2022 return 0x10 * (v/10) + v%10;
2023 }
2024
2025
2026 /** Generates the soft-version partition */
2027 static struct image_partition_entry make_soft_version(uint32_t rev) {
2028 struct image_partition_entry entry = alloc_image_partition("soft-version", sizeof(struct soft_version));
2029 struct soft_version *s = (struct soft_version *)entry.data;
2030
2031 time_t t;
2032
2033 if (source_date_epoch != -1)
2034 t = source_date_epoch;
2035 else if (time(&t) == (time_t)(-1))
2036 error(1, errno, "time");
2037
2038 struct tm *tm = localtime(&t);
2039
2040 s->magic = htonl(0x0000000c);
2041 s->zero = 0;
2042 s->pad1 = 0xff;
2043
2044 s->version_major = 0;
2045 s->version_minor = 0;
2046 s->version_patch = 0;
2047
2048 s->year_hi = bcd((1900+tm->tm_year)/100);
2049 s->year_lo = bcd(tm->tm_year%100);
2050 s->month = bcd(tm->tm_mon+1);
2051 s->day = bcd(tm->tm_mday);
2052 s->rev = htonl(rev);
2053
2054 s->pad2 = 0xff;
2055
2056 return entry;
2057 }
2058
2059 static struct image_partition_entry make_soft_version_from_string(const char *soft_ver) {
2060 /** String length _including_ the terminating zero byte */
2061 uint32_t ver_len = strlen(soft_ver) + 1;
2062 /** Partition contains 64 bit header, the version string, and one additional null byte */
2063 size_t partition_len = 2*sizeof(uint32_t) + ver_len + 1;
2064 struct image_partition_entry entry = alloc_image_partition("soft-version", partition_len);
2065
2066 uint32_t *len = (uint32_t *)entry.data;
2067 len[0] = htonl(ver_len);
2068 len[1] = 0;
2069 memcpy(&len[2], soft_ver, ver_len);
2070
2071 entry.data[partition_len - 1] = 0;
2072
2073 return entry;
2074 }
2075
2076 /** Generates the support-list partition */
2077 static struct image_partition_entry make_support_list(struct device_info *info) {
2078 size_t len = strlen(info->support_list);
2079 struct image_partition_entry entry = alloc_image_partition("support-list", len + 9);
2080
2081 put32(entry.data, len);
2082 memset(entry.data+4, 0, 4);
2083 memcpy(entry.data+8, info->support_list, len);
2084 entry.data[len+8] = info->support_trail;
2085
2086 return entry;
2087 }
2088
2089 /** Creates a new image partition with an arbitrary name from a file */
2090 static struct image_partition_entry read_file(const char *part_name, const char *filename, bool add_jffs2_eof, struct flash_partition_entry *file_system_partition) {
2091 struct stat statbuf;
2092
2093 if (stat(filename, &statbuf) < 0)
2094 error(1, errno, "unable to stat file `%s'", filename);
2095
2096 size_t len = statbuf.st_size;
2097
2098 if (add_jffs2_eof) {
2099 if (file_system_partition)
2100 len = ALIGN(len + file_system_partition->base, 0x10000) + sizeof(jffs2_eof_mark) - file_system_partition->base;
2101 else
2102 len = ALIGN(len, 0x10000) + sizeof(jffs2_eof_mark);
2103 }
2104
2105 struct image_partition_entry entry = alloc_image_partition(part_name, len);
2106
2107 FILE *file = fopen(filename, "rb");
2108 if (!file)
2109 error(1, errno, "unable to open file `%s'", filename);
2110
2111 if (fread(entry.data, statbuf.st_size, 1, file) != 1)
2112 error(1, errno, "unable to read file `%s'", filename);
2113
2114 if (add_jffs2_eof) {
2115 uint8_t *eof = entry.data + statbuf.st_size, *end = entry.data+entry.size;
2116
2117 memset(eof, 0xff, end - eof - sizeof(jffs2_eof_mark));
2118 memcpy(end - sizeof(jffs2_eof_mark), jffs2_eof_mark, sizeof(jffs2_eof_mark));
2119 }
2120
2121 fclose(file);
2122
2123 return entry;
2124 }
2125
2126 /** Creates a new image partition from arbitrary data */
2127 static struct image_partition_entry put_data(const char *part_name, const char *datain, size_t len) {
2128
2129 struct image_partition_entry entry = alloc_image_partition(part_name, len);
2130
2131 memcpy(entry.data, datain, len);
2132
2133 return entry;
2134 }
2135
2136 /**
2137 Copies a list of image partitions into an image buffer and generates the image partition table while doing so
2138
2139 Example image partition table:
2140
2141 fwup-ptn partition-table base 0x00800 size 0x00800
2142 fwup-ptn os-image base 0x01000 size 0x113b45
2143 fwup-ptn file-system base 0x114b45 size 0x1d0004
2144 fwup-ptn support-list base 0x2e4b49 size 0x000d1
2145
2146 Each line of the partition table is terminated with the bytes 09 0d 0a ("\t\r\n"),
2147 the end of the partition table is marked with a zero byte.
2148
2149 The firmware image must contain at least the partition-table and support-list partitions
2150 to be accepted. There aren't any alignment constraints for the image partitions.
2151
2152 The partition-table partition contains the actual flash layout; partitions
2153 from the image partition table are mapped to the corresponding flash partitions during
2154 the firmware upgrade. The support-list partition contains a list of devices supported by
2155 the firmware image.
2156
2157 The base offsets in the firmware partition table are relative to the end
2158 of the vendor information block, so the partition-table partition will
2159 actually start at offset 0x1814 of the image.
2160
2161 I think partition-table must be the first partition in the firmware image.
2162 */
2163 static void put_partitions(uint8_t *buffer, const struct flash_partition_entry *flash_parts, const struct image_partition_entry *parts) {
2164 size_t i, j;
2165 char *image_pt = (char *)buffer, *end = image_pt + 0x800;
2166
2167 size_t base = 0x800;
2168 for (i = 0; parts[i].name; i++) {
2169 for (j = 0; flash_parts[j].name; j++) {
2170 if (!strcmp(flash_parts[j].name, parts[i].name)) {
2171 if (parts[i].size > flash_parts[j].size)
2172 error(1, 0, "%s partition too big (more than %u bytes)", flash_parts[j].name, (unsigned)flash_parts[j].size);
2173 break;
2174 }
2175 }
2176
2177 assert(flash_parts[j].name);
2178
2179 memcpy(buffer + base, parts[i].data, parts[i].size);
2180
2181 size_t len = end-image_pt;
2182 size_t w = snprintf(image_pt, len, "fwup-ptn %s base 0x%05x size 0x%05x\t\r\n", parts[i].name, (unsigned)base, (unsigned)parts[i].size);
2183
2184 if (w > len-1)
2185 error(1, 0, "image partition table overflow?");
2186
2187 image_pt += w;
2188
2189 base += parts[i].size;
2190 }
2191 }
2192
2193 /** Generates and writes the image MD5 checksum */
2194 static void put_md5(uint8_t *md5, uint8_t *buffer, unsigned int len) {
2195 MD5_CTX ctx;
2196
2197 MD5_Init(&ctx);
2198 MD5_Update(&ctx, md5_salt, (unsigned int)sizeof(md5_salt));
2199 MD5_Update(&ctx, buffer, len);
2200 MD5_Final(md5, &ctx);
2201 }
2202
2203
2204 /**
2205 Generates the firmware image in factory format
2206
2207 Image format:
2208
2209 Bytes (hex) Usage
2210 ----------- -----
2211 0000-0003 Image size (4 bytes, big endian)
2212 0004-0013 MD5 hash (hash of a 16 byte salt and the image data starting with byte 0x14)
2213 0014-0017 Vendor information length (without padding) (4 bytes, big endian)
2214 0018-1013 Vendor information (4092 bytes, padded with 0xff; there seem to be older
2215 (VxWorks-based) TP-LINK devices which use a smaller vendor information block)
2216 1014-1813 Image partition table (2048 bytes, padded with 0xff)
2217 1814-xxxx Firmware partitions
2218 */
2219 static void * generate_factory_image(struct device_info *info, const struct image_partition_entry *parts, size_t *len) {
2220 *len = 0x1814;
2221
2222 size_t i;
2223 for (i = 0; parts[i].name; i++)
2224 *len += parts[i].size;
2225
2226 uint8_t *image = malloc(*len);
2227 if (!image)
2228 error(1, errno, "malloc");
2229
2230 memset(image, 0xff, *len);
2231 put32(image, *len);
2232
2233 if (info->vendor) {
2234 size_t vendor_len = strlen(info->vendor);
2235 put32(image+0x14, vendor_len);
2236 memcpy(image+0x18, info->vendor, vendor_len);
2237 }
2238
2239 put_partitions(image + 0x1014, info->partitions, parts);
2240 put_md5(image+0x04, image+0x14, *len-0x14);
2241
2242 return image;
2243 }
2244
2245 /**
2246 Generates the firmware image in sysupgrade format
2247
2248 This makes some assumptions about the provided flash and image partition tables and
2249 should be generalized when TP-LINK starts building its safeloader into hardware with
2250 different flash layouts.
2251 */
2252 static void * generate_sysupgrade_image(struct device_info *info, const struct image_partition_entry *image_parts, size_t *len) {
2253 size_t i, j;
2254 size_t flash_first_partition_index = 0;
2255 size_t flash_last_partition_index = 0;
2256 const struct flash_partition_entry *flash_first_partition = NULL;
2257 const struct flash_partition_entry *flash_last_partition = NULL;
2258 const struct image_partition_entry *image_last_partition = NULL;
2259
2260 /** Find first and last partitions */
2261 for (i = 0; info->partitions[i].name; i++) {
2262 if (!strcmp(info->partitions[i].name, info->first_sysupgrade_partition)) {
2263 flash_first_partition = &info->partitions[i];
2264 flash_first_partition_index = i;
2265 } else if (!strcmp(info->partitions[i].name, info->last_sysupgrade_partition)) {
2266 flash_last_partition = &info->partitions[i];
2267 flash_last_partition_index = i;
2268 }
2269 }
2270
2271 assert(flash_first_partition && flash_last_partition);
2272 assert(flash_first_partition_index < flash_last_partition_index);
2273
2274 /** Find last partition from image to calculate needed size */
2275 for (i = 0; image_parts[i].name; i++) {
2276 if (!strcmp(image_parts[i].name, info->last_sysupgrade_partition)) {
2277 image_last_partition = &image_parts[i];
2278 break;
2279 }
2280 }
2281
2282 assert(image_last_partition);
2283
2284 *len = flash_last_partition->base - flash_first_partition->base + image_last_partition->size;
2285
2286 uint8_t *image = malloc(*len);
2287 if (!image)
2288 error(1, errno, "malloc");
2289
2290 memset(image, 0xff, *len);
2291
2292 for (i = flash_first_partition_index; i <= flash_last_partition_index; i++) {
2293 for (j = 0; image_parts[j].name; j++) {
2294 if (!strcmp(info->partitions[i].name, image_parts[j].name)) {
2295 if (image_parts[j].size > info->partitions[i].size)
2296 error(1, 0, "%s partition too big (more than %u bytes)", info->partitions[i].name, (unsigned)info->partitions[i].size);
2297 memcpy(image + info->partitions[i].base - flash_first_partition->base, image_parts[j].data, image_parts[j].size);
2298 break;
2299 }
2300
2301 assert(image_parts[j].name);
2302 }
2303 }
2304
2305 return image;
2306 }
2307
2308 /** Generates an image according to a given layout and writes it to a file */
2309 static void build_image(const char *output,
2310 const char *kernel_image,
2311 const char *rootfs_image,
2312 uint32_t rev,
2313 bool add_jffs2_eof,
2314 bool sysupgrade,
2315 struct device_info *info) {
2316
2317 size_t i;
2318
2319 struct image_partition_entry parts[7] = {};
2320
2321 struct flash_partition_entry *firmware_partition = NULL;
2322 struct flash_partition_entry *os_image_partition = NULL;
2323 struct flash_partition_entry *file_system_partition = NULL;
2324 size_t firmware_partition_index = 0;
2325
2326 for (i = 0; info->partitions[i].name; i++) {
2327 if (!strcmp(info->partitions[i].name, "firmware"))
2328 {
2329 firmware_partition = &info->partitions[i];
2330 firmware_partition_index = i;
2331 }
2332 }
2333
2334 if (firmware_partition)
2335 {
2336 os_image_partition = &info->partitions[firmware_partition_index];
2337 file_system_partition = &info->partitions[firmware_partition_index + 1];
2338
2339 struct stat kernel;
2340 if (stat(kernel_image, &kernel) < 0)
2341 error(1, errno, "unable to stat file `%s'", kernel_image);
2342
2343 if (kernel.st_size > firmware_partition->size)
2344 error(1, 0, "kernel overflowed firmware partition\n");
2345
2346 for (i = MAX_PARTITIONS-1; i >= firmware_partition_index + 1; i--)
2347 info->partitions[i+1] = info->partitions[i];
2348
2349 file_system_partition->name = "file-system";
2350 file_system_partition->base = firmware_partition->base + kernel.st_size;
2351
2352 /* Align partition start to erase blocks for factory images only */
2353 if (!sysupgrade)
2354 file_system_partition->base = ALIGN(firmware_partition->base + kernel.st_size, 0x10000);
2355
2356 file_system_partition->size = firmware_partition->size - file_system_partition->base;
2357
2358 os_image_partition->name = "os-image";
2359 os_image_partition->size = kernel.st_size;
2360 }
2361
2362 parts[0] = make_partition_table(info->partitions);
2363 if (info->soft_ver)
2364 parts[1] = make_soft_version_from_string(info->soft_ver);
2365 else
2366 parts[1] = make_soft_version(rev);
2367
2368 parts[2] = make_support_list(info);
2369 parts[3] = read_file("os-image", kernel_image, false, NULL);
2370 parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof, file_system_partition);
2371
2372 /* Some devices need the extra-para partition to accept the firmware */
2373 if (strcasecmp(info->id, "ARCHER-C2-V3") == 0 ||
2374 strcasecmp(info->id, "ARCHER-C25-V1") == 0 ||
2375 strcasecmp(info->id, "ARCHER-C59-V2") == 0 ||
2376 strcasecmp(info->id, "ARCHER-C60-V2") == 0 ||
2377 strcasecmp(info->id, "ARCHER-C60-V3") == 0 ||
2378 strcasecmp(info->id, "TLWR1043NV5") == 0) {
2379 const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
2380 parts[5] = put_data("extra-para", mdat, 11);
2381 } else if (strcasecmp(info->id, "ARCHER-A7-V5") == 0 || strcasecmp(info->id, "ARCHER-C7-V4") == 0 || strcasecmp(info->id, "ARCHER-C7-V5") == 0) {
2382 const char mdat[11] = {0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x01, 0x00, 0x00};
2383 parts[5] = put_data("extra-para", mdat, 11);
2384 } else if (strcasecmp(info->id, "ARCHER-C6-V2") == 0) {
2385 const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
2386 parts[5] = put_data("extra-para", mdat, 11);
2387 } else if (strcasecmp(info->id, "ARCHER-C6-V2-US") == 0) {
2388 const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00};
2389 parts[5] = put_data("extra-para", mdat, 11);
2390 }
2391
2392 size_t len;
2393 void *image;
2394 if (sysupgrade)
2395 image = generate_sysupgrade_image(info, parts, &len);
2396 else
2397 image = generate_factory_image(info, parts, &len);
2398
2399 FILE *file = fopen(output, "wb");
2400 if (!file)
2401 error(1, errno, "unable to open output file");
2402
2403 if (fwrite(image, len, 1, file) != 1)
2404 error(1, 0, "unable to write output file");
2405
2406 fclose(file);
2407
2408 free(image);
2409
2410 for (i = 0; parts[i].name; i++)
2411 free_image_partition(parts[i]);
2412 }
2413
2414 /** Usage output */
2415 static void usage(const char *argv0) {
2416 fprintf(stderr,
2417 "Usage: %s [OPTIONS...]\n"
2418 "\n"
2419 "Options:\n"
2420 " -h show this help\n"
2421 "\n"
2422 "Create a new image:\n"
2423 " -B <board> create image for the board specified with <board>\n"
2424 " -k <file> read kernel image from the file <file>\n"
2425 " -r <file> read rootfs image from the file <file>\n"
2426 " -o <file> write output to the file <file>\n"
2427 " -V <rev> sets the revision number to <rev>\n"
2428 " -j add jffs2 end-of-filesystem markers\n"
2429 " -S create sysupgrade instead of factory image\n"
2430 "Extract an old image:\n"
2431 " -x <file> extract all oem firmware partition\n"
2432 " -d <dir> destination to extract the firmware partition\n"
2433 " -z <file> convert an oem firmware into a sysupgade file. Use -o for output file\n",
2434 argv0
2435 );
2436 };
2437
2438
2439 static struct device_info *find_board(const char *id)
2440 {
2441 struct device_info *board = NULL;
2442
2443 for (board = boards; board->id != NULL; board++)
2444 if (strcasecmp(id, board->id) == 0)
2445 return board;
2446
2447 return NULL;
2448 }
2449
2450 static int add_flash_partition(
2451 struct flash_partition_entry *part_list,
2452 size_t max_entries,
2453 const char *name,
2454 unsigned long base,
2455 unsigned long size)
2456 {
2457 size_t ptr;
2458 /* check if the list has a free entry */
2459 for (ptr = 0; ptr < max_entries; ptr++, part_list++) {
2460 if (part_list->name == NULL &&
2461 part_list->base == 0 &&
2462 part_list->size == 0)
2463 break;
2464 }
2465
2466 if (ptr == max_entries) {
2467 error(1, 0, "No free flash part entry available.");
2468 }
2469
2470 part_list->name = calloc(1, strlen(name) + 1);
2471 if (!part_list->name) {
2472 error(1, 0, "Unable to allocate memory");
2473 }
2474
2475 memcpy((char *)part_list->name, name, strlen(name));
2476 part_list->base = base;
2477 part_list->size = size;
2478
2479 return 0;
2480 }
2481
2482 /** read the partition table into struct flash_partition_entry */
2483 static int read_partition_table(
2484 FILE *file, long offset,
2485 struct flash_partition_entry *entries, size_t max_entries,
2486 int type)
2487 {
2488 char buf[2048];
2489 char *ptr, *end;
2490 const char *parthdr = NULL;
2491 const char *fwuphdr = "fwup-ptn";
2492 const char *flashhdr = "partition";
2493
2494 /* TODO: search for the partition table */
2495
2496 switch(type) {
2497 case 0:
2498 parthdr = fwuphdr;
2499 break;
2500 case 1:
2501 parthdr = flashhdr;
2502 break;
2503 default:
2504 error(1, 0, "Invalid partition table");
2505 }
2506
2507 if (fseek(file, offset, SEEK_SET) < 0)
2508 error(1, errno, "Can not seek in the firmware");
2509
2510 if (fread(buf, 2048, 1, file) != 1)
2511 error(1, errno, "Can not read fwup-ptn from the firmware");
2512
2513 buf[2047] = '\0';
2514
2515 /* look for the partition header */
2516 if (memcmp(buf, parthdr, strlen(parthdr)) != 0) {
2517 fprintf(stderr, "DEBUG: can not find fwuphdr\n");
2518 return 1;
2519 }
2520
2521 ptr = buf;
2522 end = buf + sizeof(buf);
2523 while ((ptr + strlen(parthdr)) < end &&
2524 memcmp(ptr, parthdr, strlen(parthdr)) == 0) {
2525 char *end_part;
2526 char *end_element;
2527
2528 char name[32] = { 0 };
2529 int name_len = 0;
2530 unsigned long base = 0;
2531 unsigned long size = 0;
2532
2533 end_part = memchr(ptr, '\n', (end - ptr));
2534 if (end_part == NULL) {
2535 /* in theory this should never happen, because a partition always ends with 0x09, 0x0D, 0x0A */
2536 break;
2537 }
2538
2539 for (int i = 0; i <= 4; i++) {
2540 if (end_part <= ptr)
2541 break;
2542
2543 end_element = memchr(ptr, 0x20, (end_part - ptr));
2544 if (end_element == NULL) {
2545 error(1, errno, "Ignoring the rest of the partition entries.");
2546 break;
2547 }
2548
2549 switch (i) {
2550 /* partition header */
2551 case 0:
2552 ptr = end_element + 1;
2553 continue;
2554 /* name */
2555 case 1:
2556 name_len = (end_element - ptr) > 31 ? 31 : (end_element - ptr);
2557 strncpy(name, ptr, name_len);
2558 name[name_len] = '\0';
2559 ptr = end_element + 1;
2560 continue;
2561
2562 /* string "base" */
2563 case 2:
2564 ptr = end_element + 1;
2565 continue;
2566
2567 /* actual base */
2568 case 3:
2569 base = strtoul(ptr, NULL, 16);
2570 ptr = end_element + 1;
2571 continue;
2572
2573 /* string "size" */
2574 case 4:
2575 ptr = end_element + 1;
2576 /* actual size. The last element doesn't have a sepeartor */
2577 size = strtoul(ptr, NULL, 16);
2578 /* the part ends with 0x09, 0x0d, 0x0a */
2579 ptr = end_part + 1;
2580 add_flash_partition(entries, max_entries, name, base, size);
2581 continue;
2582 }
2583 }
2584 }
2585
2586 return 0;
2587 }
2588
2589 static void write_partition(
2590 FILE *input_file,
2591 size_t firmware_offset,
2592 struct flash_partition_entry *entry,
2593 FILE *output_file)
2594 {
2595 char buf[4096];
2596 size_t offset;
2597
2598 fseek(input_file, entry->base + firmware_offset, SEEK_SET);
2599
2600 for (offset = 0; sizeof(buf) + offset <= entry->size; offset += sizeof(buf)) {
2601 if (fread(buf, sizeof(buf), 1, input_file) != 1)
2602 error(1, errno, "Can not read partition from input_file");
2603
2604 if (fwrite(buf, sizeof(buf), 1, output_file) != 1)
2605 error(1, errno, "Can not write partition to output_file");
2606 }
2607 /* write last chunk smaller than buffer */
2608 if (offset < entry->size) {
2609 offset = entry->size - offset;
2610 if (fread(buf, offset, 1, input_file) != 1)
2611 error(1, errno, "Can not read partition from input_file");
2612 if (fwrite(buf, offset, 1, output_file) != 1)
2613 error(1, errno, "Can not write partition to output_file");
2614 }
2615 }
2616
2617 static int extract_firmware_partition(FILE *input_file, size_t firmware_offset, struct flash_partition_entry *entry, const char *output_directory)
2618 {
2619 FILE *output_file;
2620 char output[PATH_MAX];
2621
2622 snprintf(output, PATH_MAX, "%s/%s", output_directory, entry->name);
2623 output_file = fopen(output, "wb+");
2624 if (output_file == NULL) {
2625 error(1, errno, "Can not open output file %s", output);
2626 }
2627
2628 write_partition(input_file, firmware_offset, entry, output_file);
2629
2630 fclose(output_file);
2631
2632 return 0;
2633 }
2634
2635 /** extract all partitions from the firmware file */
2636 static int extract_firmware(const char *input, const char *output_directory)
2637 {
2638 struct flash_partition_entry entries[16] = { 0 };
2639 size_t max_entries = 16;
2640 size_t firmware_offset = 0x1014;
2641 FILE *input_file;
2642
2643 struct stat statbuf;
2644
2645 /* check input file */
2646 if (stat(input, &statbuf)) {
2647 error(1, errno, "Can not read input firmware %s", input);
2648 }
2649
2650 /* check if output directory exists */
2651 if (stat(output_directory, &statbuf)) {
2652 error(1, errno, "Failed to stat output directory %s", output_directory);
2653 }
2654
2655 if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
2656 error(1, errno, "Given output directory is not a directory %s", output_directory);
2657 }
2658
2659 input_file = fopen(input, "rb");
2660
2661 if (read_partition_table(input_file, firmware_offset, entries, 16, 0) != 0) {
2662 error(1, 0, "Error can not read the partition table (fwup-ptn)");
2663 }
2664
2665 for (size_t i = 0; i < max_entries; i++) {
2666 if (entries[i].name == NULL &&
2667 entries[i].base == 0 &&
2668 entries[i].size == 0)
2669 continue;
2670
2671 extract_firmware_partition(input_file, firmware_offset, &entries[i], output_directory);
2672 }
2673
2674 return 0;
2675 }
2676
2677 static struct flash_partition_entry *find_partition(
2678 struct flash_partition_entry *entries, size_t max_entries,
2679 const char *name, const char *error_msg)
2680 {
2681 for (size_t i = 0; i < max_entries; i++, entries++) {
2682 if (strcmp(entries->name, name) == 0)
2683 return entries;
2684 }
2685
2686 error(1, 0, "%s", error_msg);
2687 return NULL;
2688 }
2689
2690 static void write_ff(FILE *output_file, size_t size)
2691 {
2692 char buf[4096];
2693 size_t offset;
2694
2695 memset(buf, 0xff, sizeof(buf));
2696
2697 for (offset = 0; offset + sizeof(buf) < size ; offset += sizeof(buf)) {
2698 if (fwrite(buf, sizeof(buf), 1, output_file) != 1)
2699 error(1, errno, "Can not write 0xff to output_file");
2700 }
2701
2702 /* write last chunk smaller than buffer */
2703 if (offset < size) {
2704 offset = size - offset;
2705 if (fwrite(buf, offset, 1, output_file) != 1)
2706 error(1, errno, "Can not write partition to output_file");
2707 }
2708 }
2709
2710 static void convert_firmware(const char *input, const char *output)
2711 {
2712 struct flash_partition_entry fwup[MAX_PARTITIONS] = { 0 };
2713 struct flash_partition_entry flash[MAX_PARTITIONS] = { 0 };
2714 struct flash_partition_entry *fwup_os_image = NULL, *fwup_file_system = NULL;
2715 struct flash_partition_entry *flash_os_image = NULL, *flash_file_system = NULL;
2716 struct flash_partition_entry *fwup_partition_table = NULL;
2717 size_t firmware_offset = 0x1014;
2718 FILE *input_file, *output_file;
2719
2720 struct stat statbuf;
2721
2722 /* check input file */
2723 if (stat(input, &statbuf)) {
2724 error(1, errno, "Can not read input firmware %s", input);
2725 }
2726
2727 input_file = fopen(input, "rb");
2728 if (!input_file)
2729 error(1, 0, "Can not open input firmware %s", input);
2730
2731 output_file = fopen(output, "wb");
2732 if (!output_file)
2733 error(1, 0, "Can not open output firmware %s", output);
2734
2735 if (read_partition_table(input_file, firmware_offset, fwup, MAX_PARTITIONS, 0) != 0) {
2736 error(1, 0, "Error can not read the partition table (fwup-ptn)");
2737 }
2738
2739 fwup_os_image = find_partition(fwup, MAX_PARTITIONS,
2740 "os-image", "Error can not find os-image partition (fwup)");
2741 fwup_file_system = find_partition(fwup, MAX_PARTITIONS,
2742 "file-system", "Error can not find file-system partition (fwup)");
2743 fwup_partition_table = find_partition(fwup, MAX_PARTITIONS,
2744 "partition-table", "Error can not find partition-table partition");
2745
2746 /* the flash partition table has a 0x00000004 magic haeder */
2747 if (read_partition_table(input_file, firmware_offset + fwup_partition_table->base + 4, flash, MAX_PARTITIONS, 1) != 0)
2748 error(1, 0, "Error can not read the partition table (flash)");
2749
2750 flash_os_image = find_partition(flash, MAX_PARTITIONS,
2751 "os-image", "Error can not find os-image partition (flash)");
2752 flash_file_system = find_partition(flash, MAX_PARTITIONS,
2753 "file-system", "Error can not find file-system partition (flash)");
2754
2755 /* write os_image to 0x0 */
2756 write_partition(input_file, firmware_offset, fwup_os_image, output_file);
2757 write_ff(output_file, flash_os_image->size - fwup_os_image->size);
2758
2759 /* write file-system behind os_image */
2760 fseek(output_file, flash_file_system->base - flash_os_image->base, SEEK_SET);
2761 write_partition(input_file, firmware_offset, fwup_file_system, output_file);
2762 write_ff(output_file, flash_file_system->size - fwup_file_system->size);
2763
2764 fclose(output_file);
2765 fclose(input_file);
2766 }
2767
2768 int main(int argc, char *argv[]) {
2769 const char *board = NULL, *kernel_image = NULL, *rootfs_image = NULL, *output = NULL;
2770 const char *extract_image = NULL, *output_directory = NULL, *convert_image = NULL;
2771 bool add_jffs2_eof = false, sysupgrade = false;
2772 unsigned rev = 0;
2773 struct device_info *info;
2774 set_source_date_epoch();
2775
2776 while (true) {
2777 int c;
2778
2779 c = getopt(argc, argv, "B:k:r:o:V:jSh:x:d:z:");
2780 if (c == -1)
2781 break;
2782
2783 switch (c) {
2784 case 'B':
2785 board = optarg;
2786 break;
2787
2788 case 'k':
2789 kernel_image = optarg;
2790 break;
2791
2792 case 'r':
2793 rootfs_image = optarg;
2794 break;
2795
2796 case 'o':
2797 output = optarg;
2798 break;
2799
2800 case 'V':
2801 sscanf(optarg, "r%u", &rev);
2802 break;
2803
2804 case 'j':
2805 add_jffs2_eof = true;
2806 break;
2807
2808 case 'S':
2809 sysupgrade = true;
2810 break;
2811
2812 case 'h':
2813 usage(argv[0]);
2814 return 0;
2815
2816 case 'd':
2817 output_directory = optarg;
2818 break;
2819
2820 case 'x':
2821 extract_image = optarg;
2822 break;
2823
2824 case 'z':
2825 convert_image = optarg;
2826 break;
2827
2828 default:
2829 usage(argv[0]);
2830 return 1;
2831 }
2832 }
2833
2834 if (extract_image || output_directory) {
2835 if (!extract_image)
2836 error(1, 0, "No factory/oem image given via -x <file>. Output directory is only valid with -x");
2837 if (!output_directory)
2838 error(1, 0, "Can not extract an image without output directory. Use -d <dir>");
2839 extract_firmware(extract_image, output_directory);
2840 } else if (convert_image) {
2841 if (!output)
2842 error(1, 0, "Can not convert a factory/oem image into sysupgrade image without output file. Use -o <file>");
2843 convert_firmware(convert_image, output);
2844 } else {
2845 if (!board)
2846 error(1, 0, "no board has been specified");
2847 if (!kernel_image)
2848 error(1, 0, "no kernel image has been specified");
2849 if (!rootfs_image)
2850 error(1, 0, "no rootfs image has been specified");
2851 if (!output)
2852 error(1, 0, "no output filename has been specified");
2853
2854 info = find_board(board);
2855
2856 if (info == NULL)
2857 error(1, 0, "unsupported board %s", board);
2858
2859 build_image(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade, info);
2860 }
2861
2862 return 0;
2863 }