uboot/cmd/bootm.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2009
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * Boot support
  10 */
  11#include <common.h>
  12#include <bootm.h>
  13#include <command.h>
  14#include <environment.h>
  15#include <errno.h>
  16#include <image.h>
  17#include <malloc.h>
  18#include <nand.h>
  19#include <asm/byteorder.h>
  20#include <linux/ctype.h>
  21#include <linux/err.h>
  22#include <u-boot/zlib.h>
  23
  24DECLARE_GLOBAL_DATA_PTR;
  25
  26#if defined(CONFIG_CMD_IMI)
  27static int image_info(unsigned long addr);
  28#endif
  29
  30#if defined(CONFIG_CMD_IMLS)
  31#include <flash.h>
  32#include <mtd/cfi_flash.h>
  33extern flash_info_t flash_info[]; /* info for FLASH chips */
  34#endif
  35
  36#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
  37static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
  38#endif
  39
  40/* we overload the cmd field with our state machine info instead of a
  41 * function pointer */
  42static cmd_tbl_t cmd_bootm_sub[] = {
  43        U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
  44        U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
  45#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
  46        U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
  47#endif
  48#ifdef CONFIG_OF_LIBFDT
  49        U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
  50#endif
  51        U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
  52        U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
  53        U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
  54        U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
  55        U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
  56};
  57
  58static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
  59                        char * const argv[])
  60{
  61        int ret = 0;
  62        long state;
  63        cmd_tbl_t *c;
  64
  65        c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
  66        argc--; argv++;
  67
  68        if (c) {
  69                state = (long)c->cmd;
  70                if (state == BOOTM_STATE_START)
  71                        state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
  72        } else {
  73                /* Unrecognized command */
  74                return CMD_RET_USAGE;
  75        }
  76
  77        if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
  78            images.state >= state) {
  79                printf("Trying to execute a command out of order\n");
  80                return CMD_RET_USAGE;
  81        }
  82
  83        ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
  84
  85        return ret;
  86}
  87
  88/*******************************************************************/
  89/* bootm - boot application image from image in memory */
  90/*******************************************************************/
  91
  92int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  93{
  94#ifdef CONFIG_NEEDS_MANUAL_RELOC
  95        static int relocated = 0;
  96
  97        if (!relocated) {
  98                int i;
  99
 100                /* relocate names of sub-command table */
 101                for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
 102                        cmd_bootm_sub[i].name += gd->reloc_off;
 103
 104                relocated = 1;
 105        }
 106#endif
 107
 108        /* determine if we have a sub command */
 109        argc--; argv++;
 110        if (argc > 0) {
 111                char *endp;
 112
 113                simple_strtoul(argv[0], &endp, 16);
 114                /* endp pointing to NULL means that argv[0] was just a
 115                 * valid number, pass it along to the normal bootm processing
 116                 *
 117                 * If endp is ':' or '#' assume a FIT identifier so pass
 118                 * along for normal processing.
 119                 *
 120                 * Right now we assume the first arg should never be '-'
 121                 */
 122                if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
 123                        return do_bootm_subcommand(cmdtp, flag, argc, argv);
 124        }
 125
 126        return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
 127                BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
 128                BOOTM_STATE_LOADOS |
 129#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 130                BOOTM_STATE_RAMDISK |
 131#endif
 132#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
 133                BOOTM_STATE_OS_CMDLINE |
 134#endif
 135                BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 136                BOOTM_STATE_OS_GO, &images, 1);
 137}
 138
 139int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
 140{
 141        const char *ep = env_get("autostart");
 142
 143        if (ep && !strcmp(ep, "yes")) {
 144                char *local_args[2];
 145                local_args[0] = (char *)cmd;
 146                local_args[1] = NULL;
 147                printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
 148                return do_bootm(cmdtp, 0, 1, local_args);
 149        }
 150
 151        return 0;
 152}
 153
 154#ifdef CONFIG_SYS_LONGHELP
 155static char bootm_help_text[] =
 156        "[addr [arg ...]]\n    - boot application image stored in memory\n"
 157        "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
 158        "\t'arg' can be the address of an initrd image\n"
 159#if defined(CONFIG_OF_LIBFDT)
 160        "\tWhen booting a Linux kernel which requires a flat device-tree\n"
 161        "\ta third argument is required which is the address of the\n"
 162        "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
 163        "\tuse a '-' for the second argument. If you do not pass a third\n"
 164        "\ta bd_info struct will be passed instead\n"
 165#endif
 166#if defined(CONFIG_FIT)
 167        "\t\nFor the new multi component uImage format (FIT) addresses\n"
 168        "\tmust be extended to include component or configuration unit name:\n"
 169        "\taddr:<subimg_uname> - direct component image specification\n"
 170        "\taddr#<conf_uname>   - configuration specification\n"
 171        "\tUse iminfo command to get the list of existing component\n"
 172        "\timages and configurations.\n"
 173#endif
 174        "\nSub-commands to do part of the bootm sequence.  The sub-commands "
 175        "must be\n"
 176        "issued in the order below (it's ok to not issue all sub-commands):\n"
 177        "\tstart [addr [arg ...]]\n"
 178        "\tloados  - load OS image\n"
 179#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
 180        "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
 181#endif
 182#if defined(CONFIG_OF_LIBFDT)
 183        "\tfdt     - relocate flat device tree\n"
 184#endif
 185        "\tcmdline - OS specific command line processing/setup\n"
 186        "\tbdt     - OS specific bd_t processing\n"
 187        "\tprep    - OS specific prep before relocation or go\n"
 188#if defined(CONFIG_TRACE)
 189        "\tfake    - OS specific fake start without go\n"
 190#endif
 191        "\tgo      - start OS";
 192#endif
 193
 194U_BOOT_CMD(
 195        bootm,  CONFIG_SYS_MAXARGS,     1,      do_bootm,
 196        "boot application image from memory", bootm_help_text
 197);
 198
 199/*******************************************************************/
 200/* bootd - boot default image */
 201/*******************************************************************/
 202#if defined(CONFIG_CMD_BOOTD)
 203int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 204{
 205        return run_command(env_get("bootcmd"), flag);
 206}
 207
 208U_BOOT_CMD(
 209        boot,   1,      1,      do_bootd,
 210        "boot default, i.e., run 'bootcmd'",
 211        ""
 212);
 213
 214/* keep old command name "bootd" for backward compatibility */
 215U_BOOT_CMD(
 216        bootd, 1,       1,      do_bootd,
 217        "boot default, i.e., run 'bootcmd'",
 218        ""
 219);
 220
 221#endif
 222
 223
 224/*******************************************************************/
 225/* iminfo - print header info for a requested image */
 226/*******************************************************************/
 227#if defined(CONFIG_CMD_IMI)
 228static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 229{
 230        int     arg;
 231        ulong   addr;
 232        int     rcode = 0;
 233
 234        if (argc < 2) {
 235                return image_info(load_addr);
 236        }
 237
 238        for (arg = 1; arg < argc; ++arg) {
 239                addr = simple_strtoul(argv[arg], NULL, 16);
 240                if (image_info(addr) != 0)
 241                        rcode = 1;
 242        }
 243        return rcode;
 244}
 245
 246static int image_info(ulong addr)
 247{
 248        void *hdr = (void *)addr;
 249
 250        printf("\n## Checking Image at %08lx ...\n", addr);
 251
 252        switch (genimg_get_format(hdr)) {
 253#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
 254        case IMAGE_FORMAT_LEGACY:
 255                puts("   Legacy image found\n");
 256                if (!image_check_magic(hdr)) {
 257                        puts("   Bad Magic Number\n");
 258                        return 1;
 259                }
 260
 261                if (!image_check_hcrc(hdr)) {
 262                        puts("   Bad Header Checksum\n");
 263                        return 1;
 264                }
 265
 266                image_print_contents(hdr);
 267
 268                puts("   Verifying Checksum ... ");
 269                if (!image_check_dcrc(hdr)) {
 270                        puts("   Bad Data CRC\n");
 271                        return 1;
 272                }
 273                puts("OK\n");
 274                return 0;
 275#endif
 276#if defined(CONFIG_ANDROID_BOOT_IMAGE)
 277        case IMAGE_FORMAT_ANDROID:
 278                puts("   Android image found\n");
 279                android_print_contents(hdr);
 280                return 0;
 281#endif
 282#if defined(CONFIG_FIT)
 283        case IMAGE_FORMAT_FIT:
 284                puts("   FIT image found\n");
 285
 286                if (!fit_check_format(hdr)) {
 287                        puts("Bad FIT image format!\n");
 288                        return 1;
 289                }
 290
 291                fit_print_contents(hdr);
 292
 293                if (!fit_all_image_verify(hdr)) {
 294                        puts("Bad hash in FIT image!\n");
 295                        return 1;
 296                }
 297
 298                return 0;
 299#endif
 300        default:
 301                puts("Unknown image format!\n");
 302                break;
 303        }
 304
 305        return 1;
 306}
 307
 308U_BOOT_CMD(
 309        iminfo, CONFIG_SYS_MAXARGS,     1,      do_iminfo,
 310        "print header information for application image",
 311        "addr [addr ...]\n"
 312        "    - print header information for application image starting at\n"
 313        "      address 'addr' in memory; this includes verification of the\n"
 314        "      image contents (magic number, header and payload checksums)"
 315);
 316#endif
 317
 318
 319/*******************************************************************/
 320/* imls - list all images found in flash */
 321/*******************************************************************/
 322#if defined(CONFIG_CMD_IMLS)
 323static int do_imls_nor(void)
 324{
 325        flash_info_t *info;
 326        int i, j;
 327        void *hdr;
 328
 329        for (i = 0, info = &flash_info[0];
 330                i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
 331
 332                if (info->flash_id == FLASH_UNKNOWN)
 333                        goto next_bank;
 334                for (j = 0; j < info->sector_count; ++j) {
 335
 336                        hdr = (void *)info->start[j];
 337                        if (!hdr)
 338                                goto next_sector;
 339
 340                        switch (genimg_get_format(hdr)) {
 341#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
 342                        case IMAGE_FORMAT_LEGACY:
 343                                if (!image_check_hcrc(hdr))
 344                                        goto next_sector;
 345
 346                                printf("Legacy Image at %08lX:\n", (ulong)hdr);
 347                                image_print_contents(hdr);
 348
 349                                puts("   Verifying Checksum ... ");
 350                                if (!image_check_dcrc(hdr)) {
 351                                        puts("Bad Data CRC\n");
 352                                } else {
 353                                        puts("OK\n");
 354                                }
 355                                break;
 356#endif
 357#if defined(CONFIG_FIT)
 358                        case IMAGE_FORMAT_FIT:
 359                                if (!fit_check_format(hdr))
 360                                        goto next_sector;
 361
 362                                printf("FIT Image at %08lX:\n", (ulong)hdr);
 363                                fit_print_contents(hdr);
 364                                break;
 365#endif
 366                        default:
 367                                goto next_sector;
 368                        }
 369
 370next_sector:            ;
 371                }
 372next_bank:      ;
 373        }
 374        return 0;
 375}
 376#endif
 377
 378#if defined(CONFIG_CMD_IMLS_NAND)
 379static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
 380                                 loff_t off, size_t len)
 381{
 382        void *imgdata;
 383        int ret;
 384
 385        imgdata = malloc(len);
 386        if (!imgdata) {
 387                printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
 388                                nand_dev, off);
 389                printf("   Low memory(cannot allocate memory for image)\n");
 390                return -ENOMEM;
 391        }
 392
 393        ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
 394        if (ret < 0 && ret != -EUCLEAN) {
 395                free(imgdata);
 396                return ret;
 397        }
 398
 399        if (!image_check_hcrc(imgdata)) {
 400                free(imgdata);
 401                return 0;
 402        }
 403
 404        printf("Legacy Image at NAND device %d offset %08llX:\n",
 405                        nand_dev, off);
 406        image_print_contents(imgdata);
 407
 408        puts("   Verifying Checksum ... ");
 409        if (!image_check_dcrc(imgdata))
 410                puts("Bad Data CRC\n");
 411        else
 412                puts("OK\n");
 413
 414        free(imgdata);
 415
 416        return 0;
 417}
 418
 419static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
 420                              size_t len)
 421{
 422        void *imgdata;
 423        int ret;
 424
 425        imgdata = malloc(len);
 426        if (!imgdata) {
 427                printf("May be a FIT Image at NAND device %d offset %08llX:\n",
 428                                nand_dev, off);
 429                printf("   Low memory(cannot allocate memory for image)\n");
 430                return -ENOMEM;
 431        }
 432
 433        ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
 434        if (ret < 0 && ret != -EUCLEAN) {
 435                free(imgdata);
 436                return ret;
 437        }
 438
 439        if (!fit_check_format(imgdata)) {
 440                free(imgdata);
 441                return 0;
 442        }
 443
 444        printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
 445
 446        fit_print_contents(imgdata);
 447        free(imgdata);
 448
 449        return 0;
 450}
 451
 452static int do_imls_nand(void)
 453{
 454        struct mtd_info *mtd;
 455        int nand_dev = nand_curr_device;
 456        size_t len;
 457        loff_t off;
 458        u32 buffer[16];
 459
 460        if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
 461                puts("\nNo NAND devices available\n");
 462                return -ENODEV;
 463        }
 464
 465        printf("\n");
 466
 467        for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
 468                mtd = get_nand_dev_by_index(nand_dev);
 469                if (!mtd->name || !mtd->size)
 470                        continue;
 471
 472                for (off = 0; off < mtd->size; off += mtd->erasesize) {
 473                        const image_header_t *header;
 474                        int ret;
 475
 476                        if (nand_block_isbad(mtd, off))
 477                                continue;
 478
 479                        len = sizeof(buffer);
 480
 481                        ret = nand_read(mtd, off, &len, (u8 *)buffer);
 482                        if (ret < 0 && ret != -EUCLEAN) {
 483                                printf("NAND read error %d at offset %08llX\n",
 484                                                ret, off);
 485                                continue;
 486                        }
 487
 488                        switch (genimg_get_format(buffer)) {
 489#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
 490                        case IMAGE_FORMAT_LEGACY:
 491                                header = (const image_header_t *)buffer;
 492
 493                                len = image_get_image_size(header);
 494                                nand_imls_legacyimage(mtd, nand_dev, off, len);
 495                                break;
 496#endif
 497#if defined(CONFIG_FIT)
 498                        case IMAGE_FORMAT_FIT:
 499                                len = fit_get_size(buffer);
 500                                nand_imls_fitimage(mtd, nand_dev, off, len);
 501                                break;
 502#endif
 503                        }
 504                }
 505        }
 506
 507        return 0;
 508}
 509#endif
 510
 511#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
 512static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 513{
 514        int ret_nor = 0, ret_nand = 0;
 515
 516#if defined(CONFIG_CMD_IMLS)
 517        ret_nor = do_imls_nor();
 518#endif
 519
 520#if defined(CONFIG_CMD_IMLS_NAND)
 521        ret_nand = do_imls_nand();
 522#endif
 523
 524        if (ret_nor)
 525                return ret_nor;
 526
 527        if (ret_nand)
 528                return ret_nand;
 529
 530        return (0);
 531}
 532
 533U_BOOT_CMD(
 534        imls,   1,              1,      do_imls,
 535        "list all images found in flash",
 536        "\n"
 537        "    - Prints information about all images found at sector/block\n"
 538        "      boundaries in nor/nand flash."
 539);
 540#endif
 541