4 * Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
6 * This tool is based on mktplinkfw.
7 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
8 * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
20 #include <unistd.h> /* for unlink() */
22 #include <getopt.h> /* for getopt() */
28 #include <zlib.h> /*for crc32 */
30 #include "mkdlinkfw-lib.h"
32 /* ARM update header 2.0
33 * used only in factory images to erase and flash selected area
36 uint8_t rom_id
[12]; /* 12-bit rom-id unique per router type */
37 uint16_t derange
; /* used for scramble header */
38 uint16_t image_checksum
; /* jboot_checksum of flashed data */
40 uint32_t space1
; /* zeros */
41 uint32_t space2
; /* zeros */
42 uint16_t space3
; /* zerosu */
43 uint8_t lpvs
; /* must be 0x01 */
44 uint8_t mbz
; /* bust be 0 */
45 uint32_t time_stamp
; /* timestamp calculated in jboot way */
47 uint32_t erase_start
; /* erase start address */
48 uint32_t erase_length
; /* erase length address */
49 uint32_t data_offset
; /* data start address */
50 uint32_t data_length
; /* data length address */
52 uint32_t space4
; /* zeros */
53 uint32_t space5
; /* zeros */
54 uint32_t space6
; /* zeros */
55 uint32_t space7
; /* zeros */
57 uint16_t header_id
; /* magic 0x4842 */
58 uint16_t header_version
; /* 0x02 for 2.0 */
59 uint16_t space8
; /* zeros */
60 uint8_t section_id
; /* section id */
61 uint8_t image_info_type
; /* (?) 0x04 in factory images */
62 uint32_t image_info_offset
; /* (?) zeros in factory images */
63 uint16_t family_member
; /* unique per router type */
64 uint16_t header_checksum
; /* negated jboot_checksum of header data */
67 struct stag_header
{ /* used only of sch2 wrapped kernel data */
68 uint8_t cmark
; /* in factory 0xFF ,in sysuograde must be the same as id */
69 uint8_t id
; /* 0x04 */
70 uint16_t magic
; /* magic 0x2B24 */
71 uint32_t time_stamp
; /* timestamp calculated in jboot way */
72 uint32_t image_length
; /* lentgh of kernel + sch2 header */
73 uint16_t image_checksum
; /* negated jboot_checksum of sch2 + kernel */
74 uint16_t tag_checksum
; /* negated jboot_checksum of stag header data */
77 struct sch2_header
{ /* used only in kernel partitions */
78 uint16_t magic
; /* magic 0x2124 */
79 uint8_t cp_type
; /* 0x00 for flat, 0x01 for jz, 0x02 for gzip, 0x03 for lzma */
80 uint8_t version
; /* 0x02 for sch2 */
81 uint32_t ram_addr
; /* ram entry address */
82 uint32_t image_len
; /* kernel image length */
83 uint32_t image_crc32
; /* kernel image crc */
84 uint32_t start_addr
; /* ram start address */
85 uint32_t rootfs_addr
; /* rootfs flash address */
86 uint32_t rootfs_len
; /* rootfls length */
87 uint32_t rootfs_crc32
; /* rootfs crc32 */
88 uint32_t header_crc32
; /* sch2 header crc32, durring calculation this area is replaced by zero */
89 uint16_t header_length
; /* sch2 header length: 0x28 */
90 uint16_t cmd_line_length
; /* cmd line length, known zeros */
94 static struct file_info inspect_info
;
95 struct file_info kernel_info
;
96 struct file_info rootfs_info
;
97 struct file_info image_info
;
101 uint32_t firmware_size
;
102 uint16_t family_member
;
103 char *rom_id
[12] = { 0 };
106 static void usage(int status
)
108 fprintf(stderr
, "Usage: %s [OPTIONS...]\n", progname
);
112 " -i <file> inspect given firmware file <file>\n"
113 " -f set family member id (hexval prefixed with 0x)\n"
114 " -F <file> read image and convert it to FACTORY\n"
115 " -k <file> read kernel image from the file <file>\n"
116 " -r <file> read rootfs image from the file <file>\n"
117 " -o <file> write output to the file <file>\n"
118 " -s <size> set firmware partition size\n"
119 " -m <version> set rom id to <version> (12-bit string val: \"DLK*********\")\n"
120 " -h show this screen\n");
125 void print_auh_header(struct auh_header
*printed_header
)
127 printf("\trom_id: %s\n"
128 "\tderange: 0x%04X\n"
129 "\timage_checksum: 0x%04X\n"
135 "\ttime_stamp: 0x%08X\n"
136 "\terase_start: 0x%08X\n"
137 "\terase_length: 0x%08X\n"
138 "\tdata_offset: 0x%08X\n"
139 "\tdata_length: 0x%08X\n"
144 "\theader_id: 0x%04X\n"
145 "\theader_version: 0x%02X\n"
147 "\tsection_id: 0x%02X\n"
148 "\timage_info_type: 0x%02X\n"
149 "\timage_info_offset 0x%08X\n"
150 "\tfamily_member: 0x%04X\n"
151 "\theader_checksum: 0x%04X\n",
152 printed_header
->rom_id
,
153 printed_header
->derange
,
154 printed_header
->image_checksum
,
155 printed_header
->space1
,
156 printed_header
->space2
,
157 printed_header
->space3
,
158 printed_header
->lpvs
,
160 printed_header
->time_stamp
,
161 printed_header
->erase_start
,
162 printed_header
->erase_length
,
163 printed_header
->data_offset
,
164 printed_header
->data_length
,
165 printed_header
->space4
,
166 printed_header
->space5
,
167 printed_header
->space6
,
168 printed_header
->space7
,
169 printed_header
->header_id
,
170 printed_header
->header_version
,
171 printed_header
->space8
,
172 printed_header
->section_id
,
173 printed_header
->image_info_type
,
174 printed_header
->image_info_offset
,
175 printed_header
->family_member
, printed_header
->header_checksum
);
178 void print_stag_header(struct stag_header
*printed_header
)
180 printf("\tcmark: 0x%02X\n"
183 "\ttime_stamp: 0x%08X\n"
184 "\timage_length: 0x%04X\n"
185 "\timage_checksum: 0x%04X\n"
186 "\ttag_checksum: 0x%04X\n",
187 printed_header
->cmark
,
189 printed_header
->magic
,
190 printed_header
->time_stamp
,
191 printed_header
->image_length
,
192 printed_header
->image_checksum
, printed_header
->tag_checksum
);
195 void print_sch2_header(struct sch2_header
*printed_header
)
197 printf("\tmagic: 0x%04X\n"
198 "\tcp_type: 0x%02X\n"
199 "\tversion: 0x%02X\n"
200 "\tram_addr: 0x%08X\n"
201 "\timage_len: 0x%08X\n"
202 "\timage_crc32: 0x%08X\n"
203 "\tstart_addr: 0x%08X\n"
204 "\trootfs_addr: 0x%08X\n"
205 "\trootfs_len: 0x%08X\n"
206 "\trootfs_crc32: 0x%08X\n"
207 "\theader_crc32: 0x%08X\n"
208 "\theader_length: 0x%04X\n"
209 "\tcmd_line_length: 0x%04X\n",
210 printed_header
->magic
,
211 printed_header
->cp_type
,
212 printed_header
->version
,
213 printed_header
->ram_addr
,
214 printed_header
->image_len
,
215 printed_header
->image_crc32
,
216 printed_header
->start_addr
,
217 printed_header
->rootfs_addr
,
218 printed_header
->rootfs_len
,
219 printed_header
->rootfs_crc32
,
220 printed_header
->header_crc32
,
221 printed_header
->header_length
, printed_header
->cmd_line_length
);
224 static int find_auh_headers(char *buf
)
227 struct auh_header
*tmp_header
[MAX_HEADER_COUNTER
];
228 int header_counter
= 0;
230 int ret
= EXIT_FAILURE
;
232 while (tmp_buf
- buf
<= inspect_info
.file_size
- AUH_SIZE
) {
233 if (!memcmp(tmp_buf
, AUH_MAGIC
, 3)) {
234 if (((struct auh_header
*)tmp_buf
)->header_checksum
==
235 (uint16_t) ~jboot_checksum(0, (uint16_t *) tmp_buf
,
237 uint16_t checksum
= 0;
238 printf("Find proper AUH header at: 0x%lX!\n",
240 tmp_header
[header_counter
] =
241 (struct auh_header
*)tmp_buf
;
243 jboot_checksum(0, (uint16_t *) ((char *)
248 [header_counter
]->data_length
);
249 if (tmp_header
[header_counter
]->image_checksum
251 printf("Image checksum ok.\n");
253 ERR("Image checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", tmp_header
[header_counter
]->image_checksum
, checksum
);
255 if (header_counter
> MAX_HEADER_COUNTER
)
262 if (header_counter
== 0)
263 ERR("Can't find proper AUH header!\n");
264 else if (header_counter
> MAX_HEADER_COUNTER
)
265 ERR("To many AUH headers!\n");
267 for (int i
= 0; i
< header_counter
; i
++) {
268 printf("AUH %d:\n", i
);
269 print_auh_header(tmp_header
[i
]);
278 static int check_stag_header(char *buf
, struct stag_header
*header
)
281 int ret
= EXIT_FAILURE
;
283 uint8_t cmark_tmp
= header
->cmark
;
284 header
->cmark
= header
->id
;
286 if (header
->tag_checksum
==
287 (uint16_t) ~jboot_checksum(0, (uint16_t *) header
,
289 uint16_t checksum
= 0;
290 printf("Find proper STAG header at: 0x%lX!\n",
291 (char *)header
- buf
);
293 jboot_checksum(0, (uint16_t *) ((char *)header
+ STAG_SIZE
),
294 header
->image_length
);
295 if (header
->image_checksum
== checksum
) {
296 printf("Image checksum ok.\n");
297 header
->cmark
= cmark_tmp
;
298 print_stag_header(header
);
301 ERR("Image checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", header
->image_checksum
, checksum
);
303 ERR("STAG header checksum incorrect!");
305 header
->cmark
= cmark_tmp
;
309 static int check_sch2_header(char *buf
, struct sch2_header
*header
)
312 int ret
= EXIT_FAILURE
;
314 uint32_t crc32_tmp
= header
->header_crc32
;
315 header
->header_crc32
= 0;
317 if (crc32_tmp
== crc32(0, (uint8_t *) header
, header
->header_length
)) {
319 printf("Find proper SCH2 header at: 0x%lX!\n",
320 (char *)header
- buf
);
323 crc32(0, (uint8_t *) header
+ header
->header_length
,
325 if (header
->image_crc32
== crc32_val
) {
326 printf("Kernel checksum ok.\n");
328 header
->header_crc32
= crc32_tmp
;
329 print_sch2_header(header
);
332 ERR("Kernel checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", header
->image_crc32
, crc32_val
);
335 ERR("SCH2 header checksum incorrect!");
337 header
->header_crc32
= crc32_tmp
;
341 static int inspect_fw(void)
344 struct stag_header
*stag_header_kernel
;
345 struct sch2_header
*sch2_header_kernel
;
346 int ret
= EXIT_FAILURE
;
348 buf
= malloc(inspect_info
.file_size
);
350 ERR("no memory for buffer!\n");
354 ret
= read_to_buf(&inspect_info
, buf
);
358 ret
= find_auh_headers(buf
);
362 stag_header_kernel
= (struct stag_header
*)(buf
+ AUH_SIZE
);
364 ret
= check_stag_header(buf
, stag_header_kernel
);
368 sch2_header_kernel
= (struct sch2_header
*)(buf
+ AUH_SIZE
+ STAG_SIZE
);
370 ret
= check_sch2_header(buf
, sch2_header_kernel
);
380 static int check_options(void)
384 if (inspect_info
.file_name
) {
385 ret
= get_file_stat(&inspect_info
);
395 int fill_sch2(struct sch2_header
*header
, char *kernel_ptr
, char *rootfs_ptr
)
398 header
->magic
= SCH2_MAGIC
;
399 header
->cp_type
= LZMA
;
400 header
->version
= SCH2_VER
;
401 header
->ram_addr
= RAM_LOAD_ADDR
;
402 header
->image_len
= kernel_info
.file_size
;
403 header
->image_crc32
= crc32(0, (uint8_t *) kernel_ptr
, kernel_info
.file_size
);
404 header
->start_addr
= RAM_ENTRY_ADDR
;
405 header
->rootfs_addr
=
406 JBOOT_SIZE
+ STAG_SIZE
+ SCH2_SIZE
+ kernel_info
.file_size
;
407 header
->rootfs_len
= rootfs_info
.file_size
;
408 header
->rootfs_crc32
= crc32(0, (uint8_t *) rootfs_ptr
, rootfs_info
.file_size
);
409 header
->header_crc32
= 0;
410 header
->header_length
= SCH2_SIZE
;
411 header
->cmd_line_length
= 0;
413 header
->header_crc32
= crc32(0, (uint8_t *) header
, header
->header_length
);
418 int fill_stag(struct stag_header
*header
, uint32_t length
)
420 header
->cmark
= STAG_ID
;
421 header
->id
= STAG_ID
;
422 header
->magic
= STAG_MAGIC
;
423 header
->time_stamp
= jboot_timestamp();
424 header
->image_length
= length
+ SCH2_SIZE
;
425 header
->image_checksum
=
426 jboot_checksum(0, (uint16_t *) ((char *)header
+ STAG_SIZE
),
427 header
->image_length
);
428 header
->tag_checksum
=
429 ~jboot_checksum(0, (uint16_t *) header
, STAG_SIZE
- 2);
431 if (image_type
== FACTORY
)
432 header
->cmark
= STAG_CMARK_FACTORY
;
437 int fill_auh(struct auh_header
*header
, uint32_t length
)
439 memcpy(header
->rom_id
, rom_id
, 12);
441 header
->image_checksum
=
442 jboot_checksum(0, (uint16_t *) ((char *)header
+ AUH_SIZE
), length
);
446 header
->lpvs
= AUH_LVPS
;
448 header
->time_stamp
= jboot_timestamp();
449 header
->erase_start
= JBOOT_SIZE
;
450 header
->erase_length
= firmware_size
;
451 header
->data_offset
= JBOOT_SIZE
;
452 header
->data_length
= length
;
457 header
->header_id
= AUH_HDR_ID
;
458 header
->header_version
= AUH_HDR_VER
;
460 header
->section_id
= AUH_SEC_ID
;
461 header
->image_info_type
= AUH_INFO_TYPE
;
462 header
->image_info_offset
= 0;
463 header
->family_member
= family_member
;
464 header
->header_checksum
=
465 ~jboot_checksum(0, (uint16_t *) header
, AUH_SIZE
- 2);
475 int ret
= EXIT_FAILURE
;
478 struct stag_header
*stag_header_kernel
;
479 struct sch2_header
*sch2_header_kernel
;
481 if (!kernel_info
.file_name
| !rootfs_info
.file_name
)
484 ret
= get_file_stat(&kernel_info
);
487 ret
= get_file_stat(&rootfs_info
);
491 buf
= malloc(firmware_size
);
493 ERR("no memory for buffer\n");
497 if (rootfs_info
.file_size
+ kernel_info
.file_size
+ ALL_HEADERS_SIZE
>
499 ERR("data is bigger than firmware_size!\n");
503 memset(buf
, 0xff, firmware_size
);
505 stag_header_kernel
= (struct stag_header
*)buf
;
508 (struct sch2_header
*)((char *)stag_header_kernel
+ STAG_SIZE
);
509 kernel_ptr
= (char *)sch2_header_kernel
+ SCH2_SIZE
;
511 ret
= read_to_buf(&kernel_info
, kernel_ptr
);
515 rootfs_ptr
= kernel_ptr
+ kernel_info
.file_size
;
517 ret
= read_to_buf(&rootfs_info
, rootfs_ptr
);
521 writelen
= rootfs_ptr
+ rootfs_info
.file_size
- buf
;
523 fill_sch2(sch2_header_kernel
, kernel_ptr
, rootfs_ptr
);
524 fill_stag(stag_header_kernel
, kernel_info
.file_size
);
526 ret
= write_fw(ofname
, buf
, writelen
);
542 int ret
= EXIT_FAILURE
;
545 struct auh_header
*auh_header_kernel
;
547 if (!image_info
.file_name
)
550 ret
= get_file_stat(&image_info
);
554 buf
= malloc(firmware_size
);
556 ERR("no memory for buffer\n");
560 if (image_info
.file_size
+ AUH_SIZE
>
562 ERR("data is bigger than firmware_size!\n");
565 if (!family_member
) {
566 ERR("No family_member!\n");
573 memset(buf
, 0xff, firmware_size
);
575 image_ptr
= (char *)(buf
+ AUH_SIZE
);
577 ret
= read_to_buf(&image_info
, image_ptr
);
581 writelen
= image_ptr
+ image_info
.file_size
- buf
;
583 auh_header_kernel
= (struct auh_header
*)buf
;
584 fill_auh(auh_header_kernel
, writelen
- AUH_SIZE
);
586 ret
= write_fw(ofname
, buf
, writelen
);
598 int main(int argc
, char *argv
[])
600 int ret
= EXIT_FAILURE
;
602 progname
= basename(argv
[0]);
603 image_type
= SYSUPGRADE
;
610 c
= getopt(argc
, argv
, "f:F:i:hk:m:o:r:s:");
616 sscanf(optarg
, "0x%hx", &family_member
);
619 image_info
.file_name
= optarg
;
620 image_type
= FACTORY
;
623 inspect_info
.file_name
= optarg
;
626 kernel_info
.file_name
= optarg
;
629 if (strlen(optarg
) == 12)
630 memcpy(rom_id
, optarg
, 12);
633 rootfs_info
.file_name
= optarg
;
639 sscanf(optarg
, "0x%x", &firmware_size
);
647 ret
= check_options();
651 if (!inspect_info
.file_name
) {
652 if (image_type
== FACTORY
)