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 #define DEBUG 27 28 #ifndef USE_HOSTCC 29 #include <common.h> 30 #include <watchdog.h> 31 32 #ifdef CONFIG_SHOW_BOOT_PROGRESS 33 #include <status_led.h> 34 #endif 35 36 #ifdef CONFIG_HAS_DATAFLASH 37 #include <dataflash.h> 38 #endif 39 40 #ifdef CONFIG_LOGBUFFER 41 #include <logbuff.h> 42 #endif 43 44 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 45 #include <rtc.h> 46 #endif 47 48 #if defined(CONFIG_FIT) 49 #include <fdt.h> 50 #include <libfdt.h> 51 #include <fdt_support.h> 52 #endif 53 54 #ifdef CONFIG_CMD_BDI 55 extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); 56 #endif 57 58 DECLARE_GLOBAL_DATA_PTR; 59 60 static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, 61 int argc, char *argv[], 62 ulong rd_addr, uint8_t arch, int verify); 63 #else 64 #include "mkimage.h" 65 #endif /* USE_HOSTCC*/ 66 67 #include <image.h> 68 69 unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); 70 71 int image_check_hcrc (image_header_t *hdr) 72 { 73 ulong hcrc; 74 ulong len = image_get_header_size (); 75 image_header_t header; 76 77 /* Copy header so we can blank CRC field for re-calculation */ 78 memmove (&header, (char *)hdr, image_get_header_size ()); 79 image_set_hcrc (&header, 0); 80 81 hcrc = crc32 (0, (unsigned char *)&header, len); 82 83 return (hcrc == image_get_hcrc (hdr)); 84 } 85 86 int image_check_dcrc (image_header_t *hdr) 87 { 88 ulong data = image_get_data (hdr); 89 ulong len = image_get_data_size (hdr); 90 ulong dcrc = crc32 (0, (unsigned char *)data, len); 91 92 return (dcrc == image_get_dcrc (hdr)); 93 } 94 95 #ifndef USE_HOSTCC 96 int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) 97 { 98 ulong dcrc = 0; 99 ulong len = image_get_data_size (hdr); 100 ulong data = image_get_data (hdr); 101 102 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 103 ulong cdata = data; 104 ulong edata = cdata + len; 105 106 while (cdata < edata) { 107 ulong chunk = edata - cdata; 108 109 if (chunk > chunksz) 110 chunk = chunksz; 111 dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk); 112 cdata += chunk; 113 114 WATCHDOG_RESET (); 115 } 116 #else 117 dcrc = crc32 (0, (unsigned char *)data, len); 118 #endif 119 120 return (dcrc == image_get_dcrc (hdr)); 121 } 122 123 int getenv_verify (void) 124 { 125 char *s = getenv ("verify"); 126 return (s && (*s == 'n')) ? 0 : 1; 127 } 128 129 int getenv_autostart (void) 130 { 131 char *s = getenv ("autostart"); 132 return (s && (*s == 'n')) ? 0 : 1; 133 } 134 135 ulong getenv_bootm_low(void) 136 { 137 char *s = getenv ("bootm_low"); 138 if (s) { 139 ulong tmp = simple_strtoul (s, NULL, 16); 140 return tmp; 141 } 142 143 #ifdef CFG_SDRAM_BASE 144 return CFG_SDRAM_BASE; 145 #else 146 return 0; 147 #endif 148 } 149 150 ulong getenv_bootm_size(void) 151 { 152 char *s = getenv ("bootm_size"); 153 if (s) { 154 ulong tmp = simple_strtoul (s, NULL, 16); 155 return tmp; 156 } 157 158 return gd->bd->bi_memsize; 159 } 160 161 void memmove_wd (void *to, void *from, size_t len, ulong chunksz) 162 { 163 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 164 while (len > 0) { 165 size_t tail = (len > chunksz) ? chunksz : len; 166 WATCHDOG_RESET (); 167 memmove (to, from, tail); 168 to += tail; 169 from += tail; 170 len -= tail; 171 } 172 #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ 173 memmove (to, from, len); 174 #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ 175 } 176 #endif /* USE_HOSTCC */ 177 178 /** 179 * image_multi_count - get component (sub-image) count 180 * @hdr: pointer to the header of the multi component image 181 * 182 * image_multi_count() returns number of components in a multi 183 * component image. 184 * 185 * Note: no checking of the image type is done, caller must pass 186 * a valid multi component image. 187 * 188 * returns: 189 * number of components 190 */ 191 ulong image_multi_count (image_header_t *hdr) 192 { 193 ulong i, count = 0; 194 ulong *size; 195 196 /* get start of the image payload, which in case of multi 197 * component images that points to a table of component sizes */ 198 size = (ulong *)image_get_data (hdr); 199 200 /* count non empty slots */ 201 for (i = 0; size[i]; ++i) 202 count++; 203 204 return count; 205 } 206 207 /** 208 * image_multi_getimg - get component data address and size 209 * @hdr: pointer to the header of the multi component image 210 * @idx: index of the requested component 211 * @data: pointer to a ulong variable, will hold component data address 212 * @len: pointer to a ulong variable, will hold component size 213 * 214 * image_multi_getimg() returns size and data address for the requested 215 * component in a multi component image. 216 * 217 * Note: no checking of the image type is done, caller must pass 218 * a valid multi component image. 219 * 220 * returns: 221 * data address and size of the component, if idx is valid 222 * 0 in data and len, if idx is out of range 223 */ 224 void image_multi_getimg (image_header_t *hdr, ulong idx, 225 ulong *data, ulong *len) 226 { 227 int i; 228 ulong *size; 229 ulong offset, tail, count, img_data; 230 231 /* get number of component */ 232 count = image_multi_count (hdr); 233 234 /* get start of the image payload, which in case of multi 235 * component images that points to a table of component sizes */ 236 size = (ulong *)image_get_data (hdr); 237 238 /* get address of the proper component data start, which means 239 * skipping sizes table (add 1 for last, null entry) */ 240 img_data = image_get_data (hdr) + (count + 1) * sizeof (ulong); 241 242 if (idx < count) { 243 *len = size[idx]; 244 offset = 0; 245 tail = 0; 246 247 /* go over all indices preceding requested component idx */ 248 for (i = 0; i < idx; i++) { 249 /* add up i-th component size */ 250 offset += size[i]; 251 252 /* add up alignment for i-th component */ 253 tail += (4 - size[i] % 4); 254 } 255 256 /* calculate idx-th component data address */ 257 *data = img_data + offset + tail; 258 } else { 259 *len = 0; 260 *data = 0; 261 } 262 } 263 264 #ifndef USE_HOSTCC 265 const char* image_get_os_name (uint8_t os) 266 { 267 const char *name; 268 269 switch (os) { 270 case IH_OS_INVALID: name = "Invalid OS"; break; 271 case IH_OS_NETBSD: name = "NetBSD"; break; 272 case IH_OS_LINUX: name = "Linux"; break; 273 case IH_OS_VXWORKS: name = "VxWorks"; break; 274 case IH_OS_QNX: name = "QNX"; break; 275 case IH_OS_U_BOOT: name = "U-Boot"; break; 276 case IH_OS_RTEMS: name = "RTEMS"; break; 277 #ifdef CONFIG_ARTOS 278 case IH_OS_ARTOS: name = "ARTOS"; break; 279 #endif 280 #ifdef CONFIG_LYNXKDI 281 case IH_OS_LYNXOS: name = "LynxOS"; break; 282 #endif 283 default: name = "Unknown OS"; break; 284 } 285 286 return name; 287 } 288 289 const char* image_get_arch_name (uint8_t arch) 290 { 291 const char *name; 292 293 switch (arch) { 294 case IH_ARCH_INVALID: name = "Invalid Architecture"; break; 295 case IH_ARCH_ALPHA: name = "Alpha"; break; 296 case IH_ARCH_ARM: name = "ARM"; break; 297 case IH_ARCH_AVR32: name = "AVR32"; break; 298 case IH_ARCH_BLACKFIN: name = "Blackfin"; break; 299 case IH_ARCH_I386: name = "Intel x86"; break; 300 case IH_ARCH_IA64: name = "IA64"; break; 301 case IH_ARCH_M68K: name = "M68K"; break; 302 case IH_ARCH_MICROBLAZE:name = "Microblaze"; break; 303 case IH_ARCH_MIPS64: name = "MIPS 64 Bit"; break; 304 case IH_ARCH_MIPS: name = "MIPS"; break; 305 case IH_ARCH_NIOS2: name = "Nios-II"; break; 306 case IH_ARCH_NIOS: name = "Nios"; break; 307 case IH_ARCH_PPC: name = "PowerPC"; break; 308 case IH_ARCH_S390: name = "IBM S390"; break; 309 case IH_ARCH_SH: name = "SuperH"; break; 310 case IH_ARCH_SPARC64: name = "SPARC 64 Bit"; break; 311 case IH_ARCH_SPARC: name = "SPARC"; break; 312 default: name = "Unknown Architecture"; break; 313 } 314 315 return name; 316 } 317 318 const char* image_get_type_name (uint8_t type) 319 { 320 const char *name; 321 322 switch (type) { 323 case IH_TYPE_INVALID: name = "Invalid Image"; break; 324 case IH_TYPE_STANDALONE:name = "Standalone Program"; break; 325 case IH_TYPE_KERNEL: name = "Kernel Image"; break; 326 case IH_TYPE_RAMDISK: name = "RAMDisk Image"; break; 327 case IH_TYPE_MULTI: name = "Multi-File Image"; break; 328 case IH_TYPE_FIRMWARE: name = "Firmware"; break; 329 case IH_TYPE_SCRIPT: name = "Script"; break; 330 case IH_TYPE_FLATDT: name = "Flat Device Tree"; break; 331 default: name = "Unknown Image"; break; 332 } 333 334 return name; 335 } 336 337 const char* image_get_comp_name (uint8_t comp) 338 { 339 const char *name; 340 341 switch (comp) { 342 case IH_COMP_NONE: name = "uncompressed"; break; 343 case IH_COMP_GZIP: name = "gzip compressed"; break; 344 case IH_COMP_BZIP2: name = "bzip2 compressed"; break; 345 default: name = "unknown compression"; break; 346 } 347 348 return name; 349 } 350 351 static void image_print_type (image_header_t *hdr) 352 { 353 const char *os, *arch, *type, *comp; 354 355 os = image_get_os_name (image_get_os (hdr)); 356 arch = image_get_arch_name (image_get_arch (hdr)); 357 type = image_get_type_name (image_get_type (hdr)); 358 comp = image_get_comp_name (image_get_comp (hdr)); 359 360 printf ("%s %s %s (%s)", arch, os, type, comp); 361 } 362 363 void image_print_contents (image_header_t *hdr) 364 { 365 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 366 time_t timestamp = (time_t)image_get_time (hdr); 367 struct rtc_time tm; 368 #endif 369 370 printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); 371 372 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 373 to_tm (timestamp, &tm); 374 printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", 375 tm.tm_year, tm.tm_mon, tm.tm_mday, 376 tm.tm_hour, tm.tm_min, tm.tm_sec); 377 #endif 378 puts (" Image Type: "); 379 image_print_type (hdr); 380 381 printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); 382 print_size (image_get_data_size (hdr), "\n"); 383 printf (" Load Address: %08x\n" 384 " Entry Point: %08x\n", 385 image_get_load (hdr), image_get_ep (hdr)); 386 387 if (image_check_type (hdr, IH_TYPE_MULTI)) { 388 int i; 389 ulong data, len; 390 ulong count = image_multi_count (hdr); 391 392 puts (" Contents:\n"); 393 for (i = 0; i < count; i++) { 394 image_multi_getimg (hdr, i, &data, &len); 395 printf (" Image %d: %8ld Bytes = ", i, len); 396 print_size (len, "\n"); 397 } 398 } 399 } 400 401 /** 402 * gen_image_get_format - get image format type 403 * @img_addr: image start address 404 * 405 * gen_image_get_format() checks whether provided address points to a valid 406 * legacy or FIT image. 407 * 408 * New uImage format and FDT blob are based on a libfdt. FDT blob 409 * may be passed directly or embedded in a FIT image. In both situations 410 * gen_image_get_format() must be able to dectect libfdt header. 411 * 412 * returns: 413 * image format type or IMAGE_FORMAT_INVALID if no image is present 414 */ 415 int gen_image_get_format (void *img_addr) 416 { 417 ulong format = IMAGE_FORMAT_INVALID; 418 image_header_t *hdr; 419 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 420 char *fit_hdr; 421 #endif 422 423 hdr = (image_header_t *)img_addr; 424 if (image_check_magic(hdr)) 425 format = IMAGE_FORMAT_LEGACY; 426 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 427 else { 428 fit_hdr = (char *)img_addr; 429 if (fdt_check_header (fit_hdr) == 0) 430 format = IMAGE_FORMAT_FIT; 431 } 432 #endif 433 434 return format; 435 } 436 437 /** 438 * gen_get_image - get image from special storage (if necessary) 439 * @img_addr: image start address 440 * 441 * gen_get_image() checks if provided image start adddress is located 442 * in a dataflash storage. If so, image is moved to a system RAM memory. 443 * 444 * returns: 445 * image start address after possible relocation from special storage 446 */ 447 ulong gen_get_image (ulong img_addr) 448 { 449 ulong ram_addr = img_addr; 450 451 #ifdef CONFIG_HAS_DATAFLASH 452 ulong h_size, d_size; 453 454 if (addr_dataflash (img_addr)){ 455 /* ger RAM address */ 456 ram_addr = CFG_LOAD_ADDR; 457 458 /* get header size */ 459 h_size = image_get_header_size (); 460 #if defined(CONFIG_FIT) 461 if (sizeof(struct fdt_header) > h_size) 462 h_size = sizeof(struct fdt_header); 463 #endif 464 465 /* read in header */ 466 debug (" Reading image header from dataflash address " 467 "%08lx to RAM address %08lx\n", img_addr, ram_addr); 468 469 read_dataflash (img_addr, h_size, (char *)ram_addr); 470 471 /* get data size */ 472 switch (gen_image_get_format ((void *)ram_addr)) { 473 case IMAGE_FORMAT_LEGACY: 474 d_size = image_get_data_size ((image_header_t *)ram_addr); 475 debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", 476 ram_addr, d_size); 477 break; 478 #if defined(CONFIG_FIT) 479 case IMAGE_FORMAT_FIT: 480 d_size = fdt_totalsize((void *)ram_addr) - h_size; 481 debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", 482 ram_addr, d_size); 483 break; 484 #endif 485 default: 486 printf (" No valid image found at 0x%08lx\n", img_addr); 487 return ram_addr; 488 } 489 490 /* read in image data */ 491 debug (" Reading image remaining data from dataflash address " 492 "%08lx to RAM address %08lx\n", img_addr + h_size, 493 ram_addr + h_size); 494 495 read_dataflash (img_addr + h_size, d_size, 496 (char *)(ram_addr + h_size)); 497 498 } 499 #endif /* CONFIG_HAS_DATAFLASH */ 500 501 return ram_addr; 502 } 503 504 /** 505 * image_get_ramdisk - get and verify ramdisk image 506 * @cmdtp: command table pointer 507 * @flag: command flag 508 * @argc: command argument count 509 * @argv: command argument list 510 * @rd_addr: ramdisk image start address 511 * @arch: expected ramdisk architecture 512 * @verify: checksum verification flag 513 * 514 * image_get_ramdisk() returns a pointer to the verified ramdisk image 515 * header. Routine receives image start address and expected architecture 516 * flag. Verification done covers data and header integrity and os/type/arch 517 * fields checking. 518 * 519 * If dataflash support is enabled routine checks for dataflash addresses 520 * and handles required dataflash reads. 521 * 522 * returns: 523 * pointer to a ramdisk image header, if image was found and valid 524 * otherwise, return NULL 525 */ 526 static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, 527 int argc, char *argv[], 528 ulong rd_addr, uint8_t arch, int verify) 529 { 530 image_header_t *rd_hdr; 531 532 show_boot_progress (9); 533 rd_hdr = (image_header_t *)rd_addr; 534 535 if (!image_check_magic (rd_hdr)) { 536 puts ("Bad Magic Number\n"); 537 show_boot_progress (-10); 538 return NULL; 539 } 540 541 if (!image_check_hcrc (rd_hdr)) { 542 puts ("Bad Header Checksum\n"); 543 show_boot_progress (-11); 544 return NULL; 545 } 546 547 show_boot_progress (10); 548 image_print_contents (rd_hdr); 549 550 if (verify) { 551 puts(" Verifying Checksum ... "); 552 if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { 553 puts ("Bad Data CRC\n"); 554 show_boot_progress (-12); 555 return NULL; 556 } 557 puts("OK\n"); 558 } 559 560 show_boot_progress (11); 561 562 if (!image_check_os (rd_hdr, IH_OS_LINUX) || 563 !image_check_arch (rd_hdr, arch) || 564 !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { 565 printf ("No Linux %s Ramdisk Image\n", 566 image_get_arch_name(arch)); 567 show_boot_progress (-13); 568 return NULL; 569 } 570 571 return rd_hdr; 572 } 573 574 /** 575 * get_ramdisk - main ramdisk handling routine 576 * @cmdtp: command table pointer 577 * @flag: command flag 578 * @argc: command argument count 579 * @argv: command argument list 580 * @images: pointer to the bootm images structure 581 * @arch: expected ramdisk architecture 582 * @rd_start: pointer to a ulong variable, will hold ramdisk start address 583 * @rd_end: pointer to a ulong variable, will hold ramdisk end 584 * 585 * get_ramdisk() is responsible for finding a valid ramdisk image. 586 * Curently supported are the following ramdisk sources: 587 * - multicomponent kernel/ramdisk image, 588 * - commandline provided address of decicated ramdisk image. 589 * 590 * returns: 591 * rd_start and rd_end are set to ramdisk start/end addresses if 592 * ramdisk image is found and valid 593 * rd_start and rd_end are set to 0 if no ramdisk exists 594 * return 1 if ramdisk image is found but corrupted 595 */ 596 int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], 597 bootm_headers_t *images, uint8_t arch, 598 ulong *rd_start, ulong *rd_end) 599 { 600 ulong rd_addr, rd_load; 601 ulong rd_data, rd_len; 602 image_header_t *rd_hdr; 603 #if defined(CONFIG_FIT) 604 void *fit_hdr; 605 const char *fit_uname_config = NULL; 606 const char *fit_uname_ramdisk = NULL; 607 ulong default_addr; 608 #endif 609 610 /* 611 * Look for a '-' which indicates to ignore the 612 * ramdisk argument 613 */ 614 if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) { 615 debug ("## Skipping init Ramdisk\n"); 616 rd_len = rd_data = 0; 617 } else if (argc >= 3) { 618 #if defined(CONFIG_FIT) 619 /* 620 * If the init ramdisk comes from the FIT image and the FIT image 621 * address is omitted in the command line argument, try to use 622 * os FIT image address or default load address. 623 */ 624 if (images->fit_uname_os) 625 default_addr = (ulong)images->fit_hdr_os; 626 else 627 default_addr = load_addr; 628 629 if (fit_parse_conf (argv[2], default_addr, 630 &rd_addr, &fit_uname_config)) { 631 debug ("* ramdisk: config '%s' from image at 0x%08lx\n", 632 fit_uname_config, rd_addr); 633 } else if (fit_parse_subimage (argv[2], default_addr, 634 &rd_addr, &fit_uname_ramdisk)) { 635 debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n", 636 fit_uname_ramdisk, rd_addr); 637 } else 638 #endif 639 { 640 rd_addr = simple_strtoul(argv[2], NULL, 16); 641 debug ("* ramdisk: cmdline image address = 0x%08lx\n", 642 rd_addr); 643 } 644 645 /* copy from dataflash if needed */ 646 printf ("## Loading init Ramdisk Image at %08lx ...\n", 647 rd_addr); 648 rd_addr = gen_get_image (rd_addr); 649 650 /* 651 * Check if there is an initrd image at the 652 * address provided in the second bootm argument 653 * check image type, for FIT images get FIT node. 654 */ 655 switch (gen_image_get_format ((void *)rd_addr)) { 656 case IMAGE_FORMAT_LEGACY: 657 658 debug ("* ramdisk: legacy format image\n"); 659 660 rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, 661 rd_addr, arch, images->verify); 662 663 if (rd_hdr == NULL) { 664 *rd_start = 0; 665 *rd_end = 0; 666 return 1; 667 } 668 669 rd_data = image_get_data (rd_hdr); 670 rd_len = image_get_data_size (rd_hdr); 671 rd_load = image_get_load (rd_hdr); 672 break; 673 #if defined(CONFIG_FIT) 674 case IMAGE_FORMAT_FIT: 675 fit_hdr = (void *)rd_addr; 676 debug ("* ramdisk: FIT format image\n"); 677 fit_unsupported_reset ("ramdisk"); 678 return 1; 679 #endif 680 default: 681 printf ("Wrong Image Format for %s command\n", 682 cmdtp->name); 683 rd_data = rd_len = 0; 684 } 685 686 #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) 687 /* 688 * We need to copy the ramdisk to SRAM to let Linux boot 689 */ 690 if (rd_data) { 691 memmove ((void *)rd_load, (uchar *)rd_data, rd_len); 692 rd_data = rd_load; 693 } 694 #endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ 695 696 } else if (images->legacy_hdr_valid && 697 image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { 698 /* 699 * Now check if we have a legacy mult-component image, 700 * get second entry data start address and len. 701 */ 702 show_boot_progress (13); 703 printf ("## Loading init Ramdisk from multi component " 704 "Image at %08lx ...\n", 705 (ulong)images->legacy_hdr_os); 706 707 image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len); 708 } else { 709 /* 710 * no initrd image 711 */ 712 show_boot_progress (14); 713 rd_len = rd_data = 0; 714 } 715 716 if (!rd_data) { 717 debug ("## No init Ramdisk\n"); 718 *rd_start = 0; 719 *rd_end = 0; 720 } else { 721 *rd_start = rd_data; 722 *rd_end = rd_data + rd_len; 723 } 724 debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", 725 *rd_start, *rd_end); 726 727 return 0; 728 } 729 730 #if defined(CONFIG_PPC) || defined(CONFIG_M68K) 731 /** 732 * ramdisk_high - relocate init ramdisk 733 * @lmb: pointer to lmb handle, will be used for memory mgmt 734 * @rd_data: ramdisk data start address 735 * @rd_len: ramdisk data length 736 * @initrd_start: pointer to a ulong variable, will hold final init ramdisk 737 * start address (after possible relocation) 738 * @initrd_end: pointer to a ulong variable, will hold final init ramdisk 739 * end address (after possible relocation) 740 * 741 * ramdisk_high() takes a relocation hint from "initrd_high" environement 742 * variable and if requested ramdisk data is moved to a specified location. 743 * 744 * returns: 745 * - initrd_start and initrd_end are set to final (after relocation) ramdisk 746 * start/end addresses if ramdisk image start and len were provided 747 * otherwise set initrd_start and initrd_end set to zeros 748 * - returns: 749 * 0 - success 750 * -1 - failure 751 */ 752 int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, 753 ulong *initrd_start, ulong *initrd_end) 754 { 755 char *s; 756 ulong initrd_high; 757 int initrd_copy_to_ram = 1; 758 759 if ((s = getenv ("initrd_high")) != NULL) { 760 /* a value of "no" or a similar string will act like 0, 761 * turning the "load high" feature off. This is intentional. 762 */ 763 initrd_high = simple_strtoul (s, NULL, 16); 764 if (initrd_high == ~0) 765 initrd_copy_to_ram = 0; 766 } else { 767 /* not set, no restrictions to load high */ 768 initrd_high = ~0; 769 } 770 771 debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", 772 initrd_high, initrd_copy_to_ram); 773 774 if (rd_data) { 775 if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ 776 debug (" in-place initrd\n"); 777 *initrd_start = rd_data; 778 *initrd_end = rd_data + rd_len; 779 lmb_reserve(lmb, rd_data, rd_len); 780 } else { 781 if (initrd_high) 782 *initrd_start = lmb_alloc_base(lmb, rd_len, 0x1000, initrd_high); 783 else 784 *initrd_start = lmb_alloc(lmb, rd_len, 0x1000); 785 786 if (*initrd_start == 0) { 787 puts("ramdisk - allocation error\n"); 788 goto error; 789 } 790 show_boot_progress (12); 791 792 *initrd_end = *initrd_start + rd_len; 793 printf (" Loading Ramdisk to %08lx, end %08lx ... ", 794 *initrd_start, *initrd_end); 795 796 memmove_wd((void *)*initrd_start, 797 (void *)rd_data, rd_len, CHUNKSZ); 798 799 puts ("OK\n"); 800 } 801 } else { 802 *initrd_start = 0; 803 *initrd_end = 0; 804 } 805 debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", 806 *initrd_start, *initrd_end); 807 return 0; 808 809 error: 810 return -1; 811 } 812 813 /** 814 * get_boot_cmdline - allocate and initialize kernel cmdline 815 * @lmb: pointer to lmb handle, will be used for memory mgmt 816 * @cmd_start: pointer to a ulong variable, will hold cmdline start 817 * @cmd_end: pointer to a ulong variable, will hold cmdline end 818 * @bootmap_base: ulong variable, holds offset in physical memory to 819 * base of bootmap 820 * 821 * get_boot_cmdline() allocates space for kernel command line below 822 * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt 823 * variable is present its contents is copied to allocated kernel 824 * command line. 825 * 826 * returns: 827 * 0 - success 828 * -1 - failure 829 */ 830 int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, 831 ulong bootmap_base) 832 { 833 char *cmdline; 834 char *s; 835 836 cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, 837 CFG_BOOTMAPSZ + bootmap_base); 838 839 if (cmdline == NULL) 840 return -1; 841 842 if ((s = getenv("bootargs")) == NULL) 843 s = ""; 844 845 strcpy(cmdline, s); 846 847 *cmd_start = (ulong) & cmdline[0]; 848 *cmd_end = *cmd_start + strlen(cmdline); 849 850 debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); 851 852 return 0; 853 } 854 855 /** 856 * get_boot_kbd - allocate and initialize kernel copy of board info 857 * @lmb: pointer to lmb handle, will be used for memory mgmt 858 * @kbd: double pointer to board info data 859 * @bootmap_base: ulong variable, holds offset in physical memory to 860 * base of bootmap 861 * 862 * get_boot_kbd() allocates space for kernel copy of board info data below 863 * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with 864 * the current u-boot board info data. 865 * 866 * returns: 867 * 0 - success 868 * -1 - failure 869 */ 870 int get_boot_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) 871 { 872 *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, 873 CFG_BOOTMAPSZ + bootmap_base); 874 if (*kbd == NULL) 875 return -1; 876 877 **kbd = *(gd->bd); 878 879 debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); 880 881 #if defined(DEBUG) && defined(CONFIG_CMD_BDI) 882 do_bdinfo(NULL, 0, 0, NULL); 883 #endif 884 885 return 0; 886 } 887 #endif /* CONFIG_PPC || CONFIG_M68K */ 888 889 #if defined(CONFIG_FIT) 890 /*****************************************************************************/ 891 /* New uImage format routines */ 892 /*****************************************************************************/ 893 static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, 894 ulong *addr, const char **name) 895 { 896 const char *sep; 897 898 *addr = addr_curr; 899 *name = NULL; 900 901 sep = strchr (spec, sepc); 902 if (sep) { 903 if (sep - spec > 0) 904 *addr = simple_strtoul (spec, NULL, 16); 905 906 *name = sep + 1; 907 return 1; 908 } 909 910 return 0; 911 } 912 913 /** 914 * fit_parse_conf - parse FIT configuration spec 915 * @spec: input string, containing configuration spec 916 * @add_curr: current image address (to be used as a possible default) 917 * @addr: pointer to a ulong variable, will hold FIT image address of a given 918 * configuration 919 * @conf_name double pointer to a char, will hold pointer to a configuration 920 * unit name 921 * 922 * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>, 923 * where <addr> is a FIT image address that contains configuration 924 * with a <conf> unit name. 925 * 926 * Address part is optional, and if omitted default add_curr will 927 * be used instead. 928 * 929 * returns: 930 * 1 if spec is a valid configuration string, 931 * addr and conf_name are set accordingly 932 * 0 otherwise 933 */ 934 inline int fit_parse_conf (const char *spec, ulong addr_curr, 935 ulong *addr, const char **conf_name) 936 { 937 return fit_parse_spec (spec, '#', addr_curr, addr, conf_name); 938 } 939 940 /** 941 * fit_parse_subimage - parse FIT subimage spec 942 * @spec: input string, containing subimage spec 943 * @add_curr: current image address (to be used as a possible default) 944 * @addr: pointer to a ulong variable, will hold FIT image address of a given 945 * subimage 946 * @image_name: double pointer to a char, will hold pointer to a subimage name 947 * 948 * fit_parse_subimage() expects subimage spec in the for of 949 * [<addr>]:<subimage>, where <addr> is a FIT image address that contains 950 * subimage with a <subimg> unit name. 951 * 952 * Address part is optional, and if omitted default add_curr will 953 * be used instead. 954 * 955 * returns: 956 * 1 if spec is a valid subimage string, 957 * addr and image_name are set accordingly 958 * 0 otherwise 959 */ 960 inline int fit_parse_subimage (const char *spec, ulong addr_curr, 961 ulong *addr, const char **image_name) 962 { 963 return fit_parse_spec (spec, ':', addr_curr, addr, image_name); 964 } 965 966 #endif /* CONFIG_FIT */ 967 968 #endif /* USE_HOSTCC */ 969