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