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