2 Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
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.
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.
30 Image generation tool for the TP-LINK SafeLoader as seen on
31 TP-LINK Pharos devices (CPE210/220/510/520)
45 #include <arpa/inet.h>
47 #include <sys/types.h>
54 #define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
57 #define MAX_PARTITIONS 32
59 /** An image partition table entry */
60 struct image_partition_entry
{
66 /** A flash partition table entry */
67 struct flash_partition_entry
{
73 /** Firmware layout description */
77 const char *support_list
;
80 struct flash_partition_entry partitions
[MAX_PARTITIONS
+1];
81 const char *first_sysupgrade_partition
;
82 const char *last_sysupgrade_partition
;
85 /** The content of the soft-version structure */
86 struct __attribute__((__packed__
)) soft_version
{
90 uint8_t version_major
;
91 uint8_t version_minor
;
92 uint8_t version_patch
;
102 static const uint8_t jffs2_eof_mark
[4] = {0xde, 0xad, 0xc0, 0xde};
106 Salt for the MD5 hash
108 Fortunately, TP-LINK seems to use the same salt for most devices which use
109 the new image format.
111 static const uint8_t md5_salt
[16] = {
112 0x7a, 0x2b, 0x15, 0xed,
113 0x9b, 0x98, 0x59, 0x6d,
114 0xe5, 0x04, 0xab, 0x44,
115 0xac, 0x2a, 0x9f, 0x4e,
119 /** Firmware layout table */
120 static struct device_info boards
[] = {
121 /** Firmware layout for the CPE210/220 V1 */
124 .vendor
= "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
127 "CPE210(TP-LINK|UN|N300-2):1.0\r\n"
128 "CPE210(TP-LINK|UN|N300-2):1.1\r\n"
129 "CPE210(TP-LINK|US|N300-2):1.1\r\n"
130 "CPE210(TP-LINK|EU|N300-2):1.1\r\n"
131 "CPE220(TP-LINK|UN|N300-2):1.1\r\n"
132 "CPE220(TP-LINK|US|N300-2):1.1\r\n"
133 "CPE220(TP-LINK|EU|N300-2):1.1\r\n",
134 .support_trail
= '\xff',
138 {"fs-uboot", 0x00000, 0x20000},
139 {"partition-table", 0x20000, 0x02000},
140 {"default-mac", 0x30000, 0x00020},
141 {"product-info", 0x31100, 0x00100},
142 {"signature", 0x32000, 0x00400},
143 {"os-image", 0x40000, 0x200000},
144 {"file-system", 0x240000, 0x570000},
145 {"soft-version", 0x7b0000, 0x00100},
146 {"support-list", 0x7b1000, 0x00400},
147 {"user-config", 0x7c0000, 0x10000},
148 {"default-config", 0x7d0000, 0x10000},
149 {"log", 0x7e0000, 0x10000},
150 {"radio", 0x7f0000, 0x10000},
154 .first_sysupgrade_partition
= "os-image",
155 .last_sysupgrade_partition
= "support-list",
158 /** Firmware layout for the CPE210 V2 */
161 .vendor
= "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n",
164 "CPE210(TP-LINK|EU|N300-2|00000000):2.0\r\n"
165 "CPE210(TP-LINK|EU|N300-2|45550000):2.0\r\n"
166 "CPE210(TP-LINK|EU|N300-2|55530000):2.0\r\n"
167 "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n"
168 "CPE210(TP-LINK|UN|N300-2|45550000):2.0\r\n"
169 "CPE210(TP-LINK|UN|N300-2|55530000):2.0\r\n"
170 "CPE210(TP-LINK|US|N300-2|55530000):2.0\r\n"
171 "CPE210(TP-LINK|UN|N300-2):2.0\r\n"
172 "CPE210(TP-LINK|EU|N300-2):2.0\r\n"
173 "CPE210(TP-LINK|US|N300-2):2.0\r\n",
174 .support_trail
= '\xff',
178 {"fs-uboot", 0x00000, 0x20000},
179 {"partition-table", 0x20000, 0x02000},
180 {"default-mac", 0x30000, 0x00020},
181 {"product-info", 0x31100, 0x00100},
182 {"device-info", 0x31400, 0x00400},
183 {"signature", 0x32000, 0x00400},
184 {"device-id", 0x33000, 0x00100},
185 {"firmware", 0x40000, 0x770000},
186 {"soft-version", 0x7b0000, 0x00100},
187 {"support-list", 0x7b1000, 0x01000},
188 {"user-config", 0x7c0000, 0x10000},
189 {"default-config", 0x7d0000, 0x10000},
190 {"log", 0x7e0000, 0x10000},
191 {"radio", 0x7f0000, 0x10000},
195 .first_sysupgrade_partition
= "os-image",
196 .last_sysupgrade_partition
= "support-list",
199 /** Firmware layout for the CPE210 V3 */
202 .vendor
= "CPE210(TP-LINK|UN|N300-2|00000000):3.0\r\n",
205 "CPE210(TP-LINK|EU|N300-2|45550000):3.0\r\n"
206 "CPE210(TP-LINK|UN|N300-2|00000000):3.0\r\n"
207 "CPE210(TP-LINK|UN|N300-2):3.0\r\n"
208 "CPE210(TP-LINK|EU|N300-2):3.0\r\n",
209 .support_trail
= '\xff',
213 {"fs-uboot", 0x00000, 0x20000},
214 {"partition-table", 0x20000, 0x01000},
215 {"default-mac", 0x30000, 0x00020},
216 {"product-info", 0x31100, 0x00100},
217 {"device-info", 0x31400, 0x00400},
218 {"signature", 0x32000, 0x00400},
219 {"device-id", 0x33000, 0x00100},
220 {"firmware", 0x40000, 0x770000},
221 {"soft-version", 0x7b0000, 0x00100},
222 {"support-list", 0x7b1000, 0x01000},
223 {"user-config", 0x7c0000, 0x10000},
224 {"default-config", 0x7d0000, 0x10000},
225 {"log", 0x7e0000, 0x10000},
226 {"radio", 0x7f0000, 0x10000},
230 .first_sysupgrade_partition
= "os-image",
231 .last_sysupgrade_partition
= "support-list",
234 /** Firmware layout for the CPE220 V2 */
237 .vendor
= "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
240 "CPE220(TP-LINK|EU|N300-2|00000000):2.0\r\n"
241 "CPE220(TP-LINK|EU|N300-2|45550000):2.0\r\n"
242 "CPE220(TP-LINK|EU|N300-2|55530000):2.0\r\n"
243 "CPE220(TP-LINK|UN|N300-2|00000000):2.0\r\n"
244 "CPE220(TP-LINK|UN|N300-2|45550000):2.0\r\n"
245 "CPE220(TP-LINK|UN|N300-2|55530000):2.0\r\n"
246 "CPE220(TP-LINK|US|N300-2|55530000):2.0\r\n"
247 "CPE220(TP-LINK|UN|N300-2):2.0\r\n"
248 "CPE220(TP-LINK|EU|N300-2):2.0\r\n"
249 "CPE220(TP-LINK|US|N300-2):2.0\r\n",
250 .support_trail
= '\xff',
254 {"fs-uboot", 0x00000, 0x20000},
255 {"partition-table", 0x20000, 0x02000},
256 {"default-mac", 0x30000, 0x00020},
257 {"product-info", 0x31100, 0x00100},
258 {"signature", 0x32000, 0x00400},
259 {"os-image", 0x40000, 0x200000},
260 {"file-system", 0x240000, 0x570000},
261 {"soft-version", 0x7b0000, 0x00100},
262 {"support-list", 0x7b1000, 0x00400},
263 {"user-config", 0x7c0000, 0x10000},
264 {"default-config", 0x7d0000, 0x10000},
265 {"log", 0x7e0000, 0x10000},
266 {"radio", 0x7f0000, 0x10000},
270 .first_sysupgrade_partition
= "os-image",
271 .last_sysupgrade_partition
= "support-list",
274 /** Firmware layout for the CPE510/520 V1 */
277 .vendor
= "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
280 "CPE510(TP-LINK|UN|N300-5):1.0\r\n"
281 "CPE510(TP-LINK|UN|N300-5):1.1\r\n"
282 "CPE510(TP-LINK|UN|N300-5):1.1\r\n"
283 "CPE510(TP-LINK|US|N300-5):1.1\r\n"
284 "CPE510(TP-LINK|EU|N300-5):1.1\r\n"
285 "CPE520(TP-LINK|UN|N300-5):1.1\r\n"
286 "CPE520(TP-LINK|US|N300-5):1.1\r\n"
287 "CPE520(TP-LINK|EU|N300-5):1.1\r\n",
288 .support_trail
= '\xff',
292 {"fs-uboot", 0x00000, 0x20000},
293 {"partition-table", 0x20000, 0x02000},
294 {"default-mac", 0x30000, 0x00020},
295 {"product-info", 0x31100, 0x00100},
296 {"signature", 0x32000, 0x00400},
297 {"os-image", 0x40000, 0x200000},
298 {"file-system", 0x240000, 0x570000},
299 {"soft-version", 0x7b0000, 0x00100},
300 {"support-list", 0x7b1000, 0x00400},
301 {"user-config", 0x7c0000, 0x10000},
302 {"default-config", 0x7d0000, 0x10000},
303 {"log", 0x7e0000, 0x10000},
304 {"radio", 0x7f0000, 0x10000},
308 .first_sysupgrade_partition
= "os-image",
309 .last_sysupgrade_partition
= "support-list",
312 /** Firmware layout for the CPE510 V2 */
315 .vendor
= "CPE510(TP-LINK|UN|N300-5):2.0\r\n",
318 "CPE510(TP-LINK|EU|N300-5|00000000):2.0\r\n"
319 "CPE510(TP-LINK|EU|N300-5|45550000):2.0\r\n"
320 "CPE510(TP-LINK|EU|N300-5|55530000):2.0\r\n"
321 "CPE510(TP-LINK|UN|N300-5|00000000):2.0\r\n"
322 "CPE510(TP-LINK|UN|N300-5|45550000):2.0\r\n"
323 "CPE510(TP-LINK|UN|N300-5|55530000):2.0\r\n"
324 "CPE510(TP-LINK|US|N300-5|00000000):2.0\r\n"
325 "CPE510(TP-LINK|US|N300-5|45550000):2.0\r\n"
326 "CPE510(TP-LINK|US|N300-5|55530000):2.0\r\n"
327 "CPE510(TP-LINK|UN|N300-5):2.0\r\n"
328 "CPE510(TP-LINK|EU|N300-5):2.0\r\n"
329 "CPE510(TP-LINK|US|N300-5):2.0\r\n",
330 .support_trail
= '\xff',
334 {"fs-uboot", 0x00000, 0x20000},
335 {"partition-table", 0x20000, 0x02000},
336 {"default-mac", 0x30000, 0x00020},
337 {"product-info", 0x31100, 0x00100},
338 {"signature", 0x32000, 0x00400},
339 {"os-image", 0x40000, 0x200000},
340 {"file-system", 0x240000, 0x570000},
341 {"soft-version", 0x7b0000, 0x00100},
342 {"support-list", 0x7b1000, 0x00400},
343 {"user-config", 0x7c0000, 0x10000},
344 {"default-config", 0x7d0000, 0x10000},
345 {"log", 0x7e0000, 0x10000},
346 {"radio", 0x7f0000, 0x10000},
350 .first_sysupgrade_partition
= "os-image",
351 .last_sysupgrade_partition
= "support-list",
354 /** Firmware layout for the CPE510 V3 */
357 .vendor
= "CPE510(TP-LINK|UN|N300-5):3.0\r\n",
360 "CPE510(TP-LINK|EU|N300-5|00000000):3.0\r\n"
361 "CPE510(TP-LINK|EU|N300-5|45550000):3.0\r\n"
362 "CPE510(TP-LINK|EU|N300-5|55530000):3.0\r\n"
363 "CPE510(TP-LINK|UN|N300-5|00000000):3.0\r\n"
364 "CPE510(TP-LINK|UN|N300-5|45550000):3.0\r\n"
365 "CPE510(TP-LINK|UN|N300-5|55530000):3.0\r\n"
366 "CPE510(TP-LINK|US|N300-5|00000000):3.0\r\n"
367 "CPE510(TP-LINK|US|N300-5|45550000):3.0\r\n"
368 "CPE510(TP-LINK|US|N300-5|55530000):3.0\r\n"
369 "CPE510(TP-LINK|UN|N300-5):3.0\r\n"
370 "CPE510(TP-LINK|EU|N300-5):3.0\r\n"
371 "CPE510(TP-LINK|US|N300-5):3.0\r\n",
372 .support_trail
= '\xff',
376 {"fs-uboot", 0x00000, 0x20000},
377 {"partition-table", 0x20000, 0x02000},
378 {"default-mac", 0x30000, 0x00020},
379 {"product-info", 0x31100, 0x00100},
380 {"signature", 0x32000, 0x00400},
381 {"os-image", 0x40000, 0x200000},
382 {"file-system", 0x240000, 0x570000},
383 {"soft-version", 0x7b0000, 0x00100},
384 {"support-list", 0x7b1000, 0x00400},
385 {"user-config", 0x7c0000, 0x10000},
386 {"default-config", 0x7d0000, 0x10000},
387 {"log", 0x7e0000, 0x10000},
388 {"radio", 0x7f0000, 0x10000},
392 .first_sysupgrade_partition
= "os-image",
393 .last_sysupgrade_partition
= "support-list",
396 /** Firmware layout for the CPE610V1 */
399 .vendor
= "CPE610(TP-LINK|UN|N300-5|00000000):1.0\r\n",
402 "CPE610(TP-LINK|EU|N300-5|00000000):1.0\r\n"
403 "CPE610(TP-LINK|EU|N300-5|45550000):1.0\r\n"
404 "CPE610(TP-LINK|EU|N300-5|55530000):1.0\r\n"
405 "CPE610(TP-LINK|UN|N300-5|00000000):1.0\r\n"
406 "CPE610(TP-LINK|UN|N300-5|45550000):1.0\r\n"
407 "CPE610(TP-LINK|UN|N300-5|55530000):1.0\r\n"
408 "CPE610(TP-LINK|US|N300-5|55530000):1.0\r\n"
409 "CPE610(TP-LINK|UN|N300-5):1.0\r\n"
410 "CPE610(TP-LINK|EU|N300-5):1.0\r\n"
411 "CPE610(TP-LINK|US|N300-5):1.0\r\n",
412 .support_trail
= '\xff',
416 {"fs-uboot", 0x00000, 0x20000},
417 {"partition-table", 0x20000, 0x02000},
418 {"default-mac", 0x30000, 0x00020},
419 {"product-info", 0x31100, 0x00100},
420 {"signature", 0x32000, 0x00400},
421 {"os-image", 0x40000, 0x200000},
422 {"file-system", 0x240000, 0x570000},
423 {"soft-version", 0x7b0000, 0x00100},
424 {"support-list", 0x7b1000, 0x00400},
425 {"user-config", 0x7c0000, 0x10000},
426 {"default-config", 0x7d0000, 0x10000},
427 {"log", 0x7e0000, 0x10000},
428 {"radio", 0x7f0000, 0x10000},
432 .first_sysupgrade_partition
= "os-image",
433 .last_sysupgrade_partition
= "support-list",
438 .vendor
= "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
441 "WBS210(TP-LINK|UN|N300-2):1.20\r\n"
442 "WBS210(TP-LINK|US|N300-2):1.20\r\n"
443 "WBS210(TP-LINK|EU|N300-2):1.20\r\n",
444 .support_trail
= '\xff',
448 {"fs-uboot", 0x00000, 0x20000},
449 {"partition-table", 0x20000, 0x02000},
450 {"default-mac", 0x30000, 0x00020},
451 {"product-info", 0x31100, 0x00100},
452 {"signature", 0x32000, 0x00400},
453 {"os-image", 0x40000, 0x200000},
454 {"file-system", 0x240000, 0x570000},
455 {"soft-version", 0x7b0000, 0x00100},
456 {"support-list", 0x7b1000, 0x00400},
457 {"user-config", 0x7c0000, 0x10000},
458 {"default-config", 0x7d0000, 0x10000},
459 {"log", 0x7e0000, 0x10000},
460 {"radio", 0x7f0000, 0x10000},
464 .first_sysupgrade_partition
= "os-image",
465 .last_sysupgrade_partition
= "support-list",
470 .vendor
= "CPE510(TP-LINK|UN|N300-5):1.0\r\n",
473 "WBS510(TP-LINK|UN|N300-5):1.20\r\n"
474 "WBS510(TP-LINK|US|N300-5):1.20\r\n"
475 "WBS510(TP-LINK|EU|N300-5):1.20\r\n",
476 .support_trail
= '\xff',
480 {"fs-uboot", 0x00000, 0x20000},
481 {"partition-table", 0x20000, 0x02000},
482 {"default-mac", 0x30000, 0x00020},
483 {"product-info", 0x31100, 0x00100},
484 {"signature", 0x32000, 0x00400},
485 {"os-image", 0x40000, 0x200000},
486 {"file-system", 0x240000, 0x570000},
487 {"soft-version", 0x7b0000, 0x00100},
488 {"support-list", 0x7b1000, 0x00400},
489 {"user-config", 0x7c0000, 0x10000},
490 {"default-config", 0x7d0000, 0x10000},
491 {"log", 0x7e0000, 0x10000},
492 {"radio", 0x7f0000, 0x10000},
496 .first_sysupgrade_partition
= "os-image",
497 .last_sysupgrade_partition
= "support-list",
500 /** Firmware layout for the C2600 */
506 "{product_name:Archer C2600,product_ver:1.0.0,special_id:00000000}\r\n",
507 .support_trail
= '\x00',
511 We use a bigger os-image partition than the stock images (and thus
512 smaller file-system), as our kernel doesn't fit in the stock firmware's
513 2 MB os-image since kernel 4.14.
516 {"SBL1", 0x00000, 0x20000},
517 {"MIBIB", 0x20000, 0x20000},
518 {"SBL2", 0x40000, 0x20000},
519 {"SBL3", 0x60000, 0x30000},
520 {"DDRCONFIG", 0x90000, 0x10000},
521 {"SSD", 0xa0000, 0x10000},
522 {"TZ", 0xb0000, 0x30000},
523 {"RPM", 0xe0000, 0x20000},
524 {"fs-uboot", 0x100000, 0x70000},
525 {"uboot-env", 0x170000, 0x40000},
526 {"radio", 0x1b0000, 0x40000},
527 {"os-image", 0x1f0000, 0x400000}, /* Stock: base 0x1f0000 size 0x200000 */
528 {"file-system", 0x5f0000, 0x1900000}, /* Stock: base 0x3f0000 size 0x1b00000 */
529 {"default-mac", 0x1ef0000, 0x00200},
530 {"pin", 0x1ef0200, 0x00200},
531 {"product-info", 0x1ef0400, 0x0fc00},
532 {"partition-table", 0x1f00000, 0x10000},
533 {"soft-version", 0x1f10000, 0x10000},
534 {"support-list", 0x1f20000, 0x10000},
535 {"profile", 0x1f30000, 0x10000},
536 {"default-config", 0x1f40000, 0x10000},
537 {"user-config", 0x1f50000, 0x40000},
538 {"qos-db", 0x1f90000, 0x40000},
539 {"usb-config", 0x1fd0000, 0x10000},
540 {"log", 0x1fe0000, 0x20000},
544 .first_sysupgrade_partition
= "os-image",
545 .last_sysupgrade_partition
= "file-system"
548 /** Firmware layout for the A7-V5 */
550 .id
= "ARCHER-A7-V5",
553 "{product_name:Archer A7,product_ver:5.0.0,special_id:45550000}\n"
554 "{product_name:Archer A7,product_ver:5.0.0,special_id:55530000}\n"
555 "{product_name:Archer A7,product_ver:5.0.0,special_id:43410000}\n"
556 "{product_name:Archer A7,product_ver:5.0.0,special_id:4A500000}\n"
557 "{product_name:Archer A7,product_ver:5.0.0,special_id:54570000}\n",
558 .support_trail
= '\x00',
559 .soft_ver
= "soft_ver:1.0.0\n",
561 /* We're using a dynamic kernel/rootfs split here */
563 {"factory-boot", 0x00000, 0x20000},
564 {"fs-uboot", 0x20000, 0x20000},
565 {"firmware", 0x40000, 0xec0000}, /* Stock: name os-image base 0x40000 size 0x120000 */
566 /* Stock: name file-system base 0x160000 size 0xda0000 */
567 {"default-mac", 0xf40000, 0x00200},
568 {"pin", 0xf40200, 0x00200},
569 {"device-id", 0xf40400, 0x00100},
570 {"product-info", 0xf40500, 0x0fb00},
571 {"soft-version", 0xf50000, 0x00100},
572 {"extra-para", 0xf51000, 0x01000},
573 {"support-list", 0xf52000, 0x0a000},
574 {"profile", 0xf5c000, 0x04000},
575 {"default-config", 0xf60000, 0x10000},
576 {"user-config", 0xf70000, 0x40000},
577 {"certificate", 0xfb0000, 0x10000},
578 {"partition-table", 0xfc0000, 0x10000},
579 {"log", 0xfd0000, 0x20000},
580 {"radio", 0xff0000, 0x10000},
584 .first_sysupgrade_partition
= "os-image",
585 .last_sysupgrade_partition
= "file-system",
588 /** Firmware layout for the C2v3 */
590 .id
= "ARCHER-C2-V3",
593 "{product_name:ArcherC2,product_ver:3.0.0,special_id:00000000}\n"
594 "{product_name:ArcherC2,product_ver:3.0.0,special_id:55530000}\n"
595 "{product_name:ArcherC2,product_ver:3.0.0,special_id:45550000}\n",
596 .support_trail
= '\x00',
597 .soft_ver
= "soft_ver:3.0.1\n",
599 /** We're using a dynamic kernel/rootfs split here */
602 {"factory-boot", 0x00000, 0x20000},
603 {"fs-uboot", 0x20000, 0x10000},
604 {"firmware", 0x30000, 0x7a0000},
605 {"user-config", 0x7d0000, 0x04000},
606 {"default-mac", 0x7e0000, 0x00100},
607 {"device-id", 0x7e0100, 0x00100},
608 {"extra-para", 0x7e0200, 0x00100},
609 {"pin", 0x7e0300, 0x00100},
610 {"support-list", 0x7e0400, 0x00400},
611 {"soft-version", 0x7e0800, 0x00400},
612 {"product-info", 0x7e0c00, 0x01400},
613 {"partition-table", 0x7e2000, 0x01000},
614 {"profile", 0x7e3000, 0x01000},
615 {"default-config", 0x7e4000, 0x04000},
616 {"merge-config", 0x7ec000, 0x02000},
617 {"qos-db", 0x7ee000, 0x02000},
618 {"radio", 0x7f0000, 0x10000},
622 .first_sysupgrade_partition
= "os-image",
623 .last_sysupgrade_partition
= "file-system",
626 /** Firmware layout for the C25v1 */
628 .id
= "ARCHER-C25-V1",
631 "{product_name:ArcherC25,product_ver:1.0.0,special_id:00000000}\n"
632 "{product_name:ArcherC25,product_ver:1.0.0,special_id:55530000}\n"
633 "{product_name:ArcherC25,product_ver:1.0.0,special_id:45550000}\n",
634 .support_trail
= '\x00',
635 .soft_ver
= "soft_ver:1.0.0\n",
637 /* We're using a dynamic kernel/rootfs split here */
639 {"factory-boot", 0x00000, 0x20000},
640 {"fs-uboot", 0x20000, 0x10000},
641 {"firmware", 0x30000, 0x7a0000}, /* Stock: name os-image base 0x30000 size 0x100000 */
642 /* Stock: name file-system base 0x130000 size 0x6a0000 */
643 {"user-config", 0x7d0000, 0x04000},
644 {"default-mac", 0x7e0000, 0x00100},
645 {"device-id", 0x7e0100, 0x00100},
646 {"extra-para", 0x7e0200, 0x00100},
647 {"pin", 0x7e0300, 0x00100},
648 {"support-list", 0x7e0400, 0x00400},
649 {"soft-version", 0x7e0800, 0x00400},
650 {"product-info", 0x7e0c00, 0x01400},
651 {"partition-table", 0x7e2000, 0x01000},
652 {"profile", 0x7e3000, 0x01000},
653 {"default-config", 0x7e4000, 0x04000},
654 {"merge-config", 0x7ec000, 0x02000},
655 {"qos-db", 0x7ee000, 0x02000},
656 {"radio", 0x7f0000, 0x10000},
660 .first_sysupgrade_partition
= "os-image",
661 .last_sysupgrade_partition
= "file-system",
664 /** Firmware layout for the C58v1 */
666 .id
= "ARCHER-C58-V1",
670 "{product_name:Archer C58,product_ver:1.0.0,special_id:00000000}\r\n"
671 "{product_name:Archer C58,product_ver:1.0.0,special_id:45550000}\r\n"
672 "{product_name:Archer C58,product_ver:1.0.0,special_id:55530000}\r\n",
673 .support_trail
= '\x00',
674 .soft_ver
= "soft_ver:1.0.0\n",
677 {"fs-uboot", 0x00000, 0x10000},
678 {"default-mac", 0x10000, 0x00200},
679 {"pin", 0x10200, 0x00200},
680 {"product-info", 0x10400, 0x00100},
681 {"partition-table", 0x10500, 0x00800},
682 {"soft-version", 0x11300, 0x00200},
683 {"support-list", 0x11500, 0x00100},
684 {"device-id", 0x11600, 0x00100},
685 {"profile", 0x11700, 0x03900},
686 {"default-config", 0x15000, 0x04000},
687 {"user-config", 0x19000, 0x04000},
688 {"firmware", 0x20000, 0x7c8000},
689 {"certyficate", 0x7e8000, 0x08000},
690 {"radio", 0x7f0000, 0x10000},
694 .first_sysupgrade_partition
= "os-image",
695 .last_sysupgrade_partition
= "file-system",
698 /** Firmware layout for the C59v1 */
700 .id
= "ARCHER-C59-V1",
704 "{product_name:Archer C59,product_ver:1.0.0,special_id:00000000}\r\n"
705 "{product_name:Archer C59,product_ver:1.0.0,special_id:45550000}\r\n"
706 "{product_name:Archer C59,product_ver:1.0.0,special_id:52550000}\r\n"
707 "{product_name:Archer C59,product_ver:1.0.0,special_id:55530000}\r\n",
708 .support_trail
= '\x00',
709 .soft_ver
= "soft_ver:1.0.0\n",
711 /* We're using a dynamic kernel/rootfs split here */
713 {"fs-uboot", 0x00000, 0x10000},
714 {"default-mac", 0x10000, 0x00200},
715 {"pin", 0x10200, 0x00200},
716 {"device-id", 0x10400, 0x00100},
717 {"product-info", 0x10500, 0x0fb00},
718 {"firmware", 0x20000, 0xe30000},
719 {"partition-table", 0xe50000, 0x10000},
720 {"soft-version", 0xe60000, 0x10000},
721 {"support-list", 0xe70000, 0x10000},
722 {"profile", 0xe80000, 0x10000},
723 {"default-config", 0xe90000, 0x10000},
724 {"user-config", 0xea0000, 0x40000},
725 {"usb-config", 0xee0000, 0x10000},
726 {"certificate", 0xef0000, 0x10000},
727 {"qos-db", 0xf00000, 0x40000},
728 {"log", 0xfe0000, 0x10000},
729 {"radio", 0xff0000, 0x10000},
733 .first_sysupgrade_partition
= "os-image",
734 .last_sysupgrade_partition
= "file-system",
737 /** Firmware layout for the C59v2 */
739 .id
= "ARCHER-C59-V2",
743 "{product_name:Archer C59,product_ver:2.0.0,special_id:00000000}\r\n"
744 "{product_name:Archer C59,product_ver:2.0.0,special_id:45550000}\r\n"
745 "{product_name:Archer C59,product_ver:2.0.0,special_id:55530000}\r\n",
746 .support_trail
= '\x00',
747 .soft_ver
= "soft_ver:2.0.0 Build 20161206 rel.7303\n",
749 /** We're using a dynamic kernel/rootfs split here */
751 {"factory-boot", 0x00000, 0x20000},
752 {"fs-uboot", 0x20000, 0x10000},
753 {"default-mac", 0x30000, 0x00200},
754 {"pin", 0x30200, 0x00200},
755 {"device-id", 0x30400, 0x00100},
756 {"product-info", 0x30500, 0x0fb00},
757 {"firmware", 0x40000, 0xe10000},
758 {"partition-table", 0xe50000, 0x10000},
759 {"soft-version", 0xe60000, 0x10000},
760 {"support-list", 0xe70000, 0x10000},
761 {"profile", 0xe80000, 0x10000},
762 {"default-config", 0xe90000, 0x10000},
763 {"user-config", 0xea0000, 0x40000},
764 {"usb-config", 0xee0000, 0x10000},
765 {"certificate", 0xef0000, 0x10000},
766 {"extra-para", 0xf00000, 0x10000},
767 {"qos-db", 0xf10000, 0x30000},
768 {"log", 0xfe0000, 0x10000},
769 {"radio", 0xff0000, 0x10000},
773 .first_sysupgrade_partition
= "os-image",
774 .last_sysupgrade_partition
= "file-system",
777 /** Firmware layout for the C6v2 */
779 .id
= "ARCHER-C6-V2",
783 "{product_name:Archer C6,product_ver:2.0.0,special_id:45550000}\r\n"
784 "{product_name:Archer C6,product_ver:2.0.0,special_id:52550000}\r\n"
785 "{product_name:Archer C6,product_ver:2.0.0,special_id:4A500000}\r\n",
786 .support_trail
= '\x00',
787 .soft_ver
= "soft_ver:1.0.0\n",
790 {"fs-uboot", 0x00000, 0x20000},
791 {"default-mac", 0x20000, 0x00200},
792 {"pin", 0x20200, 0x00100},
793 {"product-info", 0x20300, 0x00200},
794 {"device-id", 0x20500, 0x0fb00},
795 {"firmware", 0x30000, 0x7a9400},
796 {"soft-version", 0x7d9400, 0x00100},
797 {"extra-para", 0x7d9500, 0x00100},
798 {"support-list", 0x7d9600, 0x00200},
799 {"profile", 0x7d9800, 0x03000},
800 {"default-config", 0x7dc800, 0x03000},
801 {"partition-table", 0x7df800, 0x00800},
802 {"user-config", 0x7e0000, 0x0c000},
803 {"certificate", 0x7ec000, 0x04000},
804 {"radio", 0x7f0000, 0x10000},
808 .first_sysupgrade_partition
= "os-image",
809 .last_sysupgrade_partition
= "file-system",
813 /** Firmware layout for the C60v1 */
815 .id
= "ARCHER-C60-V1",
819 "{product_name:Archer C60,product_ver:1.0.0,special_id:00000000}\r\n"
820 "{product_name:Archer C60,product_ver:1.0.0,special_id:45550000}\r\n"
821 "{product_name:Archer C60,product_ver:1.0.0,special_id:55530000}\r\n",
822 .support_trail
= '\x00',
823 .soft_ver
= "soft_ver:1.0.0\n",
826 {"fs-uboot", 0x00000, 0x10000},
827 {"default-mac", 0x10000, 0x00200},
828 {"pin", 0x10200, 0x00200},
829 {"product-info", 0x10400, 0x00100},
830 {"partition-table", 0x10500, 0x00800},
831 {"soft-version", 0x11300, 0x00200},
832 {"support-list", 0x11500, 0x00100},
833 {"device-id", 0x11600, 0x00100},
834 {"profile", 0x11700, 0x03900},
835 {"default-config", 0x15000, 0x04000},
836 {"user-config", 0x19000, 0x04000},
837 {"firmware", 0x20000, 0x7c8000},
838 {"certyficate", 0x7e8000, 0x08000},
839 {"radio", 0x7f0000, 0x10000},
843 .first_sysupgrade_partition
= "os-image",
844 .last_sysupgrade_partition
= "file-system",
847 /** Firmware layout for the C60v2 */
849 .id
= "ARCHER-C60-V2",
853 "{product_name:Archer C60,product_ver:2.0.0,special_id:42520000}\r\n"
854 "{product_name:Archer C60,product_ver:2.0.0,special_id:45550000}\r\n"
855 "{product_name:Archer C60,product_ver:2.0.0,special_id:55530000}\r\n",
856 .support_trail
= '\x00',
857 .soft_ver
= "soft_ver:2.0.0\n",
860 {"factory-boot", 0x00000, 0x1fb00},
861 {"default-mac", 0x1fb00, 0x00200},
862 {"pin", 0x1fd00, 0x00100},
863 {"product-info", 0x1fe00, 0x00100},
864 {"device-id", 0x1ff00, 0x00100},
865 {"fs-uboot", 0x20000, 0x10000},
866 {"firmware", 0x30000, 0x7a0000},
867 {"soft-version", 0x7d9500, 0x00100},
868 {"support-list", 0x7d9600, 0x00100},
869 {"extra-para", 0x7d9700, 0x00100},
870 {"profile", 0x7d9800, 0x03000},
871 {"default-config", 0x7dc800, 0x03000},
872 {"partition-table", 0x7df800, 0x00800},
873 {"user-config", 0x7e0000, 0x0c000},
874 {"certificate", 0x7ec000, 0x04000},
875 {"radio", 0x7f0000, 0x10000},
879 .first_sysupgrade_partition
= "os-image",
880 .last_sysupgrade_partition
= "file-system",
883 /** Firmware layout for the C5 */
885 .id
= "ARCHER-C5-V2",
889 "{product_name:ArcherC5,product_ver:2.0.0,special_id:00000000}\r\n"
890 "{product_name:ArcherC5,product_ver:2.0.0,special_id:55530000}\r\n"
891 "{product_name:ArcherC5,product_ver:2.0.0,special_id:4A500000}\r\n", /* JP version */
892 .support_trail
= '\x00',
896 {"fs-uboot", 0x00000, 0x40000},
897 {"os-image", 0x40000, 0x200000},
898 {"file-system", 0x240000, 0xc00000},
899 {"default-mac", 0xe40000, 0x00200},
900 {"pin", 0xe40200, 0x00200},
901 {"product-info", 0xe40400, 0x00200},
902 {"partition-table", 0xe50000, 0x10000},
903 {"soft-version", 0xe60000, 0x00200},
904 {"support-list", 0xe61000, 0x0f000},
905 {"profile", 0xe70000, 0x10000},
906 {"default-config", 0xe80000, 0x10000},
907 {"user-config", 0xe90000, 0x50000},
908 {"log", 0xee0000, 0x100000},
909 {"radio_bk", 0xfe0000, 0x10000},
910 {"radio", 0xff0000, 0x10000},
914 .first_sysupgrade_partition
= "os-image",
915 .last_sysupgrade_partition
= "file-system"
918 /** Firmware layout for the C7 */
920 .id
= "ARCHER-C7-V4",
923 "{product_name:Archer C7,product_ver:4.0.0,special_id:00000000}\n"
924 "{product_name:Archer C7,product_ver:4.0.0,special_id:41550000}\n"
925 "{product_name:Archer C7,product_ver:4.0.0,special_id:45550000}\n"
926 "{product_name:Archer C7,product_ver:4.0.0,special_id:4B520000}\n"
927 "{product_name:Archer C7,product_ver:4.0.0,special_id:42520000}\n"
928 "{product_name:Archer C7,product_ver:4.0.0,special_id:4A500000}\n"
929 "{product_name:Archer C7,product_ver:4.0.0,special_id:52550000}\n"
930 "{product_name:Archer C7,product_ver:4.0.0,special_id:54570000}\n"
931 "{product_name:Archer C7,product_ver:4.0.0,special_id:55530000}\n"
932 "{product_name:Archer C7,product_ver:4.0.0,special_id:43410000}\n",
933 .support_trail
= '\x00',
934 .soft_ver
= "soft_ver:1.0.0\n",
936 /* We're using a dynamic kernel/rootfs split here */
938 {"factory-boot", 0x00000, 0x20000},
939 {"fs-uboot", 0x20000, 0x20000},
940 {"firmware", 0x40000, 0xEC0000}, /* Stock: name os-image base 0x40000 size 0x120000 */
941 /* Stock: name file-system base 0x160000 size 0xda0000 */
942 {"default-mac", 0xf00000, 0x00200},
943 {"pin", 0xf00200, 0x00200},
944 {"device-id", 0xf00400, 0x00100},
945 {"product-info", 0xf00500, 0x0fb00},
946 {"soft-version", 0xf10000, 0x00100},
947 {"extra-para", 0xf11000, 0x01000},
948 {"support-list", 0xf12000, 0x0a000},
949 {"profile", 0xf1c000, 0x04000},
950 {"default-config", 0xf20000, 0x10000},
951 {"user-config", 0xf30000, 0x40000},
952 {"qos-db", 0xf70000, 0x40000},
953 {"certificate", 0xfb0000, 0x10000},
954 {"partition-table", 0xfc0000, 0x10000},
955 {"log", 0xfd0000, 0x20000},
956 {"radio", 0xff0000, 0x10000},
960 .first_sysupgrade_partition
= "os-image",
961 .last_sysupgrade_partition
= "file-system",
964 /** Firmware layout for the C7 v5*/
966 .id
= "ARCHER-C7-V5",
969 "{product_name:Archer C7,product_ver:5.0.0,special_id:00000000}\n"
970 "{product_name:Archer C7,product_ver:5.0.0,special_id:45550000}\n"
971 "{product_name:Archer C7,product_ver:5.0.0,special_id:55530000}\n"
972 "{product_name:Archer C7,product_ver:5.0.0,special_id:43410000}\n"
973 "{product_name:Archer C7,product_ver:5.0.0,special_id:4A500000}\n"
974 "{product_name:Archer C7,product_ver:5.0.0,special_id:54570000}\n"
975 "{product_name:Archer C7,product_ver:5.0.0,special_id:52550000}\n"
976 "{product_name:Archer C7,product_ver:5.0.0,special_id:4B520000}\n",
978 .support_trail
= '\x00',
979 .soft_ver
= "soft_ver:1.0.0\n",
981 /* We're using a dynamic kernel/rootfs split here */
983 {"factory-boot", 0x00000, 0x20000},
984 {"fs-uboot", 0x20000, 0x20000},
985 {"partition-table", 0x40000, 0x10000},
986 {"radio", 0x50000, 0x10000},
987 {"default-mac", 0x60000, 0x00200},
988 {"pin", 0x60200, 0x00200},
989 {"device-id", 0x60400, 0x00100},
990 {"product-info", 0x60500, 0x0fb00},
991 {"soft-version", 0x70000, 0x01000},
992 {"extra-para", 0x71000, 0x01000},
993 {"support-list", 0x72000, 0x0a000},
994 {"profile", 0x7c000, 0x04000},
995 {"user-config", 0x80000, 0x40000},
998 {"firmware", 0xc0000, 0xf00000}, /* Stock: name os-image base 0xc0000 size 0x120000 */
999 /* Stock: name file-system base 0x1e0000 size 0xde0000 */
1001 {"log", 0xfc0000, 0x20000},
1002 {"certificate", 0xfe0000, 0x10000},
1003 {"default-config", 0xff0000, 0x10000},
1008 .first_sysupgrade_partition
= "os-image",
1009 .last_sysupgrade_partition
= "file-system",
1012 /** Firmware layout for the C9 */
1018 "{product_name:ArcherC9,"
1019 "product_ver:1.0.0,"
1020 "special_id:00000000}\n",
1021 .support_trail
= '\x00',
1025 {"fs-uboot", 0x00000, 0x40000},
1026 {"os-image", 0x40000, 0x200000},
1027 {"file-system", 0x240000, 0xc00000},
1028 {"default-mac", 0xe40000, 0x00200},
1029 {"pin", 0xe40200, 0x00200},
1030 {"product-info", 0xe40400, 0x00200},
1031 {"partition-table", 0xe50000, 0x10000},
1032 {"soft-version", 0xe60000, 0x00200},
1033 {"support-list", 0xe61000, 0x0f000},
1034 {"profile", 0xe70000, 0x10000},
1035 {"default-config", 0xe80000, 0x10000},
1036 {"user-config", 0xe90000, 0x50000},
1037 {"log", 0xee0000, 0x100000},
1038 {"radio_bk", 0xfe0000, 0x10000},
1039 {"radio", 0xff0000, 0x10000},
1043 .first_sysupgrade_partition
= "os-image",
1044 .last_sysupgrade_partition
= "file-system"
1047 /** Firmware layout for the EAP120 */
1050 .vendor
= "EAP120(TP-LINK|UN|N300-2):1.0\r\n",
1053 "EAP120(TP-LINK|UN|N300-2):1.0\r\n",
1054 .support_trail
= '\xff',
1058 {"fs-uboot", 0x00000, 0x20000},
1059 {"partition-table", 0x20000, 0x02000},
1060 {"default-mac", 0x30000, 0x00020},
1061 {"support-list", 0x31000, 0x00100},
1062 {"product-info", 0x31100, 0x00100},
1063 {"soft-version", 0x32000, 0x00100},
1064 {"os-image", 0x40000, 0x180000},
1065 {"file-system", 0x1c0000, 0x600000},
1066 {"user-config", 0x7c0000, 0x10000},
1067 {"backup-config", 0x7d0000, 0x10000},
1068 {"log", 0x7e0000, 0x10000},
1069 {"radio", 0x7f0000, 0x10000},
1073 .first_sysupgrade_partition
= "os-image",
1074 .last_sysupgrade_partition
= "file-system"
1077 /** Firmware layout for the TL-WA850RE v2 */
1079 .id
= "TLWA850REV2",
1083 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:55530000}\n"
1084 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:00000000}\n"
1085 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:55534100}\n"
1086 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:45550000}\n"
1087 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:4B520000}\n"
1088 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:42520000}\n"
1089 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:4A500000}\n"
1090 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:43410000}\n"
1091 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:41550000}\n"
1092 "{product_name:TL-WA850RE,product_ver:2.0.0,special_id:52550000}\n",
1093 .support_trail
= '\x00',
1097 576KB were moved from file-system to os-image
1098 in comparison to the stock image
1101 {"fs-uboot", 0x00000, 0x20000},
1102 {"os-image", 0x20000, 0x150000},
1103 {"file-system", 0x170000, 0x240000},
1104 {"partition-table", 0x3b0000, 0x02000},
1105 {"default-mac", 0x3c0000, 0x00020},
1106 {"pin", 0x3c0100, 0x00020},
1107 {"product-info", 0x3c1000, 0x01000},
1108 {"soft-version", 0x3c2000, 0x00100},
1109 {"support-list", 0x3c3000, 0x01000},
1110 {"profile", 0x3c4000, 0x08000},
1111 {"user-config", 0x3d0000, 0x10000},
1112 {"default-config", 0x3e0000, 0x10000},
1113 {"radio", 0x3f0000, 0x10000},
1117 .first_sysupgrade_partition
= "os-image",
1118 .last_sysupgrade_partition
= "file-system"
1121 /** Firmware layout for the TL-WA855RE v1 */
1123 .id
= "TLWA855REV1",
1127 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:00000000}\n"
1128 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:55530000}\n"
1129 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:45550000}\n"
1130 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:4B520000}\n"
1131 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:42520000}\n"
1132 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:4A500000}\n"
1133 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:43410000}\n"
1134 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:41550000}\n"
1135 "{product_name:TL-WA855RE,product_ver:1.0.0,special_id:52550000}\n",
1136 .support_trail
= '\x00',
1140 {"fs-uboot", 0x00000, 0x20000},
1141 {"os-image", 0x20000, 0x150000},
1142 {"file-system", 0x170000, 0x240000},
1143 {"partition-table", 0x3b0000, 0x02000},
1144 {"default-mac", 0x3c0000, 0x00020},
1145 {"pin", 0x3c0100, 0x00020},
1146 {"product-info", 0x3c1000, 0x01000},
1147 {"soft-version", 0x3c2000, 0x00100},
1148 {"support-list", 0x3c3000, 0x01000},
1149 {"profile", 0x3c4000, 0x08000},
1150 {"user-config", 0x3d0000, 0x10000},
1151 {"default-config", 0x3e0000, 0x10000},
1152 {"radio", 0x3f0000, 0x10000},
1156 .first_sysupgrade_partition
= "os-image",
1157 .last_sysupgrade_partition
= "file-system"
1160 /** Firmware layout for the TL-WR1043 v5 */
1162 .id
= "TLWR1043NV5",
1166 "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:45550000}\n"
1167 "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:55530000}\n",
1168 .support_trail
= '\x00',
1169 .soft_ver
= "soft_ver:1.0.0\n",
1171 {"factory-boot", 0x00000, 0x20000},
1172 {"fs-uboot", 0x20000, 0x20000},
1173 {"firmware", 0x40000, 0xec0000},
1174 {"default-mac", 0xf00000, 0x00200},
1175 {"pin", 0xf00200, 0x00200},
1176 {"device-id", 0xf00400, 0x00100},
1177 {"product-info", 0xf00500, 0x0fb00},
1178 {"soft-version", 0xf10000, 0x01000},
1179 {"extra-para", 0xf11000, 0x01000},
1180 {"support-list", 0xf12000, 0x0a000},
1181 {"profile", 0xf1c000, 0x04000},
1182 {"default-config", 0xf20000, 0x10000},
1183 {"user-config", 0xf30000, 0x40000},
1184 {"qos-db", 0xf70000, 0x40000},
1185 {"certificate", 0xfb0000, 0x10000},
1186 {"partition-table", 0xfc0000, 0x10000},
1187 {"log", 0xfd0000, 0x20000},
1188 {"radio", 0xff0000, 0x10000},
1191 .first_sysupgrade_partition
= "os-image",
1192 .last_sysupgrade_partition
= "file-system"
1195 /** Firmware layout for the TL-WR1043 v4 */
1197 .id
= "TLWR1043NDV4",
1201 "{product_name:TL-WR1043ND,product_ver:4.0.0,special_id:45550000}\n",
1202 .support_trail
= '\x00',
1205 /* We're using a dynamic kernel/rootfs split here */
1207 {"fs-uboot", 0x00000, 0x20000},
1208 {"firmware", 0x20000, 0xf30000},
1209 {"default-mac", 0xf50000, 0x00200},
1210 {"pin", 0xf50200, 0x00200},
1211 {"product-info", 0xf50400, 0x0fc00},
1212 {"soft-version", 0xf60000, 0x0b000},
1213 {"support-list", 0xf6b000, 0x04000},
1214 {"profile", 0xf70000, 0x04000},
1215 {"default-config", 0xf74000, 0x0b000},
1216 {"user-config", 0xf80000, 0x40000},
1217 {"partition-table", 0xfc0000, 0x10000},
1218 {"log", 0xfd0000, 0x20000},
1219 {"radio", 0xff0000, 0x10000},
1223 .first_sysupgrade_partition
= "os-image",
1224 .last_sysupgrade_partition
= "file-system"
1227 /** Firmware layout for the TL-WR902AC v1 */
1229 .id
= "TL-WR902AC-V1",
1233 "{product_name:TL-WR902AC,product_ver:1.0.0,special_id:45550000}\n"
1234 "{product_name:TL-WR902AC,product_ver:1.0.0,special_id:55530000}\n",
1235 .support_trail
= '\x00',
1239 384KB were moved from file-system to os-image
1240 in comparison to the stock image
1243 {"fs-uboot", 0x00000, 0x20000},
1244 {"firmware", 0x20000, 0x730000},
1245 {"default-mac", 0x750000, 0x00200},
1246 {"pin", 0x750200, 0x00200},
1247 {"product-info", 0x750400, 0x0fc00},
1248 {"soft-version", 0x760000, 0x0b000},
1249 {"support-list", 0x76b000, 0x04000},
1250 {"profile", 0x770000, 0x04000},
1251 {"default-config", 0x774000, 0x0b000},
1252 {"user-config", 0x780000, 0x40000},
1253 {"partition-table", 0x7c0000, 0x10000},
1254 {"log", 0x7d0000, 0x20000},
1255 {"radio", 0x7f0000, 0x10000},
1259 .first_sysupgrade_partition
= "os-image",
1260 .last_sysupgrade_partition
= "file-system",
1263 /** Firmware layout for the TL-WR942N V1 */
1269 "{product_name:TL-WR942N,product_ver:1.0.0,special_id:00000000}\r\n"
1270 "{product_name:TL-WR942N,product_ver:1.0.0,special_id:52550000}\r\n",
1271 .support_trail
= '\x00',
1275 {"fs-uboot", 0x00000, 0x20000},
1276 {"firmware", 0x20000, 0xe20000},
1277 {"default-mac", 0xe40000, 0x00200},
1278 {"pin", 0xe40200, 0x00200},
1279 {"product-info", 0xe40400, 0x0fc00},
1280 {"partition-table", 0xe50000, 0x10000},
1281 {"soft-version", 0xe60000, 0x10000},
1282 {"support-list", 0xe70000, 0x10000},
1283 {"profile", 0xe80000, 0x10000},
1284 {"default-config", 0xe90000, 0x10000},
1285 {"user-config", 0xea0000, 0x40000},
1286 {"qos-db", 0xee0000, 0x40000},
1287 {"certificate", 0xf20000, 0x10000},
1288 {"usb-config", 0xfb0000, 0x10000},
1289 {"log", 0xfc0000, 0x20000},
1290 {"radio-bk", 0xfe0000, 0x10000},
1291 {"radio", 0xff0000, 0x10000},
1295 .first_sysupgrade_partition
= "os-image",
1296 .last_sysupgrade_partition
= "file-system",
1299 /** Firmware layout for the RE350 v1 */
1305 "{product_name:RE350,product_ver:1.0.0,special_id:45550000}\n"
1306 "{product_name:RE350,product_ver:1.0.0,special_id:00000000}\n"
1307 "{product_name:RE350,product_ver:1.0.0,special_id:41550000}\n"
1308 "{product_name:RE350,product_ver:1.0.0,special_id:55530000}\n"
1309 "{product_name:RE350,product_ver:1.0.0,special_id:43410000}\n"
1310 "{product_name:RE350,product_ver:1.0.0,special_id:4b520000}\n"
1311 "{product_name:RE350,product_ver:1.0.0,special_id:4a500000}\n",
1312 .support_trail
= '\x00',
1315 /** We're using a dynamic kernel/rootfs split here */
1317 {"fs-uboot", 0x00000, 0x20000},
1318 {"firmware", 0x20000, 0x5e0000},
1319 {"partition-table", 0x600000, 0x02000},
1320 {"default-mac", 0x610000, 0x00020},
1321 {"pin", 0x610100, 0x00020},
1322 {"product-info", 0x611100, 0x01000},
1323 {"soft-version", 0x620000, 0x01000},
1324 {"support-list", 0x621000, 0x01000},
1325 {"profile", 0x622000, 0x08000},
1326 {"user-config", 0x630000, 0x10000},
1327 {"default-config", 0x640000, 0x10000},
1328 {"radio", 0x7f0000, 0x10000},
1332 .first_sysupgrade_partition
= "os-image",
1333 .last_sysupgrade_partition
= "file-system"
1336 /** Firmware layout for the RE350K v1 */
1342 "{product_name:RE350K,product_ver:1.0.0,special_id:00000000,product_region:US}\n",
1343 .support_trail
= '\x00',
1346 /** We're using a dynamic kernel/rootfs split here */
1348 {"fs-uboot", 0x00000, 0x20000},
1349 {"firmware", 0x20000, 0xd70000},
1350 {"partition-table", 0xd90000, 0x02000},
1351 {"default-mac", 0xda0000, 0x00020},
1352 {"pin", 0xda0100, 0x00020},
1353 {"product-info", 0xda1100, 0x01000},
1354 {"soft-version", 0xdb0000, 0x01000},
1355 {"support-list", 0xdb1000, 0x01000},
1356 {"profile", 0xdb2000, 0x08000},
1357 {"user-config", 0xdc0000, 0x10000},
1358 {"default-config", 0xdd0000, 0x10000},
1359 {"device-id", 0xde0000, 0x00108},
1360 {"radio", 0xff0000, 0x10000},
1364 .first_sysupgrade_partition
= "os-image",
1365 .last_sysupgrade_partition
= "file-system"
1368 /** Firmware layout for the RE355 */
1374 "{product_name:RE355,product_ver:1.0.0,special_id:00000000}\r\n"
1375 "{product_name:RE355,product_ver:1.0.0,special_id:55530000}\r\n"
1376 "{product_name:RE355,product_ver:1.0.0,special_id:45550000}\r\n"
1377 "{product_name:RE355,product_ver:1.0.0,special_id:4A500000}\r\n"
1378 "{product_name:RE355,product_ver:1.0.0,special_id:43410000}\r\n"
1379 "{product_name:RE355,product_ver:1.0.0,special_id:41550000}\r\n"
1380 "{product_name:RE355,product_ver:1.0.0,special_id:4B520000}\r\n"
1381 "{product_name:RE355,product_ver:1.0.0,special_id:55534100}\r\n",
1382 .support_trail
= '\x00',
1385 /* We're using a dynamic kernel/rootfs split here */
1387 {"fs-uboot", 0x00000, 0x20000},
1388 {"firmware", 0x20000, 0x5e0000},
1389 {"partition-table", 0x600000, 0x02000},
1390 {"default-mac", 0x610000, 0x00020},
1391 {"pin", 0x610100, 0x00020},
1392 {"product-info", 0x611100, 0x01000},
1393 {"soft-version", 0x620000, 0x01000},
1394 {"support-list", 0x621000, 0x01000},
1395 {"profile", 0x622000, 0x08000},
1396 {"user-config", 0x630000, 0x10000},
1397 {"default-config", 0x640000, 0x10000},
1398 {"radio", 0x7f0000, 0x10000},
1402 .first_sysupgrade_partition
= "os-image",
1403 .last_sysupgrade_partition
= "file-system"
1406 /** Firmware layout for the RE450 */
1412 "{product_name:RE450,product_ver:1.0.0,special_id:00000000}\r\n"
1413 "{product_name:RE450,product_ver:1.0.0,special_id:55530000}\r\n"
1414 "{product_name:RE450,product_ver:1.0.0,special_id:45550000}\r\n"
1415 "{product_name:RE450,product_ver:1.0.0,special_id:4A500000}\r\n"
1416 "{product_name:RE450,product_ver:1.0.0,special_id:43410000}\r\n"
1417 "{product_name:RE450,product_ver:1.0.0,special_id:41550000}\r\n"
1418 "{product_name:RE450,product_ver:1.0.0,special_id:4B520000}\r\n"
1419 "{product_name:RE450,product_ver:1.0.0,special_id:55534100}\r\n",
1420 .support_trail
= '\x00',
1423 /** We're using a dynamic kernel/rootfs split here */
1425 {"fs-uboot", 0x00000, 0x20000},
1426 {"firmware", 0x20000, 0x5e0000},
1427 {"partition-table", 0x600000, 0x02000},
1428 {"default-mac", 0x610000, 0x00020},
1429 {"pin", 0x610100, 0x00020},
1430 {"product-info", 0x611100, 0x01000},
1431 {"soft-version", 0x620000, 0x01000},
1432 {"support-list", 0x621000, 0x01000},
1433 {"profile", 0x622000, 0x08000},
1434 {"user-config", 0x630000, 0x10000},
1435 {"default-config", 0x640000, 0x10000},
1436 {"radio", 0x7f0000, 0x10000},
1440 .first_sysupgrade_partition
= "os-image",
1441 .last_sysupgrade_partition
= "file-system"
1444 /** Firmware layout for the RE450 v2 */
1450 "{product_name:RE450,product_ver:2.0.0,special_id:00000000}\r\n"
1451 "{product_name:RE450,product_ver:2.0.0,special_id:55530000}\r\n"
1452 "{product_name:RE450,product_ver:2.0.0,special_id:45550000}\r\n"
1453 "{product_name:RE450,product_ver:2.0.0,special_id:4A500000}\r\n"
1454 "{product_name:RE450,product_ver:2.0.0,special_id:43410000}\r\n"
1455 "{product_name:RE450,product_ver:2.0.0,special_id:41550000}\r\n"
1456 "{product_name:RE450,product_ver:2.0.0,special_id:41530000}\r\n"
1457 "{product_name:RE450,product_ver:2.0.0,special_id:4B520000}\r\n"
1458 "{product_name:RE450,product_ver:2.0.0,special_id:42520000}\r\n",
1459 .support_trail
= '\x00',
1462 /* We're using a dynamic kernel/rootfs split here */
1464 {"fs-uboot", 0x00000, 0x20000},
1465 {"firmware", 0x20000, 0x5e0000},
1466 {"partition-table", 0x600000, 0x02000},
1467 {"default-mac", 0x610000, 0x00020},
1468 {"pin", 0x610100, 0x00020},
1469 {"product-info", 0x611100, 0x01000},
1470 {"soft-version", 0x620000, 0x01000},
1471 {"support-list", 0x621000, 0x01000},
1472 {"profile", 0x622000, 0x08000},
1473 {"user-config", 0x630000, 0x10000},
1474 {"default-config", 0x640000, 0x10000},
1475 {"radio", 0x7f0000, 0x10000},
1480 .first_sysupgrade_partition
= "os-image",
1481 .last_sysupgrade_partition
= "file-system"
1484 /** Firmware layout for the RE650 */
1490 "{product_name:RE650,product_ver:1.0.0,special_id:00000000}\r\n"
1491 "{product_name:RE650,product_ver:1.0.0,special_id:55530000}\r\n"
1492 "{product_name:RE650,product_ver:1.0.0,special_id:45550000}\r\n"
1493 "{product_name:RE650,product_ver:1.0.0,special_id:4A500000}\r\n"
1494 "{product_name:RE650,product_ver:1.0.0,special_id:43410000}\r\n"
1495 "{product_name:RE650,product_ver:1.0.0,special_id:41550000}\r\n"
1496 "{product_name:RE650,product_ver:1.0.0,special_id:41530000}\r\n",
1497 .support_trail
= '\x00',
1500 /* We're using a dynamic kernel/rootfs split here */
1502 {"fs-uboot", 0x00000, 0x20000},
1503 {"firmware", 0x20000, 0xde0000},
1504 {"partition-table", 0xe00000, 0x02000},
1505 {"default-mac", 0xe10000, 0x00020},
1506 {"pin", 0xe10100, 0x00020},
1507 {"product-info", 0xe11100, 0x01000},
1508 {"soft-version", 0xe20000, 0x01000},
1509 {"support-list", 0xe21000, 0x01000},
1510 {"profile", 0xe22000, 0x08000},
1511 {"user-config", 0xe30000, 0x10000},
1512 {"default-config", 0xe40000, 0x10000},
1513 {"radio", 0xff0000, 0x10000},
1517 .first_sysupgrade_partition
= "os-image",
1518 .last_sysupgrade_partition
= "file-system"
1524 #define error(_ret, _errno, _str, ...) \
1526 fprintf(stderr, _str ": %s\n", ## __VA_ARGS__, \
1527 strerror(_errno)); \
1533 /** Stores a uint32 as big endian */
1534 static inline void put32(uint8_t *buf
, uint32_t val
) {
1541 /** Allocates a new image partition */
1542 static struct image_partition_entry
alloc_image_partition(const char *name
, size_t len
) {
1543 struct image_partition_entry entry
= {name
, len
, malloc(len
)};
1545 error(1, errno
, "malloc");
1550 /** Frees an image partition */
1551 static void free_image_partition(struct image_partition_entry entry
) {
1555 static time_t source_date_epoch
= -1;
1556 static void set_source_date_epoch() {
1557 char *env
= getenv("SOURCE_DATE_EPOCH");
1561 source_date_epoch
= strtoull(env
, &endptr
, 10);
1562 if (errno
|| (endptr
&& *endptr
!= '\0')) {
1563 fprintf(stderr
, "Invalid SOURCE_DATE_EPOCH");
1569 /** Generates the partition-table partition */
1570 static struct image_partition_entry
make_partition_table(const struct flash_partition_entry
*p
) {
1571 struct image_partition_entry entry
= alloc_image_partition("partition-table", 0x800);
1573 char *s
= (char *)entry
.data
, *end
= (char *)(s
+entry
.size
);
1581 for (i
= 0; p
[i
].name
; i
++) {
1583 size_t w
= snprintf(s
, len
, "partition %s base 0x%05x size 0x%05x\n", p
[i
].name
, p
[i
].base
, p
[i
].size
);
1586 error(1, 0, "flash partition table overflow?");
1593 memset(s
, 0xff, end
-s
);
1599 /** Generates a binary-coded decimal representation of an integer in the range [0, 99] */
1600 static inline uint8_t bcd(uint8_t v
) {
1601 return 0x10 * (v
/10) + v
%10;
1605 /** Generates the soft-version partition */
1606 static struct image_partition_entry
make_soft_version(uint32_t rev
) {
1607 struct image_partition_entry entry
= alloc_image_partition("soft-version", sizeof(struct soft_version
));
1608 struct soft_version
*s
= (struct soft_version
*)entry
.data
;
1612 if (source_date_epoch
!= -1)
1613 t
= source_date_epoch
;
1614 else if (time(&t
) == (time_t)(-1))
1615 error(1, errno
, "time");
1617 struct tm
*tm
= localtime(&t
);
1619 s
->magic
= htonl(0x0000000c);
1623 s
->version_major
= 0;
1624 s
->version_minor
= 0;
1625 s
->version_patch
= 0;
1627 s
->year_hi
= bcd((1900+tm
->tm_year
)/100);
1628 s
->year_lo
= bcd(tm
->tm_year
%100);
1629 s
->month
= bcd(tm
->tm_mon
+1);
1630 s
->day
= bcd(tm
->tm_mday
);
1631 s
->rev
= htonl(rev
);
1638 static struct image_partition_entry
make_soft_version_from_string(const char *soft_ver
) {
1639 /** String length _including_ the terminating zero byte */
1640 uint32_t ver_len
= strlen(soft_ver
) + 1;
1641 /** Partition contains 64 bit header, the version string, and one additional null byte */
1642 size_t partition_len
= 2*sizeof(uint32_t) + ver_len
+ 1;
1643 struct image_partition_entry entry
= alloc_image_partition("soft-version", partition_len
);
1645 uint32_t *len
= (uint32_t *)entry
.data
;
1646 len
[0] = htonl(ver_len
);
1648 memcpy(&len
[2], soft_ver
, ver_len
);
1650 entry
.data
[partition_len
- 1] = 0;
1655 /** Generates the support-list partition */
1656 static struct image_partition_entry
make_support_list(struct device_info
*info
) {
1657 size_t len
= strlen(info
->support_list
);
1658 struct image_partition_entry entry
= alloc_image_partition("support-list", len
+ 9);
1660 put32(entry
.data
, len
);
1661 memset(entry
.data
+4, 0, 4);
1662 memcpy(entry
.data
+8, info
->support_list
, len
);
1663 entry
.data
[len
+8] = info
->support_trail
;
1668 /** Creates a new image partition with an arbitrary name from a file */
1669 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
) {
1670 struct stat statbuf
;
1672 if (stat(filename
, &statbuf
) < 0)
1673 error(1, errno
, "unable to stat file `%s'", filename
);
1675 size_t len
= statbuf
.st_size
;
1677 if (add_jffs2_eof
) {
1678 if (file_system_partition
)
1679 len
= ALIGN(len
+ file_system_partition
->base
, 0x10000) + sizeof(jffs2_eof_mark
) - file_system_partition
->base
;
1681 len
= ALIGN(len
, 0x10000) + sizeof(jffs2_eof_mark
);
1684 struct image_partition_entry entry
= alloc_image_partition(part_name
, len
);
1686 FILE *file
= fopen(filename
, "rb");
1688 error(1, errno
, "unable to open file `%s'", filename
);
1690 if (fread(entry
.data
, statbuf
.st_size
, 1, file
) != 1)
1691 error(1, errno
, "unable to read file `%s'", filename
);
1693 if (add_jffs2_eof
) {
1694 uint8_t *eof
= entry
.data
+ statbuf
.st_size
, *end
= entry
.data
+entry
.size
;
1696 memset(eof
, 0xff, end
- eof
- sizeof(jffs2_eof_mark
));
1697 memcpy(end
- sizeof(jffs2_eof_mark
), jffs2_eof_mark
, sizeof(jffs2_eof_mark
));
1705 /** Creates a new image partition from arbitrary data */
1706 static struct image_partition_entry
put_data(const char *part_name
, const char *datain
, size_t len
) {
1708 struct image_partition_entry entry
= alloc_image_partition(part_name
, len
);
1710 memcpy(entry
.data
, datain
, len
);
1716 Copies a list of image partitions into an image buffer and generates the image partition table while doing so
1718 Example image partition table:
1720 fwup-ptn partition-table base 0x00800 size 0x00800
1721 fwup-ptn os-image base 0x01000 size 0x113b45
1722 fwup-ptn file-system base 0x114b45 size 0x1d0004
1723 fwup-ptn support-list base 0x2e4b49 size 0x000d1
1725 Each line of the partition table is terminated with the bytes 09 0d 0a ("\t\r\n"),
1726 the end of the partition table is marked with a zero byte.
1728 The firmware image must contain at least the partition-table and support-list partitions
1729 to be accepted. There aren't any alignment constraints for the image partitions.
1731 The partition-table partition contains the actual flash layout; partitions
1732 from the image partition table are mapped to the corresponding flash partitions during
1733 the firmware upgrade. The support-list partition contains a list of devices supported by
1736 The base offsets in the firmware partition table are relative to the end
1737 of the vendor information block, so the partition-table partition will
1738 actually start at offset 0x1814 of the image.
1740 I think partition-table must be the first partition in the firmware image.
1742 static void put_partitions(uint8_t *buffer
, const struct flash_partition_entry
*flash_parts
, const struct image_partition_entry
*parts
) {
1744 char *image_pt
= (char *)buffer
, *end
= image_pt
+ 0x800;
1746 size_t base
= 0x800;
1747 for (i
= 0; parts
[i
].name
; i
++) {
1748 for (j
= 0; flash_parts
[j
].name
; j
++) {
1749 if (!strcmp(flash_parts
[j
].name
, parts
[i
].name
)) {
1750 if (parts
[i
].size
> flash_parts
[j
].size
)
1751 error(1, 0, "%s partition too big (more than %u bytes)", flash_parts
[j
].name
, (unsigned)flash_parts
[j
].size
);
1756 assert(flash_parts
[j
].name
);
1758 memcpy(buffer
+ base
, parts
[i
].data
, parts
[i
].size
);
1760 size_t len
= end
-image_pt
;
1761 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
);
1764 error(1, 0, "image partition table overflow?");
1768 base
+= parts
[i
].size
;
1772 /** Generates and writes the image MD5 checksum */
1773 static void put_md5(uint8_t *md5
, uint8_t *buffer
, unsigned int len
) {
1777 MD5_Update(&ctx
, md5_salt
, (unsigned int)sizeof(md5_salt
));
1778 MD5_Update(&ctx
, buffer
, len
);
1779 MD5_Final(md5
, &ctx
);
1784 Generates the firmware image in factory format
1790 0000-0003 Image size (4 bytes, big endian)
1791 0004-0013 MD5 hash (hash of a 16 byte salt and the image data starting with byte 0x14)
1792 0014-0017 Vendor information length (without padding) (4 bytes, big endian)
1793 0018-1013 Vendor information (4092 bytes, padded with 0xff; there seem to be older
1794 (VxWorks-based) TP-LINK devices which use a smaller vendor information block)
1795 1014-1813 Image partition table (2048 bytes, padded with 0xff)
1796 1814-xxxx Firmware partitions
1798 static void * generate_factory_image(struct device_info
*info
, const struct image_partition_entry
*parts
, size_t *len
) {
1802 for (i
= 0; parts
[i
].name
; i
++)
1803 *len
+= parts
[i
].size
;
1805 uint8_t *image
= malloc(*len
);
1807 error(1, errno
, "malloc");
1809 memset(image
, 0xff, *len
);
1813 size_t vendor_len
= strlen(info
->vendor
);
1814 put32(image
+0x14, vendor_len
);
1815 memcpy(image
+0x18, info
->vendor
, vendor_len
);
1818 put_partitions(image
+ 0x1014, info
->partitions
, parts
);
1819 put_md5(image
+0x04, image
+0x14, *len
-0x14);
1825 Generates the firmware image in sysupgrade format
1827 This makes some assumptions about the provided flash and image partition tables and
1828 should be generalized when TP-LINK starts building its safeloader into hardware with
1829 different flash layouts.
1831 static void * generate_sysupgrade_image(struct device_info
*info
, const struct image_partition_entry
*image_parts
, size_t *len
) {
1833 size_t flash_first_partition_index
= 0;
1834 size_t flash_last_partition_index
= 0;
1835 const struct flash_partition_entry
*flash_first_partition
= NULL
;
1836 const struct flash_partition_entry
*flash_last_partition
= NULL
;
1837 const struct image_partition_entry
*image_last_partition
= NULL
;
1839 /** Find first and last partitions */
1840 for (i
= 0; info
->partitions
[i
].name
; i
++) {
1841 if (!strcmp(info
->partitions
[i
].name
, info
->first_sysupgrade_partition
)) {
1842 flash_first_partition
= &info
->partitions
[i
];
1843 flash_first_partition_index
= i
;
1844 } else if (!strcmp(info
->partitions
[i
].name
, info
->last_sysupgrade_partition
)) {
1845 flash_last_partition
= &info
->partitions
[i
];
1846 flash_last_partition_index
= i
;
1850 assert(flash_first_partition
&& flash_last_partition
);
1851 assert(flash_first_partition_index
< flash_last_partition_index
);
1853 /** Find last partition from image to calculate needed size */
1854 for (i
= 0; image_parts
[i
].name
; i
++) {
1855 if (!strcmp(image_parts
[i
].name
, info
->last_sysupgrade_partition
)) {
1856 image_last_partition
= &image_parts
[i
];
1861 assert(image_last_partition
);
1863 *len
= flash_last_partition
->base
- flash_first_partition
->base
+ image_last_partition
->size
;
1865 uint8_t *image
= malloc(*len
);
1867 error(1, errno
, "malloc");
1869 memset(image
, 0xff, *len
);
1871 for (i
= flash_first_partition_index
; i
<= flash_last_partition_index
; i
++) {
1872 for (j
= 0; image_parts
[j
].name
; j
++) {
1873 if (!strcmp(info
->partitions
[i
].name
, image_parts
[j
].name
)) {
1874 if (image_parts
[j
].size
> info
->partitions
[i
].size
)
1875 error(1, 0, "%s partition too big (more than %u bytes)", info
->partitions
[i
].name
, (unsigned)info
->partitions
[i
].size
);
1876 memcpy(image
+ info
->partitions
[i
].base
- flash_first_partition
->base
, image_parts
[j
].data
, image_parts
[j
].size
);
1880 assert(image_parts
[j
].name
);
1887 /** Generates an image according to a given layout and writes it to a file */
1888 static void build_image(const char *output
,
1889 const char *kernel_image
,
1890 const char *rootfs_image
,
1894 struct device_info
*info
) {
1898 struct image_partition_entry parts
[7] = {};
1900 struct flash_partition_entry
*firmware_partition
= NULL
;
1901 struct flash_partition_entry
*os_image_partition
= NULL
;
1902 struct flash_partition_entry
*file_system_partition
= NULL
;
1903 size_t firmware_partition_index
= 0;
1905 for (i
= 0; info
->partitions
[i
].name
; i
++) {
1906 if (!strcmp(info
->partitions
[i
].name
, "firmware"))
1908 firmware_partition
= &info
->partitions
[i
];
1909 firmware_partition_index
= i
;
1913 if (firmware_partition
)
1915 os_image_partition
= &info
->partitions
[firmware_partition_index
];
1916 file_system_partition
= &info
->partitions
[firmware_partition_index
+ 1];
1919 if (stat(kernel_image
, &kernel
) < 0)
1920 error(1, errno
, "unable to stat file `%s'", kernel_image
);
1922 if (kernel
.st_size
> firmware_partition
->size
)
1923 error(1, 0, "kernel overflowed firmware partition\n");
1925 for (i
= MAX_PARTITIONS
-1; i
>= firmware_partition_index
+ 1; i
--)
1926 info
->partitions
[i
+1] = info
->partitions
[i
];
1928 file_system_partition
->name
= "file-system";
1929 file_system_partition
->base
= firmware_partition
->base
+ kernel
.st_size
;
1931 /* Align partition start to erase blocks for factory images only */
1933 file_system_partition
->base
= ALIGN(firmware_partition
->base
+ kernel
.st_size
, 0x10000);
1935 file_system_partition
->size
= firmware_partition
->size
- file_system_partition
->base
;
1937 os_image_partition
->name
= "os-image";
1938 os_image_partition
->size
= kernel
.st_size
;
1941 parts
[0] = make_partition_table(info
->partitions
);
1943 parts
[1] = make_soft_version_from_string(info
->soft_ver
);
1945 parts
[1] = make_soft_version(rev
);
1947 parts
[2] = make_support_list(info
);
1948 parts
[3] = read_file("os-image", kernel_image
, false, NULL
);
1949 parts
[4] = read_file("file-system", rootfs_image
, add_jffs2_eof
, file_system_partition
);
1951 /* Some devices need the extra-para partition to accept the firmware */
1952 if (strcasecmp(info
->id
, "ARCHER-C2-V3") == 0 ||
1953 strcasecmp(info
->id
, "ARCHER-C25-V1") == 0 ||
1954 strcasecmp(info
->id
, "ARCHER-C59-V2") == 0 ||
1955 strcasecmp(info
->id
, "ARCHER-C60-V2") == 0 ||
1956 strcasecmp(info
->id
, "TLWR1043NV5") == 0) {
1957 const char mdat
[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
1958 parts
[5] = put_data("extra-para", mdat
, 11);
1959 } else if (strcasecmp(info
->id
, "ARCHER-A7-V5") == 0 || strcasecmp(info
->id
, "ARCHER-C7-V4") == 0 || strcasecmp(info
->id
, "ARCHER-C7-V5") == 0) {
1960 const char mdat
[11] = {0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x01, 0x00, 0x00};
1961 parts
[5] = put_data("extra-para", mdat
, 11);
1962 } else if (strcasecmp(info
->id
, "ARCHER-C6-V2") == 0) {
1963 const char mdat
[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
1964 parts
[5] = put_data("extra-para", mdat
, 11);
1970 image
= generate_sysupgrade_image(info
, parts
, &len
);
1972 image
= generate_factory_image(info
, parts
, &len
);
1974 FILE *file
= fopen(output
, "wb");
1976 error(1, errno
, "unable to open output file");
1978 if (fwrite(image
, len
, 1, file
) != 1)
1979 error(1, 0, "unable to write output file");
1985 for (i
= 0; parts
[i
].name
; i
++)
1986 free_image_partition(parts
[i
]);
1990 static void usage(const char *argv0
) {
1992 "Usage: %s [OPTIONS...]\n"
1995 " -h show this help\n"
1997 "Create a new image:\n"
1998 " -B <board> create image for the board specified with <board>\n"
1999 " -k <file> read kernel image from the file <file>\n"
2000 " -r <file> read rootfs image from the file <file>\n"
2001 " -o <file> write output to the file <file>\n"
2002 " -V <rev> sets the revision number to <rev>\n"
2003 " -j add jffs2 end-of-filesystem markers\n"
2004 " -S create sysupgrade instead of factory image\n"
2005 "Extract an old image:\n"
2006 " -x <file> extract all oem firmware partition\n"
2007 " -d <dir> destination to extract the firmware partition\n"
2008 " -z <file> convert an oem firmware into a sysupgade file. Use -o for output file\n",
2014 static struct device_info
*find_board(const char *id
)
2016 struct device_info
*board
= NULL
;
2018 for (board
= boards
; board
->id
!= NULL
; board
++)
2019 if (strcasecmp(id
, board
->id
) == 0)
2025 static int add_flash_partition(
2026 struct flash_partition_entry
*part_list
,
2033 /* check if the list has a free entry */
2034 for (ptr
= 0; ptr
< max_entries
; ptr
++, part_list
++) {
2035 if (part_list
->name
== NULL
&&
2036 part_list
->base
== 0 &&
2037 part_list
->size
== 0)
2041 if (ptr
== max_entries
) {
2042 error(1, 0, "No free flash part entry available.");
2045 part_list
->name
= calloc(1, strlen(name
) + 1);
2046 if (!part_list
->name
) {
2047 error(1, 0, "Unable to allocate memory");
2050 memcpy((char *)part_list
->name
, name
, strlen(name
));
2051 part_list
->base
= base
;
2052 part_list
->size
= size
;
2057 /** read the partition table into struct flash_partition_entry */
2058 static int read_partition_table(
2059 FILE *file
, long offset
,
2060 struct flash_partition_entry
*entries
, size_t max_entries
,
2065 const char *parthdr
= NULL
;
2066 const char *fwuphdr
= "fwup-ptn";
2067 const char *flashhdr
= "partition";
2069 /* TODO: search for the partition table */
2079 error(1, 0, "Invalid partition table");
2082 if (fseek(file
, offset
, SEEK_SET
) < 0)
2083 error(1, errno
, "Can not seek in the firmware");
2085 if (fread(buf
, 2048, 1, file
) != 1)
2086 error(1, errno
, "Can not read fwup-ptn from the firmware");
2090 /* look for the partition header */
2091 if (memcmp(buf
, parthdr
, strlen(parthdr
)) != 0) {
2092 fprintf(stderr
, "DEBUG: can not find fwuphdr\n");
2097 end
= buf
+ sizeof(buf
);
2098 while ((ptr
+ strlen(parthdr
)) < end
&&
2099 memcmp(ptr
, parthdr
, strlen(parthdr
)) == 0) {
2103 char name
[32] = { 0 };
2105 unsigned long base
= 0;
2106 unsigned long size
= 0;
2108 end_part
= memchr(ptr
, '\n', (end
- ptr
));
2109 if (end_part
== NULL
) {
2110 /* in theory this should never happen, because a partition always ends with 0x09, 0x0D, 0x0A */
2114 for (int i
= 0; i
<= 4; i
++) {
2115 if (end_part
<= ptr
)
2118 end_element
= memchr(ptr
, 0x20, (end_part
- ptr
));
2119 if (end_element
== NULL
) {
2120 error(1, errno
, "Ignoring the rest of the partition entries.");
2125 /* partition header */
2127 ptr
= end_element
+ 1;
2131 name_len
= (end_element
- ptr
) > 31 ? 31 : (end_element
- ptr
);
2132 strncpy(name
, ptr
, name_len
);
2133 name
[name_len
] = '\0';
2134 ptr
= end_element
+ 1;
2139 ptr
= end_element
+ 1;
2144 base
= strtoul(ptr
, NULL
, 16);
2145 ptr
= end_element
+ 1;
2150 ptr
= end_element
+ 1;
2151 /* actual size. The last element doesn't have a sepeartor */
2152 size
= strtoul(ptr
, NULL
, 16);
2153 /* the part ends with 0x09, 0x0d, 0x0a */
2155 add_flash_partition(entries
, max_entries
, name
, base
, size
);
2164 static void write_partition(
2166 size_t firmware_offset
,
2167 struct flash_partition_entry
*entry
,
2173 fseek(input_file
, entry
->base
+ firmware_offset
, SEEK_SET
);
2175 for (offset
= 0; sizeof(buf
) + offset
<= entry
->size
; offset
+= sizeof(buf
)) {
2176 if (fread(buf
, sizeof(buf
), 1, input_file
) != 1)
2177 error(1, errno
, "Can not read partition from input_file");
2179 if (fwrite(buf
, sizeof(buf
), 1, output_file
) != 1)
2180 error(1, errno
, "Can not write partition to output_file");
2182 /* write last chunk smaller than buffer */
2183 if (offset
< entry
->size
) {
2184 offset
= entry
->size
- offset
;
2185 if (fread(buf
, offset
, 1, input_file
) != 1)
2186 error(1, errno
, "Can not read partition from input_file");
2187 if (fwrite(buf
, offset
, 1, output_file
) != 1)
2188 error(1, errno
, "Can not write partition to output_file");
2192 static int extract_firmware_partition(FILE *input_file
, size_t firmware_offset
, struct flash_partition_entry
*entry
, const char *output_directory
)
2195 char output
[PATH_MAX
];
2197 snprintf(output
, PATH_MAX
, "%s/%s", output_directory
, entry
->name
);
2198 output_file
= fopen(output
, "wb+");
2199 if (output_file
== NULL
) {
2200 error(1, errno
, "Can not open output file %s", output
);
2203 write_partition(input_file
, firmware_offset
, entry
, output_file
);
2205 fclose(output_file
);
2210 /** extract all partitions from the firmware file */
2211 static int extract_firmware(const char *input
, const char *output_directory
)
2213 struct flash_partition_entry entries
[16] = { 0 };
2214 size_t max_entries
= 16;
2215 size_t firmware_offset
= 0x1014;
2218 struct stat statbuf
;
2220 /* check input file */
2221 if (stat(input
, &statbuf
)) {
2222 error(1, errno
, "Can not read input firmware %s", input
);
2225 /* check if output directory exists */
2226 if (stat(output_directory
, &statbuf
)) {
2227 error(1, errno
, "Failed to stat output directory %s", output_directory
);
2230 if ((statbuf
.st_mode
& S_IFMT
) != S_IFDIR
) {
2231 error(1, errno
, "Given output directory is not a directory %s", output_directory
);
2234 input_file
= fopen(input
, "rb");
2236 if (read_partition_table(input_file
, firmware_offset
, entries
, 16, 0) != 0) {
2237 error(1, 0, "Error can not read the partition table (fwup-ptn)");
2240 for (size_t i
= 0; i
< max_entries
; i
++) {
2241 if (entries
[i
].name
== NULL
&&
2242 entries
[i
].base
== 0 &&
2243 entries
[i
].size
== 0)
2246 extract_firmware_partition(input_file
, firmware_offset
, &entries
[i
], output_directory
);
2252 static struct flash_partition_entry
*find_partition(
2253 struct flash_partition_entry
*entries
, size_t max_entries
,
2254 const char *name
, const char *error_msg
)
2256 for (size_t i
= 0; i
< max_entries
; i
++, entries
++) {
2257 if (strcmp(entries
->name
, name
) == 0)
2261 error(1, 0, "%s", error_msg
);
2265 static void write_ff(FILE *output_file
, size_t size
)
2270 memset(buf
, 0xff, sizeof(buf
));
2272 for (offset
= 0; offset
+ sizeof(buf
) < size
; offset
+= sizeof(buf
)) {
2273 if (fwrite(buf
, sizeof(buf
), 1, output_file
) != 1)
2274 error(1, errno
, "Can not write 0xff to output_file");
2277 /* write last chunk smaller than buffer */
2278 if (offset
< size
) {
2279 offset
= size
- offset
;
2280 if (fwrite(buf
, offset
, 1, output_file
) != 1)
2281 error(1, errno
, "Can not write partition to output_file");
2285 static void convert_firmware(const char *input
, const char *output
)
2287 struct flash_partition_entry fwup
[MAX_PARTITIONS
] = { 0 };
2288 struct flash_partition_entry flash
[MAX_PARTITIONS
] = { 0 };
2289 struct flash_partition_entry
*fwup_os_image
= NULL
, *fwup_file_system
= NULL
;
2290 struct flash_partition_entry
*flash_os_image
= NULL
, *flash_file_system
= NULL
;
2291 struct flash_partition_entry
*fwup_partition_table
= NULL
;
2292 size_t firmware_offset
= 0x1014;
2293 FILE *input_file
, *output_file
;
2295 struct stat statbuf
;
2297 /* check input file */
2298 if (stat(input
, &statbuf
)) {
2299 error(1, errno
, "Can not read input firmware %s", input
);
2302 input_file
= fopen(input
, "rb");
2304 error(1, 0, "Can not open input firmware %s", input
);
2306 output_file
= fopen(output
, "wb");
2308 error(1, 0, "Can not open output firmware %s", output
);
2310 if (read_partition_table(input_file
, firmware_offset
, fwup
, MAX_PARTITIONS
, 0) != 0) {
2311 error(1, 0, "Error can not read the partition table (fwup-ptn)");
2314 fwup_os_image
= find_partition(fwup
, MAX_PARTITIONS
,
2315 "os-image", "Error can not find os-image partition (fwup)");
2316 fwup_file_system
= find_partition(fwup
, MAX_PARTITIONS
,
2317 "file-system", "Error can not find file-system partition (fwup)");
2318 fwup_partition_table
= find_partition(fwup
, MAX_PARTITIONS
,
2319 "partition-table", "Error can not find partition-table partition");
2321 /* the flash partition table has a 0x00000004 magic haeder */
2322 if (read_partition_table(input_file
, firmware_offset
+ fwup_partition_table
->base
+ 4, flash
, MAX_PARTITIONS
, 1) != 0)
2323 error(1, 0, "Error can not read the partition table (flash)");
2325 flash_os_image
= find_partition(flash
, MAX_PARTITIONS
,
2326 "os-image", "Error can not find os-image partition (flash)");
2327 flash_file_system
= find_partition(flash
, MAX_PARTITIONS
,
2328 "file-system", "Error can not find file-system partition (flash)");
2330 /* write os_image to 0x0 */
2331 write_partition(input_file
, firmware_offset
, fwup_os_image
, output_file
);
2332 write_ff(output_file
, flash_os_image
->size
- fwup_os_image
->size
);
2334 /* write file-system behind os_image */
2335 fseek(output_file
, flash_file_system
->base
- flash_os_image
->base
, SEEK_SET
);
2336 write_partition(input_file
, firmware_offset
, fwup_file_system
, output_file
);
2337 write_ff(output_file
, flash_file_system
->size
- fwup_file_system
->size
);
2339 fclose(output_file
);
2343 int main(int argc
, char *argv
[]) {
2344 const char *board
= NULL
, *kernel_image
= NULL
, *rootfs_image
= NULL
, *output
= NULL
;
2345 const char *extract_image
= NULL
, *output_directory
= NULL
, *convert_image
= NULL
;
2346 bool add_jffs2_eof
= false, sysupgrade
= false;
2348 struct device_info
*info
;
2349 set_source_date_epoch();
2354 c
= getopt(argc
, argv
, "B:k:r:o:V:jSh:x:d:z:");
2364 kernel_image
= optarg
;
2368 rootfs_image
= optarg
;
2376 sscanf(optarg
, "r%u", &rev
);
2380 add_jffs2_eof
= true;
2392 output_directory
= optarg
;
2396 extract_image
= optarg
;
2400 convert_image
= optarg
;
2409 if (extract_image
|| output_directory
) {
2411 error(1, 0, "No factory/oem image given via -x <file>. Output directory is only valid with -x");
2412 if (!output_directory
)
2413 error(1, 0, "Can not extract an image without output directory. Use -d <dir>");
2414 extract_firmware(extract_image
, output_directory
);
2415 } else if (convert_image
) {
2417 error(1, 0, "Can not convert a factory/oem image into sysupgrade image without output file. Use -o <file>");
2418 convert_firmware(convert_image
, output
);
2421 error(1, 0, "no board has been specified");
2423 error(1, 0, "no kernel image has been specified");
2425 error(1, 0, "no rootfs image has been specified");
2427 error(1, 0, "no output filename has been specified");
2429 info
= find_board(board
);
2432 error(1, 0, "unsupported board %s", board
);
2434 build_image(output
, kernel_image
, rootfs_image
, rev
, add_jffs2_eof
, sysupgrade
, info
);