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