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