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