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