1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * 4 * Copyright (C) 2024 OpenWrt.org 5 * Copyright (C) 2024 Oleg S <remittor@gmail.com> 6 */ 7 8 #include <endian.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <stddef.h> 14 #include <stdint.h> 15 #include <string.h> 16 #include <stdarg.h> 17 #include <time.h> 18 #include <netinet/in.h> 19 #include <unistd.h> 20 #include <byteswap.h> 21 #include <zlib.h> /* crc32 */ 22 23 /* Various defines picked from U-boot */ 24 25 #define FDT_MAGIC 0xD00DFEED 26 27 #define IH_MAGIC 0x27051956 28 29 #define IH_OS_LINUX 5 30 31 #define IH_ARCH_ARM64 22 32 33 #define IH_TYPE_KERNEL 2 34 #define IH_TYPE_MULTI 4 35 36 #define IH_COMP_NONE 0 37 38 #define GET_BE24(ptr) ( (((uint8_t *)(ptr))[0] << 16) | (((uint8_t *)(ptr))[1] << 8) | ((uint8_t *)(ptr))[2] ) 39 #define SET_BE24(ptr, value) do { \ 40 ((uint8_t *)(ptr))[0] = ((value) >> 16) & 0xFF; \ 41 ((uint8_t *)(ptr))[1] = ((value) >> 8) & 0xFF; \ 42 ((uint8_t *)(ptr))[2] = (value) & 0xFF; \ 43 } while (0) 44 45 enum volume_t { 46 VOL_KERNEL = 0, 47 VOL_RAMDISK, 48 VOL_FLATDT, 49 50 VOL_COUNT, 51 }; 52 53 typedef struct { 54 uint8_t major; 55 uint8_t minor; 56 } __attribute__ ((packed)) version_t; 57 58 #define FS_OFFSET_PREFIX (0xA9) 59 #define TRX3_UNK1 (0x003000) 60 61 typedef struct { 62 char prod_name[23]; 63 uint8_t unk0; // version of rootfs ??? 64 uint8_t fs_prefix; // prefix for fs_offset (0xA9) 65 uint8_t fs_offset[3];// offset for fs-image (24 bit BE) 66 } __attribute__ ((packed)) trx1_t; 67 68 typedef struct { 69 char prod_name[12]; 70 uint16_t sn; // fw build no (example: 388) 71 uint16_t en; // fw extended build no (example: 51234) 72 uint8_t dummy; // likely random byte 73 uint8_t key; // hash value from kernel and fs 74 uint8_t unk[6]; // likely random bytes 75 uint8_t fs_prefix; // prefix for fs_offset (0xA9) 76 uint8_t fs_offset[3];// offset for fs-image (24 bit BE) 77 } __attribute__ ((packed)) trx2_t; // hdr2 78 79 typedef struct { 80 char prod_name[23]; 81 uint8_t unk0; 82 uint32_t unk1; // ??? usualy: 0x003000 83 } __attribute__ ((packed)) trx3_t; 84 85 typedef struct image_header { 86 uint32_t ih_magic; 87 uint32_t ih_hcrc; 88 uint32_t ih_time; 89 uint32_t ih_size; // content size 90 uint32_t ih_load; // load addr 91 uint32_t ih_ep; // entry point 92 uint32_t ih_dcrc; // content hash 93 uint8_t ih_os; // os type 94 uint8_t ih_arch; // kernel arch 95 uint8_t ih_type; // image type 96 uint8_t ih_comp; // compression 97 version_t kernel_ver; // usualy: 3.0 98 version_t fs_ver; // usualy: 0.4 99 union { 100 trx1_t trx1; 101 trx2_t trx2; 102 trx3_t trx3; 103 } tail; 104 } __attribute__ ((packed)) image_header_t; 105 106 typedef struct { 107 uint32_t extendno; // fw extended build no (example: 51234) 108 uint16_t buildno; // fw build no (example: 388) 109 uint16_t r16; // always 0 ??? 110 uint32_t r32; // always 0 ??? 111 } __attribute__ ((packed)) tail_content_t; 112 113 #define DEF_ASUS_TAIL_MAGIC 0x2AFED414 114 115 typedef struct { 116 uint8_t flags: 4, // always 0 ??? 117 type : 4; // always 1 ??? 118 uint8_t clen[3]; // content len (24bit BE) 119 uint16_t fcrc; // crc for footer 120 uint16_t checksum; // content hash 121 uint32_t magic; 122 } __attribute__ ((packed)) tail_footer_t; 123 124 typedef struct { 125 int show_info; 126 char * imagefn; 127 char * outfn; 128 char prod_name[128]; 129 int trx_ver; 130 version_t kernel_ver; 131 version_t fs_ver; 132 uint32_t magic; 133 uint32_t type; 134 uint32_t flags; 135 uint32_t extendno; 136 uint32_t buildno; 137 uint32_t r16; 138 uint32_t r32; 139 } trx_opt_t; 140 141 trx_opt_t g_def = {0}; 142 trx_opt_t g_opt = {0}; 143 144 // ========================================================= 145 146 #define ROUNDUP(x, n) (((x) + (n - 1)) & ~(n - 1)) 147 148 // ========================================================= 149 150 char * g_progname = ""; 151 int g_debug = 0; 152 153 #define DBG(...) do { if (g_debug) printf(__VA_ARGS__); } while(0) 154 #define _attr_fmt_err_ __attribute__ ((format (printf, 1, 2))) 155 156 static _attr_fmt_err_ 157 void fatal_error(const char * fmtstr, ...) 158 { 159 va_list ap; 160 fflush(0); 161 fprintf(stderr, "%s: ERROR: ", g_progname); 162 va_start(ap, fmtstr); 163 vfprintf(stderr, fmtstr, ap); 164 va_end (ap); 165 fprintf(stderr, "\n"); 166 exit(EXIT_FAILURE); 167 } 168 169 #define ERR(fmtstr, ...) fatal_error(fmtstr, ## __VA_ARGS__) 170 171 static 172 uint16_t asus_hash16(const void * data, size_t length) 173 { 174 uint16_t * current = (uint16_t *) data; 175 length = length / sizeof(uint16_t); 176 uint16_t hash = 0; 177 178 while (length--) { 179 hash ^= *current++; 180 } 181 return ~hash; // same as hash ^ 0xFFFF 182 } 183 184 void update_iheader_crc(image_header_t * hdr, const void * data, size_t data_size) 185 { 186 if (data == NULL) 187 data = (const void *)((char *)hdr + sizeof(image_header_t)); 188 189 // Calculate payload checksum 190 hdr->ih_dcrc = htobe32(crc32(0, data, data_size)); 191 hdr->ih_size = htobe32(data_size); 192 193 // Calculate header checksum 194 hdr->ih_hcrc = 0; 195 hdr->ih_hcrc = htobe32(crc32(0, (const void *)hdr, sizeof(image_header_t))); 196 } 197 198 static 199 void init_opt(void) 200 { 201 memset(&g_def, 0, sizeof(g_def)); 202 g_def.show_info = 0; 203 g_def.trx_ver = 3; 204 g_def.magic = DEF_ASUS_TAIL_MAGIC; 205 g_def.type = 1; 206 g_def.flags = 0; 207 memcpy(&g_opt, &g_def, sizeof(g_def)); 208 } 209 210 static 211 void usage(int status) 212 { 213 FILE * fp = (status != EXIT_SUCCESS) ? stderr : stdout; 214 215 fprintf(fp, "Usage: %s -i <image> [OPTIONS...]\n", g_progname); 216 fprintf(fp, "\n"); 217 fprintf(fp, "Options:\n"); 218 fprintf(fp, " -i <filename> input image filename \n"); 219 fprintf(fp, " -o <filename> output image filename \n"); 220 fprintf(fp, " -x show only image info \n"); 221 fprintf(fp, " -n <name> product name \n"); 222 fprintf(fp, " -v <number> TRX version: 2 or 3 (def: %d) \n", g_def.trx_ver); 223 fprintf(fp, " -K <#>.<#> kernel version (def: \"%d.%d\") \n", g_def.kernel_ver.major, g_def.kernel_ver.minor); 224 fprintf(fp, " -F <#>.<#> filesys version (def: \"%d.%d\") \n", g_def.fs_ver.major, g_def.fs_ver.minor); 225 fprintf(fp, " -m <signature> tail HEX signature (def: %08X) \n", g_def.magic); 226 fprintf(fp, " -t <number> tail type (def: %X) \n", g_def.type); 227 fprintf(fp, " -f <number> tail flags (def: %X) \n", g_def.flags); 228 fprintf(fp, " -e <number> tail ext no (def: %u) \n", g_def.extendno); 229 fprintf(fp, " -b <number> tail build no (def: %u) \n", g_def.buildno); 230 fprintf(fp, " -h show this screen \n"); 231 exit(status); 232 } 233 234 static 235 int parse_args(int argc, char ** argv) 236 { 237 char *str, *end; 238 int opt; 239 240 while ((opt = getopt(argc, argv, "Dxi:o:n:K:F:v:m:t:f:e:b:h?")) != -1) { 241 switch (opt) { 242 case 'i': 243 g_opt.imagefn = optarg; 244 break; 245 case 'o': 246 g_opt.outfn = optarg; 247 break; 248 case 'x': 249 g_opt.show_info = 1; 250 g_debug = 1; 251 break; 252 case 'D': 253 g_debug = 1; 254 break; 255 case 'n': 256 strncpy(g_opt.prod_name, optarg, sizeof(g_opt.prod_name) - 1); 257 break; 258 case 'v': 259 g_opt.trx_ver = strtoul(optarg, &end, 0); 260 if (end == optarg) 261 ERR("Incorrect -v argument!"); 262 break; 263 case 'K': 264 g_opt.kernel_ver.major = (uint8_t) strtoul(optarg, &end, 10); 265 if (end == optarg || end[0] != '.') 266 ERR("Incorrect -K argument!"); 267 268 str = end + 1; 269 g_opt.kernel_ver.minor = (uint8_t) strtoul(str, &end, 10); 270 if (end == str) 271 ERR("Incorrect -K argument!"); 272 break; 273 case 'F': 274 g_opt.fs_ver.major = (uint8_t) strtoul(optarg, &end, 10); 275 if (end == optarg || end[0] != '.') 276 ERR("Incorrect -F argument!"); 277 278 str = end + 1; 279 g_opt.fs_ver.minor = (uint8_t) strtoul(str, &end, 10); 280 if (end == str) 281 ERR("Incorrect -F argument!"); 282 break; 283 case 'm': 284 g_opt.magic = strtoul(optarg, &end, 16); 285 if (end == optarg) 286 ERR("Incorrect -m argument!"); 287 break; 288 case 't': 289 g_opt.type = strtoul(optarg, &end, 0); 290 if (end == optarg) 291 ERR("Incorrect -t argument!"); 292 break; 293 case 'f': 294 g_opt.flags = strtoul(optarg, &end, 0); 295 if (end == optarg) 296 ERR("Incorrect -f argument!"); 297 break; 298 case 'e': 299 g_opt.extendno = strtoul(optarg, &end, 0); 300 if (end == optarg) 301 ERR("Incorrect -e argument!"); 302 break; 303 case 'b': 304 g_opt.buildno = strtoul(optarg, &end, 0); 305 if (end == optarg) 306 ERR("Incorrect -b argument!"); 307 break; 308 case 'h': 309 default: 310 usage(EXIT_FAILURE); 311 } 312 } 313 if (g_opt.imagefn == NULL || g_opt.imagefn[0] == 0) 314 usage(EXIT_FAILURE); // Required input image filename! 315 316 if (g_opt.show_info == 0) 317 if (g_opt.outfn == NULL || g_opt.outfn[0] == 0) 318 usage(EXIT_FAILURE); // Required output image filename! 319 320 if (g_opt.trx_ver < 2 || g_opt.trx_ver > 3) 321 usage(EXIT_FAILURE); 322 323 return 0; 324 } 325 326 static 327 char * load_image(size_t pad_size, size_t * psize) 328 { 329 uint32_t file_sz; 330 size_t readed; 331 void * buf; 332 FILE *fp; 333 334 fp = fopen(g_opt.imagefn, "rb"); 335 if (!fp) 336 ERR("Can't open %s: %s", g_opt.imagefn, strerror(errno)); 337 338 rewind(fp); 339 fseek(fp, 0, SEEK_END); 340 file_sz = ftell(fp); 341 rewind(fp); 342 343 if ((int32_t)file_sz <= 0) { 344 fclose(fp); 345 ERR("Error getting filesize: %s", g_opt.imagefn); 346 } 347 348 if (file_sz <= sizeof(image_header_t)) { 349 fclose(fp); 350 ERR("Bad size: \"%s\" is no valid image", g_opt.imagefn); 351 } 352 353 buf = malloc(file_sz + pad_size); 354 if (!buf) { 355 fclose(fp); 356 ERR("Out of memory!"); 357 } 358 memset(buf, 0, file_sz + pad_size); 359 360 readed = fread(buf, 1, file_sz, fp); 361 fclose(fp); 362 if (readed != (size_t)file_sz) 363 ERR("Error reading file %s", g_opt.imagefn); 364 365 *psize = file_sz; 366 367 return (char *)buf; 368 } 369 370 static 371 uint32_t get_timestamp(void) 372 { 373 char * env = getenv("SOURCE_DATE_EPOCH"); 374 time_t fixed_timestamp = -1; 375 char * endptr = env; 376 377 if (env && *env) { 378 errno = 0; 379 fixed_timestamp = (time_t) strtoull(env, &endptr, 10); 380 381 if (errno || (endptr && *endptr != '\0')) { 382 fprintf(stderr, "ERROR: Invalid SOURCE_DATE_EPOCH \n"); 383 fixed_timestamp = -1; 384 } 385 } 386 387 if (fixed_timestamp == -1) 388 time(&fixed_timestamp); 389 390 DBG("timestamp: %u \n", (uint32_t)fixed_timestamp); 391 return (uint32_t)fixed_timestamp; 392 } 393 394 static int show_info(char *img, size_t img_size) 395 { 396 uint32_t data_size, fdt_size, fs_size, fs_offset = 0; 397 uint16_t fcrc, fcrc_c, checksum_c; 398 uint8_t fs_key, kernel_key, key; 399 uint32_t sn, en, xx = 0; 400 size_t buf_size; 401 tail_footer_t * foot; 402 tail_content_t *cont; 403 image_header_t *hdr; 404 uint32_t cont_len; 405 uint32_t *fs_data; 406 uint8_t *buf; 407 trx2_t *trx; 408 int i; 409 410 /* Assume valid, already validated early in process_image */ 411 hdr = (image_header_t *)img; 412 foot = (tail_footer_t *)(img + img_size - sizeof(tail_footer_t)); 413 414 if (be32toh(hdr->ih_magic) != IH_MAGIC) { 415 free(img); 416 ERR("Incorrect image: \"%s\" magic must be %08X", g_opt.imagefn, IH_MAGIC); 417 } 418 419 g_opt.trx_ver = 0; 420 if (be32toh(foot->magic) == g_opt.magic) 421 g_opt.trx_ver = 3; /* tail with magic = DEF_ASUS_TAIL_MAGIC */ 422 423 if (hdr->tail.trx2.fs_prefix == FS_OFFSET_PREFIX) { 424 g_opt.trx_ver = 1; /* hdr1 */ 425 426 for (i = 0; i < sizeof(hdr->tail.trx1.prod_name); i++) { 427 if (hdr->tail.trx1.prod_name[i] >= 0x7F) 428 g_opt.trx_ver = 2; /* hdr2 */ 429 } 430 431 if (hdr->tail.trx2.sn >= 380 && hdr->tail.trx2.sn <= 490) 432 g_opt.trx_ver = 2; /* hdr2 */ 433 } 434 435 DBG("detect trx version = %d \n", g_opt.trx_ver); 436 switch(g_opt.trx_ver) { 437 case 1: 438 free(img); 439 ERR("Formart HDR1 currently not supported"); 440 break; 441 case 2: 442 trx = &hdr->tail.trx2; 443 444 data_size = (uint32_t)be32toh(hdr->ih_size); 445 sn = htole16(trx->sn); 446 en = htole16(trx->en); 447 448 if (en < 20000 && sn >= 386) 449 en += 0x10000; 450 451 DBG("hdr2.sn: %u (0x%04X) \n", sn, sn); 452 DBG("hdr2.en: %u (0x%04X) \n", en, htole16(trx->en)); 453 DBG("hdr2.key: 0x%02X \n", trx->key); 454 buf = trx->unk; 455 buf_size = sizeof(trx2_t) - offsetof(trx2_t, unk); 456 for (size_t i = 0; i < buf_size; i += 2) { 457 if (buf[i] == FS_OFFSET_PREFIX) { 458 xx = GET_BE24(buf + 1); 459 if ((xx & 3) == 0) { 460 fs_offset = xx; 461 break; 462 } 463 } 464 } 465 DBG("fs_offset: 0x%08X \n", fs_offset); 466 if (!fs_offset || fs_offset + 128 > img_size) 467 ERR("Incorrect fs_offset!"); 468 469 fs_data = (uint32_t *)(img + fs_offset); 470 DBG("fs_data: %08X %08X \n", be32toh(fs_data[0]), be32toh(fs_data[1])); 471 fs_size = sizeof(image_header_t) + data_size - fs_offset; 472 DBG("fs_size: 0x%X bytes \n", fs_size); 473 fs_key = img[fs_offset + fs_size / 2]; 474 kernel_key = img[fs_offset / 2]; 475 DBG("fs_key: 0x%02X kernel_key: 0x%02X \n", fs_key, kernel_key); 476 if (fs_key) { 477 key = kernel_key + ~fs_key; 478 } else { 479 key = (kernel_key % 3) - 3; 480 } 481 DBG("key = 0x%02X \n", key); 482 if (be32toh(fs_data[0]) == FDT_MAGIC) { 483 DBG("fdt_offset: 0x%08X \n", fs_offset); 484 fdt_size = be32toh(fs_data[1]); 485 DBG("fdt_size: 0x%X bytes \n", fdt_size); 486 fs_offset += ROUNDUP(fdt_size, 64); 487 DBG("fs_offset: 0x%08X \n", fs_offset); 488 fs_size -= ROUNDUP(fdt_size, 64); 489 DBG("fs_size: 0x%X bytes \n", fs_size); 490 } 491 break; 492 case 3: 493 DBG("tail: footer size = 0x%lX (%lu) \n", sizeof(tail_footer_t), sizeof(tail_footer_t)); 494 DBG("tail: footer magic: 0x%X \n", be32toh(foot->magic)); 495 496 cont_len = GET_BE24(foot->clen); 497 DBG("tail: type = %X, flags = %X, content len = 0x%06X \n", foot->type, foot->flags, cont_len); 498 499 fcrc = foot->fcrc; 500 foot->fcrc = 0; 501 fcrc_c = asus_hash16(foot, sizeof(*foot)); 502 DBG("tail: fcrc = %04X (%04X) \n", be16toh(fcrc), fcrc_c); 503 504 cont = (tail_content_t *)((char *)foot - cont_len); 505 checksum_c = asus_hash16(cont, sizeof(*cont)); 506 DBG("cont: checksum = %04X (%04X) \n", be16toh(foot->checksum), checksum_c); 507 508 DBG("cont: buildno: %u, extendno: %u \n", be16toh(cont->buildno), be32toh(cont->extendno)); 509 DBG("cont: r16: 0x%08X, r32: 0x%08X \n", be16toh(cont->r16), be32toh(cont->r32)); 510 break; 511 default: 512 free(img); 513 ERR("Input image is not compatible with AsusWRT"); 514 } 515 516 free(img); 517 return 0; 518 } 519 520 static 521 int process_image(void) 522 { 523 const uint32_t hsz = sizeof(image_header_t); 524 uint32_t vol_offset[VOL_COUNT + 1] = { 0 }; 525 uint32_t i, data_size, data_crc_c, fs_offset = 0, vol_count = 0, 526 *fs_data, fs_size, fdt_size, *vol_size, xoffset, *fdt, 527 cur_fdt_offset, new_fdt_offset, new_fs_offset, pad, 528 hsqs_offset, hsqs_size, *hsqs_data, cont_len; 529 uint32_t __attribute__ ((unused)) fdt_offset; 530 size_t img_size = 0, max_prod_len, new_img_size, 531 new_data_size, wlen; 532 char *img, *img_end, *prod_name; 533 uint8_t fs_key, kernel_key, key; 534 const char *prod_name_str; 535 tail_content_t *cont; 536 image_header_t *hdr; 537 tail_footer_t *foot; 538 trx2_t *trx; 539 FILE *fp; 540 541 img = load_image(1024, &img_size); 542 if (!img) 543 ERR("Can't load file %s", g_opt.imagefn); 544 545 if (g_opt.show_info) 546 return show_info(img, img_size); 547 548 hdr = (image_header_t *)img; 549 if (be32toh(hdr->ih_magic) != IH_MAGIC) { 550 memmove(img + hsz, img, img_size); 551 memset(hdr, 0, hsz); 552 hdr->ih_magic = htobe32(IH_MAGIC); 553 hdr->ih_time = htobe32(get_timestamp()); 554 hdr->ih_size = htobe32(img_size); 555 hdr->ih_load = 0; 556 hdr->ih_ep = 0; 557 hdr->ih_os = IH_OS_LINUX; 558 hdr->ih_arch = IH_ARCH_ARM64; 559 hdr->ih_type = IH_TYPE_KERNEL; 560 hdr->ih_comp = IH_COMP_NONE; 561 img_size += hsz; 562 } 563 data_size = (uint32_t)be32toh(hdr->ih_size); 564 DBG("data: size = 0x%08X (%u bytes) \n", data_size, data_size); 565 if (data_size + hsz > img_size) 566 ERR("Bad size: \"%s\" is no valid content size", g_opt.imagefn); 567 568 data_crc_c = crc32(0, (const unsigned char *)(img + hsz), data_size); 569 DBG("data: crc = %08X (%08X) \n", be32toh(hdr->ih_dcrc), data_crc_c); 570 571 DBG("image type: %d \n", (int)hdr->ih_type); 572 573 img_end = img + img_size; 574 575 memset(&hdr->tail.trx1, 0, sizeof(hdr->tail.trx1)); 576 switch(g_opt.trx_ver) { 577 case 2: 578 prod_name = hdr->tail.trx2.prod_name; 579 max_prod_len = sizeof(hdr->tail.trx2.prod_name); 580 break; 581 case 3: 582 prod_name = hdr->tail.trx3.prod_name; 583 max_prod_len = sizeof(hdr->tail.trx3.prod_name); 584 break; 585 default: 586 ERR("Incorrect option -v"); 587 } 588 589 prod_name_str = (const char *)&hdr->kernel_ver; 590 if (g_opt.prod_name[0]) 591 prod_name_str = g_opt.prod_name; 592 593 #pragma GCC diagnostic push 594 #pragma GCC diagnostic ignored "-Wstringop-truncation" 595 strncpy(prod_name, prod_name_str, max_prod_len); 596 #pragma GCC diagnostic pop 597 hdr->kernel_ver = g_opt.kernel_ver; 598 hdr->fs_ver = g_opt.fs_ver; 599 600 switch(g_opt.trx_ver) { 601 case 2: 602 trx = &hdr->tail.trx2; 603 604 if (hdr->ih_type == IH_TYPE_MULTI) { 605 DBG("detect image with type: IH_TYPE_MULTI \n"); 606 vol_size = (uint32_t *)(img + hsz); 607 if (vol_size[0] == 0) { 608 free(img); 609 ERR("Multi image does not contain volumes"); 610 } 611 612 for (uint32_t i = 0; i <= VOL_COUNT; i++) { 613 if (vol_size[i] == 0) 614 break; 615 vol_count++; 616 } 617 DBG("Multi image: volumes count = %u \n", vol_count); 618 619 if (vol_count > VOL_COUNT) { 620 free(img); 621 ERR("Multi image contains too many volumes"); 622 } 623 624 xoffset = hsz + sizeof(uint32_t) * (vol_count + 1); 625 for (i = 0; i < vol_count; i++) { 626 xoffset = ROUNDUP(xoffset, 4); 627 vol_offset[i] = xoffset; 628 DBG("Multi image: volume %u has offset = 0x%08X \n", i, xoffset); 629 if (be32toh(vol_size[i]) > 0x4FFFFFF) { 630 free(img); 631 ERR("Multi image contain volume %u with huge size", i); 632 } 633 634 xoffset += be32toh(vol_size[i]); 635 } 636 if (xoffset > img_size) { 637 free(img); 638 ERR("Multi image contain incorrect img-size header"); 639 } 640 641 fdt = (uint32_t *)(img + vol_offset[VOL_FLATDT]); 642 if (vol_offset[VOL_FLATDT] && be32toh(fdt[0]) == FDT_MAGIC) { 643 if (hdr->ih_arch == IH_ARCH_ARM64 && (vol_offset[VOL_FLATDT] & 7) != 0) { 644 // for ARM64 offset of FlatDT must be 8-bytes align 645 cur_fdt_offset = vol_offset[VOL_FLATDT]; 646 new_fdt_offset = vol_offset[VOL_FLATDT] + 4; 647 memmove(img + new_fdt_offset, img + cur_fdt_offset, img_size - cur_fdt_offset); 648 memset(img + cur_fdt_offset, 0, 4); 649 img_size += 4; 650 data_size += 4; 651 vol_offset[VOL_FLATDT] = new_fdt_offset; 652 vol_size[VOL_RAMDISK] = htobe32( be32toh(vol_size[VOL_RAMDISK]) + 4 ); 653 DBG("Multi image: volume %u size increased by 4 bytes \n", VOL_RAMDISK); 654 DBG("Multi image: volume %u has offset = 0x%08X (patched) \n", VOL_FLATDT, new_fdt_offset); 655 } 656 } 657 fs_offset = vol_offset[VOL_RAMDISK]; 658 if (fs_offset == 0) { 659 //ERR("Multi image does not contain rootfs volume"); 660 fs_offset = hsz + data_size; 661 } 662 } else { 663 fs_offset = hsz + data_size; 664 if (fs_offset & 3) { 665 //ERR("kernel size must be align to 4 bytes"); 666 new_fs_offset = ROUNDUP(fs_offset, 4); 667 memmove(img + new_fs_offset, img + fs_offset, img_size - fs_offset); 668 pad = new_fs_offset - fs_offset; 669 memset(img + fs_offset, 0, pad); 670 img_size += pad; 671 data_size += pad; 672 fs_offset = new_fs_offset; 673 } 674 } 675 DBG("fs_offset: 0x%08X \n", fs_offset); 676 fs_data = (uint32_t *)(img + fs_offset); 677 DBG("fs_data: %08X %08X \n", be32toh(fs_data[0]), be32toh(fs_data[1])); 678 fs_size = img_size - fs_offset; 679 fdt_offset = 0; 680 fdt_size = 0; 681 hsqs_offset = fs_offset; 682 hsqs_size = fs_size; 683 if (be32toh(fs_data[0]) == FDT_MAGIC && !vol_count) { 684 fdt_offset = fs_offset; 685 DBG("fdt_offset: 0x%08X \n", fs_offset); 686 fdt_size = be32toh(fs_data[1]); 687 DBG("fdt_size: 0x%X bytes \n", fdt_size); 688 hsqs_offset += ROUNDUP(fdt_size, 64); 689 hsqs_size -= ROUNDUP(fdt_size, 64); 690 } 691 DBG("hsqs_offset: 0x%08X \n", hsqs_offset); 692 DBG("hsqs_size: 0x%X bytes \n", hsqs_size); 693 hsqs_data = (uint32_t *)(img + hsqs_offset); 694 DBG("hsqs_data: %08X %08X \n", be32toh(hsqs_data[0]), be32toh(hsqs_data[1])); 695 kernel_key = img[fs_offset / 2]; 696 fs_key = img[fs_offset + fs_size / 2]; 697 DBG("fs_key: 0x%02X kernel_key: 0x%02X \n", fs_key, kernel_key); 698 key = fs_key ? kernel_key + ~fs_key : (kernel_key % 3) - 3; 699 DBG("key = 0x%02X \n", key); 700 trx->sn = htole16((uint16_t)g_opt.buildno); 701 trx->en = htole16((uint16_t)g_opt.extendno); 702 trx->key = key; 703 if (fs_offset >= 0xFFFFFF) { 704 free(img); 705 ERR("kernel image size is too big (max size: 16MiB)"); 706 } 707 708 trx->fs_prefix = FS_OFFSET_PREFIX; 709 SET_BE24(trx->fs_offset, fs_offset); 710 update_iheader_crc(hdr, NULL, img_size - hsz); 711 break; 712 case 3: 713 cont_len = 0; 714 cont = NULL; 715 foot = NULL; 716 717 hdr->tail.trx3.unk1 = htobe32(TRX3_UNK1); // unknown value 718 719 cont_len = img_size - hsz - data_size + sizeof(tail_content_t); 720 cont = (tail_content_t *)img_end; 721 cont->extendno = htobe32(g_opt.extendno); 722 cont->buildno = htobe16(g_opt.buildno); 723 cont->r16 = htobe16(g_opt.r16); 724 cont->r32 = htobe32(g_opt.r32); 725 726 foot = (tail_footer_t *)(img_end + sizeof(tail_content_t)); 727 char * cont_ptr = img + hsz + data_size; 728 foot->checksum = htobe16(asus_hash16(cont_ptr, cont_len)); 729 730 if (cont_len >= (1UL << 24)) { 731 free(img); 732 ERR("Content length is too long (more than 0x%lX bytes)", 1UL << 24); 733 } 734 735 SET_BE24(foot->clen, cont_len); // 24bit BigEndian 736 737 foot->magic = htobe32(g_opt.magic); 738 foot->type = g_opt.type; 739 foot->flags = g_opt.flags; 740 foot->fcrc = 0; 741 foot->fcrc = htobe16(asus_hash16(foot, sizeof(*foot))); 742 743 new_img_size = (size_t)((char *)foot + sizeof(tail_footer_t) - img); 744 new_data_size = new_img_size - hsz; 745 update_iheader_crc(hdr, NULL, new_data_size); 746 747 img_size = hsz + data_size + cont_len + sizeof(tail_footer_t); 748 } 749 750 fp = fopen(g_opt.outfn, "wb"); 751 if (!fp) { 752 free(img); 753 ERR("Can't open %s for writing: %s", g_opt.outfn, strerror(errno)); 754 } 755 756 wlen = fwrite(img, img_size, 1, fp); 757 fclose(fp); 758 if (wlen != 1) { 759 free(img); 760 ERR("Failed to write: %s", g_opt.outfn); 761 } 762 763 DBG("New TRX-image file created: \"%s\" \n", g_opt.outfn); 764 free(img); 765 766 return 0; // OK 767 } 768 769 int main(int argc, char ** argv) 770 { 771 g_progname = argv[0]; 772 773 init_opt(); 774 parse_args(argc, argv); 775 776 int rc = process_image(); 777 778 return rc; 779 } 780
This page was automatically generated by LXR 0.3.1. • OpenWrt