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