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