1 /* 2 * Copyright (c) 2013, Google Inc. 3 * 4 * (C) Copyright 2008 Semihalf 5 * 6 * (C) Copyright 2000-2006 7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 8 * 9 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 */ 27 28 #ifdef USE_HOSTCC 29 #include "mkimage.h" 30 #include <image.h> 31 #include <time.h> 32 #else 33 #include <common.h> 34 #include <errno.h> 35 #include <asm/io.h> 36 DECLARE_GLOBAL_DATA_PTR; 37 #endif /* !USE_HOSTCC*/ 38 39 #include <bootstage.h> 40 #include <sha1.h> 41 #include <u-boot/crc.h> 42 #include <u-boot/md5.h> 43 44 /*****************************************************************************/ 45 /* New uImage format routines */ 46 /*****************************************************************************/ 47 #ifndef USE_HOSTCC 48 static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr, 49 ulong *addr, const char **name) 50 { 51 const char *sep; 52 53 *addr = addr_curr; 54 *name = NULL; 55 56 sep = strchr(spec, sepc); 57 if (sep) { 58 if (sep - spec > 0) 59 *addr = simple_strtoul(spec, NULL, 16); 60 61 *name = sep + 1; 62 return 1; 63 } 64 65 return 0; 66 } 67 68 /** 69 * fit_parse_conf - parse FIT configuration spec 70 * @spec: input string, containing configuration spec 71 * @add_curr: current image address (to be used as a possible default) 72 * @addr: pointer to a ulong variable, will hold FIT image address of a given 73 * configuration 74 * @conf_name double pointer to a char, will hold pointer to a configuration 75 * unit name 76 * 77 * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>, 78 * where <addr> is a FIT image address that contains configuration 79 * with a <conf> unit name. 80 * 81 * Address part is optional, and if omitted default add_curr will 82 * be used instead. 83 * 84 * returns: 85 * 1 if spec is a valid configuration string, 86 * addr and conf_name are set accordingly 87 * 0 otherwise 88 */ 89 int fit_parse_conf(const char *spec, ulong addr_curr, 90 ulong *addr, const char **conf_name) 91 { 92 return fit_parse_spec(spec, '#', addr_curr, addr, conf_name); 93 } 94 95 /** 96 * fit_parse_subimage - parse FIT subimage spec 97 * @spec: input string, containing subimage spec 98 * @add_curr: current image address (to be used as a possible default) 99 * @addr: pointer to a ulong variable, will hold FIT image address of a given 100 * subimage 101 * @image_name: double pointer to a char, will hold pointer to a subimage name 102 * 103 * fit_parse_subimage() expects subimage spec in the for of 104 * [<addr>]:<subimage>, where <addr> is a FIT image address that contains 105 * subimage with a <subimg> unit name. 106 * 107 * Address part is optional, and if omitted default add_curr will 108 * be used instead. 109 * 110 * returns: 111 * 1 if spec is a valid subimage string, 112 * addr and image_name are set accordingly 113 * 0 otherwise 114 */ 115 int fit_parse_subimage(const char *spec, ulong addr_curr, 116 ulong *addr, const char **image_name) 117 { 118 return fit_parse_spec(spec, ':', addr_curr, addr, image_name); 119 } 120 #endif /* !USE_HOSTCC */ 121 122 static void fit_get_debug(const void *fit, int noffset, 123 char *prop_name, int err) 124 { 125 debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n", 126 prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL), 127 fdt_strerror(err)); 128 } 129 130 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) 131 /** 132 * fit_print_contents - prints out the contents of the FIT format image 133 * @fit: pointer to the FIT format image header 134 * @p: pointer to prefix string 135 * 136 * fit_print_contents() formats a multi line FIT image contents description. 137 * The routine prints out FIT image properties (root node level) follwed by 138 * the details of each component image. 139 * 140 * returns: 141 * no returned results 142 */ 143 void fit_print_contents(const void *fit) 144 { 145 char *desc; 146 char *uname; 147 int images_noffset; 148 int confs_noffset; 149 int noffset; 150 int ndepth; 151 int count = 0; 152 int ret; 153 const char *p; 154 time_t timestamp; 155 156 /* Indent string is defined in header image.h */ 157 p = IMAGE_INDENT_STRING; 158 159 /* Root node properties */ 160 ret = fit_get_desc(fit, 0, &desc); 161 printf("%sFIT description: ", p); 162 if (ret) 163 printf("unavailable\n"); 164 else 165 printf("%s\n", desc); 166 167 if (IMAGE_ENABLE_TIMESTAMP) { 168 ret = fit_get_timestamp(fit, 0, ×tamp); 169 printf("%sCreated: ", p); 170 if (ret) 171 printf("unavailable\n"); 172 else 173 genimg_print_time(timestamp); 174 } 175 176 /* Find images parent node offset */ 177 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 178 if (images_noffset < 0) { 179 printf("Can't find images parent node '%s' (%s)\n", 180 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 181 return; 182 } 183 184 /* Process its subnodes, print out component images details */ 185 for (ndepth = 0, count = 0, 186 noffset = fdt_next_node(fit, images_noffset, &ndepth); 187 (noffset >= 0) && (ndepth > 0); 188 noffset = fdt_next_node(fit, noffset, &ndepth)) { 189 if (ndepth == 1) { 190 /* 191 * Direct child node of the images parent node, 192 * i.e. component image node. 193 */ 194 printf("%s Image %u (%s)\n", p, count++, 195 fit_get_name(fit, noffset, NULL)); 196 197 fit_image_print(fit, noffset, p); 198 } 199 } 200 201 /* Find configurations parent node offset */ 202 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 203 if (confs_noffset < 0) { 204 debug("Can't get configurations parent node '%s' (%s)\n", 205 FIT_CONFS_PATH, fdt_strerror(confs_noffset)); 206 return; 207 } 208 209 /* get default configuration unit name from default property */ 210 uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL); 211 if (uname) 212 printf("%s Default Configuration: '%s'\n", p, uname); 213 214 /* Process its subnodes, print out configurations details */ 215 for (ndepth = 0, count = 0, 216 noffset = fdt_next_node(fit, confs_noffset, &ndepth); 217 (noffset >= 0) && (ndepth > 0); 218 noffset = fdt_next_node(fit, noffset, &ndepth)) { 219 if (ndepth == 1) { 220 /* 221 * Direct child node of the configurations parent node, 222 * i.e. configuration node. 223 */ 224 printf("%s Configuration %u (%s)\n", p, count++, 225 fit_get_name(fit, noffset, NULL)); 226 227 fit_conf_print(fit, noffset, p); 228 } 229 } 230 } 231 232 /** 233 * fit_image_print_data() - prints out the hash node details 234 * @fit: pointer to the FIT format image header 235 * @noffset: offset of the hash node 236 * @p: pointer to prefix string 237 * 238 * fit_image_print_data() lists properies for the processed hash node 239 * 240 * returns: 241 * no returned results 242 */ 243 static void fit_image_print_data(const void *fit, int noffset, const char *p) 244 { 245 char *algo; 246 uint8_t *value; 247 int value_len; 248 int i, ret; 249 250 /* 251 * Check subnode name, must be equal to "hash". 252 * Multiple hash nodes require unique unit node 253 * names, e.g. hash@1, hash@2, etc. 254 */ 255 if (strncmp(fit_get_name(fit, noffset, NULL), 256 FIT_HASH_NODENAME, 257 strlen(FIT_HASH_NODENAME)) != 0) 258 return; 259 260 debug("%s Hash node: '%s'\n", p, 261 fit_get_name(fit, noffset, NULL)); 262 263 printf("%s Hash algo: ", p); 264 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 265 printf("invalid/unsupported\n"); 266 return; 267 } 268 printf("%s\n", algo); 269 270 ret = fit_image_hash_get_value(fit, noffset, &value, 271 &value_len); 272 printf("%s Hash value: ", p); 273 if (ret) { 274 printf("unavailable\n"); 275 } else { 276 for (i = 0; i < value_len; i++) 277 printf("%02x", value[i]); 278 printf("\n"); 279 } 280 281 debug("%s Hash len: %d\n", p, value_len); 282 } 283 284 /** 285 * fit_image_print_verification_data() - prints out the hash/signature details 286 * @fit: pointer to the FIT format image header 287 * @noffset: offset of the hash or signature node 288 * @p: pointer to prefix string 289 * 290 * This lists properies for the processed hash node 291 * 292 * returns: 293 * no returned results 294 */ 295 static void fit_image_print_verification_data(const void *fit, int noffset, 296 const char *p) 297 { 298 const char *name; 299 300 /* 301 * Check subnode name, must be equal to "hash" or "signature". 302 * Multiple hash/signature nodes require unique unit node 303 * names, e.g. hash@1, hash@2, signature@1, signature@2, etc. 304 */ 305 name = fit_get_name(fit, noffset, NULL); 306 if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) 307 fit_image_print_data(fit, noffset, p); 308 } 309 310 /** 311 * fit_image_print - prints out the FIT component image details 312 * @fit: pointer to the FIT format image header 313 * @image_noffset: offset of the component image node 314 * @p: pointer to prefix string 315 * 316 * fit_image_print() lists all mandatory properies for the processed component 317 * image. If present, hash nodes are printed out as well. Load 318 * address for images of type firmware is also printed out. Since the load 319 * address is not mandatory for firmware images, it will be output as 320 * "unavailable" when not present. 321 * 322 * returns: 323 * no returned results 324 */ 325 void fit_image_print(const void *fit, int image_noffset, const char *p) 326 { 327 char *desc; 328 uint8_t type, arch, os, comp; 329 size_t size; 330 ulong load, entry; 331 const void *data; 332 int noffset; 333 int ndepth; 334 int ret; 335 336 /* Mandatory properties */ 337 ret = fit_get_desc(fit, image_noffset, &desc); 338 printf("%s Description: ", p); 339 if (ret) 340 printf("unavailable\n"); 341 else 342 printf("%s\n", desc); 343 344 fit_image_get_type(fit, image_noffset, &type); 345 printf("%s Type: %s\n", p, genimg_get_type_name(type)); 346 347 fit_image_get_comp(fit, image_noffset, &comp); 348 printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); 349 350 ret = fit_image_get_data(fit, image_noffset, &data, &size); 351 352 #ifndef USE_HOSTCC 353 printf("%s Data Start: ", p); 354 if (ret) 355 printf("unavailable\n"); 356 else 357 printf("0x%08lx\n", (ulong)data); 358 #endif 359 360 printf("%s Data Size: ", p); 361 if (ret) 362 printf("unavailable\n"); 363 else 364 genimg_print_size(size); 365 366 /* Remaining, type dependent properties */ 367 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || 368 (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || 369 (type == IH_TYPE_FLATDT)) { 370 fit_image_get_arch(fit, image_noffset, &arch); 371 printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); 372 } 373 374 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { 375 fit_image_get_os(fit, image_noffset, &os); 376 printf("%s OS: %s\n", p, genimg_get_os_name(os)); 377 } 378 379 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || 380 (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { 381 ret = fit_image_get_load(fit, image_noffset, &load); 382 printf("%s Load Address: ", p); 383 if (ret) 384 printf("unavailable\n"); 385 else 386 printf("0x%08lx\n", load); 387 } 388 389 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || 390 (type == IH_TYPE_RAMDISK)) { 391 fit_image_get_entry(fit, image_noffset, &entry); 392 printf("%s Entry Point: ", p); 393 if (ret) 394 printf("unavailable\n"); 395 else 396 printf("0x%08lx\n", entry); 397 } 398 399 /* Process all hash subnodes of the component image node */ 400 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); 401 (noffset >= 0) && (ndepth > 0); 402 noffset = fdt_next_node(fit, noffset, &ndepth)) { 403 if (ndepth == 1) { 404 /* Direct child node of the component image node */ 405 fit_image_print_verification_data(fit, noffset, p); 406 } 407 } 408 } 409 #endif 410 411 /** 412 * fit_get_desc - get node description property 413 * @fit: pointer to the FIT format image header 414 * @noffset: node offset 415 * @desc: double pointer to the char, will hold pointer to the descrption 416 * 417 * fit_get_desc() reads description property from a given node, if 418 * description is found pointer to it is returened in third call argument. 419 * 420 * returns: 421 * 0, on success 422 * -1, on failure 423 */ 424 int fit_get_desc(const void *fit, int noffset, char **desc) 425 { 426 int len; 427 428 *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len); 429 if (*desc == NULL) { 430 fit_get_debug(fit, noffset, FIT_DESC_PROP, len); 431 return -1; 432 } 433 434 return 0; 435 } 436 437 /** 438 * fit_get_timestamp - get node timestamp property 439 * @fit: pointer to the FIT format image header 440 * @noffset: node offset 441 * @timestamp: pointer to the time_t, will hold read timestamp 442 * 443 * fit_get_timestamp() reads timestamp poperty from given node, if timestamp 444 * is found and has a correct size its value is retured in third call 445 * argument. 446 * 447 * returns: 448 * 0, on success 449 * -1, on property read failure 450 * -2, on wrong timestamp size 451 */ 452 int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp) 453 { 454 int len; 455 const void *data; 456 457 data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len); 458 if (data == NULL) { 459 fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len); 460 return -1; 461 } 462 if (len != sizeof(uint32_t)) { 463 debug("FIT timestamp with incorrect size of (%u)\n", len); 464 return -2; 465 } 466 467 *timestamp = uimage_to_cpu(*((uint32_t *)data)); 468 return 0; 469 } 470 471 /** 472 * fit_image_get_node - get node offset for component image of a given unit name 473 * @fit: pointer to the FIT format image header 474 * @image_uname: component image node unit name 475 * 476 * fit_image_get_node() finds a component image (withing the '/images' 477 * node) of a provided unit name. If image is found its node offset is 478 * returned to the caller. 479 * 480 * returns: 481 * image node offset when found (>=0) 482 * negative number on failure (FDT_ERR_* code) 483 */ 484 int fit_image_get_node(const void *fit, const char *image_uname) 485 { 486 int noffset, images_noffset; 487 488 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 489 if (images_noffset < 0) { 490 debug("Can't find images parent node '%s' (%s)\n", 491 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 492 return images_noffset; 493 } 494 495 noffset = fdt_subnode_offset(fit, images_noffset, image_uname); 496 if (noffset < 0) { 497 debug("Can't get node offset for image unit name: '%s' (%s)\n", 498 image_uname, fdt_strerror(noffset)); 499 } 500 501 return noffset; 502 } 503 504 /** 505 * fit_image_get_os - get os id for a given component image node 506 * @fit: pointer to the FIT format image header 507 * @noffset: component image node offset 508 * @os: pointer to the uint8_t, will hold os numeric id 509 * 510 * fit_image_get_os() finds os property in a given component image node. 511 * If the property is found, its (string) value is translated to the numeric 512 * id which is returned to the caller. 513 * 514 * returns: 515 * 0, on success 516 * -1, on failure 517 */ 518 int fit_image_get_os(const void *fit, int noffset, uint8_t *os) 519 { 520 int len; 521 const void *data; 522 523 /* Get OS name from property data */ 524 data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len); 525 if (data == NULL) { 526 fit_get_debug(fit, noffset, FIT_OS_PROP, len); 527 *os = -1; 528 return -1; 529 } 530 531 /* Translate OS name to id */ 532 *os = genimg_get_os_id(data); 533 return 0; 534 } 535 536 /** 537 * fit_image_get_arch - get arch id for a given component image node 538 * @fit: pointer to the FIT format image header 539 * @noffset: component image node offset 540 * @arch: pointer to the uint8_t, will hold arch numeric id 541 * 542 * fit_image_get_arch() finds arch property in a given component image node. 543 * If the property is found, its (string) value is translated to the numeric 544 * id which is returned to the caller. 545 * 546 * returns: 547 * 0, on success 548 * -1, on failure 549 */ 550 int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch) 551 { 552 int len; 553 const void *data; 554 555 /* Get architecture name from property data */ 556 data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len); 557 if (data == NULL) { 558 fit_get_debug(fit, noffset, FIT_ARCH_PROP, len); 559 *arch = -1; 560 return -1; 561 } 562 563 /* Translate architecture name to id */ 564 *arch = genimg_get_arch_id(data); 565 return 0; 566 } 567 568 /** 569 * fit_image_get_type - get type id for a given component image node 570 * @fit: pointer to the FIT format image header 571 * @noffset: component image node offset 572 * @type: pointer to the uint8_t, will hold type numeric id 573 * 574 * fit_image_get_type() finds type property in a given component image node. 575 * If the property is found, its (string) value is translated to the numeric 576 * id which is returned to the caller. 577 * 578 * returns: 579 * 0, on success 580 * -1, on failure 581 */ 582 int fit_image_get_type(const void *fit, int noffset, uint8_t *type) 583 { 584 int len; 585 const void *data; 586 587 /* Get image type name from property data */ 588 data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len); 589 if (data == NULL) { 590 fit_get_debug(fit, noffset, FIT_TYPE_PROP, len); 591 *type = -1; 592 return -1; 593 } 594 595 /* Translate image type name to id */ 596 *type = genimg_get_type_id(data); 597 return 0; 598 } 599 600 /** 601 * fit_image_get_comp - get comp id for a given component image node 602 * @fit: pointer to the FIT format image header 603 * @noffset: component image node offset 604 * @comp: pointer to the uint8_t, will hold comp numeric id 605 * 606 * fit_image_get_comp() finds comp property in a given component image node. 607 * If the property is found, its (string) value is translated to the numeric 608 * id which is returned to the caller. 609 * 610 * returns: 611 * 0, on success 612 * -1, on failure 613 */ 614 int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp) 615 { 616 int len; 617 const void *data; 618 619 /* Get compression name from property data */ 620 data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len); 621 if (data == NULL) { 622 fit_get_debug(fit, noffset, FIT_COMP_PROP, len); 623 *comp = -1; 624 return -1; 625 } 626 627 /* Translate compression name to id */ 628 *comp = genimg_get_comp_id(data); 629 return 0; 630 } 631 632 /** 633 * fit_image_get_load() - get load addr property for given component image node 634 * @fit: pointer to the FIT format image header 635 * @noffset: component image node offset 636 * @load: pointer to the uint32_t, will hold load address 637 * 638 * fit_image_get_load() finds load address property in a given component 639 * image node. If the property is found, its value is returned to the caller. 640 * 641 * returns: 642 * 0, on success 643 * -1, on failure 644 */ 645 int fit_image_get_load(const void *fit, int noffset, ulong *load) 646 { 647 int len; 648 const uint32_t *data; 649 650 data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len); 651 if (data == NULL) { 652 fit_get_debug(fit, noffset, FIT_LOAD_PROP, len); 653 return -1; 654 } 655 656 *load = uimage_to_cpu(*data); 657 return 0; 658 } 659 660 /** 661 * fit_image_get_entry() - get entry point address property 662 * @fit: pointer to the FIT format image header 663 * @noffset: component image node offset 664 * @entry: pointer to the uint32_t, will hold entry point address 665 * 666 * This gets the entry point address property for a given component image 667 * node. 668 * 669 * fit_image_get_entry() finds entry point address property in a given 670 * component image node. If the property is found, its value is returned 671 * to the caller. 672 * 673 * returns: 674 * 0, on success 675 * -1, on failure 676 */ 677 int fit_image_get_entry(const void *fit, int noffset, ulong *entry) 678 { 679 int len; 680 const uint32_t *data; 681 682 data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len); 683 if (data == NULL) { 684 fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len); 685 return -1; 686 } 687 688 *entry = uimage_to_cpu(*data); 689 return 0; 690 } 691 692 /** 693 * fit_image_get_data - get data property and its size for a given component image node 694 * @fit: pointer to the FIT format image header 695 * @noffset: component image node offset 696 * @data: double pointer to void, will hold data property's data address 697 * @size: pointer to size_t, will hold data property's data size 698 * 699 * fit_image_get_data() finds data property in a given component image node. 700 * If the property is found its data start address and size are returned to 701 * the caller. 702 * 703 * returns: 704 * 0, on success 705 * -1, on failure 706 */ 707 int fit_image_get_data(const void *fit, int noffset, 708 const void **data, size_t *size) 709 { 710 int len; 711 712 *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len); 713 if (*data == NULL) { 714 fit_get_debug(fit, noffset, FIT_DATA_PROP, len); 715 *size = 0; 716 return -1; 717 } 718 719 *size = len; 720 return 0; 721 } 722 723 /** 724 * fit_image_hash_get_algo - get hash algorithm name 725 * @fit: pointer to the FIT format image header 726 * @noffset: hash node offset 727 * @algo: double pointer to char, will hold pointer to the algorithm name 728 * 729 * fit_image_hash_get_algo() finds hash algorithm property in a given hash node. 730 * If the property is found its data start address is returned to the caller. 731 * 732 * returns: 733 * 0, on success 734 * -1, on failure 735 */ 736 int fit_image_hash_get_algo(const void *fit, int noffset, char **algo) 737 { 738 int len; 739 740 *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len); 741 if (*algo == NULL) { 742 fit_get_debug(fit, noffset, FIT_ALGO_PROP, len); 743 return -1; 744 } 745 746 return 0; 747 } 748 749 /** 750 * fit_image_hash_get_value - get hash value and length 751 * @fit: pointer to the FIT format image header 752 * @noffset: hash node offset 753 * @value: double pointer to uint8_t, will hold address of a hash value data 754 * @value_len: pointer to an int, will hold hash data length 755 * 756 * fit_image_hash_get_value() finds hash value property in a given hash node. 757 * If the property is found its data start address and size are returned to 758 * the caller. 759 * 760 * returns: 761 * 0, on success 762 * -1, on failure 763 */ 764 int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, 765 int *value_len) 766 { 767 int len; 768 769 *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len); 770 if (*value == NULL) { 771 fit_get_debug(fit, noffset, FIT_VALUE_PROP, len); 772 *value_len = 0; 773 return -1; 774 } 775 776 *value_len = len; 777 return 0; 778 } 779 780 /** 781 * fit_image_hash_get_ignore - get hash ignore flag 782 * @fit: pointer to the FIT format image header 783 * @noffset: hash node offset 784 * @ignore: pointer to an int, will hold hash ignore flag 785 * 786 * fit_image_hash_get_ignore() finds hash ignore property in a given hash node. 787 * If the property is found and non-zero, the hash algorithm is not verified by 788 * u-boot automatically. 789 * 790 * returns: 791 * 0, on ignore not found 792 * value, on ignore found 793 */ 794 static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) 795 { 796 int len; 797 int *value; 798 799 value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len); 800 if (value == NULL || len != sizeof(int)) 801 *ignore = 0; 802 else 803 *ignore = *value; 804 805 return 0; 806 } 807 808 /** 809 * fit_set_timestamp - set node timestamp property 810 * @fit: pointer to the FIT format image header 811 * @noffset: node offset 812 * @timestamp: timestamp value to be set 813 * 814 * fit_set_timestamp() attempts to set timestamp property in the requested 815 * node and returns operation status to the caller. 816 * 817 * returns: 818 * 0, on success 819 * -1, on property read failure 820 */ 821 int fit_set_timestamp(void *fit, int noffset, time_t timestamp) 822 { 823 uint32_t t; 824 int ret; 825 826 t = cpu_to_uimage(timestamp); 827 ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t, 828 sizeof(uint32_t)); 829 if (ret) { 830 printf("Can't set '%s' property for '%s' node (%s)\n", 831 FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), 832 fdt_strerror(ret)); 833 return -1; 834 } 835 836 return 0; 837 } 838 839 /** 840 * calculate_hash - calculate and return hash for provided input data 841 * @data: pointer to the input data 842 * @data_len: data length 843 * @algo: requested hash algorithm 844 * @value: pointer to the char, will hold hash value data (caller must 845 * allocate enough free space) 846 * value_len: length of the calculated hash 847 * 848 * calculate_hash() computes input data hash according to the requested 849 * algorithm. 850 * Resulting hash value is placed in caller provided 'value' buffer, length 851 * of the calculated hash is returned via value_len pointer argument. 852 * 853 * returns: 854 * 0, on success 855 * -1, when algo is unsupported 856 */ 857 int calculate_hash(const void *data, int data_len, const char *algo, 858 uint8_t *value, int *value_len) 859 { 860 if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) { 861 *((uint32_t *)value) = crc32_wd(0, data, data_len, 862 CHUNKSZ_CRC32); 863 *((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value)); 864 *value_len = 4; 865 } else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) { 866 sha1_csum_wd((unsigned char *)data, data_len, 867 (unsigned char *)value, CHUNKSZ_SHA1); 868 *value_len = 20; 869 } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) { 870 md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5); 871 *value_len = 16; 872 } else { 873 debug("Unsupported hash alogrithm\n"); 874 return -1; 875 } 876 return 0; 877 } 878 879 static int fit_image_check_hash(const void *fit, int noffset, const void *data, 880 size_t size, char **err_msgp) 881 { 882 uint8_t value[FIT_MAX_HASH_LEN]; 883 int value_len; 884 char *algo; 885 uint8_t *fit_value; 886 int fit_value_len; 887 int ignore; 888 889 *err_msgp = NULL; 890 891 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 892 *err_msgp = "Can't get hash algo property"; 893 return -1; 894 } 895 printf("%s", algo); 896 897 if (IMAGE_ENABLE_IGNORE) { 898 fit_image_hash_get_ignore(fit, noffset, &ignore); 899 if (ignore) { 900 printf("-skipped "); 901 return 0; 902 } 903 } 904 905 if (fit_image_hash_get_value(fit, noffset, &fit_value, 906 &fit_value_len)) { 907 *err_msgp = "Can't get hash value property"; 908 return -1; 909 } 910 911 if (calculate_hash(data, size, algo, value, &value_len)) { 912 *err_msgp = "Unsupported hash algorithm"; 913 return -1; 914 } 915 916 if (value_len != fit_value_len) { 917 *err_msgp = "Bad hash value len"; 918 return -1; 919 } else if (memcmp(value, fit_value, value_len) != 0) { 920 *err_msgp = "Bad hash value"; 921 return -1; 922 } 923 924 return 0; 925 } 926 927 /** 928 * fit_image_verify - verify data intergity 929 * @fit: pointer to the FIT format image header 930 * @image_noffset: component image node offset 931 * 932 * fit_image_verify() goes over component image hash nodes, 933 * re-calculates each data hash and compares with the value stored in hash 934 * node. 935 * 936 * returns: 937 * 1, if all hashes are valid 938 * 0, otherwise (or on error) 939 */ 940 int fit_image_verify(const void *fit, int image_noffset) 941 { 942 const void *data; 943 size_t size; 944 int noffset; 945 char *err_msg = ""; 946 947 /* Get image data and data length */ 948 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 949 err_msg = "Can't get image data/size"; 950 return 0; 951 } 952 953 /* Process all hash subnodes of the component image node */ 954 for (noffset = fdt_first_subnode(fit, image_noffset); 955 noffset >= 0; 956 noffset = fdt_next_subnode(fit, noffset)) { 957 const char *name = fit_get_name(fit, noffset, NULL); 958 959 /* 960 * Check subnode name, must be equal to "hash". 961 * Multiple hash nodes require unique unit node 962 * names, e.g. hash@1, hash@2, etc. 963 */ 964 if (!strncmp(name, FIT_HASH_NODENAME, 965 strlen(FIT_HASH_NODENAME))) { 966 if (fit_image_check_hash(fit, noffset, data, size, 967 &err_msg)) 968 goto error; 969 puts("+ "); 970 } 971 } 972 973 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { 974 err_msg = "Corrupted or truncated tree"; 975 goto error; 976 } 977 978 return 1; 979 980 error: 981 printf(" error!\n%s for '%s' hash node in '%s' image node\n", 982 err_msg, fit_get_name(fit, noffset, NULL), 983 fit_get_name(fit, image_noffset, NULL)); 984 return 0; 985 } 986 987 /** 988 * fit_all_image_verify - verify data intergity for all images 989 * @fit: pointer to the FIT format image header 990 * 991 * fit_all_image_verify() goes over all images in the FIT and 992 * for every images checks if all it's hashes are valid. 993 * 994 * returns: 995 * 1, if all hashes of all images are valid 996 * 0, otherwise (or on error) 997 */ 998 int fit_all_image_verify(const void *fit) 999 { 1000 int images_noffset; 1001 int noffset; 1002 int ndepth; 1003 int count; 1004 1005 /* Find images parent node offset */ 1006 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 1007 if (images_noffset < 0) { 1008 printf("Can't find images parent node '%s' (%s)\n", 1009 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 1010 return 0; 1011 } 1012 1013 /* Process all image subnodes, check hashes for each */ 1014 printf("## Checking hash(es) for FIT Image at %08lx ...\n", 1015 (ulong)fit); 1016 for (ndepth = 0, count = 0, 1017 noffset = fdt_next_node(fit, images_noffset, &ndepth); 1018 (noffset >= 0) && (ndepth > 0); 1019 noffset = fdt_next_node(fit, noffset, &ndepth)) { 1020 if (ndepth == 1) { 1021 /* 1022 * Direct child node of the images parent node, 1023 * i.e. component image node. 1024 */ 1025 printf(" Hash(es) for Image %u (%s): ", count++, 1026 fit_get_name(fit, noffset, NULL)); 1027 1028 if (!fit_image_verify(fit, noffset)) 1029 return 0; 1030 printf("\n"); 1031 } 1032 } 1033 return 1; 1034 } 1035 1036 /** 1037 * fit_image_check_os - check whether image node is of a given os type 1038 * @fit: pointer to the FIT format image header 1039 * @noffset: component image node offset 1040 * @os: requested image os 1041 * 1042 * fit_image_check_os() reads image os property and compares its numeric 1043 * id with the requested os. Comparison result is returned to the caller. 1044 * 1045 * returns: 1046 * 1 if image is of given os type 1047 * 0 otherwise (or on error) 1048 */ 1049 int fit_image_check_os(const void *fit, int noffset, uint8_t os) 1050 { 1051 uint8_t image_os; 1052 1053 if (fit_image_get_os(fit, noffset, &image_os)) 1054 return 0; 1055 return (os == image_os); 1056 } 1057 1058 /** 1059 * fit_image_check_arch - check whether image node is of a given arch 1060 * @fit: pointer to the FIT format image header 1061 * @noffset: component image node offset 1062 * @arch: requested imagearch 1063 * 1064 * fit_image_check_arch() reads image arch property and compares its numeric 1065 * id with the requested arch. Comparison result is returned to the caller. 1066 * 1067 * returns: 1068 * 1 if image is of given arch 1069 * 0 otherwise (or on error) 1070 */ 1071 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) 1072 { 1073 uint8_t image_arch; 1074 1075 if (fit_image_get_arch(fit, noffset, &image_arch)) 1076 return 0; 1077 return (arch == image_arch); 1078 } 1079 1080 /** 1081 * fit_image_check_type - check whether image node is of a given type 1082 * @fit: pointer to the FIT format image header 1083 * @noffset: component image node offset 1084 * @type: requested image type 1085 * 1086 * fit_image_check_type() reads image type property and compares its numeric 1087 * id with the requested type. Comparison result is returned to the caller. 1088 * 1089 * returns: 1090 * 1 if image is of given type 1091 * 0 otherwise (or on error) 1092 */ 1093 int fit_image_check_type(const void *fit, int noffset, uint8_t type) 1094 { 1095 uint8_t image_type; 1096 1097 if (fit_image_get_type(fit, noffset, &image_type)) 1098 return 0; 1099 return (type == image_type); 1100 } 1101 1102 /** 1103 * fit_image_check_comp - check whether image node uses given compression 1104 * @fit: pointer to the FIT format image header 1105 * @noffset: component image node offset 1106 * @comp: requested image compression type 1107 * 1108 * fit_image_check_comp() reads image compression property and compares its 1109 * numeric id with the requested compression type. Comparison result is 1110 * returned to the caller. 1111 * 1112 * returns: 1113 * 1 if image uses requested compression 1114 * 0 otherwise (or on error) 1115 */ 1116 int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) 1117 { 1118 uint8_t image_comp; 1119 1120 if (fit_image_get_comp(fit, noffset, &image_comp)) 1121 return 0; 1122 return (comp == image_comp); 1123 } 1124 1125 /** 1126 * fit_check_format - sanity check FIT image format 1127 * @fit: pointer to the FIT format image header 1128 * 1129 * fit_check_format() runs a basic sanity FIT image verification. 1130 * Routine checks for mandatory properties, nodes, etc. 1131 * 1132 * returns: 1133 * 1, on success 1134 * 0, on failure 1135 */ 1136 int fit_check_format(const void *fit) 1137 { 1138 /* mandatory / node 'description' property */ 1139 if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) { 1140 debug("Wrong FIT format: no description\n"); 1141 return 0; 1142 } 1143 1144 if (IMAGE_ENABLE_TIMESTAMP) { 1145 /* mandatory / node 'timestamp' property */ 1146 if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) { 1147 debug("Wrong FIT format: no timestamp\n"); 1148 return 0; 1149 } 1150 } 1151 1152 /* mandatory subimages parent '/images' node */ 1153 if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) { 1154 debug("Wrong FIT format: no images parent node\n"); 1155 return 0; 1156 } 1157 1158 return 1; 1159 } 1160 1161 1162 /** 1163 * fit_conf_find_compat 1164 * @fit: pointer to the FIT format image header 1165 * @fdt: pointer to the device tree to compare against 1166 * 1167 * fit_conf_find_compat() attempts to find the configuration whose fdt is the 1168 * most compatible with the passed in device tree. 1169 * 1170 * Example: 1171 * 1172 * / o image-tree 1173 * |-o images 1174 * | |-o fdt@1 1175 * | |-o fdt@2 1176 * | 1177 * |-o configurations 1178 * |-o config@1 1179 * | |-fdt = fdt@1 1180 * | 1181 * |-o config@2 1182 * |-fdt = fdt@2 1183 * 1184 * / o U-Boot fdt 1185 * |-compatible = "foo,bar", "bim,bam" 1186 * 1187 * / o kernel fdt1 1188 * |-compatible = "foo,bar", 1189 * 1190 * / o kernel fdt2 1191 * |-compatible = "bim,bam", "baz,biz" 1192 * 1193 * Configuration 1 would be picked because the first string in U-Boot's 1194 * compatible list, "foo,bar", matches a compatible string in the root of fdt1. 1195 * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1. 1196 * 1197 * returns: 1198 * offset to the configuration to use if one was found 1199 * -1 otherwise 1200 */ 1201 int fit_conf_find_compat(const void *fit, const void *fdt) 1202 { 1203 int ndepth = 0; 1204 int noffset, confs_noffset, images_noffset; 1205 const void *fdt_compat; 1206 int fdt_compat_len; 1207 int best_match_offset = 0; 1208 int best_match_pos = 0; 1209 1210 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 1211 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 1212 if (confs_noffset < 0 || images_noffset < 0) { 1213 debug("Can't find configurations or images nodes.\n"); 1214 return -1; 1215 } 1216 1217 fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len); 1218 if (!fdt_compat) { 1219 debug("Fdt for comparison has no \"compatible\" property.\n"); 1220 return -1; 1221 } 1222 1223 /* 1224 * Loop over the configurations in the FIT image. 1225 */ 1226 for (noffset = fdt_next_node(fit, confs_noffset, &ndepth); 1227 (noffset >= 0) && (ndepth > 0); 1228 noffset = fdt_next_node(fit, noffset, &ndepth)) { 1229 const void *kfdt; 1230 const char *kfdt_name; 1231 int kfdt_noffset; 1232 const char *cur_fdt_compat; 1233 int len; 1234 size_t size; 1235 int i; 1236 1237 if (ndepth > 1) 1238 continue; 1239 1240 kfdt_name = fdt_getprop(fit, noffset, "fdt", &len); 1241 if (!kfdt_name) { 1242 debug("No fdt property found.\n"); 1243 continue; 1244 } 1245 kfdt_noffset = fdt_subnode_offset(fit, images_noffset, 1246 kfdt_name); 1247 if (kfdt_noffset < 0) { 1248 debug("No image node named \"%s\" found.\n", 1249 kfdt_name); 1250 continue; 1251 } 1252 /* 1253 * Get a pointer to this configuration's fdt. 1254 */ 1255 if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) { 1256 debug("Failed to get fdt \"%s\".\n", kfdt_name); 1257 continue; 1258 } 1259 1260 len = fdt_compat_len; 1261 cur_fdt_compat = fdt_compat; 1262 /* 1263 * Look for a match for each U-Boot compatibility string in 1264 * turn in this configuration's fdt. 1265 */ 1266 for (i = 0; len > 0 && 1267 (!best_match_offset || best_match_pos > i); i++) { 1268 int cur_len = strlen(cur_fdt_compat) + 1; 1269 1270 if (!fdt_node_check_compatible(kfdt, 0, 1271 cur_fdt_compat)) { 1272 best_match_offset = noffset; 1273 best_match_pos = i; 1274 break; 1275 } 1276 len -= cur_len; 1277 cur_fdt_compat += cur_len; 1278 } 1279 } 1280 if (!best_match_offset) { 1281 debug("No match found.\n"); 1282 return -1; 1283 } 1284 1285 return best_match_offset; 1286 } 1287 1288 /** 1289 * fit_conf_get_node - get node offset for configuration of a given unit name 1290 * @fit: pointer to the FIT format image header 1291 * @conf_uname: configuration node unit name 1292 * 1293 * fit_conf_get_node() finds a configuration (withing the '/configurations' 1294 * parant node) of a provided unit name. If configuration is found its node 1295 * offset is returned to the caller. 1296 * 1297 * When NULL is provided in second argument fit_conf_get_node() will search 1298 * for a default configuration node instead. Default configuration node unit 1299 * name is retrived from FIT_DEFAULT_PROP property of the '/configurations' 1300 * node. 1301 * 1302 * returns: 1303 * configuration node offset when found (>=0) 1304 * negative number on failure (FDT_ERR_* code) 1305 */ 1306 int fit_conf_get_node(const void *fit, const char *conf_uname) 1307 { 1308 int noffset, confs_noffset; 1309 int len; 1310 1311 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 1312 if (confs_noffset < 0) { 1313 debug("Can't find configurations parent node '%s' (%s)\n", 1314 FIT_CONFS_PATH, fdt_strerror(confs_noffset)); 1315 return confs_noffset; 1316 } 1317 1318 if (conf_uname == NULL) { 1319 /* get configuration unit name from the default property */ 1320 debug("No configuration specified, trying default...\n"); 1321 conf_uname = (char *)fdt_getprop(fit, confs_noffset, 1322 FIT_DEFAULT_PROP, &len); 1323 if (conf_uname == NULL) { 1324 fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP, 1325 len); 1326 return len; 1327 } 1328 debug("Found default configuration: '%s'\n", conf_uname); 1329 } 1330 1331 noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); 1332 if (noffset < 0) { 1333 debug("Can't get node offset for configuration unit name: '%s' (%s)\n", 1334 conf_uname, fdt_strerror(noffset)); 1335 } 1336 1337 return noffset; 1338 } 1339 1340 int fit_conf_get_prop_node(const void *fit, int noffset, 1341 const char *prop_name) 1342 { 1343 char *uname; 1344 int len; 1345 1346 /* get kernel image unit name from configuration kernel property */ 1347 uname = (char *)fdt_getprop(fit, noffset, prop_name, &len); 1348 if (uname == NULL) 1349 return len; 1350 1351 return fit_image_get_node(fit, uname); 1352 } 1353 1354 /** 1355 * fit_conf_get_kernel_node - get kernel image node offset that corresponds to 1356 * a given configuration 1357 * @fit: pointer to the FIT format image header 1358 * @noffset: configuration node offset 1359 * 1360 * fit_conf_get_kernel_node() retrives kernel image node unit name from 1361 * configuration FIT_KERNEL_PROP property and translates it to the node 1362 * offset. 1363 * 1364 * returns: 1365 * image node offset when found (>=0) 1366 * negative number on failure (FDT_ERR_* code) 1367 */ 1368 int fit_conf_get_kernel_node(const void *fit, int noffset) 1369 { 1370 return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP); 1371 } 1372 1373 /** 1374 * fit_conf_get_fdt_node - get fdt image node offset that corresponds to 1375 * a given configuration 1376 * @fit: pointer to the FIT format image header 1377 * @noffset: configuration node offset 1378 * 1379 * fit_conf_get_fdt_node() retrives fdt image node unit name from 1380 * configuration FIT_KERNEL_PROP property and translates it to the node 1381 * offset. 1382 * 1383 * returns: 1384 * image node offset when found (>=0) 1385 * negative number on failure (FDT_ERR_* code) 1386 */ 1387 int fit_conf_get_fdt_node(const void *fit, int noffset) 1388 { 1389 return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP); 1390 } 1391 1392 /** 1393 * fit_conf_print - prints out the FIT configuration details 1394 * @fit: pointer to the FIT format image header 1395 * @noffset: offset of the configuration node 1396 * @p: pointer to prefix string 1397 * 1398 * fit_conf_print() lists all mandatory properies for the processed 1399 * configuration node. 1400 * 1401 * returns: 1402 * no returned results 1403 */ 1404 void fit_conf_print(const void *fit, int noffset, const char *p) 1405 { 1406 char *desc; 1407 char *uname; 1408 int ret; 1409 1410 /* Mandatory properties */ 1411 ret = fit_get_desc(fit, noffset, &desc); 1412 printf("%s Description: ", p); 1413 if (ret) 1414 printf("unavailable\n"); 1415 else 1416 printf("%s\n", desc); 1417 1418 uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL); 1419 printf("%s Kernel: ", p); 1420 if (uname == NULL) 1421 printf("unavailable\n"); 1422 else 1423 printf("%s\n", uname); 1424 1425 /* Optional properties */ 1426 uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL); 1427 if (uname) 1428 printf("%s Init Ramdisk: %s\n", p, uname); 1429 1430 uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); 1431 if (uname) 1432 printf("%s FDT: %s\n", p, uname); 1433 } 1434 1435 int fit_image_select(const void *fit, int rd_noffset, int verify) 1436 { 1437 fit_image_print(fit, rd_noffset, " "); 1438 1439 if (verify) { 1440 puts(" Verifying Hash Integrity ... "); 1441 if (!fit_image_verify(fit, rd_noffset)) { 1442 puts("Bad Data Hash\n"); 1443 return -EACCES; 1444 } 1445 puts("OK\n"); 1446 } 1447 1448 return 0; 1449 } 1450 1451 int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, 1452 ulong addr) 1453 { 1454 int cfg_noffset; 1455 void *fit_hdr; 1456 int noffset; 1457 1458 debug("* %s: using config '%s' from image at 0x%08lx\n", 1459 prop_name, images->fit_uname_cfg, addr); 1460 1461 /* Check whether configuration has this property defined */ 1462 fit_hdr = map_sysmem(addr, 0); 1463 cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg); 1464 if (cfg_noffset < 0) { 1465 debug("* %s: no such config\n", prop_name); 1466 return -ENOENT; 1467 } 1468 1469 noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); 1470 if (noffset < 0) { 1471 debug("* %s: no '%s' in config\n", prop_name, prop_name); 1472 return -ENOLINK; 1473 } 1474 1475 return noffset; 1476 } 1477 1478 int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, 1479 const char **fit_unamep, const char *fit_uname_config, 1480 int arch, int image_type, int bootstage_id, 1481 enum fit_load_op load_op, ulong *datap, ulong *lenp) 1482 { 1483 int cfg_noffset, noffset; 1484 const char *fit_uname; 1485 const void *fit; 1486 const void *buf; 1487 size_t size; 1488 int type_ok, os_ok; 1489 ulong load, data, len; 1490 int ret; 1491 1492 fit = map_sysmem(addr, 0); 1493 fit_uname = fit_unamep ? *fit_unamep : NULL; 1494 printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); 1495 1496 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); 1497 if (!fit_check_format(fit)) { 1498 printf("Bad FIT %s image format!\n", prop_name); 1499 bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); 1500 return -ENOEXEC; 1501 } 1502 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); 1503 if (fit_uname) { 1504 /* get ramdisk component image node offset */ 1505 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); 1506 noffset = fit_image_get_node(fit, fit_uname); 1507 } else { 1508 /* 1509 * no image node unit name, try to get config 1510 * node first. If config unit node name is NULL 1511 * fit_conf_get_node() will try to find default config node 1512 */ 1513 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); 1514 if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { 1515 cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); 1516 } else { 1517 cfg_noffset = fit_conf_get_node(fit, 1518 fit_uname_config); 1519 } 1520 if (cfg_noffset < 0) { 1521 puts("Could not find configuration node\n"); 1522 bootstage_error(bootstage_id + 1523 BOOTSTAGE_SUB_NO_UNIT_NAME); 1524 return -ENOENT; 1525 } 1526 fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); 1527 printf(" Using '%s' configuration\n", fit_uname_config); 1528 if (image_type == IH_TYPE_KERNEL) { 1529 /* Remember (and possibly verify) this config */ 1530 images->fit_uname_cfg = fit_uname_config; 1531 if (IMAGE_ENABLE_VERIFY && images->verify) { 1532 puts(" Verifying Hash Integrity ... "); 1533 if (!fit_config_verify(fit, cfg_noffset)) { 1534 puts("Bad Data Hash\n"); 1535 bootstage_error(bootstage_id + 1536 BOOTSTAGE_SUB_HASH); 1537 return -EACCES; 1538 } 1539 puts("OK\n"); 1540 } 1541 bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); 1542 } 1543 1544 noffset = fit_conf_get_prop_node(fit, cfg_noffset, 1545 prop_name); 1546 fit_uname = fit_get_name(fit, noffset, NULL); 1547 } 1548 if (noffset < 0) { 1549 puts("Could not find subimage node\n"); 1550 bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); 1551 return -ENOENT; 1552 } 1553 1554 printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); 1555 1556 ret = fit_image_select(fit, noffset, images->verify); 1557 if (ret) { 1558 bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); 1559 return ret; 1560 } 1561 1562 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); 1563 if (!fit_image_check_target_arch(fit, noffset)) { 1564 puts("Unsupported Architecture\n"); 1565 bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); 1566 return -ENOEXEC; 1567 } 1568 1569 if (image_type == IH_TYPE_FLATDT && 1570 !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { 1571 puts("FDT image is compressed"); 1572 return -EPROTONOSUPPORT; 1573 } 1574 1575 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); 1576 type_ok = fit_image_check_type(fit, noffset, image_type) || 1577 (image_type == IH_TYPE_KERNEL && 1578 fit_image_check_type(fit, noffset, 1579 IH_TYPE_KERNEL_NOLOAD)); 1580 os_ok = image_type == IH_TYPE_FLATDT || 1581 fit_image_check_os(fit, noffset, IH_OS_LINUX); 1582 if (!type_ok || !os_ok) { 1583 printf("No Linux %s %s Image\n", genimg_get_arch_name(arch), 1584 genimg_get_type_name(image_type)); 1585 bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); 1586 return -EIO; 1587 } 1588 1589 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); 1590 1591 /* get image data address and length */ 1592 if (fit_image_get_data(fit, noffset, &buf, &size)) { 1593 printf("Could not find %s subimage data!\n", prop_name); 1594 bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); 1595 return -ENOMEDIUM; 1596 } 1597 len = (ulong)size; 1598 1599 /* verify that image data is a proper FDT blob */ 1600 if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) { 1601 puts("Subimage data is not a FDT"); 1602 return -ENOEXEC; 1603 } 1604 1605 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); 1606 1607 /* 1608 * Work-around for eldk-4.2 which gives this warning if we try to 1609 * case in the unmap_sysmem() call: 1610 * warning: initialization discards qualifiers from pointer target type 1611 */ 1612 { 1613 void *vbuf = (void *)buf; 1614 1615 data = map_to_sysmem(vbuf); 1616 } 1617 1618 if (load_op == FIT_LOAD_IGNORED) { 1619 /* Don't load */ 1620 } else if (fit_image_get_load(fit, noffset, &load)) { 1621 if (load_op == FIT_LOAD_REQUIRED) { 1622 printf("Can't get %s subimage load address!\n", 1623 prop_name); 1624 bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); 1625 return -EBADF; 1626 } 1627 } else { 1628 ulong image_start, image_end; 1629 ulong load_end; 1630 void *dst; 1631 1632 /* 1633 * move image data to the load address, 1634 * make sure we don't overwrite initial image 1635 */ 1636 image_start = addr; 1637 image_end = addr + fit_get_size(fit); 1638 1639 load_end = load + len; 1640 if (image_type != IH_TYPE_KERNEL && 1641 load < image_end && load_end > image_start) { 1642 printf("Error: %s overwritten\n", prop_name); 1643 return -EXDEV; 1644 } 1645 1646 printf(" Loading %s from 0x%08lx to 0x%08lx\n", 1647 prop_name, data, load); 1648 1649 dst = map_sysmem(load, len); 1650 memmove(dst, buf, len); 1651 data = load; 1652 } 1653 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); 1654 1655 *datap = data; 1656 *lenp = len; 1657 if (fit_unamep) 1658 *fit_unamep = (char *)fit_uname; 1659 1660 return noffset; 1661 } 1662