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