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