uboot/drivers/mtd/nand/raw/nand_util.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * drivers/mtd/nand/raw/nand_util.c
   4 *
   5 * Copyright (C) 2006 by Weiss-Electronic GmbH.
   6 * All rights reserved.
   7 *
   8 * @author:     Guido Classen <clagix@gmail.com>
   9 * @descr:      NAND Flash support
  10 * @references: borrowed heavily from Linux mtd-utils code:
  11 *              flash_eraseall.c by Arcom Control System Ltd
  12 *              nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
  13 *                             and Thomas Gleixner (tglx@linutronix.de)
  14 *
  15 * Copyright (C) 2008 Nokia Corporation: drop_ffs() function by
  16 * Artem Bityutskiy <dedekind1@gmail.com> from mtd-utils
  17 *
  18 * Copyright 2010 Freescale Semiconductor
  19 */
  20
  21#include <common.h>
  22#include <command.h>
  23#include <watchdog.h>
  24#include <malloc.h>
  25#include <memalign.h>
  26#include <div64.h>
  27
  28#include <linux/errno.h>
  29#include <linux/mtd/mtd.h>
  30#include <nand.h>
  31#include <jffs2/jffs2.h>
  32
  33typedef struct erase_info       erase_info_t;
  34typedef struct mtd_info         mtd_info_t;
  35
  36/* support only for native endian JFFS2 */
  37#define cpu_to_je16(x) (x)
  38#define cpu_to_je32(x) (x)
  39
  40/**
  41 * nand_erase_opts: - erase NAND flash with support for various options
  42 *                    (jffs2 formatting)
  43 *
  44 * @param mtd           nand mtd instance to erase
  45 * @param opts          options,  @see struct nand_erase_options
  46 * @return              0 in case of success
  47 *
  48 * This code is ported from flash_eraseall.c from Linux mtd utils by
  49 * Arcom Control System Ltd.
  50 */
  51int nand_erase_opts(struct mtd_info *mtd,
  52                    const nand_erase_options_t *opts)
  53{
  54        struct jffs2_unknown_node cleanmarker;
  55        erase_info_t erase;
  56        unsigned long erase_length, erased_length; /* in blocks */
  57        int result;
  58        int percent_complete = -1;
  59        const char *mtd_device = mtd->name;
  60        struct mtd_oob_ops oob_opts;
  61        struct nand_chip *chip = mtd_to_nand(mtd);
  62
  63        if ((opts->offset & (mtd->erasesize - 1)) != 0) {
  64                printf("Attempt to erase non block-aligned data\n");
  65                return -1;
  66        }
  67
  68        memset(&erase, 0, sizeof(erase));
  69        memset(&oob_opts, 0, sizeof(oob_opts));
  70
  71        erase.mtd = mtd;
  72        erase.len = mtd->erasesize;
  73        erase.addr = opts->offset;
  74        erase_length = lldiv(opts->length + mtd->erasesize - 1,
  75                             mtd->erasesize);
  76
  77        cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  78        cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
  79        cleanmarker.totlen = cpu_to_je32(8);
  80
  81        /* scrub option allows to erase badblock. To prevent internal
  82         * check from erase() method, set block check method to dummy
  83         * and disable bad block table while erasing.
  84         */
  85        if (opts->scrub) {
  86                erase.scrub = opts->scrub;
  87                /*
  88                 * We don't need the bad block table anymore...
  89                 * after scrub, there are no bad blocks left!
  90                 */
  91                if (chip->bbt) {
  92                        kfree(chip->bbt);
  93                }
  94                chip->bbt = NULL;
  95                chip->options &= ~NAND_BBT_SCANNED;
  96        }
  97
  98        for (erased_length = 0;
  99             erased_length < erase_length;
 100             erase.addr += mtd->erasesize) {
 101
 102                WATCHDOG_RESET();
 103
 104                if (opts->lim && (erase.addr >= (opts->offset + opts->lim))) {
 105                        puts("Size of erase exceeds limit\n");
 106                        return -EFBIG;
 107                }
 108                if (!opts->scrub) {
 109                        int ret = mtd_block_isbad(mtd, erase.addr);
 110                        if (ret > 0) {
 111                                if (!opts->quiet)
 112                                        printf("\rSkipping bad block at  "
 113                                               "0x%08llx                 "
 114                                               "                         \n",
 115                                               erase.addr);
 116
 117                                if (!opts->spread)
 118                                        erased_length++;
 119
 120                                continue;
 121
 122                        } else if (ret < 0) {
 123                                printf("\n%s: MTD get bad block failed: %d\n",
 124                                       mtd_device,
 125                                       ret);
 126                                return -1;
 127                        }
 128                }
 129
 130                erased_length++;
 131
 132                result = mtd_erase(mtd, &erase);
 133                if (result != 0) {
 134                        printf("\n%s: MTD Erase failure: %d\n",
 135                               mtd_device, result);
 136                        continue;
 137                }
 138
 139                /* format for JFFS2 ? */
 140                if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) {
 141                        struct mtd_oob_ops ops;
 142                        ops.ooblen = 8;
 143                        ops.datbuf = NULL;
 144                        ops.oobbuf = (uint8_t *)&cleanmarker;
 145                        ops.ooboffs = 0;
 146                        ops.mode = MTD_OPS_AUTO_OOB;
 147
 148                        result = mtd_write_oob(mtd, erase.addr, &ops);
 149                        if (result != 0) {
 150                                printf("\n%s: MTD writeoob failure: %d\n",
 151                                       mtd_device, result);
 152                                continue;
 153                        }
 154                }
 155
 156                if (!opts->quiet) {
 157                        unsigned long long n = erased_length * 100ULL;
 158                        int percent;
 159
 160                        do_div(n, erase_length);
 161                        percent = (int)n;
 162
 163                        /* output progress message only at whole percent
 164                         * steps to reduce the number of messages printed
 165                         * on (slow) serial consoles
 166                         */
 167                        if (percent != percent_complete) {
 168                                percent_complete = percent;
 169
 170                                printf("\rErasing at 0x%llx -- %3d%% complete.",
 171                                       erase.addr, percent);
 172
 173                                if (opts->jffs2 && result == 0)
 174                                        printf(" Cleanmarker written at 0x%llx.",
 175                                               erase.addr);
 176                        }
 177                }
 178        }
 179        if (!opts->quiet)
 180                printf("\n");
 181
 182        return 0;
 183}
 184
 185#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 186
 187#define NAND_CMD_LOCK_TIGHT     0x2c
 188#define NAND_CMD_LOCK_STATUS    0x7a
 189 
 190/******************************************************************************
 191 * Support for locking / unlocking operations of some NAND devices
 192 *****************************************************************************/
 193
 194/**
 195 * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT
 196 *            state
 197 *
 198 * @param mtd           nand mtd instance
 199 * @param tight         bring device in lock tight mode
 200 *
 201 * @return              0 on success, -1 in case of error
 202 *
 203 * The lock / lock-tight command only applies to the whole chip. To get some
 204 * parts of the chip lock and others unlocked use the following sequence:
 205 *
 206 * - Lock all pages of the chip using nand_lock(mtd, 0) (or the lockpre pin)
 207 * - Call nand_unlock() once for each consecutive area to be unlocked
 208 * - If desired: Bring the chip to the lock-tight state using nand_lock(mtd, 1)
 209 *
 210 *   If the device is in lock-tight state software can't change the
 211 *   current active lock/unlock state of all pages. nand_lock() / nand_unlock()
 212 *   calls will fail. It is only posible to leave lock-tight state by
 213 *   an hardware signal (low pulse on _WP pin) or by power down.
 214 */
 215int nand_lock(struct mtd_info *mtd, int tight)
 216{
 217        int ret = 0;
 218        int status;
 219        struct nand_chip *chip = mtd_to_nand(mtd);
 220
 221        /* select the NAND device */
 222        chip->select_chip(mtd, 0);
 223
 224        /* check the Lock Tight Status */
 225        chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, 0);
 226        if (chip->read_byte(mtd) & NAND_LOCK_STATUS_TIGHT) {
 227                printf("nand_lock: Device is locked tight!\n");
 228                ret = -1;
 229                goto out;
 230        }
 231
 232        chip->cmdfunc(mtd,
 233                      (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),
 234                      -1, -1);
 235
 236        /* call wait ready function */
 237        status = chip->waitfunc(mtd, chip);
 238
 239        /* see if device thinks it succeeded */
 240        if (status & 0x01) {
 241                ret = -1;
 242        }
 243
 244 out:
 245        /* de-select the NAND device */
 246        chip->select_chip(mtd, -1);
 247        return ret;
 248}
 249
 250/**
 251 * nand_get_lock_status: - query current lock state from one page of NAND
 252 *                         flash
 253 *
 254 * @param mtd           nand mtd instance
 255 * @param offset        page address to query (must be page-aligned!)
 256 *
 257 * @return              -1 in case of error
 258 *                      >0 lock status:
 259 *                        bitfield with the following combinations:
 260 *                        NAND_LOCK_STATUS_TIGHT: page in tight state
 261 *                        NAND_LOCK_STATUS_UNLOCK: page unlocked
 262 *
 263 */
 264int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
 265{
 266        int ret = 0;
 267        int chipnr;
 268        int page;
 269        struct nand_chip *chip = mtd_to_nand(mtd);
 270
 271        /* select the NAND device */
 272        chipnr = (int)(offset >> chip->chip_shift);
 273        chip->select_chip(mtd, chipnr);
 274
 275
 276        if ((offset & (mtd->writesize - 1)) != 0) {
 277                printf("nand_get_lock_status: "
 278                        "Start address must be beginning of "
 279                        "nand page!\n");
 280                ret = -1;
 281                goto out;
 282        }
 283
 284        /* check the Lock Status */
 285        page = (int)(offset >> chip->page_shift);
 286        chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask);
 287
 288        ret = chip->read_byte(mtd) & (NAND_LOCK_STATUS_TIGHT
 289                                          | NAND_LOCK_STATUS_UNLOCK);
 290
 291 out:
 292        /* de-select the NAND device */
 293        chip->select_chip(mtd, -1);
 294        return ret;
 295}
 296
 297/**
 298 * nand_unlock: - Unlock area of NAND pages
 299 *                only one consecutive area can be unlocked at one time!
 300 *
 301 * @param mtd           nand mtd instance
 302 * @param start         start byte address
 303 * @param length        number of bytes to unlock (must be a multiple of
 304 *                      page size mtd->writesize)
 305 * @param allexcept     if set, unlock everything not selected
 306 *
 307 * @return              0 on success, -1 in case of error
 308 */
 309int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
 310        int allexcept)
 311{
 312        int ret = 0;
 313        int chipnr;
 314        int status;
 315        int page;
 316        struct nand_chip *chip = mtd_to_nand(mtd);
 317
 318        debug("nand_unlock%s: start: %08llx, length: %zd!\n",
 319                allexcept ? " (allexcept)" : "", start, length);
 320
 321        /* select the NAND device */
 322        chipnr = (int)(start >> chip->chip_shift);
 323        chip->select_chip(mtd, chipnr);
 324
 325        /* check the WP bit */
 326        chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 327        if (!(chip->read_byte(mtd) & NAND_STATUS_WP)) {
 328                printf("nand_unlock: Device is write protected!\n");
 329                ret = -1;
 330                goto out;
 331        }
 332
 333        /* check the Lock Tight Status */
 334        page = (int)(start >> chip->page_shift);
 335        chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask);
 336        if (chip->read_byte(mtd) & NAND_LOCK_STATUS_TIGHT) {
 337                printf("nand_unlock: Device is locked tight!\n");
 338                ret = -1;
 339                goto out;
 340        }
 341
 342        if ((start & (mtd->erasesize - 1)) != 0) {
 343                printf("nand_unlock: Start address must be beginning of "
 344                        "nand block!\n");
 345                ret = -1;
 346                goto out;
 347        }
 348
 349        if (length == 0 || (length & (mtd->erasesize - 1)) != 0) {
 350                printf("nand_unlock: Length must be a multiple of nand block "
 351                        "size %08x!\n", mtd->erasesize);
 352                ret = -1;
 353                goto out;
 354        }
 355
 356        /*
 357         * Set length so that the last address is set to the
 358         * starting address of the last block
 359         */
 360        length -= mtd->erasesize;
 361
 362        /* submit address of first page to unlock */
 363        chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);
 364
 365        /* submit ADDRESS of LAST page to unlock */
 366        page += (int)(length >> chip->page_shift);
 367
 368        /*
 369         * Page addresses for unlocking are supposed to be block-aligned.
 370         * At least some NAND chips use the low bit to indicate that the
 371         * page range should be inverted.
 372         */
 373        if (allexcept)
 374                page |= 1;
 375
 376        chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1, page & chip->pagemask);
 377
 378        /* call wait ready function */
 379        status = chip->waitfunc(mtd, chip);
 380        /* see if device thinks it succeeded */
 381        if (status & 0x01) {
 382                /* there was an error */
 383                ret = -1;
 384                goto out;
 385        }
 386
 387 out:
 388        /* de-select the NAND device */
 389        chip->select_chip(mtd, -1);
 390        return ret;
 391}
 392#endif
 393
 394/**
 395 * check_skip_len
 396 *
 397 * Check if there are any bad blocks, and whether length including bad
 398 * blocks fits into device
 399 *
 400 * @param mtd nand mtd instance
 401 * @param offset offset in flash
 402 * @param length image length
 403 * @param used length of flash needed for the requested length
 404 * @return 0 if the image fits and there are no bad blocks
 405 *         1 if the image fits, but there are bad blocks
 406 *        -1 if the image does not fit
 407 */
 408static int check_skip_len(struct mtd_info *mtd, loff_t offset, size_t length,
 409                          size_t *used)
 410{
 411        size_t len_excl_bad = 0;
 412        int ret = 0;
 413
 414        while (len_excl_bad < length) {
 415                size_t block_len, block_off;
 416                loff_t block_start;
 417
 418                if (offset >= mtd->size)
 419                        return -1;
 420
 421                block_start = offset & ~(loff_t)(mtd->erasesize - 1);
 422                block_off = offset & (mtd->erasesize - 1);
 423                block_len = mtd->erasesize - block_off;
 424
 425                if (!nand_block_isbad(mtd, block_start))
 426                        len_excl_bad += block_len;
 427                else
 428                        ret = 1;
 429
 430                offset += block_len;
 431                *used += block_len;
 432        }
 433
 434        /* If the length is not a multiple of block_len, adjust. */
 435        if (len_excl_bad > length)
 436                *used -= (len_excl_bad - length);
 437
 438        return ret;
 439}
 440
 441#ifdef CONFIG_CMD_NAND_TRIMFFS
 442static size_t drop_ffs(const struct mtd_info *mtd, const u_char *buf,
 443                        const size_t *len)
 444{
 445        size_t l = *len;
 446        ssize_t i;
 447
 448        for (i = l - 1; i >= 0; i--)
 449                if (buf[i] != 0xFF)
 450                        break;
 451
 452        /* The resulting length must be aligned to the minimum flash I/O size */
 453        l = i + 1;
 454        l = (l + mtd->writesize - 1) / mtd->writesize;
 455        l *=  mtd->writesize;
 456
 457        /*
 458         * since the input length may be unaligned, prevent access past the end
 459         * of the buffer
 460         */
 461        return min(l, *len);
 462}
 463#endif
 464
 465/**
 466 * nand_verify_page_oob:
 467 *
 468 * Verify a page of NAND flash, including the OOB.
 469 * Reads page of NAND and verifies the contents and OOB against the
 470 * values in ops.
 471 *
 472 * @param mtd           nand mtd instance
 473 * @param ops           MTD operations, including data to verify
 474 * @param ofs           offset in flash
 475 * @return              0 in case of success
 476 */
 477int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
 478                         loff_t ofs)
 479{
 480        int rval;
 481        struct mtd_oob_ops vops;
 482        size_t verlen = mtd->writesize + mtd->oobsize;
 483
 484        memcpy(&vops, ops, sizeof(vops));
 485
 486        vops.datbuf = memalign(ARCH_DMA_MINALIGN, verlen);
 487
 488        if (!vops.datbuf)
 489                return -ENOMEM;
 490
 491        vops.oobbuf = vops.datbuf + mtd->writesize;
 492
 493        rval = mtd_read_oob(mtd, ofs, &vops);
 494        if (!rval)
 495                rval = memcmp(ops->datbuf, vops.datbuf, vops.len);
 496        if (!rval)
 497                rval = memcmp(ops->oobbuf, vops.oobbuf, vops.ooblen);
 498
 499        free(vops.datbuf);
 500
 501        return rval ? -EIO : 0;
 502}
 503
 504/**
 505 * nand_verify:
 506 *
 507 * Verify a region of NAND flash.
 508 * Reads NAND in page-sized chunks and verifies the contents against
 509 * the contents of a buffer.  The offset into the NAND must be
 510 * page-aligned, and the function doesn't handle skipping bad blocks.
 511 *
 512 * @param mtd           nand mtd instance
 513 * @param ofs           offset in flash
 514 * @param len           buffer length
 515 * @param buf           buffer to read from
 516 * @return              0 in case of success
 517 */
 518int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf)
 519{
 520        int rval = 0;
 521        size_t verofs;
 522        size_t verlen = mtd->writesize;
 523        uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen);
 524
 525        if (!verbuf)
 526                return -ENOMEM;
 527
 528        /* Read the NAND back in page-size groups to limit malloc size */
 529        for (verofs = ofs; verofs < ofs + len;
 530             verofs += verlen, buf += verlen) {
 531                verlen = min(mtd->writesize, (uint32_t)(ofs + len - verofs));
 532                rval = nand_read(mtd, verofs, &verlen, verbuf);
 533                if (!rval || (rval == -EUCLEAN))
 534                        rval = memcmp(buf, verbuf, verlen);
 535
 536                if (rval)
 537                        break;
 538        }
 539
 540        free(verbuf);
 541
 542        return rval ? -EIO : 0;
 543}
 544
 545
 546
 547/**
 548 * nand_write_skip_bad:
 549 *
 550 * Write image to NAND flash.
 551 * Blocks that are marked bad are skipped and the is written to the next
 552 * block instead as long as the image is short enough to fit even after
 553 * skipping the bad blocks.  Due to bad blocks we may not be able to
 554 * perform the requested write.  In the case where the write would
 555 * extend beyond the end of the NAND device, both length and actual (if
 556 * not NULL) are set to 0.  In the case where the write would extend
 557 * beyond the limit we are passed, length is set to 0 and actual is set
 558 * to the required length.
 559 *
 560 * @param mtd           nand mtd instance
 561 * @param offset        offset in flash
 562 * @param length        buffer length
 563 * @param actual        set to size required to write length worth of
 564 *                      buffer or 0 on error, if not NULL
 565 * @param lim           maximum size that actual may be in order to not
 566 *                      exceed the buffer
 567 * @param buffer        buffer to read from
 568 * @param flags         flags modifying the behaviour of the write to NAND
 569 * @return              0 in case of success
 570 */
 571int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
 572                        size_t *actual, loff_t lim, u_char *buffer, int flags)
 573{
 574        int rval = 0, blocksize;
 575        size_t left_to_write = *length;
 576        size_t used_for_write = 0;
 577        u_char *p_buffer = buffer;
 578        int need_skip;
 579
 580        if (actual)
 581                *actual = 0;
 582
 583        blocksize = mtd->erasesize;
 584
 585        /*
 586         * nand_write() handles unaligned, partial page writes.
 587         *
 588         * We allow length to be unaligned, for convenience in
 589         * using the $filesize variable.
 590         *
 591         * However, starting at an unaligned offset makes the
 592         * semantics of bad block skipping ambiguous (really,
 593         * you should only start a block skipping access at a
 594         * partition boundary).  So don't try to handle that.
 595         */
 596        if ((offset & (mtd->writesize - 1)) != 0) {
 597                printf("Attempt to write non page-aligned data\n");
 598                *length = 0;
 599                return -EINVAL;
 600        }
 601
 602        need_skip = check_skip_len(mtd, offset, *length, &used_for_write);
 603
 604        if (actual)
 605                *actual = used_for_write;
 606
 607        if (need_skip < 0) {
 608                printf("Attempt to write outside the flash area\n");
 609                *length = 0;
 610                return -EINVAL;
 611        }
 612
 613        if (used_for_write > lim) {
 614                puts("Size of write exceeds partition or device limit\n");
 615                *length = 0;
 616                return -EFBIG;
 617        }
 618
 619        if (!need_skip && !(flags & WITH_DROP_FFS)) {
 620                rval = nand_write(mtd, offset, length, buffer);
 621
 622                if ((flags & WITH_WR_VERIFY) && !rval)
 623                        rval = nand_verify(mtd, offset, *length, buffer);
 624
 625                if (rval == 0)
 626                        return 0;
 627
 628                *length = 0;
 629                printf("NAND write to offset %llx failed %d\n",
 630                        offset, rval);
 631                return rval;
 632        }
 633
 634        while (left_to_write > 0) {
 635                loff_t block_start = offset & ~(loff_t)(mtd->erasesize - 1);
 636                size_t block_offset = offset & (mtd->erasesize - 1);
 637                size_t write_size, truncated_write_size;
 638
 639                WATCHDOG_RESET();
 640
 641                if (nand_block_isbad(mtd, block_start)) {
 642                        printf("Skip bad block 0x%08llx\n", block_start);
 643                        offset += mtd->erasesize - block_offset;
 644                        continue;
 645                }
 646
 647                if (left_to_write < (blocksize - block_offset))
 648                        write_size = left_to_write;
 649                else
 650                        write_size = blocksize - block_offset;
 651
 652                truncated_write_size = write_size;
 653#ifdef CONFIG_CMD_NAND_TRIMFFS
 654                if (flags & WITH_DROP_FFS)
 655                        truncated_write_size = drop_ffs(mtd, p_buffer,
 656                                        &write_size);
 657#endif
 658
 659                rval = nand_write(mtd, offset, &truncated_write_size,
 660                                p_buffer);
 661
 662                if ((flags & WITH_WR_VERIFY) && !rval)
 663                        rval = nand_verify(mtd, offset,
 664                                truncated_write_size, p_buffer);
 665
 666                offset += write_size;
 667                p_buffer += write_size;
 668
 669                if (rval != 0) {
 670                        printf("NAND write to offset %llx failed %d\n",
 671                                offset, rval);
 672                        *length -= left_to_write;
 673                        return rval;
 674                }
 675
 676                left_to_write -= write_size;
 677        }
 678
 679        return 0;
 680}
 681
 682/**
 683 * nand_read_skip_bad:
 684 *
 685 * Read image from NAND flash.
 686 * Blocks that are marked bad are skipped and the next block is read
 687 * instead as long as the image is short enough to fit even after
 688 * skipping the bad blocks.  Due to bad blocks we may not be able to
 689 * perform the requested read.  In the case where the read would extend
 690 * beyond the end of the NAND device, both length and actual (if not
 691 * NULL) are set to 0.  In the case where the read would extend beyond
 692 * the limit we are passed, length is set to 0 and actual is set to the
 693 * required length.
 694 *
 695 * @param mtd nand mtd instance
 696 * @param offset offset in flash
 697 * @param length buffer length, on return holds number of read bytes
 698 * @param actual set to size required to read length worth of buffer or 0
 699 * on error, if not NULL
 700 * @param lim maximum size that actual may be in order to not exceed the
 701 * buffer
 702 * @param buffer buffer to write to
 703 * @return 0 in case of success
 704 */
 705int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
 706                       size_t *actual, loff_t lim, u_char *buffer)
 707{
 708        int rval;
 709        size_t left_to_read = *length;
 710        size_t used_for_read = 0;
 711        u_char *p_buffer = buffer;
 712        int need_skip;
 713
 714        if ((offset & (mtd->writesize - 1)) != 0) {
 715                printf("Attempt to read non page-aligned data\n");
 716                *length = 0;
 717                if (actual)
 718                        *actual = 0;
 719                return -EINVAL;
 720        }
 721
 722        need_skip = check_skip_len(mtd, offset, *length, &used_for_read);
 723
 724        if (actual)
 725                *actual = used_for_read;
 726
 727        if (need_skip < 0) {
 728                printf("Attempt to read outside the flash area\n");
 729                *length = 0;
 730                return -EINVAL;
 731        }
 732
 733        if (used_for_read > lim) {
 734                puts("Size of read exceeds partition or device limit\n");
 735                *length = 0;
 736                return -EFBIG;
 737        }
 738
 739        if (!need_skip) {
 740                rval = nand_read(mtd, offset, length, buffer);
 741                if (!rval || rval == -EUCLEAN)
 742                        return 0;
 743
 744                *length = 0;
 745                printf("NAND read from offset %llx failed %d\n",
 746                        offset, rval);
 747                return rval;
 748        }
 749
 750        while (left_to_read > 0) {
 751                size_t block_offset = offset & (mtd->erasesize - 1);
 752                size_t read_length;
 753
 754                WATCHDOG_RESET();
 755
 756                if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
 757                        printf("Skipping bad block 0x%08llx\n",
 758                                offset & ~(mtd->erasesize - 1));
 759                        offset += mtd->erasesize - block_offset;
 760                        continue;
 761                }
 762
 763                if (left_to_read < (mtd->erasesize - block_offset))
 764                        read_length = left_to_read;
 765                else
 766                        read_length = mtd->erasesize - block_offset;
 767
 768                rval = nand_read(mtd, offset, &read_length, p_buffer);
 769                if (rval && rval != -EUCLEAN) {
 770                        printf("NAND read from offset %llx failed %d\n",
 771                                offset, rval);
 772                        *length -= left_to_read;
 773                        return rval;
 774                }
 775
 776                left_to_read -= read_length;
 777                offset       += read_length;
 778                p_buffer     += read_length;
 779        }
 780
 781        return 0;
 782}
 783
 784#ifdef CONFIG_CMD_NAND_TORTURE
 785
 786/**
 787 * check_pattern:
 788 *
 789 * Check if buffer contains only a certain byte pattern.
 790 *
 791 * @param buf buffer to check
 792 * @param patt the pattern to check
 793 * @param size buffer size in bytes
 794 * @return 1 if there are only patt bytes in buf
 795 *         0 if something else was found
 796 */
 797static int check_pattern(const u_char *buf, u_char patt, int size)
 798{
 799        int i;
 800
 801        for (i = 0; i < size; i++)
 802                if (buf[i] != patt)
 803                        return 0;
 804        return 1;
 805}
 806
 807/**
 808 * nand_torture:
 809 *
 810 * Torture a block of NAND flash.
 811 * This is useful to determine if a block that caused a write error is still
 812 * good or should be marked as bad.
 813 *
 814 * @param mtd nand mtd instance
 815 * @param offset offset in flash
 816 * @return 0 if the block is still good
 817 */
 818int nand_torture(struct mtd_info *mtd, loff_t offset)
 819{
 820        u_char patterns[] = {0xa5, 0x5a, 0x00};
 821        struct erase_info instr = {
 822                .mtd = mtd,
 823                .addr = offset,
 824                .len = mtd->erasesize,
 825        };
 826        size_t retlen;
 827        int err, ret = -1, i, patt_count;
 828        u_char *buf;
 829
 830        if ((offset & (mtd->erasesize - 1)) != 0) {
 831                puts("Attempt to torture a block at a non block-aligned offset\n");
 832                return -EINVAL;
 833        }
 834
 835        if (offset + mtd->erasesize > mtd->size) {
 836                puts("Attempt to torture a block outside the flash area\n");
 837                return -EINVAL;
 838        }
 839
 840        patt_count = ARRAY_SIZE(patterns);
 841
 842        buf = malloc_cache_aligned(mtd->erasesize);
 843        if (buf == NULL) {
 844                puts("Out of memory for erase block buffer\n");
 845                return -ENOMEM;
 846        }
 847
 848        for (i = 0; i < patt_count; i++) {
 849                err = mtd_erase(mtd, &instr);
 850                if (err) {
 851                        printf("%s: erase() failed for block at 0x%llx: %d\n",
 852                                mtd->name, instr.addr, err);
 853                        goto out;
 854                }
 855
 856                /* Make sure the block contains only 0xff bytes */
 857                err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
 858                if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
 859                        printf("%s: read() failed for block at 0x%llx: %d\n",
 860                                mtd->name, instr.addr, err);
 861                        goto out;
 862                }
 863
 864                err = check_pattern(buf, 0xff, mtd->erasesize);
 865                if (!err) {
 866                        printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
 867                                offset);
 868                        ret = -EIO;
 869                        goto out;
 870                }
 871
 872                /* Write a pattern and check it */
 873                memset(buf, patterns[i], mtd->erasesize);
 874                err = mtd_write(mtd, offset, mtd->erasesize, &retlen, buf);
 875                if (err || retlen != mtd->erasesize) {
 876                        printf("%s: write() failed for block at 0x%llx: %d\n",
 877                                mtd->name, instr.addr, err);
 878                        goto out;
 879                }
 880
 881                err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
 882                if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
 883                        printf("%s: read() failed for block at 0x%llx: %d\n",
 884                                mtd->name, instr.addr, err);
 885                        goto out;
 886                }
 887
 888                err = check_pattern(buf, patterns[i], mtd->erasesize);
 889                if (!err) {
 890                        printf("Pattern 0x%.2x checking failed for block at "
 891                                        "0x%llx\n", patterns[i], offset);
 892                        ret = -EIO;
 893                        goto out;
 894                }
 895        }
 896
 897        ret = 0;
 898
 899out:
 900        free(buf);
 901        return ret;
 902}
 903
 904#endif
 905