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