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