3b59a5d2df9a2bb3c9759951af355729aee2fb4d
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 uint32_t image_offset
;
103 uint16_t family_member
;
104 char *rom_id
[12] = { 0 };
107 static void usage(int status
)
109 fprintf(stderr
, "Usage: %s [OPTIONS...]\n", progname
);
113 " -i <file> inspect given firmware file <file>\n"
114 " -f set family member id (hexval prefixed with 0x)\n"
115 " -F <file> read image and convert it to FACTORY\n"
116 " -k <file> read kernel image from the file <file>\n"
117 " -r <file> read rootfs image from the file <file>\n"
118 " -o <file> write output to the file <file>\n"
119 " -s <size> set firmware partition size\n"
120 " -m <version> set rom id to <version> (12-bit string val: \"DLK*********\")\n"
121 " -h show this screen\n");
126 void print_auh_header(struct auh_header
*printed_header
)
128 printf("\trom_id: %s\n"
129 "\tderange: 0x%04X\n"
130 "\timage_checksum: 0x%04X\n"
136 "\ttime_stamp: 0x%08X\n"
137 "\terase_start: 0x%08X\n"
138 "\terase_length: 0x%08X\n"
139 "\tdata_offset: 0x%08X\n"
140 "\tdata_length: 0x%08X\n"
145 "\theader_id: 0x%04X\n"
146 "\theader_version: 0x%02X\n"
148 "\tsection_id: 0x%02X\n"
149 "\timage_info_type: 0x%02X\n"
150 "\timage_info_offset 0x%08X\n"
151 "\tfamily_member: 0x%04X\n"
152 "\theader_checksum: 0x%04X\n",
153 printed_header
->rom_id
,
154 printed_header
->derange
,
155 printed_header
->image_checksum
,
156 printed_header
->space1
,
157 printed_header
->space2
,
158 printed_header
->space3
,
159 printed_header
->lpvs
,
161 printed_header
->time_stamp
,
162 printed_header
->erase_start
,
163 printed_header
->erase_length
,
164 printed_header
->data_offset
,
165 printed_header
->data_length
,
166 printed_header
->space4
,
167 printed_header
->space5
,
168 printed_header
->space6
,
169 printed_header
->space7
,
170 printed_header
->header_id
,
171 printed_header
->header_version
,
172 printed_header
->space8
,
173 printed_header
->section_id
,
174 printed_header
->image_info_type
,
175 printed_header
->image_info_offset
,
176 printed_header
->family_member
, printed_header
->header_checksum
);
179 void print_stag_header(struct stag_header
*printed_header
)
181 printf("\tcmark: 0x%02X\n"
184 "\ttime_stamp: 0x%08X\n"
185 "\timage_length: 0x%04X\n"
186 "\timage_checksum: 0x%04X\n"
187 "\ttag_checksum: 0x%04X\n",
188 printed_header
->cmark
,
190 printed_header
->magic
,
191 printed_header
->time_stamp
,
192 printed_header
->image_length
,
193 printed_header
->image_checksum
, printed_header
->tag_checksum
);
196 void print_sch2_header(struct sch2_header
*printed_header
)
198 printf("\tmagic: 0x%04X\n"
199 "\tcp_type: 0x%02X\n"
200 "\tversion: 0x%02X\n"
201 "\tram_addr: 0x%08X\n"
202 "\timage_len: 0x%08X\n"
203 "\timage_crc32: 0x%08X\n"
204 "\tstart_addr: 0x%08X\n"
205 "\trootfs_addr: 0x%08X\n"
206 "\trootfs_len: 0x%08X\n"
207 "\trootfs_crc32: 0x%08X\n"
208 "\theader_crc32: 0x%08X\n"
209 "\theader_length: 0x%04X\n"
210 "\tcmd_line_length: 0x%04X\n",
211 printed_header
->magic
,
212 printed_header
->cp_type
,
213 printed_header
->version
,
214 printed_header
->ram_addr
,
215 printed_header
->image_len
,
216 printed_header
->image_crc32
,
217 printed_header
->start_addr
,
218 printed_header
->rootfs_addr
,
219 printed_header
->rootfs_len
,
220 printed_header
->rootfs_crc32
,
221 printed_header
->header_crc32
,
222 printed_header
->header_length
, printed_header
->cmd_line_length
);
225 static int find_auh_headers(char *buf
)
228 struct auh_header
*tmp_header
[MAX_HEADER_COUNTER
];
229 int header_counter
= 0;
231 int ret
= EXIT_FAILURE
;
233 while (tmp_buf
- buf
<= inspect_info
.file_size
- AUH_SIZE
) {
234 if (!memcmp(tmp_buf
, AUH_MAGIC
, 3)) {
235 if (((struct auh_header
*)tmp_buf
)->header_checksum
==
236 (uint16_t) ~jboot_checksum(0, (uint16_t *) tmp_buf
,
238 uint16_t checksum
= 0;
239 printf("Find proper AUH header at: 0x%lX!\n",
241 tmp_header
[header_counter
] =
242 (struct auh_header
*)tmp_buf
;
244 jboot_checksum(0, (uint16_t *) ((char *)
249 [header_counter
]->data_length
);
250 if (tmp_header
[header_counter
]->image_checksum
252 printf("Image checksum ok.\n");
254 ERR("Image checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", tmp_header
[header_counter
]->image_checksum
, checksum
);
256 if (header_counter
> MAX_HEADER_COUNTER
)
263 if (header_counter
== 0)
264 ERR("Can't find proper AUH header!\n");
265 else if (header_counter
> MAX_HEADER_COUNTER
)
266 ERR("To many AUH headers!\n");
268 for (int i
= 0; i
< header_counter
; i
++) {
269 printf("AUH %d:\n", i
);
270 print_auh_header(tmp_header
[i
]);
279 static int check_stag_header(char *buf
, struct stag_header
*header
)
282 int ret
= EXIT_FAILURE
;
284 uint8_t cmark_tmp
= header
->cmark
;
285 header
->cmark
= header
->id
;
287 if (header
->tag_checksum
==
288 (uint16_t) ~jboot_checksum(0, (uint16_t *) header
,
290 uint16_t checksum
= 0;
291 printf("Find proper STAG header at: 0x%lX!\n",
292 (char *)header
- buf
);
294 jboot_checksum(0, (uint16_t *) ((char *)header
+ STAG_SIZE
),
295 header
->image_length
);
296 if (header
->image_checksum
== checksum
) {
297 printf("Image checksum ok.\n");
298 header
->cmark
= cmark_tmp
;
299 print_stag_header(header
);
302 ERR("Image checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", header
->image_checksum
, checksum
);
304 ERR("STAG header checksum incorrect!");
306 header
->cmark
= cmark_tmp
;
310 static int check_sch2_header(char *buf
, struct sch2_header
*header
)
313 int ret
= EXIT_FAILURE
;
315 uint32_t crc32_tmp
= header
->header_crc32
;
316 header
->header_crc32
= 0;
318 if (crc32_tmp
== crc32(0, (uint8_t *) header
, header
->header_length
)) {
320 printf("Find proper SCH2 header at: 0x%lX!\n",
321 (char *)header
- buf
);
324 crc32(0, (uint8_t *) header
+ header
->header_length
,
326 if (header
->image_crc32
== crc32_val
) {
327 printf("Kernel checksum ok.\n");
329 header
->header_crc32
= crc32_tmp
;
330 print_sch2_header(header
);
333 ERR("Kernel checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", header
->image_crc32
, crc32_val
);
336 ERR("SCH2 header checksum incorrect!");
338 header
->header_crc32
= crc32_tmp
;
342 static int inspect_fw(void)
345 struct stag_header
*stag_header_kernel
;
346 struct sch2_header
*sch2_header_kernel
;
347 int ret
= EXIT_FAILURE
;
349 buf
= malloc(inspect_info
.file_size
);
351 ERR("no memory for buffer!\n");
355 ret
= read_to_buf(&inspect_info
, buf
);
359 ret
= find_auh_headers(buf
);
363 stag_header_kernel
= (struct stag_header
*)(buf
+ AUH_SIZE
);
365 ret
= check_stag_header(buf
, stag_header_kernel
);
369 sch2_header_kernel
= (struct sch2_header
*)(buf
+ AUH_SIZE
+ STAG_SIZE
);
371 ret
= check_sch2_header(buf
, sch2_header_kernel
);
381 static int check_options(void)
385 if (inspect_info
.file_name
) {
386 ret
= get_file_stat(&inspect_info
);
396 int fill_sch2(struct sch2_header
*header
, char *kernel_ptr
, char *rootfs_ptr
)
399 header
->magic
= SCH2_MAGIC
;
400 header
->cp_type
= LZMA
;
401 header
->version
= SCH2_VER
;
402 header
->ram_addr
= RAM_LOAD_ADDR
;
403 header
->image_len
= kernel_info
.file_size
;
404 header
->image_crc32
= crc32(0, (uint8_t *) kernel_ptr
, kernel_info
.file_size
);
405 header
->start_addr
= RAM_ENTRY_ADDR
;
406 header
->rootfs_addr
=
407 image_offset
+ STAG_SIZE
+ SCH2_SIZE
+ kernel_info
.file_size
;
408 header
->rootfs_len
= rootfs_info
.file_size
;
409 header
->rootfs_crc32
= crc32(0, (uint8_t *) rootfs_ptr
, rootfs_info
.file_size
);
410 header
->header_crc32
= 0;
411 header
->header_length
= SCH2_SIZE
;
412 header
->cmd_line_length
= 0;
414 header
->header_crc32
= crc32(0, (uint8_t *) header
, header
->header_length
);
419 int fill_stag(struct stag_header
*header
, uint32_t length
)
421 header
->cmark
= STAG_ID
;
422 header
->id
= STAG_ID
;
423 header
->magic
= STAG_MAGIC
;
424 header
->time_stamp
= jboot_timestamp();
425 header
->image_length
= length
+ SCH2_SIZE
;
426 header
->image_checksum
=
427 jboot_checksum(0, (uint16_t *) ((char *)header
+ STAG_SIZE
),
428 header
->image_length
);
429 header
->tag_checksum
=
430 ~jboot_checksum(0, (uint16_t *) header
, STAG_SIZE
- 2);
432 if (image_type
== FACTORY
)
433 header
->cmark
= STAG_CMARK_FACTORY
;
438 int fill_auh(struct auh_header
*header
, uint32_t length
)
440 memcpy(header
->rom_id
, rom_id
, 12);
442 header
->image_checksum
=
443 jboot_checksum(0, (uint16_t *) ((char *)header
+ AUH_SIZE
), length
);
447 header
->lpvs
= AUH_LVPS
;
449 header
->time_stamp
= jboot_timestamp();
450 header
->erase_start
= image_offset
;
451 header
->erase_length
= firmware_size
;
452 header
->data_offset
= image_offset
;
453 header
->data_length
= length
;
458 header
->header_id
= AUH_HDR_ID
;
459 header
->header_version
= AUH_HDR_VER
;
461 header
->section_id
= AUH_SEC_ID
;
462 header
->image_info_type
= AUH_INFO_TYPE
;
463 header
->image_info_offset
= 0;
464 header
->family_member
= family_member
;
465 header
->header_checksum
=
466 ~jboot_checksum(0, (uint16_t *) header
, AUH_SIZE
- 2);
476 int ret
= EXIT_FAILURE
;
479 struct stag_header
*stag_header_kernel
;
480 struct sch2_header
*sch2_header_kernel
;
482 if (!kernel_info
.file_name
| !rootfs_info
.file_name
)
485 ret
= get_file_stat(&kernel_info
);
488 ret
= get_file_stat(&rootfs_info
);
492 buf
= malloc(firmware_size
);
494 ERR("no memory for buffer\n");
498 if (rootfs_info
.file_size
+ kernel_info
.file_size
+ ALL_HEADERS_SIZE
>
500 ERR("data is bigger than firmware_size!\n");
504 memset(buf
, 0xff, firmware_size
);
506 stag_header_kernel
= (struct stag_header
*)buf
;
509 (struct sch2_header
*)((char *)stag_header_kernel
+ STAG_SIZE
);
510 kernel_ptr
= (char *)sch2_header_kernel
+ SCH2_SIZE
;
512 ret
= read_to_buf(&kernel_info
, kernel_ptr
);
516 rootfs_ptr
= kernel_ptr
+ kernel_info
.file_size
;
518 ret
= read_to_buf(&rootfs_info
, rootfs_ptr
);
522 writelen
= rootfs_ptr
+ rootfs_info
.file_size
- buf
;
524 fill_sch2(sch2_header_kernel
, kernel_ptr
, rootfs_ptr
);
525 fill_stag(stag_header_kernel
, kernel_info
.file_size
);
527 ret
= write_fw(ofname
, buf
, writelen
);
543 int ret
= EXIT_FAILURE
;
546 struct auh_header
*auh_header_kernel
;
548 if (!image_info
.file_name
)
551 ret
= get_file_stat(&image_info
);
555 buf
= malloc(firmware_size
);
557 ERR("no memory for buffer\n");
561 if (image_info
.file_size
+ AUH_SIZE
>
563 ERR("data is bigger than firmware_size!\n");
566 if (!family_member
) {
567 ERR("No family_member!\n");
574 memset(buf
, 0xff, firmware_size
);
576 image_ptr
= (char *)(buf
+ AUH_SIZE
);
578 ret
= read_to_buf(&image_info
, image_ptr
);
582 writelen
= image_ptr
+ image_info
.file_size
- buf
;
584 auh_header_kernel
= (struct auh_header
*)buf
;
585 fill_auh(auh_header_kernel
, writelen
- AUH_SIZE
);
587 ret
= write_fw(ofname
, buf
, writelen
);
599 int main(int argc
, char *argv
[])
601 int ret
= EXIT_FAILURE
;
603 progname
= basename(argv
[0]);
604 image_type
= SYSUPGRADE
;
607 image_offset
= JBOOT_SIZE
;
612 c
= getopt(argc
, argv
, "f:F:i:hk:m:o:O:r:s:");
618 sscanf(optarg
, "0x%hx", &family_member
);
621 image_info
.file_name
= optarg
;
622 image_type
= FACTORY
;
625 inspect_info
.file_name
= optarg
;
628 kernel_info
.file_name
= optarg
;
631 if (strlen(optarg
) == 12)
632 memcpy(rom_id
, optarg
, 12);
635 rootfs_info
.file_name
= optarg
;
638 sscanf(optarg
, "0x%x", &image_offset
);
644 sscanf(optarg
, "0x%x", &firmware_size
);
652 ret
= check_options();
656 if (!inspect_info
.file_name
) {
657 if (image_type
== FACTORY
)