1 /* 2 * (C) Copyright 2008 Semihalf 3 * 4 * (C) Copyright 2000-2006 5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 #ifndef USE_HOSTCC 27 #include <common.h> 28 #include <watchdog.h> 29 30 #ifdef CONFIG_SHOW_BOOT_PROGRESS 31 #include <status_led.h> 32 #endif 33 34 #ifdef CONFIG_HAS_DATAFLASH 35 #include <dataflash.h> 36 #endif 37 38 #ifdef CONFIG_LOGBUFFER 39 #include <logbuff.h> 40 #endif 41 42 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 43 #include <rtc.h> 44 #endif 45 46 #include <image.h> 47 48 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 49 #include <fdt.h> 50 #include <libfdt.h> 51 #include <fdt_support.h> 52 #endif 53 54 #if defined(CONFIG_FIT) 55 #include <u-boot/md5.h> 56 #include <sha1.h> 57 58 static int fit_check_ramdisk(const void *fit, int os_noffset, 59 uint8_t arch, int verify); 60 #endif 61 62 #ifdef CONFIG_CMD_BDI 63 extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); 64 #endif 65 66 DECLARE_GLOBAL_DATA_PTR; 67 68 static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, 69 int verify); 70 #else 71 #include "mkimage.h" 72 #include <u-boot/md5.h> 73 #include <time.h> 74 #include <image.h> 75 #endif /* !USE_HOSTCC*/ 76 77 static const table_entry_t uimage_arch[] = { 78 { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, 79 { IH_ARCH_ALPHA, "alpha", "Alpha", }, 80 { IH_ARCH_ARM, "arm", "ARM", }, 81 { IH_ARCH_I386, "x86", "Intel x86", }, 82 { IH_ARCH_IA64, "ia64", "IA64", }, 83 { IH_ARCH_M68K, "m68k", "M68K", }, 84 { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, 85 { IH_ARCH_MIPS, "mips", "MIPS", }, 86 { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, 87 { IH_ARCH_NIOS2, "nios2", "NIOS II", }, 88 { IH_ARCH_PPC, "powerpc", "PowerPC", }, 89 { IH_ARCH_PPC, "ppc", "PowerPC", }, 90 { IH_ARCH_S390, "s390", "IBM S390", }, 91 { IH_ARCH_SH, "sh", "SuperH", }, 92 { IH_ARCH_SPARC, "sparc", "SPARC", }, 93 { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, 94 { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, 95 { IH_ARCH_AVR32, "avr32", "AVR32", }, 96 { IH_ARCH_NDS32, "nds32", "NDS32", }, 97 { -1, "", "", }, 98 }; 99 100 static const table_entry_t uimage_os[] = { 101 { IH_OS_INVALID, NULL, "Invalid OS", }, 102 { IH_OS_LINUX, "linux", "Linux", }, 103 #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) 104 { IH_OS_LYNXOS, "lynxos", "LynxOS", }, 105 #endif 106 { IH_OS_NETBSD, "netbsd", "NetBSD", }, 107 { IH_OS_OSE, "ose", "Enea OSE", }, 108 { IH_OS_RTEMS, "rtems", "RTEMS", }, 109 { IH_OS_U_BOOT, "u-boot", "U-Boot", }, 110 #if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) 111 { IH_OS_QNX, "qnx", "QNX", }, 112 { IH_OS_VXWORKS, "vxworks", "VxWorks", }, 113 #endif 114 #if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC) 115 { IH_OS_INTEGRITY,"integrity", "INTEGRITY", }, 116 #endif 117 #ifdef USE_HOSTCC 118 { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, 119 { IH_OS_DELL, "dell", "Dell", }, 120 { IH_OS_ESIX, "esix", "Esix", }, 121 { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, 122 { IH_OS_IRIX, "irix", "Irix", }, 123 { IH_OS_NCR, "ncr", "NCR", }, 124 { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, 125 { IH_OS_PSOS, "psos", "pSOS", }, 126 { IH_OS_SCO, "sco", "SCO", }, 127 { IH_OS_SOLARIS, "solaris", "Solaris", }, 128 { IH_OS_SVR4, "svr4", "SVR4", }, 129 #endif 130 { -1, "", "", }, 131 }; 132 133 static const table_entry_t uimage_type[] = { 134 { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, 135 { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, 136 { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, 137 { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, 138 { IH_TYPE_MULTI, "multi", "Multi-File Image", }, 139 { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, 140 { IH_TYPE_SCRIPT, "script", "Script", }, 141 { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, 142 { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, 143 { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, 144 { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, 145 { IH_TYPE_UBLIMAGE, "ublimage", "Davinci UBL image",}, 146 { IH_TYPE_INVALID, NULL, "Invalid Image", }, 147 { -1, "", "", }, 148 }; 149 150 static const table_entry_t uimage_comp[] = { 151 { IH_COMP_NONE, "none", "uncompressed", }, 152 { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, 153 { IH_COMP_GZIP, "gzip", "gzip compressed", }, 154 { IH_COMP_LZMA, "lzma", "lzma compressed", }, 155 { IH_COMP_LZO, "lzo", "lzo compressed", }, 156 { -1, "", "", }, 157 }; 158 159 uint32_t crc32(uint32_t, const unsigned char *, uint); 160 uint32_t crc32_wd(uint32_t, const unsigned char *, uint, uint); 161 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) 162 static void genimg_print_time(time_t timestamp); 163 #endif 164 165 /*****************************************************************************/ 166 /* Legacy format routines */ 167 /*****************************************************************************/ 168 int image_check_hcrc(const image_header_t *hdr) 169 { 170 ulong hcrc; 171 ulong len = image_get_header_size(); 172 image_header_t header; 173 174 /* Copy header so we can blank CRC field for re-calculation */ 175 memmove(&header, (char *)hdr, image_get_header_size()); 176 image_set_hcrc(&header, 0); 177 178 hcrc = crc32(0, (unsigned char *)&header, len); 179 180 return (hcrc == image_get_hcrc(hdr)); 181 } 182 183 int image_check_dcrc(const image_header_t *hdr) 184 { 185 ulong data = image_get_data(hdr); 186 ulong len = image_get_data_size(hdr); 187 ulong dcrc = crc32_wd(0, (unsigned char *)data, len, CHUNKSZ_CRC32); 188 189 return (dcrc == image_get_dcrc(hdr)); 190 } 191 192 /** 193 * image_multi_count - get component (sub-image) count 194 * @hdr: pointer to the header of the multi component image 195 * 196 * image_multi_count() returns number of components in a multi 197 * component image. 198 * 199 * Note: no checking of the image type is done, caller must pass 200 * a valid multi component image. 201 * 202 * returns: 203 * number of components 204 */ 205 ulong image_multi_count(const image_header_t *hdr) 206 { 207 ulong i, count = 0; 208 uint32_t *size; 209 210 /* get start of the image payload, which in case of multi 211 * component images that points to a table of component sizes */ 212 size = (uint32_t *)image_get_data(hdr); 213 214 /* count non empty slots */ 215 for (i = 0; size[i]; ++i) 216 count++; 217 218 return count; 219 } 220 221 /** 222 * image_multi_getimg - get component data address and size 223 * @hdr: pointer to the header of the multi component image 224 * @idx: index of the requested component 225 * @data: pointer to a ulong variable, will hold component data address 226 * @len: pointer to a ulong variable, will hold component size 227 * 228 * image_multi_getimg() returns size and data address for the requested 229 * component in a multi component image. 230 * 231 * Note: no checking of the image type is done, caller must pass 232 * a valid multi component image. 233 * 234 * returns: 235 * data address and size of the component, if idx is valid 236 * 0 in data and len, if idx is out of range 237 */ 238 void image_multi_getimg(const image_header_t *hdr, ulong idx, 239 ulong *data, ulong *len) 240 { 241 int i; 242 uint32_t *size; 243 ulong offset, count, img_data; 244 245 /* get number of component */ 246 count = image_multi_count(hdr); 247 248 /* get start of the image payload, which in case of multi 249 * component images that points to a table of component sizes */ 250 size = (uint32_t *)image_get_data(hdr); 251 252 /* get address of the proper component data start, which means 253 * skipping sizes table (add 1 for last, null entry) */ 254 img_data = image_get_data(hdr) + (count + 1) * sizeof(uint32_t); 255 256 if (idx < count) { 257 *len = uimage_to_cpu(size[idx]); 258 offset = 0; 259 260 /* go over all indices preceding requested component idx */ 261 for (i = 0; i < idx; i++) { 262 /* add up i-th component size, rounding up to 4 bytes */ 263 offset += (uimage_to_cpu(size[i]) + 3) & ~3 ; 264 } 265 266 /* calculate idx-th component data address */ 267 *data = img_data + offset; 268 } else { 269 *len = 0; 270 *data = 0; 271 } 272 } 273 274 static void image_print_type(const image_header_t *hdr) 275 { 276 const char *os, *arch, *type, *comp; 277 278 os = genimg_get_os_name(image_get_os(hdr)); 279 arch = genimg_get_arch_name(image_get_arch(hdr)); 280 type = genimg_get_type_name(image_get_type(hdr)); 281 comp = genimg_get_comp_name(image_get_comp(hdr)); 282 283 printf("%s %s %s (%s)\n", arch, os, type, comp); 284 } 285 286 /** 287 * image_print_contents - prints out the contents of the legacy format image 288 * @ptr: pointer to the legacy format image header 289 * @p: pointer to prefix string 290 * 291 * image_print_contents() formats a multi line legacy image contents description. 292 * The routine prints out all header fields followed by the size/offset data 293 * for MULTI/SCRIPT images. 294 * 295 * returns: 296 * no returned results 297 */ 298 void image_print_contents(const void *ptr) 299 { 300 const image_header_t *hdr = (const image_header_t *)ptr; 301 const char *p; 302 303 #ifdef USE_HOSTCC 304 p = ""; 305 #else 306 p = " "; 307 #endif 308 309 printf("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name(hdr)); 310 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) 311 printf("%sCreated: ", p); 312 genimg_print_time((time_t)image_get_time(hdr)); 313 #endif 314 printf("%sImage Type: ", p); 315 image_print_type(hdr); 316 printf("%sData Size: ", p); 317 genimg_print_size(image_get_data_size(hdr)); 318 printf("%sLoad Address: %08x\n", p, image_get_load(hdr)); 319 printf("%sEntry Point: %08x\n", p, image_get_ep(hdr)); 320 321 if (image_check_type(hdr, IH_TYPE_MULTI) || 322 image_check_type(hdr, IH_TYPE_SCRIPT)) { 323 int i; 324 ulong data, len; 325 ulong count = image_multi_count(hdr); 326 327 printf("%sContents:\n", p); 328 for (i = 0; i < count; i++) { 329 image_multi_getimg(hdr, i, &data, &len); 330 331 printf("%s Image %d: ", p, i); 332 genimg_print_size(len); 333 334 if (image_check_type(hdr, IH_TYPE_SCRIPT) && i > 0) { 335 /* 336 * the user may need to know offsets 337 * if planning to do something with 338 * multiple files 339 */ 340 printf("%s Offset = 0x%08lx\n", p, data); 341 } 342 } 343 } 344 } 345 346 347 #ifndef USE_HOSTCC 348 /** 349 * image_get_ramdisk - get and verify ramdisk image 350 * @rd_addr: ramdisk image start address 351 * @arch: expected ramdisk architecture 352 * @verify: checksum verification flag 353 * 354 * image_get_ramdisk() returns a pointer to the verified ramdisk image 355 * header. Routine receives image start address and expected architecture 356 * flag. Verification done covers data and header integrity and os/type/arch 357 * fields checking. 358 * 359 * If dataflash support is enabled routine checks for dataflash addresses 360 * and handles required dataflash reads. 361 * 362 * returns: 363 * pointer to a ramdisk image header, if image was found and valid 364 * otherwise, return NULL 365 */ 366 static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, 367 int verify) 368 { 369 const image_header_t *rd_hdr = (const image_header_t *)rd_addr; 370 371 if (!image_check_magic(rd_hdr)) { 372 puts("Bad Magic Number\n"); 373 show_boot_progress(-10); 374 return NULL; 375 } 376 377 if (!image_check_hcrc(rd_hdr)) { 378 puts("Bad Header Checksum\n"); 379 show_boot_progress(-11); 380 return NULL; 381 } 382 383 show_boot_progress(10); 384 image_print_contents(rd_hdr); 385 386 if (verify) { 387 puts(" Verifying Checksum ... "); 388 if (!image_check_dcrc(rd_hdr)) { 389 puts("Bad Data CRC\n"); 390 show_boot_progress(-12); 391 return NULL; 392 } 393 puts("OK\n"); 394 } 395 396 show_boot_progress(11); 397 398 if (!image_check_os(rd_hdr, IH_OS_LINUX) || 399 !image_check_arch(rd_hdr, arch) || 400 !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) { 401 printf("No Linux %s Ramdisk Image\n", 402 genimg_get_arch_name(arch)); 403 show_boot_progress(-13); 404 return NULL; 405 } 406 407 return rd_hdr; 408 } 409 #endif /* !USE_HOSTCC */ 410 411 /*****************************************************************************/ 412 /* Shared dual-format routines */ 413 /*****************************************************************************/ 414 #ifndef USE_HOSTCC 415 int getenv_yesno(char *var) 416 { 417 char *s = getenv(var); 418 return (s && (*s == 'n')) ? 0 : 1; 419 } 420 421 ulong getenv_bootm_low(void) 422 { 423 char *s = getenv("bootm_low"); 424 if (s) { 425 ulong tmp = simple_strtoul(s, NULL, 16); 426 return tmp; 427 } 428 429 #if defined(CONFIG_SYS_SDRAM_BASE) 430 return CONFIG_SYS_SDRAM_BASE; 431 #elif defined(CONFIG_ARM) 432 return gd->bd->bi_dram[0].start; 433 #else 434 return 0; 435 #endif 436 } 437 438 phys_size_t getenv_bootm_size(void) 439 { 440 phys_size_t tmp; 441 char *s = getenv("bootm_size"); 442 if (s) { 443 tmp = (phys_size_t)simple_strtoull(s, NULL, 16); 444 return tmp; 445 } 446 s = getenv("bootm_low"); 447 if (s) 448 tmp = (phys_size_t)simple_strtoull(s, NULL, 16); 449 else 450 tmp = 0; 451 452 453 #if defined(CONFIG_ARM) 454 return gd->bd->bi_dram[0].size - tmp; 455 #else 456 return gd->bd->bi_memsize - tmp; 457 #endif 458 } 459 460 phys_size_t getenv_bootm_mapsize(void) 461 { 462 phys_size_t tmp; 463 char *s = getenv("bootm_mapsize"); 464 if (s) { 465 tmp = (phys_size_t)simple_strtoull(s, NULL, 16); 466 return tmp; 467 } 468 469 #if defined(CONFIG_SYS_BOOTMAPSZ) 470 return CONFIG_SYS_BOOTMAPSZ; 471 #else 472 return getenv_bootm_size(); 473 #endif 474 } 475 476 void memmove_wd(void *to, void *from, size_t len, ulong chunksz) 477 { 478 if (to == from) 479 return; 480 481 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 482 while (len > 0) { 483 size_t tail = (len > chunksz) ? chunksz : len; 484 WATCHDOG_RESET(); 485 memmove(to, from, tail); 486 to += tail; 487 from += tail; 488 len -= tail; 489 } 490 #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ 491 memmove(to, from, len); 492 #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ 493 } 494 #endif /* !USE_HOSTCC */ 495 496 void genimg_print_size(uint32_t size) 497 { 498 #ifndef USE_HOSTCC 499 printf("%d Bytes = ", size); 500 print_size(size, "\n"); 501 #else 502 printf("%d Bytes = %.2f kB = %.2f MB\n", 503 size, (double)size / 1.024e3, 504 (double)size / 1.048576e6); 505 #endif 506 } 507 508 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) 509 static void genimg_print_time(time_t timestamp) 510 { 511 #ifndef USE_HOSTCC 512 struct rtc_time tm; 513 514 to_tm(timestamp, &tm); 515 printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", 516 tm.tm_year, tm.tm_mon, tm.tm_mday, 517 tm.tm_hour, tm.tm_min, tm.tm_sec); 518 #else 519 printf("%s", ctime(×tamp)); 520 #endif 521 } 522 #endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */ 523 524 /** 525 * get_table_entry_name - translate entry id to long name 526 * @table: pointer to a translation table for entries of a specific type 527 * @msg: message to be returned when translation fails 528 * @id: entry id to be translated 529 * 530 * get_table_entry_name() will go over translation table trying to find 531 * entry that matches given id. If matching entry is found, its long 532 * name is returned to the caller. 533 * 534 * returns: 535 * long entry name if translation succeeds 536 * msg otherwise 537 */ 538 char *get_table_entry_name(const table_entry_t *table, char *msg, int id) 539 { 540 for (; table->id >= 0; ++table) { 541 if (table->id == id) 542 #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) 543 return table->lname; 544 #else 545 return table->lname + gd->reloc_off; 546 #endif 547 } 548 return (msg); 549 } 550 551 const char *genimg_get_os_name(uint8_t os) 552 { 553 return (get_table_entry_name(uimage_os, "Unknown OS", os)); 554 } 555 556 const char *genimg_get_arch_name(uint8_t arch) 557 { 558 return (get_table_entry_name(uimage_arch, "Unknown Architecture", 559 arch)); 560 } 561 562 const char *genimg_get_type_name(uint8_t type) 563 { 564 return (get_table_entry_name(uimage_type, "Unknown Image", type)); 565 } 566 567 const char *genimg_get_comp_name(uint8_t comp) 568 { 569 return (get_table_entry_name(uimage_comp, "Unknown Compression", 570 comp)); 571 } 572 573 /** 574 * get_table_entry_id - translate short entry name to id 575 * @table: pointer to a translation table for entries of a specific type 576 * @table_name: to be used in case of error 577 * @name: entry short name to be translated 578 * 579 * get_table_entry_id() will go over translation table trying to find 580 * entry that matches given short name. If matching entry is found, 581 * its id returned to the caller. 582 * 583 * returns: 584 * entry id if translation succeeds 585 * -1 otherwise 586 */ 587 int get_table_entry_id(const table_entry_t *table, 588 const char *table_name, const char *name) 589 { 590 const table_entry_t *t; 591 #ifdef USE_HOSTCC 592 int first = 1; 593 594 for (t = table; t->id >= 0; ++t) { 595 if (t->sname && strcasecmp(t->sname, name) == 0) 596 return(t->id); 597 } 598 599 fprintf(stderr, "\nInvalid %s Type - valid names are", table_name); 600 for (t = table; t->id >= 0; ++t) { 601 if (t->sname == NULL) 602 continue; 603 fprintf(stderr, "%c %s", (first) ? ':' : ',', t->sname); 604 first = 0; 605 } 606 fprintf(stderr, "\n"); 607 #else 608 for (t = table; t->id >= 0; ++t) { 609 #ifdef CONFIG_NEEDS_MANUAL_RELOC 610 if (t->sname && strcmp(t->sname + gd->reloc_off, name) == 0) 611 #else 612 if (t->sname && strcmp(t->sname, name) == 0) 613 #endif 614 return (t->id); 615 } 616 debug("Invalid %s Type: %s\n", table_name, name); 617 #endif /* USE_HOSTCC */ 618 return (-1); 619 } 620 621 int genimg_get_os_id(const char *name) 622 { 623 return (get_table_entry_id(uimage_os, "OS", name)); 624 } 625 626 int genimg_get_arch_id(const char *name) 627 { 628 return (get_table_entry_id(uimage_arch, "CPU", name)); 629 } 630 631 int genimg_get_type_id(const char *name) 632 { 633 return (get_table_entry_id(uimage_type, "Image", name)); 634 } 635 636 int genimg_get_comp_id(const char *name) 637 { 638 return (get_table_entry_id(uimage_comp, "Compression", name)); 639 } 640 641 #ifndef USE_HOSTCC 642 /** 643 * genimg_get_format - get image format type 644 * @img_addr: image start address 645 * 646 * genimg_get_format() checks whether provided address points to a valid 647 * legacy or FIT image. 648 * 649 * New uImage format and FDT blob are based on a libfdt. FDT blob 650 * may be passed directly or embedded in a FIT image. In both situations 651 * genimg_get_format() must be able to dectect libfdt header. 652 * 653 * returns: 654 * image format type or IMAGE_FORMAT_INVALID if no image is present 655 */ 656 int genimg_get_format(void *img_addr) 657 { 658 ulong format = IMAGE_FORMAT_INVALID; 659 const image_header_t *hdr; 660 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 661 char *fit_hdr; 662 #endif 663 664 hdr = (const image_header_t *)img_addr; 665 if (image_check_magic(hdr)) 666 format = IMAGE_FORMAT_LEGACY; 667 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 668 else { 669 fit_hdr = (char *)img_addr; 670 if (fdt_check_header(fit_hdr) == 0) 671 format = IMAGE_FORMAT_FIT; 672 } 673 #endif 674 675 return format; 676 } 677 678 /** 679 * genimg_get_image - get image from special storage (if necessary) 680 * @img_addr: image start address 681 * 682 * genimg_get_image() checks if provided image start adddress is located 683 * in a dataflash storage. If so, image is moved to a system RAM memory. 684 * 685 * returns: 686 * image start address after possible relocation from special storage 687 */ 688 ulong genimg_get_image(ulong img_addr) 689 { 690 ulong ram_addr = img_addr; 691 692 #ifdef CONFIG_HAS_DATAFLASH 693 ulong h_size, d_size; 694 695 if (addr_dataflash(img_addr)) { 696 /* ger RAM address */ 697 ram_addr = CONFIG_SYS_LOAD_ADDR; 698 699 /* get header size */ 700 h_size = image_get_header_size(); 701 #if defined(CONFIG_FIT) 702 if (sizeof(struct fdt_header) > h_size) 703 h_size = sizeof(struct fdt_header); 704 #endif 705 706 /* read in header */ 707 debug(" Reading image header from dataflash address " 708 "%08lx to RAM address %08lx\n", img_addr, ram_addr); 709 710 read_dataflash(img_addr, h_size, (char *)ram_addr); 711 712 /* get data size */ 713 switch (genimg_get_format((void *)ram_addr)) { 714 case IMAGE_FORMAT_LEGACY: 715 d_size = image_get_data_size( 716 (const image_header_t *)ram_addr); 717 debug(" Legacy format image found at 0x%08lx, " 718 "size 0x%08lx\n", 719 ram_addr, d_size); 720 break; 721 #if defined(CONFIG_FIT) 722 case IMAGE_FORMAT_FIT: 723 d_size = fit_get_size((const void *)ram_addr) - h_size; 724 debug(" FIT/FDT format image found at 0x%08lx, " 725 "size 0x%08lx\n", 726 ram_addr, d_size); 727 break; 728 #endif 729 default: 730 printf(" No valid image found at 0x%08lx\n", 731 img_addr); 732 return ram_addr; 733 } 734 735 /* read in image data */ 736 debug(" Reading image remaining data from dataflash address " 737 "%08lx to RAM address %08lx\n", img_addr + h_size, 738 ram_addr + h_size); 739 740 read_dataflash(img_addr + h_size, d_size, 741 (char *)(ram_addr + h_size)); 742 743 } 744 #endif /* CONFIG_HAS_DATAFLASH */ 745 746 return ram_addr; 747 } 748 749 /** 750 * fit_has_config - check if there is a valid FIT configuration 751 * @images: pointer to the bootm command headers structure 752 * 753 * fit_has_config() checks if there is a FIT configuration in use 754 * (if FTI support is present). 755 * 756 * returns: 757 * 0, no FIT support or no configuration found 758 * 1, configuration found 759 */ 760 int genimg_has_config(bootm_headers_t *images) 761 { 762 #if defined(CONFIG_FIT) 763 if (images->fit_uname_cfg) 764 return 1; 765 #endif 766 return 0; 767 } 768 769 /** 770 * boot_get_ramdisk - main ramdisk handling routine 771 * @argc: command argument count 772 * @argv: command argument list 773 * @images: pointer to the bootm images structure 774 * @arch: expected ramdisk architecture 775 * @rd_start: pointer to a ulong variable, will hold ramdisk start address 776 * @rd_end: pointer to a ulong variable, will hold ramdisk end 777 * 778 * boot_get_ramdisk() is responsible for finding a valid ramdisk image. 779 * Curently supported are the following ramdisk sources: 780 * - multicomponent kernel/ramdisk image, 781 * - commandline provided address of decicated ramdisk image. 782 * 783 * returns: 784 * 0, if ramdisk image was found and valid, or skiped 785 * rd_start and rd_end are set to ramdisk start/end addresses if 786 * ramdisk image is found and valid 787 * 788 * 1, if ramdisk image is found but corrupted, or invalid 789 * rd_start and rd_end are set to 0 if no ramdisk exists 790 */ 791 int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, 792 uint8_t arch, ulong *rd_start, ulong *rd_end) 793 { 794 ulong rd_addr, rd_load; 795 ulong rd_data, rd_len; 796 const image_header_t *rd_hdr; 797 #if defined(CONFIG_FIT) 798 void *fit_hdr; 799 const char *fit_uname_config = NULL; 800 const char *fit_uname_ramdisk = NULL; 801 ulong default_addr; 802 int rd_noffset; 803 int cfg_noffset; 804 const void *data; 805 size_t size; 806 #endif 807 808 *rd_start = 0; 809 *rd_end = 0; 810 811 /* 812 * Look for a '-' which indicates to ignore the 813 * ramdisk argument 814 */ 815 if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) { 816 debug("## Skipping init Ramdisk\n"); 817 rd_len = rd_data = 0; 818 } else if (argc >= 3 || genimg_has_config(images)) { 819 #if defined(CONFIG_FIT) 820 if (argc >= 3) { 821 /* 822 * If the init ramdisk comes from the FIT image and 823 * the FIT image address is omitted in the command 824 * line argument, try to use os FIT image address or 825 * default load address. 826 */ 827 if (images->fit_uname_os) 828 default_addr = (ulong)images->fit_hdr_os; 829 else 830 default_addr = load_addr; 831 832 if (fit_parse_conf(argv[2], default_addr, 833 &rd_addr, &fit_uname_config)) { 834 debug("* ramdisk: config '%s' from image at " 835 "0x%08lx\n", 836 fit_uname_config, rd_addr); 837 } else if (fit_parse_subimage(argv[2], default_addr, 838 &rd_addr, &fit_uname_ramdisk)) { 839 debug("* ramdisk: subimage '%s' from image at " 840 "0x%08lx\n", 841 fit_uname_ramdisk, rd_addr); 842 } else 843 #endif 844 { 845 rd_addr = simple_strtoul(argv[2], NULL, 16); 846 debug("* ramdisk: cmdline image address = " 847 "0x%08lx\n", 848 rd_addr); 849 } 850 #if defined(CONFIG_FIT) 851 } else { 852 /* use FIT configuration provided in first bootm 853 * command argument 854 */ 855 rd_addr = (ulong)images->fit_hdr_os; 856 fit_uname_config = images->fit_uname_cfg; 857 debug("* ramdisk: using config '%s' from image " 858 "at 0x%08lx\n", 859 fit_uname_config, rd_addr); 860 861 /* 862 * Check whether configuration has ramdisk defined, 863 * if not, don't try to use it, quit silently. 864 */ 865 fit_hdr = (void *)rd_addr; 866 cfg_noffset = fit_conf_get_node(fit_hdr, 867 fit_uname_config); 868 if (cfg_noffset < 0) { 869 debug("* ramdisk: no such config\n"); 870 return 1; 871 } 872 873 rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, 874 cfg_noffset); 875 if (rd_noffset < 0) { 876 debug("* ramdisk: no ramdisk in config\n"); 877 return 0; 878 } 879 } 880 #endif 881 882 /* copy from dataflash if needed */ 883 rd_addr = genimg_get_image(rd_addr); 884 885 /* 886 * Check if there is an initrd image at the 887 * address provided in the second bootm argument 888 * check image type, for FIT images get FIT node. 889 */ 890 switch (genimg_get_format((void *)rd_addr)) { 891 case IMAGE_FORMAT_LEGACY: 892 printf("## Loading init Ramdisk from Legacy " 893 "Image at %08lx ...\n", rd_addr); 894 895 show_boot_progress(9); 896 rd_hdr = image_get_ramdisk(rd_addr, arch, 897 images->verify); 898 899 if (rd_hdr == NULL) 900 return 1; 901 902 rd_data = image_get_data(rd_hdr); 903 rd_len = image_get_data_size(rd_hdr); 904 rd_load = image_get_load(rd_hdr); 905 break; 906 #if defined(CONFIG_FIT) 907 case IMAGE_FORMAT_FIT: 908 fit_hdr = (void *)rd_addr; 909 printf("## Loading init Ramdisk from FIT " 910 "Image at %08lx ...\n", rd_addr); 911 912 show_boot_progress(120); 913 if (!fit_check_format(fit_hdr)) { 914 puts("Bad FIT ramdisk image format!\n"); 915 show_boot_progress(-120); 916 return 1; 917 } 918 show_boot_progress(121); 919 920 if (!fit_uname_ramdisk) { 921 /* 922 * no ramdisk image node unit name, try to get config 923 * node first. If config unit node name is NULL 924 * fit_conf_get_node() will try to find default config node 925 */ 926 show_boot_progress(122); 927 cfg_noffset = fit_conf_get_node(fit_hdr, 928 fit_uname_config); 929 if (cfg_noffset < 0) { 930 puts("Could not find configuration " 931 "node\n"); 932 show_boot_progress(-122); 933 return 1; 934 } 935 fit_uname_config = fdt_get_name(fit_hdr, 936 cfg_noffset, NULL); 937 printf(" Using '%s' configuration\n", 938 fit_uname_config); 939 940 rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, 941 cfg_noffset); 942 fit_uname_ramdisk = fit_get_name(fit_hdr, 943 rd_noffset, NULL); 944 } else { 945 /* get ramdisk component image node offset */ 946 show_boot_progress(123); 947 rd_noffset = fit_image_get_node(fit_hdr, 948 fit_uname_ramdisk); 949 } 950 if (rd_noffset < 0) { 951 puts("Could not find subimage node\n"); 952 show_boot_progress(-124); 953 return 1; 954 } 955 956 printf(" Trying '%s' ramdisk subimage\n", 957 fit_uname_ramdisk); 958 959 show_boot_progress(125); 960 if (!fit_check_ramdisk(fit_hdr, rd_noffset, arch, 961 images->verify)) 962 return 1; 963 964 /* get ramdisk image data address and length */ 965 if (fit_image_get_data(fit_hdr, rd_noffset, &data, 966 &size)) { 967 puts("Could not find ramdisk subimage data!\n"); 968 show_boot_progress(-127); 969 return 1; 970 } 971 show_boot_progress(128); 972 973 rd_data = (ulong)data; 974 rd_len = size; 975 976 if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) { 977 puts("Can't get ramdisk subimage load " 978 "address!\n"); 979 show_boot_progress(-129); 980 return 1; 981 } 982 show_boot_progress(129); 983 984 images->fit_hdr_rd = fit_hdr; 985 images->fit_uname_rd = fit_uname_ramdisk; 986 images->fit_noffset_rd = rd_noffset; 987 break; 988 #endif 989 default: 990 puts("Wrong Ramdisk Image Format\n"); 991 rd_data = rd_len = rd_load = 0; 992 return 1; 993 } 994 } else if (images->legacy_hdr_valid && 995 image_check_type(&images->legacy_hdr_os_copy, 996 IH_TYPE_MULTI)) { 997 998 /* 999 * Now check if we have a legacy mult-component image, 1000 * get second entry data start address and len. 1001 */ 1002 show_boot_progress(13); 1003 printf("## Loading init Ramdisk from multi component " 1004 "Legacy Image at %08lx ...\n", 1005 (ulong)images->legacy_hdr_os); 1006 1007 image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len); 1008 } else { 1009 /* 1010 * no initrd image 1011 */ 1012 show_boot_progress(14); 1013 rd_len = rd_data = 0; 1014 } 1015 1016 if (!rd_data) { 1017 debug("## No init Ramdisk\n"); 1018 } else { 1019 *rd_start = rd_data; 1020 *rd_end = rd_data + rd_len; 1021 } 1022 debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", 1023 *rd_start, *rd_end); 1024 1025 return 0; 1026 } 1027 1028 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH 1029 /** 1030 * boot_ramdisk_high - relocate init ramdisk 1031 * @lmb: pointer to lmb handle, will be used for memory mgmt 1032 * @rd_data: ramdisk data start address 1033 * @rd_len: ramdisk data length 1034 * @initrd_start: pointer to a ulong variable, will hold final init ramdisk 1035 * start address (after possible relocation) 1036 * @initrd_end: pointer to a ulong variable, will hold final init ramdisk 1037 * end address (after possible relocation) 1038 * 1039 * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement 1040 * variable and if requested ramdisk data is moved to a specified location. 1041 * 1042 * Initrd_start and initrd_end are set to final (after relocation) ramdisk 1043 * start/end addresses if ramdisk image start and len were provided, 1044 * otherwise set initrd_start and initrd_end set to zeros. 1045 * 1046 * returns: 1047 * 0 - success 1048 * -1 - failure 1049 */ 1050 int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, 1051 ulong *initrd_start, ulong *initrd_end) 1052 { 1053 char *s; 1054 ulong initrd_high; 1055 int initrd_copy_to_ram = 1; 1056 1057 if ((s = getenv("initrd_high")) != NULL) { 1058 /* a value of "no" or a similar string will act like 0, 1059 * turning the "load high" feature off. This is intentional. 1060 */ 1061 initrd_high = simple_strtoul(s, NULL, 16); 1062 if (initrd_high == ~0) 1063 initrd_copy_to_ram = 0; 1064 } else { 1065 /* not set, no restrictions to load high */ 1066 initrd_high = ~0; 1067 } 1068 1069 1070 #ifdef CONFIG_LOGBUFFER 1071 /* Prevent initrd from overwriting logbuffer */ 1072 lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE); 1073 #endif 1074 1075 debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", 1076 initrd_high, initrd_copy_to_ram); 1077 1078 if (rd_data) { 1079 if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ 1080 debug(" in-place initrd\n"); 1081 *initrd_start = rd_data; 1082 *initrd_end = rd_data + rd_len; 1083 lmb_reserve(lmb, rd_data, rd_len); 1084 } else { 1085 if (initrd_high) 1086 *initrd_start = (ulong)lmb_alloc_base(lmb, 1087 rd_len, 0x1000, initrd_high); 1088 else 1089 *initrd_start = (ulong)lmb_alloc(lmb, rd_len, 1090 0x1000); 1091 1092 if (*initrd_start == 0) { 1093 puts("ramdisk - allocation error\n"); 1094 goto error; 1095 } 1096 show_boot_progress(12); 1097 1098 *initrd_end = *initrd_start + rd_len; 1099 printf(" Loading Ramdisk to %08lx, end %08lx ... ", 1100 *initrd_start, *initrd_end); 1101 1102 memmove_wd((void *)*initrd_start, 1103 (void *)rd_data, rd_len, CHUNKSZ); 1104 1105 puts("OK\n"); 1106 } 1107 } else { 1108 *initrd_start = 0; 1109 *initrd_end = 0; 1110 } 1111 debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", 1112 *initrd_start, *initrd_end); 1113 1114 return 0; 1115 1116 error: 1117 return -1; 1118 } 1119 #endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */ 1120 1121 #ifdef CONFIG_OF_LIBFDT 1122 static void fdt_error(const char *msg) 1123 { 1124 puts("ERROR: "); 1125 puts(msg); 1126 puts(" - must RESET the board to recover.\n"); 1127 } 1128 1129 static const image_header_t *image_get_fdt(ulong fdt_addr) 1130 { 1131 const image_header_t *fdt_hdr = (const image_header_t *)fdt_addr; 1132 1133 image_print_contents(fdt_hdr); 1134 1135 puts(" Verifying Checksum ... "); 1136 if (!image_check_hcrc(fdt_hdr)) { 1137 fdt_error("fdt header checksum invalid"); 1138 return NULL; 1139 } 1140 1141 if (!image_check_dcrc(fdt_hdr)) { 1142 fdt_error("fdt checksum invalid"); 1143 return NULL; 1144 } 1145 puts("OK\n"); 1146 1147 if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)) { 1148 fdt_error("uImage is not a fdt"); 1149 return NULL; 1150 } 1151 if (image_get_comp(fdt_hdr) != IH_COMP_NONE) { 1152 fdt_error("uImage is compressed"); 1153 return NULL; 1154 } 1155 if (fdt_check_header((char *)image_get_data(fdt_hdr)) != 0) { 1156 fdt_error("uImage data is not a fdt"); 1157 return NULL; 1158 } 1159 return fdt_hdr; 1160 } 1161 1162 /** 1163 * fit_check_fdt - verify FIT format FDT subimage 1164 * @fit_hdr: pointer to the FIT header 1165 * fdt_noffset: FDT subimage node offset within FIT image 1166 * @verify: data CRC verification flag 1167 * 1168 * fit_check_fdt() verifies integrity of the FDT subimage and from 1169 * specified FIT image. 1170 * 1171 * returns: 1172 * 1, on success 1173 * 0, on failure 1174 */ 1175 #if defined(CONFIG_FIT) 1176 static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) 1177 { 1178 fit_image_print(fit, fdt_noffset, " "); 1179 1180 if (verify) { 1181 puts(" Verifying Hash Integrity ... "); 1182 if (!fit_image_check_hashes(fit, fdt_noffset)) { 1183 fdt_error("Bad Data Hash"); 1184 return 0; 1185 } 1186 puts("OK\n"); 1187 } 1188 1189 if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) { 1190 fdt_error("Not a FDT image"); 1191 return 0; 1192 } 1193 1194 if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) { 1195 fdt_error("FDT image is compressed"); 1196 return 0; 1197 } 1198 1199 return 1; 1200 } 1201 #endif /* CONFIG_FIT */ 1202 1203 #ifndef CONFIG_SYS_FDT_PAD 1204 #define CONFIG_SYS_FDT_PAD 0x3000 1205 #endif 1206 1207 #if defined(CONFIG_OF_LIBFDT) 1208 /** 1209 * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable 1210 * @lmb: pointer to lmb handle, will be used for memory mgmt 1211 * @fdt_blob: pointer to fdt blob base address 1212 * 1213 * Adds the memreserve regions in the dtb to the lmb block. Adding the 1214 * memreserve regions prevents u-boot from using them to store the initrd 1215 * or the fdt blob. 1216 */ 1217 void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob) 1218 { 1219 uint64_t addr, size; 1220 int i, total; 1221 1222 if (fdt_check_header(fdt_blob) != 0) 1223 return; 1224 1225 total = fdt_num_mem_rsv(fdt_blob); 1226 for (i = 0; i < total; i++) { 1227 if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0) 1228 continue; 1229 printf(" reserving fdt memory region: addr=%llx size=%llx\n", 1230 (unsigned long long)addr, (unsigned long long)size); 1231 lmb_reserve(lmb, addr, size); 1232 } 1233 } 1234 1235 /** 1236 * boot_relocate_fdt - relocate flat device tree 1237 * @lmb: pointer to lmb handle, will be used for memory mgmt 1238 * @of_flat_tree: pointer to a char* variable, will hold fdt start address 1239 * @of_size: pointer to a ulong variable, will hold fdt length 1240 * 1241 * boot_relocate_fdt() allocates a region of memory within the bootmap and 1242 * relocates the of_flat_tree into that region, even if the fdt is already in 1243 * the bootmap. It also expands the size of the fdt by CONFIG_SYS_FDT_PAD 1244 * bytes. 1245 * 1246 * of_flat_tree and of_size are set to final (after relocation) values 1247 * 1248 * returns: 1249 * 0 - success 1250 * 1 - failure 1251 */ 1252 int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) 1253 { 1254 void *fdt_blob = *of_flat_tree; 1255 void *of_start = 0; 1256 char *fdt_high; 1257 ulong of_len = 0; 1258 int err; 1259 int disable_relocation = 0; 1260 1261 /* nothing to do */ 1262 if (*of_size == 0) 1263 return 0; 1264 1265 if (fdt_check_header(fdt_blob) != 0) { 1266 fdt_error("image is not a fdt"); 1267 goto error; 1268 } 1269 1270 /* position on a 4K boundary before the alloc_current */ 1271 /* Pad the FDT by a specified amount */ 1272 of_len = *of_size + CONFIG_SYS_FDT_PAD; 1273 1274 /* If fdt_high is set use it to select the relocation address */ 1275 fdt_high = getenv("fdt_high"); 1276 if (fdt_high) { 1277 void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16); 1278 1279 if (((ulong) desired_addr) == ~0UL) { 1280 /* All ones means use fdt in place */ 1281 desired_addr = fdt_blob; 1282 disable_relocation = 1; 1283 } 1284 if (desired_addr) { 1285 of_start = 1286 (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, 1287 ((ulong) 1288 desired_addr) 1289 + of_len); 1290 if (desired_addr && of_start != desired_addr) { 1291 puts("Failed using fdt_high value for Device Tree"); 1292 goto error; 1293 } 1294 } else { 1295 of_start = 1296 (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000); 1297 } 1298 } else { 1299 of_start = 1300 (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, 1301 getenv_bootm_mapsize() 1302 + getenv_bootm_low()); 1303 } 1304 1305 if (of_start == 0) { 1306 puts("device tree - allocation error\n"); 1307 goto error; 1308 } 1309 1310 if (disable_relocation) { 1311 /* We assume there is space after the existing fdt to use for padding */ 1312 fdt_set_totalsize(of_start, of_len); 1313 printf(" Using Device Tree in place at %p, end %p\n", 1314 of_start, of_start + of_len - 1); 1315 } else { 1316 debug("## device tree at %p ... %p (len=%ld [0x%lX])\n", 1317 fdt_blob, fdt_blob + *of_size - 1, of_len, of_len); 1318 1319 printf(" Loading Device Tree to %p, end %p ... ", 1320 of_start, of_start + of_len - 1); 1321 1322 err = fdt_open_into(fdt_blob, of_start, of_len); 1323 if (err != 0) { 1324 fdt_error("fdt move failed"); 1325 goto error; 1326 } 1327 puts("OK\n"); 1328 } 1329 1330 *of_flat_tree = of_start; 1331 *of_size = of_len; 1332 1333 set_working_fdt_addr(*of_flat_tree); 1334 return 0; 1335 1336 error: 1337 return 1; 1338 } 1339 #endif /* CONFIG_OF_LIBFDT */ 1340 1341 /** 1342 * boot_get_fdt - main fdt handling routine 1343 * @argc: command argument count 1344 * @argv: command argument list 1345 * @images: pointer to the bootm images structure 1346 * @of_flat_tree: pointer to a char* variable, will hold fdt start address 1347 * @of_size: pointer to a ulong variable, will hold fdt length 1348 * 1349 * boot_get_fdt() is responsible for finding a valid flat device tree image. 1350 * Curently supported are the following ramdisk sources: 1351 * - multicomponent kernel/ramdisk image, 1352 * - commandline provided address of decicated ramdisk image. 1353 * 1354 * returns: 1355 * 0, if fdt image was found and valid, or skipped 1356 * of_flat_tree and of_size are set to fdt start address and length if 1357 * fdt image is found and valid 1358 * 1359 * 1, if fdt image is found but corrupted 1360 * of_flat_tree and of_size are set to 0 if no fdt exists 1361 */ 1362 int boot_get_fdt(int flag, int argc, char * const argv[], 1363 bootm_headers_t *images, char **of_flat_tree, ulong *of_size) 1364 { 1365 const image_header_t *fdt_hdr; 1366 ulong fdt_addr; 1367 char *fdt_blob = NULL; 1368 ulong image_start, image_end; 1369 ulong load_start, load_end; 1370 #if defined(CONFIG_FIT) 1371 void *fit_hdr; 1372 const char *fit_uname_config = NULL; 1373 const char *fit_uname_fdt = NULL; 1374 ulong default_addr; 1375 int cfg_noffset; 1376 int fdt_noffset; 1377 const void *data; 1378 size_t size; 1379 #endif 1380 1381 *of_flat_tree = NULL; 1382 *of_size = 0; 1383 1384 if (argc > 3 || genimg_has_config(images)) { 1385 #if defined(CONFIG_FIT) 1386 if (argc > 3) { 1387 /* 1388 * If the FDT blob comes from the FIT image and the 1389 * FIT image address is omitted in the command line 1390 * argument, try to use ramdisk or os FIT image 1391 * address or default load address. 1392 */ 1393 if (images->fit_uname_rd) 1394 default_addr = (ulong)images->fit_hdr_rd; 1395 else if (images->fit_uname_os) 1396 default_addr = (ulong)images->fit_hdr_os; 1397 else 1398 default_addr = load_addr; 1399 1400 if (fit_parse_conf(argv[3], default_addr, 1401 &fdt_addr, &fit_uname_config)) { 1402 debug("* fdt: config '%s' from image at " 1403 "0x%08lx\n", 1404 fit_uname_config, fdt_addr); 1405 } else if (fit_parse_subimage(argv[3], default_addr, 1406 &fdt_addr, &fit_uname_fdt)) { 1407 debug("* fdt: subimage '%s' from image at " 1408 "0x%08lx\n", 1409 fit_uname_fdt, fdt_addr); 1410 } else 1411 #endif 1412 { 1413 fdt_addr = simple_strtoul(argv[3], NULL, 16); 1414 debug("* fdt: cmdline image address = " 1415 "0x%08lx\n", 1416 fdt_addr); 1417 } 1418 #if defined(CONFIG_FIT) 1419 } else { 1420 /* use FIT configuration provided in first bootm 1421 * command argument 1422 */ 1423 fdt_addr = (ulong)images->fit_hdr_os; 1424 fit_uname_config = images->fit_uname_cfg; 1425 debug("* fdt: using config '%s' from image " 1426 "at 0x%08lx\n", 1427 fit_uname_config, fdt_addr); 1428 1429 /* 1430 * Check whether configuration has FDT blob defined, 1431 * if not quit silently. 1432 */ 1433 fit_hdr = (void *)fdt_addr; 1434 cfg_noffset = fit_conf_get_node(fit_hdr, 1435 fit_uname_config); 1436 if (cfg_noffset < 0) { 1437 debug("* fdt: no such config\n"); 1438 return 0; 1439 } 1440 1441 fdt_noffset = fit_conf_get_fdt_node(fit_hdr, 1442 cfg_noffset); 1443 if (fdt_noffset < 0) { 1444 debug("* fdt: no fdt in config\n"); 1445 return 0; 1446 } 1447 } 1448 #endif 1449 1450 debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", 1451 fdt_addr); 1452 1453 /* copy from dataflash if needed */ 1454 fdt_addr = genimg_get_image(fdt_addr); 1455 1456 /* 1457 * Check if there is an FDT image at the 1458 * address provided in the second bootm argument 1459 * check image type, for FIT images get a FIT node. 1460 */ 1461 switch (genimg_get_format((void *)fdt_addr)) { 1462 case IMAGE_FORMAT_LEGACY: 1463 /* verify fdt_addr points to a valid image header */ 1464 printf("## Flattened Device Tree from Legacy Image " 1465 "at %08lx\n", 1466 fdt_addr); 1467 fdt_hdr = image_get_fdt(fdt_addr); 1468 if (!fdt_hdr) 1469 goto error; 1470 1471 /* 1472 * move image data to the load address, 1473 * make sure we don't overwrite initial image 1474 */ 1475 image_start = (ulong)fdt_hdr; 1476 image_end = image_get_image_end(fdt_hdr); 1477 1478 load_start = image_get_load(fdt_hdr); 1479 load_end = load_start + image_get_data_size(fdt_hdr); 1480 1481 if ((load_start < image_end) && (load_end > image_start)) { 1482 fdt_error("fdt overwritten"); 1483 goto error; 1484 } 1485 1486 debug(" Loading FDT from 0x%08lx to 0x%08lx\n", 1487 image_get_data(fdt_hdr), load_start); 1488 1489 memmove((void *)load_start, 1490 (void *)image_get_data(fdt_hdr), 1491 image_get_data_size(fdt_hdr)); 1492 1493 fdt_blob = (char *)load_start; 1494 break; 1495 case IMAGE_FORMAT_FIT: 1496 /* 1497 * This case will catch both: new uImage format 1498 * (libfdt based) and raw FDT blob (also libfdt 1499 * based). 1500 */ 1501 #if defined(CONFIG_FIT) 1502 /* check FDT blob vs FIT blob */ 1503 if (fit_check_format((const void *)fdt_addr)) { 1504 /* 1505 * FIT image 1506 */ 1507 fit_hdr = (void *)fdt_addr; 1508 printf("## Flattened Device Tree from FIT " 1509 "Image at %08lx\n", 1510 fdt_addr); 1511 1512 if (!fit_uname_fdt) { 1513 /* 1514 * no FDT blob image node unit name, 1515 * try to get config node first. If 1516 * config unit node name is NULL 1517 * fit_conf_get_node() will try to 1518 * find default config node 1519 */ 1520 cfg_noffset = fit_conf_get_node(fit_hdr, 1521 fit_uname_config); 1522 1523 if (cfg_noffset < 0) { 1524 fdt_error("Could not find " 1525 "configuration " 1526 "node\n"); 1527 goto error; 1528 } 1529 1530 fit_uname_config = fdt_get_name(fit_hdr, 1531 cfg_noffset, NULL); 1532 printf(" Using '%s' configuration\n", 1533 fit_uname_config); 1534 1535 fdt_noffset = fit_conf_get_fdt_node( 1536 fit_hdr, 1537 cfg_noffset); 1538 fit_uname_fdt = fit_get_name(fit_hdr, 1539 fdt_noffset, NULL); 1540 } else { 1541 /* get FDT component image node offset */ 1542 fdt_noffset = fit_image_get_node( 1543 fit_hdr, 1544 fit_uname_fdt); 1545 } 1546 if (fdt_noffset < 0) { 1547 fdt_error("Could not find subimage " 1548 "node\n"); 1549 goto error; 1550 } 1551 1552 printf(" Trying '%s' FDT blob subimage\n", 1553 fit_uname_fdt); 1554 1555 if (!fit_check_fdt(fit_hdr, fdt_noffset, 1556 images->verify)) 1557 goto error; 1558 1559 /* get ramdisk image data address and length */ 1560 if (fit_image_get_data(fit_hdr, fdt_noffset, 1561 &data, &size)) { 1562 fdt_error("Could not find FDT " 1563 "subimage data"); 1564 goto error; 1565 } 1566 1567 /* verift that image data is a proper FDT blob */ 1568 if (fdt_check_header((char *)data) != 0) { 1569 fdt_error("Subimage data is not a FTD"); 1570 goto error; 1571 } 1572 1573 /* 1574 * move image data to the load address, 1575 * make sure we don't overwrite initial image 1576 */ 1577 image_start = (ulong)fit_hdr; 1578 image_end = fit_get_end(fit_hdr); 1579 1580 if (fit_image_get_load(fit_hdr, fdt_noffset, 1581 &load_start) == 0) { 1582 load_end = load_start + size; 1583 1584 if ((load_start < image_end) && 1585 (load_end > image_start)) { 1586 fdt_error("FDT overwritten"); 1587 goto error; 1588 } 1589 1590 printf(" Loading FDT from 0x%08lx " 1591 "to 0x%08lx\n", 1592 (ulong)data, 1593 load_start); 1594 1595 memmove((void *)load_start, 1596 (void *)data, size); 1597 1598 fdt_blob = (char *)load_start; 1599 } else { 1600 fdt_blob = (char *)data; 1601 } 1602 1603 images->fit_hdr_fdt = fit_hdr; 1604 images->fit_uname_fdt = fit_uname_fdt; 1605 images->fit_noffset_fdt = fdt_noffset; 1606 break; 1607 } else 1608 #endif 1609 { 1610 /* 1611 * FDT blob 1612 */ 1613 fdt_blob = (char *)fdt_addr; 1614 debug("* fdt: raw FDT blob\n"); 1615 printf("## Flattened Device Tree blob at " 1616 "%08lx\n", (long)fdt_blob); 1617 } 1618 break; 1619 default: 1620 puts("ERROR: Did not find a cmdline Flattened Device " 1621 "Tree\n"); 1622 goto error; 1623 } 1624 1625 printf(" Booting using the fdt blob at 0x%p\n", fdt_blob); 1626 1627 } else if (images->legacy_hdr_valid && 1628 image_check_type(&images->legacy_hdr_os_copy, 1629 IH_TYPE_MULTI)) { 1630 1631 ulong fdt_data, fdt_len; 1632 1633 /* 1634 * Now check if we have a legacy multi-component image, 1635 * get second entry data start address and len. 1636 */ 1637 printf("## Flattened Device Tree from multi " 1638 "component Image at %08lX\n", 1639 (ulong)images->legacy_hdr_os); 1640 1641 image_multi_getimg(images->legacy_hdr_os, 2, &fdt_data, 1642 &fdt_len); 1643 if (fdt_len) { 1644 1645 fdt_blob = (char *)fdt_data; 1646 printf(" Booting using the fdt at 0x%p\n", fdt_blob); 1647 1648 if (fdt_check_header(fdt_blob) != 0) { 1649 fdt_error("image is not a fdt"); 1650 goto error; 1651 } 1652 1653 if (fdt_totalsize(fdt_blob) != fdt_len) { 1654 fdt_error("fdt size != image size"); 1655 goto error; 1656 } 1657 } else { 1658 debug("## No Flattened Device Tree\n"); 1659 return 0; 1660 } 1661 } else { 1662 debug("## No Flattened Device Tree\n"); 1663 return 0; 1664 } 1665 1666 *of_flat_tree = fdt_blob; 1667 *of_size = fdt_totalsize(fdt_blob); 1668 debug(" of_flat_tree at 0x%08lx size 0x%08lx\n", 1669 (ulong)*of_flat_tree, *of_size); 1670 1671 return 0; 1672 1673 error: 1674 *of_flat_tree = 0; 1675 *of_size = 0; 1676 return 1; 1677 } 1678 #endif /* CONFIG_OF_LIBFDT */ 1679 1680 #ifdef CONFIG_SYS_BOOT_GET_CMDLINE 1681 /** 1682 * boot_get_cmdline - allocate and initialize kernel cmdline 1683 * @lmb: pointer to lmb handle, will be used for memory mgmt 1684 * @cmd_start: pointer to a ulong variable, will hold cmdline start 1685 * @cmd_end: pointer to a ulong variable, will hold cmdline end 1686 * 1687 * boot_get_cmdline() allocates space for kernel command line below 1688 * BOOTMAPSZ + getenv_bootm_low() address. If "bootargs" U-boot environemnt 1689 * variable is present its contents is copied to allocated kernel 1690 * command line. 1691 * 1692 * returns: 1693 * 0 - success 1694 * -1 - failure 1695 */ 1696 int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end) 1697 { 1698 char *cmdline; 1699 char *s; 1700 1701 cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, 1702 getenv_bootm_mapsize() + getenv_bootm_low()); 1703 1704 if (cmdline == NULL) 1705 return -1; 1706 1707 if ((s = getenv("bootargs")) == NULL) 1708 s = ""; 1709 1710 strcpy(cmdline, s); 1711 1712 *cmd_start = (ulong) & cmdline[0]; 1713 *cmd_end = *cmd_start + strlen(cmdline); 1714 1715 debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); 1716 1717 return 0; 1718 } 1719 #endif /* CONFIG_SYS_BOOT_GET_CMDLINE */ 1720 1721 #ifdef CONFIG_SYS_BOOT_GET_KBD 1722 /** 1723 * boot_get_kbd - allocate and initialize kernel copy of board info 1724 * @lmb: pointer to lmb handle, will be used for memory mgmt 1725 * @kbd: double pointer to board info data 1726 * 1727 * boot_get_kbd() allocates space for kernel copy of board info data below 1728 * BOOTMAPSZ + getenv_bootm_low() address and kernel board info is initialized 1729 * with the current u-boot board info data. 1730 * 1731 * returns: 1732 * 0 - success 1733 * -1 - failure 1734 */ 1735 int boot_get_kbd(struct lmb *lmb, bd_t **kbd) 1736 { 1737 *kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, 1738 getenv_bootm_mapsize() + getenv_bootm_low()); 1739 if (*kbd == NULL) 1740 return -1; 1741 1742 **kbd = *(gd->bd); 1743 1744 debug("## kernel board info at 0x%08lx\n", (ulong)*kbd); 1745 1746 #if defined(DEBUG) && defined(CONFIG_CMD_BDI) 1747 do_bdinfo(NULL, 0, 0, NULL); 1748 #endif 1749 1750 return 0; 1751 } 1752 #endif /* CONFIG_SYS_BOOT_GET_KBD */ 1753 #endif /* !USE_HOSTCC */ 1754 1755 #if defined(CONFIG_FIT) 1756 /*****************************************************************************/ 1757 /* New uImage format routines */ 1758 /*****************************************************************************/ 1759 #ifndef USE_HOSTCC 1760 static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr, 1761 ulong *addr, const char **name) 1762 { 1763 const char *sep; 1764 1765 *addr = addr_curr; 1766 *name = NULL; 1767 1768 sep = strchr(spec, sepc); 1769 if (sep) { 1770 if (sep - spec > 0) 1771 *addr = simple_strtoul(spec, NULL, 16); 1772 1773 *name = sep + 1; 1774 return 1; 1775 } 1776 1777 return 0; 1778 } 1779 1780 /** 1781 * fit_parse_conf - parse FIT configuration spec 1782 * @spec: input string, containing configuration spec 1783 * @add_curr: current image address (to be used as a possible default) 1784 * @addr: pointer to a ulong variable, will hold FIT image address of a given 1785 * configuration 1786 * @conf_name double pointer to a char, will hold pointer to a configuration 1787 * unit name 1788 * 1789 * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>, 1790 * where <addr> is a FIT image address that contains configuration 1791 * with a <conf> unit name. 1792 * 1793 * Address part is optional, and if omitted default add_curr will 1794 * be used instead. 1795 * 1796 * returns: 1797 * 1 if spec is a valid configuration string, 1798 * addr and conf_name are set accordingly 1799 * 0 otherwise 1800 */ 1801 inline int fit_parse_conf(const char *spec, ulong addr_curr, 1802 ulong *addr, const char **conf_name) 1803 { 1804 return fit_parse_spec(spec, '#', addr_curr, addr, conf_name); 1805 } 1806 1807 /** 1808 * fit_parse_subimage - parse FIT subimage spec 1809 * @spec: input string, containing subimage spec 1810 * @add_curr: current image address (to be used as a possible default) 1811 * @addr: pointer to a ulong variable, will hold FIT image address of a given 1812 * subimage 1813 * @image_name: double pointer to a char, will hold pointer to a subimage name 1814 * 1815 * fit_parse_subimage() expects subimage spec in the for of 1816 * [<addr>]:<subimage>, where <addr> is a FIT image address that contains 1817 * subimage with a <subimg> unit name. 1818 * 1819 * Address part is optional, and if omitted default add_curr will 1820 * be used instead. 1821 * 1822 * returns: 1823 * 1 if spec is a valid subimage string, 1824 * addr and image_name are set accordingly 1825 * 0 otherwise 1826 */ 1827 inline int fit_parse_subimage(const char *spec, ulong addr_curr, 1828 ulong *addr, const char **image_name) 1829 { 1830 return fit_parse_spec(spec, ':', addr_curr, addr, image_name); 1831 } 1832 #endif /* !USE_HOSTCC */ 1833 1834 static void fit_get_debug(const void *fit, int noffset, 1835 char *prop_name, int err) 1836 { 1837 debug("Can't get '%s' property from FIT 0x%08lx, " 1838 "node: offset %d, name %s (%s)\n", 1839 prop_name, (ulong)fit, noffset, 1840 fit_get_name(fit, noffset, NULL), 1841 fdt_strerror(err)); 1842 } 1843 1844 /** 1845 * fit_print_contents - prints out the contents of the FIT format image 1846 * @fit: pointer to the FIT format image header 1847 * @p: pointer to prefix string 1848 * 1849 * fit_print_contents() formats a multi line FIT image contents description. 1850 * The routine prints out FIT image properties (root node level) follwed by 1851 * the details of each component image. 1852 * 1853 * returns: 1854 * no returned results 1855 */ 1856 void fit_print_contents(const void *fit) 1857 { 1858 char *desc; 1859 char *uname; 1860 int images_noffset; 1861 int confs_noffset; 1862 int noffset; 1863 int ndepth; 1864 int count = 0; 1865 int ret; 1866 const char *p; 1867 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) 1868 time_t timestamp; 1869 #endif 1870 1871 #ifdef USE_HOSTCC 1872 p = ""; 1873 #else 1874 p = " "; 1875 #endif 1876 1877 /* Root node properties */ 1878 ret = fit_get_desc(fit, 0, &desc); 1879 printf("%sFIT description: ", p); 1880 if (ret) 1881 printf("unavailable\n"); 1882 else 1883 printf("%s\n", desc); 1884 1885 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) 1886 ret = fit_get_timestamp(fit, 0, ×tamp); 1887 printf("%sCreated: ", p); 1888 if (ret) 1889 printf("unavailable\n"); 1890 else 1891 genimg_print_time(timestamp); 1892 #endif 1893 1894 /* Find images parent node offset */ 1895 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 1896 if (images_noffset < 0) { 1897 printf("Can't find images parent node '%s' (%s)\n", 1898 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 1899 return; 1900 } 1901 1902 /* Process its subnodes, print out component images details */ 1903 for (ndepth = 0, count = 0, 1904 noffset = fdt_next_node(fit, images_noffset, &ndepth); 1905 (noffset >= 0) && (ndepth > 0); 1906 noffset = fdt_next_node(fit, noffset, &ndepth)) { 1907 if (ndepth == 1) { 1908 /* 1909 * Direct child node of the images parent node, 1910 * i.e. component image node. 1911 */ 1912 printf("%s Image %u (%s)\n", p, count++, 1913 fit_get_name(fit, noffset, NULL)); 1914 1915 fit_image_print(fit, noffset, p); 1916 } 1917 } 1918 1919 /* Find configurations parent node offset */ 1920 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 1921 if (confs_noffset < 0) { 1922 debug("Can't get configurations parent node '%s' (%s)\n", 1923 FIT_CONFS_PATH, fdt_strerror(confs_noffset)); 1924 return; 1925 } 1926 1927 /* get default configuration unit name from default property */ 1928 uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL); 1929 if (uname) 1930 printf("%s Default Configuration: '%s'\n", p, uname); 1931 1932 /* Process its subnodes, print out configurations details */ 1933 for (ndepth = 0, count = 0, 1934 noffset = fdt_next_node(fit, confs_noffset, &ndepth); 1935 (noffset >= 0) && (ndepth > 0); 1936 noffset = fdt_next_node(fit, noffset, &ndepth)) { 1937 if (ndepth == 1) { 1938 /* 1939 * Direct child node of the configurations parent node, 1940 * i.e. configuration node. 1941 */ 1942 printf("%s Configuration %u (%s)\n", p, count++, 1943 fit_get_name(fit, noffset, NULL)); 1944 1945 fit_conf_print(fit, noffset, p); 1946 } 1947 } 1948 } 1949 1950 /** 1951 * fit_image_print - prints out the FIT component image details 1952 * @fit: pointer to the FIT format image header 1953 * @image_noffset: offset of the component image node 1954 * @p: pointer to prefix string 1955 * 1956 * fit_image_print() lists all mandatory properies for the processed component 1957 * image. If present, hash nodes are printed out as well. Load 1958 * address for images of type firmware is also printed out. Since the load 1959 * address is not mandatory for firmware images, it will be output as 1960 * "unavailable" when not present. 1961 * 1962 * returns: 1963 * no returned results 1964 */ 1965 void fit_image_print(const void *fit, int image_noffset, const char *p) 1966 { 1967 char *desc; 1968 uint8_t type, arch, os, comp; 1969 size_t size; 1970 ulong load, entry; 1971 const void *data; 1972 int noffset; 1973 int ndepth; 1974 int ret; 1975 1976 /* Mandatory properties */ 1977 ret = fit_get_desc(fit, image_noffset, &desc); 1978 printf("%s Description: ", p); 1979 if (ret) 1980 printf("unavailable\n"); 1981 else 1982 printf("%s\n", desc); 1983 1984 fit_image_get_type(fit, image_noffset, &type); 1985 printf("%s Type: %s\n", p, genimg_get_type_name(type)); 1986 1987 fit_image_get_comp(fit, image_noffset, &comp); 1988 printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); 1989 1990 ret = fit_image_get_data(fit, image_noffset, &data, &size); 1991 1992 #ifndef USE_HOSTCC 1993 printf("%s Data Start: ", p); 1994 if (ret) 1995 printf("unavailable\n"); 1996 else 1997 printf("0x%08lx\n", (ulong)data); 1998 #endif 1999 2000 printf("%s Data Size: ", p); 2001 if (ret) 2002 printf("unavailable\n"); 2003 else 2004 genimg_print_size(size); 2005 2006 /* Remaining, type dependent properties */ 2007 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || 2008 (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || 2009 (type == IH_TYPE_FLATDT)) { 2010 fit_image_get_arch(fit, image_noffset, &arch); 2011 printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); 2012 } 2013 2014 if (type == IH_TYPE_KERNEL) { 2015 fit_image_get_os(fit, image_noffset, &os); 2016 printf("%s OS: %s\n", p, genimg_get_os_name(os)); 2017 } 2018 2019 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || 2020 (type == IH_TYPE_FIRMWARE)) { 2021 ret = fit_image_get_load(fit, image_noffset, &load); 2022 printf("%s Load Address: ", p); 2023 if (ret) 2024 printf("unavailable\n"); 2025 else 2026 printf("0x%08lx\n", load); 2027 } 2028 2029 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { 2030 fit_image_get_entry(fit, image_noffset, &entry); 2031 printf("%s Entry Point: ", p); 2032 if (ret) 2033 printf("unavailable\n"); 2034 else 2035 printf("0x%08lx\n", entry); 2036 } 2037 2038 /* Process all hash subnodes of the component image node */ 2039 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); 2040 (noffset >= 0) && (ndepth > 0); 2041 noffset = fdt_next_node(fit, noffset, &ndepth)) { 2042 if (ndepth == 1) { 2043 /* Direct child node of the component image node */ 2044 fit_image_print_hash(fit, noffset, p); 2045 } 2046 } 2047 } 2048 2049 /** 2050 * fit_image_print_hash - prints out the hash node details 2051 * @fit: pointer to the FIT format image header 2052 * @noffset: offset of the hash node 2053 * @p: pointer to prefix string 2054 * 2055 * fit_image_print_hash() lists properies for the processed hash node 2056 * 2057 * returns: 2058 * no returned results 2059 */ 2060 void fit_image_print_hash(const void *fit, int noffset, const char *p) 2061 { 2062 char *algo; 2063 uint8_t *value; 2064 int value_len; 2065 int i, ret; 2066 2067 /* 2068 * Check subnode name, must be equal to "hash". 2069 * Multiple hash nodes require unique unit node 2070 * names, e.g. hash@1, hash@2, etc. 2071 */ 2072 if (strncmp(fit_get_name(fit, noffset, NULL), 2073 FIT_HASH_NODENAME, 2074 strlen(FIT_HASH_NODENAME)) != 0) 2075 return; 2076 2077 debug("%s Hash node: '%s'\n", p, 2078 fit_get_name(fit, noffset, NULL)); 2079 2080 printf("%s Hash algo: ", p); 2081 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 2082 printf("invalid/unsupported\n"); 2083 return; 2084 } 2085 printf("%s\n", algo); 2086 2087 ret = fit_image_hash_get_value(fit, noffset, &value, 2088 &value_len); 2089 printf("%s Hash value: ", p); 2090 if (ret) { 2091 printf("unavailable\n"); 2092 } else { 2093 for (i = 0; i < value_len; i++) 2094 printf("%02x", value[i]); 2095 printf("\n"); 2096 } 2097 2098 debug("%s Hash len: %d\n", p, value_len); 2099 } 2100 2101 /** 2102 * fit_get_desc - get node description property 2103 * @fit: pointer to the FIT format image header 2104 * @noffset: node offset 2105 * @desc: double pointer to the char, will hold pointer to the descrption 2106 * 2107 * fit_get_desc() reads description property from a given node, if 2108 * description is found pointer to it is returened in third call argument. 2109 * 2110 * returns: 2111 * 0, on success 2112 * -1, on failure 2113 */ 2114 int fit_get_desc(const void *fit, int noffset, char **desc) 2115 { 2116 int len; 2117 2118 *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len); 2119 if (*desc == NULL) { 2120 fit_get_debug(fit, noffset, FIT_DESC_PROP, len); 2121 return -1; 2122 } 2123 2124 return 0; 2125 } 2126 2127 /** 2128 * fit_get_timestamp - get node timestamp property 2129 * @fit: pointer to the FIT format image header 2130 * @noffset: node offset 2131 * @timestamp: pointer to the time_t, will hold read timestamp 2132 * 2133 * fit_get_timestamp() reads timestamp poperty from given node, if timestamp 2134 * is found and has a correct size its value is retured in third call 2135 * argument. 2136 * 2137 * returns: 2138 * 0, on success 2139 * -1, on property read failure 2140 * -2, on wrong timestamp size 2141 */ 2142 int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp) 2143 { 2144 int len; 2145 const void *data; 2146 2147 data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len); 2148 if (data == NULL) { 2149 fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len); 2150 return -1; 2151 } 2152 if (len != sizeof(uint32_t)) { 2153 debug("FIT timestamp with incorrect size of (%u)\n", len); 2154 return -2; 2155 } 2156 2157 *timestamp = uimage_to_cpu(*((uint32_t *)data)); 2158 return 0; 2159 } 2160 2161 /** 2162 * fit_image_get_node - get node offset for component image of a given unit name 2163 * @fit: pointer to the FIT format image header 2164 * @image_uname: component image node unit name 2165 * 2166 * fit_image_get_node() finds a component image (withing the '/images' 2167 * node) of a provided unit name. If image is found its node offset is 2168 * returned to the caller. 2169 * 2170 * returns: 2171 * image node offset when found (>=0) 2172 * negative number on failure (FDT_ERR_* code) 2173 */ 2174 int fit_image_get_node(const void *fit, const char *image_uname) 2175 { 2176 int noffset, images_noffset; 2177 2178 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 2179 if (images_noffset < 0) { 2180 debug("Can't find images parent node '%s' (%s)\n", 2181 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 2182 return images_noffset; 2183 } 2184 2185 noffset = fdt_subnode_offset(fit, images_noffset, image_uname); 2186 if (noffset < 0) { 2187 debug("Can't get node offset for image unit name: '%s' (%s)\n", 2188 image_uname, fdt_strerror(noffset)); 2189 } 2190 2191 return noffset; 2192 } 2193 2194 /** 2195 * fit_image_get_os - get os id for a given component image node 2196 * @fit: pointer to the FIT format image header 2197 * @noffset: component image node offset 2198 * @os: pointer to the uint8_t, will hold os numeric id 2199 * 2200 * fit_image_get_os() finds os property in a given component image node. 2201 * If the property is found, its (string) value is translated to the numeric 2202 * id which is returned to the caller. 2203 * 2204 * returns: 2205 * 0, on success 2206 * -1, on failure 2207 */ 2208 int fit_image_get_os(const void *fit, int noffset, uint8_t *os) 2209 { 2210 int len; 2211 const void *data; 2212 2213 /* Get OS name from property data */ 2214 data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len); 2215 if (data == NULL) { 2216 fit_get_debug(fit, noffset, FIT_OS_PROP, len); 2217 *os = -1; 2218 return -1; 2219 } 2220 2221 /* Translate OS name to id */ 2222 *os = genimg_get_os_id(data); 2223 return 0; 2224 } 2225 2226 /** 2227 * fit_image_get_arch - get arch id for a given component image node 2228 * @fit: pointer to the FIT format image header 2229 * @noffset: component image node offset 2230 * @arch: pointer to the uint8_t, will hold arch numeric id 2231 * 2232 * fit_image_get_arch() finds arch property in a given component image node. 2233 * If the property is found, its (string) value is translated to the numeric 2234 * id which is returned to the caller. 2235 * 2236 * returns: 2237 * 0, on success 2238 * -1, on failure 2239 */ 2240 int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch) 2241 { 2242 int len; 2243 const void *data; 2244 2245 /* Get architecture name from property data */ 2246 data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len); 2247 if (data == NULL) { 2248 fit_get_debug(fit, noffset, FIT_ARCH_PROP, len); 2249 *arch = -1; 2250 return -1; 2251 } 2252 2253 /* Translate architecture name to id */ 2254 *arch = genimg_get_arch_id(data); 2255 return 0; 2256 } 2257 2258 /** 2259 * fit_image_get_type - get type id for a given component image node 2260 * @fit: pointer to the FIT format image header 2261 * @noffset: component image node offset 2262 * @type: pointer to the uint8_t, will hold type numeric id 2263 * 2264 * fit_image_get_type() finds type property in a given component image node. 2265 * If the property is found, its (string) value is translated to the numeric 2266 * id which is returned to the caller. 2267 * 2268 * returns: 2269 * 0, on success 2270 * -1, on failure 2271 */ 2272 int fit_image_get_type(const void *fit, int noffset, uint8_t *type) 2273 { 2274 int len; 2275 const void *data; 2276 2277 /* Get image type name from property data */ 2278 data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len); 2279 if (data == NULL) { 2280 fit_get_debug(fit, noffset, FIT_TYPE_PROP, len); 2281 *type = -1; 2282 return -1; 2283 } 2284 2285 /* Translate image type name to id */ 2286 *type = genimg_get_type_id(data); 2287 return 0; 2288 } 2289 2290 /** 2291 * fit_image_get_comp - get comp id for a given component image node 2292 * @fit: pointer to the FIT format image header 2293 * @noffset: component image node offset 2294 * @comp: pointer to the uint8_t, will hold comp numeric id 2295 * 2296 * fit_image_get_comp() finds comp property in a given component image node. 2297 * If the property is found, its (string) value is translated to the numeric 2298 * id which is returned to the caller. 2299 * 2300 * returns: 2301 * 0, on success 2302 * -1, on failure 2303 */ 2304 int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp) 2305 { 2306 int len; 2307 const void *data; 2308 2309 /* Get compression name from property data */ 2310 data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len); 2311 if (data == NULL) { 2312 fit_get_debug(fit, noffset, FIT_COMP_PROP, len); 2313 *comp = -1; 2314 return -1; 2315 } 2316 2317 /* Translate compression name to id */ 2318 *comp = genimg_get_comp_id(data); 2319 return 0; 2320 } 2321 2322 /** 2323 * fit_image_get_load - get load address property for a given component image node 2324 * @fit: pointer to the FIT format image header 2325 * @noffset: component image node offset 2326 * @load: pointer to the uint32_t, will hold load address 2327 * 2328 * fit_image_get_load() finds load address property in a given component image node. 2329 * If the property is found, its value is returned to the caller. 2330 * 2331 * returns: 2332 * 0, on success 2333 * -1, on failure 2334 */ 2335 int fit_image_get_load(const void *fit, int noffset, ulong *load) 2336 { 2337 int len; 2338 const uint32_t *data; 2339 2340 data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len); 2341 if (data == NULL) { 2342 fit_get_debug(fit, noffset, FIT_LOAD_PROP, len); 2343 return -1; 2344 } 2345 2346 *load = uimage_to_cpu(*data); 2347 return 0; 2348 } 2349 2350 /** 2351 * fit_image_get_entry - get entry point address property for a given component image node 2352 * @fit: pointer to the FIT format image header 2353 * @noffset: component image node offset 2354 * @entry: pointer to the uint32_t, will hold entry point address 2355 * 2356 * fit_image_get_entry() finds entry point address property in a given component image node. 2357 * If the property is found, its value is returned to the caller. 2358 * 2359 * returns: 2360 * 0, on success 2361 * -1, on failure 2362 */ 2363 int fit_image_get_entry(const void *fit, int noffset, ulong *entry) 2364 { 2365 int len; 2366 const uint32_t *data; 2367 2368 data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len); 2369 if (data == NULL) { 2370 fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len); 2371 return -1; 2372 } 2373 2374 *entry = uimage_to_cpu(*data); 2375 return 0; 2376 } 2377 2378 /** 2379 * fit_image_get_data - get data property and its size for a given component image node 2380 * @fit: pointer to the FIT format image header 2381 * @noffset: component image node offset 2382 * @data: double pointer to void, will hold data property's data address 2383 * @size: pointer to size_t, will hold data property's data size 2384 * 2385 * fit_image_get_data() finds data property in a given component image node. 2386 * If the property is found its data start address and size are returned to 2387 * the caller. 2388 * 2389 * returns: 2390 * 0, on success 2391 * -1, on failure 2392 */ 2393 int fit_image_get_data(const void *fit, int noffset, 2394 const void **data, size_t *size) 2395 { 2396 int len; 2397 2398 *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len); 2399 if (*data == NULL) { 2400 fit_get_debug(fit, noffset, FIT_DATA_PROP, len); 2401 *size = 0; 2402 return -1; 2403 } 2404 2405 *size = len; 2406 return 0; 2407 } 2408 2409 /** 2410 * fit_image_hash_get_algo - get hash algorithm name 2411 * @fit: pointer to the FIT format image header 2412 * @noffset: hash node offset 2413 * @algo: double pointer to char, will hold pointer to the algorithm name 2414 * 2415 * fit_image_hash_get_algo() finds hash algorithm property in a given hash node. 2416 * If the property is found its data start address is returned to the caller. 2417 * 2418 * returns: 2419 * 0, on success 2420 * -1, on failure 2421 */ 2422 int fit_image_hash_get_algo(const void *fit, int noffset, char **algo) 2423 { 2424 int len; 2425 2426 *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len); 2427 if (*algo == NULL) { 2428 fit_get_debug(fit, noffset, FIT_ALGO_PROP, len); 2429 return -1; 2430 } 2431 2432 return 0; 2433 } 2434 2435 /** 2436 * fit_image_hash_get_value - get hash value and length 2437 * @fit: pointer to the FIT format image header 2438 * @noffset: hash node offset 2439 * @value: double pointer to uint8_t, will hold address of a hash value data 2440 * @value_len: pointer to an int, will hold hash data length 2441 * 2442 * fit_image_hash_get_value() finds hash value property in a given hash node. 2443 * If the property is found its data start address and size are returned to 2444 * the caller. 2445 * 2446 * returns: 2447 * 0, on success 2448 * -1, on failure 2449 */ 2450 int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, 2451 int *value_len) 2452 { 2453 int len; 2454 2455 *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len); 2456 if (*value == NULL) { 2457 fit_get_debug(fit, noffset, FIT_VALUE_PROP, len); 2458 *value_len = 0; 2459 return -1; 2460 } 2461 2462 *value_len = len; 2463 return 0; 2464 } 2465 2466 /** 2467 * fit_set_timestamp - set node timestamp property 2468 * @fit: pointer to the FIT format image header 2469 * @noffset: node offset 2470 * @timestamp: timestamp value to be set 2471 * 2472 * fit_set_timestamp() attempts to set timestamp property in the requested 2473 * node and returns operation status to the caller. 2474 * 2475 * returns: 2476 * 0, on success 2477 * -1, on property read failure 2478 */ 2479 int fit_set_timestamp(void *fit, int noffset, time_t timestamp) 2480 { 2481 uint32_t t; 2482 int ret; 2483 2484 t = cpu_to_uimage(timestamp); 2485 ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t, 2486 sizeof(uint32_t)); 2487 if (ret) { 2488 printf("Can't set '%s' property for '%s' node (%s)\n", 2489 FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), 2490 fdt_strerror(ret)); 2491 return -1; 2492 } 2493 2494 return 0; 2495 } 2496 2497 /** 2498 * calculate_hash - calculate and return hash for provided input data 2499 * @data: pointer to the input data 2500 * @data_len: data length 2501 * @algo: requested hash algorithm 2502 * @value: pointer to the char, will hold hash value data (caller must 2503 * allocate enough free space) 2504 * value_len: length of the calculated hash 2505 * 2506 * calculate_hash() computes input data hash according to the requested algorithm. 2507 * Resulting hash value is placed in caller provided 'value' buffer, length 2508 * of the calculated hash is returned via value_len pointer argument. 2509 * 2510 * returns: 2511 * 0, on success 2512 * -1, when algo is unsupported 2513 */ 2514 static int calculate_hash(const void *data, int data_len, const char *algo, 2515 uint8_t *value, int *value_len) 2516 { 2517 if (strcmp(algo, "crc32") == 0) { 2518 *((uint32_t *)value) = crc32_wd(0, data, data_len, 2519 CHUNKSZ_CRC32); 2520 *((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value)); 2521 *value_len = 4; 2522 } else if (strcmp(algo, "sha1") == 0) { 2523 sha1_csum_wd((unsigned char *) data, data_len, 2524 (unsigned char *) value, CHUNKSZ_SHA1); 2525 *value_len = 20; 2526 } else if (strcmp(algo, "md5") == 0) { 2527 md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5); 2528 *value_len = 16; 2529 } else { 2530 debug("Unsupported hash alogrithm\n"); 2531 return -1; 2532 } 2533 return 0; 2534 } 2535 2536 #ifdef USE_HOSTCC 2537 /** 2538 * fit_set_hashes - process FIT component image nodes and calculate hashes 2539 * @fit: pointer to the FIT format image header 2540 * 2541 * fit_set_hashes() adds hash values for all component images in the FIT blob. 2542 * Hashes are calculated for all component images which have hash subnodes 2543 * with algorithm property set to one of the supported hash algorithms. 2544 * 2545 * returns 2546 * 0, on success 2547 * libfdt error code, on failure 2548 */ 2549 int fit_set_hashes(void *fit) 2550 { 2551 int images_noffset; 2552 int noffset; 2553 int ndepth; 2554 int ret; 2555 2556 /* Find images parent node offset */ 2557 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 2558 if (images_noffset < 0) { 2559 printf("Can't find images parent node '%s' (%s)\n", 2560 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 2561 return images_noffset; 2562 } 2563 2564 /* Process its subnodes, print out component images details */ 2565 for (ndepth = 0, noffset = fdt_next_node(fit, images_noffset, &ndepth); 2566 (noffset >= 0) && (ndepth > 0); 2567 noffset = fdt_next_node(fit, noffset, &ndepth)) { 2568 if (ndepth == 1) { 2569 /* 2570 * Direct child node of the images parent node, 2571 * i.e. component image node. 2572 */ 2573 ret = fit_image_set_hashes(fit, noffset); 2574 if (ret) 2575 return ret; 2576 } 2577 } 2578 2579 return 0; 2580 } 2581 2582 /** 2583 * fit_image_set_hashes - calculate/set hashes for given component image node 2584 * @fit: pointer to the FIT format image header 2585 * @image_noffset: requested component image node 2586 * 2587 * fit_image_set_hashes() adds hash values for an component image node. All 2588 * existing hash subnodes are checked, if algorithm property is set to one of 2589 * the supported hash algorithms, hash value is computed and corresponding 2590 * hash node property is set, for example: 2591 * 2592 * Input component image node structure: 2593 * 2594 * o image@1 (at image_noffset) 2595 * | - data = [binary data] 2596 * o hash@1 2597 * |- algo = "sha1" 2598 * 2599 * Output component image node structure: 2600 * 2601 * o image@1 (at image_noffset) 2602 * | - data = [binary data] 2603 * o hash@1 2604 * |- algo = "sha1" 2605 * |- value = sha1(data) 2606 * 2607 * returns: 2608 * 0 on sucess 2609 * <0 on failure 2610 */ 2611 int fit_image_set_hashes(void *fit, int image_noffset) 2612 { 2613 const void *data; 2614 size_t size; 2615 char *algo; 2616 uint8_t value[FIT_MAX_HASH_LEN]; 2617 int value_len; 2618 int noffset; 2619 int ndepth; 2620 2621 /* Get image data and data length */ 2622 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 2623 printf("Can't get image data/size\n"); 2624 return -1; 2625 } 2626 2627 /* Process all hash subnodes of the component image node */ 2628 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); 2629 (noffset >= 0) && (ndepth > 0); 2630 noffset = fdt_next_node(fit, noffset, &ndepth)) { 2631 if (ndepth == 1) { 2632 /* Direct child node of the component image node */ 2633 2634 /* 2635 * Check subnode name, must be equal to "hash". 2636 * Multiple hash nodes require unique unit node 2637 * names, e.g. hash@1, hash@2, etc. 2638 */ 2639 if (strncmp(fit_get_name(fit, noffset, NULL), 2640 FIT_HASH_NODENAME, 2641 strlen(FIT_HASH_NODENAME)) != 0) { 2642 /* Not a hash subnode, skip it */ 2643 continue; 2644 } 2645 2646 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 2647 printf("Can't get hash algo property for " 2648 "'%s' hash node in '%s' image node\n", 2649 fit_get_name(fit, noffset, NULL), 2650 fit_get_name(fit, image_noffset, NULL)); 2651 return -1; 2652 } 2653 2654 if (calculate_hash(data, size, algo, value, 2655 &value_len)) { 2656 printf("Unsupported hash algorithm (%s) for " 2657 "'%s' hash node in '%s' image node\n", 2658 algo, fit_get_name(fit, noffset, NULL), 2659 fit_get_name(fit, image_noffset, 2660 NULL)); 2661 return -1; 2662 } 2663 2664 if (fit_image_hash_set_value(fit, noffset, value, 2665 value_len)) { 2666 printf("Can't set hash value for " 2667 "'%s' hash node in '%s' image node\n", 2668 fit_get_name(fit, noffset, NULL), 2669 fit_get_name(fit, image_noffset, NULL)); 2670 return -1; 2671 } 2672 } 2673 } 2674 2675 return 0; 2676 } 2677 2678 /** 2679 * fit_image_hash_set_value - set hash value in requested has node 2680 * @fit: pointer to the FIT format image header 2681 * @noffset: hash node offset 2682 * @value: hash value to be set 2683 * @value_len: hash value length 2684 * 2685 * fit_image_hash_set_value() attempts to set hash value in a node at offset 2686 * given and returns operation status to the caller. 2687 * 2688 * returns 2689 * 0, on success 2690 * -1, on failure 2691 */ 2692 int fit_image_hash_set_value(void *fit, int noffset, uint8_t *value, 2693 int value_len) 2694 { 2695 int ret; 2696 2697 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 2698 if (ret) { 2699 printf("Can't set hash '%s' property for '%s' node(%s)\n", 2700 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), 2701 fdt_strerror(ret)); 2702 return -1; 2703 } 2704 2705 return 0; 2706 } 2707 #endif /* USE_HOSTCC */ 2708 2709 /** 2710 * fit_image_check_hashes - verify data intergity 2711 * @fit: pointer to the FIT format image header 2712 * @image_noffset: component image node offset 2713 * 2714 * fit_image_check_hashes() goes over component image hash nodes, 2715 * re-calculates each data hash and compares with the value stored in hash 2716 * node. 2717 * 2718 * returns: 2719 * 1, if all hashes are valid 2720 * 0, otherwise (or on error) 2721 */ 2722 int fit_image_check_hashes(const void *fit, int image_noffset) 2723 { 2724 const void *data; 2725 size_t size; 2726 char *algo; 2727 uint8_t *fit_value; 2728 int fit_value_len; 2729 uint8_t value[FIT_MAX_HASH_LEN]; 2730 int value_len; 2731 int noffset; 2732 int ndepth; 2733 char *err_msg = ""; 2734 2735 /* Get image data and data length */ 2736 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 2737 printf("Can't get image data/size\n"); 2738 return 0; 2739 } 2740 2741 /* Process all hash subnodes of the component image node */ 2742 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); 2743 (noffset >= 0) && (ndepth > 0); 2744 noffset = fdt_next_node(fit, noffset, &ndepth)) { 2745 if (ndepth == 1) { 2746 /* Direct child node of the component image node */ 2747 2748 /* 2749 * Check subnode name, must be equal to "hash". 2750 * Multiple hash nodes require unique unit node 2751 * names, e.g. hash@1, hash@2, etc. 2752 */ 2753 if (strncmp(fit_get_name(fit, noffset, NULL), 2754 FIT_HASH_NODENAME, 2755 strlen(FIT_HASH_NODENAME)) != 0) 2756 continue; 2757 2758 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 2759 err_msg = " error!\nCan't get hash algo " 2760 "property"; 2761 goto error; 2762 } 2763 printf("%s", algo); 2764 2765 if (fit_image_hash_get_value(fit, noffset, &fit_value, 2766 &fit_value_len)) { 2767 err_msg = " error!\nCan't get hash value " 2768 "property"; 2769 goto error; 2770 } 2771 2772 if (calculate_hash(data, size, algo, value, 2773 &value_len)) { 2774 err_msg = " error!\n" 2775 "Unsupported hash algorithm"; 2776 goto error; 2777 } 2778 2779 if (value_len != fit_value_len) { 2780 err_msg = " error !\nBad hash value len"; 2781 goto error; 2782 } else if (memcmp(value, fit_value, value_len) != 0) { 2783 err_msg = " error!\nBad hash value"; 2784 goto error; 2785 } 2786 printf("+ "); 2787 } 2788 } 2789 2790 return 1; 2791 2792 error: 2793 printf("%s for '%s' hash node in '%s' image node\n", 2794 err_msg, fit_get_name(fit, noffset, NULL), 2795 fit_get_name(fit, image_noffset, NULL)); 2796 return 0; 2797 } 2798 2799 /** 2800 * fit_all_image_check_hashes - verify data intergity for all images 2801 * @fit: pointer to the FIT format image header 2802 * 2803 * fit_all_image_check_hashes() goes over all images in the FIT and 2804 * for every images checks if all it's hashes are valid. 2805 * 2806 * returns: 2807 * 1, if all hashes of all images are valid 2808 * 0, otherwise (or on error) 2809 */ 2810 int fit_all_image_check_hashes(const void *fit) 2811 { 2812 int images_noffset; 2813 int noffset; 2814 int ndepth; 2815 int count; 2816 2817 /* Find images parent node offset */ 2818 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 2819 if (images_noffset < 0) { 2820 printf("Can't find images parent node '%s' (%s)\n", 2821 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 2822 return 0; 2823 } 2824 2825 /* Process all image subnodes, check hashes for each */ 2826 printf("## Checking hash(es) for FIT Image at %08lx ...\n", 2827 (ulong)fit); 2828 for (ndepth = 0, count = 0, 2829 noffset = fdt_next_node(fit, images_noffset, &ndepth); 2830 (noffset >= 0) && (ndepth > 0); 2831 noffset = fdt_next_node(fit, noffset, &ndepth)) { 2832 if (ndepth == 1) { 2833 /* 2834 * Direct child node of the images parent node, 2835 * i.e. component image node. 2836 */ 2837 printf(" Hash(es) for Image %u (%s): ", count++, 2838 fit_get_name(fit, noffset, NULL)); 2839 2840 if (!fit_image_check_hashes(fit, noffset)) 2841 return 0; 2842 printf("\n"); 2843 } 2844 } 2845 return 1; 2846 } 2847 2848 /** 2849 * fit_image_check_os - check whether image node is of a given os type 2850 * @fit: pointer to the FIT format image header 2851 * @noffset: component image node offset 2852 * @os: requested image os 2853 * 2854 * fit_image_check_os() reads image os property and compares its numeric 2855 * id with the requested os. Comparison result is returned to the caller. 2856 * 2857 * returns: 2858 * 1 if image is of given os type 2859 * 0 otherwise (or on error) 2860 */ 2861 int fit_image_check_os(const void *fit, int noffset, uint8_t os) 2862 { 2863 uint8_t image_os; 2864 2865 if (fit_image_get_os(fit, noffset, &image_os)) 2866 return 0; 2867 return (os == image_os); 2868 } 2869 2870 /** 2871 * fit_image_check_arch - check whether image node is of a given arch 2872 * @fit: pointer to the FIT format image header 2873 * @noffset: component image node offset 2874 * @arch: requested imagearch 2875 * 2876 * fit_image_check_arch() reads image arch property and compares its numeric 2877 * id with the requested arch. Comparison result is returned to the caller. 2878 * 2879 * returns: 2880 * 1 if image is of given arch 2881 * 0 otherwise (or on error) 2882 */ 2883 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) 2884 { 2885 uint8_t image_arch; 2886 2887 if (fit_image_get_arch(fit, noffset, &image_arch)) 2888 return 0; 2889 return (arch == image_arch); 2890 } 2891 2892 /** 2893 * fit_image_check_type - check whether image node is of a given type 2894 * @fit: pointer to the FIT format image header 2895 * @noffset: component image node offset 2896 * @type: requested image type 2897 * 2898 * fit_image_check_type() reads image type property and compares its numeric 2899 * id with the requested type. Comparison result is returned to the caller. 2900 * 2901 * returns: 2902 * 1 if image is of given type 2903 * 0 otherwise (or on error) 2904 */ 2905 int fit_image_check_type(const void *fit, int noffset, uint8_t type) 2906 { 2907 uint8_t image_type; 2908 2909 if (fit_image_get_type(fit, noffset, &image_type)) 2910 return 0; 2911 return (type == image_type); 2912 } 2913 2914 /** 2915 * fit_image_check_comp - check whether image node uses given compression 2916 * @fit: pointer to the FIT format image header 2917 * @noffset: component image node offset 2918 * @comp: requested image compression type 2919 * 2920 * fit_image_check_comp() reads image compression property and compares its 2921 * numeric id with the requested compression type. Comparison result is 2922 * returned to the caller. 2923 * 2924 * returns: 2925 * 1 if image uses requested compression 2926 * 0 otherwise (or on error) 2927 */ 2928 int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) 2929 { 2930 uint8_t image_comp; 2931 2932 if (fit_image_get_comp(fit, noffset, &image_comp)) 2933 return 0; 2934 return (comp == image_comp); 2935 } 2936 2937 /** 2938 * fit_check_format - sanity check FIT image format 2939 * @fit: pointer to the FIT format image header 2940 * 2941 * fit_check_format() runs a basic sanity FIT image verification. 2942 * Routine checks for mandatory properties, nodes, etc. 2943 * 2944 * returns: 2945 * 1, on success 2946 * 0, on failure 2947 */ 2948 int fit_check_format(const void *fit) 2949 { 2950 /* mandatory / node 'description' property */ 2951 if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) { 2952 debug("Wrong FIT format: no description\n"); 2953 return 0; 2954 } 2955 2956 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) 2957 /* mandatory / node 'timestamp' property */ 2958 if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) { 2959 debug("Wrong FIT format: no timestamp\n"); 2960 return 0; 2961 } 2962 #endif 2963 2964 /* mandatory subimages parent '/images' node */ 2965 if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) { 2966 debug("Wrong FIT format: no images parent node\n"); 2967 return 0; 2968 } 2969 2970 return 1; 2971 } 2972 2973 /** 2974 * fit_conf_get_node - get node offset for configuration of a given unit name 2975 * @fit: pointer to the FIT format image header 2976 * @conf_uname: configuration node unit name 2977 * 2978 * fit_conf_get_node() finds a configuration (withing the '/configurations' 2979 * parant node) of a provided unit name. If configuration is found its node offset 2980 * is returned to the caller. 2981 * 2982 * When NULL is provided in second argument fit_conf_get_node() will search 2983 * for a default configuration node instead. Default configuration node unit name 2984 * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node. 2985 * 2986 * returns: 2987 * configuration node offset when found (>=0) 2988 * negative number on failure (FDT_ERR_* code) 2989 */ 2990 int fit_conf_get_node(const void *fit, const char *conf_uname) 2991 { 2992 int noffset, confs_noffset; 2993 int len; 2994 2995 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); 2996 if (confs_noffset < 0) { 2997 debug("Can't find configurations parent node '%s' (%s)\n", 2998 FIT_CONFS_PATH, fdt_strerror(confs_noffset)); 2999 return confs_noffset; 3000 } 3001 3002 if (conf_uname == NULL) { 3003 /* get configuration unit name from the default property */ 3004 debug("No configuration specified, trying default...\n"); 3005 conf_uname = (char *)fdt_getprop(fit, confs_noffset, 3006 FIT_DEFAULT_PROP, &len); 3007 if (conf_uname == NULL) { 3008 fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP, 3009 len); 3010 return len; 3011 } 3012 debug("Found default configuration: '%s'\n", conf_uname); 3013 } 3014 3015 noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); 3016 if (noffset < 0) { 3017 debug("Can't get node offset for configuration unit name: " 3018 "'%s' (%s)\n", 3019 conf_uname, fdt_strerror(noffset)); 3020 } 3021 3022 return noffset; 3023 } 3024 3025 static int __fit_conf_get_prop_node(const void *fit, int noffset, 3026 const char *prop_name) 3027 { 3028 char *uname; 3029 int len; 3030 3031 /* get kernel image unit name from configuration kernel property */ 3032 uname = (char *)fdt_getprop(fit, noffset, prop_name, &len); 3033 if (uname == NULL) 3034 return len; 3035 3036 return fit_image_get_node(fit, uname); 3037 } 3038 3039 /** 3040 * fit_conf_get_kernel_node - get kernel image node offset that corresponds to 3041 * a given configuration 3042 * @fit: pointer to the FIT format image header 3043 * @noffset: configuration node offset 3044 * 3045 * fit_conf_get_kernel_node() retrives kernel image node unit name from 3046 * configuration FIT_KERNEL_PROP property and translates it to the node 3047 * offset. 3048 * 3049 * returns: 3050 * image node offset when found (>=0) 3051 * negative number on failure (FDT_ERR_* code) 3052 */ 3053 int fit_conf_get_kernel_node(const void *fit, int noffset) 3054 { 3055 return __fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP); 3056 } 3057 3058 /** 3059 * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to 3060 * a given configuration 3061 * @fit: pointer to the FIT format image header 3062 * @noffset: configuration node offset 3063 * 3064 * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from 3065 * configuration FIT_KERNEL_PROP property and translates it to the node 3066 * offset. 3067 * 3068 * returns: 3069 * image node offset when found (>=0) 3070 * negative number on failure (FDT_ERR_* code) 3071 */ 3072 int fit_conf_get_ramdisk_node(const void *fit, int noffset) 3073 { 3074 return __fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP); 3075 } 3076 3077 /** 3078 * fit_conf_get_fdt_node - get fdt image node offset that corresponds to 3079 * a given configuration 3080 * @fit: pointer to the FIT format image header 3081 * @noffset: configuration node offset 3082 * 3083 * fit_conf_get_fdt_node() retrives fdt image node unit name from 3084 * configuration FIT_KERNEL_PROP property and translates it to the node 3085 * offset. 3086 * 3087 * returns: 3088 * image node offset when found (>=0) 3089 * negative number on failure (FDT_ERR_* code) 3090 */ 3091 int fit_conf_get_fdt_node(const void *fit, int noffset) 3092 { 3093 return __fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP); 3094 } 3095 3096 /** 3097 * fit_conf_print - prints out the FIT configuration details 3098 * @fit: pointer to the FIT format image header 3099 * @noffset: offset of the configuration node 3100 * @p: pointer to prefix string 3101 * 3102 * fit_conf_print() lists all mandatory properies for the processed 3103 * configuration node. 3104 * 3105 * returns: 3106 * no returned results 3107 */ 3108 void fit_conf_print(const void *fit, int noffset, const char *p) 3109 { 3110 char *desc; 3111 char *uname; 3112 int ret; 3113 3114 /* Mandatory properties */ 3115 ret = fit_get_desc(fit, noffset, &desc); 3116 printf("%s Description: ", p); 3117 if (ret) 3118 printf("unavailable\n"); 3119 else 3120 printf("%s\n", desc); 3121 3122 uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL); 3123 printf("%s Kernel: ", p); 3124 if (uname == NULL) 3125 printf("unavailable\n"); 3126 else 3127 printf("%s\n", uname); 3128 3129 /* Optional properties */ 3130 uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL); 3131 if (uname) 3132 printf("%s Init Ramdisk: %s\n", p, uname); 3133 3134 uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); 3135 if (uname) 3136 printf("%s FDT: %s\n", p, uname); 3137 } 3138 3139 /** 3140 * fit_check_ramdisk - verify FIT format ramdisk subimage 3141 * @fit_hdr: pointer to the FIT ramdisk header 3142 * @rd_noffset: ramdisk subimage node offset within FIT image 3143 * @arch: requested ramdisk image architecture type 3144 * @verify: data CRC verification flag 3145 * 3146 * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from 3147 * specified FIT image. 3148 * 3149 * returns: 3150 * 1, on success 3151 * 0, on failure 3152 */ 3153 #ifndef USE_HOSTCC 3154 static int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, 3155 int verify) 3156 { 3157 fit_image_print(fit, rd_noffset, " "); 3158 3159 if (verify) { 3160 puts(" Verifying Hash Integrity ... "); 3161 if (!fit_image_check_hashes(fit, rd_noffset)) { 3162 puts("Bad Data Hash\n"); 3163 show_boot_progress(-125); 3164 return 0; 3165 } 3166 puts("OK\n"); 3167 } 3168 3169 show_boot_progress(126); 3170 if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) || 3171 !fit_image_check_arch(fit, rd_noffset, arch) || 3172 !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) { 3173 printf("No Linux %s Ramdisk Image\n", 3174 genimg_get_arch_name(arch)); 3175 show_boot_progress(-126); 3176 return 0; 3177 } 3178 3179 show_boot_progress(127); 3180 return 1; 3181 } 3182 #endif /* USE_HOSTCC */ 3183 #endif /* CONFIG_FIT */ 3184