uboot/cmd/nand.c
<<
>>
Prefs
   1/*
   2 * Driver for NAND support, Rick Bronson
   3 * borrowed heavily from:
   4 * (c) 1999 Machine Vision Holdings, Inc.
   5 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
   6 *
   7 * Ported 'dynenv' to 'nand env.oob' command
   8 * (C) 2010 Nanometrics, Inc.
   9 * 'dynenv' -- Dynamic environment offset in NAND OOB
  10 * (C) Copyright 2006-2007 OpenMoko, Inc.
  11 * Added 16-bit nand support
  12 * (C) 2004 Texas Instruments
  13 *
  14 * Copyright 2010, 2012 Freescale Semiconductor
  15 * The portions of this file whose copyright is held by Freescale and which
  16 * are not considered a derived work of GPL v2-only code may be distributed
  17 * and/or modified under the terms of the GNU General Public License as
  18 * published by the Free Software Foundation; either version 2 of the
  19 * License, or (at your option) any later version.
  20 */
  21
  22#include <common.h>
  23#include <bootstage.h>
  24#include <image.h>
  25#include <asm/cache.h>
  26#include <linux/mtd/mtd.h>
  27#include <command.h>
  28#include <console.h>
  29#include <env.h>
  30#include <watchdog.h>
  31#include <malloc.h>
  32#include <asm/byteorder.h>
  33#include <jffs2/jffs2.h>
  34#include <nand.h>
  35
  36#include "legacy-mtd-utils.h"
  37
  38#if defined(CONFIG_CMD_MTDPARTS)
  39
  40/* partition handling routines */
  41int mtdparts_init(void);
  42int find_dev_and_part(const char *id, struct mtd_device **dev,
  43                      u8 *part_num, struct part_info **part);
  44#endif
  45
  46static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
  47                     int repeat)
  48{
  49        int i;
  50        u_char *datbuf, *oobbuf, *p;
  51        static loff_t last;
  52        int ret = 0;
  53
  54        if (repeat)
  55                off = last + mtd->writesize;
  56
  57        last = off;
  58
  59        datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
  60        if (!datbuf) {
  61                puts("No memory for page buffer\n");
  62                return 1;
  63        }
  64
  65        oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
  66        if (!oobbuf) {
  67                puts("No memory for page buffer\n");
  68                ret = 1;
  69                goto free_dat;
  70        }
  71        off &= ~(mtd->writesize - 1);
  72        loff_t addr = (loff_t) off;
  73        struct mtd_oob_ops ops;
  74        memset(&ops, 0, sizeof(ops));
  75        ops.datbuf = datbuf;
  76        ops.oobbuf = oobbuf;
  77        ops.len = mtd->writesize;
  78        ops.ooblen = mtd->oobsize;
  79        ops.mode = MTD_OPS_RAW;
  80        i = mtd_read_oob(mtd, addr, &ops);
  81        if (i < 0) {
  82                printf("Error (%d) reading page %08lx\n", i, off);
  83                ret = 1;
  84                goto free_all;
  85        }
  86        printf("Page %08lx dump:\n", off);
  87
  88        if (!only_oob) {
  89                i = mtd->writesize >> 4;
  90                p = datbuf;
  91
  92                while (i--) {
  93                        printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
  94                               "  %02x %02x %02x %02x %02x %02x %02x %02x\n",
  95                               p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
  96                               p[8], p[9], p[10], p[11], p[12], p[13], p[14],
  97                               p[15]);
  98                        p += 16;
  99                }
 100        }
 101
 102        puts("OOB:\n");
 103        i = mtd->oobsize >> 3;
 104        p = oobbuf;
 105        while (i--) {
 106                printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
 107                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
 108                p += 8;
 109        }
 110
 111free_all:
 112        free(oobbuf);
 113free_dat:
 114        free(datbuf);
 115
 116        return ret;
 117}
 118
 119/* ------------------------------------------------------------------------- */
 120
 121static int set_dev(int dev)
 122{
 123        struct mtd_info *mtd = get_nand_dev_by_index(dev);
 124
 125        if (!mtd)
 126                return -ENODEV;
 127
 128        if (nand_curr_device == dev)
 129                return 0;
 130
 131        printf("Device %d: %s", dev, mtd->name);
 132        puts("... is now current device\n");
 133        nand_curr_device = dev;
 134
 135#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
 136        board_nand_select_device(mtd_to_nand(mtd), dev);
 137#endif
 138
 139        return 0;
 140}
 141
 142#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 143static void print_status(ulong start, ulong end, ulong erasesize, int status)
 144{
 145        /*
 146         * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
 147         * not the same as others.  Instead of bit 1 being lock, it is
 148         * #lock_tight. To make the driver support either format, ignore bit 1
 149         * and use only bit 0 and bit 2.
 150         */
 151        printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
 152                start,
 153                end - 1,
 154                (end - start) / erasesize,
 155                ((status & NAND_LOCK_STATUS_TIGHT) ?  "TIGHT " : ""),
 156                (!(status & NAND_LOCK_STATUS_UNLOCK) ?  "LOCK " : ""),
 157                ((status & NAND_LOCK_STATUS_UNLOCK) ?  "UNLOCK " : ""));
 158}
 159
 160static void do_nand_status(struct mtd_info *mtd)
 161{
 162        ulong block_start = 0;
 163        ulong off;
 164        int last_status = -1;
 165
 166        struct nand_chip *nand_chip = mtd_to_nand(mtd);
 167        /* check the WP bit */
 168        nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 169        printf("device is %swrite protected\n",
 170                (nand_chip->read_byte(mtd) & 0x80 ?
 171                 "NOT " : ""));
 172
 173        for (off = 0; off < mtd->size; off += mtd->erasesize) {
 174                int s = nand_get_lock_status(mtd, off);
 175
 176                /* print message only if status has changed */
 177                if (s != last_status && off != 0) {
 178                        print_status(block_start, off, mtd->erasesize,
 179                                        last_status);
 180                        block_start = off;
 181                }
 182                last_status = s;
 183        }
 184        /* Print the last block info */
 185        print_status(block_start, off, mtd->erasesize, last_status);
 186}
 187#endif
 188
 189#ifdef CONFIG_ENV_OFFSET_OOB
 190unsigned long nand_env_oob_offset;
 191
 192int do_nand_env_oob(struct cmd_tbl *cmdtp, int argc, char *const argv[])
 193{
 194        int ret;
 195        uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
 196        struct mtd_info *mtd = get_nand_dev_by_index(0);
 197        char *cmd = argv[1];
 198
 199        if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
 200                puts("no devices available\n");
 201                return 1;
 202        }
 203
 204        set_dev(0);
 205
 206        if (!strcmp(cmd, "get")) {
 207                ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
 208                if (ret)
 209                        return 1;
 210
 211                printf("0x%08lx\n", nand_env_oob_offset);
 212        } else if (!strcmp(cmd, "set")) {
 213                loff_t addr;
 214                loff_t maxsize;
 215                struct mtd_oob_ops ops;
 216                int idx = 0;
 217
 218                if (argc < 3)
 219                        goto usage;
 220
 221                mtd = get_nand_dev_by_index(idx);
 222                /* We don't care about size, or maxsize. */
 223                if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
 224                                MTD_DEV_TYPE_NAND, mtd->size)) {
 225                        puts("Offset or partition name expected\n");
 226                        return 1;
 227                }
 228                if (set_dev(idx)) {
 229                        puts("Offset or partition name expected\n");
 230                        return 1;
 231                }
 232
 233                if (idx != 0) {
 234                        puts("Partition not on first NAND device\n");
 235                        return 1;
 236                }
 237
 238                if (mtd->oobavail < ENV_OFFSET_SIZE) {
 239                        printf("Insufficient available OOB bytes:\n"
 240                               "%d OOB bytes available but %d required for "
 241                               "env.oob support\n",
 242                               mtd->oobavail, ENV_OFFSET_SIZE);
 243                        return 1;
 244                }
 245
 246                if ((addr & (mtd->erasesize - 1)) != 0) {
 247                        printf("Environment offset must be block-aligned\n");
 248                        return 1;
 249                }
 250
 251                ops.datbuf = NULL;
 252                ops.mode = MTD_OOB_AUTO;
 253                ops.ooboffs = 0;
 254                ops.ooblen = ENV_OFFSET_SIZE;
 255                ops.oobbuf = (void *) oob_buf;
 256
 257                oob_buf[0] = ENV_OOB_MARKER;
 258                oob_buf[1] = addr / mtd->erasesize;
 259
 260                ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
 261                if (ret) {
 262                        printf("Error writing OOB block 0\n");
 263                        return ret;
 264                }
 265
 266                ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
 267                if (ret) {
 268                        printf("Error reading env offset in OOB\n");
 269                        return ret;
 270                }
 271
 272                if (addr != nand_env_oob_offset) {
 273                        printf("Verification of env offset in OOB failed: "
 274                               "0x%08llx expected but got 0x%08lx\n",
 275                               (unsigned long long)addr, nand_env_oob_offset);
 276                        return 1;
 277                }
 278        } else {
 279                goto usage;
 280        }
 281
 282        return ret;
 283
 284usage:
 285        return CMD_RET_USAGE;
 286}
 287
 288#endif
 289
 290static void nand_print_and_set_info(int idx)
 291{
 292        struct mtd_info *mtd;
 293        struct nand_chip *chip;
 294
 295        mtd = get_nand_dev_by_index(idx);
 296        if (!mtd)
 297                return;
 298
 299        chip = mtd_to_nand(mtd);
 300        printf("Device %d: ", idx);
 301        if (chip->numchips > 1)
 302                printf("%dx ", chip->numchips);
 303        printf("%s, sector size %u KiB\n",
 304               mtd->name, mtd->erasesize >> 10);
 305        printf("  Page size   %8d b\n", mtd->writesize);
 306        printf("  OOB size    %8d b\n", mtd->oobsize);
 307        printf("  Erase size  %8d b\n", mtd->erasesize);
 308        printf("  subpagesize %8d b\n", chip->subpagesize);
 309        printf("  options     0x%08x\n", chip->options);
 310        printf("  bbt options 0x%08x\n", chip->bbt_options);
 311
 312        /* Set geometry info */
 313        env_set_hex("nand_writesize", mtd->writesize);
 314        env_set_hex("nand_oobsize", mtd->oobsize);
 315        env_set_hex("nand_erasesize", mtd->erasesize);
 316}
 317
 318static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
 319                      ulong count, int read, int no_verify)
 320{
 321        int ret = 0;
 322
 323        while (count--) {
 324                /* Raw access */
 325                mtd_oob_ops_t ops = {
 326                        .datbuf = (u8 *)addr,
 327                        .oobbuf = ((u8 *)addr) + mtd->writesize,
 328                        .len = mtd->writesize,
 329                        .ooblen = mtd->oobsize,
 330                        .mode = MTD_OPS_RAW
 331                };
 332
 333                if (read) {
 334                        ret = mtd_read_oob(mtd, off, &ops);
 335                } else {
 336                        ret = mtd_write_oob(mtd, off, &ops);
 337                        if (!ret && !no_verify)
 338                                ret = nand_verify_page_oob(mtd, &ops, off);
 339                }
 340
 341                if (ret) {
 342                        printf("%s: error at offset %llx, ret %d\n",
 343                                __func__, (long long)off, ret);
 344                        break;
 345                }
 346
 347                addr += mtd->writesize + mtd->oobsize;
 348                off += mtd->writesize;
 349        }
 350
 351        return ret;
 352}
 353
 354/* Adjust a chip/partition size down for bad blocks so we don't
 355 * read/write past the end of a chip/partition by accident.
 356 */
 357static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
 358{
 359        /* We grab the nand info object here fresh because this is usually
 360         * called after arg_off_size() which can change the value of dev.
 361         */
 362        struct mtd_info *mtd = get_nand_dev_by_index(dev);
 363        loff_t maxoffset = offset + *size;
 364        int badblocks = 0;
 365
 366        /* count badblocks in NAND from offset to offset + size */
 367        for (; offset < maxoffset; offset += mtd->erasesize) {
 368                if (nand_block_isbad(mtd, offset))
 369                        badblocks++;
 370        }
 371        /* adjust size if any bad blocks found */
 372        if (badblocks) {
 373                *size -= badblocks * mtd->erasesize;
 374                printf("size adjusted to 0x%llx (%d bad blocks)\n",
 375                       (unsigned long long)*size, badblocks);
 376        }
 377}
 378
 379static int do_nand(struct cmd_tbl *cmdtp, int flag, int argc,
 380                   char *const argv[])
 381{
 382        int i, ret = 0;
 383        ulong addr;
 384        loff_t off, size, maxsize;
 385        char *cmd, *s;
 386        struct mtd_info *mtd;
 387#ifdef CONFIG_SYS_NAND_QUIET
 388        int quiet = CONFIG_SYS_NAND_QUIET;
 389#else
 390        int quiet = 0;
 391#endif
 392        const char *quiet_str = env_get("quiet");
 393        int dev = nand_curr_device;
 394        int repeat = flag & CMD_FLAG_REPEAT;
 395
 396        /* at least two arguments please */
 397        if (argc < 2)
 398                goto usage;
 399
 400        if (quiet_str)
 401                quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
 402
 403        cmd = argv[1];
 404
 405        /* Only "dump" is repeatable. */
 406        if (repeat && strcmp(cmd, "dump"))
 407                return 0;
 408
 409        if (strcmp(cmd, "info") == 0) {
 410
 411                putc('\n');
 412                for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
 413                        nand_print_and_set_info(i);
 414                return 0;
 415        }
 416
 417        if (strcmp(cmd, "device") == 0) {
 418                if (argc < 3) {
 419                        putc('\n');
 420                        if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
 421                                puts("no devices available\n");
 422                        else
 423                                nand_print_and_set_info(dev);
 424                        return 0;
 425                }
 426
 427                dev = (int)dectoul(argv[2], NULL);
 428                set_dev(dev);
 429
 430                return 0;
 431        }
 432
 433#ifdef CONFIG_ENV_OFFSET_OOB
 434        /* this command operates only on the first nand device */
 435        if (strcmp(cmd, "env.oob") == 0)
 436                return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
 437#endif
 438
 439        /* The following commands operate on the current device, unless
 440         * overridden by a partition specifier.  Note that if somehow the
 441         * current device is invalid, it will have to be changed to a valid
 442         * one before these commands can run, even if a partition specifier
 443         * for another device is to be used.
 444         */
 445        mtd = get_nand_dev_by_index(dev);
 446        if (!mtd) {
 447                puts("\nno devices available\n");
 448                return 1;
 449        }
 450
 451        if (strcmp(cmd, "bad") == 0) {
 452                printf("\nDevice %d bad blocks:\n", dev);
 453                for (off = 0; off < mtd->size; off += mtd->erasesize)
 454                        if (nand_block_isbad(mtd, off))
 455                                printf("  %08llx\n", (unsigned long long)off);
 456                return 0;
 457        }
 458
 459        /*
 460         * Syntax is:
 461         *   0    1     2       3    4
 462         *   nand erase [clean] [off size]
 463         */
 464        if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
 465                nand_erase_options_t opts;
 466                /* "clean" at index 2 means request to write cleanmarker */
 467                int clean = argc > 2 && !strcmp("clean", argv[2]);
 468                int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
 469                int o = (clean || scrub_yes) ? 3 : 2;
 470                int scrub = !strncmp(cmd, "scrub", 5);
 471                int spread = 0;
 472                int args = 2;
 473                const char *scrub_warn =
 474                        "Warning: "
 475                        "scrub option will erase all factory set bad blocks!\n"
 476                        "         "
 477                        "There is no reliable way to recover them.\n"
 478                        "         "
 479                        "Use this command only for testing purposes if you\n"
 480                        "         "
 481                        "are sure of what you are doing!\n"
 482                        "\nReally scrub this NAND flash? <y/N>\n";
 483
 484                if (cmd[5] != 0) {
 485                        if (!strcmp(&cmd[5], ".spread")) {
 486                                spread = 1;
 487                        } else if (!strcmp(&cmd[5], ".part")) {
 488                                args = 1;
 489                        } else if (!strcmp(&cmd[5], ".chip")) {
 490                                args = 0;
 491                        } else {
 492                                goto usage;
 493                        }
 494                }
 495
 496                /*
 497                 * Don't allow missing arguments to cause full chip/partition
 498                 * erases -- easy to do accidentally, e.g. with a misspelled
 499                 * variable name.
 500                 */
 501                if (argc != o + args)
 502                        goto usage;
 503
 504                printf("\nNAND %s: ", cmd);
 505                /* skip first two or three arguments, look for offset and size */
 506                if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
 507                                     &maxsize, MTD_DEV_TYPE_NAND,
 508                                     mtd->size) != 0)
 509                        return 1;
 510
 511                if (set_dev(dev))
 512                        return 1;
 513
 514                mtd = get_nand_dev_by_index(dev);
 515
 516                memset(&opts, 0, sizeof(opts));
 517                opts.offset = off;
 518                opts.length = size;
 519                opts.jffs2  = clean;
 520                opts.quiet  = quiet;
 521                opts.spread = spread;
 522
 523                if (scrub) {
 524                        if (scrub_yes) {
 525                                opts.scrub = 1;
 526                        } else {
 527                                puts(scrub_warn);
 528                                if (confirm_yesno()) {
 529                                        opts.scrub = 1;
 530                                } else {
 531                                        puts("scrub aborted\n");
 532                                        return 1;
 533                                }
 534                        }
 535                }
 536                ret = nand_erase_opts(mtd, &opts);
 537                printf("%s\n", ret ? "ERROR" : "OK");
 538
 539                return ret == 0 ? 0 : 1;
 540        }
 541
 542        if (strncmp(cmd, "dump", 4) == 0) {
 543                if (argc < 3)
 544                        goto usage;
 545
 546                off = (int)hextoul(argv[2], NULL);
 547                ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
 548
 549                return ret == 0 ? 1 : 0;
 550        }
 551
 552        if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
 553                size_t rwsize;
 554                ulong pagecount = 1;
 555                int read;
 556                int raw = 0;
 557                int no_verify = 0;
 558
 559                if (argc < 4)
 560                        goto usage;
 561
 562                addr = (ulong)hextoul(argv[2], NULL);
 563
 564                read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
 565                printf("\nNAND %s: ", read ? "read" : "write");
 566
 567                s = strchr(cmd, '.');
 568
 569                if (s && !strncmp(s, ".raw", 4)) {
 570                        raw = 1;
 571
 572                        if (!strcmp(s, ".raw.noverify"))
 573                                no_verify = 1;
 574
 575                        if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
 576                                        MTD_DEV_TYPE_NAND,
 577                                        mtd->size))
 578                                return 1;
 579
 580                        if (set_dev(dev))
 581                                return 1;
 582
 583                        mtd = get_nand_dev_by_index(dev);
 584
 585                        if (argc > 4 && !str2long(argv[4], &pagecount)) {
 586                                printf("'%s' is not a number\n", argv[4]);
 587                                return 1;
 588                        }
 589
 590                        if (pagecount * mtd->writesize > size) {
 591                                puts("Size exceeds partition or device limit\n");
 592                                return -1;
 593                        }
 594
 595                        rwsize = pagecount * (mtd->writesize + mtd->oobsize);
 596                } else {
 597                        if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
 598                                             &size, &maxsize,
 599                                             MTD_DEV_TYPE_NAND,
 600                                             mtd->size) != 0)
 601                                return 1;
 602
 603                        if (set_dev(dev))
 604                                return 1;
 605
 606                        /* size is unspecified */
 607                        if (argc < 5)
 608                                adjust_size_for_badblocks(&size, off, dev);
 609                        rwsize = size;
 610                }
 611
 612                mtd = get_nand_dev_by_index(dev);
 613
 614                if (!s || !strcmp(s, ".jffs2") ||
 615                    !strcmp(s, ".e") || !strcmp(s, ".i")) {
 616                        if (read)
 617                                ret = nand_read_skip_bad(mtd, off, &rwsize,
 618                                                         NULL, maxsize,
 619                                                         (u_char *)addr);
 620                        else
 621                                ret = nand_write_skip_bad(mtd, off, &rwsize,
 622                                                          NULL, maxsize,
 623                                                          (u_char *)addr,
 624                                                          WITH_WR_VERIFY);
 625#ifdef CONFIG_CMD_NAND_TRIMFFS
 626                } else if (!strcmp(s, ".trimffs")) {
 627                        if (read) {
 628                                printf("Unknown nand command suffix '%s'\n", s);
 629                                return 1;
 630                        }
 631                        ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
 632                                                maxsize, (u_char *)addr,
 633                                                WITH_DROP_FFS | WITH_WR_VERIFY);
 634#endif
 635                } else if (!strcmp(s, ".oob")) {
 636                        /* out-of-band data */
 637                        mtd_oob_ops_t ops = {
 638                                .oobbuf = (u8 *)addr,
 639                                .ooblen = rwsize,
 640                                .mode = MTD_OPS_RAW
 641                        };
 642
 643                        if (read)
 644                                ret = mtd_read_oob(mtd, off, &ops);
 645                        else
 646                                ret = mtd_write_oob(mtd, off, &ops);
 647                } else if (raw) {
 648                        ret = raw_access(mtd, addr, off, pagecount, read,
 649                                         no_verify);
 650                } else {
 651                        printf("Unknown nand command suffix '%s'.\n", s);
 652                        return 1;
 653                }
 654
 655                printf(" %zu bytes %s: %s\n", rwsize,
 656                       read ? "read" : "written", ret ? "ERROR" : "OK");
 657
 658                return ret == 0 ? 0 : 1;
 659        }
 660
 661#ifdef CONFIG_CMD_NAND_TORTURE
 662        if (strcmp(cmd, "torture") == 0) {
 663                loff_t endoff;
 664                unsigned int failed = 0, passed = 0;
 665
 666                if (argc < 3)
 667                        goto usage;
 668
 669                if (!str2off(argv[2], &off)) {
 670                        puts("Offset is not a valid number\n");
 671                        return 1;
 672                }
 673
 674                size = mtd->erasesize;
 675                if (argc > 3) {
 676                        if (!str2off(argv[3], &size)) {
 677                                puts("Size is not a valid number\n");
 678                                return 1;
 679                        }
 680                }
 681
 682                endoff = off + size;
 683                if (endoff > mtd->size) {
 684                        puts("Arguments beyond end of NAND\n");
 685                        return 1;
 686                }
 687
 688                off = round_down(off, mtd->erasesize);
 689                endoff = round_up(endoff, mtd->erasesize);
 690                size = endoff - off;
 691                printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
 692                       dev, off, size, mtd->erasesize);
 693                while (off < endoff) {
 694                        ret = nand_torture(mtd, off);
 695                        if (ret) {
 696                                failed++;
 697                                printf("  block at 0x%llx failed\n", off);
 698                        } else {
 699                                passed++;
 700                        }
 701                        off += mtd->erasesize;
 702                }
 703                printf(" Passed: %u, failed: %u\n", passed, failed);
 704                return failed != 0;
 705        }
 706#endif
 707
 708        if (strcmp(cmd, "markbad") == 0) {
 709                argc -= 2;
 710                argv += 2;
 711
 712                if (argc <= 0)
 713                        goto usage;
 714
 715                while (argc > 0) {
 716                        addr = hextoul(*argv, NULL);
 717
 718                        if (mtd_block_markbad(mtd, addr)) {
 719                                printf("block 0x%08lx NOT marked "
 720                                        "as bad! ERROR %d\n",
 721                                        addr, ret);
 722                                ret = 1;
 723                        } else {
 724                                printf("block 0x%08lx successfully "
 725                                        "marked as bad\n",
 726                                        addr);
 727                        }
 728                        --argc;
 729                        ++argv;
 730                }
 731                return ret;
 732        }
 733
 734        if (strcmp(cmd, "biterr") == 0) {
 735                /* todo */
 736                return 1;
 737        }
 738
 739#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 740        if (strcmp(cmd, "lock") == 0) {
 741                int tight = 0;
 742                int status = 0;
 743                if (argc == 3) {
 744                        if (!strcmp("tight", argv[2]))
 745                                tight = 1;
 746                        if (!strcmp("status", argv[2]))
 747                                status = 1;
 748                }
 749                if (status) {
 750                        do_nand_status(mtd);
 751                } else {
 752                        if (!nand_lock(mtd, tight)) {
 753                                puts("NAND flash successfully locked\n");
 754                        } else {
 755                                puts("Error locking NAND flash\n");
 756                                return 1;
 757                        }
 758                }
 759                return 0;
 760        }
 761
 762        if (strncmp(cmd, "unlock", 5) == 0) {
 763                int allexcept = 0;
 764
 765                s = strchr(cmd, '.');
 766
 767                if (s && !strcmp(s, ".allexcept"))
 768                        allexcept = 1;
 769
 770                if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
 771                                     &maxsize, MTD_DEV_TYPE_NAND,
 772                                     mtd->size) < 0)
 773                        return 1;
 774
 775                if (set_dev(dev))
 776                        return 1;
 777
 778                mtd = get_nand_dev_by_index(dev);
 779
 780                if (!nand_unlock(mtd, off, size, allexcept)) {
 781                        puts("NAND flash successfully unlocked\n");
 782                } else {
 783                        puts("Error unlocking NAND flash, "
 784                             "write and erase will probably fail\n");
 785                        return 1;
 786                }
 787                return 0;
 788        }
 789#endif
 790
 791usage:
 792        return CMD_RET_USAGE;
 793}
 794
 795#ifdef CONFIG_SYS_LONGHELP
 796static char nand_help_text[] =
 797        "info - show available NAND devices\n"
 798        "nand device [dev] - show or set current device\n"
 799        "nand read - addr off|partition size\n"
 800        "nand write - addr off|partition size\n"
 801        "    read/write 'size' bytes starting at offset 'off'\n"
 802        "    to/from memory address 'addr', skipping bad blocks.\n"
 803        "nand read.raw - addr off|partition [count]\n"
 804        "nand write.raw[.noverify] - addr off|partition [count]\n"
 805        "    Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
 806#ifdef CONFIG_CMD_NAND_TRIMFFS
 807        "nand write.trimffs - addr off|partition size\n"
 808        "    write 'size' bytes starting at offset 'off' from memory address\n"
 809        "    'addr', skipping bad blocks and dropping any pages at the end\n"
 810        "    of eraseblocks that contain only 0xFF\n"
 811#endif
 812        "nand erase[.spread] [clean] off size - erase 'size' bytes "
 813        "from offset 'off'\n"
 814        "    With '.spread', erase enough for given file size, otherwise,\n"
 815        "    'size' includes skipped bad blocks.\n"
 816        "nand erase.part [clean] partition - erase entire mtd partition'\n"
 817        "nand erase.chip [clean] - erase entire chip'\n"
 818        "nand bad - show bad blocks\n"
 819        "nand dump[.oob] off - dump page\n"
 820#ifdef CONFIG_CMD_NAND_TORTURE
 821        "nand torture off - torture one block at offset\n"
 822        "nand torture off [size] - torture blocks from off to off+size\n"
 823#endif
 824        "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
 825        "    really clean NAND erasing bad blocks (UNSAFE)\n"
 826        "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
 827        "nand biterr off - make a bit error at offset (UNSAFE)"
 828#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 829        "\n"
 830        "nand lock [tight] [status]\n"
 831        "    bring nand to lock state or display locked pages\n"
 832        "nand unlock[.allexcept] [offset] [size] - unlock section"
 833#endif
 834#ifdef CONFIG_ENV_OFFSET_OOB
 835        "\n"
 836        "nand env.oob - environment offset in OOB of block 0 of"
 837        "    first device.\n"
 838        "nand env.oob set off|partition - set enviromnent offset\n"
 839        "nand env.oob get - get environment offset"
 840#endif
 841        "";
 842#endif
 843
 844U_BOOT_CMD(
 845        nand, CONFIG_SYS_MAXARGS, 1, do_nand,
 846        "NAND sub-system", nand_help_text
 847);
 848
 849static int nand_load_image(struct cmd_tbl *cmdtp, struct mtd_info *mtd,
 850                           ulong offset, ulong addr, char *cmd)
 851{
 852        int r;
 853        char *s;
 854        size_t cnt;
 855#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
 856        image_header_t *hdr;
 857#endif
 858#if defined(CONFIG_FIT)
 859        const void *fit_hdr = NULL;
 860#endif
 861
 862        s = strchr(cmd, '.');
 863        if (s != NULL &&
 864            (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
 865                printf("Unknown nand load suffix '%s'\n", s);
 866                bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
 867                return 1;
 868        }
 869
 870        printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
 871
 872        cnt = mtd->writesize;
 873        r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
 874                               (u_char *)addr);
 875        if (r) {
 876                puts("** Read error\n");
 877                bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
 878                return 1;
 879        }
 880        bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
 881
 882        switch (genimg_get_format ((void *)addr)) {
 883#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
 884        case IMAGE_FORMAT_LEGACY:
 885                hdr = (image_header_t *)addr;
 886
 887                bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
 888                image_print_contents (hdr);
 889
 890                cnt = image_get_image_size (hdr);
 891                break;
 892#endif
 893#if defined(CONFIG_FIT)
 894        case IMAGE_FORMAT_FIT:
 895                fit_hdr = (const void *)addr;
 896                puts ("Fit image detected...\n");
 897
 898                cnt = fit_get_size (fit_hdr);
 899                break;
 900#endif
 901        default:
 902                bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
 903                puts ("** Unknown image type\n");
 904                return 1;
 905        }
 906        bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
 907
 908        r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
 909                               (u_char *)addr);
 910        if (r) {
 911                puts("** Read error\n");
 912                bootstage_error(BOOTSTAGE_ID_NAND_READ);
 913                return 1;
 914        }
 915        bootstage_mark(BOOTSTAGE_ID_NAND_READ);
 916
 917#if defined(CONFIG_FIT)
 918        /* This cannot be done earlier, we need complete FIT image in RAM first */
 919        if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
 920                if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 921                        bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
 922                        puts ("** Bad FIT image format\n");
 923                        return 1;
 924                }
 925                bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
 926                fit_print_contents (fit_hdr);
 927        }
 928#endif
 929
 930        /* Loading ok, update default load address */
 931
 932        image_load_addr = addr;
 933
 934        return bootm_maybe_autostart(cmdtp, cmd);
 935}
 936
 937static int do_nandboot(struct cmd_tbl *cmdtp, int flag, int argc,
 938                       char *const argv[])
 939{
 940        char *boot_device = NULL;
 941        int idx;
 942        ulong addr, offset = 0;
 943        struct mtd_info *mtd;
 944#if defined(CONFIG_CMD_MTDPARTS)
 945        struct mtd_device *dev;
 946        struct part_info *part;
 947        u8 pnum;
 948
 949        if (argc >= 2) {
 950                char *p = (argc == 2) ? argv[1] : argv[2];
 951                if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
 952                    (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
 953                        if (dev->id->type != MTD_DEV_TYPE_NAND) {
 954                                puts("Not a NAND device\n");
 955                                return 1;
 956                        }
 957                        if (argc > 3)
 958                                goto usage;
 959                        if (argc == 3)
 960                                addr = hextoul(argv[1], NULL);
 961                        else
 962                                addr = CONFIG_SYS_LOAD_ADDR;
 963
 964                        mtd = get_nand_dev_by_index(dev->id->num);
 965                        return nand_load_image(cmdtp, mtd, part->offset,
 966                                               addr, argv[0]);
 967                }
 968        }
 969#endif
 970
 971        bootstage_mark(BOOTSTAGE_ID_NAND_PART);
 972        switch (argc) {
 973        case 1:
 974                addr = CONFIG_SYS_LOAD_ADDR;
 975                boot_device = env_get("bootdevice");
 976                break;
 977        case 2:
 978                addr = hextoul(argv[1], NULL);
 979                boot_device = env_get("bootdevice");
 980                break;
 981        case 3:
 982                addr = hextoul(argv[1], NULL);
 983                boot_device = argv[2];
 984                break;
 985        case 4:
 986                addr = hextoul(argv[1], NULL);
 987                boot_device = argv[2];
 988                offset = hextoul(argv[3], NULL);
 989                break;
 990        default:
 991#if defined(CONFIG_CMD_MTDPARTS)
 992usage:
 993#endif
 994                bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
 995                return CMD_RET_USAGE;
 996        }
 997        bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
 998
 999        if (!boot_device) {
1000                puts("\n** No boot device **\n");
1001                bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1002                return 1;
1003        }
1004        bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1005
1006        idx = hextoul(boot_device, NULL);
1007
1008        mtd = get_nand_dev_by_index(idx);
1009        if (!mtd) {
1010                printf("\n** Device %d not available\n", idx);
1011                bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1012                return 1;
1013        }
1014        bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1015
1016        return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
1017}
1018
1019U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1020        "boot from NAND device",
1021        "[partition] | [[[loadAddr] dev] offset]"
1022);
1023