1 /* 2 * Image manipulator for Marvell SoCs 3 * supports Kirkwood, Dove, Armada 370, and Armada XP 4 * 5 * (C) Copyright 2013 Thomas Petazzoni 6 * <thomas.petazzoni@free-electrons.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 * 10 * Not implemented: support for the register headers and secure 11 * headers in v1 images 12 */ 13 14 #include "imagetool.h" 15 #include <limits.h> 16 #include <image.h> 17 #include <stdint.h> 18 #include "kwbimage.h" 19 20 static struct image_cfg_element *image_cfg; 21 static int cfgn; 22 23 struct boot_mode { 24 unsigned int id; 25 const char *name; 26 }; 27 28 struct boot_mode boot_modes[] = { 29 { 0x4D, "i2c" }, 30 { 0x5A, "spi" }, 31 { 0x8B, "nand" }, 32 { 0x78, "sata" }, 33 { 0x9C, "pex" }, 34 { 0x69, "uart" }, 35 { 0xAE, "sdio" }, 36 {}, 37 }; 38 39 struct nand_ecc_mode { 40 unsigned int id; 41 const char *name; 42 }; 43 44 struct nand_ecc_mode nand_ecc_modes[] = { 45 { 0x00, "default" }, 46 { 0x01, "hamming" }, 47 { 0x02, "rs" }, 48 { 0x03, "disabled" }, 49 {}, 50 }; 51 52 /* Used to identify an undefined execution or destination address */ 53 #define ADDR_INVALID ((uint32_t)-1) 54 55 #define BINARY_MAX_ARGS 8 56 57 /* In-memory representation of a line of the configuration file */ 58 59 enum image_cfg_type { 60 IMAGE_CFG_VERSION = 0x1, 61 IMAGE_CFG_BOOT_FROM, 62 IMAGE_CFG_DEST_ADDR, 63 IMAGE_CFG_EXEC_ADDR, 64 IMAGE_CFG_NAND_BLKSZ, 65 IMAGE_CFG_NAND_BADBLK_LOCATION, 66 IMAGE_CFG_NAND_ECC_MODE, 67 IMAGE_CFG_NAND_PAGESZ, 68 IMAGE_CFG_BINARY, 69 IMAGE_CFG_PAYLOAD, 70 IMAGE_CFG_DATA, 71 IMAGE_CFG_BAUDRATE, 72 IMAGE_CFG_DEBUG, 73 74 IMAGE_CFG_COUNT 75 } type; 76 77 static const char * const id_strs[] = { 78 [IMAGE_CFG_VERSION] = "VERSION", 79 [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM", 80 [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR", 81 [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR", 82 [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ", 83 [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION", 84 [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE", 85 [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE", 86 [IMAGE_CFG_BINARY] = "BINARY", 87 [IMAGE_CFG_PAYLOAD] = "PAYLOAD", 88 [IMAGE_CFG_DATA] = "DATA", 89 [IMAGE_CFG_BAUDRATE] = "BAUDRATE", 90 [IMAGE_CFG_DEBUG] = "DEBUG", 91 }; 92 93 struct image_cfg_element { 94 enum image_cfg_type type; 95 union { 96 unsigned int version; 97 unsigned int bootfrom; 98 struct { 99 const char *file; 100 unsigned int args[BINARY_MAX_ARGS]; 101 unsigned int nargs; 102 } binary; 103 const char *payload; 104 unsigned int dstaddr; 105 unsigned int execaddr; 106 unsigned int nandblksz; 107 unsigned int nandbadblklocation; 108 unsigned int nandeccmode; 109 unsigned int nandpagesz; 110 struct ext_hdr_v0_reg regdata; 111 unsigned int baudrate; 112 unsigned int debug; 113 }; 114 }; 115 116 #define IMAGE_CFG_ELEMENT_MAX 256 117 118 /* 119 * Utility functions to manipulate boot mode and ecc modes (convert 120 * them back and forth between description strings and the 121 * corresponding numerical identifiers). 122 */ 123 124 static const char *image_boot_mode_name(unsigned int id) 125 { 126 int i; 127 128 for (i = 0; boot_modes[i].name; i++) 129 if (boot_modes[i].id == id) 130 return boot_modes[i].name; 131 return NULL; 132 } 133 134 int image_boot_mode_id(const char *boot_mode_name) 135 { 136 int i; 137 138 for (i = 0; boot_modes[i].name; i++) 139 if (!strcmp(boot_modes[i].name, boot_mode_name)) 140 return boot_modes[i].id; 141 142 return -1; 143 } 144 145 int image_nand_ecc_mode_id(const char *nand_ecc_mode_name) 146 { 147 int i; 148 149 for (i = 0; nand_ecc_modes[i].name; i++) 150 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name)) 151 return nand_ecc_modes[i].id; 152 return -1; 153 } 154 155 static struct image_cfg_element * 156 image_find_option(unsigned int optiontype) 157 { 158 int i; 159 160 for (i = 0; i < cfgn; i++) { 161 if (image_cfg[i].type == optiontype) 162 return &image_cfg[i]; 163 } 164 165 return NULL; 166 } 167 168 static unsigned int 169 image_count_options(unsigned int optiontype) 170 { 171 int i; 172 unsigned int count = 0; 173 174 for (i = 0; i < cfgn; i++) 175 if (image_cfg[i].type == optiontype) 176 count++; 177 178 return count; 179 } 180 181 /* 182 * Compute a 8-bit checksum of a memory area. This algorithm follows 183 * the requirements of the Marvell SoC BootROM specifications. 184 */ 185 static uint8_t image_checksum8(void *start, uint32_t len) 186 { 187 uint8_t csum = 0; 188 uint8_t *p = start; 189 190 /* check len and return zero checksum if invalid */ 191 if (!len) 192 return 0; 193 194 do { 195 csum += *p; 196 p++; 197 } while (--len); 198 199 return csum; 200 } 201 202 static uint32_t image_checksum32(void *start, uint32_t len) 203 { 204 uint32_t csum = 0; 205 uint32_t *p = start; 206 207 /* check len and return zero checksum if invalid */ 208 if (!len) 209 return 0; 210 211 if (len % sizeof(uint32_t)) { 212 fprintf(stderr, "Length %d is not in multiple of %zu\n", 213 len, sizeof(uint32_t)); 214 return 0; 215 } 216 217 do { 218 csum += *p; 219 p++; 220 len -= sizeof(uint32_t); 221 } while (len > 0); 222 223 return csum; 224 } 225 226 static uint8_t baudrate_to_option(unsigned int baudrate) 227 { 228 switch (baudrate) { 229 case 2400: 230 return MAIN_HDR_V1_OPT_BAUD_2400; 231 case 4800: 232 return MAIN_HDR_V1_OPT_BAUD_4800; 233 case 9600: 234 return MAIN_HDR_V1_OPT_BAUD_9600; 235 case 19200: 236 return MAIN_HDR_V1_OPT_BAUD_19200; 237 case 38400: 238 return MAIN_HDR_V1_OPT_BAUD_38400; 239 case 57600: 240 return MAIN_HDR_V1_OPT_BAUD_57600; 241 case 115200: 242 return MAIN_HDR_V1_OPT_BAUD_115200; 243 default: 244 return MAIN_HDR_V1_OPT_BAUD_DEFAULT; 245 } 246 } 247 248 static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, 249 int payloadsz) 250 { 251 struct image_cfg_element *e; 252 size_t headersz; 253 struct main_hdr_v0 *main_hdr; 254 uint8_t *image; 255 int has_ext = 0; 256 257 /* 258 * Calculate the size of the header and the size of the 259 * payload 260 */ 261 headersz = sizeof(struct main_hdr_v0); 262 263 if (image_count_options(IMAGE_CFG_DATA) > 0) { 264 has_ext = 1; 265 headersz += sizeof(struct ext_hdr_v0); 266 } 267 268 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) { 269 fprintf(stderr, "More than one payload, not possible\n"); 270 return NULL; 271 } 272 273 image = malloc(headersz); 274 if (!image) { 275 fprintf(stderr, "Cannot allocate memory for image\n"); 276 return NULL; 277 } 278 279 memset(image, 0, headersz); 280 281 main_hdr = (struct main_hdr_v0 *)image; 282 283 /* Fill in the main header */ 284 main_hdr->blocksize = 285 cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz); 286 main_hdr->srcaddr = cpu_to_le32(headersz); 287 main_hdr->ext = has_ext; 288 main_hdr->destaddr = cpu_to_le32(params->addr); 289 main_hdr->execaddr = cpu_to_le32(params->ep); 290 291 e = image_find_option(IMAGE_CFG_BOOT_FROM); 292 if (e) 293 main_hdr->blockid = e->bootfrom; 294 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE); 295 if (e) 296 main_hdr->nandeccmode = e->nandeccmode; 297 e = image_find_option(IMAGE_CFG_NAND_PAGESZ); 298 if (e) 299 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz); 300 main_hdr->checksum = image_checksum8(image, 301 sizeof(struct main_hdr_v0)); 302 303 /* Generate the ext header */ 304 if (has_ext) { 305 struct ext_hdr_v0 *ext_hdr; 306 int cfgi, datai; 307 308 ext_hdr = (struct ext_hdr_v0 *) 309 (image + sizeof(struct main_hdr_v0)); 310 ext_hdr->offset = cpu_to_le32(0x40); 311 312 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) { 313 e = &image_cfg[cfgi]; 314 if (e->type != IMAGE_CFG_DATA) 315 continue; 316 317 ext_hdr->rcfg[datai].raddr = 318 cpu_to_le32(e->regdata.raddr); 319 ext_hdr->rcfg[datai].rdata = 320 cpu_to_le32(e->regdata.rdata); 321 datai++; 322 } 323 324 ext_hdr->checksum = image_checksum8(ext_hdr, 325 sizeof(struct ext_hdr_v0)); 326 } 327 328 *imagesz = headersz; 329 return image; 330 } 331 332 static size_t image_headersz_v1(int *hasext) 333 { 334 struct image_cfg_element *binarye; 335 size_t headersz; 336 337 /* 338 * Calculate the size of the header and the size of the 339 * payload 340 */ 341 headersz = sizeof(struct main_hdr_v1); 342 343 if (image_count_options(IMAGE_CFG_BINARY) > 1) { 344 fprintf(stderr, "More than one binary blob, not supported\n"); 345 return 0; 346 } 347 348 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) { 349 fprintf(stderr, "More than one payload, not possible\n"); 350 return 0; 351 } 352 353 binarye = image_find_option(IMAGE_CFG_BINARY); 354 if (binarye) { 355 int ret; 356 struct stat s; 357 358 ret = stat(binarye->binary.file, &s); 359 if (ret < 0) { 360 char cwd[PATH_MAX]; 361 char *dir = cwd; 362 363 memset(cwd, 0, sizeof(cwd)); 364 if (!getcwd(cwd, sizeof(cwd))) { 365 dir = "current working directory"; 366 perror("getcwd() failed"); 367 } 368 369 fprintf(stderr, 370 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" 371 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" 372 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n", 373 binarye->binary.file, dir); 374 return 0; 375 } 376 377 headersz += sizeof(struct opt_hdr_v1) + 378 s.st_size + 379 (binarye->binary.nargs + 2) * sizeof(uint32_t); 380 if (hasext) 381 *hasext = 1; 382 } 383 384 #if defined(CONFIG_SYS_U_BOOT_OFFS) 385 if (headersz > CONFIG_SYS_U_BOOT_OFFS) { 386 fprintf(stderr, 387 "Error: Image header (incl. SPL image) too big!\n"); 388 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n", 389 (int)headersz, CONFIG_SYS_U_BOOT_OFFS); 390 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n"); 391 return 0; 392 } 393 394 headersz = CONFIG_SYS_U_BOOT_OFFS; 395 #endif 396 397 /* 398 * The payload should be aligned on some reasonable 399 * boundary 400 */ 401 return ALIGN_SUP(headersz, 4096); 402 } 403 404 int add_binary_header_v1(uint8_t *cur) 405 { 406 struct image_cfg_element *binarye; 407 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur; 408 uint32_t *args; 409 size_t binhdrsz; 410 struct stat s; 411 int argi; 412 FILE *bin; 413 int ret; 414 415 binarye = image_find_option(IMAGE_CFG_BINARY); 416 417 if (!binarye) 418 return 0; 419 420 hdr->headertype = OPT_HDR_V1_BINARY_TYPE; 421 422 bin = fopen(binarye->binary.file, "r"); 423 if (!bin) { 424 fprintf(stderr, "Cannot open binary file %s\n", 425 binarye->binary.file); 426 return -1; 427 } 428 429 fstat(fileno(bin), &s); 430 431 binhdrsz = sizeof(struct opt_hdr_v1) + 432 (binarye->binary.nargs + 2) * sizeof(uint32_t) + 433 s.st_size; 434 435 /* 436 * The size includes the binary image size, rounded 437 * up to a 4-byte boundary. Plus 4 bytes for the 438 * next-header byte and 3-byte alignment at the end. 439 */ 440 binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4; 441 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF); 442 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; 443 444 cur += sizeof(struct opt_hdr_v1); 445 446 args = (uint32_t *)cur; 447 *args = cpu_to_le32(binarye->binary.nargs); 448 args++; 449 for (argi = 0; argi < binarye->binary.nargs; argi++) 450 args[argi] = cpu_to_le32(binarye->binary.args[argi]); 451 452 cur += (binarye->binary.nargs + 1) * sizeof(uint32_t); 453 454 ret = fread(cur, s.st_size, 1, bin); 455 if (ret != 1) { 456 fprintf(stderr, 457 "Could not read binary image %s\n", 458 binarye->binary.file); 459 return -1; 460 } 461 462 fclose(bin); 463 464 cur += ALIGN_SUP(s.st_size, 4); 465 466 /* 467 * For now, we don't support more than one binary 468 * header, and no other header types are 469 * supported. So, the binary header is necessarily the 470 * last one 471 */ 472 *((uint32_t *)cur) = 0x00000000; 473 474 cur += sizeof(uint32_t); 475 476 return 0; 477 } 478 479 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, 480 int payloadsz) 481 { 482 struct image_cfg_element *e; 483 struct main_hdr_v1 *main_hdr; 484 size_t headersz; 485 uint8_t *image, *cur; 486 int hasext = 0; 487 488 /* 489 * Calculate the size of the header and the size of the 490 * payload 491 */ 492 headersz = image_headersz_v1(&hasext); 493 if (headersz == 0) 494 return NULL; 495 496 image = malloc(headersz); 497 if (!image) { 498 fprintf(stderr, "Cannot allocate memory for image\n"); 499 return NULL; 500 } 501 502 memset(image, 0, headersz); 503 504 main_hdr = (struct main_hdr_v1 *)image; 505 cur = image + sizeof(struct main_hdr_v1); 506 507 /* Fill the main header */ 508 main_hdr->blocksize = 509 cpu_to_le32(payloadsz - headersz + sizeof(uint32_t)); 510 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF); 511 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; 512 main_hdr->destaddr = cpu_to_le32(params->addr) 513 - sizeof(image_header_t); 514 main_hdr->execaddr = cpu_to_le32(params->ep); 515 main_hdr->srcaddr = cpu_to_le32(headersz); 516 main_hdr->ext = hasext; 517 main_hdr->version = 1; 518 e = image_find_option(IMAGE_CFG_BOOT_FROM); 519 if (e) 520 main_hdr->blockid = e->bootfrom; 521 e = image_find_option(IMAGE_CFG_NAND_BLKSZ); 522 if (e) 523 main_hdr->nandblocksize = e->nandblksz / (64 * 1024); 524 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); 525 if (e) 526 main_hdr->nandbadblklocation = e->nandbadblklocation; 527 e = image_find_option(IMAGE_CFG_BAUDRATE); 528 if (e) 529 main_hdr->options = baudrate_to_option(e->baudrate); 530 e = image_find_option(IMAGE_CFG_DEBUG); 531 if (e) 532 main_hdr->flags = e->debug ? 0x1 : 0; 533 534 if (add_binary_header_v1(cur)) 535 return NULL; 536 537 /* Calculate and set the header checksum */ 538 main_hdr->checksum = image_checksum8(main_hdr, headersz); 539 540 *imagesz = headersz; 541 return image; 542 } 543 544 int recognize_keyword(char *keyword) 545 { 546 int kw_id; 547 548 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id) 549 if (!strcmp(keyword, id_strs[kw_id])) 550 return kw_id; 551 552 return 0; 553 } 554 555 static int image_create_config_parse_oneline(char *line, 556 struct image_cfg_element *el) 557 { 558 char *keyword, *saveptr, *value1, *value2; 559 char delimiters[] = " \t"; 560 int keyword_id, ret, argi; 561 char *unknown_msg = "Ignoring unknown line '%s'\n"; 562 563 keyword = strtok_r(line, delimiters, &saveptr); 564 keyword_id = recognize_keyword(keyword); 565 566 if (!keyword_id) { 567 fprintf(stderr, unknown_msg, line); 568 return 0; 569 } 570 571 el->type = keyword_id; 572 573 value1 = strtok_r(NULL, delimiters, &saveptr); 574 575 if (!value1) { 576 fprintf(stderr, "Parameter missing in line '%s'\n", line); 577 return -1; 578 } 579 580 switch (keyword_id) { 581 case IMAGE_CFG_VERSION: 582 el->version = atoi(value1); 583 break; 584 case IMAGE_CFG_BOOT_FROM: 585 ret = image_boot_mode_id(value1); 586 587 if (ret < 0) { 588 fprintf(stderr, "Invalid boot media '%s'\n", value1); 589 return -1; 590 } 591 el->bootfrom = ret; 592 break; 593 case IMAGE_CFG_NAND_BLKSZ: 594 el->nandblksz = strtoul(value1, NULL, 16); 595 break; 596 case IMAGE_CFG_NAND_BADBLK_LOCATION: 597 el->nandbadblklocation = strtoul(value1, NULL, 16); 598 break; 599 case IMAGE_CFG_NAND_ECC_MODE: 600 ret = image_nand_ecc_mode_id(value1); 601 602 if (ret < 0) { 603 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1); 604 return -1; 605 } 606 el->nandeccmode = ret; 607 break; 608 case IMAGE_CFG_NAND_PAGESZ: 609 el->nandpagesz = strtoul(value1, NULL, 16); 610 break; 611 case IMAGE_CFG_BINARY: 612 argi = 0; 613 614 el->binary.file = strdup(value1); 615 while (1) { 616 char *value = strtok_r(NULL, delimiters, &saveptr); 617 618 if (!value) 619 break; 620 el->binary.args[argi] = strtoul(value, NULL, 16); 621 argi++; 622 if (argi >= BINARY_MAX_ARGS) { 623 fprintf(stderr, 624 "Too many arguments for BINARY\n"); 625 return -1; 626 } 627 } 628 el->binary.nargs = argi; 629 break; 630 case IMAGE_CFG_DATA: 631 value2 = strtok_r(NULL, delimiters, &saveptr); 632 633 if (!value1 || !value2) { 634 fprintf(stderr, 635 "Invalid number of arguments for DATA\n"); 636 return -1; 637 } 638 639 el->regdata.raddr = strtoul(value1, NULL, 16); 640 el->regdata.rdata = strtoul(value2, NULL, 16); 641 break; 642 case IMAGE_CFG_BAUDRATE: 643 el->baudrate = strtoul(value1, NULL, 10); 644 break; 645 case IMAGE_CFG_DEBUG: 646 el->debug = strtoul(value1, NULL, 10); 647 break; 648 default: 649 fprintf(stderr, unknown_msg, line); 650 } 651 652 return 0; 653 } 654 655 /* 656 * Parse the configuration file 'fcfg' into the array of configuration 657 * elements 'image_cfg', and return the number of configuration 658 * elements in 'cfgn'. 659 */ 660 static int image_create_config_parse(FILE *fcfg) 661 { 662 int ret; 663 int cfgi = 0; 664 665 /* Parse the configuration file */ 666 while (!feof(fcfg)) { 667 char *line; 668 char buf[256]; 669 670 /* Read the current line */ 671 memset(buf, 0, sizeof(buf)); 672 line = fgets(buf, sizeof(buf), fcfg); 673 if (!line) 674 break; 675 676 /* Ignore useless lines */ 677 if (line[0] == '\n' || line[0] == '#') 678 continue; 679 680 /* Strip final newline */ 681 if (line[strlen(line) - 1] == '\n') 682 line[strlen(line) - 1] = 0; 683 684 /* Parse the current line */ 685 ret = image_create_config_parse_oneline(line, 686 &image_cfg[cfgi]); 687 if (ret) 688 return ret; 689 690 cfgi++; 691 692 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) { 693 fprintf(stderr, 694 "Too many configuration elements in .cfg file\n"); 695 return -1; 696 } 697 } 698 699 cfgn = cfgi; 700 return 0; 701 } 702 703 static int image_get_version(void) 704 { 705 struct image_cfg_element *e; 706 707 e = image_find_option(IMAGE_CFG_VERSION); 708 if (!e) 709 return -1; 710 711 return e->version; 712 } 713 714 static int image_version_file(const char *input) 715 { 716 FILE *fcfg; 717 int version; 718 int ret; 719 720 fcfg = fopen(input, "r"); 721 if (!fcfg) { 722 fprintf(stderr, "Could not open input file %s\n", input); 723 return -1; 724 } 725 726 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX * 727 sizeof(struct image_cfg_element)); 728 if (!image_cfg) { 729 fprintf(stderr, "Cannot allocate memory\n"); 730 fclose(fcfg); 731 return -1; 732 } 733 734 memset(image_cfg, 0, 735 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); 736 rewind(fcfg); 737 738 ret = image_create_config_parse(fcfg); 739 fclose(fcfg); 740 if (ret) { 741 free(image_cfg); 742 return -1; 743 } 744 745 version = image_get_version(); 746 /* Fallback to version 0 is no version is provided in the cfg file */ 747 if (version == -1) 748 version = 0; 749 750 free(image_cfg); 751 752 return version; 753 } 754 755 static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, 756 struct image_tool_params *params) 757 { 758 FILE *fcfg; 759 void *image = NULL; 760 int version; 761 size_t headersz = 0; 762 uint32_t checksum; 763 int ret; 764 int size; 765 766 fcfg = fopen(params->imagename, "r"); 767 if (!fcfg) { 768 fprintf(stderr, "Could not open input file %s\n", 769 params->imagename); 770 exit(EXIT_FAILURE); 771 } 772 773 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX * 774 sizeof(struct image_cfg_element)); 775 if (!image_cfg) { 776 fprintf(stderr, "Cannot allocate memory\n"); 777 fclose(fcfg); 778 exit(EXIT_FAILURE); 779 } 780 781 memset(image_cfg, 0, 782 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); 783 rewind(fcfg); 784 785 ret = image_create_config_parse(fcfg); 786 fclose(fcfg); 787 if (ret) { 788 free(image_cfg); 789 exit(EXIT_FAILURE); 790 } 791 792 /* The MVEBU BootROM does not allow non word aligned payloads */ 793 sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4); 794 795 version = image_get_version(); 796 switch (version) { 797 /* 798 * Fallback to version 0 if no version is provided in the 799 * cfg file 800 */ 801 case -1: 802 case 0: 803 image = image_create_v0(&headersz, params, sbuf->st_size); 804 break; 805 806 case 1: 807 image = image_create_v1(&headersz, params, sbuf->st_size); 808 break; 809 810 default: 811 fprintf(stderr, "Unsupported version %d\n", version); 812 free(image_cfg); 813 exit(EXIT_FAILURE); 814 } 815 816 if (!image) { 817 fprintf(stderr, "Could not create image\n"); 818 free(image_cfg); 819 exit(EXIT_FAILURE); 820 } 821 822 free(image_cfg); 823 824 /* Build and add image checksum header */ 825 checksum = 826 cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size)); 827 size = write(ifd, &checksum, sizeof(uint32_t)); 828 if (size != sizeof(uint32_t)) { 829 fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n", 830 params->cmdname, size, params->imagefile); 831 exit(EXIT_FAILURE); 832 } 833 834 sbuf->st_size += sizeof(uint32_t); 835 836 /* Finally copy the header into the image area */ 837 memcpy(ptr, image, headersz); 838 839 free(image); 840 } 841 842 static void kwbimage_print_header(const void *ptr) 843 { 844 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr; 845 846 printf("Image Type: MVEBU Boot from %s Image\n", 847 image_boot_mode_name(mhdr->blockid)); 848 printf("Image version:%d\n", image_version((void *)ptr)); 849 printf("Data Size: "); 850 genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); 851 printf("Load Address: %08x\n", mhdr->destaddr); 852 printf("Entry Point: %08x\n", mhdr->execaddr); 853 } 854 855 static int kwbimage_check_image_types(uint8_t type) 856 { 857 if (type == IH_TYPE_KWBIMAGE) 858 return EXIT_SUCCESS; 859 860 return EXIT_FAILURE; 861 } 862 863 static int kwbimage_verify_header(unsigned char *ptr, int image_size, 864 struct image_tool_params *params) 865 { 866 struct main_hdr_v0 *main_hdr; 867 uint8_t checksum; 868 869 main_hdr = (struct main_hdr_v0 *)ptr; 870 checksum = image_checksum8(ptr, 871 sizeof(struct main_hdr_v0) 872 - sizeof(uint8_t)); 873 if (checksum != main_hdr->checksum) 874 return -FDT_ERR_BADSTRUCTURE; 875 876 /* Only version 0 extended header has checksum */ 877 if (image_version((void *)ptr) == 0) { 878 struct ext_hdr_v0 *ext_hdr; 879 880 ext_hdr = (struct ext_hdr_v0 *) 881 (ptr + sizeof(struct main_hdr_v0)); 882 checksum = image_checksum8(ext_hdr, 883 sizeof(struct ext_hdr_v0) 884 - sizeof(uint8_t)); 885 if (checksum != ext_hdr->checksum) 886 return -FDT_ERR_BADSTRUCTURE; 887 } 888 889 return 0; 890 } 891 892 static int kwbimage_generate(struct image_tool_params *params, 893 struct image_type_params *tparams) 894 { 895 int alloc_len; 896 void *hdr; 897 int version = 0; 898 899 version = image_version_file(params->imagename); 900 if (version == 0) { 901 alloc_len = sizeof(struct main_hdr_v0) + 902 sizeof(struct ext_hdr_v0); 903 } else { 904 alloc_len = image_headersz_v1(NULL); 905 } 906 907 hdr = malloc(alloc_len); 908 if (!hdr) { 909 fprintf(stderr, "%s: malloc return failure: %s\n", 910 params->cmdname, strerror(errno)); 911 exit(EXIT_FAILURE); 912 } 913 914 memset(hdr, 0, alloc_len); 915 tparams->header_size = alloc_len; 916 tparams->hdr = hdr; 917 918 /* 919 * The resulting image needs to be 4-byte aligned. At least 920 * the Marvell hdrparser tool complains if its unaligned. 921 * By returning 1 here in this function, called via 922 * tparams->vrec_header() in mkimage.c, mkimage will 923 * automatically pad the the resulting image to a 4-byte 924 * size if necessary. 925 */ 926 return 1; 927 } 928 929 /* 930 * Report Error if xflag is set in addition to default 931 */ 932 static int kwbimage_check_params(struct image_tool_params *params) 933 { 934 if (!strlen(params->imagename)) { 935 char *msg = "Configuration file for kwbimage creation omitted"; 936 937 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg); 938 return CFG_INVALID; 939 } 940 941 return (params->dflag && (params->fflag || params->lflag)) || 942 (params->fflag && (params->dflag || params->lflag)) || 943 (params->lflag && (params->dflag || params->fflag)) || 944 (params->xflag) || !(strlen(params->imagename)); 945 } 946 947 /* 948 * kwbimage type parameters definition 949 */ 950 U_BOOT_IMAGE_TYPE( 951 kwbimage, 952 "Marvell MVEBU Boot Image support", 953 0, 954 NULL, 955 kwbimage_check_params, 956 kwbimage_verify_header, 957 kwbimage_print_header, 958 kwbimage_set_header, 959 NULL, 960 kwbimage_check_image_types, 961 NULL, 962 kwbimage_generate 963 ); 964