uboot/common/cmd_bootm.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2009
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24
  25/*
  26 * Boot support
  27 */
  28#include <common.h>
  29#include <watchdog.h>
  30#include <command.h>
  31#include <image.h>
  32#include <malloc.h>
  33#include <u-boot/zlib.h>
  34#include <bzlib.h>
  35#include <environment.h>
  36#include <lmb.h>
  37#include <linux/ctype.h>
  38#include <asm/byteorder.h>
  39#include <linux/compiler.h>
  40
  41#if defined(CONFIG_CMD_USB)
  42#include <usb.h>
  43#endif
  44
  45#ifdef CONFIG_SYS_HUSH_PARSER
  46#include <hush.h>
  47#endif
  48
  49#if defined(CONFIG_OF_LIBFDT)
  50#include <fdt.h>
  51#include <libfdt.h>
  52#include <fdt_support.h>
  53#endif
  54
  55#ifdef CONFIG_LZMA
  56#include <lzma/LzmaTypes.h>
  57#include <lzma/LzmaDec.h>
  58#include <lzma/LzmaTools.h>
  59#endif /* CONFIG_LZMA */
  60
  61#ifdef CONFIG_LZO
  62#include <linux/lzo.h>
  63#endif /* CONFIG_LZO */
  64
  65DECLARE_GLOBAL_DATA_PTR;
  66
  67#ifndef CONFIG_SYS_BOOTM_LEN
  68#define CONFIG_SYS_BOOTM_LEN    0x800000        /* use 8MByte as default max gunzip size */
  69#endif
  70
  71#ifdef CONFIG_BZIP2
  72extern void bz_internal_error(int);
  73#endif
  74
  75#if defined(CONFIG_CMD_IMI)
  76static int image_info(unsigned long addr);
  77#endif
  78
  79#if defined(CONFIG_CMD_IMLS)
  80#include <flash.h>
  81#include <mtd/cfi_flash.h>
  82extern flash_info_t flash_info[]; /* info for FLASH chips */
  83static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
  84#endif
  85
  86#ifdef CONFIG_SILENT_CONSOLE
  87static void fixup_silent_linux(void);
  88#endif
  89
  90static image_header_t *image_get_kernel(ulong img_addr, int verify);
  91#if defined(CONFIG_FIT)
  92static int fit_check_kernel(const void *fit, int os_noffset, int verify);
  93#endif
  94
  95static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
  96                                char * const argv[], bootm_headers_t *images,
  97                                ulong *os_data, ulong *os_len);
  98
  99/*
 100 *  Continue booting an OS image; caller already has:
 101 *  - copied image header to global variable `header'
 102 *  - checked header magic number, checksums (both header & image),
 103 *  - verified image architecture (PPC) and type (KERNEL or MULTI),
 104 *  - loaded (first part of) image to header load address,
 105 *  - disabled interrupts.
 106 */
 107typedef int boot_os_fn(int flag, int argc, char * const argv[],
 108                        bootm_headers_t *images); /* pointers to os/initrd/fdt */
 109
 110#ifdef CONFIG_BOOTM_LINUX
 111extern boot_os_fn do_bootm_linux;
 112#endif
 113#ifdef CONFIG_BOOTM_NETBSD
 114static boot_os_fn do_bootm_netbsd;
 115#endif
 116#if defined(CONFIG_LYNXKDI)
 117static boot_os_fn do_bootm_lynxkdi;
 118extern void lynxkdi_boot(image_header_t *);
 119#endif
 120#ifdef CONFIG_BOOTM_RTEMS
 121static boot_os_fn do_bootm_rtems;
 122#endif
 123#if defined(CONFIG_BOOTM_OSE)
 124static boot_os_fn do_bootm_ose;
 125#endif
 126#if defined(CONFIG_CMD_ELF)
 127static boot_os_fn do_bootm_vxworks;
 128static boot_os_fn do_bootm_qnxelf;
 129int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 130int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 131#endif
 132#if defined(CONFIG_INTEGRITY)
 133static boot_os_fn do_bootm_integrity;
 134#endif
 135
 136static boot_os_fn *boot_os[] = {
 137#ifdef CONFIG_BOOTM_LINUX
 138        [IH_OS_LINUX] = do_bootm_linux,
 139#endif
 140#ifdef CONFIG_BOOTM_NETBSD
 141        [IH_OS_NETBSD] = do_bootm_netbsd,
 142#endif
 143#ifdef CONFIG_LYNXKDI
 144        [IH_OS_LYNXOS] = do_bootm_lynxkdi,
 145#endif
 146#ifdef CONFIG_BOOTM_RTEMS
 147        [IH_OS_RTEMS] = do_bootm_rtems,
 148#endif
 149#if defined(CONFIG_BOOTM_OSE)
 150        [IH_OS_OSE] = do_bootm_ose,
 151#endif
 152#if defined(CONFIG_CMD_ELF)
 153        [IH_OS_VXWORKS] = do_bootm_vxworks,
 154        [IH_OS_QNX] = do_bootm_qnxelf,
 155#endif
 156#ifdef CONFIG_INTEGRITY
 157        [IH_OS_INTEGRITY] = do_bootm_integrity,
 158#endif
 159};
 160
 161bootm_headers_t images;         /* pointers to os/initrd/fdt images */
 162
 163/* Allow for arch specific config before we boot */
 164void __arch_preboot_os(void)
 165{
 166        /* please define platform specific arch_preboot_os() */
 167}
 168void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
 169
 170#define IH_INITRD_ARCH IH_ARCH_DEFAULT
 171
 172#ifdef CONFIG_LMB
 173static void boot_start_lmb(bootm_headers_t *images)
 174{
 175        ulong           mem_start;
 176        phys_size_t     mem_size;
 177
 178        lmb_init(&images->lmb);
 179
 180        mem_start = getenv_bootm_low();
 181        mem_size = getenv_bootm_size();
 182
 183        lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
 184
 185        arch_lmb_reserve(&images->lmb);
 186        board_lmb_reserve(&images->lmb);
 187}
 188#else
 189#define lmb_reserve(lmb, base, size)
 190static inline void boot_start_lmb(bootm_headers_t *images) { }
 191#endif
 192
 193static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 194{
 195        void            *os_hdr;
 196        int             ret;
 197
 198        memset((void *)&images, 0, sizeof(images));
 199        images.verify = getenv_yesno("verify");
 200
 201        boot_start_lmb(&images);
 202
 203        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
 204
 205        /* get kernel image header, start address and length */
 206        os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
 207                        &images, &images.os.image_start, &images.os.image_len);
 208        if (images.os.image_len == 0) {
 209                puts("ERROR: can't get kernel image!\n");
 210                return 1;
 211        }
 212
 213        /* get image parameters */
 214        switch (genimg_get_format(os_hdr)) {
 215        case IMAGE_FORMAT_LEGACY:
 216                images.os.type = image_get_type(os_hdr);
 217                images.os.comp = image_get_comp(os_hdr);
 218                images.os.os = image_get_os(os_hdr);
 219
 220                images.os.end = image_get_image_end(os_hdr);
 221                images.os.load = image_get_load(os_hdr);
 222                break;
 223#if defined(CONFIG_FIT)
 224        case IMAGE_FORMAT_FIT:
 225                if (fit_image_get_type(images.fit_hdr_os,
 226                                        images.fit_noffset_os, &images.os.type)) {
 227                        puts("Can't get image type!\n");
 228                        bootstage_error(BOOTSTAGE_ID_FIT_TYPE);
 229                        return 1;
 230                }
 231
 232                if (fit_image_get_comp(images.fit_hdr_os,
 233                                        images.fit_noffset_os, &images.os.comp)) {
 234                        puts("Can't get image compression!\n");
 235                        bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION);
 236                        return 1;
 237                }
 238
 239                if (fit_image_get_os(images.fit_hdr_os,
 240                                        images.fit_noffset_os, &images.os.os)) {
 241                        puts("Can't get image OS!\n");
 242                        bootstage_error(BOOTSTAGE_ID_FIT_OS);
 243                        return 1;
 244                }
 245
 246                images.os.end = fit_get_end(images.fit_hdr_os);
 247
 248                if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
 249                                        &images.os.load)) {
 250                        puts("Can't get image load address!\n");
 251                        bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR);
 252                        return 1;
 253                }
 254                break;
 255#endif
 256        default:
 257                puts("ERROR: unknown image format type!\n");
 258                return 1;
 259        }
 260
 261        /* find kernel entry point */
 262        if (images.legacy_hdr_valid) {
 263                images.ep = image_get_ep(&images.legacy_hdr_os_copy);
 264#if defined(CONFIG_FIT)
 265        } else if (images.fit_uname_os) {
 266                ret = fit_image_get_entry(images.fit_hdr_os,
 267                                images.fit_noffset_os, &images.ep);
 268                if (ret) {
 269                        puts("Can't get entry point property!\n");
 270                        return 1;
 271                }
 272#endif
 273        } else {
 274                puts("Could not find kernel entry point!\n");
 275                return 1;
 276        }
 277
 278        if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
 279                images.os.load = images.os.image_start;
 280                images.ep += images.os.load;
 281        }
 282
 283        if (((images.os.type == IH_TYPE_KERNEL) ||
 284             (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
 285             (images.os.type == IH_TYPE_MULTI)) &&
 286            (images.os.os == IH_OS_LINUX)) {
 287                /* find ramdisk */
 288                ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
 289                                &images.rd_start, &images.rd_end);
 290                if (ret) {
 291                        puts("Ramdisk image is corrupt or invalid\n");
 292                        return 1;
 293                }
 294
 295#if defined(CONFIG_OF_LIBFDT)
 296                /* find flattened device tree */
 297                ret = boot_get_fdt(flag, argc, argv, &images,
 298                                   &images.ft_addr, &images.ft_len);
 299                if (ret) {
 300                        puts("Could not find a valid device tree\n");
 301                        return 1;
 302                }
 303
 304                set_working_fdt_addr(images.ft_addr);
 305#endif
 306        }
 307
 308        images.os.start = (ulong)os_hdr;
 309        images.state = BOOTM_STATE_START;
 310
 311        return 0;
 312}
 313
 314#define BOOTM_ERR_RESET         -1
 315#define BOOTM_ERR_OVERLAP       -2
 316#define BOOTM_ERR_UNIMPLEMENTED -3
 317static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
 318{
 319        uint8_t comp = os.comp;
 320        ulong load = os.load;
 321        ulong blob_start = os.start;
 322        ulong blob_end = os.end;
 323        ulong image_start = os.image_start;
 324        ulong image_len = os.image_len;
 325        __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN;
 326        int no_overlap = 0;
 327#if defined(CONFIG_LZMA) || defined(CONFIG_LZO)
 328        int ret;
 329#endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */
 330
 331        const char *type_name = genimg_get_type_name(os.type);
 332
 333        switch (comp) {
 334        case IH_COMP_NONE:
 335                if (load == blob_start || load == image_start) {
 336                        printf("   XIP %s ... ", type_name);
 337                        no_overlap = 1;
 338                } else {
 339                        printf("   Loading %s ... ", type_name);
 340                        memmove_wd((void *)load, (void *)image_start,
 341                                        image_len, CHUNKSZ);
 342                }
 343                *load_end = load + image_len;
 344                puts("OK\n");
 345                break;
 346#ifdef CONFIG_GZIP
 347        case IH_COMP_GZIP:
 348                printf("   Uncompressing %s ... ", type_name);
 349                if (gunzip((void *)load, unc_len,
 350                                (uchar *)image_start, &image_len) != 0) {
 351                        puts("GUNZIP: uncompress, out-of-mem or overwrite "
 352                                "error - must RESET board to recover\n");
 353                        if (boot_progress)
 354                                bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
 355                        return BOOTM_ERR_RESET;
 356                }
 357
 358                *load_end = load + image_len;
 359                break;
 360#endif /* CONFIG_GZIP */
 361#ifdef CONFIG_BZIP2
 362        case IH_COMP_BZIP2:
 363                printf("   Uncompressing %s ... ", type_name);
 364                /*
 365                 * If we've got less than 4 MB of malloc() space,
 366                 * use slower decompression algorithm which requires
 367                 * at most 2300 KB of memory.
 368                 */
 369                int i = BZ2_bzBuffToBuffDecompress((char *)load,
 370                                        &unc_len, (char *)image_start, image_len,
 371                                        CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
 372                if (i != BZ_OK) {
 373                        printf("BUNZIP2: uncompress or overwrite error %d "
 374                                "- must RESET board to recover\n", i);
 375                        if (boot_progress)
 376                                bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
 377                        return BOOTM_ERR_RESET;
 378                }
 379
 380                *load_end = load + unc_len;
 381                break;
 382#endif /* CONFIG_BZIP2 */
 383#ifdef CONFIG_LZMA
 384        case IH_COMP_LZMA: {
 385                SizeT lzma_len = unc_len;
 386                printf("   Uncompressing %s ... ", type_name);
 387
 388                ret = lzmaBuffToBuffDecompress(
 389                        (unsigned char *)load, &lzma_len,
 390                        (unsigned char *)image_start, image_len);
 391                unc_len = lzma_len;
 392                if (ret != SZ_OK) {
 393                        printf("LZMA: uncompress or overwrite error %d "
 394                                "- must RESET board to recover\n", ret);
 395                        bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
 396                        return BOOTM_ERR_RESET;
 397                }
 398                *load_end = load + unc_len;
 399                break;
 400        }
 401#endif /* CONFIG_LZMA */
 402#ifdef CONFIG_LZO
 403        case IH_COMP_LZO:
 404                printf("   Uncompressing %s ... ", type_name);
 405
 406                ret = lzop_decompress((const unsigned char *)image_start,
 407                                          image_len, (unsigned char *)load,
 408                                          &unc_len);
 409                if (ret != LZO_E_OK) {
 410                        printf("LZO: uncompress or overwrite error %d "
 411                              "- must RESET board to recover\n", ret);
 412                        if (boot_progress)
 413                                bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
 414                        return BOOTM_ERR_RESET;
 415                }
 416
 417                *load_end = load + unc_len;
 418                break;
 419#endif /* CONFIG_LZO */
 420        default:
 421                printf("Unimplemented compression type %d\n", comp);
 422                return BOOTM_ERR_UNIMPLEMENTED;
 423        }
 424
 425        flush_cache(load, (*load_end - load) * sizeof(ulong));
 426
 427        puts("OK\n");
 428        debug("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end);
 429        bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
 430
 431        if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) {
 432                debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
 433                        blob_start, blob_end);
 434                debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
 435                        *load_end);
 436
 437                return BOOTM_ERR_OVERLAP;
 438        }
 439
 440        return 0;
 441}
 442
 443static int bootm_start_standalone(ulong iflag, int argc, char * const argv[])
 444{
 445        char  *s;
 446        int   (*appl)(int, char * const []);
 447
 448        /* Don't start if "autostart" is set to "no" */
 449        if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) {
 450                char buf[32];
 451                sprintf(buf, "%lX", images.os.image_len);
 452                setenv("filesize", buf);
 453                return 0;
 454        }
 455        appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
 456        (*appl)(argc-1, &argv[1]);
 457        return 0;
 458}
 459
 460/* we overload the cmd field with our state machine info instead of a
 461 * function pointer */
 462static cmd_tbl_t cmd_bootm_sub[] = {
 463        U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
 464        U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
 465#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 466        U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
 467#endif
 468#ifdef CONFIG_OF_LIBFDT
 469        U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
 470#endif
 471        U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
 472        U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
 473        U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
 474        U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
 475};
 476
 477int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
 478                        char * const argv[])
 479{
 480        int ret = 0;
 481        long state;
 482        cmd_tbl_t *c;
 483        boot_os_fn *boot_fn;
 484
 485        c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
 486
 487        if (c) {
 488                state = (long)c->cmd;
 489
 490                /* treat start special since it resets the state machine */
 491                if (state == BOOTM_STATE_START) {
 492                        argc--;
 493                        argv++;
 494                        return bootm_start(cmdtp, flag, argc, argv);
 495                }
 496        } else {
 497                /* Unrecognized command */
 498                return CMD_RET_USAGE;
 499        }
 500
 501        if (images.state >= state) {
 502                printf("Trying to execute a command out of order\n");
 503                return CMD_RET_USAGE;
 504        }
 505
 506        images.state |= state;
 507        boot_fn = boot_os[images.os.os];
 508
 509        switch (state) {
 510                ulong load_end;
 511                case BOOTM_STATE_START:
 512                        /* should never occur */
 513                        break;
 514                case BOOTM_STATE_LOADOS:
 515                        ret = bootm_load_os(images.os, &load_end, 0);
 516                        if (ret)
 517                                return ret;
 518
 519                        lmb_reserve(&images.lmb, images.os.load,
 520                                        (load_end - images.os.load));
 521                        break;
 522#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 523                case BOOTM_STATE_RAMDISK:
 524                {
 525                        ulong rd_len = images.rd_end - images.rd_start;
 526                        char str[17];
 527
 528                        ret = boot_ramdisk_high(&images.lmb, images.rd_start,
 529                                rd_len, &images.initrd_start, &images.initrd_end);
 530                        if (ret)
 531                                return ret;
 532
 533                        sprintf(str, "%lx", images.initrd_start);
 534                        setenv("initrd_start", str);
 535                        sprintf(str, "%lx", images.initrd_end);
 536                        setenv("initrd_end", str);
 537                }
 538                        break;
 539#endif
 540#if defined(CONFIG_OF_LIBFDT)
 541                case BOOTM_STATE_FDT:
 542                {
 543                        boot_fdt_add_mem_rsv_regions(&images.lmb,
 544                                                     images.ft_addr);
 545                        ret = boot_relocate_fdt(&images.lmb,
 546                                &images.ft_addr, &images.ft_len);
 547                        break;
 548                }
 549#endif
 550                case BOOTM_STATE_OS_CMDLINE:
 551                        ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images);
 552                        if (ret)
 553                                printf("cmdline subcommand not supported\n");
 554                        break;
 555                case BOOTM_STATE_OS_BD_T:
 556                        ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images);
 557                        if (ret)
 558                                printf("bdt subcommand not supported\n");
 559                        break;
 560                case BOOTM_STATE_OS_PREP:
 561                        ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images);
 562                        if (ret)
 563                                printf("prep subcommand not supported\n");
 564                        break;
 565                case BOOTM_STATE_OS_GO:
 566                        disable_interrupts();
 567#ifdef CONFIG_NETCONSOLE
 568                        /*
 569                         * Stop the ethernet stack if NetConsole could have
 570                         * left it up
 571                         */
 572                        eth_halt();
 573#endif
 574                        arch_preboot_os();
 575                        boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
 576                        break;
 577        }
 578
 579        return ret;
 580}
 581
 582/*******************************************************************/
 583/* bootm - boot application image from image in memory */
 584/*******************************************************************/
 585
 586int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 587{
 588        ulong           iflag;
 589        ulong           load_end = 0;
 590        int             ret;
 591        boot_os_fn      *boot_fn;
 592#ifdef CONFIG_NEEDS_MANUAL_RELOC
 593        static int relocated = 0;
 594
 595        /* relocate boot function table */
 596        if (!relocated) {
 597                int i;
 598                for (i = 0; i < ARRAY_SIZE(boot_os); i++)
 599                        if (boot_os[i] != NULL)
 600                                boot_os[i] += gd->reloc_off;
 601                relocated = 1;
 602        }
 603#endif
 604
 605        /* determine if we have a sub command */
 606        if (argc > 1) {
 607                char *endp;
 608
 609                simple_strtoul(argv[1], &endp, 16);
 610                /* endp pointing to NULL means that argv[1] was just a
 611                 * valid number, pass it along to the normal bootm processing
 612                 *
 613                 * If endp is ':' or '#' assume a FIT identifier so pass
 614                 * along for normal processing.
 615                 *
 616                 * Right now we assume the first arg should never be '-'
 617                 */
 618                if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
 619                        return do_bootm_subcommand(cmdtp, flag, argc, argv);
 620        }
 621
 622        if (bootm_start(cmdtp, flag, argc, argv))
 623                return 1;
 624
 625        /*
 626         * We have reached the point of no return: we are going to
 627         * overwrite all exception vector code, so we cannot easily
 628         * recover from any failures any more...
 629         */
 630        iflag = disable_interrupts();
 631
 632#ifdef CONFIG_NETCONSOLE
 633        /* Stop the ethernet stack if NetConsole could have left it up */
 634        eth_halt();
 635#endif
 636
 637#if defined(CONFIG_CMD_USB)
 638        /*
 639         * turn off USB to prevent the host controller from writing to the
 640         * SDRAM while Linux is booting. This could happen (at least for OHCI
 641         * controller), because the HCCA (Host Controller Communication Area)
 642         * lies within the SDRAM and the host controller writes continously to
 643         * this area (as busmaster!). The HccaFrameNumber is for example
 644         * updated every 1 ms within the HCCA structure in SDRAM! For more
 645         * details see the OpenHCI specification.
 646         */
 647        usb_stop();
 648#endif
 649
 650        ret = bootm_load_os(images.os, &load_end, 1);
 651
 652        if (ret < 0) {
 653                if (ret == BOOTM_ERR_RESET)
 654                        do_reset(cmdtp, flag, argc, argv);
 655                if (ret == BOOTM_ERR_OVERLAP) {
 656                        if (images.legacy_hdr_valid) {
 657                                image_header_t *hdr;
 658                                hdr = &images.legacy_hdr_os_copy;
 659                                if (image_get_type(hdr) == IH_TYPE_MULTI)
 660                                        puts("WARNING: legacy format multi "
 661                                                "component image "
 662                                                "overwritten\n");
 663                        } else {
 664                                puts("ERROR: new format image overwritten - "
 665                                        "must RESET the board to recover\n");
 666                                bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
 667                                do_reset(cmdtp, flag, argc, argv);
 668                        }
 669                }
 670                if (ret == BOOTM_ERR_UNIMPLEMENTED) {
 671                        if (iflag)
 672                                enable_interrupts();
 673                        bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
 674                        return 1;
 675                }
 676        }
 677
 678        lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
 679
 680        if (images.os.type == IH_TYPE_STANDALONE) {
 681                if (iflag)
 682                        enable_interrupts();
 683                /* This may return when 'autostart' is 'no' */
 684                bootm_start_standalone(iflag, argc, argv);
 685                return 0;
 686        }
 687
 688        bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS);
 689
 690#ifdef CONFIG_SILENT_CONSOLE
 691        if (images.os.os == IH_OS_LINUX)
 692                fixup_silent_linux();
 693#endif
 694
 695        boot_fn = boot_os[images.os.os];
 696
 697        if (boot_fn == NULL) {
 698                if (iflag)
 699                        enable_interrupts();
 700                printf("ERROR: booting os '%s' (%d) is not supported\n",
 701                        genimg_get_os_name(images.os.os), images.os.os);
 702                bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
 703                return 1;
 704        }
 705
 706        arch_preboot_os();
 707
 708        boot_fn(0, argc, argv, &images);
 709
 710        bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
 711#ifdef DEBUG
 712        puts("\n## Control returned to monitor - resetting...\n");
 713#endif
 714        do_reset(cmdtp, flag, argc, argv);
 715
 716        return 1;
 717}
 718
 719int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
 720{
 721        const char *ep = getenv("autostart");
 722
 723        if (ep && !strcmp(ep, "yes")) {
 724                char *local_args[2];
 725                local_args[0] = (char *)cmd;
 726                local_args[1] = NULL;
 727                printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
 728                return do_bootm(cmdtp, 0, 1, local_args);
 729        }
 730
 731        return 0;
 732}
 733
 734/**
 735 * image_get_kernel - verify legacy format kernel image
 736 * @img_addr: in RAM address of the legacy format image to be verified
 737 * @verify: data CRC verification flag
 738 *
 739 * image_get_kernel() verifies legacy image integrity and returns pointer to
 740 * legacy image header if image verification was completed successfully.
 741 *
 742 * returns:
 743 *     pointer to a legacy image header if valid image was found
 744 *     otherwise return NULL
 745 */
 746static image_header_t *image_get_kernel(ulong img_addr, int verify)
 747{
 748        image_header_t *hdr = (image_header_t *)img_addr;
 749
 750        if (!image_check_magic(hdr)) {
 751                puts("Bad Magic Number\n");
 752                bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC);
 753                return NULL;
 754        }
 755        bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER);
 756
 757        if (!image_check_hcrc(hdr)) {
 758                puts("Bad Header Checksum\n");
 759                bootstage_error(BOOTSTAGE_ID_CHECK_HEADER);
 760                return NULL;
 761        }
 762
 763        bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM);
 764        image_print_contents(hdr);
 765
 766        if (verify) {
 767                puts("   Verifying Checksum ... ");
 768                if (!image_check_dcrc(hdr)) {
 769                        printf("Bad Data CRC\n");
 770                        bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM);
 771                        return NULL;
 772                }
 773                puts("OK\n");
 774        }
 775        bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH);
 776
 777        if (!image_check_target_arch(hdr)) {
 778                printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr));
 779                bootstage_error(BOOTSTAGE_ID_CHECK_ARCH);
 780                return NULL;
 781        }
 782        return hdr;
 783}
 784
 785/**
 786 * fit_check_kernel - verify FIT format kernel subimage
 787 * @fit_hdr: pointer to the FIT image header
 788 * os_noffset: kernel subimage node offset within FIT image
 789 * @verify: data CRC verification flag
 790 *
 791 * fit_check_kernel() verifies integrity of the kernel subimage and from
 792 * specified FIT image.
 793 *
 794 * returns:
 795 *     1, on success
 796 *     0, on failure
 797 */
 798#if defined(CONFIG_FIT)
 799static int fit_check_kernel(const void *fit, int os_noffset, int verify)
 800{
 801        fit_image_print(fit, os_noffset, "   ");
 802
 803        if (verify) {
 804                puts("   Verifying Hash Integrity ... ");
 805                if (!fit_image_check_hashes(fit, os_noffset)) {
 806                        puts("Bad Data Hash\n");
 807                        bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH);
 808                        return 0;
 809                }
 810                puts("OK\n");
 811        }
 812        bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH);
 813
 814        if (!fit_image_check_target_arch(fit, os_noffset)) {
 815                puts("Unsupported Architecture\n");
 816                bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH);
 817                return 0;
 818        }
 819
 820        bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL);
 821        if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) &&
 822            !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) {
 823                puts("Not a kernel image\n");
 824                bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL);
 825                return 0;
 826        }
 827
 828        bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED);
 829        return 1;
 830}
 831#endif /* CONFIG_FIT */
 832
 833/**
 834 * boot_get_kernel - find kernel image
 835 * @os_data: pointer to a ulong variable, will hold os data start address
 836 * @os_len: pointer to a ulong variable, will hold os data length
 837 *
 838 * boot_get_kernel() tries to find a kernel image, verifies its integrity
 839 * and locates kernel data.
 840 *
 841 * returns:
 842 *     pointer to image header if valid image was found, plus kernel start
 843 *     address and length, otherwise NULL
 844 */
 845static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 846                char * const argv[], bootm_headers_t *images, ulong *os_data,
 847                ulong *os_len)
 848{
 849        image_header_t  *hdr;
 850        ulong           img_addr;
 851#if defined(CONFIG_FIT)
 852        void            *fit_hdr;
 853        const char      *fit_uname_config = NULL;
 854        const char      *fit_uname_kernel = NULL;
 855        const void      *data;
 856        size_t          len;
 857        int             cfg_noffset;
 858        int             os_noffset;
 859#endif
 860
 861        /* find out kernel image address */
 862        if (argc < 2) {
 863                img_addr = load_addr;
 864                debug("*  kernel: default image load address = 0x%08lx\n",
 865                                load_addr);
 866#if defined(CONFIG_FIT)
 867        } else if (fit_parse_conf(argv[1], load_addr, &img_addr,
 868                                                        &fit_uname_config)) {
 869                debug("*  kernel: config '%s' from image at 0x%08lx\n",
 870                                fit_uname_config, img_addr);
 871        } else if (fit_parse_subimage(argv[1], load_addr, &img_addr,
 872                                                        &fit_uname_kernel)) {
 873                debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
 874                                fit_uname_kernel, img_addr);
 875#endif
 876        } else {
 877                img_addr = simple_strtoul(argv[1], NULL, 16);
 878                debug("*  kernel: cmdline image address = 0x%08lx\n", img_addr);
 879        }
 880
 881        bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
 882
 883        /* copy from dataflash if needed */
 884        img_addr = genimg_get_image(img_addr);
 885
 886        /* check image type, for FIT images get FIT kernel node */
 887        *os_data = *os_len = 0;
 888        switch (genimg_get_format((void *)img_addr)) {
 889        case IMAGE_FORMAT_LEGACY:
 890                printf("## Booting kernel from Legacy Image at %08lx ...\n",
 891                                img_addr);
 892                hdr = image_get_kernel(img_addr, images->verify);
 893                if (!hdr)
 894                        return NULL;
 895                bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE);
 896
 897                /* get os_data and os_len */
 898                switch (image_get_type(hdr)) {
 899                case IH_TYPE_KERNEL:
 900                case IH_TYPE_KERNEL_NOLOAD:
 901                        *os_data = image_get_data(hdr);
 902                        *os_len = image_get_data_size(hdr);
 903                        break;
 904                case IH_TYPE_MULTI:
 905                        image_multi_getimg(hdr, 0, os_data, os_len);
 906                        break;
 907                case IH_TYPE_STANDALONE:
 908                        *os_data = image_get_data(hdr);
 909                        *os_len = image_get_data_size(hdr);
 910                        break;
 911                default:
 912                        printf("Wrong Image Type for %s command\n",
 913                                cmdtp->name);
 914                        bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
 915                        return NULL;
 916                }
 917
 918                /*
 919                 * copy image header to allow for image overwrites during
 920                 * kernel decompression.
 921                 */
 922                memmove(&images->legacy_hdr_os_copy, hdr,
 923                        sizeof(image_header_t));
 924
 925                /* save pointer to image header */
 926                images->legacy_hdr_os = hdr;
 927
 928                images->legacy_hdr_valid = 1;
 929                bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
 930                break;
 931#if defined(CONFIG_FIT)
 932        case IMAGE_FORMAT_FIT:
 933                fit_hdr = (void *)img_addr;
 934                printf("## Booting kernel from FIT Image at %08lx ...\n",
 935                                img_addr);
 936
 937                if (!fit_check_format(fit_hdr)) {
 938                        puts("Bad FIT kernel image format!\n");
 939                        bootstage_error(BOOTSTAGE_ID_FIT_FORMAT);
 940                        return NULL;
 941                }
 942                bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT);
 943
 944                if (!fit_uname_kernel) {
 945                        /*
 946                         * no kernel image node unit name, try to get config
 947                         * node first. If config unit node name is NULL
 948                         * fit_conf_get_node() will try to find default config
 949                         * node
 950                         */
 951                        bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
 952                        cfg_noffset = fit_conf_get_node(fit_hdr,
 953                                                        fit_uname_config);
 954                        if (cfg_noffset < 0) {
 955                                bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
 956                                return NULL;
 957                        }
 958                        /* save configuration uname provided in the first
 959                         * bootm argument
 960                         */
 961                        images->fit_uname_cfg = fdt_get_name(fit_hdr,
 962                                                                cfg_noffset,
 963                                                                NULL);
 964                        printf("   Using '%s' configuration\n",
 965                                images->fit_uname_cfg);
 966                        bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
 967
 968                        os_noffset = fit_conf_get_kernel_node(fit_hdr,
 969                                                                cfg_noffset);
 970                        fit_uname_kernel = fit_get_name(fit_hdr, os_noffset,
 971                                                        NULL);
 972                } else {
 973                        /* get kernel component image node offset */
 974                        bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME);
 975                        os_noffset = fit_image_get_node(fit_hdr,
 976                                                        fit_uname_kernel);
 977                }
 978                if (os_noffset < 0) {
 979                        bootstage_error(BOOTSTAGE_ID_FIT_CONFIG);
 980                        return NULL;
 981                }
 982
 983                printf("   Trying '%s' kernel subimage\n", fit_uname_kernel);
 984
 985                bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE);
 986                if (!fit_check_kernel(fit_hdr, os_noffset, images->verify))
 987                        return NULL;
 988
 989                /* get kernel image data address and length */
 990                if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) {
 991                        puts("Could not find kernel subimage data!\n");
 992                        bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR);
 993                        return NULL;
 994                }
 995                bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO);
 996
 997                *os_len = len;
 998                *os_data = (ulong)data;
 999                images->fit_hdr_os = fit_hdr;
1000                images->fit_uname_os = fit_uname_kernel;
1001                images->fit_noffset_os = os_noffset;
1002                break;
1003#endif
1004        default:
1005                printf("Wrong Image Format for %s command\n", cmdtp->name);
1006                bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
1007                return NULL;
1008        }
1009
1010        debug("   kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
1011                        *os_data, *os_len, *os_len);
1012
1013        return (void *)img_addr;
1014}
1015
1016U_BOOT_CMD(
1017        bootm,  CONFIG_SYS_MAXARGS,     1,      do_bootm,
1018        "boot application image from memory",
1019        "[addr [arg ...]]\n    - boot application image stored in memory\n"
1020        "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
1021        "\t'arg' can be the address of an initrd image\n"
1022#if defined(CONFIG_OF_LIBFDT)
1023        "\tWhen booting a Linux kernel which requires a flat device-tree\n"
1024        "\ta third argument is required which is the address of the\n"
1025        "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
1026        "\tuse a '-' for the second argument. If you do not pass a third\n"
1027        "\ta bd_info struct will be passed instead\n"
1028#endif
1029#if defined(CONFIG_FIT)
1030        "\t\nFor the new multi component uImage format (FIT) addresses\n"
1031        "\tmust be extened to include component or configuration unit name:\n"
1032        "\taddr:<subimg_uname> - direct component image specification\n"
1033        "\taddr#<conf_uname>   - configuration specification\n"
1034        "\tUse iminfo command to get the list of existing component\n"
1035        "\timages and configurations.\n"
1036#endif
1037        "\nSub-commands to do part of the bootm sequence.  The sub-commands "
1038        "must be\n"
1039        "issued in the order below (it's ok to not issue all sub-commands):\n"
1040        "\tstart [addr [arg ...]]\n"
1041        "\tloados  - load OS image\n"
1042#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
1043        "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
1044#endif
1045#if defined(CONFIG_OF_LIBFDT)
1046        "\tfdt     - relocate flat device tree\n"
1047#endif
1048        "\tcmdline - OS specific command line processing/setup\n"
1049        "\tbdt     - OS specific bd_t processing\n"
1050        "\tprep    - OS specific prep before relocation or go\n"
1051        "\tgo      - start OS"
1052);
1053
1054/*******************************************************************/
1055/* bootd - boot default image */
1056/*******************************************************************/
1057#if defined(CONFIG_CMD_BOOTD)
1058int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1059{
1060        int rcode = 0;
1061
1062        if (run_command(getenv("bootcmd"), flag) < 0)
1063                rcode = 1;
1064        return rcode;
1065}
1066
1067U_BOOT_CMD(
1068        boot,   1,      1,      do_bootd,
1069        "boot default, i.e., run 'bootcmd'",
1070        ""
1071);
1072
1073/* keep old command name "bootd" for backward compatibility */
1074U_BOOT_CMD(
1075        bootd, 1,       1,      do_bootd,
1076        "boot default, i.e., run 'bootcmd'",
1077        ""
1078);
1079
1080#endif
1081
1082
1083/*******************************************************************/
1084/* iminfo - print header info for a requested image */
1085/*******************************************************************/
1086#if defined(CONFIG_CMD_IMI)
1087int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1088{
1089        int     arg;
1090        ulong   addr;
1091        int     rcode = 0;
1092
1093        if (argc < 2) {
1094                return image_info(load_addr);
1095        }
1096
1097        for (arg = 1; arg < argc; ++arg) {
1098                addr = simple_strtoul(argv[arg], NULL, 16);
1099                if (image_info(addr) != 0)
1100                        rcode = 1;
1101        }
1102        return rcode;
1103}
1104
1105static int image_info(ulong addr)
1106{
1107        void *hdr = (void *)addr;
1108
1109        printf("\n## Checking Image at %08lx ...\n", addr);
1110
1111        switch (genimg_get_format(hdr)) {
1112        case IMAGE_FORMAT_LEGACY:
1113                puts("   Legacy image found\n");
1114                if (!image_check_magic(hdr)) {
1115                        puts("   Bad Magic Number\n");
1116                        return 1;
1117                }
1118
1119                if (!image_check_hcrc(hdr)) {
1120                        puts("   Bad Header Checksum\n");
1121                        return 1;
1122                }
1123
1124                image_print_contents(hdr);
1125
1126                puts("   Verifying Checksum ... ");
1127                if (!image_check_dcrc(hdr)) {
1128                        puts("   Bad Data CRC\n");
1129                        return 1;
1130                }
1131                puts("OK\n");
1132                return 0;
1133#if defined(CONFIG_FIT)
1134        case IMAGE_FORMAT_FIT:
1135                puts("   FIT image found\n");
1136
1137                if (!fit_check_format(hdr)) {
1138                        puts("Bad FIT image format!\n");
1139                        return 1;
1140                }
1141
1142                fit_print_contents(hdr);
1143
1144                if (!fit_all_image_check_hashes(hdr)) {
1145                        puts("Bad hash in FIT image!\n");
1146                        return 1;
1147                }
1148
1149                return 0;
1150#endif
1151        default:
1152                puts("Unknown image format!\n");
1153                break;
1154        }
1155
1156        return 1;
1157}
1158
1159U_BOOT_CMD(
1160        iminfo, CONFIG_SYS_MAXARGS,     1,      do_iminfo,
1161        "print header information for application image",
1162        "addr [addr ...]\n"
1163        "    - print header information for application image starting at\n"
1164        "      address 'addr' in memory; this includes verification of the\n"
1165        "      image contents (magic number, header and payload checksums)"
1166);
1167#endif
1168
1169
1170/*******************************************************************/
1171/* imls - list all images found in flash */
1172/*******************************************************************/
1173#if defined(CONFIG_CMD_IMLS)
1174int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1175{
1176        flash_info_t *info;
1177        int i, j;
1178        void *hdr;
1179
1180        for (i = 0, info = &flash_info[0];
1181                i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
1182
1183                if (info->flash_id == FLASH_UNKNOWN)
1184                        goto next_bank;
1185                for (j = 0; j < info->sector_count; ++j) {
1186
1187                        hdr = (void *)info->start[j];
1188                        if (!hdr)
1189                                goto next_sector;
1190
1191                        switch (genimg_get_format(hdr)) {
1192                        case IMAGE_FORMAT_LEGACY:
1193                                if (!image_check_hcrc(hdr))
1194                                        goto next_sector;
1195
1196                                printf("Legacy Image at %08lX:\n", (ulong)hdr);
1197                                image_print_contents(hdr);
1198
1199                                puts("   Verifying Checksum ... ");
1200                                if (!image_check_dcrc(hdr)) {
1201                                        puts("Bad Data CRC\n");
1202                                } else {
1203                                        puts("OK\n");
1204                                }
1205                                break;
1206#if defined(CONFIG_FIT)
1207                        case IMAGE_FORMAT_FIT:
1208                                if (!fit_check_format(hdr))
1209                                        goto next_sector;
1210
1211                                printf("FIT Image at %08lX:\n", (ulong)hdr);
1212                                fit_print_contents(hdr);
1213                                break;
1214#endif
1215                        default:
1216                                goto next_sector;
1217                        }
1218
1219next_sector:            ;
1220                }
1221next_bank:      ;
1222        }
1223
1224        return (0);
1225}
1226
1227U_BOOT_CMD(
1228        imls,   1,              1,      do_imls,
1229        "list all images found in flash",
1230        "\n"
1231        "    - Prints information about all images found at sector\n"
1232        "      boundaries in flash."
1233);
1234#endif
1235
1236/*******************************************************************/
1237/* helper routines */
1238/*******************************************************************/
1239#ifdef CONFIG_SILENT_CONSOLE
1240static void fixup_silent_linux(void)
1241{
1242        char buf[256], *start, *end;
1243        char *cmdline = getenv("bootargs");
1244
1245        /* Only fix cmdline when requested */
1246        if (!(gd->flags & GD_FLG_SILENT))
1247                return;
1248
1249        debug("before silent fix-up: %s\n", cmdline);
1250        if (cmdline) {
1251                start = strstr(cmdline, "console=");
1252                if (start) {
1253                        end = strchr(start, ' ');
1254                        strncpy(buf, cmdline, (start - cmdline + 8));
1255                        if (end)
1256                                strcpy(buf + (start - cmdline + 8), end);
1257                        else
1258                                buf[start - cmdline + 8] = '\0';
1259                } else {
1260                        strcpy(buf, cmdline);
1261                        strcat(buf, " console=");
1262                }
1263        } else {
1264                strcpy(buf, "console=");
1265        }
1266
1267        setenv("bootargs", buf);
1268        debug("after silent fix-up: %s\n", buf);
1269}
1270#endif /* CONFIG_SILENT_CONSOLE */
1271
1272
1273/*******************************************************************/
1274/* OS booting routines */
1275/*******************************************************************/
1276
1277#ifdef CONFIG_BOOTM_NETBSD
1278static int do_bootm_netbsd(int flag, int argc, char * const argv[],
1279                            bootm_headers_t *images)
1280{
1281        void (*loader)(bd_t *, image_header_t *, char *, char *);
1282        image_header_t *os_hdr, *hdr;
1283        ulong kernel_data, kernel_len;
1284        char *consdev;
1285        char *cmdline;
1286
1287        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1288                return 1;
1289
1290#if defined(CONFIG_FIT)
1291        if (!images->legacy_hdr_valid) {
1292                fit_unsupported_reset("NetBSD");
1293                return 1;
1294        }
1295#endif
1296        hdr = images->legacy_hdr_os;
1297
1298        /*
1299         * Booting a (NetBSD) kernel image
1300         *
1301         * This process is pretty similar to a standalone application:
1302         * The (first part of an multi-) image must be a stage-2 loader,
1303         * which in turn is responsible for loading & invoking the actual
1304         * kernel.  The only differences are the parameters being passed:
1305         * besides the board info strucure, the loader expects a command
1306         * line, the name of the console device, and (optionally) the
1307         * address of the original image header.
1308         */
1309        os_hdr = NULL;
1310        if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
1311                image_multi_getimg(hdr, 1, &kernel_data, &kernel_len);
1312                if (kernel_len)
1313                        os_hdr = hdr;
1314        }
1315
1316        consdev = "";
1317#if   defined(CONFIG_8xx_CONS_SMC1)
1318        consdev = "smc1";
1319#elif defined(CONFIG_8xx_CONS_SMC2)
1320        consdev = "smc2";
1321#elif defined(CONFIG_8xx_CONS_SCC2)
1322        consdev = "scc2";
1323#elif defined(CONFIG_8xx_CONS_SCC3)
1324        consdev = "scc3";
1325#endif
1326
1327        if (argc > 2) {
1328                ulong len;
1329                int   i;
1330
1331                for (i = 2, len = 0; i < argc; i += 1)
1332                        len += strlen(argv[i]) + 1;
1333                cmdline = malloc(len);
1334
1335                for (i = 2, len = 0; i < argc; i += 1) {
1336                        if (i > 2)
1337                                cmdline[len++] = ' ';
1338                        strcpy(&cmdline[len], argv[i]);
1339                        len += strlen(argv[i]);
1340                }
1341        } else if ((cmdline = getenv("bootargs")) == NULL) {
1342                cmdline = "";
1343        }
1344
1345        loader = (void (*)(bd_t *, image_header_t *, char *, char *))images->ep;
1346
1347        printf("## Transferring control to NetBSD stage-2 loader "
1348                "(at address %08lx) ...\n",
1349                (ulong)loader);
1350
1351        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
1352
1353        /*
1354         * NetBSD Stage-2 Loader Parameters:
1355         *   r3: ptr to board info data
1356         *   r4: image address
1357         *   r5: console device
1358         *   r6: boot args string
1359         */
1360        (*loader)(gd->bd, os_hdr, consdev, cmdline);
1361
1362        return 1;
1363}
1364#endif /* CONFIG_BOOTM_NETBSD*/
1365
1366#ifdef CONFIG_LYNXKDI
1367static int do_bootm_lynxkdi(int flag, int argc, char * const argv[],
1368                             bootm_headers_t *images)
1369{
1370        image_header_t *hdr = &images->legacy_hdr_os_copy;
1371
1372        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1373                return 1;
1374
1375#if defined(CONFIG_FIT)
1376        if (!images->legacy_hdr_valid) {
1377                fit_unsupported_reset("Lynx");
1378                return 1;
1379        }
1380#endif
1381
1382        lynxkdi_boot((image_header_t *)hdr);
1383
1384        return 1;
1385}
1386#endif /* CONFIG_LYNXKDI */
1387
1388#ifdef CONFIG_BOOTM_RTEMS
1389static int do_bootm_rtems(int flag, int argc, char * const argv[],
1390                           bootm_headers_t *images)
1391{
1392        void (*entry_point)(bd_t *);
1393
1394        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1395                return 1;
1396
1397#if defined(CONFIG_FIT)
1398        if (!images->legacy_hdr_valid) {
1399                fit_unsupported_reset("RTEMS");
1400                return 1;
1401        }
1402#endif
1403
1404        entry_point = (void (*)(bd_t *))images->ep;
1405
1406        printf("## Transferring control to RTEMS (at address %08lx) ...\n",
1407                (ulong)entry_point);
1408
1409        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
1410
1411        /*
1412         * RTEMS Parameters:
1413         *   r3: ptr to board info data
1414         */
1415        (*entry_point)(gd->bd);
1416
1417        return 1;
1418}
1419#endif /* CONFIG_BOOTM_RTEMS */
1420
1421#if defined(CONFIG_BOOTM_OSE)
1422static int do_bootm_ose(int flag, int argc, char * const argv[],
1423                           bootm_headers_t *images)
1424{
1425        void (*entry_point)(void);
1426
1427        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1428                return 1;
1429
1430#if defined(CONFIG_FIT)
1431        if (!images->legacy_hdr_valid) {
1432                fit_unsupported_reset("OSE");
1433                return 1;
1434        }
1435#endif
1436
1437        entry_point = (void (*)(void))images->ep;
1438
1439        printf("## Transferring control to OSE (at address %08lx) ...\n",
1440                (ulong)entry_point);
1441
1442        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
1443
1444        /*
1445         * OSE Parameters:
1446         *   None
1447         */
1448        (*entry_point)();
1449
1450        return 1;
1451}
1452#endif /* CONFIG_BOOTM_OSE */
1453
1454#if defined(CONFIG_CMD_ELF)
1455static int do_bootm_vxworks(int flag, int argc, char * const argv[],
1456                             bootm_headers_t *images)
1457{
1458        char str[80];
1459
1460        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1461                return 1;
1462
1463#if defined(CONFIG_FIT)
1464        if (!images->legacy_hdr_valid) {
1465                fit_unsupported_reset("VxWorks");
1466                return 1;
1467        }
1468#endif
1469
1470        sprintf(str, "%lx", images->ep); /* write entry-point into string */
1471        setenv("loadaddr", str);
1472        do_bootvx(NULL, 0, 0, NULL);
1473
1474        return 1;
1475}
1476
1477static int do_bootm_qnxelf(int flag, int argc, char * const argv[],
1478                            bootm_headers_t *images)
1479{
1480        char *local_args[2];
1481        char str[16];
1482
1483        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1484                return 1;
1485
1486#if defined(CONFIG_FIT)
1487        if (!images->legacy_hdr_valid) {
1488                fit_unsupported_reset("QNX");
1489                return 1;
1490        }
1491#endif
1492
1493        sprintf(str, "%lx", images->ep); /* write entry-point into string */
1494        local_args[0] = argv[0];
1495        local_args[1] = str;    /* and provide it via the arguments */
1496        do_bootelf(NULL, 0, 2, local_args);
1497
1498        return 1;
1499}
1500#endif
1501
1502#ifdef CONFIG_INTEGRITY
1503static int do_bootm_integrity(int flag, int argc, char * const argv[],
1504                           bootm_headers_t *images)
1505{
1506        void (*entry_point)(void);
1507
1508        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
1509                return 1;
1510
1511#if defined(CONFIG_FIT)
1512        if (!images->legacy_hdr_valid) {
1513                fit_unsupported_reset("INTEGRITY");
1514                return 1;
1515        }
1516#endif
1517
1518        entry_point = (void (*)(void))images->ep;
1519
1520        printf("## Transferring control to INTEGRITY (at address %08lx) ...\n",
1521                (ulong)entry_point);
1522
1523        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
1524
1525        /*
1526         * INTEGRITY Parameters:
1527         *   None
1528         */
1529        (*entry_point)();
1530
1531        return 1;
1532}
1533#endif
1534
1535#ifdef CONFIG_CMD_BOOTZ
1536
1537static int __bootz_setup(void *image, void **start, void **end)
1538{
1539        /* Please define bootz_setup() for your platform */
1540
1541        puts("Your platform's zImage format isn't supported yet!\n");
1542        return -1;
1543}
1544int bootz_setup(void *image, void **start, void **end)
1545        __attribute__((weak, alias("__bootz_setup")));
1546
1547/*
1548 * zImage booting support
1549 */
1550static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
1551                        char * const argv[], bootm_headers_t *images)
1552{
1553        int ret;
1554        void *zi_start, *zi_end;
1555
1556        memset(images, 0, sizeof(bootm_headers_t));
1557
1558        boot_start_lmb(images);
1559
1560        /* Setup Linux kernel zImage entry point */
1561        if (argc < 2) {
1562                images->ep = load_addr;
1563                debug("*  kernel: default image load address = 0x%08lx\n",
1564                                load_addr);
1565        } else {
1566                images->ep = simple_strtoul(argv[1], NULL, 16);
1567                debug("*  kernel: cmdline image address = 0x%08lx\n",
1568                        images->ep);
1569        }
1570
1571        ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
1572        if (ret != 0)
1573                return 1;
1574
1575        lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
1576
1577        /* Find ramdisk */
1578        ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
1579                        &images->rd_start, &images->rd_end);
1580        if (ret) {
1581                puts("Ramdisk image is corrupt or invalid\n");
1582                return 1;
1583        }
1584
1585#if defined(CONFIG_OF_LIBFDT)
1586        /* find flattened device tree */
1587        ret = boot_get_fdt(flag, argc, argv, images,
1588                           &images->ft_addr, &images->ft_len);
1589        if (ret) {
1590                puts("Could not find a valid device tree\n");
1591                return 1;
1592        }
1593
1594        set_working_fdt_addr(images->ft_addr);
1595#endif
1596
1597        return 0;
1598}
1599
1600static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1601{
1602        bootm_headers_t images;
1603
1604        if (bootz_start(cmdtp, flag, argc, argv, &images))
1605                return 1;
1606
1607        /*
1608         * We have reached the point of no return: we are going to
1609         * overwrite all exception vector code, so we cannot easily
1610         * recover from any failures any more...
1611         */
1612        disable_interrupts();
1613
1614#ifdef CONFIG_NETCONSOLE
1615        /* Stop the ethernet stack if NetConsole could have left it up */
1616        eth_halt();
1617#endif
1618
1619#if defined(CONFIG_CMD_USB)
1620        /*
1621         * turn off USB to prevent the host controller from writing to the
1622         * SDRAM while Linux is booting. This could happen (at least for OHCI
1623         * controller), because the HCCA (Host Controller Communication Area)
1624         * lies within the SDRAM and the host controller writes continously to
1625         * this area (as busmaster!). The HccaFrameNumber is for example
1626         * updated every 1 ms within the HCCA structure in SDRAM! For more
1627         * details see the OpenHCI specification.
1628         */
1629        usb_stop();
1630#endif
1631
1632#ifdef CONFIG_SILENT_CONSOLE
1633        fixup_silent_linux();
1634#endif
1635        arch_preboot_os();
1636
1637        do_bootm_linux(0, argc, argv, &images);
1638#ifdef DEBUG
1639        puts("\n## Control returned to monitor - resetting...\n");
1640#endif
1641        do_reset(cmdtp, flag, argc, argv);
1642
1643        return 1;
1644}
1645
1646U_BOOT_CMD(
1647        bootz,  CONFIG_SYS_MAXARGS,     1,      do_bootz,
1648        "boot Linux zImage image from memory",
1649        "[addr [initrd[:size]] [fdt]]\n"
1650        "    - boot Linux zImage stored in memory\n"
1651        "\tThe argument 'initrd' is optional and specifies the address\n"
1652        "\tof the initrd in memory. The optional argument ':size' allows\n"
1653        "\tspecifying the size of RAW initrd.\n"
1654#if defined(CONFIG_OF_LIBFDT)
1655        "\tWhen booting a Linux kernel which requires a flat device-tree\n"
1656        "\ta third argument is required which is the address of the\n"
1657        "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
1658        "\tuse a '-' for the second argument. If you do not pass a third\n"
1659        "\ta bd_info struct will be passed instead\n"
1660#endif
1661);
1662#endif  /* CONFIG_CMD_BOOTZ */
1663