1 /* 2 * (C) Copyright 2009 3 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. 4 * 5 * (C) Copyright 2008 6 * Marvell Semiconductor <www.marvell.com> 7 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include "imagetool.h" 13 #include <image.h> 14 #include "imximage.h" 15 16 #define UNDEFINED 0xFFFFFFFF 17 18 /* 19 * Supported commands for configuration file 20 */ 21 static table_entry_t imximage_cmds[] = { 22 {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, 23 {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, 24 {CMD_DATA, "DATA", "Reg Write Data", }, 25 {CMD_CSF, "CSF", "Command Sequence File", }, 26 {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, 27 {-1, "", "", }, 28 }; 29 30 /* 31 * Supported Boot options for configuration file 32 * this is needed to set the correct flash offset 33 */ 34 static table_entry_t imximage_boot_offset[] = { 35 {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, 36 {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, 37 {FLASH_OFFSET_NOR, "nor", "NOR Flash", }, 38 {FLASH_OFFSET_SATA, "sata", "SATA Disk", }, 39 {FLASH_OFFSET_SD, "sd", "SD Card", }, 40 {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, 41 {FLASH_OFFSET_QSPI, "qspi", "QSPI NOR Flash",}, 42 {-1, "", "Invalid", }, 43 }; 44 45 /* 46 * Supported Boot options for configuration file 47 * this is needed to determine the initial load size 48 */ 49 static table_entry_t imximage_boot_loadsize[] = { 50 {FLASH_LOADSIZE_ONENAND, "onenand", "OneNAND Flash",}, 51 {FLASH_LOADSIZE_NAND, "nand", "NAND Flash", }, 52 {FLASH_LOADSIZE_NOR, "nor", "NOR Flash", }, 53 {FLASH_LOADSIZE_SATA, "sata", "SATA Disk", }, 54 {FLASH_LOADSIZE_SD, "sd", "SD Card", }, 55 {FLASH_LOADSIZE_SPI, "spi", "SPI Flash", }, 56 {FLASH_LOADSIZE_QSPI, "qspi", "QSPI NOR Flash",}, 57 {-1, "", "Invalid", }, 58 }; 59 60 /* 61 * IMXIMAGE version definition for i.MX chips 62 */ 63 static table_entry_t imximage_versions[] = { 64 {IMXIMAGE_V1, "", " (i.MX25/35/51 compatible)", }, 65 {IMXIMAGE_V2, "", " (i.MX53/6 compatible)", }, 66 {-1, "", " (Invalid)", }, 67 }; 68 69 static struct imx_header imximage_header; 70 static uint32_t imximage_version; 71 /* 72 * Image Vector Table Offset 73 * Initialized to a wrong not 4-bytes aligned address to 74 * check if it is was set by the cfg file. 75 */ 76 static uint32_t imximage_ivt_offset = UNDEFINED; 77 static uint32_t imximage_csf_size = UNDEFINED; 78 /* Initial Load Region Size */ 79 static uint32_t imximage_init_loadsize; 80 81 static set_dcd_val_t set_dcd_val; 82 static set_dcd_rst_t set_dcd_rst; 83 static set_imx_hdr_t set_imx_hdr; 84 static uint32_t max_dcd_entries; 85 static uint32_t *header_size_ptr; 86 static uint32_t *csf_ptr; 87 88 static uint32_t get_cfg_value(char *token, char *name, int linenr) 89 { 90 char *endptr; 91 uint32_t value; 92 93 errno = 0; 94 value = strtoul(token, &endptr, 16); 95 if (errno || (token == endptr)) { 96 fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", 97 name, linenr, token); 98 exit(EXIT_FAILURE); 99 } 100 return value; 101 } 102 103 static uint32_t detect_imximage_version(struct imx_header *imx_hdr) 104 { 105 imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; 106 imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; 107 flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; 108 flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; 109 110 /* Try to detect V1 */ 111 if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) && 112 (hdr_v1->dcd_table.preamble.barker == DCD_BARKER)) 113 return IMXIMAGE_V1; 114 115 /* Try to detect V2 */ 116 if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && 117 (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) 118 return IMXIMAGE_V2; 119 120 return IMXIMAGE_VER_INVALID; 121 } 122 123 static void err_imximage_version(int version) 124 { 125 fprintf(stderr, 126 "Error: Unsupported imximage version:%d\n", version); 127 128 exit(EXIT_FAILURE); 129 } 130 131 static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno, 132 int fld, uint32_t value, uint32_t off) 133 { 134 dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; 135 136 switch (fld) { 137 case CFG_REG_SIZE: 138 /* Byte, halfword, word */ 139 if ((value != 1) && (value != 2) && (value != 4)) { 140 fprintf(stderr, "Error: %s[%d] - " 141 "Invalid register size " "(%d)\n", 142 name, lineno, value); 143 exit(EXIT_FAILURE); 144 } 145 dcd_v1->addr_data[off].type = value; 146 break; 147 case CFG_REG_ADDRESS: 148 dcd_v1->addr_data[off].addr = value; 149 break; 150 case CFG_REG_VALUE: 151 dcd_v1->addr_data[off].value = value; 152 break; 153 default: 154 break; 155 156 } 157 } 158 159 static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno, 160 int fld, uint32_t value, uint32_t off) 161 { 162 dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; 163 164 switch (fld) { 165 case CFG_REG_ADDRESS: 166 dcd_v2->addr_data[off].addr = cpu_to_be32(value); 167 break; 168 case CFG_REG_VALUE: 169 dcd_v2->addr_data[off].value = cpu_to_be32(value); 170 break; 171 default: 172 break; 173 174 } 175 } 176 177 /* 178 * Complete setting up the rest field of DCD of V1 179 * such as barker code and DCD data length. 180 */ 181 static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len, 182 char *name, int lineno) 183 { 184 dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; 185 186 dcd_v1->preamble.barker = DCD_BARKER; 187 dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); 188 } 189 190 /* 191 * Complete setting up the reset field of DCD of V2 192 * such as DCD tag, version, length, etc. 193 */ 194 static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len, 195 char *name, int lineno) 196 { 197 dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; 198 199 dcd_v2->header.tag = DCD_HEADER_TAG; 200 dcd_v2->header.length = cpu_to_be16( 201 dcd_len * sizeof(dcd_addr_data_t) + 8); 202 dcd_v2->header.version = DCD_VERSION; 203 dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; 204 dcd_v2->write_dcd_command.length = cpu_to_be16( 205 dcd_len * sizeof(dcd_addr_data_t) + 4); 206 dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; 207 } 208 209 static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, 210 uint32_t entry_point, uint32_t flash_offset) 211 { 212 imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1; 213 flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; 214 dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; 215 uint32_t hdr_base; 216 uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr) 217 - ((char *)imxhdr)); 218 219 /* Set magic number */ 220 fhdr_v1->app_code_barker = APP_CODE_BARKER; 221 222 /* TODO: check i.MX image V1 handling, for now use 'old' style */ 223 hdr_base = entry_point - 4096; 224 fhdr_v1->app_dest_ptr = hdr_base - flash_offset; 225 fhdr_v1->app_code_jump_vector = entry_point; 226 227 fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr); 228 fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table); 229 230 /* Security feature are not supported */ 231 fhdr_v1->app_code_csf = 0; 232 fhdr_v1->super_root_key = 0; 233 header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4); 234 } 235 236 static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len, 237 uint32_t entry_point, uint32_t flash_offset) 238 { 239 imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; 240 flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; 241 uint32_t hdr_base; 242 243 /* Set magic number */ 244 fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ 245 fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t)); 246 fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ 247 248 fhdr_v2->entry = entry_point; 249 fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; 250 hdr_base = entry_point - imximage_init_loadsize + 251 flash_offset; 252 fhdr_v2->self = hdr_base; 253 fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table); 254 fhdr_v2->boot_data_ptr = hdr_base 255 + offsetof(imx_header_v2_t, boot_data); 256 hdr_v2->boot_data.start = entry_point - imximage_init_loadsize; 257 258 fhdr_v2->csf = 0; 259 260 header_size_ptr = &hdr_v2->boot_data.size; 261 csf_ptr = &fhdr_v2->csf; 262 } 263 264 static void set_hdr_func(void) 265 { 266 switch (imximage_version) { 267 case IMXIMAGE_V1: 268 set_dcd_val = set_dcd_val_v1; 269 set_dcd_rst = set_dcd_rst_v1; 270 set_imx_hdr = set_imx_hdr_v1; 271 max_dcd_entries = MAX_HW_CFG_SIZE_V1; 272 break; 273 case IMXIMAGE_V2: 274 set_dcd_val = set_dcd_val_v2; 275 set_dcd_rst = set_dcd_rst_v2; 276 set_imx_hdr = set_imx_hdr_v2; 277 max_dcd_entries = MAX_HW_CFG_SIZE_V2; 278 break; 279 default: 280 err_imximage_version(imximage_version); 281 break; 282 } 283 } 284 285 static void print_hdr_v1(struct imx_header *imx_hdr) 286 { 287 imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; 288 flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; 289 dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; 290 uint32_t size, length, ver; 291 292 size = dcd_v1->preamble.length; 293 if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) { 294 fprintf(stderr, 295 "Error: Image corrupt DCD size %d exceed maximum %d\n", 296 (uint32_t)(size / sizeof(dcd_type_addr_data_t)), 297 MAX_HW_CFG_SIZE_V1); 298 exit(EXIT_FAILURE); 299 } 300 301 length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t); 302 ver = detect_imximage_version(imx_hdr); 303 304 printf("Image Type: Freescale IMX Boot Image\n"); 305 printf("Image Ver: %x", ver); 306 printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver)); 307 printf("Data Size: "); 308 genimg_print_size(dcd_v1->addr_data[length].type); 309 printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr); 310 printf("Entry Point: %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector); 311 } 312 313 static void print_hdr_v2(struct imx_header *imx_hdr) 314 { 315 imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; 316 flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; 317 dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; 318 uint32_t size, version; 319 320 size = be16_to_cpu(dcd_v2->header.length) - 8; 321 if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { 322 fprintf(stderr, 323 "Error: Image corrupt DCD size %d exceed maximum %d\n", 324 (uint32_t)(size / sizeof(dcd_addr_data_t)), 325 MAX_HW_CFG_SIZE_V2); 326 exit(EXIT_FAILURE); 327 } 328 329 version = detect_imximage_version(imx_hdr); 330 331 printf("Image Type: Freescale IMX Boot Image\n"); 332 printf("Image Ver: %x", version); 333 printf("%s\n", get_table_entry_name(imximage_versions, NULL, version)); 334 printf("Data Size: "); 335 genimg_print_size(hdr_v2->boot_data.size); 336 printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); 337 printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); 338 if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) && 339 (imximage_csf_size != UNDEFINED)) { 340 printf("HAB Blocks: %08x %08x %08x\n", 341 (uint32_t)fhdr_v2->self, 0, 342 hdr_v2->boot_data.size - imximage_ivt_offset - 343 imximage_csf_size); 344 } 345 } 346 347 static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, 348 char *name, int lineno, int fld, int dcd_len) 349 { 350 int value; 351 static int cmd_ver_first = ~0; 352 353 switch (cmd) { 354 case CMD_IMAGE_VERSION: 355 imximage_version = get_cfg_value(token, name, lineno); 356 if (cmd_ver_first == 0) { 357 fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION " 358 "command need be the first before other " 359 "valid command in the file\n", name, lineno); 360 exit(EXIT_FAILURE); 361 } 362 cmd_ver_first = 1; 363 set_hdr_func(); 364 break; 365 case CMD_BOOT_FROM: 366 imximage_ivt_offset = get_table_entry_id(imximage_boot_offset, 367 "imximage boot option", token); 368 if (imximage_ivt_offset == -1) { 369 fprintf(stderr, "Error: %s[%d] -Invalid boot device" 370 "(%s)\n", name, lineno, token); 371 exit(EXIT_FAILURE); 372 } 373 374 imximage_init_loadsize = 375 get_table_entry_id(imximage_boot_loadsize, 376 "imximage boot option", token); 377 378 if (imximage_init_loadsize == -1) { 379 fprintf(stderr, 380 "Error: %s[%d] -Invalid boot device(%s)\n", 381 name, lineno, token); 382 exit(EXIT_FAILURE); 383 } 384 385 /* 386 * The SOC loads from the storage starting at address 0 387 * then ensures that the load size contains the offset 388 */ 389 if (imximage_init_loadsize < imximage_ivt_offset) 390 imximage_init_loadsize = imximage_ivt_offset; 391 if (unlikely(cmd_ver_first != 1)) 392 cmd_ver_first = 0; 393 break; 394 case CMD_BOOT_OFFSET: 395 imximage_ivt_offset = get_cfg_value(token, name, lineno); 396 if (unlikely(cmd_ver_first != 1)) 397 cmd_ver_first = 0; 398 break; 399 case CMD_DATA: 400 value = get_cfg_value(token, name, lineno); 401 (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len); 402 if (unlikely(cmd_ver_first != 1)) 403 cmd_ver_first = 0; 404 break; 405 case CMD_CSF: 406 if (imximage_version != 2) { 407 fprintf(stderr, 408 "Error: %s[%d] - CSF only supported for VERSION 2(%s)\n", 409 name, lineno, token); 410 exit(EXIT_FAILURE); 411 } 412 imximage_csf_size = get_cfg_value(token, name, lineno); 413 if (unlikely(cmd_ver_first != 1)) 414 cmd_ver_first = 0; 415 break; 416 } 417 } 418 419 static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, 420 char *token, char *name, int lineno, int fld, int *dcd_len) 421 { 422 int value; 423 424 switch (fld) { 425 case CFG_COMMAND: 426 *cmd = get_table_entry_id(imximage_cmds, 427 "imximage commands", token); 428 if (*cmd < 0) { 429 fprintf(stderr, "Error: %s[%d] - Invalid command" 430 "(%s)\n", name, lineno, token); 431 exit(EXIT_FAILURE); 432 } 433 break; 434 case CFG_REG_SIZE: 435 parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len); 436 break; 437 case CFG_REG_ADDRESS: 438 case CFG_REG_VALUE: 439 if (*cmd != CMD_DATA) 440 return; 441 442 value = get_cfg_value(token, name, lineno); 443 (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len); 444 445 if (fld == CFG_REG_VALUE) { 446 (*dcd_len)++; 447 if (*dcd_len > max_dcd_entries) { 448 fprintf(stderr, "Error: %s[%d] -" 449 "DCD table exceeds maximum size(%d)\n", 450 name, lineno, max_dcd_entries); 451 exit(EXIT_FAILURE); 452 } 453 } 454 break; 455 default: 456 break; 457 } 458 } 459 static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name) 460 { 461 FILE *fd = NULL; 462 char *line = NULL; 463 char *token, *saveptr1, *saveptr2; 464 int lineno = 0; 465 int fld; 466 size_t len; 467 int dcd_len = 0; 468 int32_t cmd; 469 470 fd = fopen(name, "r"); 471 if (fd == 0) { 472 fprintf(stderr, "Error: %s - Can't open DCD file\n", name); 473 exit(EXIT_FAILURE); 474 } 475 476 /* 477 * Very simple parsing, line starting with # are comments 478 * and are dropped 479 */ 480 while ((getline(&line, &len, fd)) > 0) { 481 lineno++; 482 483 token = strtok_r(line, "\r\n", &saveptr1); 484 if (token == NULL) 485 continue; 486 487 /* Check inside the single line */ 488 for (fld = CFG_COMMAND, cmd = CMD_INVALID, 489 line = token; ; line = NULL, fld++) { 490 token = strtok_r(line, " \t", &saveptr2); 491 if (token == NULL) 492 break; 493 494 /* Drop all text starting with '#' as comments */ 495 if (token[0] == '#') 496 break; 497 498 parse_cfg_fld(imxhdr, &cmd, token, name, 499 lineno, fld, &dcd_len); 500 } 501 502 } 503 504 (*set_dcd_rst)(imxhdr, dcd_len, name, lineno); 505 fclose(fd); 506 507 /* Exit if there is no BOOT_FROM field specifying the flash_offset */ 508 if (imximage_ivt_offset == FLASH_OFFSET_UNDEFINED) { 509 fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name); 510 exit(EXIT_FAILURE); 511 } 512 return dcd_len; 513 } 514 515 516 static int imximage_check_image_types(uint8_t type) 517 { 518 if (type == IH_TYPE_IMXIMAGE) 519 return EXIT_SUCCESS; 520 else 521 return EXIT_FAILURE; 522 } 523 524 static int imximage_verify_header(unsigned char *ptr, int image_size, 525 struct image_tool_params *params) 526 { 527 struct imx_header *imx_hdr = (struct imx_header *) ptr; 528 529 if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID) 530 return -FDT_ERR_BADSTRUCTURE; 531 532 return 0; 533 } 534 535 static void imximage_print_header(const void *ptr) 536 { 537 struct imx_header *imx_hdr = (struct imx_header *) ptr; 538 uint32_t version = detect_imximage_version(imx_hdr); 539 540 switch (version) { 541 case IMXIMAGE_V1: 542 print_hdr_v1(imx_hdr); 543 break; 544 case IMXIMAGE_V2: 545 print_hdr_v2(imx_hdr); 546 break; 547 default: 548 err_imximage_version(version); 549 break; 550 } 551 } 552 553 static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, 554 struct image_tool_params *params) 555 { 556 struct imx_header *imxhdr = (struct imx_header *)ptr; 557 uint32_t dcd_len; 558 559 /* 560 * In order to not change the old imx cfg file 561 * by adding VERSION command into it, here need 562 * set up function ptr group to V1 by default. 563 */ 564 imximage_version = IMXIMAGE_V1; 565 /* Be able to detect if the cfg file has no BOOT_FROM tag */ 566 imximage_ivt_offset = FLASH_OFFSET_UNDEFINED; 567 imximage_csf_size = 0; 568 set_hdr_func(); 569 570 /* Parse dcd configuration file */ 571 dcd_len = parse_cfg_file(imxhdr, params->imagename); 572 573 if (imximage_version == IMXIMAGE_V2) { 574 if (imximage_init_loadsize < imximage_ivt_offset + 575 sizeof(imx_header_v2_t)) 576 imximage_init_loadsize = imximage_ivt_offset + 577 sizeof(imx_header_v2_t); 578 } 579 580 /* Set the imx header */ 581 (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imximage_ivt_offset); 582 583 /* 584 * ROM bug alert 585 * 586 * MX53 only loads 512 byte multiples in case of SD boot. 587 * MX53 only loads NAND page multiples in case of NAND boot and 588 * supports up to 4096 byte large pages, thus align to 4096. 589 * 590 * The remaining fraction of a block bytes would not be loaded! 591 */ 592 *header_size_ptr = ROUND((sbuf->st_size + imximage_ivt_offset), 4096); 593 594 if (csf_ptr && imximage_csf_size) { 595 *csf_ptr = params->ep - imximage_init_loadsize + 596 *header_size_ptr; 597 *header_size_ptr += imximage_csf_size; 598 } 599 } 600 601 int imximage_check_params(struct image_tool_params *params) 602 { 603 if (!params) 604 return CFG_INVALID; 605 if (!strlen(params->imagename)) { 606 fprintf(stderr, "Error: %s - Configuration file not specified, " 607 "it is needed for imximage generation\n", 608 params->cmdname); 609 return CFG_INVALID; 610 } 611 /* 612 * Check parameters: 613 * XIP is not allowed and verify that incompatible 614 * parameters are not sent at the same time 615 * For example, if list is required a data image must not be provided 616 */ 617 return (params->dflag && (params->fflag || params->lflag)) || 618 (params->fflag && (params->dflag || params->lflag)) || 619 (params->lflag && (params->dflag || params->fflag)) || 620 (params->xflag) || !(strlen(params->imagename)); 621 } 622 623 static int imximage_generate(struct image_tool_params *params, 624 struct image_type_params *tparams) 625 { 626 struct imx_header *imxhdr; 627 size_t alloc_len; 628 struct stat sbuf; 629 char *datafile = params->datafile; 630 uint32_t pad_len; 631 632 memset(&imximage_header, 0, sizeof(imximage_header)); 633 634 /* 635 * In order to not change the old imx cfg file 636 * by adding VERSION command into it, here need 637 * set up function ptr group to V1 by default. 638 */ 639 imximage_version = IMXIMAGE_V1; 640 /* Be able to detect if the cfg file has no BOOT_FROM tag */ 641 imximage_ivt_offset = FLASH_OFFSET_UNDEFINED; 642 imximage_csf_size = 0; 643 set_hdr_func(); 644 645 /* Parse dcd configuration file */ 646 parse_cfg_file(&imximage_header, params->imagename); 647 648 /* TODO: check i.MX image V1 handling, for now use 'old' style */ 649 if (imximage_version == IMXIMAGE_V1) { 650 alloc_len = 4096; 651 } else { 652 if (imximage_init_loadsize < imximage_ivt_offset + 653 sizeof(imx_header_v2_t)) 654 imximage_init_loadsize = imximage_ivt_offset + 655 sizeof(imx_header_v2_t); 656 alloc_len = imximage_init_loadsize - imximage_ivt_offset; 657 } 658 659 if (alloc_len < sizeof(struct imx_header)) { 660 fprintf(stderr, "%s: header error\n", 661 params->cmdname); 662 exit(EXIT_FAILURE); 663 } 664 665 imxhdr = malloc(alloc_len); 666 667 if (!imxhdr) { 668 fprintf(stderr, "%s: malloc return failure: %s\n", 669 params->cmdname, strerror(errno)); 670 exit(EXIT_FAILURE); 671 } 672 673 memset(imxhdr, 0, alloc_len); 674 675 tparams->header_size = alloc_len; 676 tparams->hdr = imxhdr; 677 678 /* determine data image file length */ 679 680 if (stat(datafile, &sbuf) < 0) { 681 fprintf(stderr, "%s: Can't stat %s: %s\n", 682 params->cmdname, datafile, strerror(errno)); 683 exit(EXIT_FAILURE); 684 } 685 686 pad_len = ROUND(sbuf.st_size, 4096) - sbuf.st_size; 687 688 /* TODO: check i.MX image V1 handling, for now use 'old' style */ 689 if (imximage_version == IMXIMAGE_V1) 690 return 0; 691 else 692 return pad_len; 693 } 694 695 696 /* 697 * imximage parameters 698 */ 699 U_BOOT_IMAGE_TYPE( 700 imximage, 701 "Freescale i.MX Boot Image support", 702 0, 703 NULL, 704 imximage_check_params, 705 imximage_verify_header, 706 imximage_print_header, 707 imximage_set_header, 708 NULL, 709 imximage_check_image_types, 710 NULL, 711 imximage_generate 712 ); 713