1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2018 NXP 4 * 5 * Peng Fan <peng.fan@nxp.com> 6 */ 7 8 9#include "imagetool.h" 10#include <image.h> 11#include "imximage.h" 12#include "compiler.h" 13 14static uint32_t ap_start_addr, sld_start_addr, sld_src_off; 15static char *ap_img, *sld_img, *signed_hdmi; 16static imx_header_v3_t imx_header[2]; /* At most there are 3 IVT headers */ 17static uint32_t rom_image_offset; 18static uint32_t sector_size = 0x200; 19static uint32_t image_off; 20static uint32_t sld_header_off; 21static uint32_t ivt_offset; 22static uint32_t using_fit; 23 24#define ROM_V1 1 25#define ROM_V2 2 26 27static uint32_t rom_version = ROM_V1; 28 29#define CSF_SIZE 0x2000 30#define HDMI_IVT_ID 0 31#define IMAGE_IVT_ID 1 32 33#define HDMI_FW_SIZE 0x17000 /* Use Last 0x1000 for IVT and CSF */ 34#define ALIGN_SIZE 0x1000 35#define ALIGN_IMX(x, a) __ALIGN_MASK_IMX((x), (__typeof__(x))(a) - 1, a) 36#define __ALIGN_MASK_IMX(x, mask, mask2) (((x) + (mask)) / (mask2) * (mask2)) 37 38static uint32_t get_cfg_value(char *token, char *name, int linenr) 39{ 40 char *endptr; 41 uint32_t value; 42 43 errno = 0; 44 value = strtoul(token, &endptr, 16); 45 if (errno || token == endptr) { 46 fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", 47 name, linenr, token); 48 exit(EXIT_FAILURE); 49 } 50 return value; 51} 52 53int imx8mimage_check_params(struct image_tool_params *params) 54{ 55 return 0; 56} 57 58static void imx8mimage_set_header(void *ptr, struct stat *sbuf, int ifd, 59 struct image_tool_params *params) 60{ 61} 62 63static void imx8mimage_print_header(const void *ptr, struct image_tool_params *params) 64{ 65} 66 67static int imx8mimage_check_image_types(uint8_t type) 68{ 69 return (type == IH_TYPE_IMX8MIMAGE) ? EXIT_SUCCESS : EXIT_FAILURE; 70} 71 72static table_entry_t imx8mimage_cmds[] = { 73 {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, 74 {CMD_FIT, "FIT", "fit image", }, 75 {CMD_SIGNED_HDMI, "SIGNED_HDMI", "signed hdmi image", }, 76 {CMD_LOADER, "LOADER", "loader image", }, 77 {CMD_SECOND_LOADER, "SECOND_LOADER", "2nd loader image", }, 78 {CMD_DDR_FW, "DDR_FW", "ddr firmware", }, 79 {CMD_ROM_VERSION, "ROM_VERSION", "rom version", }, 80 {-1, "", "", }, 81}; 82 83static table_entry_t imx8mimage_ivt_offset[] = { 84 {0x400, "sd", "sd/emmc",}, 85 {0x400, "emmc_fastboot", "emmc fastboot",}, 86 {0x1000, "fspi", "flexspi", }, 87 {-1, "", "Invalid", }, 88}; 89 90static void parse_cfg_cmd(int32_t cmd, char *token, char *name, int lineno) 91{ 92 switch (cmd) { 93 case CMD_BOOT_FROM: 94 ivt_offset = get_table_entry_id(imx8mimage_ivt_offset, 95 "imx8mimage ivt offset", 96 token); 97 if (!strncmp(token, "sd", 2)) 98 rom_image_offset = 0x8000; 99 100 if (rom_version == ROM_V2) 101 ivt_offset = 0; 102 break; 103 case CMD_LOADER: 104 ap_img = token; 105 break; 106 case CMD_SECOND_LOADER: 107 sld_img = token; 108 break; 109 case CMD_SIGNED_HDMI: 110 signed_hdmi = token; 111 break; 112 case CMD_DDR_FW: 113 /* Do nothing */ 114 break; 115 case CMD_ROM_VERSION: 116 if (!strncmp(token, "v2", 2)) { 117 rom_version = ROM_V2; 118 ivt_offset = 0; 119 } else if (!strncmp(token, "v1", 2)) { 120 rom_version = ROM_V1; 121 } 122 break; 123 } 124} 125 126static void parse_cfg_fld(int32_t *cmd, char *token, 127 char *name, int lineno, int fld) 128{ 129 switch (fld) { 130 case CFG_COMMAND: 131 *cmd = get_table_entry_id(imx8mimage_cmds, 132 "imx8mimage commands", token); 133 if (*cmd < 0) { 134 fprintf(stderr, "Error: %s[%d] - Invalid command" "(%s)\n", 135 name, lineno, token); 136 exit(EXIT_FAILURE); 137 } 138 switch (*cmd) { 139 case CMD_FIT: 140 using_fit = 1; 141 break; 142 } 143 break; 144 case CFG_REG_SIZE: 145 parse_cfg_cmd(*cmd, token, name, lineno); 146 break; 147 case CFG_REG_ADDRESS: 148 switch (*cmd) { 149 case CMD_LOADER: 150 ap_start_addr = get_cfg_value(token, name, lineno); 151 break; 152 case CMD_SECOND_LOADER: 153 sld_start_addr = get_cfg_value(token, name, lineno); 154 break; 155 } 156 break; 157 case CFG_REG_VALUE: 158 switch (*cmd) { 159 case CMD_SECOND_LOADER: 160 sld_src_off = get_cfg_value(token, name, lineno); 161 break; 162 } 163 default: 164 break; 165 } 166} 167 168static uint32_t parse_cfg_file(char *name) 169{ 170 FILE *fd = NULL; 171 char *line = NULL; 172 char *token, *saveptr1, *saveptr2; 173 int lineno = 0; 174 int fld; 175 size_t len; 176 int32_t cmd; 177 178 fd = fopen(name, "r"); 179 if (fd == 0) { 180 fprintf(stderr, "Error: %s - Can't open cfg file\n", name); 181 exit(EXIT_FAILURE); 182 } 183 184 /* 185 * Very simple parsing, line starting with # are comments 186 * and are dropped 187 */ 188 while ((getline(&line, &len, fd)) > 0) { 189 lineno++; 190 191 token = strtok_r(line, "\r\n", &saveptr1); 192 if (!token) 193 continue; 194 195 /* Check inside the single line */ 196 for (fld = CFG_COMMAND, cmd = CFG_INVALID, 197 line = token; ; line = NULL, fld++) { 198 token = strtok_r(line, " \t", &saveptr2); 199 if (!token) 200 break; 201 202 /* Drop all text starting with '#' as comments */ 203 if (token[0] == '#') 204 break; 205 206 parse_cfg_fld(&cmd, token, name, lineno, fld); 207 } 208 } 209 210 fclose(fd); 211 return 0; 212} 213 214static void fill_zero(int ifd, int size, int offset) 215{ 216 int fill_size; 217 uint8_t zeros[4096]; 218 int ret; 219 220 memset(zeros, 0, sizeof(zeros)); 221 222 ret = lseek(ifd, offset, SEEK_SET); 223 if (ret < 0) { 224 fprintf(stderr, "%s seek: %s\n", __func__, strerror(errno)); 225 exit(EXIT_FAILURE); 226 } 227 228 while (size) { 229 if (size > 4096) 230 fill_size = 4096; 231 else 232 fill_size = size; 233 234 if (write(ifd, (char *)&zeros, fill_size) != fill_size) { 235 fprintf(stderr, "Write error: %s\n", 236 strerror(errno)); 237 exit(EXIT_FAILURE); 238 } 239 240 size -= fill_size; 241 }; 242} 243 244static void copy_file(int ifd, const char *datafile, int pad, int offset, 245 int datafile_offset) 246{ 247 int dfd; 248 struct stat sbuf; 249 unsigned char *ptr; 250 int tail; 251 uint64_t zero = 0; 252 uint8_t zeros[4096]; 253 int size, ret; 254 255 memset(zeros, 0, sizeof(zeros)); 256 257 dfd = open(datafile, O_RDONLY | O_BINARY); 258 if (dfd < 0) { 259 fprintf(stderr, "Can't open %s: %s\n", 260 datafile, strerror(errno)); 261 exit(EXIT_FAILURE); 262 } 263 264 if (fstat(dfd, &sbuf) < 0) { 265 fprintf(stderr, "Can't stat %s: %s\n", 266 datafile, strerror(errno)); 267 exit(EXIT_FAILURE); 268 } 269 270 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); 271 if (ptr == MAP_FAILED) { 272 fprintf(stderr, "Can't read %s: %s\n", 273 datafile, strerror(errno)); 274 goto err_mmap; 275 } 276 277 size = sbuf.st_size - datafile_offset; 278 ret = lseek(ifd, offset, SEEK_SET); 279 if (ret < 0) { 280 fprintf(stderr, "lseek ifd fail\n"); 281 exit(EXIT_FAILURE); 282 } 283 284 if (write(ifd, ptr + datafile_offset, size) != size) { 285 fprintf(stderr, "Write error %s\n", 286 strerror(errno)); 287 exit(EXIT_FAILURE); 288 } 289 290 tail = size % 4; 291 pad = pad - size; 292 if (pad == 1 && tail != 0) { 293 if (write(ifd, (char *)&zero, 4 - tail) != 4 - tail) { 294 fprintf(stderr, "Write error on %s\n", 295 strerror(errno)); 296 exit(EXIT_FAILURE); 297 } 298 } else if (pad > 1) { 299 while (pad > 0) { 300 int todo = sizeof(zeros); 301 302 if (todo > pad) 303 todo = pad; 304 if (write(ifd, (char *)&zeros, todo) != todo) { 305 fprintf(stderr, "Write error: %s\n", 306 strerror(errno)); 307 exit(EXIT_FAILURE); 308 } 309 pad -= todo; 310 } 311 } 312 313 munmap((void *)ptr, sbuf.st_size); 314err_mmap: 315 close(dfd); 316} 317 318/* Return this IVT offset in the final output file */ 319static int generate_ivt_for_fit(int fd, int fit_offset, uint32_t ep, 320 uint32_t *fit_load_addr) 321{ 322 struct legacy_img_hdr image_header; 323 int ret; 324 325 uint32_t fit_size, load_addr; 326 int align_len = 64 - 1; /* 64 is cacheline size */ 327 328 ret = lseek(fd, fit_offset, SEEK_SET); 329 if (ret < 0) { 330 fprintf(stderr, "lseek fd fail for fit\n"); 331 exit(EXIT_FAILURE); 332 } 333 334 if (read(fd, (char *)&image_header, sizeof(struct legacy_img_hdr)) != 335 sizeof(struct legacy_img_hdr)) { 336 fprintf(stderr, "generate_ivt_for_fit read failed: %s\n", 337 strerror(errno)); 338 exit(EXIT_FAILURE); 339 } 340 341 if (be32_to_cpu(image_header.ih_magic) != FDT_MAGIC) { 342 fprintf(stderr, "%s error: not a FIT file\n", __func__); 343 exit(EXIT_FAILURE); 344 } 345 346 fit_size = fdt_totalsize(&image_header); 347 348 fit_size = ALIGN_IMX(fit_size, ALIGN_SIZE); 349 350 ret = lseek(fd, fit_offset + fit_size, SEEK_SET); 351 if (ret < 0) { 352 fprintf(stderr, "lseek fd fail for fit\n"); 353 exit(EXIT_FAILURE); 354 } 355 356 /* 357 * ep is the u-boot entry. SPL loads the FIT before the u-boot 358 * address. 0x2000 is for CSF_SIZE 359 */ 360 load_addr = (ep - (fit_size + CSF_SIZE) - 512 - align_len) & 361 ~align_len; 362 363 flash_header_v2_t ivt_header = { { 0xd1, 0x2000, 0x40 }, 364 load_addr, 0, 0, 0, 365 (load_addr + fit_size), 366 (load_addr + fit_size + 0x20), 367 0 }; 368 369 if (write(fd, &ivt_header, sizeof(flash_header_v2_t)) != 370 sizeof(flash_header_v2_t)) { 371 fprintf(stderr, "IVT writing error on fit image\n"); 372 exit(EXIT_FAILURE); 373 } 374 375 *fit_load_addr = load_addr; 376 377 return fit_offset + fit_size; 378} 379 380static void dump_header_v2(imx_header_v3_t *imx_header, int index) 381{ 382 const char *ivt_name[2] = {"HDMI FW", "LOADER IMAGE"}; 383 384 fprintf(stdout, "========= IVT HEADER [%s] =========\n", 385 ivt_name[index]); 386 fprintf(stdout, "header.tag: \t\t0x%x\n", 387 imx_header[index].fhdr.header.tag); 388 fprintf(stdout, "header.length: \t\t0x%x\n", 389 imx_header[index].fhdr.header.length); 390 fprintf(stdout, "header.version: \t0x%x\n", 391 imx_header[index].fhdr.header.version); 392 fprintf(stdout, "entry: \t\t\t0x%x\n", 393 imx_header[index].fhdr.entry); 394 fprintf(stdout, "reserved1: \t\t0x%x\n", 395 imx_header[index].fhdr.reserved1); 396 fprintf(stdout, "dcd_ptr: \t\t0x%x\n", 397 imx_header[index].fhdr.dcd_ptr); 398 fprintf(stdout, "boot_data_ptr: \t\t0x%x\n", 399 imx_header[index].fhdr.boot_data_ptr); 400 fprintf(stdout, "self: \t\t\t0x%x\n", 401 imx_header[index].fhdr.self); 402 fprintf(stdout, "csf: \t\t\t0x%x\n", 403 imx_header[index].fhdr.csf); 404 fprintf(stdout, "reserved2: \t\t0x%x\n", 405 imx_header[index].fhdr.reserved2); 406 407 fprintf(stdout, "boot_data.start: \t0x%x\n", 408 imx_header[index].boot_data.start); 409 fprintf(stdout, "boot_data.size: \t0x%x\n", 410 imx_header[index].boot_data.size); 411 fprintf(stdout, "boot_data.plugin: \t0x%x\n", 412 imx_header[index].boot_data.plugin); 413} 414 415#ifdef CONFIG_FSPI_CONF_HEADER 416static int generate_fspi_header (int ifd) 417{ 418 int ret, i = 0; 419 char *val; 420 char lut_str[] = CONFIG_LUT_SEQUENCE; 421 422 fspi_conf fspi_conf_data = { 423 .tag = {0x46, 0x43, 0x46, 0x42}, 424 .version = {0x00, 0x00, 0x01, 0x56}, 425 .reserved_1 = {0x00, 0x00, 0x00, 0x00}, 426 .read_sample = CONFIG_READ_CLK_SOURCE, 427 .datahold = 0x03, 428 .datasetup = 0x03, 429 .coladdrwidth = CONFIG_FSPI_COL_ADDR_W, 430 .devcfgenable = 0x00, 431 .deviceModeType = 0x00, 432 .waitTimeCfgCommands = 0x0000, 433 .devmodeseq = {0x00, 0x00, 0x00, 0x00}, 434 .devmodearg = 0x00000000, 435 .cmd_enable = 0x00, 436 .configModeType = {0x00}, 437 .cmd_seq = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 439 .cmd_arg = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 441 .controllermisc = cpu_to_le32(CONFIG_FSPI_CONTROLLER_MISC), 442 .dev_type = CONFIG_DEVICE_TYPE, 443 .sflash_pad = CONFIG_FLASH_PAD_TYPE, 444 .serial_clk = CONFIG_SERIAL_CLK_FREQUENCY, 445 .lut_custom = CONFIG_LUT_CUSTOM_SEQUENCE, 446 .reserved_2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 447 .sflashA1 = cpu_to_le32(CONFIG_FSPI_FLASH_A1_SIZE), 448 .sflashA2 = 0x00000000, 449 .sflashB1 = 0x00000000, 450 .sflashB2 = 0x00000000, 451 .cspadover = 0x00000000, 452 .sclkpadover = 0x00000000, 453 .datapadover = 0x00000000, 454 .dqspadover = 0x00000000, 455 .timeout = 0x00000000, 456 .commandInt = 0x00000000, 457 .datavalid = {0x0000, 0x0000}, 458 .busyoffset = 0x0000, 459 .busybitpolarity = 0x0000, 460 .lutCustomSeq = {0x00}, 461 .reserved_3 = {0x00} 462 }; 463 464 for (val = strtok(lut_str, ","); val; val = strtok(NULL, ",")) { 465 fspi_conf_data.lut[i++] = strtoul(val, NULL, 16); 466 } 467 468 ret = lseek(ifd, 0, SEEK_CUR); 469 if (write(ifd, &fspi_conf_data, sizeof(fspi_conf_data)) == -1) 470 exit(EXIT_FAILURE); 471 472 ret = lseek(ifd, sizeof(fspi_conf_data), SEEK_CUR); 473 474 return ret; 475} 476#endif 477 478void build_image(int ofd) 479{ 480 int file_off, header_hdmi_off = 0, header_image_off; 481 482#ifdef CONFIG_FSPI_CONF_HEADER 483 int fspi_off, fspi_fd; 484 char *fspi; 485#endif 486 487 int hdmi_fd, ap_fd, sld_fd; 488 uint32_t sld_load_addr = 0; 489 uint32_t csf_off, sld_csf_off = 0; 490 int ret; 491 struct stat sbuf; 492 493 if (!ap_img) { 494 fprintf(stderr, "No LOADER image specificed\n"); 495 exit(EXIT_FAILURE); 496 } 497 498 file_off = 0; 499 500 if (signed_hdmi) { 501 header_hdmi_off = file_off + ivt_offset; 502 503 hdmi_fd = open(signed_hdmi, O_RDONLY | O_BINARY); 504 if (hdmi_fd < 0) { 505 fprintf(stderr, "%s: Can't open: %s\n", 506 signed_hdmi, strerror(errno)); 507 exit(EXIT_FAILURE); 508 } 509 510 if (fstat(hdmi_fd, &sbuf) < 0) { 511 fprintf(stderr, "%s: Can't stat: %s\n", 512 signed_hdmi, strerror(errno)); 513 exit(EXIT_FAILURE); 514 } 515 close(hdmi_fd); 516 517 /* 518 * Aligned to 104KB = 92KB FW image + 0x8000 519 * (IVT and alignment) + 0x4000 (second IVT + CSF) 520 */ 521 file_off += ALIGN_IMX(sbuf.st_size, 522 HDMI_FW_SIZE + 0x2000 + 0x1000); 523 } 524 525 header_image_off = file_off + ivt_offset; 526 527#ifdef CONFIG_FSPI_CONF_HEADER 528 fspi = CONFIG_FSPI_CONF_FILE; 529 fspi_fd = open(fspi, O_RDWR | O_CREAT, S_IRWXU); 530 if (fspi_fd < 0) { 531 fprintf(stderr, "Can't open %s: %s\n", 532 fspi, strerror(errno)); 533 exit(EXIT_FAILURE); 534 } 535 536 fspi_off = generate_fspi_header(fspi_fd); 537 file_off = header_image_off + fspi_off; 538 close(fspi_fd); 539 540#endif 541 ap_fd = open(ap_img, O_RDONLY | O_BINARY); 542 if (ap_fd < 0) { 543 fprintf(stderr, "%s: Can't open: %s\n", 544 ap_img, strerror(errno)); 545 exit(EXIT_FAILURE); 546 } 547 if (fstat(ap_fd, &sbuf) < 0) { 548 fprintf(stderr, "%s: Can't stat: %s\n", 549 ap_img, strerror(errno)); 550 exit(EXIT_FAILURE); 551 } 552 close(ap_fd); 553 554 imx_header[IMAGE_IVT_ID].fhdr.header.tag = IVT_HEADER_TAG; /* 0xD1 */ 555 imx_header[IMAGE_IVT_ID].fhdr.header.length = 556 cpu_to_be16(sizeof(flash_header_v2_t)); 557 imx_header[IMAGE_IVT_ID].fhdr.header.version = IVT_VERSION_V3; /* 0x41 */ 558 imx_header[IMAGE_IVT_ID].fhdr.entry = ap_start_addr; 559 imx_header[IMAGE_IVT_ID].fhdr.self = ap_start_addr - 560 sizeof(imx_header_v3_t); 561 imx_header[IMAGE_IVT_ID].fhdr.dcd_ptr = 0; 562 imx_header[IMAGE_IVT_ID].fhdr.boot_data_ptr = 563 imx_header[IMAGE_IVT_ID].fhdr.self + 564 offsetof(imx_header_v3_t, boot_data); 565 imx_header[IMAGE_IVT_ID].boot_data.start = 566 imx_header[IMAGE_IVT_ID].fhdr.self - ivt_offset; 567 imx_header[IMAGE_IVT_ID].boot_data.size = 568 ALIGN_IMX(sbuf.st_size + sizeof(imx_header_v3_t) + ivt_offset, 569 sector_size); 570 571 image_off = header_image_off + sizeof(imx_header_v3_t); 572 file_off += imx_header[IMAGE_IVT_ID].boot_data.size; 573 574 imx_header[IMAGE_IVT_ID].boot_data.plugin = 0; 575 imx_header[IMAGE_IVT_ID].fhdr.csf = 576 imx_header[IMAGE_IVT_ID].boot_data.start + 577 imx_header[IMAGE_IVT_ID].boot_data.size; 578 579 imx_header[IMAGE_IVT_ID].boot_data.size += CSF_SIZE; /* 8K region dummy CSF */ 580 581 csf_off = file_off; 582 file_off += CSF_SIZE; 583 584 /* Second boot loader image */ 585 if (sld_img) { 586 if (!using_fit) { 587 fprintf(stderr, "Not support no fit\n"); 588 exit(EXIT_FAILURE); 589 } else { 590 sld_header_off = sld_src_off - rom_image_offset; 591 sld_fd = open(sld_img, O_RDONLY | O_BINARY); 592 if (sld_fd < 0) { 593 fprintf(stderr, "%s: Can't open: %s\n", 594 sld_img, strerror(errno)); 595 exit(EXIT_FAILURE); 596 } 597 598 if (fstat(sld_fd, &sbuf) < 0) { 599 fprintf(stderr, "%s: Can't stat: %s\n", 600 sld_img, strerror(errno)); 601 exit(EXIT_FAILURE); 602 } 603 604 close(sld_fd); 605 606 file_off = sld_header_off; 607 file_off += sbuf.st_size + sizeof(struct legacy_img_hdr); 608 } 609 } 610 611 if (signed_hdmi) { 612 header_hdmi_off -= ivt_offset; 613 ret = lseek(ofd, header_hdmi_off, SEEK_SET); 614 if (ret < 0) { 615 fprintf(stderr, "lseek ofd fail for hdmi\n"); 616 exit(EXIT_FAILURE); 617 } 618 619 /* The signed HDMI FW has 0x400 IVT offset, need remove it */ 620 copy_file(ofd, signed_hdmi, 0, header_hdmi_off, 0x400); 621 } 622 623 /* Main Image */ 624 header_image_off -= ivt_offset; 625 image_off -= ivt_offset; 626 ret = lseek(ofd, header_image_off, SEEK_SET); 627 if (ret < 0) { 628 fprintf(stderr, "lseek ofd fail\n"); 629 exit(EXIT_FAILURE); 630 } 631 632 /* Write image header */ 633 if (write(ofd, &imx_header[IMAGE_IVT_ID], sizeof(imx_header_v3_t)) != 634 sizeof(imx_header_v3_t)) { 635 fprintf(stderr, "error writing image hdr\n"); 636 exit(1); 637 } 638 639 copy_file(ofd, ap_img, 0, image_off, 0); 640 641 csf_off -= ivt_offset; 642 fill_zero(ofd, CSF_SIZE, csf_off); 643 644 if (sld_img) { 645 sld_header_off -= ivt_offset; 646 ret = lseek(ofd, sld_header_off, SEEK_SET); 647 if (ret < 0) { 648 fprintf(stderr, "lseek ofd fail for sld_img\n"); 649 exit(EXIT_FAILURE); 650 } 651 652 /* Write image header */ 653 if (!using_fit) { 654 /* TODO */ 655 } else { 656 copy_file(ofd, sld_img, 0, sld_header_off, 0); 657 sld_csf_off = 658 generate_ivt_for_fit(ofd, sld_header_off, 659 sld_start_addr, 660 &sld_load_addr) + 0x20; 661 } 662 } 663 664 if (!signed_hdmi) 665 dump_header_v2(imx_header, 0); 666 dump_header_v2(imx_header, 1); 667 668 fprintf(stdout, "========= OFFSET dump ========="); 669 if (signed_hdmi) { 670 fprintf(stdout, "\nSIGNED HDMI FW:\n"); 671 fprintf(stdout, " header_hdmi_off \t0x%x\n", 672 header_hdmi_off); 673 } 674 675 fprintf(stdout, "\nLoader IMAGE:\n"); 676 fprintf(stdout, " header_image_off \t0x%x\n image_off \t\t0x%x\n csf_off \t\t0x%x\n", 677 header_image_off, image_off, csf_off); 678 fprintf(stdout, " spl hab block: \t0x%x 0x%x 0x%x\n", 679 imx_header[IMAGE_IVT_ID].fhdr.self, header_image_off, 680 csf_off - header_image_off); 681 682 fprintf(stdout, "\nSecond Loader IMAGE:\n"); 683 fprintf(stdout, " sld_header_off \t0x%x\n", 684 sld_header_off); 685 fprintf(stdout, " sld_csf_off \t\t0x%x\n", 686 sld_csf_off); 687 fprintf(stdout, " sld hab block: \t0x%x 0x%x 0x%x\n", 688 sld_load_addr, sld_header_off, sld_csf_off - sld_header_off); 689} 690 691int imx8mimage_copy_image(int outfd, struct image_tool_params *mparams) 692{ 693 /* 694 * SECO FW is a container image, this is to calculate the 695 * 2nd container offset. 696 */ 697 fprintf(stdout, "parsing %s\n", mparams->imagename); 698 parse_cfg_file(mparams->imagename); 699 700 build_image(outfd); 701 702 return 0; 703} 704 705/* 706 * imx8mimage parameters 707 */ 708U_BOOT_IMAGE_TYPE( 709 imx8mimage, 710 "NXP i.MX8M Boot Image support", 711 0, 712 NULL, 713 imx8mimage_check_params, 714 NULL, 715 imx8mimage_print_header, 716 imx8mimage_set_header, 717 NULL, 718 imx8mimage_check_image_types, 719 NULL, 720 NULL 721); 722