1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Freescale i.MX23/i.MX28 SB image generator 4 * 5 * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de> 6 */ 7 8#ifdef CFG_MXS 9 10#include <errno.h> 11#include <fcntl.h> 12#include <stdio.h> 13#include <string.h> 14#include <u-boot/crc.h> 15#include <unistd.h> 16#include <limits.h> 17 18#include <openssl/evp.h> 19 20#include "imagetool.h" 21#include "mxsimage.h" 22#include "pbl_crc32.h" 23#include <image.h> 24 25/* 26 * OpenSSL 1.1.0 and newer compatibility functions: 27 * https://wiki.openssl.org/index.php/1.1_API_Changes 28 */ 29#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 30 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) 31static void *OPENSSL_zalloc(size_t num) 32{ 33 void *ret = OPENSSL_malloc(num); 34 35 if (ret != NULL) 36 memset(ret, 0, num); 37 return ret; 38} 39 40EVP_MD_CTX *EVP_MD_CTX_new(void) 41{ 42 return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); 43} 44 45void EVP_MD_CTX_free(EVP_MD_CTX *ctx) 46{ 47 EVP_MD_CTX_cleanup(ctx); 48 OPENSSL_free(ctx); 49} 50 51int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) 52{ 53 return EVP_CIPHER_CTX_cleanup(ctx); 54} 55#endif 56 57/* 58 * DCD block 59 * |-Write to address command block 60 * | 0xf00 == 0xf33d 61 * | 0xba2 == 0xb33f 62 * |-ORR address with mask command block 63 * | 0xf00 |= 0x1337 64 * |-Write to address command block 65 * | 0xba2 == 0xd00d 66 * : 67 */ 68#define SB_HAB_DCD_WRITE 0xccUL 69#define SB_HAB_DCD_CHECK 0xcfUL 70#define SB_HAB_DCD_NOOP 0xc0UL 71#define SB_HAB_DCD_MASK_BIT (1 << 3) 72#define SB_HAB_DCD_SET_BIT (1 << 4) 73 74/* Addr.n = Value.n */ 75#define SB_DCD_WRITE \ 76 (SB_HAB_DCD_WRITE << 24) 77/* Addr.n &= ~Value.n */ 78#define SB_DCD_ANDC \ 79 ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT) 80/* Addr.n |= Value.n */ 81#define SB_DCD_ORR \ 82 ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT) 83/* (Addr.n & Value.n) == 0 */ 84#define SB_DCD_CHK_EQZ \ 85 (SB_HAB_DCD_CHECK << 24) 86/* (Addr.n & Value.n) == Value.n */ 87#define SB_DCD_CHK_EQ \ 88 ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT) 89/* (Addr.n & Value.n) != Value.n */ 90#define SB_DCD_CHK_NEQ \ 91 ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_MASK_BIT) 92/* (Addr.n & Value.n) != 0 */ 93#define SB_DCD_CHK_NEZ \ 94 ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT) 95/* NOP */ 96#define SB_DCD_NOOP \ 97 (SB_HAB_DCD_NOOP << 24) 98 99struct sb_dcd_ctx { 100 struct sb_dcd_ctx *dcd; 101 102 uint32_t id; 103 104 /* The DCD block. */ 105 uint32_t *payload; 106 /* Size of the whole DCD block. */ 107 uint32_t size; 108 109 /* Pointer to previous DCD command block. */ 110 uint32_t *prev_dcd_head; 111}; 112 113/* 114 * IMAGE 115 * |-SECTION 116 * | |-CMD 117 * | |-CMD 118 * | `-CMD 119 * |-SECTION 120 * | |-CMD 121 * : : 122 */ 123struct sb_cmd_list { 124 char *cmd; 125 size_t len; 126 unsigned int lineno; 127}; 128 129struct sb_cmd_ctx { 130 uint32_t size; 131 132 struct sb_cmd_ctx *cmd; 133 134 uint8_t *data; 135 uint32_t length; 136 137 struct sb_command payload; 138 struct sb_command c_payload; 139}; 140 141struct sb_section_ctx { 142 uint32_t size; 143 144 /* Section flags */ 145 unsigned int boot:1; 146 147 struct sb_section_ctx *sect; 148 149 struct sb_cmd_ctx *cmd_head; 150 struct sb_cmd_ctx *cmd_tail; 151 152 struct sb_sections_header payload; 153}; 154 155struct sb_image_ctx { 156 unsigned int in_section:1; 157 unsigned int in_dcd:1; 158 /* Image configuration */ 159 unsigned int display_progress:1; 160 unsigned int silent_dump:1; 161 char *input_filename; 162 char *output_filename; 163 char *cfg_filename; 164 uint8_t image_key[16]; 165 166 /* Number of section in the image */ 167 unsigned int sect_count; 168 /* Bootable section */ 169 unsigned int sect_boot; 170 unsigned int sect_boot_found:1; 171 172 struct sb_section_ctx *sect_head; 173 struct sb_section_ctx *sect_tail; 174 175 struct sb_dcd_ctx *dcd_head; 176 struct sb_dcd_ctx *dcd_tail; 177 178 EVP_CIPHER_CTX *cipher_ctx; 179 EVP_MD_CTX *md_ctx; 180 uint8_t digest[32]; 181 struct sb_key_dictionary_key sb_dict_key; 182 183 struct sb_boot_image_header payload; 184}; 185 186/* 187 * Instruction semantics: 188 * NOOP 189 * TAG [LAST] 190 * LOAD address file 191 * LOAD IVT address IVT_entry_point 192 * FILL address pattern length 193 * JUMP [HAB] address [r0_arg] 194 * CALL [HAB] address [r0_arg] 195 * MODE mode 196 * For i.MX23, mode = USB/I2C/SPI1_FLASH/SPI2_FLASH/NAND_BCH 197 * JTAG/SPI3_EEPROM/SD_SSP0/SD_SSP1 198 * For i.MX28, mode = USB/I2C/SPI2_FLASH/SPI3_FLASH/NAND_BCH 199 * JTAG/SPI2_EEPROM/SD_SSP0/SD_SSP1 200 */ 201 202/* 203 * AES libcrypto 204 */ 205static int sb_aes_init(struct sb_image_ctx *ictx, uint8_t *iv, int enc) 206{ 207 EVP_CIPHER_CTX *ctx; 208 int ret; 209 210 /* If there is no init vector, init vector is all zeroes. */ 211 if (!iv) 212 iv = ictx->image_key; 213 214 ctx = EVP_CIPHER_CTX_new(); 215 ret = EVP_CipherInit(ctx, EVP_aes_128_cbc(), ictx->image_key, iv, enc); 216 if (ret == 1) { 217 EVP_CIPHER_CTX_set_padding(ctx, 0); 218 ictx->cipher_ctx = ctx; 219 } 220 return ret; 221} 222 223static int sb_aes_crypt(struct sb_image_ctx *ictx, uint8_t *in_data, 224 uint8_t *out_data, int in_len) 225{ 226 EVP_CIPHER_CTX *ctx = ictx->cipher_ctx; 227 int ret, outlen; 228 uint8_t *outbuf; 229 230 outbuf = malloc(in_len); 231 if (!outbuf) 232 return -ENOMEM; 233 memset(outbuf, 0, sizeof(in_len)); 234 235 ret = EVP_CipherUpdate(ctx, outbuf, &outlen, in_data, in_len); 236 if (!ret) { 237 ret = -EINVAL; 238 goto err; 239 } 240 241 if (out_data) 242 memcpy(out_data, outbuf, outlen); 243 244err: 245 free(outbuf); 246 return ret; 247} 248 249static int sb_aes_deinit(EVP_CIPHER_CTX *ctx) 250{ 251 return EVP_CIPHER_CTX_reset(ctx); 252} 253 254static int sb_aes_reinit(struct sb_image_ctx *ictx, int enc) 255{ 256 int ret; 257 EVP_CIPHER_CTX *ctx = ictx->cipher_ctx; 258 struct sb_boot_image_header *sb_header = &ictx->payload; 259 uint8_t *iv = sb_header->iv; 260 261 ret = sb_aes_deinit(ctx); 262 if (!ret) 263 return ret; 264 return sb_aes_init(ictx, iv, enc); 265} 266 267/* 268 * Debug 269 */ 270static void soprintf(struct sb_image_ctx *ictx, const char *fmt, ...) 271{ 272 va_list ap; 273 274 if (ictx->silent_dump) 275 return; 276 277 va_start(ap, fmt); 278 vfprintf(stdout, fmt, ap); 279 va_end(ap); 280} 281 282/* 283 * Code 284 */ 285static time_t sb_get_timestamp(void) 286{ 287 struct tm time_2000 = { 288 .tm_yday = 1, /* Jan. 1st */ 289 .tm_year = 100, /* 2000 */ 290 }; 291 time_t seconds_to_2000 = mktime(&time_2000); 292 time_t seconds_to_now = time(NULL); 293 294 return seconds_to_now - seconds_to_2000; 295} 296 297static int sb_get_time(time_t time, struct tm *tm) 298{ 299 struct tm time_2000 = { 300 .tm_yday = 1, /* Jan. 1st */ 301 .tm_year = 0, /* 1900 */ 302 }; 303 const time_t seconds_to_2000 = mktime(&time_2000); 304 const time_t seconds_to_now = seconds_to_2000 + time; 305 struct tm *ret; 306 ret = gmtime_r(&seconds_to_now, tm); 307 return ret ? 0 : -EINVAL; 308} 309 310static void sb_encrypt_sb_header(struct sb_image_ctx *ictx) 311{ 312 EVP_MD_CTX *md_ctx = ictx->md_ctx; 313 struct sb_boot_image_header *sb_header = &ictx->payload; 314 uint8_t *sb_header_ptr = (uint8_t *)sb_header; 315 316 /* Encrypt the header, compute the digest. */ 317 sb_aes_crypt(ictx, sb_header_ptr, NULL, sizeof(*sb_header)); 318 EVP_DigestUpdate(md_ctx, sb_header_ptr, sizeof(*sb_header)); 319} 320 321static void sb_encrypt_sb_sections_header(struct sb_image_ctx *ictx) 322{ 323 EVP_MD_CTX *md_ctx = ictx->md_ctx; 324 struct sb_section_ctx *sctx = ictx->sect_head; 325 struct sb_sections_header *shdr; 326 uint8_t *sb_sections_header_ptr; 327 const int size = sizeof(*shdr); 328 329 while (sctx) { 330 shdr = &sctx->payload; 331 sb_sections_header_ptr = (uint8_t *)shdr; 332 333 sb_aes_crypt(ictx, sb_sections_header_ptr, 334 ictx->sb_dict_key.cbc_mac, size); 335 EVP_DigestUpdate(md_ctx, sb_sections_header_ptr, size); 336 337 sctx = sctx->sect; 338 }; 339} 340 341static void sb_encrypt_key_dictionary_key(struct sb_image_ctx *ictx) 342{ 343 EVP_MD_CTX *md_ctx = ictx->md_ctx; 344 345 sb_aes_crypt(ictx, ictx->image_key, ictx->sb_dict_key.key, 346 sizeof(ictx->sb_dict_key.key)); 347 EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key)); 348} 349 350static void sb_decrypt_key_dictionary_key(struct sb_image_ctx *ictx) 351{ 352 EVP_MD_CTX *md_ctx = ictx->md_ctx; 353 354 EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key)); 355 sb_aes_crypt(ictx, ictx->sb_dict_key.key, ictx->image_key, 356 sizeof(ictx->sb_dict_key.key)); 357} 358 359static void sb_encrypt_tag(struct sb_image_ctx *ictx, 360 struct sb_cmd_ctx *cctx) 361{ 362 EVP_MD_CTX *md_ctx = ictx->md_ctx; 363 struct sb_command *cmd = &cctx->payload; 364 365 sb_aes_crypt(ictx, (uint8_t *)cmd, 366 (uint8_t *)&cctx->c_payload, sizeof(*cmd)); 367 EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd)); 368} 369 370static int sb_encrypt_image(struct sb_image_ctx *ictx) 371{ 372 /* Start image-wide crypto. */ 373 ictx->md_ctx = EVP_MD_CTX_new(); 374 EVP_DigestInit(ictx->md_ctx, EVP_sha1()); 375 376 /* 377 * SB image header. 378 */ 379 sb_aes_init(ictx, NULL, 1); 380 sb_encrypt_sb_header(ictx); 381 382 /* 383 * SB sections header. 384 */ 385 sb_encrypt_sb_sections_header(ictx); 386 387 /* 388 * Key dictionary. 389 */ 390 sb_aes_reinit(ictx, 1); 391 sb_encrypt_key_dictionary_key(ictx); 392 393 /* 394 * Section tags. 395 */ 396 struct sb_cmd_ctx *cctx; 397 struct sb_command *ccmd; 398 struct sb_section_ctx *sctx = ictx->sect_head; 399 400 while (sctx) { 401 cctx = sctx->cmd_head; 402 403 sb_aes_reinit(ictx, 1); 404 405 while (cctx) { 406 ccmd = &cctx->payload; 407 408 sb_encrypt_tag(ictx, cctx); 409 410 if (ccmd->header.tag == ROM_TAG_CMD) { 411 sb_aes_reinit(ictx, 1); 412 } else if (ccmd->header.tag == ROM_LOAD_CMD) { 413 sb_aes_crypt(ictx, cctx->data, cctx->data, 414 cctx->length); 415 EVP_DigestUpdate(ictx->md_ctx, cctx->data, 416 cctx->length); 417 } 418 419 cctx = cctx->cmd; 420 } 421 422 sctx = sctx->sect; 423 }; 424 425 /* 426 * Dump the SHA1 of the whole image. 427 */ 428 sb_aes_reinit(ictx, 1); 429 430 EVP_DigestFinal(ictx->md_ctx, ictx->digest, NULL); 431 EVP_MD_CTX_free(ictx->md_ctx); 432 sb_aes_crypt(ictx, ictx->digest, ictx->digest, sizeof(ictx->digest)); 433 434 /* Stop the encryption session. */ 435 sb_aes_deinit(ictx->cipher_ctx); 436 437 return 0; 438} 439 440static int sb_load_file(struct sb_cmd_ctx *cctx, char *filename) 441{ 442 long real_size, roundup_size; 443 uint8_t *data; 444 long ret; 445 unsigned long size; 446 FILE *fp; 447 448 if (!filename) { 449 fprintf(stderr, "ERR: Missing filename!\n"); 450 return -EINVAL; 451 } 452 453 fp = fopen(filename, "r"); 454 if (!fp) 455 goto err_open; 456 457 ret = fseek(fp, 0, SEEK_END); 458 if (ret < 0) 459 goto err_file; 460 461 real_size = ftell(fp); 462 if (real_size < 0) 463 goto err_file; 464 465 ret = fseek(fp, 0, SEEK_SET); 466 if (ret < 0) 467 goto err_file; 468 469 roundup_size = roundup(real_size, SB_BLOCK_SIZE); 470 data = calloc(1, roundup_size); 471 if (!data) 472 goto err_file; 473 474 size = fread(data, 1, real_size, fp); 475 if (size != (unsigned long)real_size) 476 goto err_alloc; 477 478 cctx->data = data; 479 cctx->length = roundup_size; 480 481 fclose(fp); 482 return 0; 483 484err_alloc: 485 free(data); 486err_file: 487 fclose(fp); 488err_open: 489 fprintf(stderr, "ERR: Failed to load file \"%s\"\n", filename); 490 return -EINVAL; 491} 492 493static uint8_t sb_command_checksum(struct sb_command *inst) 494{ 495 uint8_t *inst_ptr = (uint8_t *)inst; 496 uint8_t csum = 0; 497 unsigned int i; 498 499 for (i = 0; i < sizeof(struct sb_command); i++) 500 csum += inst_ptr[i]; 501 502 return csum; 503} 504 505static int sb_token_to_long(char *tok, uint32_t *rid) 506{ 507 char *endptr; 508 unsigned long id; 509 510 if (tok[0] != '0' || tok[1] != 'x') { 511 fprintf(stderr, "ERR: Invalid hexadecimal number!\n"); 512 return -EINVAL; 513 } 514 515 tok += 2; 516 517 errno = 0; 518 id = strtoul(tok, &endptr, 16); 519 if ((errno == ERANGE && id == ULONG_MAX) || (errno != 0 && id == 0)) { 520 fprintf(stderr, "ERR: Value can't be decoded!\n"); 521 return -EINVAL; 522 } 523 524 /* Check for 32-bit overflow. */ 525 if (id > 0xffffffff) { 526 fprintf(stderr, "ERR: Value too big!\n"); 527 return -EINVAL; 528 } 529 530 if (endptr == tok) { 531 fprintf(stderr, "ERR: Deformed value!\n"); 532 return -EINVAL; 533 } 534 535 *rid = (uint32_t)id; 536 return 0; 537} 538 539static int sb_grow_dcd(struct sb_dcd_ctx *dctx, unsigned int inc_size) 540{ 541 uint32_t *tmp; 542 543 if (!inc_size) 544 return 0; 545 546 dctx->size += inc_size; 547 tmp = realloc(dctx->payload, dctx->size); 548 if (!tmp) 549 return -ENOMEM; 550 551 dctx->payload = tmp; 552 553 /* Assemble and update the HAB DCD header. */ 554 dctx->payload[0] = htonl((SB_HAB_DCD_TAG << 24) | 555 (dctx->size << 8) | 556 SB_HAB_VERSION); 557 558 return 0; 559} 560 561static int sb_build_dcd(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd) 562{ 563 struct sb_dcd_ctx *dctx; 564 565 char *tok; 566 uint32_t id; 567 int ret; 568 569 dctx = calloc(1, sizeof(*dctx)); 570 if (!dctx) 571 return -ENOMEM; 572 573 ret = sb_grow_dcd(dctx, 4); 574 if (ret) 575 goto err_dcd; 576 577 /* Read DCD block number. */ 578 tok = strtok(cmd->cmd, " "); 579 if (!tok) { 580 fprintf(stderr, "#%i ERR: DCD block without number!\n", 581 cmd->lineno); 582 ret = -EINVAL; 583 goto err_dcd; 584 } 585 586 /* Parse the DCD block number. */ 587 ret = sb_token_to_long(tok, &id); 588 if (ret) { 589 fprintf(stderr, "#%i ERR: Malformed DCD block number!\n", 590 cmd->lineno); 591 goto err_dcd; 592 } 593 594 dctx->id = id; 595 596 /* 597 * The DCD block is now constructed. Append it to the list. 598 * WARNING: The DCD size is still not computed and will be 599 * updated while parsing it's commands. 600 */ 601 if (!ictx->dcd_head) { 602 ictx->dcd_head = dctx; 603 ictx->dcd_tail = dctx; 604 } else { 605 ictx->dcd_tail->dcd = dctx; 606 ictx->dcd_tail = dctx; 607 } 608 609 return 0; 610 611err_dcd: 612 free(dctx->payload); 613 free(dctx); 614 return ret; 615} 616 617static int sb_build_dcd_block(struct sb_image_ctx *ictx, 618 struct sb_cmd_list *cmd, 619 uint32_t type) 620{ 621 char *tok; 622 uint32_t address, value, length; 623 int ret; 624 625 struct sb_dcd_ctx *dctx = ictx->dcd_tail; 626 uint32_t *dcd; 627 628 if (dctx->prev_dcd_head && (type != SB_DCD_NOOP) && 629 ((dctx->prev_dcd_head[0] & 0xff0000ff) == type)) { 630 /* Same instruction as before, just append it. */ 631 ret = sb_grow_dcd(dctx, 8); 632 if (ret) 633 return ret; 634 } else if (type == SB_DCD_NOOP) { 635 ret = sb_grow_dcd(dctx, 4); 636 if (ret) 637 return ret; 638 639 /* Update DCD command block pointer. */ 640 dctx->prev_dcd_head = dctx->payload + 641 dctx->size / sizeof(*dctx->payload) - 1; 642 643 /* NOOP has only 4 bytes and no payload. */ 644 goto noop; 645 } else { 646 /* 647 * Either a different instruction block started now 648 * or this is the first instruction block. 649 */ 650 ret = sb_grow_dcd(dctx, 12); 651 if (ret) 652 return ret; 653 654 /* Update DCD command block pointer. */ 655 dctx->prev_dcd_head = dctx->payload + 656 dctx->size / sizeof(*dctx->payload) - 3; 657 } 658 659 dcd = dctx->payload + dctx->size / sizeof(*dctx->payload) - 2; 660 661 /* 662 * Prepare the command. 663 */ 664 tok = strtok(cmd->cmd, " "); 665 if (!tok) { 666 fprintf(stderr, "#%i ERR: Missing DCD address!\n", 667 cmd->lineno); 668 ret = -EINVAL; 669 goto err; 670 } 671 672 /* Read DCD destination address. */ 673 ret = sb_token_to_long(tok, &address); 674 if (ret) { 675 fprintf(stderr, "#%i ERR: Incorrect DCD address!\n", 676 cmd->lineno); 677 goto err; 678 } 679 680 tok = strtok(NULL, " "); 681 if (!tok) { 682 fprintf(stderr, "#%i ERR: Missing DCD value!\n", 683 cmd->lineno); 684 ret = -EINVAL; 685 goto err; 686 } 687 688 /* Read DCD operation value. */ 689 ret = sb_token_to_long(tok, &value); 690 if (ret) { 691 fprintf(stderr, "#%i ERR: Incorrect DCD value!\n", 692 cmd->lineno); 693 goto err; 694 } 695 696 /* Fill in the new DCD entry. */ 697 dcd[0] = htonl(address); 698 dcd[1] = htonl(value); 699 700noop: 701 /* Update the DCD command block. */ 702 length = dctx->size - 703 ((dctx->prev_dcd_head - dctx->payload) * 704 sizeof(*dctx->payload)); 705 dctx->prev_dcd_head[0] = htonl(type | (length << 8)); 706 707err: 708 return ret; 709} 710 711static int sb_build_section(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd) 712{ 713 struct sb_section_ctx *sctx; 714 struct sb_sections_header *shdr; 715 char *tok; 716 uint32_t bootable = 0; 717 uint32_t id; 718 int ret; 719 720 sctx = calloc(1, sizeof(*sctx)); 721 if (!sctx) 722 return -ENOMEM; 723 724 /* Read section number. */ 725 tok = strtok(cmd->cmd, " "); 726 if (!tok) { 727 fprintf(stderr, "#%i ERR: Section without number!\n", 728 cmd->lineno); 729 ret = -EINVAL; 730 goto err_sect; 731 } 732 733 /* Parse the section number. */ 734 ret = sb_token_to_long(tok, &id); 735 if (ret) { 736 fprintf(stderr, "#%i ERR: Malformed section number!\n", 737 cmd->lineno); 738 goto err_sect; 739 } 740 741 /* Read section's BOOTABLE flag. */ 742 tok = strtok(NULL, " "); 743 if (tok && (strlen(tok) == 8) && !strncmp(tok, "BOOTABLE", 8)) 744 bootable = SB_SECTION_FLAG_BOOTABLE; 745 746 sctx->boot = bootable; 747 748 shdr = &sctx->payload; 749 shdr->section_number = id; 750 shdr->section_flags = bootable; 751 752 /* 753 * The section is now constructed. Append it to the list. 754 * WARNING: The section size is still not computed and will 755 * be updated while parsing it's commands. 756 */ 757 ictx->sect_count++; 758 759 /* Mark that this section is bootable one. */ 760 if (bootable) { 761 if (ictx->sect_boot_found) { 762 fprintf(stderr, 763 "#%i WARN: Multiple bootable section!\n", 764 cmd->lineno); 765 } else { 766 ictx->sect_boot = id; 767 ictx->sect_boot_found = 1; 768 } 769 } 770 771 if (!ictx->sect_head) { 772 ictx->sect_head = sctx; 773 ictx->sect_tail = sctx; 774 } else { 775 ictx->sect_tail->sect = sctx; 776 ictx->sect_tail = sctx; 777 } 778 779 return 0; 780 781err_sect: 782 free(sctx); 783 return ret; 784} 785 786static int sb_build_command_nop(struct sb_image_ctx *ictx) 787{ 788 struct sb_section_ctx *sctx = ictx->sect_tail; 789 struct sb_cmd_ctx *cctx; 790 struct sb_command *ccmd; 791 792 cctx = calloc(1, sizeof(*cctx)); 793 if (!cctx) 794 return -ENOMEM; 795 796 ccmd = &cctx->payload; 797 798 /* 799 * Construct the command. 800 */ 801 ccmd->header.checksum = 0x5a; 802 ccmd->header.tag = ROM_NOP_CMD; 803 804 cctx->size = sizeof(*ccmd); 805 806 /* 807 * Append the command to the last section. 808 */ 809 if (!sctx->cmd_head) { 810 sctx->cmd_head = cctx; 811 sctx->cmd_tail = cctx; 812 } else { 813 sctx->cmd_tail->cmd = cctx; 814 sctx->cmd_tail = cctx; 815 } 816 817 return 0; 818} 819 820static int sb_build_command_tag(struct sb_image_ctx *ictx, 821 struct sb_cmd_list *cmd) 822{ 823 struct sb_section_ctx *sctx = ictx->sect_tail; 824 struct sb_cmd_ctx *cctx; 825 struct sb_command *ccmd; 826 char *tok; 827 828 cctx = calloc(1, sizeof(*cctx)); 829 if (!cctx) 830 return -ENOMEM; 831 832 ccmd = &cctx->payload; 833 834 /* 835 * Prepare the command. 836 */ 837 /* Check for the LAST keyword. */ 838 tok = strtok(cmd->cmd, " "); 839 if (tok && !strcmp(tok, "LAST")) 840 ccmd->header.flags = ROM_TAG_CMD_FLAG_ROM_LAST_TAG; 841 842 /* 843 * Construct the command. 844 */ 845 ccmd->header.checksum = 0x5a; 846 ccmd->header.tag = ROM_TAG_CMD; 847 848 cctx->size = sizeof(*ccmd); 849 850 /* 851 * Append the command to the last section. 852 */ 853 if (!sctx->cmd_head) { 854 sctx->cmd_head = cctx; 855 sctx->cmd_tail = cctx; 856 } else { 857 sctx->cmd_tail->cmd = cctx; 858 sctx->cmd_tail = cctx; 859 } 860 861 return 0; 862} 863 864static int sb_build_command_load(struct sb_image_ctx *ictx, 865 struct sb_cmd_list *cmd) 866{ 867 struct sb_section_ctx *sctx = ictx->sect_tail; 868 struct sb_cmd_ctx *cctx; 869 struct sb_command *ccmd; 870 char *tok; 871 int ret, is_ivt = 0, is_dcd = 0; 872 uint32_t dest, dcd = 0; 873 874 cctx = calloc(1, sizeof(*cctx)); 875 if (!cctx) 876 return -ENOMEM; 877 878 ccmd = &cctx->payload; 879 880 /* 881 * Prepare the command. 882 */ 883 tok = strtok(cmd->cmd, " "); 884 if (!tok) { 885 fprintf(stderr, "#%i ERR: Missing LOAD address or 'IVT'!\n", 886 cmd->lineno); 887 ret = -EINVAL; 888 goto err; 889 } 890 891 /* Check for "IVT" flag. */ 892 if (!strcmp(tok, "IVT")) 893 is_ivt = 1; 894 if (!strcmp(tok, "DCD")) 895 is_dcd = 1; 896 if (is_ivt || is_dcd) { 897 tok = strtok(NULL, " "); 898 if (!tok) { 899 fprintf(stderr, "#%i ERR: Missing LOAD address!\n", 900 cmd->lineno); 901 ret = -EINVAL; 902 goto err; 903 } 904 } 905 906 /* Read load destination address. */ 907 ret = sb_token_to_long(tok, &dest); 908 if (ret) { 909 fprintf(stderr, "#%i ERR: Incorrect LOAD address!\n", 910 cmd->lineno); 911 goto err; 912 } 913 914 /* Read filename or IVT entrypoint or DCD block ID. */ 915 tok = strtok(NULL, " "); 916 if (!tok) { 917 fprintf(stderr, 918 "#%i ERR: Missing LOAD filename or IVT ep or DCD block ID!\n", 919 cmd->lineno); 920 ret = -EINVAL; 921 goto err; 922 } 923 924 if (is_ivt) { 925 /* Handle IVT. */ 926 struct sb_ivt_header *ivt; 927 uint32_t ivtep; 928 ret = sb_token_to_long(tok, &ivtep); 929 930 if (ret) { 931 fprintf(stderr, 932 "#%i ERR: Incorrect IVT entry point!\n", 933 cmd->lineno); 934 goto err; 935 } 936 937 ivt = calloc(1, sizeof(*ivt)); 938 if (!ivt) { 939 ret = -ENOMEM; 940 goto err; 941 } 942 943 ivt->header = sb_hab_ivt_header(); 944 ivt->entry = ivtep; 945 ivt->self = dest; 946 947 cctx->data = (uint8_t *)ivt; 948 cctx->length = sizeof(*ivt); 949 } else if (is_dcd) { 950 struct sb_dcd_ctx *dctx = ictx->dcd_head; 951 uint32_t dcdid; 952 uint8_t *payload; 953 uint32_t asize; 954 ret = sb_token_to_long(tok, &dcdid); 955 956 if (ret) { 957 fprintf(stderr, 958 "#%i ERR: Incorrect DCD block ID!\n", 959 cmd->lineno); 960 goto err; 961 } 962 963 while (dctx) { 964 if (dctx->id == dcdid) 965 break; 966 dctx = dctx->dcd; 967 } 968 969 if (!dctx) { 970 fprintf(stderr, "#%i ERR: DCD block %08x not found!\n", 971 cmd->lineno, dcdid); 972 goto err; 973 } 974 975 asize = roundup(dctx->size, SB_BLOCK_SIZE); 976 payload = calloc(1, asize); 977 if (!payload) { 978 ret = -ENOMEM; 979 goto err; 980 } 981 982 memcpy(payload, dctx->payload, dctx->size); 983 984 cctx->data = payload; 985 cctx->length = asize; 986 987 /* Set the Load DCD flag. */ 988 dcd = ROM_LOAD_CMD_FLAG_DCD_LOAD; 989 } else { 990 /* Regular LOAD of a file. */ 991 ret = sb_load_file(cctx, tok); 992 if (ret) { 993 fprintf(stderr, "#%i ERR: Cannot load '%s'!\n", 994 cmd->lineno, tok); 995 goto err; 996 } 997 } 998 999 if (cctx->length & (SB_BLOCK_SIZE - 1)) { 1000 fprintf(stderr, "#%i ERR: Unaligned payload!\n", 1001 cmd->lineno); 1002 } 1003 1004 /* 1005 * Construct the command. 1006 */ 1007 ccmd->header.checksum = 0x5a; 1008 ccmd->header.tag = ROM_LOAD_CMD; 1009 ccmd->header.flags = dcd; 1010 1011 ccmd->load.address = dest; 1012 ccmd->load.count = cctx->length; 1013 ccmd->load.crc32 = pbl_crc32(0, 1014 (const char *)cctx->data, 1015 cctx->length); 1016 1017 cctx->size = sizeof(*ccmd) + cctx->length; 1018 1019 /* 1020 * Append the command to the last section. 1021 */ 1022 if (!sctx->cmd_head) { 1023 sctx->cmd_head = cctx; 1024 sctx->cmd_tail = cctx; 1025 } else { 1026 sctx->cmd_tail->cmd = cctx; 1027 sctx->cmd_tail = cctx; 1028 } 1029 1030 return 0; 1031 1032err: 1033 free(cctx); 1034 return ret; 1035} 1036 1037static int sb_build_command_fill(struct sb_image_ctx *ictx, 1038 struct sb_cmd_list *cmd) 1039{ 1040 struct sb_section_ctx *sctx = ictx->sect_tail; 1041 struct sb_cmd_ctx *cctx; 1042 struct sb_command *ccmd; 1043 char *tok; 1044 uint32_t address, pattern, length; 1045 int ret; 1046 1047 cctx = calloc(1, sizeof(*cctx)); 1048 if (!cctx) 1049 return -ENOMEM; 1050 1051 ccmd = &cctx->payload; 1052 1053 /* 1054 * Prepare the command. 1055 */ 1056 tok = strtok(cmd->cmd, " "); 1057 if (!tok) { 1058 fprintf(stderr, "#%i ERR: Missing FILL address!\n", 1059 cmd->lineno); 1060 ret = -EINVAL; 1061 goto err; 1062 } 1063 1064 /* Read fill destination address. */ 1065 ret = sb_token_to_long(tok, &address); 1066 if (ret) { 1067 fprintf(stderr, "#%i ERR: Incorrect FILL address!\n", 1068 cmd->lineno); 1069 goto err; 1070 } 1071 1072 tok = strtok(NULL, " "); 1073 if (!tok) { 1074 fprintf(stderr, "#%i ERR: Missing FILL pattern!\n", 1075 cmd->lineno); 1076 ret = -EINVAL; 1077 goto err; 1078 } 1079 1080 /* Read fill pattern address. */ 1081 ret = sb_token_to_long(tok, &pattern); 1082 if (ret) { 1083 fprintf(stderr, "#%i ERR: Incorrect FILL pattern!\n", 1084 cmd->lineno); 1085 goto err; 1086 } 1087 1088 tok = strtok(NULL, " "); 1089 if (!tok) { 1090 fprintf(stderr, "#%i ERR: Missing FILL length!\n", 1091 cmd->lineno); 1092 ret = -EINVAL; 1093 goto err; 1094 } 1095 1096 /* Read fill pattern address. */ 1097 ret = sb_token_to_long(tok, &length); 1098 if (ret) { 1099 fprintf(stderr, "#%i ERR: Incorrect FILL length!\n", 1100 cmd->lineno); 1101 goto err; 1102 } 1103 1104 /* 1105 * Construct the command. 1106 */ 1107 ccmd->header.checksum = 0x5a; 1108 ccmd->header.tag = ROM_FILL_CMD; 1109 1110 ccmd->fill.address = address; 1111 ccmd->fill.count = length; 1112 ccmd->fill.pattern = pattern; 1113 1114 cctx->size = sizeof(*ccmd); 1115 1116 /* 1117 * Append the command to the last section. 1118 */ 1119 if (!sctx->cmd_head) { 1120 sctx->cmd_head = cctx; 1121 sctx->cmd_tail = cctx; 1122 } else { 1123 sctx->cmd_tail->cmd = cctx; 1124 sctx->cmd_tail = cctx; 1125 } 1126 1127 return 0; 1128 1129err: 1130 free(cctx); 1131 return ret; 1132} 1133 1134static int sb_build_command_jump_call(struct sb_image_ctx *ictx, 1135 struct sb_cmd_list *cmd, 1136 unsigned int is_call) 1137{ 1138 struct sb_section_ctx *sctx = ictx->sect_tail; 1139 struct sb_cmd_ctx *cctx; 1140 struct sb_command *ccmd; 1141 char *tok; 1142 uint32_t dest, arg = 0x0; 1143 uint32_t hab = 0; 1144 int ret; 1145 const char *cmdname = is_call ? "CALL" : "JUMP"; 1146 1147 cctx = calloc(1, sizeof(*cctx)); 1148 if (!cctx) 1149 return -ENOMEM; 1150 1151 ccmd = &cctx->payload; 1152 1153 /* 1154 * Prepare the command. 1155 */ 1156 tok = strtok(cmd->cmd, " "); 1157 if (!tok) { 1158 fprintf(stderr, 1159 "#%i ERR: Missing %s address or 'HAB'!\n", 1160 cmd->lineno, cmdname); 1161 ret = -EINVAL; 1162 goto err; 1163 } 1164 1165 /* Check for "HAB" flag. */ 1166 if (!strcmp(tok, "HAB")) { 1167 hab = is_call ? ROM_CALL_CMD_FLAG_HAB : ROM_JUMP_CMD_FLAG_HAB; 1168 tok = strtok(NULL, " "); 1169 if (!tok) { 1170 fprintf(stderr, "#%i ERR: Missing %s address!\n", 1171 cmd->lineno, cmdname); 1172 ret = -EINVAL; 1173 goto err; 1174 } 1175 } 1176 /* Read load destination address. */ 1177 ret = sb_token_to_long(tok, &dest); 1178 if (ret) { 1179 fprintf(stderr, "#%i ERR: Incorrect %s address!\n", 1180 cmd->lineno, cmdname); 1181 goto err; 1182 } 1183 1184 tok = strtok(NULL, " "); 1185 if (tok) { 1186 ret = sb_token_to_long(tok, &arg); 1187 if (ret) { 1188 fprintf(stderr, 1189 "#%i ERR: Incorrect %s argument!\n", 1190 cmd->lineno, cmdname); 1191 goto err; 1192 } 1193 } 1194 1195 /* 1196 * Construct the command. 1197 */ 1198 ccmd->header.checksum = 0x5a; 1199 ccmd->header.tag = is_call ? ROM_CALL_CMD : ROM_JUMP_CMD; 1200 ccmd->header.flags = hab; 1201 1202 ccmd->call.address = dest; 1203 ccmd->call.argument = arg; 1204 1205 cctx->size = sizeof(*ccmd); 1206 1207 /* 1208 * Append the command to the last section. 1209 */ 1210 if (!sctx->cmd_head) { 1211 sctx->cmd_head = cctx; 1212 sctx->cmd_tail = cctx; 1213 } else { 1214 sctx->cmd_tail->cmd = cctx; 1215 sctx->cmd_tail = cctx; 1216 } 1217 1218 return 0; 1219 1220err: 1221 free(cctx); 1222 return ret; 1223} 1224 1225static int sb_build_command_jump(struct sb_image_ctx *ictx, 1226 struct sb_cmd_list *cmd) 1227{ 1228 return sb_build_command_jump_call(ictx, cmd, 0); 1229} 1230 1231static int sb_build_command_call(struct sb_image_ctx *ictx, 1232 struct sb_cmd_list *cmd) 1233{ 1234 return sb_build_command_jump_call(ictx, cmd, 1); 1235} 1236 1237static int sb_build_command_mode(struct sb_image_ctx *ictx, 1238 struct sb_cmd_list *cmd) 1239{ 1240 struct sb_section_ctx *sctx = ictx->sect_tail; 1241 struct sb_cmd_ctx *cctx; 1242 struct sb_command *ccmd; 1243 char *tok; 1244 int ret; 1245 unsigned int i; 1246 uint32_t mode = 0xffffffff; 1247 1248 cctx = calloc(1, sizeof(*cctx)); 1249 if (!cctx) 1250 return -ENOMEM; 1251 1252 ccmd = &cctx->payload; 1253 1254 /* 1255 * Prepare the command. 1256 */ 1257 tok = strtok(cmd->cmd, " "); 1258 if (!tok) { 1259 fprintf(stderr, "#%i ERR: Missing MODE boot mode argument!\n", 1260 cmd->lineno); 1261 ret = -EINVAL; 1262 goto err; 1263 } 1264 1265 for (i = 0; i < ARRAY_SIZE(modetable); i++) { 1266 if (!strcmp(tok, modetable[i].name)) { 1267 mode = modetable[i].mode; 1268 break; 1269 } 1270 1271 if (!modetable[i].altname) 1272 continue; 1273 1274 if (!strcmp(tok, modetable[i].altname)) { 1275 mode = modetable[i].mode; 1276 break; 1277 } 1278 } 1279 1280 if (mode == 0xffffffff) { 1281 fprintf(stderr, "#%i ERR: Invalid MODE boot mode argument!\n", 1282 cmd->lineno); 1283 ret = -EINVAL; 1284 goto err; 1285 } 1286 1287 /* 1288 * Construct the command. 1289 */ 1290 ccmd->header.checksum = 0x5a; 1291 ccmd->header.tag = ROM_MODE_CMD; 1292 1293 ccmd->mode.mode = mode; 1294 1295 cctx->size = sizeof(*ccmd); 1296 1297 /* 1298 * Append the command to the last section. 1299 */ 1300 if (!sctx->cmd_head) { 1301 sctx->cmd_head = cctx; 1302 sctx->cmd_tail = cctx; 1303 } else { 1304 sctx->cmd_tail->cmd = cctx; 1305 sctx->cmd_tail = cctx; 1306 } 1307 1308 return 0; 1309 1310err: 1311 free(cctx); 1312 return ret; 1313} 1314 1315static int sb_prefill_image_header(struct sb_image_ctx *ictx) 1316{ 1317 struct sb_boot_image_header *hdr = &ictx->payload; 1318 1319 /* Fill signatures */ 1320 memcpy(hdr->signature1, "STMP", 4); 1321 memcpy(hdr->signature2, "sgtl", 4); 1322 1323 /* SB Image version 1.1 */ 1324 hdr->major_version = SB_VERSION_MAJOR; 1325 hdr->minor_version = SB_VERSION_MINOR; 1326 1327 /* Boot image major version */ 1328 hdr->product_version.major = htons(0x999); 1329 hdr->product_version.minor = htons(0x999); 1330 hdr->product_version.revision = htons(0x999); 1331 /* Boot image major version */ 1332 hdr->component_version.major = htons(0x999); 1333 hdr->component_version.minor = htons(0x999); 1334 hdr->component_version.revision = htons(0x999); 1335 1336 /* Drive tag must be 0x0 for i.MX23 */ 1337 hdr->drive_tag = 0; 1338 1339 hdr->header_blocks = 1340 sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE; 1341 hdr->section_header_size = 1342 sizeof(struct sb_sections_header) / SB_BLOCK_SIZE; 1343 hdr->timestamp_us = sb_get_timestamp() * 1000000; 1344 1345 hdr->flags = ictx->display_progress ? 1346 SB_IMAGE_FLAG_DISPLAY_PROGRESS : 0; 1347 1348 /* FIXME -- We support only default key */ 1349 hdr->key_count = 1; 1350 1351 return 0; 1352} 1353 1354static int sb_postfill_image_header(struct sb_image_ctx *ictx) 1355{ 1356 struct sb_boot_image_header *hdr = &ictx->payload; 1357 struct sb_section_ctx *sctx = ictx->sect_head; 1358 uint32_t kd_size, sections_blocks; 1359 EVP_MD_CTX *md_ctx; 1360 1361 /* The main SB header size in blocks. */ 1362 hdr->image_blocks = hdr->header_blocks; 1363 1364 /* Size of the key dictionary, which has single zero entry. */ 1365 kd_size = hdr->key_count * sizeof(struct sb_key_dictionary_key); 1366 hdr->image_blocks += kd_size / SB_BLOCK_SIZE; 1367 1368 /* Now count the payloads. */ 1369 hdr->section_count = ictx->sect_count; 1370 while (sctx) { 1371 hdr->image_blocks += sctx->size / SB_BLOCK_SIZE; 1372 sctx = sctx->sect; 1373 } 1374 1375 if (!ictx->sect_boot_found) { 1376 fprintf(stderr, "ERR: No bootable section selected!\n"); 1377 return -EINVAL; 1378 } 1379 hdr->first_boot_section_id = ictx->sect_boot; 1380 1381 /* The n * SB section size in blocks. */ 1382 sections_blocks = hdr->section_count * hdr->section_header_size; 1383 hdr->image_blocks += sections_blocks; 1384 1385 /* Key dictionary offset. */ 1386 hdr->key_dictionary_block = hdr->header_blocks + sections_blocks; 1387 1388 /* Digest of the whole image. */ 1389 hdr->image_blocks += 2; 1390 1391 /* Pointer past the dictionary. */ 1392 hdr->first_boot_tag_block = 1393 hdr->key_dictionary_block + kd_size / SB_BLOCK_SIZE; 1394 1395 /* Compute header digest. */ 1396 md_ctx = EVP_MD_CTX_new(); 1397 1398 EVP_DigestInit(md_ctx, EVP_sha1()); 1399 EVP_DigestUpdate(md_ctx, hdr->signature1, 1400 sizeof(struct sb_boot_image_header) - 1401 sizeof(hdr->digest)); 1402 EVP_DigestFinal(md_ctx, hdr->digest, NULL); 1403 EVP_MD_CTX_free(md_ctx); 1404 1405 return 0; 1406} 1407 1408static int sb_fixup_sections_and_tags(struct sb_image_ctx *ictx) 1409{ 1410 /* Fixup the placement of sections. */ 1411 struct sb_boot_image_header *ihdr = &ictx->payload; 1412 struct sb_section_ctx *sctx = ictx->sect_head; 1413 struct sb_sections_header *shdr; 1414 struct sb_cmd_ctx *cctx; 1415 struct sb_command *ccmd; 1416 uint32_t offset = ihdr->first_boot_tag_block; 1417 1418 while (sctx) { 1419 shdr = &sctx->payload; 1420 1421 /* Fill in the section TAG offset. */ 1422 shdr->section_offset = offset + 1; 1423 offset += shdr->section_size; 1424 1425 /* Section length is measured from the TAG block. */ 1426 shdr->section_size--; 1427 1428 /* Fixup the TAG command. */ 1429 cctx = sctx->cmd_head; 1430 while (cctx) { 1431 ccmd = &cctx->payload; 1432 if (ccmd->header.tag == ROM_TAG_CMD) { 1433 ccmd->tag.section_number = shdr->section_number; 1434 ccmd->tag.section_length = shdr->section_size; 1435 ccmd->tag.section_flags = shdr->section_flags; 1436 } 1437 1438 /* Update the command checksum. */ 1439 ccmd->header.checksum = sb_command_checksum(ccmd); 1440 1441 cctx = cctx->cmd; 1442 } 1443 1444 sctx = sctx->sect; 1445 } 1446 1447 return 0; 1448} 1449 1450static int sb_parse_line(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd) 1451{ 1452 char *tok; 1453 char *line = cmd->cmd; 1454 char *rptr = NULL; 1455 int ret; 1456 1457 /* Analyze the identifier on this line first. */ 1458 tok = strtok_r(line, " ", &rptr); 1459 if (!tok || (strlen(tok) == 0)) { 1460 fprintf(stderr, "#%i ERR: Invalid line!\n", cmd->lineno); 1461 return -EINVAL; 1462 } 1463 1464 cmd->cmd = rptr; 1465 1466 /* set DISPLAY_PROGRESS flag */ 1467 if (!strcmp(tok, "DISPLAYPROGRESS")) { 1468 ictx->display_progress = 1; 1469 return 0; 1470 } 1471 1472 /* DCD */ 1473 if (!strcmp(tok, "DCD")) { 1474 ictx->in_section = 0; 1475 ictx->in_dcd = 1; 1476 sb_build_dcd(ictx, cmd); 1477 return 0; 1478 } 1479 1480 /* Section */ 1481 if (!strcmp(tok, "SECTION")) { 1482 ictx->in_section = 1; 1483 ictx->in_dcd = 0; 1484 sb_build_section(ictx, cmd); 1485 return 0; 1486 } 1487 1488 if (!ictx->in_section && !ictx->in_dcd) { 1489 fprintf(stderr, "#%i ERR: Data outside of a section!\n", 1490 cmd->lineno); 1491 return -EINVAL; 1492 } 1493 1494 if (ictx->in_section) { 1495 /* Section commands */ 1496 if (!strcmp(tok, "NOP")) { 1497 ret = sb_build_command_nop(ictx); 1498 } else if (!strcmp(tok, "TAG")) { 1499 ret = sb_build_command_tag(ictx, cmd); 1500 } else if (!strcmp(tok, "LOAD")) { 1501 ret = sb_build_command_load(ictx, cmd); 1502 } else if (!strcmp(tok, "FILL")) { 1503 ret = sb_build_command_fill(ictx, cmd); 1504 } else if (!strcmp(tok, "JUMP")) { 1505 ret = sb_build_command_jump(ictx, cmd); 1506 } else if (!strcmp(tok, "CALL")) { 1507 ret = sb_build_command_call(ictx, cmd); 1508 } else if (!strcmp(tok, "MODE")) { 1509 ret = sb_build_command_mode(ictx, cmd); 1510 } else { 1511 fprintf(stderr, 1512 "#%i ERR: Unsupported instruction '%s'!\n", 1513 cmd->lineno, tok); 1514 return -ENOTSUP; 1515 } 1516 } else if (ictx->in_dcd) { 1517 char *lptr; 1518 uint32_t ilen = '1'; 1519 1520 tok = strtok_r(tok, ".", &lptr); 1521 if (!tok || (strlen(tok) == 0) || (lptr && strlen(lptr) != 1)) { 1522 fprintf(stderr, "#%i ERR: Invalid line!\n", 1523 cmd->lineno); 1524 return -EINVAL; 1525 } 1526 1527 if (lptr && 1528 (lptr[0] != '1' && lptr[0] != '2' && lptr[0] != '4')) { 1529 fprintf(stderr, "#%i ERR: Invalid instruction width!\n", 1530 cmd->lineno); 1531 return -EINVAL; 1532 } 1533 1534 if (lptr) 1535 ilen = lptr[0] - '1'; 1536 1537 /* DCD commands */ 1538 if (!strcmp(tok, "WRITE")) { 1539 ret = sb_build_dcd_block(ictx, cmd, 1540 SB_DCD_WRITE | ilen); 1541 } else if (!strcmp(tok, "ANDC")) { 1542 ret = sb_build_dcd_block(ictx, cmd, 1543 SB_DCD_ANDC | ilen); 1544 } else if (!strcmp(tok, "ORR")) { 1545 ret = sb_build_dcd_block(ictx, cmd, 1546 SB_DCD_ORR | ilen); 1547 } else if (!strcmp(tok, "EQZ")) { 1548 ret = sb_build_dcd_block(ictx, cmd, 1549 SB_DCD_CHK_EQZ | ilen); 1550 } else if (!strcmp(tok, "EQ")) { 1551 ret = sb_build_dcd_block(ictx, cmd, 1552 SB_DCD_CHK_EQ | ilen); 1553 } else if (!strcmp(tok, "NEQ")) { 1554 ret = sb_build_dcd_block(ictx, cmd, 1555 SB_DCD_CHK_NEQ | ilen); 1556 } else if (!strcmp(tok, "NEZ")) { 1557 ret = sb_build_dcd_block(ictx, cmd, 1558 SB_DCD_CHK_NEZ | ilen); 1559 } else if (!strcmp(tok, "NOOP")) { 1560 ret = sb_build_dcd_block(ictx, cmd, SB_DCD_NOOP); 1561 } else { 1562 fprintf(stderr, 1563 "#%i ERR: Unsupported instruction '%s'!\n", 1564 cmd->lineno, tok); 1565 return -ENOTSUP; 1566 } 1567 } else { 1568 fprintf(stderr, "#%i ERR: Unsupported instruction '%s'!\n", 1569 cmd->lineno, tok); 1570 return -ENOTSUP; 1571 } 1572 1573 /* 1574 * Here we have at least one section with one command, otherwise we 1575 * would have failed already higher above. 1576 * 1577 * FIXME -- should the updating happen here ? 1578 */ 1579 if (ictx->in_section && !ret) { 1580 ictx->sect_tail->size += ictx->sect_tail->cmd_tail->size; 1581 ictx->sect_tail->payload.section_size = 1582 ictx->sect_tail->size / SB_BLOCK_SIZE; 1583 } 1584 1585 return ret; 1586} 1587 1588static int sb_load_cmdfile(struct sb_image_ctx *ictx) 1589{ 1590 struct sb_cmd_list cmd; 1591 int lineno = 1; 1592 FILE *fp; 1593 char *line = NULL; 1594 ssize_t rlen; 1595 size_t len; 1596 1597 fp = fopen(ictx->cfg_filename, "r"); 1598 if (!fp) { 1599 fprintf(stderr, "ERR: Failed to load file \"%s\": \"%s\"\n", 1600 ictx->cfg_filename, strerror(errno)); 1601 return -EINVAL; 1602 } 1603 1604 while ((rlen = getline(&line, &len, fp)) > 0) { 1605 memset(&cmd, 0, sizeof(cmd)); 1606 1607 /* Strip the trailing newline. */ 1608 line[rlen - 1] = '\0'; 1609 1610 cmd.cmd = line; 1611 cmd.len = rlen; 1612 cmd.lineno = lineno++; 1613 1614 sb_parse_line(ictx, &cmd); 1615 } 1616 1617 free(line); 1618 1619 fclose(fp); 1620 1621 return 0; 1622} 1623 1624static int sb_build_tree_from_cfg(struct sb_image_ctx *ictx) 1625{ 1626 int ret; 1627 1628 ret = sb_load_cmdfile(ictx); 1629 if (ret) 1630 return ret; 1631 1632 ret = sb_prefill_image_header(ictx); 1633 if (ret) 1634 return ret; 1635 1636 ret = sb_postfill_image_header(ictx); 1637 if (ret) 1638 return ret; 1639 1640 ret = sb_fixup_sections_and_tags(ictx); 1641 if (ret) 1642 return ret; 1643 1644 return 0; 1645} 1646 1647static int sb_verify_image_header(struct sb_image_ctx *ictx, 1648 FILE *fp, long fsize) 1649{ 1650 /* Verify static fields in the image header. */ 1651 struct sb_boot_image_header *hdr = &ictx->payload; 1652 const char *stat[2] = { "[PASS]", "[FAIL]" }; 1653 struct tm tm; 1654 int sz, ret = 0; 1655 unsigned char digest[20]; 1656 EVP_MD_CTX *md_ctx; 1657 unsigned long size; 1658 1659 /* Start image-wide crypto. */ 1660 ictx->md_ctx = EVP_MD_CTX_new(); 1661 EVP_DigestInit(ictx->md_ctx, EVP_sha1()); 1662 1663 soprintf(ictx, "---------- Verifying SB Image Header ----------\n"); 1664 1665 size = fread(&ictx->payload, 1, sizeof(ictx->payload), fp); 1666 if (size != sizeof(ictx->payload)) { 1667 fprintf(stderr, "ERR: SB image header too short!\n"); 1668 return -EINVAL; 1669 } 1670 1671 /* Compute header digest. */ 1672 md_ctx = EVP_MD_CTX_new(); 1673 EVP_DigestInit(md_ctx, EVP_sha1()); 1674 EVP_DigestUpdate(md_ctx, hdr->signature1, 1675 sizeof(struct sb_boot_image_header) - 1676 sizeof(hdr->digest)); 1677 EVP_DigestFinal(md_ctx, digest, NULL); 1678 EVP_MD_CTX_free(md_ctx); 1679 1680 sb_aes_init(ictx, NULL, 1); 1681 sb_encrypt_sb_header(ictx); 1682 1683 if (memcmp(digest, hdr->digest, 20)) 1684 ret = -EINVAL; 1685 soprintf(ictx, "%s Image header checksum: %s\n", stat[!!ret], 1686 ret ? "BAD" : "OK"); 1687 if (ret) 1688 return ret; 1689 1690 if (memcmp(hdr->signature1, "STMP", 4) || 1691 memcmp(hdr->signature2, "sgtl", 4)) 1692 ret = -EINVAL; 1693 soprintf(ictx, "%s Signatures: '%.4s' '%.4s'\n", 1694 stat[!!ret], hdr->signature1, hdr->signature2); 1695 if (ret) 1696 return ret; 1697 1698 if ((hdr->major_version != SB_VERSION_MAJOR) || 1699 ((hdr->minor_version != 1) && (hdr->minor_version != 2))) 1700 ret = -EINVAL; 1701 soprintf(ictx, "%s Image version: v%i.%i\n", stat[!!ret], 1702 hdr->major_version, hdr->minor_version); 1703 if (ret) 1704 return ret; 1705 1706 ret = sb_get_time(hdr->timestamp_us / 1000000, &tm); 1707 soprintf(ictx, 1708 "%s Creation time: %02i:%02i:%02i %02i/%02i/%04i\n", 1709 stat[!!ret], tm.tm_hour, tm.tm_min, tm.tm_sec, 1710 tm.tm_mday, tm.tm_mon, tm.tm_year + 2000); 1711 if (ret) 1712 return ret; 1713 1714 soprintf(ictx, "%s Product version: %x.%x.%x\n", stat[0], 1715 ntohs(hdr->product_version.major), 1716 ntohs(hdr->product_version.minor), 1717 ntohs(hdr->product_version.revision)); 1718 soprintf(ictx, "%s Component version: %x.%x.%x\n", stat[0], 1719 ntohs(hdr->component_version.major), 1720 ntohs(hdr->component_version.minor), 1721 ntohs(hdr->component_version.revision)); 1722 1723 if (hdr->flags & ~SB_IMAGE_FLAGS_MASK) 1724 ret = -EINVAL; 1725 soprintf(ictx, "%s Image flags: %s\n", stat[!!ret], 1726 hdr->flags & SB_IMAGE_FLAG_DISPLAY_PROGRESS ? 1727 "Display_progress" : ""); 1728 if (ret) 1729 return ret; 1730 1731 if (hdr->drive_tag != 0) 1732 ret = -EINVAL; 1733 soprintf(ictx, "%s Drive tag: %i\n", stat[!!ret], 1734 hdr->drive_tag); 1735 if (ret) 1736 return ret; 1737 1738 sz = sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE; 1739 if (hdr->header_blocks != sz) 1740 ret = -EINVAL; 1741 soprintf(ictx, "%s Image header size (blocks): %i\n", stat[!!ret], 1742 hdr->header_blocks); 1743 if (ret) 1744 return ret; 1745 1746 sz = sizeof(struct sb_sections_header) / SB_BLOCK_SIZE; 1747 if (hdr->section_header_size != sz) 1748 ret = -EINVAL; 1749 soprintf(ictx, "%s Section header size (blocks): %i\n", stat[!!ret], 1750 hdr->section_header_size); 1751 if (ret) 1752 return ret; 1753 1754 soprintf(ictx, "%s Sections count: %i\n", stat[!!ret], 1755 hdr->section_count); 1756 soprintf(ictx, "%s First bootable section %i\n", stat[!!ret], 1757 hdr->first_boot_section_id); 1758 1759 if (hdr->image_blocks != fsize / SB_BLOCK_SIZE) 1760 ret = -EINVAL; 1761 soprintf(ictx, "%s Image size (blocks): %i\n", stat[!!ret], 1762 hdr->image_blocks); 1763 if (ret) 1764 return ret; 1765 1766 sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count; 1767 if (hdr->key_dictionary_block != sz) 1768 ret = -EINVAL; 1769 soprintf(ictx, "%s Key dict offset (blocks): %i\n", stat[!!ret], 1770 hdr->key_dictionary_block); 1771 if (ret) 1772 return ret; 1773 1774 if (hdr->key_count != 1) 1775 ret = -EINVAL; 1776 soprintf(ictx, "%s Number of encryption keys: %i\n", stat[!!ret], 1777 hdr->key_count); 1778 if (ret) 1779 return ret; 1780 1781 sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count; 1782 sz += hdr->key_count * 1783 sizeof(struct sb_key_dictionary_key) / SB_BLOCK_SIZE; 1784 if (hdr->first_boot_tag_block != (unsigned)sz) 1785 ret = -EINVAL; 1786 soprintf(ictx, "%s First TAG block (blocks): %i\n", stat[!!ret], 1787 hdr->first_boot_tag_block); 1788 if (ret) 1789 return ret; 1790 1791 return 0; 1792} 1793 1794static void sb_decrypt_tag(struct sb_image_ctx *ictx, 1795 struct sb_cmd_ctx *cctx) 1796{ 1797 EVP_MD_CTX *md_ctx = ictx->md_ctx; 1798 struct sb_command *cmd = &cctx->payload; 1799 1800 sb_aes_crypt(ictx, (uint8_t *)&cctx->c_payload, 1801 (uint8_t *)&cctx->payload, sizeof(*cmd)); 1802 EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd)); 1803} 1804 1805static int sb_verify_command(struct sb_image_ctx *ictx, 1806 struct sb_cmd_ctx *cctx, FILE *fp, 1807 unsigned long *tsize) 1808{ 1809 struct sb_command *ccmd = &cctx->payload; 1810 unsigned long size, asize; 1811 char *csum, *flag = ""; 1812 int ret; 1813 unsigned int i; 1814 uint8_t csn, csc = ccmd->header.checksum; 1815 ccmd->header.checksum = 0x5a; 1816 csn = sb_command_checksum(ccmd); 1817 ccmd->header.checksum = csc; 1818 1819 if (csc == csn) 1820 ret = 0; 1821 else 1822 ret = -EINVAL; 1823 csum = ret ? "checksum BAD" : "checksum OK"; 1824 1825 switch (ccmd->header.tag) { 1826 case ROM_NOP_CMD: 1827 soprintf(ictx, " NOOP # %s\n", csum); 1828 return ret; 1829 case ROM_TAG_CMD: 1830 if (ccmd->header.flags & ROM_TAG_CMD_FLAG_ROM_LAST_TAG) 1831 flag = "LAST"; 1832 soprintf(ictx, " TAG %s # %s\n", flag, csum); 1833 sb_aes_reinit(ictx, 0); 1834 return ret; 1835 case ROM_LOAD_CMD: 1836 soprintf(ictx, " LOAD addr=0x%08x length=0x%08x # %s\n", 1837 ccmd->load.address, ccmd->load.count, csum); 1838 1839 cctx->length = ccmd->load.count; 1840 asize = roundup(cctx->length, SB_BLOCK_SIZE); 1841 cctx->data = malloc(asize); 1842 if (!cctx->data) 1843 return -ENOMEM; 1844 1845 size = fread(cctx->data, 1, asize, fp); 1846 if (size != asize) { 1847 fprintf(stderr, 1848 "ERR: SB LOAD command payload too short!\n"); 1849 return -EINVAL; 1850 } 1851 1852 *tsize += size; 1853 1854 EVP_DigestUpdate(ictx->md_ctx, cctx->data, asize); 1855 sb_aes_crypt(ictx, cctx->data, cctx->data, asize); 1856 1857 if (ccmd->load.crc32 != pbl_crc32(0, 1858 (const char *)cctx->data, 1859 asize)) { 1860 fprintf(stderr, 1861 "ERR: SB LOAD command payload CRC32 invalid!\n"); 1862 return -EINVAL; 1863 } 1864 return 0; 1865 case ROM_FILL_CMD: 1866 soprintf(ictx, 1867 " FILL addr=0x%08x length=0x%08x pattern=0x%08x # %s\n", 1868 ccmd->fill.address, ccmd->fill.count, 1869 ccmd->fill.pattern, csum); 1870 return 0; 1871 case ROM_JUMP_CMD: 1872 if (ccmd->header.flags & ROM_JUMP_CMD_FLAG_HAB) 1873 flag = " HAB"; 1874 soprintf(ictx, 1875 " JUMP%s addr=0x%08x r0_arg=0x%08x # %s\n", 1876 flag, ccmd->fill.address, ccmd->jump.argument, csum); 1877 return 0; 1878 case ROM_CALL_CMD: 1879 if (ccmd->header.flags & ROM_CALL_CMD_FLAG_HAB) 1880 flag = " HAB"; 1881 soprintf(ictx, 1882 " CALL%s addr=0x%08x r0_arg=0x%08x # %s\n", 1883 flag, ccmd->fill.address, ccmd->jump.argument, csum); 1884 return 0; 1885 case ROM_MODE_CMD: 1886 for (i = 0; i < ARRAY_SIZE(modetable); i++) { 1887 if (ccmd->mode.mode == modetable[i].mode) { 1888 soprintf(ictx, " MODE %s # %s\n", 1889 modetable[i].name, csum); 1890 break; 1891 } 1892 } 1893 fprintf(stderr, " MODE !INVALID! # %s\n", csum); 1894 return 0; 1895 } 1896 1897 return ret; 1898} 1899 1900static int sb_verify_commands(struct sb_image_ctx *ictx, 1901 struct sb_section_ctx *sctx, FILE *fp) 1902{ 1903 unsigned long size, tsize = 0; 1904 struct sb_cmd_ctx *cctx; 1905 int ret; 1906 1907 sb_aes_reinit(ictx, 0); 1908 1909 while (tsize < sctx->size) { 1910 cctx = calloc(1, sizeof(*cctx)); 1911 if (!cctx) 1912 return -ENOMEM; 1913 if (!sctx->cmd_head) { 1914 sctx->cmd_head = cctx; 1915 sctx->cmd_tail = cctx; 1916 } else { 1917 sctx->cmd_tail->cmd = cctx; 1918 sctx->cmd_tail = cctx; 1919 } 1920 1921 size = fread(&cctx->c_payload, 1, sizeof(cctx->c_payload), fp); 1922 if (size != sizeof(cctx->c_payload)) { 1923 fprintf(stderr, "ERR: SB command header too short!\n"); 1924 return -EINVAL; 1925 } 1926 1927 tsize += size; 1928 1929 sb_decrypt_tag(ictx, cctx); 1930 1931 ret = sb_verify_command(ictx, cctx, fp, &tsize); 1932 if (ret) 1933 return -EINVAL; 1934 } 1935 1936 return 0; 1937} 1938 1939static int sb_verify_sections_cmds(struct sb_image_ctx *ictx, FILE *fp) 1940{ 1941 struct sb_boot_image_header *hdr = &ictx->payload; 1942 struct sb_sections_header *shdr; 1943 unsigned int i; 1944 int ret; 1945 struct sb_section_ctx *sctx; 1946 unsigned long size; 1947 char *bootable = ""; 1948 1949 soprintf(ictx, "----- Verifying SB Sections and Commands -----\n"); 1950 1951 for (i = 0; i < hdr->section_count; i++) { 1952 sctx = calloc(1, sizeof(*sctx)); 1953 if (!sctx) 1954 return -ENOMEM; 1955 if (!ictx->sect_head) { 1956 ictx->sect_head = sctx; 1957 ictx->sect_tail = sctx; 1958 } else { 1959 ictx->sect_tail->sect = sctx; 1960 ictx->sect_tail = sctx; 1961 } 1962 1963 size = fread(&sctx->payload, 1, sizeof(sctx->payload), fp); 1964 if (size != sizeof(sctx->payload)) { 1965 fprintf(stderr, "ERR: SB section header too short!\n"); 1966 return -EINVAL; 1967 } 1968 } 1969 1970 size = fread(&ictx->sb_dict_key, 1, sizeof(ictx->sb_dict_key), fp); 1971 if (size != sizeof(ictx->sb_dict_key)) { 1972 fprintf(stderr, "ERR: SB key dictionary too short!\n"); 1973 return -EINVAL; 1974 } 1975 1976 sb_encrypt_sb_sections_header(ictx); 1977 sb_aes_reinit(ictx, 0); 1978 sb_decrypt_key_dictionary_key(ictx); 1979 1980 sb_aes_reinit(ictx, 0); 1981 1982 sctx = ictx->sect_head; 1983 while (sctx) { 1984 shdr = &sctx->payload; 1985 1986 if (shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) { 1987 sctx->boot = 1; 1988 bootable = " BOOTABLE"; 1989 } 1990 1991 sctx->size = (shdr->section_size * SB_BLOCK_SIZE) + 1992 sizeof(struct sb_command); 1993 soprintf(ictx, "SECTION 0x%x%s # size = %i bytes\n", 1994 shdr->section_number, bootable, sctx->size); 1995 1996 if (shdr->section_flags & ~SB_SECTION_FLAG_BOOTABLE) 1997 fprintf(stderr, " WARN: Unknown section flag(s) %08x\n", 1998 shdr->section_flags); 1999 2000 if ((shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) && 2001 (hdr->first_boot_section_id != shdr->section_number)) { 2002 fprintf(stderr, 2003 " WARN: Bootable section does ID not match image header ID!\n"); 2004 } 2005 2006 ret = sb_verify_commands(ictx, sctx, fp); 2007 if (ret) 2008 return ret; 2009 2010 sctx = sctx->sect; 2011 } 2012 2013 /* 2014 * FIXME IDEA: 2015 * check if the first TAG command is at sctx->section_offset 2016 */ 2017 return 0; 2018} 2019 2020static int sb_verify_image_end(struct sb_image_ctx *ictx, 2021 FILE *fp, off_t filesz) 2022{ 2023 uint8_t digest[32]; 2024 unsigned long size; 2025 off_t pos; 2026 int ret; 2027 2028 soprintf(ictx, "------------- Verifying image end -------------\n"); 2029 2030 size = fread(digest, 1, sizeof(digest), fp); 2031 if (size != sizeof(digest)) { 2032 fprintf(stderr, "ERR: SB key dictionary too short!\n"); 2033 return -EINVAL; 2034 } 2035 2036 pos = ftell(fp); 2037 if (pos != filesz) { 2038 fprintf(stderr, "ERR: Trailing data past the image!\n"); 2039 return -EINVAL; 2040 } 2041 2042 /* Check the image digest. */ 2043 EVP_DigestFinal(ictx->md_ctx, ictx->digest, NULL); 2044 EVP_MD_CTX_free(ictx->md_ctx); 2045 2046 /* Decrypt the image digest from the input image. */ 2047 sb_aes_reinit(ictx, 0); 2048 sb_aes_crypt(ictx, digest, digest, sizeof(digest)); 2049 2050 /* Check all of 20 bytes of the SHA1 hash. */ 2051 ret = memcmp(digest, ictx->digest, 20) ? -EINVAL : 0; 2052 2053 if (ret) 2054 soprintf(ictx, "[FAIL] Full-image checksum: BAD\n"); 2055 else 2056 soprintf(ictx, "[PASS] Full-image checksum: OK\n"); 2057 2058 return ret; 2059} 2060 2061 2062static int sb_build_tree_from_img(struct sb_image_ctx *ictx) 2063{ 2064 long filesize; 2065 int ret; 2066 FILE *fp; 2067 2068 if (!ictx->input_filename) { 2069 fprintf(stderr, "ERR: Missing filename!\n"); 2070 return -EINVAL; 2071 } 2072 2073 fp = fopen(ictx->input_filename, "r"); 2074 if (!fp) 2075 goto err_open; 2076 2077 ret = fseek(fp, 0, SEEK_END); 2078 if (ret < 0) 2079 goto err_file; 2080 2081 filesize = ftell(fp); 2082 if (filesize < 0) 2083 goto err_file; 2084 2085 ret = fseek(fp, 0, SEEK_SET); 2086 if (ret < 0) 2087 goto err_file; 2088 2089 if (filesize < (signed)sizeof(ictx->payload)) { 2090 fprintf(stderr, "ERR: File too short!\n"); 2091 goto err_file; 2092 } 2093 2094 if (filesize & (SB_BLOCK_SIZE - 1)) { 2095 fprintf(stderr, "ERR: The file is not aligned!\n"); 2096 goto err_file; 2097 } 2098 2099 /* Load and verify image header */ 2100 ret = sb_verify_image_header(ictx, fp, filesize); 2101 if (ret) 2102 goto err_verify; 2103 2104 /* Load and verify sections and commands */ 2105 ret = sb_verify_sections_cmds(ictx, fp); 2106 if (ret) 2107 goto err_verify; 2108 2109 ret = sb_verify_image_end(ictx, fp, filesize); 2110 if (ret) 2111 goto err_verify; 2112 2113 ret = 0; 2114 2115err_verify: 2116 soprintf(ictx, "-------------------- Result -------------------\n"); 2117 soprintf(ictx, "Verification %s\n", ret ? "FAILED" : "PASSED"); 2118 2119 /* Stop the encryption session. */ 2120 sb_aes_deinit(ictx->cipher_ctx); 2121 2122 fclose(fp); 2123 return ret; 2124 2125err_file: 2126 fclose(fp); 2127err_open: 2128 fprintf(stderr, "ERR: Failed to load file \"%s\"\n", 2129 ictx->input_filename); 2130 return -EINVAL; 2131} 2132 2133static void sb_free_image(struct sb_image_ctx *ictx) 2134{ 2135 struct sb_section_ctx *sctx = ictx->sect_head, *s_head; 2136 struct sb_dcd_ctx *dctx = ictx->dcd_head, *d_head; 2137 struct sb_cmd_ctx *cctx, *c_head; 2138 2139 while (sctx) { 2140 s_head = sctx; 2141 c_head = sctx->cmd_head; 2142 2143 while (c_head) { 2144 cctx = c_head; 2145 c_head = c_head->cmd; 2146 if (cctx->data) 2147 free(cctx->data); 2148 free(cctx); 2149 } 2150 2151 sctx = sctx->sect; 2152 free(s_head); 2153 } 2154 2155 while (dctx) { 2156 d_head = dctx; 2157 dctx = dctx->dcd; 2158 free(d_head->payload); 2159 free(d_head); 2160 } 2161} 2162 2163/* 2164 * MXSSB-MKIMAGE glue code. 2165 */ 2166static int mxsimage_check_image_types(uint8_t type) 2167{ 2168 if (type == IH_TYPE_MXSIMAGE) 2169 return EXIT_SUCCESS; 2170 else 2171 return EXIT_FAILURE; 2172} 2173 2174static void mxsimage_set_header(void *ptr, struct stat *sbuf, int ifd, 2175 struct image_tool_params *params) 2176{ 2177} 2178 2179int mxsimage_check_params(struct image_tool_params *params) 2180{ 2181 if (!params) 2182 return -1; 2183 if (!strlen(params->imagename)) { 2184 fprintf(stderr, 2185 "Error: %s - Configuration file not specified, it is needed for mxsimage generation\n", 2186 params->cmdname); 2187 return -1; 2188 } 2189 2190 /* 2191 * Check parameters: 2192 * XIP is not allowed and verify that incompatible 2193 * parameters are not sent at the same time 2194 * For example, if list is required a data image must not be provided 2195 */ 2196 return (params->dflag && (params->fflag || params->lflag)) || 2197 (params->fflag && (params->dflag || params->lflag)) || 2198 (params->lflag && (params->dflag || params->fflag)) || 2199 (params->xflag) || !(strlen(params->imagename)); 2200} 2201 2202static int mxsimage_verify_print_header(char *file, int silent) 2203{ 2204 int ret; 2205 struct sb_image_ctx ctx; 2206 2207 memset(&ctx, 0, sizeof(ctx)); 2208 2209 ctx.input_filename = file; 2210 ctx.silent_dump = silent; 2211 2212 ret = sb_build_tree_from_img(&ctx); 2213 sb_free_image(&ctx); 2214 2215 return ret; 2216} 2217 2218char *imagefile; 2219static int mxsimage_verify_header(unsigned char *ptr, int image_size, 2220 struct image_tool_params *params) 2221{ 2222 struct sb_boot_image_header *hdr; 2223 2224 if (!ptr) 2225 return -EINVAL; 2226 2227 hdr = (struct sb_boot_image_header *)ptr; 2228 2229 /* 2230 * Check if the header contains the MXS image signatures, 2231 * if so, do a full-image verification. 2232 */ 2233 if (memcmp(hdr->signature1, "STMP", 4) || 2234 memcmp(hdr->signature2, "sgtl", 4)) 2235 return -EINVAL; 2236 2237 imagefile = params->imagefile; 2238 2239 return mxsimage_verify_print_header(params->imagefile, 1); 2240} 2241 2242static void mxsimage_print_header(const void *hdr, struct image_tool_params *params) 2243{ 2244 if (imagefile) 2245 mxsimage_verify_print_header(imagefile, 0); 2246} 2247 2248static int sb_build_image(struct sb_image_ctx *ictx, 2249 struct image_type_params *tparams) 2250{ 2251 struct sb_boot_image_header *sb_header = &ictx->payload; 2252 struct sb_section_ctx *sctx; 2253 struct sb_cmd_ctx *cctx; 2254 struct sb_command *ccmd; 2255 struct sb_key_dictionary_key *sb_dict_key = &ictx->sb_dict_key; 2256 2257 uint8_t *image, *iptr; 2258 2259 /* Calculate image size. */ 2260 uint32_t size = sizeof(*sb_header) + 2261 ictx->sect_count * sizeof(struct sb_sections_header) + 2262 sizeof(*sb_dict_key) + sizeof(ictx->digest); 2263 2264 sctx = ictx->sect_head; 2265 while (sctx) { 2266 size += sctx->size; 2267 sctx = sctx->sect; 2268 }; 2269 2270 image = malloc(size); 2271 if (!image) 2272 return -ENOMEM; 2273 iptr = image; 2274 2275 memcpy(iptr, sb_header, sizeof(*sb_header)); 2276 iptr += sizeof(*sb_header); 2277 2278 sctx = ictx->sect_head; 2279 while (sctx) { 2280 memcpy(iptr, &sctx->payload, sizeof(struct sb_sections_header)); 2281 iptr += sizeof(struct sb_sections_header); 2282 sctx = sctx->sect; 2283 }; 2284 2285 memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key)); 2286 iptr += sizeof(*sb_dict_key); 2287 2288 sctx = ictx->sect_head; 2289 while (sctx) { 2290 cctx = sctx->cmd_head; 2291 while (cctx) { 2292 ccmd = &cctx->payload; 2293 2294 memcpy(iptr, &cctx->c_payload, sizeof(cctx->payload)); 2295 iptr += sizeof(cctx->payload); 2296 2297 if (ccmd->header.tag == ROM_LOAD_CMD) { 2298 memcpy(iptr, cctx->data, cctx->length); 2299 iptr += cctx->length; 2300 } 2301 2302 cctx = cctx->cmd; 2303 } 2304 2305 sctx = sctx->sect; 2306 }; 2307 2308 memcpy(iptr, ictx->digest, sizeof(ictx->digest)); 2309 iptr += sizeof(ictx->digest); 2310 2311 /* Configure the mkimage */ 2312 tparams->hdr = image; 2313 tparams->header_size = size; 2314 2315 return 0; 2316} 2317 2318static int mxsimage_generate(struct image_tool_params *params, 2319 struct image_type_params *tparams) 2320{ 2321 int ret; 2322 struct sb_image_ctx ctx; 2323 2324 /* Do not copy the U-Boot image! */ 2325 params->skipcpy = 1; 2326 2327 memset(&ctx, 0, sizeof(ctx)); 2328 2329 ctx.cfg_filename = params->imagename; 2330 ctx.output_filename = params->imagefile; 2331 2332 ret = sb_build_tree_from_cfg(&ctx); 2333 if (ret) 2334 goto fail; 2335 2336 ret = sb_encrypt_image(&ctx); 2337 if (!ret) 2338 ret = sb_build_image(&ctx, tparams); 2339 2340fail: 2341 sb_free_image(&ctx); 2342 2343 return ret; 2344} 2345 2346/* 2347 * mxsimage parameters 2348 */ 2349U_BOOT_IMAGE_TYPE( 2350 mxsimage, 2351 "Freescale MXS Boot Image support", 2352 0, 2353 NULL, 2354 mxsimage_check_params, 2355 mxsimage_verify_header, 2356 mxsimage_print_header, 2357 mxsimage_set_header, 2358 NULL, 2359 mxsimage_check_image_types, 2360 NULL, 2361 mxsimage_generate 2362); 2363#endif 2364