ramips: add support for TP-Link RE200 v4
[openwrt/staging/hauke.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 uint32_t soft_ver_compat_level;
81 struct flash_partition_entry partitions[MAX_PARTITIONS+1];
82 const char *first_sysupgrade_partition;
83 const char *last_sysupgrade_partition;
84 };
85
86 /** The content of the soft-version structure */
87 struct __attribute__((__packed__)) soft_version {
88 uint32_t data_len;
89 uint32_t zero;
90 uint8_t pad1;
91 uint8_t version_major;
92 uint8_t version_minor;
93 uint8_t version_patch;
94 uint8_t year_hi;
95 uint8_t year_lo;
96 uint8_t month;
97 uint8_t day;
98 uint32_t rev;
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, 0x300000},
144 {"file-system", 0x340000, 0x470000},
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, 0x300000},
267 {"file-system", 0x340000, 0x470000},
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, 0x300000},
346 {"file-system", 0x340000, 0x470000},
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, 0x300000},
388 {"file-system", 0x340000, 0x470000},
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, 0x300000},
430 {"file-system", 0x340000, 0x470000},
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, 0x300000},
470 {"file-system", 0x340000, 0x470000},
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, 0x300000},
510 {"file-system", 0x340000, 0x470000},
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, 0x300000},
542 {"file-system", 0x340000, 0x470000},
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, 0x300000},
574 {"file-system", 0x340000, 0x470000},
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, 0x300000},
607 {"file-system", 0x340000, 0x470000},
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, 0x300000},
640 {"file-system", 0x340000, 0x470000},
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.9.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.9.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 EAP225-Wall v2 */
1302 {
1303 .id = "EAP225-WALL-V2",
1304 .support_list =
1305 "SupportList:\r\n"
1306 "EAP225-Wall(TP-Link|UN|AC1200-D):2.0\r\n",
1307 .support_trail = '\xff',
1308 .soft_ver = NULL,
1309 .soft_ver_compat_level = 1,
1310
1311 .partitions = {
1312 {"fs-uboot", 0x00000, 0x20000},
1313 {"partition-table", 0x20000, 0x02000},
1314 {"default-mac", 0x30000, 0x01000},
1315 {"support-list", 0x31000, 0x00100},
1316 {"product-info", 0x31100, 0x00400},
1317 {"soft-version", 0x32000, 0x00100},
1318 {"firmware", 0x40000, 0xd80000},
1319 {"user-config", 0xdc0000, 0x30000},
1320 {"mutil-log", 0xf30000, 0x80000},
1321 {"oops", 0xfb0000, 0x40000},
1322 {"radio", 0xff0000, 0x10000},
1323 {NULL, 0, 0}
1324 },
1325
1326 .first_sysupgrade_partition = "os-image",
1327 .last_sysupgrade_partition = "file-system"
1328 },
1329
1330 /** Firmware layout for the EAP245 v3 */
1331 {
1332 .id = "EAP245-V3",
1333 .support_list =
1334 "SupportList:\r\n"
1335 "EAP245(TP-Link|UN|AC1750-D):3.0\r\n",
1336 .support_trail = '\xff',
1337 .soft_ver = NULL,
1338 .soft_ver_compat_level = 1,
1339
1340 /** Firmware partition with dynamic kernel/rootfs split */
1341 .partitions = {
1342 {"factroy-boot", 0x00000, 0x40000},
1343 {"fs-uboot", 0x40000, 0x40000},
1344 {"partition-table", 0x80000, 0x10000},
1345 {"default-mac", 0x90000, 0x01000},
1346 {"support-list", 0x91000, 0x00100},
1347 {"product-info", 0x91100, 0x00400},
1348 {"soft-version", 0x92000, 0x00100},
1349 {"radio", 0xa0000, 0x10000},
1350 {"extra-para", 0xb0000, 0x10000},
1351 {"firmware", 0xc0000, 0xe40000},
1352 {"config", 0xf00000, 0x30000},
1353 {"mutil-log", 0xf30000, 0x80000},
1354 {"oops", 0xfb0000, 0x40000},
1355 {NULL, 0, 0}
1356 },
1357
1358 .first_sysupgrade_partition = "os-image",
1359 .last_sysupgrade_partition = "file-system"
1360 },
1361
1362 /** Firmware layout for the TL-WA850RE v2 */
1363 {
1364 .id = "TLWA850REV2",
1365 .vendor = "",
1366 .support_list =
1367 "SupportList:\n"
1368 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:55530000}\n"
1369 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:00000000}\n"
1370 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:55534100}\n"
1371 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:45550000}\n"
1372 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:4B520000}\n"
1373 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:42520000}\n"
1374 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:4A500000}\n"
1375 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:43410000}\n"
1376 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:41550000}\n"
1377 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:52550000}\n",
1378 .support_trail = '\x00',
1379 .soft_ver = NULL,
1380
1381 /**
1382 576KB were moved from file-system to os-image
1383 in comparison to the stock image
1384 */
1385 .partitions = {
1386 {"fs-uboot", 0x00000, 0x20000},
1387 {"firmware", 0x20000, 0x390000},
1388 {"partition-table", 0x3b0000, 0x02000},
1389 {"default-mac", 0x3c0000, 0x00020},
1390 {"pin", 0x3c0100, 0x00020},
1391 {"product-info", 0x3c1000, 0x01000},
1392 {"soft-version", 0x3c2000, 0x00100},
1393 {"support-list", 0x3c3000, 0x01000},
1394 {"profile", 0x3c4000, 0x08000},
1395 {"user-config", 0x3d0000, 0x10000},
1396 {"default-config", 0x3e0000, 0x10000},
1397 {"radio", 0x3f0000, 0x10000},
1398 {NULL, 0, 0}
1399 },
1400
1401 .first_sysupgrade_partition = "os-image",
1402 .last_sysupgrade_partition = "file-system"
1403 },
1404
1405 /** Firmware layout for the TL-WA855RE v1 */
1406 {
1407 .id = "TLWA855REV1",
1408 .vendor = "",
1409 .support_list =
1410 "SupportList:\n"
1411 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:00000000}\n"
1412 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:55530000}\n"
1413 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:45550000}\n"
1414 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:4B520000}\n"
1415 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:42520000}\n"
1416 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:4A500000}\n"
1417 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:43410000}\n"
1418 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:41550000}\n"
1419 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:52550000}\n",
1420 .support_trail = '\x00',
1421 .soft_ver = NULL,
1422
1423 .partitions = {
1424 {"fs-uboot", 0x00000, 0x20000},
1425 {"os-image", 0x20000, 0x150000},
1426 {"file-system", 0x170000, 0x240000},
1427 {"partition-table", 0x3b0000, 0x02000},
1428 {"default-mac", 0x3c0000, 0x00020},
1429 {"pin", 0x3c0100, 0x00020},
1430 {"product-info", 0x3c1000, 0x01000},
1431 {"soft-version", 0x3c2000, 0x00100},
1432 {"support-list", 0x3c3000, 0x01000},
1433 {"profile", 0x3c4000, 0x08000},
1434 {"user-config", 0x3d0000, 0x10000},
1435 {"default-config", 0x3e0000, 0x10000},
1436 {"radio", 0x3f0000, 0x10000},
1437 {NULL, 0, 0}
1438 },
1439
1440 .first_sysupgrade_partition = "os-image",
1441 .last_sysupgrade_partition = "file-system"
1442 },
1443
1444 /** Firmware layout for the TL-WPA8630P v2 (EU)*/
1445 {
1446 .id = "TL-WPA8630P-V2.0-EU",
1447 .vendor = "",
1448 .support_list =
1449 "SupportList:\n"
1450 "{product_name:TL-WPA8630P,product_ver:2.0.0,special_id:45550000}\n",
1451 .support_trail = '\x00',
1452 .soft_ver = NULL,
1453
1454 .partitions = {
1455 {"factory-uboot", 0x00000, 0x20000},
1456 {"fs-uboot", 0x20000, 0x20000},
1457 {"firmware", 0x40000, 0x5e0000},
1458 {"partition-table", 0x620000, 0x02000},
1459 {"default-mac", 0x630000, 0x00020},
1460 {"pin", 0x630100, 0x00020},
1461 {"device-id", 0x630200, 0x00030},
1462 {"product-info", 0x631100, 0x01000},
1463 {"extra-para", 0x632100, 0x01000},
1464 {"soft-version", 0x640000, 0x01000},
1465 {"support-list", 0x641000, 0x01000},
1466 {"profile", 0x642000, 0x08000},
1467 {"user-config", 0x650000, 0x10000},
1468 {"default-config", 0x660000, 0x10000},
1469 {"default-nvm", 0x670000, 0xc0000},
1470 {"default-pib", 0x730000, 0x40000},
1471 {"radio", 0x7f0000, 0x10000},
1472 {NULL, 0, 0}
1473 },
1474
1475 .first_sysupgrade_partition = "os-image",
1476 .last_sysupgrade_partition = "file-system"
1477 },
1478
1479 /** Firmware layout for the TL-WPA8630P v2 (INT)*/
1480 {
1481 .id = "TL-WPA8630P-V2-INT",
1482 .vendor = "",
1483 .support_list =
1484 "SupportList:\n"
1485 "{product_name:TL-WPA8630P,product_ver:2.0.0,special_id:41550000}\n"
1486 "{product_name:TL-WPA8630P,product_ver:2.0.0,special_id:44450000}\n"
1487 "{product_name:TL-WPA8630P,product_ver:2.1.0,special_id:41550000}\n",
1488 .support_trail = '\x00',
1489 .soft_ver = NULL,
1490
1491 .partitions = {
1492 {"factory-uboot", 0x00000, 0x20000},
1493 {"fs-uboot", 0x20000, 0x20000},
1494 {"firmware", 0x40000, 0x5e0000},
1495 {"partition-table", 0x620000, 0x02000},
1496 {"extra-para", 0x632100, 0x01000},
1497 {"soft-version", 0x640000, 0x01000},
1498 {"support-list", 0x641000, 0x01000},
1499 {"profile", 0x642000, 0x08000},
1500 {"user-config", 0x650000, 0x10000},
1501 {"default-config", 0x660000, 0x10000},
1502 {"default-nvm", 0x670000, 0xc0000},
1503 {"default-pib", 0x730000, 0x40000},
1504 {"default-mac", 0x7e0000, 0x00020},
1505 {"pin", 0x7e0100, 0x00020},
1506 {"device-id", 0x7e0200, 0x00030},
1507 {"product-info", 0x7e1100, 0x01000},
1508 {"radio", 0x7f0000, 0x10000},
1509 {NULL, 0, 0}
1510 },
1511
1512 .first_sysupgrade_partition = "os-image",
1513 .last_sysupgrade_partition = "file-system"
1514 },
1515
1516 /** Firmware layout for the TL-WPA8630P v2.1 (EU)*/
1517 {
1518 .id = "TL-WPA8630P-V2.1-EU",
1519 .vendor = "",
1520 .support_list =
1521 "SupportList:\n"
1522 "{product_name:TL-WPA8630P,product_ver:2.1.0,special_id:45550000}\n",
1523 .support_trail = '\x00',
1524 .soft_ver = NULL,
1525
1526 .partitions = {
1527 {"factory-uboot", 0x00000, 0x20000},
1528 {"fs-uboot", 0x20000, 0x20000},
1529 {"firmware", 0x40000, 0x5e0000},
1530 {"extra-para", 0x680000, 0x01000},
1531 {"product-info", 0x690000, 0x01000},
1532 {"partition-table", 0x6a0000, 0x02000},
1533 {"soft-version", 0x6b0000, 0x01000},
1534 {"support-list", 0x6b1000, 0x01000},
1535 {"profile", 0x6b2000, 0x08000},
1536 {"user-config", 0x6c0000, 0x10000},
1537 {"default-config", 0x6d0000, 0x10000},
1538 {"default-nvm", 0x6e0000, 0xc0000},
1539 {"default-pib", 0x7a0000, 0x40000},
1540 {"default-mac", 0x7e0000, 0x00020},
1541 {"pin", 0x7e0100, 0x00020},
1542 {"device-id", 0x7e0200, 0x00030},
1543 {"radio", 0x7f0000, 0x10000},
1544 {NULL, 0, 0}
1545 },
1546
1547 .first_sysupgrade_partition = "os-image",
1548 .last_sysupgrade_partition = "file-system"
1549 },
1550
1551 /** Firmware layout for the TL-WR1043 v5 */
1552 {
1553 .id = "TLWR1043NV5",
1554 .vendor = "",
1555 .support_list =
1556 "SupportList:\n"
1557 "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:45550000}\n"
1558 "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:55530000}\n",
1559 .support_trail = '\x00',
1560 .soft_ver = "soft_ver:1.0.0\n",
1561 .partitions = {
1562 {"factory-boot", 0x00000, 0x20000},
1563 {"fs-uboot", 0x20000, 0x20000},
1564 {"firmware", 0x40000, 0xec0000},
1565 {"default-mac", 0xf00000, 0x00200},
1566 {"pin", 0xf00200, 0x00200},
1567 {"device-id", 0xf00400, 0x00100},
1568 {"product-info", 0xf00500, 0x0fb00},
1569 {"soft-version", 0xf10000, 0x01000},
1570 {"extra-para", 0xf11000, 0x01000},
1571 {"support-list", 0xf12000, 0x0a000},
1572 {"profile", 0xf1c000, 0x04000},
1573 {"default-config", 0xf20000, 0x10000},
1574 {"user-config", 0xf30000, 0x40000},
1575 {"qos-db", 0xf70000, 0x40000},
1576 {"certificate", 0xfb0000, 0x10000},
1577 {"partition-table", 0xfc0000, 0x10000},
1578 {"log", 0xfd0000, 0x20000},
1579 {"radio", 0xff0000, 0x10000},
1580 {NULL, 0, 0}
1581 },
1582 .first_sysupgrade_partition = "os-image",
1583 .last_sysupgrade_partition = "file-system"
1584 },
1585
1586 /** Firmware layout for the TL-WR1043 v4 */
1587 {
1588 .id = "TLWR1043NDV4",
1589 .vendor = "",
1590 .support_list =
1591 "SupportList:\n"
1592 "{product_name:TL-WR1043ND,product_ver:4.0.0,special_id:45550000}\n",
1593 .support_trail = '\x00',
1594 .soft_ver = NULL,
1595
1596 /* We're using a dynamic kernel/rootfs split here */
1597 .partitions = {
1598 {"fs-uboot", 0x00000, 0x20000},
1599 {"firmware", 0x20000, 0xf30000},
1600 {"default-mac", 0xf50000, 0x00200},
1601 {"pin", 0xf50200, 0x00200},
1602 {"product-info", 0xf50400, 0x0fc00},
1603 {"soft-version", 0xf60000, 0x0b000},
1604 {"support-list", 0xf6b000, 0x04000},
1605 {"profile", 0xf70000, 0x04000},
1606 {"default-config", 0xf74000, 0x0b000},
1607 {"user-config", 0xf80000, 0x40000},
1608 {"partition-table", 0xfc0000, 0x10000},
1609 {"log", 0xfd0000, 0x20000},
1610 {"radio", 0xff0000, 0x10000},
1611 {NULL, 0, 0}
1612 },
1613
1614 .first_sysupgrade_partition = "os-image",
1615 .last_sysupgrade_partition = "file-system"
1616 },
1617
1618 /** Firmware layout for the TL-WR902AC v1 */
1619 {
1620 .id = "TL-WR902AC-V1",
1621 .vendor = "",
1622 .support_list =
1623 "SupportList:\n"
1624 "{product_name:TL-WR902AC,product_ver:1.0.0,special_id:45550000}\n"
1625 "{product_name:TL-WR902AC,product_ver:1.0.0,special_id:55530000}\n",
1626 .support_trail = '\x00',
1627 .soft_ver = NULL,
1628
1629 /**
1630 384KB were moved from file-system to os-image
1631 in comparison to the stock image
1632 */
1633 .partitions = {
1634 {"fs-uboot", 0x00000, 0x20000},
1635 {"firmware", 0x20000, 0x730000},
1636 {"default-mac", 0x750000, 0x00200},
1637 {"pin", 0x750200, 0x00200},
1638 {"product-info", 0x750400, 0x0fc00},
1639 {"soft-version", 0x760000, 0x0b000},
1640 {"support-list", 0x76b000, 0x04000},
1641 {"profile", 0x770000, 0x04000},
1642 {"default-config", 0x774000, 0x0b000},
1643 {"user-config", 0x780000, 0x40000},
1644 {"partition-table", 0x7c0000, 0x10000},
1645 {"log", 0x7d0000, 0x20000},
1646 {"radio", 0x7f0000, 0x10000},
1647 {NULL, 0, 0}
1648 },
1649
1650 .first_sysupgrade_partition = "os-image",
1651 .last_sysupgrade_partition = "file-system",
1652 },
1653
1654 /** Firmware layout for the TL-WR942N V1 */
1655 {
1656 .id = "TLWR942NV1",
1657 .vendor = "",
1658 .support_list =
1659 "SupportList:\r\n"
1660 "{product_name:TL-WR942N,product_ver:1.0.0,special_id:00000000}\r\n"
1661 "{product_name:TL-WR942N,product_ver:1.0.0,special_id:52550000}\r\n",
1662 .support_trail = '\x00',
1663 .soft_ver = NULL,
1664
1665 .partitions = {
1666 {"fs-uboot", 0x00000, 0x20000},
1667 {"firmware", 0x20000, 0xe20000},
1668 {"default-mac", 0xe40000, 0x00200},
1669 {"pin", 0xe40200, 0x00200},
1670 {"product-info", 0xe40400, 0x0fc00},
1671 {"partition-table", 0xe50000, 0x10000},
1672 {"soft-version", 0xe60000, 0x10000},
1673 {"support-list", 0xe70000, 0x10000},
1674 {"profile", 0xe80000, 0x10000},
1675 {"default-config", 0xe90000, 0x10000},
1676 {"user-config", 0xea0000, 0x40000},
1677 {"qos-db", 0xee0000, 0x40000},
1678 {"certificate", 0xf20000, 0x10000},
1679 {"usb-config", 0xfb0000, 0x10000},
1680 {"log", 0xfc0000, 0x20000},
1681 {"radio-bk", 0xfe0000, 0x10000},
1682 {"radio", 0xff0000, 0x10000},
1683 {NULL, 0, 0}
1684 },
1685
1686 .first_sysupgrade_partition = "os-image",
1687 .last_sysupgrade_partition = "file-system",
1688 },
1689
1690 /** Firmware layout for the RE200 v2 */
1691 {
1692 .id = "RE200-V2",
1693 .vendor = "",
1694 .support_list =
1695 "SupportList:\n"
1696 "{product_name:RE200,product_ver:2.0.0,special_id:00000000}\n"
1697 "{product_name:RE200,product_ver:2.0.0,special_id:41520000}\n"
1698 "{product_name:RE200,product_ver:2.0.0,special_id:41550000}\n"
1699 "{product_name:RE200,product_ver:2.0.0,special_id:42520000}\n"
1700 "{product_name:RE200,product_ver:2.0.0,special_id:43410000}\n"
1701 "{product_name:RE200,product_ver:2.0.0,special_id:45530000}\n"
1702 "{product_name:RE200,product_ver:2.0.0,special_id:45550000}\n"
1703 "{product_name:RE200,product_ver:2.0.0,special_id:49440000}\n"
1704 "{product_name:RE200,product_ver:2.0.0,special_id:4a500000}\n"
1705 "{product_name:RE200,product_ver:2.0.0,special_id:4b520000}\n"
1706 "{product_name:RE200,product_ver:2.0.0,special_id:52550000}\n"
1707 "{product_name:RE200,product_ver:2.0.0,special_id:54570000}\n"
1708 "{product_name:RE200,product_ver:2.0.0,special_id:55530000}\n",
1709 .support_trail = '\x00',
1710 .soft_ver = NULL,
1711
1712 .partitions = {
1713 {"fs-uboot", 0x00000, 0x20000},
1714 {"firmware", 0x20000, 0x7a0000},
1715 {"partition-table", 0x7c0000, 0x02000},
1716 {"default-mac", 0x7c2000, 0x00020},
1717 {"pin", 0x7c2100, 0x00020},
1718 {"product-info", 0x7c3100, 0x01000},
1719 {"soft-version", 0x7c4200, 0x01000},
1720 {"support-list", 0x7c5200, 0x01000},
1721 {"profile", 0x7c6200, 0x08000},
1722 {"config-info", 0x7ce200, 0x00400},
1723 {"user-config", 0x7d0000, 0x10000},
1724 {"default-config", 0x7e0000, 0x10000},
1725 {"radio", 0x7f0000, 0x10000},
1726 {NULL, 0, 0}
1727 },
1728
1729 .first_sysupgrade_partition = "os-image",
1730 .last_sysupgrade_partition = "file-system"
1731 },
1732
1733 /** Firmware layout for the RE200 v3 */
1734 {
1735 .id = "RE200-V3",
1736 .vendor = "",
1737 .support_list =
1738 "SupportList:\n"
1739 "{product_name:RE200,product_ver:3.0.0,special_id:00000000}\n"
1740 "{product_name:RE200,product_ver:3.0.0,special_id:41520000}\n"
1741 "{product_name:RE200,product_ver:3.0.0,special_id:41550000}\n"
1742 "{product_name:RE200,product_ver:3.0.0,special_id:42520000}\n"
1743 "{product_name:RE200,product_ver:3.0.0,special_id:43410000}\n"
1744 "{product_name:RE200,product_ver:3.0.0,special_id:45470000}\n"
1745 "{product_name:RE200,product_ver:3.0.0,special_id:45530000}\n"
1746 "{product_name:RE200,product_ver:3.0.0,special_id:45550000}\n"
1747 "{product_name:RE200,product_ver:3.0.0,special_id:49440000}\n"
1748 "{product_name:RE200,product_ver:3.0.0,special_id:4A500000}\n"
1749 "{product_name:RE200,product_ver:3.0.0,special_id:4B520000}\n"
1750 "{product_name:RE200,product_ver:3.0.0,special_id:52550000}\n"
1751 "{product_name:RE200,product_ver:3.0.0,special_id:54570000}\n"
1752 "{product_name:RE200,product_ver:3.0.0,special_id:55530000}\n",
1753 .support_trail = '\x00',
1754 .soft_ver = NULL,
1755
1756 .partitions = {
1757 {"fs-uboot", 0x00000, 0x20000},
1758 {"firmware", 0x20000, 0x7a0000},
1759 {"partition-table", 0x7c0000, 0x02000},
1760 {"default-mac", 0x7c2000, 0x00020},
1761 {"pin", 0x7c2100, 0x00020},
1762 {"product-info", 0x7c3100, 0x01000},
1763 {"soft-version", 0x7c4200, 0x01000},
1764 {"support-list", 0x7c5200, 0x01000},
1765 {"profile", 0x7c6200, 0x08000},
1766 {"config-info", 0x7ce200, 0x00400},
1767 {"user-config", 0x7d0000, 0x10000},
1768 {"default-config", 0x7e0000, 0x10000},
1769 {"radio", 0x7f0000, 0x10000},
1770 {NULL, 0, 0}
1771 },
1772
1773 .first_sysupgrade_partition = "os-image",
1774 .last_sysupgrade_partition = "file-system"
1775 },
1776
1777 /** Firmware layout for the RE200 v4 */
1778 {
1779 .id = "RE200-V4",
1780 .vendor = "",
1781 .support_list =
1782 "SupportList:\n"
1783 "{product_name:RE200,product_ver:4.0.0,special_id:00000000}\n"
1784 "{product_name:RE200,product_ver:4.0.0,special_id:45550000}\n"
1785 "{product_name:RE200,product_ver:4.0.0,special_id:4A500000}\n"
1786 "{product_name:RE200,product_ver:4.0.0,special_id:4B520000}\n"
1787 "{product_name:RE200,product_ver:4.0.0,special_id:43410000}\n"
1788 "{product_name:RE200,product_ver:4.0.0,special_id:41550000}\n"
1789 "{product_name:RE200,product_ver:4.0.0,special_id:42520000}\n"
1790 "{product_name:RE200,product_ver:4.0.0,special_id:55530000}\n"
1791 "{product_name:RE200,product_ver:4.0.0,special_id:41520000}\n"
1792 "{product_name:RE200,product_ver:4.0.0,special_id:52550000}\n"
1793 "{product_name:RE200,product_ver:4.0.0,special_id:54570000}\n"
1794 "{product_name:RE200,product_ver:4.0.0,special_id:45530000}\n"
1795 "{product_name:RE200,product_ver:4.0.0,special_id:49440000}\n"
1796 "{product_name:RE200,product_ver:4.0.0,special_id:45470000}\n",
1797 .support_trail = '\x00',
1798 .soft_ver = "soft_ver:1.1.0\n",
1799
1800 .partitions = {
1801 {"fs-uboot", 0x00000, 0x20000},
1802 {"firmware", 0x20000, 0x7a0000},
1803 {"partition-table", 0x7c0000, 0x02000},
1804 {"default-mac", 0x7c2000, 0x00020},
1805 {"pin", 0x7c2100, 0x00020},
1806 {"product-info", 0x7c3100, 0x01000},
1807 {"soft-version", 0x7c4200, 0x01000},
1808 {"support-list", 0x7c5200, 0x01000},
1809 {"profile", 0x7c6200, 0x08000},
1810 {"config-info", 0x7ce200, 0x00400},
1811 {"user-config", 0x7d0000, 0x10000},
1812 {"default-config", 0x7e0000, 0x10000},
1813 {"radio", 0x7f0000, 0x10000},
1814 {NULL, 0, 0}
1815 },
1816
1817 .first_sysupgrade_partition = "os-image",
1818 .last_sysupgrade_partition = "file-system"
1819 },
1820
1821 /** Firmware layout for the RE220 v2 */
1822 {
1823 .id = "RE220-V2",
1824 .vendor = "",
1825 .support_list =
1826 "SupportList:\n"
1827 "{product_name:RE220,product_ver:2.0.0,special_id:00000000}\n"
1828 "{product_name:RE220,product_ver:2.0.0,special_id:41520000}\n"
1829 "{product_name:RE220,product_ver:2.0.0,special_id:41550000}\n"
1830 "{product_name:RE220,product_ver:2.0.0,special_id:42520000}\n"
1831 "{product_name:RE220,product_ver:2.0.0,special_id:43410000}\n"
1832 "{product_name:RE220,product_ver:2.0.0,special_id:45530000}\n"
1833 "{product_name:RE220,product_ver:2.0.0,special_id:45550000}\n"
1834 "{product_name:RE220,product_ver:2.0.0,special_id:49440000}\n"
1835 "{product_name:RE220,product_ver:2.0.0,special_id:4a500000}\n"
1836 "{product_name:RE220,product_ver:2.0.0,special_id:4b520000}\n"
1837 "{product_name:RE220,product_ver:2.0.0,special_id:52550000}\n"
1838 "{product_name:RE220,product_ver:2.0.0,special_id:54570000}\n"
1839 "{product_name:RE220,product_ver:2.0.0,special_id:55530000}\n",
1840 .support_trail = '\x00',
1841 .soft_ver = NULL,
1842
1843 .partitions = {
1844 {"fs-uboot", 0x00000, 0x20000},
1845 {"firmware", 0x20000, 0x7a0000},
1846 {"partition-table", 0x7c0000, 0x02000},
1847 {"default-mac", 0x7c2000, 0x00020},
1848 {"pin", 0x7c2100, 0x00020},
1849 {"product-info", 0x7c3100, 0x01000},
1850 {"soft-version", 0x7c4200, 0x01000},
1851 {"support-list", 0x7c5200, 0x01000},
1852 {"profile", 0x7c6200, 0x08000},
1853 {"config-info", 0x7ce200, 0x00400},
1854 {"user-config", 0x7d0000, 0x10000},
1855 {"default-config", 0x7e0000, 0x10000},
1856 {"radio", 0x7f0000, 0x10000},
1857 {NULL, 0, 0}
1858 },
1859
1860 .first_sysupgrade_partition = "os-image",
1861 .last_sysupgrade_partition = "file-system"
1862 },
1863
1864 /** Firmware layout for the RE305 v1 */
1865 {
1866 .id = "RE305-V1",
1867 .vendor = "",
1868 .support_list =
1869 "SupportList:\n"
1870 "{product_name:RE305,product_ver:1.0.0,special_id:45550000}\n"
1871 "{product_name:RE305,product_ver:1.0.0,special_id:55530000}\n"
1872 "{product_name:RE305,product_ver:1.0.0,special_id:4a500000}\n"
1873 "{product_name:RE305,product_ver:1.0.0,special_id:42520000}\n"
1874 "{product_name:RE305,product_ver:1.0.0,special_id:4b520000}\n"
1875 "{product_name:RE305,product_ver:1.0.0,special_id:41550000}\n"
1876 "{product_name:RE305,product_ver:1.0.0,special_id:43410000}\n",
1877 .support_trail = '\x00',
1878 .soft_ver = NULL,
1879
1880 .partitions = {
1881 {"fs-uboot", 0x00000, 0x20000},
1882 {"firmware", 0x20000, 0x5e0000},
1883 {"partition-table", 0x600000, 0x02000},
1884 {"default-mac", 0x610000, 0x00020},
1885 {"pin", 0x610100, 0x00020},
1886 {"product-info", 0x611100, 0x01000},
1887 {"soft-version", 0x620000, 0x01000},
1888 {"support-list", 0x621000, 0x01000},
1889 {"profile", 0x622000, 0x08000},
1890 {"user-config", 0x630000, 0x10000},
1891 {"default-config", 0x640000, 0x10000},
1892 {"radio", 0x7f0000, 0x10000},
1893 {NULL, 0, 0}
1894 },
1895
1896 .first_sysupgrade_partition = "os-image",
1897 .last_sysupgrade_partition = "file-system"
1898 },
1899
1900 /** Firmware layout for the RE350 v1 */
1901 {
1902 .id = "RE350-V1",
1903 .vendor = "",
1904 .support_list =
1905 "SupportList:\n"
1906 "{product_name:RE350,product_ver:1.0.0,special_id:45550000}\n"
1907 "{product_name:RE350,product_ver:1.0.0,special_id:00000000}\n"
1908 "{product_name:RE350,product_ver:1.0.0,special_id:41550000}\n"
1909 "{product_name:RE350,product_ver:1.0.0,special_id:55530000}\n"
1910 "{product_name:RE350,product_ver:1.0.0,special_id:43410000}\n"
1911 "{product_name:RE350,product_ver:1.0.0,special_id:4b520000}\n"
1912 "{product_name:RE350,product_ver:1.0.0,special_id:4a500000}\n",
1913 .support_trail = '\x00',
1914 .soft_ver = NULL,
1915
1916 /** We're using a dynamic kernel/rootfs split here */
1917 .partitions = {
1918 {"fs-uboot", 0x00000, 0x20000},
1919 {"firmware", 0x20000, 0x5e0000},
1920 {"partition-table", 0x600000, 0x02000},
1921 {"default-mac", 0x610000, 0x00020},
1922 {"pin", 0x610100, 0x00020},
1923 {"product-info", 0x611100, 0x01000},
1924 {"soft-version", 0x620000, 0x01000},
1925 {"support-list", 0x621000, 0x01000},
1926 {"profile", 0x622000, 0x08000},
1927 {"user-config", 0x630000, 0x10000},
1928 {"default-config", 0x640000, 0x10000},
1929 {"radio", 0x7f0000, 0x10000},
1930 {NULL, 0, 0}
1931 },
1932
1933 .first_sysupgrade_partition = "os-image",
1934 .last_sysupgrade_partition = "file-system"
1935 },
1936
1937 /** Firmware layout for the RE350K v1 */
1938 {
1939 .id = "RE350K-V1",
1940 .vendor = "",
1941 .support_list =
1942 "SupportList:\n"
1943 "{product_name:RE350K,product_ver:1.0.0,special_id:00000000,product_region:US}\n",
1944 .support_trail = '\x00',
1945 .soft_ver = NULL,
1946
1947 /** We're using a dynamic kernel/rootfs split here */
1948 .partitions = {
1949 {"fs-uboot", 0x00000, 0x20000},
1950 {"firmware", 0x20000, 0xd70000},
1951 {"partition-table", 0xd90000, 0x02000},
1952 {"default-mac", 0xda0000, 0x00020},
1953 {"pin", 0xda0100, 0x00020},
1954 {"product-info", 0xda1100, 0x01000},
1955 {"soft-version", 0xdb0000, 0x01000},
1956 {"support-list", 0xdb1000, 0x01000},
1957 {"profile", 0xdb2000, 0x08000},
1958 {"user-config", 0xdc0000, 0x10000},
1959 {"default-config", 0xdd0000, 0x10000},
1960 {"device-id", 0xde0000, 0x00108},
1961 {"radio", 0xff0000, 0x10000},
1962 {NULL, 0, 0}
1963 },
1964
1965 .first_sysupgrade_partition = "os-image",
1966 .last_sysupgrade_partition = "file-system"
1967 },
1968
1969 /** Firmware layout for the RE355 */
1970 {
1971 .id = "RE355",
1972 .vendor = "",
1973 .support_list =
1974 "SupportList:\r\n"
1975 "{product_name:RE355,product_ver:1.0.0,special_id:00000000}\r\n"
1976 "{product_name:RE355,product_ver:1.0.0,special_id:55530000}\r\n"
1977 "{product_name:RE355,product_ver:1.0.0,special_id:45550000}\r\n"
1978 "{product_name:RE355,product_ver:1.0.0,special_id:4A500000}\r\n"
1979 "{product_name:RE355,product_ver:1.0.0,special_id:43410000}\r\n"
1980 "{product_name:RE355,product_ver:1.0.0,special_id:41550000}\r\n"
1981 "{product_name:RE355,product_ver:1.0.0,special_id:4B520000}\r\n"
1982 "{product_name:RE355,product_ver:1.0.0,special_id:55534100}\r\n",
1983 .support_trail = '\x00',
1984 .soft_ver = NULL,
1985
1986 /* We're using a dynamic kernel/rootfs split here */
1987 .partitions = {
1988 {"fs-uboot", 0x00000, 0x20000},
1989 {"firmware", 0x20000, 0x5e0000},
1990 {"partition-table", 0x600000, 0x02000},
1991 {"default-mac", 0x610000, 0x00020},
1992 {"pin", 0x610100, 0x00020},
1993 {"product-info", 0x611100, 0x01000},
1994 {"soft-version", 0x620000, 0x01000},
1995 {"support-list", 0x621000, 0x01000},
1996 {"profile", 0x622000, 0x08000},
1997 {"user-config", 0x630000, 0x10000},
1998 {"default-config", 0x640000, 0x10000},
1999 {"radio", 0x7f0000, 0x10000},
2000 {NULL, 0, 0}
2001 },
2002
2003 .first_sysupgrade_partition = "os-image",
2004 .last_sysupgrade_partition = "file-system"
2005 },
2006
2007 /** Firmware layout for the RE450 */
2008 {
2009 .id = "RE450",
2010 .vendor = "",
2011 .support_list =
2012 "SupportList:\r\n"
2013 "{product_name:RE450,product_ver:1.0.0,special_id:00000000}\r\n"
2014 "{product_name:RE450,product_ver:1.0.0,special_id:55530000}\r\n"
2015 "{product_name:RE450,product_ver:1.0.0,special_id:45550000}\r\n"
2016 "{product_name:RE450,product_ver:1.0.0,special_id:4A500000}\r\n"
2017 "{product_name:RE450,product_ver:1.0.0,special_id:43410000}\r\n"
2018 "{product_name:RE450,product_ver:1.0.0,special_id:41550000}\r\n"
2019 "{product_name:RE450,product_ver:1.0.0,special_id:4B520000}\r\n"
2020 "{product_name:RE450,product_ver:1.0.0,special_id:55534100}\r\n",
2021 .support_trail = '\x00',
2022 .soft_ver = NULL,
2023
2024 /** We're using a dynamic kernel/rootfs split here */
2025 .partitions = {
2026 {"fs-uboot", 0x00000, 0x20000},
2027 {"firmware", 0x20000, 0x5e0000},
2028 {"partition-table", 0x600000, 0x02000},
2029 {"default-mac", 0x610000, 0x00020},
2030 {"pin", 0x610100, 0x00020},
2031 {"product-info", 0x611100, 0x01000},
2032 {"soft-version", 0x620000, 0x01000},
2033 {"support-list", 0x621000, 0x01000},
2034 {"profile", 0x622000, 0x08000},
2035 {"user-config", 0x630000, 0x10000},
2036 {"default-config", 0x640000, 0x10000},
2037 {"radio", 0x7f0000, 0x10000},
2038 {NULL, 0, 0}
2039 },
2040
2041 .first_sysupgrade_partition = "os-image",
2042 .last_sysupgrade_partition = "file-system"
2043 },
2044
2045 /** Firmware layout for the RE450 v2 */
2046 {
2047 .id = "RE450-V2",
2048 .vendor = "",
2049 .support_list =
2050 "SupportList:\r\n"
2051 "{product_name:RE450,product_ver:2.0.0,special_id:00000000}\r\n"
2052 "{product_name:RE450,product_ver:2.0.0,special_id:55530000}\r\n"
2053 "{product_name:RE450,product_ver:2.0.0,special_id:45550000}\r\n"
2054 "{product_name:RE450,product_ver:2.0.0,special_id:4A500000}\r\n"
2055 "{product_name:RE450,product_ver:2.0.0,special_id:43410000}\r\n"
2056 "{product_name:RE450,product_ver:2.0.0,special_id:41550000}\r\n"
2057 "{product_name:RE450,product_ver:2.0.0,special_id:41530000}\r\n"
2058 "{product_name:RE450,product_ver:2.0.0,special_id:4B520000}\r\n"
2059 "{product_name:RE450,product_ver:2.0.0,special_id:42520000}\r\n",
2060 .support_trail = '\x00',
2061 .soft_ver = NULL,
2062
2063 /* We're using a dynamic kernel/rootfs split here */
2064 .partitions = {
2065 {"fs-uboot", 0x00000, 0x20000},
2066 {"firmware", 0x20000, 0x5e0000},
2067 {"partition-table", 0x600000, 0x02000},
2068 {"default-mac", 0x610000, 0x00020},
2069 {"pin", 0x610100, 0x00020},
2070 {"product-info", 0x611100, 0x01000},
2071 {"soft-version", 0x620000, 0x01000},
2072 {"support-list", 0x621000, 0x01000},
2073 {"profile", 0x622000, 0x08000},
2074 {"user-config", 0x630000, 0x10000},
2075 {"default-config", 0x640000, 0x10000},
2076 {"radio", 0x7f0000, 0x10000},
2077 {NULL, 0, 0}
2078 },
2079
2080 .first_sysupgrade_partition = "os-image",
2081 .last_sysupgrade_partition = "file-system"
2082 },
2083
2084 /** Firmware layout for the RE450 v3 */
2085 {
2086 .id = "RE450-V3",
2087 .vendor = "",
2088 .support_list =
2089 "SupportList:\r\n"
2090 "{product_name:RE450,product_ver:3.0.0,special_id:00000000}\r\n"
2091 "{product_name:RE450,product_ver:3.0.0,special_id:55530000}\r\n"
2092 "{product_name:RE450,product_ver:3.0.0,special_id:45550000}\r\n"
2093 "{product_name:RE450,product_ver:3.0.0,special_id:4A500000}\r\n"
2094 "{product_name:RE450,product_ver:3.0.0,special_id:43410000}\r\n"
2095 "{product_name:RE450,product_ver:3.0.0,special_id:41550000}\r\n"
2096 "{product_name:RE450,product_ver:3.0.0,special_id:41530000}\r\n"
2097 "{product_name:RE450,product_ver:3.0.0,special_id:4B520000}\r\n"
2098 "{product_name:RE450,product_ver:3.0.0,special_id:42520000}\r\n",
2099 .support_trail = '\x00',
2100 .soft_ver = NULL,
2101
2102 /* We're using a dynamic kernel/rootfs split here */
2103 .partitions = {
2104 {"fs-uboot", 0x00000, 0x20000},
2105 {"default-mac", 0x20000, 0x00020},
2106 {"pin", 0x20020, 0x00020},
2107 {"product-info", 0x21000, 0x01000},
2108 {"partition-table", 0x22000, 0x02000},
2109 {"soft-version", 0x24000, 0x01000},
2110 {"support-list", 0x25000, 0x01000},
2111 {"profile", 0x26000, 0x08000},
2112 {"user-config", 0x2e000, 0x10000},
2113 {"default-config", 0x3e000, 0x10000},
2114 {"config-info", 0x4e000, 0x00400},
2115 {"firmware", 0x50000, 0x7a0000},
2116 {"radio", 0x7f0000, 0x10000},
2117 {NULL, 0, 0}
2118 },
2119
2120 .first_sysupgrade_partition = "os-image",
2121 .last_sysupgrade_partition = "file-system"
2122 },
2123
2124 /** Firmware layout for the RE500 */
2125 {
2126 .id = "RE500-V1",
2127 .vendor = "",
2128 .support_list =
2129 "SupportList:\r\n"
2130 "{product_name:RE500,product_ver:1.0.0,special_id:00000000}\r\n"
2131 "{product_name:RE500,product_ver:1.0.0,special_id:55530000}\r\n"
2132 "{product_name:RE500,product_ver:1.0.0,special_id:45550000}\r\n"
2133 "{product_name:RE500,product_ver:1.0.0,special_id:4A500000}\r\n"
2134 "{product_name:RE500,product_ver:1.0.0,special_id:43410000}\r\n"
2135 "{product_name:RE500,product_ver:1.0.0,special_id:41550000}\r\n"
2136 "{product_name:RE500,product_ver:1.0.0,special_id:41530000}\r\n",
2137 .support_trail = '\x00',
2138 .soft_ver = NULL,
2139
2140 /* We're using a dynamic kernel/rootfs split here */
2141 .partitions = {
2142 {"fs-uboot", 0x00000, 0x20000},
2143 {"firmware", 0x20000, 0xde0000},
2144 {"partition-table", 0xe00000, 0x02000},
2145 {"default-mac", 0xe10000, 0x00020},
2146 {"pin", 0xe10100, 0x00020},
2147 {"product-info", 0xe11100, 0x01000},
2148 {"soft-version", 0xe20000, 0x01000},
2149 {"support-list", 0xe21000, 0x01000},
2150 {"profile", 0xe22000, 0x08000},
2151 {"user-config", 0xe30000, 0x10000},
2152 {"default-config", 0xe40000, 0x10000},
2153 {"radio", 0xff0000, 0x10000},
2154 {NULL, 0, 0}
2155 },
2156
2157 .first_sysupgrade_partition = "os-image",
2158 .last_sysupgrade_partition = "file-system"
2159 },
2160
2161 /** Firmware layout for the RE650 */
2162 {
2163 .id = "RE650-V1",
2164 .vendor = "",
2165 .support_list =
2166 "SupportList:\r\n"
2167 "{product_name:RE650,product_ver:1.0.0,special_id:00000000}\r\n"
2168 "{product_name:RE650,product_ver:1.0.0,special_id:55530000}\r\n"
2169 "{product_name:RE650,product_ver:1.0.0,special_id:45550000}\r\n"
2170 "{product_name:RE650,product_ver:1.0.0,special_id:4A500000}\r\n"
2171 "{product_name:RE650,product_ver:1.0.0,special_id:43410000}\r\n"
2172 "{product_name:RE650,product_ver:1.0.0,special_id:41550000}\r\n"
2173 "{product_name:RE650,product_ver:1.0.0,special_id:41530000}\r\n",
2174 .support_trail = '\x00',
2175 .soft_ver = NULL,
2176
2177 /* We're using a dynamic kernel/rootfs split here */
2178 .partitions = {
2179 {"fs-uboot", 0x00000, 0x20000},
2180 {"firmware", 0x20000, 0xde0000},
2181 {"partition-table", 0xe00000, 0x02000},
2182 {"default-mac", 0xe10000, 0x00020},
2183 {"pin", 0xe10100, 0x00020},
2184 {"product-info", 0xe11100, 0x01000},
2185 {"soft-version", 0xe20000, 0x01000},
2186 {"support-list", 0xe21000, 0x01000},
2187 {"profile", 0xe22000, 0x08000},
2188 {"user-config", 0xe30000, 0x10000},
2189 {"default-config", 0xe40000, 0x10000},
2190 {"radio", 0xff0000, 0x10000},
2191 {NULL, 0, 0}
2192 },
2193
2194 .first_sysupgrade_partition = "os-image",
2195 .last_sysupgrade_partition = "file-system"
2196 },
2197
2198 {}
2199 };
2200
2201 #define error(_ret, _errno, _str, ...) \
2202 do { \
2203 fprintf(stderr, _str ": %s\n", ## __VA_ARGS__, \
2204 strerror(_errno)); \
2205 if (_ret) \
2206 exit(_ret); \
2207 } while (0)
2208
2209
2210 /** Stores a uint32 as big endian */
2211 static inline void put32(uint8_t *buf, uint32_t val) {
2212 buf[0] = val >> 24;
2213 buf[1] = val >> 16;
2214 buf[2] = val >> 8;
2215 buf[3] = val;
2216 }
2217
2218 /** Allocates a new image partition */
2219 static struct image_partition_entry alloc_image_partition(const char *name, size_t len) {
2220 struct image_partition_entry entry = {name, len, malloc(len)};
2221 if (!entry.data)
2222 error(1, errno, "malloc");
2223
2224 return entry;
2225 }
2226
2227 /** Frees an image partition */
2228 static void free_image_partition(struct image_partition_entry entry) {
2229 free(entry.data);
2230 }
2231
2232 static time_t source_date_epoch = -1;
2233 static void set_source_date_epoch() {
2234 char *env = getenv("SOURCE_DATE_EPOCH");
2235 char *endptr = env;
2236 errno = 0;
2237 if (env && *env) {
2238 source_date_epoch = strtoull(env, &endptr, 10);
2239 if (errno || (endptr && *endptr != '\0')) {
2240 fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
2241 exit(1);
2242 }
2243 }
2244 }
2245
2246 /** Generates the partition-table partition */
2247 static struct image_partition_entry make_partition_table(const struct flash_partition_entry *p) {
2248 struct image_partition_entry entry = alloc_image_partition("partition-table", 0x800);
2249
2250 char *s = (char *)entry.data, *end = (char *)(s+entry.size);
2251
2252 *(s++) = 0x00;
2253 *(s++) = 0x04;
2254 *(s++) = 0x00;
2255 *(s++) = 0x00;
2256
2257 size_t i;
2258 for (i = 0; p[i].name; i++) {
2259 size_t len = end-s;
2260 size_t w = snprintf(s, len, "partition %s base 0x%05x size 0x%05x\n", p[i].name, p[i].base, p[i].size);
2261
2262 if (w > len-1)
2263 error(1, 0, "flash partition table overflow?");
2264
2265 s += w;
2266 }
2267
2268 s++;
2269
2270 memset(s, 0xff, end-s);
2271
2272 return entry;
2273 }
2274
2275
2276 /** Generates a binary-coded decimal representation of an integer in the range [0, 99] */
2277 static inline uint8_t bcd(uint8_t v) {
2278 return 0x10 * (v/10) + v%10;
2279 }
2280
2281
2282 /** Generates the soft-version partition */
2283 static struct image_partition_entry make_soft_version(struct device_info *info, uint32_t rev) {
2284 size_t part_len = sizeof(struct soft_version);
2285 if (info->soft_ver_compat_level > 0)
2286 part_len += sizeof(uint32_t);
2287
2288 struct image_partition_entry entry =
2289 alloc_image_partition("soft-version", part_len+1);
2290 struct soft_version *s = (struct soft_version *)entry.data;
2291
2292 time_t t;
2293
2294 if (source_date_epoch != -1)
2295 t = source_date_epoch;
2296 else if (time(&t) == (time_t)(-1))
2297 error(1, errno, "time");
2298
2299 struct tm *tm = gmtime(&t);
2300
2301 /* Partition contents size, minus 8 byte header and trailing byte */
2302 s->data_len = htonl(entry.size-9);
2303 s->zero = 0;
2304 s->pad1 = 0xff;
2305
2306 s->version_major = 0;
2307 s->version_minor = 0;
2308 s->version_patch = 0;
2309
2310 s->year_hi = bcd((1900+tm->tm_year)/100);
2311 s->year_lo = bcd(tm->tm_year%100);
2312 s->month = bcd(tm->tm_mon+1);
2313 s->day = bcd(tm->tm_mday);
2314 s->rev = htonl(rev);
2315
2316 if (info->soft_ver_compat_level > 0)
2317 *(uint32_t *)(entry.data + sizeof(struct soft_version)) =
2318 htonl(info->soft_ver_compat_level);
2319
2320 entry.data[entry.size-1] = 0xff;
2321
2322 return entry;
2323 }
2324
2325 static struct image_partition_entry make_soft_version_from_string(const char *soft_ver) {
2326 /** String length _including_ the terminating zero byte */
2327 uint32_t ver_len = strlen(soft_ver) + 1;
2328 /** Partition contains 64 bit header, the version string, and one additional null byte */
2329 size_t partition_len = 2*sizeof(uint32_t) + ver_len + 1;
2330 struct image_partition_entry entry = alloc_image_partition("soft-version", partition_len);
2331
2332 uint32_t *len = (uint32_t *)entry.data;
2333 len[0] = htonl(ver_len);
2334 len[1] = 0;
2335 memcpy(&len[2], soft_ver, ver_len);
2336
2337 entry.data[partition_len - 1] = 0;
2338
2339 return entry;
2340 }
2341
2342 /** Generates the support-list partition */
2343 static struct image_partition_entry make_support_list(struct device_info *info) {
2344 size_t len = strlen(info->support_list);
2345 struct image_partition_entry entry = alloc_image_partition("support-list", len + 9);
2346
2347 put32(entry.data, len);
2348 memset(entry.data+4, 0, 4);
2349 memcpy(entry.data+8, info->support_list, len);
2350 entry.data[len+8] = info->support_trail;
2351
2352 return entry;
2353 }
2354
2355 /** Creates a new image partition with an arbitrary name from a file */
2356 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) {
2357 struct stat statbuf;
2358
2359 if (stat(filename, &statbuf) < 0)
2360 error(1, errno, "unable to stat file `%s'", filename);
2361
2362 size_t len = statbuf.st_size;
2363
2364 if (add_jffs2_eof) {
2365 if (file_system_partition)
2366 len = ALIGN(len + file_system_partition->base, 0x10000) + sizeof(jffs2_eof_mark) - file_system_partition->base;
2367 else
2368 len = ALIGN(len, 0x10000) + sizeof(jffs2_eof_mark);
2369 }
2370
2371 struct image_partition_entry entry = alloc_image_partition(part_name, len);
2372
2373 FILE *file = fopen(filename, "rb");
2374 if (!file)
2375 error(1, errno, "unable to open file `%s'", filename);
2376
2377 if (fread(entry.data, statbuf.st_size, 1, file) != 1)
2378 error(1, errno, "unable to read file `%s'", filename);
2379
2380 if (add_jffs2_eof) {
2381 uint8_t *eof = entry.data + statbuf.st_size, *end = entry.data+entry.size;
2382
2383 memset(eof, 0xff, end - eof - sizeof(jffs2_eof_mark));
2384 memcpy(end - sizeof(jffs2_eof_mark), jffs2_eof_mark, sizeof(jffs2_eof_mark));
2385 }
2386
2387 fclose(file);
2388
2389 return entry;
2390 }
2391
2392 /** Creates a new image partition from arbitrary data */
2393 static struct image_partition_entry put_data(const char *part_name, const char *datain, size_t len) {
2394
2395 struct image_partition_entry entry = alloc_image_partition(part_name, len);
2396
2397 memcpy(entry.data, datain, len);
2398
2399 return entry;
2400 }
2401
2402 /**
2403 Copies a list of image partitions into an image buffer and generates the image partition table while doing so
2404
2405 Example image partition table:
2406
2407 fwup-ptn partition-table base 0x00800 size 0x00800
2408 fwup-ptn os-image base 0x01000 size 0x113b45
2409 fwup-ptn file-system base 0x114b45 size 0x1d0004
2410 fwup-ptn support-list base 0x2e4b49 size 0x000d1
2411
2412 Each line of the partition table is terminated with the bytes 09 0d 0a ("\t\r\n"),
2413 the end of the partition table is marked with a zero byte.
2414
2415 The firmware image must contain at least the partition-table and support-list partitions
2416 to be accepted. There aren't any alignment constraints for the image partitions.
2417
2418 The partition-table partition contains the actual flash layout; partitions
2419 from the image partition table are mapped to the corresponding flash partitions during
2420 the firmware upgrade. The support-list partition contains a list of devices supported by
2421 the firmware image.
2422
2423 The base offsets in the firmware partition table are relative to the end
2424 of the vendor information block, so the partition-table partition will
2425 actually start at offset 0x1814 of the image.
2426
2427 I think partition-table must be the first partition in the firmware image.
2428 */
2429 static void put_partitions(uint8_t *buffer, const struct flash_partition_entry *flash_parts, const struct image_partition_entry *parts) {
2430 size_t i, j;
2431 char *image_pt = (char *)buffer, *end = image_pt + 0x800;
2432
2433 size_t base = 0x800;
2434 for (i = 0; parts[i].name; i++) {
2435 for (j = 0; flash_parts[j].name; j++) {
2436 if (!strcmp(flash_parts[j].name, parts[i].name)) {
2437 if (parts[i].size > flash_parts[j].size)
2438 error(1, 0, "%s partition too big (more than %u bytes)", flash_parts[j].name, (unsigned)flash_parts[j].size);
2439 break;
2440 }
2441 }
2442
2443 assert(flash_parts[j].name);
2444
2445 memcpy(buffer + base, parts[i].data, parts[i].size);
2446
2447 size_t len = end-image_pt;
2448 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);
2449
2450 if (w > len-1)
2451 error(1, 0, "image partition table overflow?");
2452
2453 image_pt += w;
2454
2455 base += parts[i].size;
2456 }
2457 }
2458
2459 /** Generates and writes the image MD5 checksum */
2460 static void put_md5(uint8_t *md5, uint8_t *buffer, unsigned int len) {
2461 MD5_CTX ctx;
2462
2463 MD5_Init(&ctx);
2464 MD5_Update(&ctx, md5_salt, (unsigned int)sizeof(md5_salt));
2465 MD5_Update(&ctx, buffer, len);
2466 MD5_Final(md5, &ctx);
2467 }
2468
2469
2470 /**
2471 Generates the firmware image in factory format
2472
2473 Image format:
2474
2475 Bytes (hex) Usage
2476 ----------- -----
2477 0000-0003 Image size (4 bytes, big endian)
2478 0004-0013 MD5 hash (hash of a 16 byte salt and the image data starting with byte 0x14)
2479 0014-0017 Vendor information length (without padding) (4 bytes, big endian)
2480 0018-1013 Vendor information (4092 bytes, padded with 0xff; there seem to be older
2481 (VxWorks-based) TP-LINK devices which use a smaller vendor information block)
2482 1014-1813 Image partition table (2048 bytes, padded with 0xff)
2483 1814-xxxx Firmware partitions
2484 */
2485 static void * generate_factory_image(struct device_info *info, const struct image_partition_entry *parts, size_t *len) {
2486 *len = 0x1814;
2487
2488 size_t i;
2489 for (i = 0; parts[i].name; i++)
2490 *len += parts[i].size;
2491
2492 uint8_t *image = malloc(*len);
2493 if (!image)
2494 error(1, errno, "malloc");
2495
2496 memset(image, 0xff, *len);
2497 put32(image, *len);
2498
2499 if (info->vendor) {
2500 size_t vendor_len = strlen(info->vendor);
2501 put32(image+0x14, vendor_len);
2502 memcpy(image+0x18, info->vendor, vendor_len);
2503 }
2504
2505 put_partitions(image + 0x1014, info->partitions, parts);
2506 put_md5(image+0x04, image+0x14, *len-0x14);
2507
2508 return image;
2509 }
2510
2511 /**
2512 Generates the firmware image in sysupgrade format
2513
2514 This makes some assumptions about the provided flash and image partition tables and
2515 should be generalized when TP-LINK starts building its safeloader into hardware with
2516 different flash layouts.
2517 */
2518 static void * generate_sysupgrade_image(struct device_info *info, const struct image_partition_entry *image_parts, size_t *len) {
2519 size_t i, j;
2520 size_t flash_first_partition_index = 0;
2521 size_t flash_last_partition_index = 0;
2522 const struct flash_partition_entry *flash_first_partition = NULL;
2523 const struct flash_partition_entry *flash_last_partition = NULL;
2524 const struct image_partition_entry *image_last_partition = NULL;
2525
2526 /** Find first and last partitions */
2527 for (i = 0; info->partitions[i].name; i++) {
2528 if (!strcmp(info->partitions[i].name, info->first_sysupgrade_partition)) {
2529 flash_first_partition = &info->partitions[i];
2530 flash_first_partition_index = i;
2531 } else if (!strcmp(info->partitions[i].name, info->last_sysupgrade_partition)) {
2532 flash_last_partition = &info->partitions[i];
2533 flash_last_partition_index = i;
2534 }
2535 }
2536
2537 assert(flash_first_partition && flash_last_partition);
2538 assert(flash_first_partition_index < flash_last_partition_index);
2539
2540 /** Find last partition from image to calculate needed size */
2541 for (i = 0; image_parts[i].name; i++) {
2542 if (!strcmp(image_parts[i].name, info->last_sysupgrade_partition)) {
2543 image_last_partition = &image_parts[i];
2544 break;
2545 }
2546 }
2547
2548 assert(image_last_partition);
2549
2550 *len = flash_last_partition->base - flash_first_partition->base + image_last_partition->size;
2551
2552 uint8_t *image = malloc(*len);
2553 if (!image)
2554 error(1, errno, "malloc");
2555
2556 memset(image, 0xff, *len);
2557
2558 for (i = flash_first_partition_index; i <= flash_last_partition_index; i++) {
2559 for (j = 0; image_parts[j].name; j++) {
2560 if (!strcmp(info->partitions[i].name, image_parts[j].name)) {
2561 if (image_parts[j].size > info->partitions[i].size)
2562 error(1, 0, "%s partition too big (more than %u bytes)", info->partitions[i].name, (unsigned)info->partitions[i].size);
2563 memcpy(image + info->partitions[i].base - flash_first_partition->base, image_parts[j].data, image_parts[j].size);
2564 break;
2565 }
2566
2567 assert(image_parts[j].name);
2568 }
2569 }
2570
2571 return image;
2572 }
2573
2574 /** Generates an image according to a given layout and writes it to a file */
2575 static void build_image(const char *output,
2576 const char *kernel_image,
2577 const char *rootfs_image,
2578 uint32_t rev,
2579 bool add_jffs2_eof,
2580 bool sysupgrade,
2581 struct device_info *info) {
2582
2583 size_t i;
2584
2585 struct image_partition_entry parts[7] = {};
2586
2587 struct flash_partition_entry *firmware_partition = NULL;
2588 struct flash_partition_entry *os_image_partition = NULL;
2589 struct flash_partition_entry *file_system_partition = NULL;
2590 size_t firmware_partition_index = 0;
2591
2592 for (i = 0; info->partitions[i].name; i++) {
2593 if (!strcmp(info->partitions[i].name, "firmware"))
2594 {
2595 firmware_partition = &info->partitions[i];
2596 firmware_partition_index = i;
2597 }
2598 }
2599
2600 if (firmware_partition)
2601 {
2602 os_image_partition = &info->partitions[firmware_partition_index];
2603 file_system_partition = &info->partitions[firmware_partition_index + 1];
2604
2605 struct stat kernel;
2606 if (stat(kernel_image, &kernel) < 0)
2607 error(1, errno, "unable to stat file `%s'", kernel_image);
2608
2609 if (kernel.st_size > firmware_partition->size)
2610 error(1, 0, "kernel overflowed firmware partition\n");
2611
2612 for (i = MAX_PARTITIONS-1; i >= firmware_partition_index + 1; i--)
2613 info->partitions[i+1] = info->partitions[i];
2614
2615 file_system_partition->name = "file-system";
2616 file_system_partition->base = firmware_partition->base + kernel.st_size;
2617
2618 /* Align partition start to erase blocks for factory images only */
2619 if (!sysupgrade)
2620 file_system_partition->base = ALIGN(firmware_partition->base + kernel.st_size, 0x10000);
2621
2622 file_system_partition->size = firmware_partition->size - file_system_partition->base;
2623
2624 os_image_partition->name = "os-image";
2625 os_image_partition->size = kernel.st_size;
2626 }
2627
2628 parts[0] = make_partition_table(info->partitions);
2629 if (info->soft_ver)
2630 parts[1] = make_soft_version_from_string(info->soft_ver);
2631 else
2632 parts[1] = make_soft_version(info, rev);
2633
2634 parts[2] = make_support_list(info);
2635 parts[3] = read_file("os-image", kernel_image, false, NULL);
2636 parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof, file_system_partition);
2637
2638 /* Some devices need the extra-para partition to accept the firmware */
2639 if (strcasecmp(info->id, "ARCHER-C2-V3") == 0 ||
2640 strcasecmp(info->id, "ARCHER-C25-V1") == 0 ||
2641 strcasecmp(info->id, "ARCHER-C59-V2") == 0 ||
2642 strcasecmp(info->id, "ARCHER-C60-V2") == 0 ||
2643 strcasecmp(info->id, "ARCHER-C60-V3") == 0 ||
2644 strcasecmp(info->id, "TLWR1043NV5") == 0) {
2645 const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
2646 parts[5] = put_data("extra-para", mdat, 11);
2647 } else if (strcasecmp(info->id, "ARCHER-A7-V5") == 0 || strcasecmp(info->id, "ARCHER-C7-V4") == 0 || strcasecmp(info->id, "ARCHER-C7-V5") == 0) {
2648 const char mdat[11] = {0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x01, 0x00, 0x00};
2649 parts[5] = put_data("extra-para", mdat, 11);
2650 } else if (strcasecmp(info->id, "ARCHER-C6-V2") == 0) {
2651 const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
2652 parts[5] = put_data("extra-para", mdat, 11);
2653 } else if (strcasecmp(info->id, "ARCHER-C6-V2-US") == 0) {
2654 const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00};
2655 parts[5] = put_data("extra-para", mdat, 11);
2656 } else if (strcasecmp(info->id, "EAP245-V3") == 0) {
2657 const char mdat[10] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
2658 parts[5] = put_data("extra-para", mdat, 10);
2659 }
2660
2661 size_t len;
2662 void *image;
2663 if (sysupgrade)
2664 image = generate_sysupgrade_image(info, parts, &len);
2665 else
2666 image = generate_factory_image(info, parts, &len);
2667
2668 FILE *file = fopen(output, "wb");
2669 if (!file)
2670 error(1, errno, "unable to open output file");
2671
2672 if (fwrite(image, len, 1, file) != 1)
2673 error(1, 0, "unable to write output file");
2674
2675 fclose(file);
2676
2677 free(image);
2678
2679 for (i = 0; parts[i].name; i++)
2680 free_image_partition(parts[i]);
2681 }
2682
2683 /** Usage output */
2684 static void usage(const char *argv0) {
2685 fprintf(stderr,
2686 "Usage: %s [OPTIONS...]\n"
2687 "\n"
2688 "Options:\n"
2689 " -h show this help\n"
2690 "\n"
2691 "Create a new image:\n"
2692 " -B <board> create image for the board specified with <board>\n"
2693 " -k <file> read kernel image from the file <file>\n"
2694 " -r <file> read rootfs image from the file <file>\n"
2695 " -o <file> write output to the file <file>\n"
2696 " -V <rev> sets the revision number to <rev>\n"
2697 " -j add jffs2 end-of-filesystem markers\n"
2698 " -S create sysupgrade instead of factory image\n"
2699 "Extract an old image:\n"
2700 " -x <file> extract all oem firmware partition\n"
2701 " -d <dir> destination to extract the firmware partition\n"
2702 " -z <file> convert an oem firmware into a sysupgade file. Use -o for output file\n",
2703 argv0
2704 );
2705 };
2706
2707
2708 static struct device_info *find_board(const char *id)
2709 {
2710 struct device_info *board = NULL;
2711
2712 for (board = boards; board->id != NULL; board++)
2713 if (strcasecmp(id, board->id) == 0)
2714 return board;
2715
2716 return NULL;
2717 }
2718
2719 static int add_flash_partition(
2720 struct flash_partition_entry *part_list,
2721 size_t max_entries,
2722 const char *name,
2723 unsigned long base,
2724 unsigned long size)
2725 {
2726 size_t ptr;
2727 /* check if the list has a free entry */
2728 for (ptr = 0; ptr < max_entries; ptr++, part_list++) {
2729 if (part_list->name == NULL &&
2730 part_list->base == 0 &&
2731 part_list->size == 0)
2732 break;
2733 }
2734
2735 if (ptr == max_entries) {
2736 error(1, 0, "No free flash part entry available.");
2737 }
2738
2739 part_list->name = calloc(1, strlen(name) + 1);
2740 if (!part_list->name) {
2741 error(1, 0, "Unable to allocate memory");
2742 }
2743
2744 memcpy((char *)part_list->name, name, strlen(name));
2745 part_list->base = base;
2746 part_list->size = size;
2747
2748 return 0;
2749 }
2750
2751 /** read the partition table into struct flash_partition_entry */
2752 static int read_partition_table(
2753 FILE *file, long offset,
2754 struct flash_partition_entry *entries, size_t max_entries,
2755 int type)
2756 {
2757 char buf[2048];
2758 char *ptr, *end;
2759 const char *parthdr = NULL;
2760 const char *fwuphdr = "fwup-ptn";
2761 const char *flashhdr = "partition";
2762
2763 /* TODO: search for the partition table */
2764
2765 switch(type) {
2766 case 0:
2767 parthdr = fwuphdr;
2768 break;
2769 case 1:
2770 parthdr = flashhdr;
2771 break;
2772 default:
2773 error(1, 0, "Invalid partition table");
2774 }
2775
2776 if (fseek(file, offset, SEEK_SET) < 0)
2777 error(1, errno, "Can not seek in the firmware");
2778
2779 if (fread(buf, 2048, 1, file) != 1)
2780 error(1, errno, "Can not read fwup-ptn from the firmware");
2781
2782 buf[2047] = '\0';
2783
2784 /* look for the partition header */
2785 if (memcmp(buf, parthdr, strlen(parthdr)) != 0) {
2786 fprintf(stderr, "DEBUG: can not find fwuphdr\n");
2787 return 1;
2788 }
2789
2790 ptr = buf;
2791 end = buf + sizeof(buf);
2792 while ((ptr + strlen(parthdr)) < end &&
2793 memcmp(ptr, parthdr, strlen(parthdr)) == 0) {
2794 char *end_part;
2795 char *end_element;
2796
2797 char name[32] = { 0 };
2798 int name_len = 0;
2799 unsigned long base = 0;
2800 unsigned long size = 0;
2801
2802 end_part = memchr(ptr, '\n', (end - ptr));
2803 if (end_part == NULL) {
2804 /* in theory this should never happen, because a partition always ends with 0x09, 0x0D, 0x0A */
2805 break;
2806 }
2807
2808 for (int i = 0; i <= 4; i++) {
2809 if (end_part <= ptr)
2810 break;
2811
2812 end_element = memchr(ptr, 0x20, (end_part - ptr));
2813 if (end_element == NULL) {
2814 error(1, errno, "Ignoring the rest of the partition entries.");
2815 break;
2816 }
2817
2818 switch (i) {
2819 /* partition header */
2820 case 0:
2821 ptr = end_element + 1;
2822 continue;
2823 /* name */
2824 case 1:
2825 name_len = (end_element - ptr) > 31 ? 31 : (end_element - ptr);
2826 strncpy(name, ptr, name_len);
2827 name[name_len] = '\0';
2828 ptr = end_element + 1;
2829 continue;
2830
2831 /* string "base" */
2832 case 2:
2833 ptr = end_element + 1;
2834 continue;
2835
2836 /* actual base */
2837 case 3:
2838 base = strtoul(ptr, NULL, 16);
2839 ptr = end_element + 1;
2840 continue;
2841
2842 /* string "size" */
2843 case 4:
2844 ptr = end_element + 1;
2845 /* actual size. The last element doesn't have a sepeartor */
2846 size = strtoul(ptr, NULL, 16);
2847 /* the part ends with 0x09, 0x0d, 0x0a */
2848 ptr = end_part + 1;
2849 add_flash_partition(entries, max_entries, name, base, size);
2850 continue;
2851 }
2852 }
2853 }
2854
2855 return 0;
2856 }
2857
2858 static void write_partition(
2859 FILE *input_file,
2860 size_t firmware_offset,
2861 struct flash_partition_entry *entry,
2862 FILE *output_file)
2863 {
2864 char buf[4096];
2865 size_t offset;
2866
2867 fseek(input_file, entry->base + firmware_offset, SEEK_SET);
2868
2869 for (offset = 0; sizeof(buf) + offset <= entry->size; offset += sizeof(buf)) {
2870 if (fread(buf, sizeof(buf), 1, input_file) != 1)
2871 error(1, errno, "Can not read partition from input_file");
2872
2873 if (fwrite(buf, sizeof(buf), 1, output_file) != 1)
2874 error(1, errno, "Can not write partition to output_file");
2875 }
2876 /* write last chunk smaller than buffer */
2877 if (offset < entry->size) {
2878 offset = entry->size - offset;
2879 if (fread(buf, offset, 1, input_file) != 1)
2880 error(1, errno, "Can not read partition from input_file");
2881 if (fwrite(buf, offset, 1, output_file) != 1)
2882 error(1, errno, "Can not write partition to output_file");
2883 }
2884 }
2885
2886 static int extract_firmware_partition(FILE *input_file, size_t firmware_offset, struct flash_partition_entry *entry, const char *output_directory)
2887 {
2888 FILE *output_file;
2889 char output[PATH_MAX];
2890
2891 snprintf(output, PATH_MAX, "%s/%s", output_directory, entry->name);
2892 output_file = fopen(output, "wb+");
2893 if (output_file == NULL) {
2894 error(1, errno, "Can not open output file %s", output);
2895 }
2896
2897 write_partition(input_file, firmware_offset, entry, output_file);
2898
2899 fclose(output_file);
2900
2901 return 0;
2902 }
2903
2904 /** extract all partitions from the firmware file */
2905 static int extract_firmware(const char *input, const char *output_directory)
2906 {
2907 struct flash_partition_entry entries[16] = { 0 };
2908 size_t max_entries = 16;
2909 size_t firmware_offset = 0x1014;
2910 FILE *input_file;
2911
2912 struct stat statbuf;
2913
2914 /* check input file */
2915 if (stat(input, &statbuf)) {
2916 error(1, errno, "Can not read input firmware %s", input);
2917 }
2918
2919 /* check if output directory exists */
2920 if (stat(output_directory, &statbuf)) {
2921 error(1, errno, "Failed to stat output directory %s", output_directory);
2922 }
2923
2924 if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
2925 error(1, errno, "Given output directory is not a directory %s", output_directory);
2926 }
2927
2928 input_file = fopen(input, "rb");
2929
2930 if (read_partition_table(input_file, firmware_offset, entries, 16, 0) != 0) {
2931 error(1, 0, "Error can not read the partition table (fwup-ptn)");
2932 }
2933
2934 for (size_t i = 0; i < max_entries; i++) {
2935 if (entries[i].name == NULL &&
2936 entries[i].base == 0 &&
2937 entries[i].size == 0)
2938 continue;
2939
2940 extract_firmware_partition(input_file, firmware_offset, &entries[i], output_directory);
2941 }
2942
2943 return 0;
2944 }
2945
2946 static struct flash_partition_entry *find_partition(
2947 struct flash_partition_entry *entries, size_t max_entries,
2948 const char *name, const char *error_msg)
2949 {
2950 for (size_t i = 0; i < max_entries; i++, entries++) {
2951 if (strcmp(entries->name, name) == 0)
2952 return entries;
2953 }
2954
2955 error(1, 0, "%s", error_msg);
2956 return NULL;
2957 }
2958
2959 static void write_ff(FILE *output_file, size_t size)
2960 {
2961 char buf[4096];
2962 size_t offset;
2963
2964 memset(buf, 0xff, sizeof(buf));
2965
2966 for (offset = 0; offset + sizeof(buf) < size ; offset += sizeof(buf)) {
2967 if (fwrite(buf, sizeof(buf), 1, output_file) != 1)
2968 error(1, errno, "Can not write 0xff to output_file");
2969 }
2970
2971 /* write last chunk smaller than buffer */
2972 if (offset < size) {
2973 offset = size - offset;
2974 if (fwrite(buf, offset, 1, output_file) != 1)
2975 error(1, errno, "Can not write partition to output_file");
2976 }
2977 }
2978
2979 static void convert_firmware(const char *input, const char *output)
2980 {
2981 struct flash_partition_entry fwup[MAX_PARTITIONS] = { 0 };
2982 struct flash_partition_entry flash[MAX_PARTITIONS] = { 0 };
2983 struct flash_partition_entry *fwup_os_image = NULL, *fwup_file_system = NULL;
2984 struct flash_partition_entry *flash_os_image = NULL, *flash_file_system = NULL;
2985 struct flash_partition_entry *fwup_partition_table = NULL;
2986 size_t firmware_offset = 0x1014;
2987 FILE *input_file, *output_file;
2988
2989 struct stat statbuf;
2990
2991 /* check input file */
2992 if (stat(input, &statbuf)) {
2993 error(1, errno, "Can not read input firmware %s", input);
2994 }
2995
2996 input_file = fopen(input, "rb");
2997 if (!input_file)
2998 error(1, 0, "Can not open input firmware %s", input);
2999
3000 output_file = fopen(output, "wb");
3001 if (!output_file)
3002 error(1, 0, "Can not open output firmware %s", output);
3003
3004 if (read_partition_table(input_file, firmware_offset, fwup, MAX_PARTITIONS, 0) != 0) {
3005 error(1, 0, "Error can not read the partition table (fwup-ptn)");
3006 }
3007
3008 fwup_os_image = find_partition(fwup, MAX_PARTITIONS,
3009 "os-image", "Error can not find os-image partition (fwup)");
3010 fwup_file_system = find_partition(fwup, MAX_PARTITIONS,
3011 "file-system", "Error can not find file-system partition (fwup)");
3012 fwup_partition_table = find_partition(fwup, MAX_PARTITIONS,
3013 "partition-table", "Error can not find partition-table partition");
3014
3015 /* the flash partition table has a 0x00000004 magic haeder */
3016 if (read_partition_table(input_file, firmware_offset + fwup_partition_table->base + 4, flash, MAX_PARTITIONS, 1) != 0)
3017 error(1, 0, "Error can not read the partition table (flash)");
3018
3019 flash_os_image = find_partition(flash, MAX_PARTITIONS,
3020 "os-image", "Error can not find os-image partition (flash)");
3021 flash_file_system = find_partition(flash, MAX_PARTITIONS,
3022 "file-system", "Error can not find file-system partition (flash)");
3023
3024 /* write os_image to 0x0 */
3025 write_partition(input_file, firmware_offset, fwup_os_image, output_file);
3026 write_ff(output_file, flash_os_image->size - fwup_os_image->size);
3027
3028 /* write file-system behind os_image */
3029 fseek(output_file, flash_file_system->base - flash_os_image->base, SEEK_SET);
3030 write_partition(input_file, firmware_offset, fwup_file_system, output_file);
3031 write_ff(output_file, flash_file_system->size - fwup_file_system->size);
3032
3033 fclose(output_file);
3034 fclose(input_file);
3035 }
3036
3037 int main(int argc, char *argv[]) {
3038 const char *board = NULL, *kernel_image = NULL, *rootfs_image = NULL, *output = NULL;
3039 const char *extract_image = NULL, *output_directory = NULL, *convert_image = NULL;
3040 bool add_jffs2_eof = false, sysupgrade = false;
3041 unsigned rev = 0;
3042 struct device_info *info;
3043 set_source_date_epoch();
3044
3045 while (true) {
3046 int c;
3047
3048 c = getopt(argc, argv, "B:k:r:o:V:jSh:x:d:z:");
3049 if (c == -1)
3050 break;
3051
3052 switch (c) {
3053 case 'B':
3054 board = optarg;
3055 break;
3056
3057 case 'k':
3058 kernel_image = optarg;
3059 break;
3060
3061 case 'r':
3062 rootfs_image = optarg;
3063 break;
3064
3065 case 'o':
3066 output = optarg;
3067 break;
3068
3069 case 'V':
3070 sscanf(optarg, "r%u", &rev);
3071 break;
3072
3073 case 'j':
3074 add_jffs2_eof = true;
3075 break;
3076
3077 case 'S':
3078 sysupgrade = true;
3079 break;
3080
3081 case 'h':
3082 usage(argv[0]);
3083 return 0;
3084
3085 case 'd':
3086 output_directory = optarg;
3087 break;
3088
3089 case 'x':
3090 extract_image = optarg;
3091 break;
3092
3093 case 'z':
3094 convert_image = optarg;
3095 break;
3096
3097 default:
3098 usage(argv[0]);
3099 return 1;
3100 }
3101 }
3102
3103 if (extract_image || output_directory) {
3104 if (!extract_image)
3105 error(1, 0, "No factory/oem image given via -x <file>. Output directory is only valid with -x");
3106 if (!output_directory)
3107 error(1, 0, "Can not extract an image without output directory. Use -d <dir>");
3108 extract_firmware(extract_image, output_directory);
3109 } else if (convert_image) {
3110 if (!output)
3111 error(1, 0, "Can not convert a factory/oem image into sysupgrade image without output file. Use -o <file>");
3112 convert_firmware(convert_image, output);
3113 } else {
3114 if (!board)
3115 error(1, 0, "no board has been specified");
3116 if (!kernel_image)
3117 error(1, 0, "no kernel image has been specified");
3118 if (!rootfs_image)
3119 error(1, 0, "no rootfs image has been specified");
3120 if (!output)
3121 error(1, 0, "no output filename has been specified");
3122
3123 info = find_board(board);
3124
3125 if (info == NULL)
3126 error(1, 0, "unsupported board %s", board);
3127
3128 build_image(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade, info);
3129 }
3130
3131 return 0;
3132 }