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