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(struct image_tool_params *params, 312 int *hasext) 313 { 314 struct image_cfg_element *binarye; 315 size_t headersz; 316 317 /* 318 * Calculate the size of the header and the size of the 319 * payload 320 */ 321 headersz = sizeof(struct main_hdr_v1); 322 323 if (image_count_options(IMAGE_CFG_BINARY) > 1) { 324 fprintf(stderr, "More than one binary blob, not supported\n"); 325 return 0; 326 } 327 328 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) { 329 fprintf(stderr, "More than one payload, not possible\n"); 330 return 0; 331 } 332 333 binarye = image_find_option(IMAGE_CFG_BINARY); 334 if (binarye) { 335 int ret; 336 struct stat s; 337 338 ret = stat(binarye->binary.file, &s); 339 if (ret < 0) { 340 char cwd[PATH_MAX]; 341 char *dir = cwd; 342 343 memset(cwd, 0, sizeof(cwd)); 344 if (!getcwd(cwd, sizeof(cwd))) { 345 dir = "current working directory"; 346 perror("getcwd() failed"); 347 } 348 349 fprintf(stderr, 350 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" 351 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" 352 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n", 353 binarye->binary.file, dir); 354 return 0; 355 } 356 357 headersz += sizeof(struct opt_hdr_v1) + 358 s.st_size + 359 (binarye->binary.nargs + 2) * sizeof(uint32_t); 360 if (hasext) 361 *hasext = 1; 362 } 363 364 #if defined(CONFIG_SYS_U_BOOT_OFFS) 365 if (headersz > CONFIG_SYS_U_BOOT_OFFS) { 366 fprintf(stderr, 367 "Error: Image header (incl. SPL image) too big!\n"); 368 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n", 369 (int)headersz, CONFIG_SYS_U_BOOT_OFFS); 370 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n"); 371 return 0; 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 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, 384 int payloadsz) 385 { 386 struct image_cfg_element *e, *binarye; 387 struct main_hdr_v1 *main_hdr; 388 size_t headersz; 389 uint8_t *image, *cur; 390 int hasext = 0; 391 392 /* 393 * Calculate the size of the header and the size of the 394 * payload 395 */ 396 headersz = image_headersz_v1(params, &hasext); 397 if (headersz == 0) 398 return NULL; 399 400 image = malloc(headersz); 401 if (!image) { 402 fprintf(stderr, "Cannot allocate memory for image\n"); 403 return NULL; 404 } 405 406 memset(image, 0, headersz); 407 408 main_hdr = (struct main_hdr_v1 *)image; 409 cur = image + sizeof(struct main_hdr_v1); 410 411 /* Fill the main header */ 412 main_hdr->blocksize = 413 cpu_to_le32(payloadsz - headersz + sizeof(uint32_t)); 414 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF); 415 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; 416 main_hdr->destaddr = cpu_to_le32(params->addr) 417 - sizeof(image_header_t); 418 main_hdr->execaddr = cpu_to_le32(params->ep); 419 main_hdr->srcaddr = cpu_to_le32(headersz); 420 main_hdr->ext = hasext; 421 main_hdr->version = 1; 422 e = image_find_option(IMAGE_CFG_BOOT_FROM); 423 if (e) 424 main_hdr->blockid = e->bootfrom; 425 e = image_find_option(IMAGE_CFG_NAND_BLKSZ); 426 if (e) 427 main_hdr->nandblocksize = e->nandblksz / (64 * 1024); 428 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); 429 if (e) 430 main_hdr->nandbadblklocation = e->nandbadblklocation; 431 e = image_find_option(IMAGE_CFG_BAUDRATE); 432 if (e) 433 main_hdr->options = baudrate_to_option(e->baudrate); 434 e = image_find_option(IMAGE_CFG_DEBUG); 435 if (e) 436 main_hdr->flags = e->debug ? 0x1 : 0; 437 438 binarye = image_find_option(IMAGE_CFG_BINARY); 439 if (binarye) { 440 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur; 441 uint32_t *args; 442 size_t binhdrsz; 443 struct stat s; 444 int argi; 445 FILE *bin; 446 int ret; 447 448 hdr->headertype = OPT_HDR_V1_BINARY_TYPE; 449 450 bin = fopen(binarye->binary.file, "r"); 451 if (!bin) { 452 fprintf(stderr, "Cannot open binary file %s\n", 453 binarye->binary.file); 454 return NULL; 455 } 456 457 fstat(fileno(bin), &s); 458 459 binhdrsz = sizeof(struct opt_hdr_v1) + 460 (binarye->binary.nargs + 2) * sizeof(uint32_t) + 461 s.st_size; 462 463 /* 464 * The size includes the binary image size, rounded 465 * up to a 4-byte boundary. Plus 4 bytes for the 466 * next-header byte and 3-byte alignment at the end. 467 */ 468 binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4; 469 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF); 470 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; 471 472 cur += sizeof(struct opt_hdr_v1); 473 474 args = (uint32_t *)cur; 475 *args = cpu_to_le32(binarye->binary.nargs); 476 args++; 477 for (argi = 0; argi < binarye->binary.nargs; argi++) 478 args[argi] = cpu_to_le32(binarye->binary.args[argi]); 479 480 cur += (binarye->binary.nargs + 1) * sizeof(uint32_t); 481 482 ret = fread(cur, s.st_size, 1, bin); 483 if (ret != 1) { 484 fprintf(stderr, 485 "Could not read binary image %s\n", 486 binarye->binary.file); 487 return NULL; 488 } 489 490 fclose(bin); 491 492 cur += ALIGN_SUP(s.st_size, 4); 493 494 /* 495 * For now, we don't support more than one binary 496 * header, and no other header types are 497 * supported. So, the binary header is necessarily the 498 * last one 499 */ 500 *((uint32_t *)cur) = 0x00000000; 501 502 cur += sizeof(uint32_t); 503 } 504 505 /* Calculate and set the header checksum */ 506 main_hdr->checksum = image_checksum8(main_hdr, headersz); 507 508 *imagesz = headersz; 509 return image; 510 } 511 512 static int image_create_config_parse_oneline(char *line, 513 struct image_cfg_element *el) 514 { 515 char *keyword, *saveptr; 516 char deliminiters[] = " \t"; 517 518 keyword = strtok_r(line, deliminiters, &saveptr); 519 if (!strcmp(keyword, "VERSION")) { 520 char *value = strtok_r(NULL, deliminiters, &saveptr); 521 522 el->type = IMAGE_CFG_VERSION; 523 el->version = atoi(value); 524 } else if (!strcmp(keyword, "BOOT_FROM")) { 525 char *value = strtok_r(NULL, deliminiters, &saveptr); 526 int ret = image_boot_mode_id(value); 527 528 if (ret < 0) { 529 fprintf(stderr, 530 "Invalid boot media '%s'\n", value); 531 return -1; 532 } 533 el->type = IMAGE_CFG_BOOT_FROM; 534 el->bootfrom = ret; 535 } else if (!strcmp(keyword, "NAND_BLKSZ")) { 536 char *value = strtok_r(NULL, deliminiters, &saveptr); 537 538 el->type = IMAGE_CFG_NAND_BLKSZ; 539 el->nandblksz = strtoul(value, NULL, 16); 540 } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) { 541 char *value = strtok_r(NULL, deliminiters, &saveptr); 542 543 el->type = IMAGE_CFG_NAND_BADBLK_LOCATION; 544 el->nandbadblklocation = 545 strtoul(value, NULL, 16); 546 } else if (!strcmp(keyword, "NAND_ECC_MODE")) { 547 char *value = strtok_r(NULL, deliminiters, &saveptr); 548 int ret = image_nand_ecc_mode_id(value); 549 550 if (ret < 0) { 551 fprintf(stderr, 552 "Invalid NAND ECC mode '%s'\n", value); 553 return -1; 554 } 555 el->type = IMAGE_CFG_NAND_ECC_MODE; 556 el->nandeccmode = ret; 557 } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) { 558 char *value = strtok_r(NULL, deliminiters, &saveptr); 559 560 el->type = IMAGE_CFG_NAND_PAGESZ; 561 el->nandpagesz = strtoul(value, NULL, 16); 562 } else if (!strcmp(keyword, "BINARY")) { 563 char *value = strtok_r(NULL, deliminiters, &saveptr); 564 int argi = 0; 565 566 el->type = IMAGE_CFG_BINARY; 567 el->binary.file = strdup(value); 568 while (1) { 569 value = strtok_r(NULL, deliminiters, &saveptr); 570 if (!value) 571 break; 572 el->binary.args[argi] = strtoul(value, NULL, 16); 573 argi++; 574 if (argi >= BINARY_MAX_ARGS) { 575 fprintf(stderr, 576 "Too many argument for binary\n"); 577 return -1; 578 } 579 } 580 el->binary.nargs = argi; 581 } else if (!strcmp(keyword, "DATA")) { 582 char *value1 = strtok_r(NULL, deliminiters, &saveptr); 583 char *value2 = strtok_r(NULL, deliminiters, &saveptr); 584 585 if (!value1 || !value2) { 586 fprintf(stderr, 587 "Invalid number of arguments for DATA\n"); 588 return -1; 589 } 590 591 el->type = IMAGE_CFG_DATA; 592 el->regdata.raddr = strtoul(value1, NULL, 16); 593 el->regdata.rdata = strtoul(value2, NULL, 16); 594 } else if (!strcmp(keyword, "BAUDRATE")) { 595 char *value = strtok_r(NULL, deliminiters, &saveptr); 596 el->type = IMAGE_CFG_BAUDRATE; 597 el->baudrate = strtoul(value, NULL, 10); 598 } else if (!strcmp(keyword, "DEBUG")) { 599 char *value = strtok_r(NULL, deliminiters, &saveptr); 600 el->type = IMAGE_CFG_DEBUG; 601 el->debug = strtoul(value, NULL, 10); 602 } else { 603 fprintf(stderr, "Ignoring unknown line '%s'\n", line); 604 } 605 606 return 0; 607 } 608 609 /* 610 * Parse the configuration file 'fcfg' into the array of configuration 611 * elements 'image_cfg', and return the number of configuration 612 * elements in 'cfgn'. 613 */ 614 static int image_create_config_parse(FILE *fcfg) 615 { 616 int ret; 617 int cfgi = 0; 618 619 /* Parse the configuration file */ 620 while (!feof(fcfg)) { 621 char *line; 622 char buf[256]; 623 624 /* Read the current line */ 625 memset(buf, 0, sizeof(buf)); 626 line = fgets(buf, sizeof(buf), fcfg); 627 if (!line) 628 break; 629 630 /* Ignore useless lines */ 631 if (line[0] == '\n' || line[0] == '#') 632 continue; 633 634 /* Strip final newline */ 635 if (line[strlen(line) - 1] == '\n') 636 line[strlen(line) - 1] = 0; 637 638 /* Parse the current line */ 639 ret = image_create_config_parse_oneline(line, 640 &image_cfg[cfgi]); 641 if (ret) 642 return ret; 643 644 cfgi++; 645 646 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) { 647 fprintf(stderr, 648 "Too many configuration elements in .cfg file\n"); 649 return -1; 650 } 651 } 652 653 cfgn = cfgi; 654 return 0; 655 } 656 657 static int image_get_version(void) 658 { 659 struct image_cfg_element *e; 660 661 e = image_find_option(IMAGE_CFG_VERSION); 662 if (!e) 663 return -1; 664 665 return e->version; 666 } 667 668 static int image_version_file(const char *input) 669 { 670 FILE *fcfg; 671 int version; 672 int ret; 673 674 fcfg = fopen(input, "r"); 675 if (!fcfg) { 676 fprintf(stderr, "Could not open input file %s\n", input); 677 return -1; 678 } 679 680 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX * 681 sizeof(struct image_cfg_element)); 682 if (!image_cfg) { 683 fprintf(stderr, "Cannot allocate memory\n"); 684 fclose(fcfg); 685 return -1; 686 } 687 688 memset(image_cfg, 0, 689 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); 690 rewind(fcfg); 691 692 ret = image_create_config_parse(fcfg); 693 fclose(fcfg); 694 if (ret) { 695 free(image_cfg); 696 return -1; 697 } 698 699 version = image_get_version(); 700 /* Fallback to version 0 is no version is provided in the cfg file */ 701 if (version == -1) 702 version = 0; 703 704 free(image_cfg); 705 706 return version; 707 } 708 709 static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, 710 struct image_tool_params *params) 711 { 712 FILE *fcfg; 713 void *image = NULL; 714 int version; 715 size_t headersz = 0; 716 uint32_t checksum; 717 int ret; 718 int size; 719 720 fcfg = fopen(params->imagename, "r"); 721 if (!fcfg) { 722 fprintf(stderr, "Could not open input file %s\n", 723 params->imagename); 724 exit(EXIT_FAILURE); 725 } 726 727 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX * 728 sizeof(struct image_cfg_element)); 729 if (!image_cfg) { 730 fprintf(stderr, "Cannot allocate memory\n"); 731 fclose(fcfg); 732 exit(EXIT_FAILURE); 733 } 734 735 memset(image_cfg, 0, 736 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); 737 rewind(fcfg); 738 739 ret = image_create_config_parse(fcfg); 740 fclose(fcfg); 741 if (ret) { 742 free(image_cfg); 743 exit(EXIT_FAILURE); 744 } 745 746 /* The MVEBU BootROM does not allow non word aligned payloads */ 747 sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4); 748 749 version = image_get_version(); 750 switch (version) { 751 /* 752 * Fallback to version 0 if no version is provided in the 753 * cfg file 754 */ 755 case -1: 756 case 0: 757 image = image_create_v0(&headersz, params, sbuf->st_size); 758 break; 759 760 case 1: 761 image = image_create_v1(&headersz, params, sbuf->st_size); 762 break; 763 764 default: 765 fprintf(stderr, "Unsupported version %d\n", version); 766 free(image_cfg); 767 exit(EXIT_FAILURE); 768 } 769 770 if (!image) { 771 fprintf(stderr, "Could not create image\n"); 772 free(image_cfg); 773 exit(EXIT_FAILURE); 774 } 775 776 free(image_cfg); 777 778 /* Build and add image checksum header */ 779 checksum = 780 cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size)); 781 size = write(ifd, &checksum, sizeof(uint32_t)); 782 if (size != sizeof(uint32_t)) { 783 fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n", 784 params->cmdname, size, params->imagefile); 785 exit(EXIT_FAILURE); 786 } 787 788 sbuf->st_size += sizeof(uint32_t); 789 790 /* Finally copy the header into the image area */ 791 memcpy(ptr, image, headersz); 792 793 free(image); 794 } 795 796 static void kwbimage_print_header(const void *ptr) 797 { 798 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr; 799 800 printf("Image Type: MVEBU Boot from %s Image\n", 801 image_boot_mode_name(mhdr->blockid)); 802 printf("Image version:%d\n", image_version((void *)ptr)); 803 printf("Data Size: "); 804 genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); 805 printf("Load Address: %08x\n", mhdr->destaddr); 806 printf("Entry Point: %08x\n", mhdr->execaddr); 807 } 808 809 static int kwbimage_check_image_types(uint8_t type) 810 { 811 if (type == IH_TYPE_KWBIMAGE) 812 return EXIT_SUCCESS; 813 814 return EXIT_FAILURE; 815 } 816 817 static int kwbimage_verify_header(unsigned char *ptr, int image_size, 818 struct image_tool_params *params) 819 { 820 struct main_hdr_v0 *main_hdr; 821 uint8_t checksum; 822 823 main_hdr = (struct main_hdr_v0 *)ptr; 824 checksum = image_checksum8(ptr, 825 sizeof(struct main_hdr_v0) 826 - sizeof(uint8_t)); 827 if (checksum != main_hdr->checksum) 828 return -FDT_ERR_BADSTRUCTURE; 829 830 /* Only version 0 extended header has checksum */ 831 if (image_version((void *)ptr) == 0) { 832 struct ext_hdr_v0 *ext_hdr; 833 834 ext_hdr = (struct ext_hdr_v0 *) 835 (ptr + sizeof(struct main_hdr_v0)); 836 checksum = image_checksum8(ext_hdr, 837 sizeof(struct ext_hdr_v0) 838 - sizeof(uint8_t)); 839 if (checksum != ext_hdr->checksum) 840 return -FDT_ERR_BADSTRUCTURE; 841 } 842 843 return 0; 844 } 845 846 static int kwbimage_generate(struct image_tool_params *params, 847 struct image_type_params *tparams) 848 { 849 int alloc_len; 850 void *hdr; 851 int version = 0; 852 853 version = image_version_file(params->imagename); 854 if (version == 0) { 855 alloc_len = sizeof(struct main_hdr_v0) + 856 sizeof(struct ext_hdr_v0); 857 } else { 858 alloc_len = image_headersz_v1(params, NULL); 859 } 860 861 hdr = malloc(alloc_len); 862 if (!hdr) { 863 fprintf(stderr, "%s: malloc return failure: %s\n", 864 params->cmdname, strerror(errno)); 865 exit(EXIT_FAILURE); 866 } 867 868 memset(hdr, 0, alloc_len); 869 tparams->header_size = alloc_len; 870 tparams->hdr = hdr; 871 872 /* 873 * The resulting image needs to be 4-byte aligned. At least 874 * the Marvell hdrparser tool complains if its unaligned. 875 * By returning 1 here in this function, called via 876 * tparams->vrec_header() in mkimage.c, mkimage will 877 * automatically pad the the resulting image to a 4-byte 878 * size if necessary. 879 */ 880 return 1; 881 } 882 883 /* 884 * Report Error if xflag is set in addition to default 885 */ 886 static int kwbimage_check_params(struct image_tool_params *params) 887 { 888 if (!strlen(params->imagename)) { 889 char *msg = "Configuration file for kwbimage creation omitted"; 890 891 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg); 892 return CFG_INVALID; 893 } 894 895 return (params->dflag && (params->fflag || params->lflag)) || 896 (params->fflag && (params->dflag || params->lflag)) || 897 (params->lflag && (params->dflag || params->fflag)) || 898 (params->xflag) || !(strlen(params->imagename)); 899 } 900 901 /* 902 * kwbimage type parameters definition 903 */ 904 U_BOOT_IMAGE_TYPE( 905 kwbimage, 906 "Marvell MVEBU Boot Image support", 907 0, 908 NULL, 909 kwbimage_check_params, 910 kwbimage_verify_header, 911 kwbimage_print_header, 912 kwbimage_set_header, 913 NULL, 914 kwbimage_check_image_types, 915 NULL, 916 kwbimage_generate 917 ); 918