⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand_util.c

📁 嵌入式试验箱S3C2410的bootloader源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        buffer += readlen;        if (opts->writeoob) {            /* read OOB data from input memory block, exit             * on failure */            memcpy(oob_buf, buffer, meminfo->oobsize);            buffer += meminfo->oobsize;            /* write OOB data first, as ecc will be placed             * in there*/            result = meminfo->write_oob(meminfo,                            mtdoffset,                            meminfo->oobsize,                            &written,                            (unsigned char *)                            &oob_buf);            if (result != 0) {                printf("\nMTD writeoob failure: %d\n",                       result);                goto restoreoob;            }            imglen -= meminfo->oobsize;        }        /* write out the page data */        result = meminfo->write(meminfo,                    mtdoffset,                    meminfo->oobblock,                    &written,                    (unsigned char *) &data_buf);        if (result != 0) {            printf("writing NAND page at offset 0x%lx failed\n",                   mtdoffset);            goto restoreoob;        }        imglen -= readlen;        if (!opts->quiet) {            int percent = (int)                ((unsigned long long)                 (opts->length-imglen) * 100                 / opts->length);            /* output progress message only at whole percent             * steps to reduce the number of messages printed             * on (slow) serial consoles             */            if (percent != percent_complete) {                printf("\rWriting data at 0x%x "                       "-- %3d%% complete.",                       mtdoffset, percent);                percent_complete = percent;            }        }        mtdoffset += meminfo->oobblock;    }    if (!opts->quiet)        printf("\n");restoreoob:    if (oobinfochanged) {        memcpy(&meminfo->oobinfo, &old_oobinfo,               sizeof(meminfo->oobinfo));    }    if (imglen > 0) {        printf("Data did not fit into device, due to bad blocks\n");        return -1;    }    /* return happy */    return 0;}/** * nand_read_opts: - read image from NAND flash with support for various options * * @param meminfo   NAND device to erase * @param opts      read options (@see struct nand_read_options) * @return      0 in case of success * */int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts){    int imglen = opts->length;    int pagelen;    int baderaseblock;    int blockstart = -1;    int percent_complete = -1;    loff_t offs;    size_t readlen;    ulong mtdoffset = opts->offset;    u_char *buffer = opts->buffer;    int result;    struct nand_oobinfo old_oobinfo;    int oobinfochanged = 0;    /* make sure device page sizes are valid */    if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)        && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)        && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {        printf("Unknown flash (not normal NAND)\n");        return -1;    }    pagelen = meminfo->oobblock        + ((opts->readoob != 0) ? meminfo->oobsize : 0);    /* check, if length is not larger than device */    if (((imglen / pagelen) * meminfo->oobblock)         > (meminfo->size - opts->offset)) {        printf("Image %d bytes, NAND page %d bytes, "               "OOB area %u bytes, device size %u bytes\n",               imglen, pagelen, meminfo->oobblock, meminfo->size);        printf("Input block is larger than device\n");        return -1;    }    if (!opts->quiet)        printf("\n");    /* read the current oob info */    memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo));    /* write without ecc? */    if (opts->noecc) {        memcpy(&meminfo->oobinfo, &none_oobinfo,               sizeof(meminfo->oobinfo));        oobinfochanged = 1;    }    /* get data from input and write to the device */    while (imglen && (mtdoffset < meminfo->size)) {        WATCHDOG_RESET ();        /*         * new eraseblock, check for bad block(s). Stay in the         * loop to be sure if the offset changes because of         * a bad block, that the next block that will be         * written to is also checked. Thus avoiding errors if         * the block(s) after the skipped block(s) is also bad         * (number of blocks depending on the blockalign         */        while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) {            blockstart = mtdoffset & (~meminfo->erasesize+1);            offs = blockstart;            baderaseblock = 0;            /* check all the blocks in an erase block for             * bad blocks */            if (!opts->nocheckbadblk) {                do {                    int ret = meminfo->block_isbad(meminfo, offs);                    if (ret < 0) {                        printf("Bad block check failed\n");                        goto restoreoob;                    }                    if (ret == 1) {                        baderaseblock = 1;                        if (!opts->quiet)                            printf("\rBad block at 0x%lx "                                   "in erase block from "                                   "0x%x will be skipped\n",                                   (long) offs,                                   blockstart);                    }                    if (baderaseblock) {                        mtdoffset = blockstart                            + meminfo->erasesize;                    }                    offs +=  meminfo->erasesize;                } while (offs < blockstart + meminfo->erasesize);            }        }        /* read page data to memory buffer */        result = meminfo->read(meminfo,                       mtdoffset,                       meminfo->oobblock,                       &readlen,                       (unsigned char *) &data_buf);        if (result != 0) {            printf("reading NAND page at offset 0x%lx failed\n",                   mtdoffset);            goto restoreoob;        }        if (imglen < readlen) {            readlen = imglen;        }        memcpy(buffer, data_buf, readlen);        buffer += readlen;        imglen -= readlen;        if (opts->readoob) {            result = meminfo->read_oob(meminfo,                           mtdoffset,                           meminfo->oobsize,                           &readlen,                           (unsigned char *)                           &oob_buf);            if (result != 0) {                printf("\nMTD readoob failure: %d\n",                       result);                goto restoreoob;            }            if (imglen < readlen) {                readlen = imglen;            }            memcpy(buffer, oob_buf, readlen);            buffer += readlen;            imglen -= readlen;        }        if (!opts->quiet) {            int percent = (int)                ((unsigned long long)                 (opts->length-imglen) * 100                 / opts->length);            /* output progress message only at whole percent             * steps to reduce the number of messages printed             * on (slow) serial consoles             */            if (percent != percent_complete) {            if (!opts->quiet)                printf("\rReading data from 0x%x "                       "-- %3d%% complete.",                       mtdoffset, percent);                percent_complete = percent;            }        }        mtdoffset += meminfo->oobblock;    }    if (!opts->quiet)        printf("\n");restoreoob:    if (oobinfochanged) {        memcpy(&meminfo->oobinfo, &old_oobinfo,               sizeof(meminfo->oobinfo));    }    if (imglen > 0) {        printf("Could not read entire image due to bad blocks\n");        return -1;    }    /* return happy */    return 0;}/****************************************************************************** * Support for locking / unlocking operations of some NAND devices *****************************************************************************/#define NAND_CMD_LOCK       0x2a#define NAND_CMD_LOCK_TIGHT 0x2c#define NAND_CMD_UNLOCK1    0x23#define NAND_CMD_UNLOCK2    0x24#define NAND_CMD_LOCK_STATUS    0x7a/** * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT *        state * * @param meminfo   nand mtd instance * @param tight     bring device in lock tight mode * * @return      0 on success, -1 in case of error * * The lock / lock-tight command only applies to the whole chip. To get some * parts of the chip lock and others unlocked use the following sequence: * * - Lock all pages of the chip using nand_lock(mtd, 0) (or the lockpre pin) * - Call nand_unlock() once for each consecutive area to be unlocked * - If desired: Bring the chip to the lock-tight state using nand_lock(mtd, 1) * *   If the device is in lock-tight state software can't change the *   current active lock/unlock state of all pages. nand_lock() / nand_unlock() *   calls will fail. It is only posible to leave lock-tight state by *   an hardware signal (low pulse on _WP pin) or by power down. */int nand_lock(nand_info_t *meminfo, int tight){    int ret = 0;    int status;    struct nand_chip *this = meminfo->priv;    /* select the NAND device */    this->select_chip(meminfo, 0);    this->cmdfunc(meminfo,              (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),              -1, -1);    /* call wait ready function */    status = this->waitfunc(meminfo, this, FL_WRITING);    /* see if device thinks it succeeded */    if (status & 0x01) {        ret = -1;    }    /* de-select the NAND device */    this->select_chip(meminfo, -1);    return ret;}/** * nand_get_lock_status: - query current lock state from one page of NAND *             flash * * @param meminfo   nand mtd instance * @param offset    page address to query (muss be page aligned!) * * @return      -1 in case of error *          >0 lock status: *            bitfield with the following combinations: *            NAND_LOCK_STATUS_TIGHT: page in tight state *            NAND_LOCK_STATUS_LOCK:  page locked *            NAND_LOCK_STATUS_UNLOCK: page unlocked * */int nand_get_lock_status(nand_info_t *meminfo, ulong offset){    int ret = 0;    int chipnr;    int page;    struct nand_chip *this = meminfo->priv;    /* select the NAND device */    chipnr = (int)(offset >> this->chip_shift);    this->select_chip(meminfo, chipnr);    if ((offset & (meminfo->oobblock - 1)) != 0) {        printf ("nand_get_lock_status: "            "Start address must be beginning of "            "nand page!\n");        ret = -1;        goto out;    }    /* check the Lock Status */    page = (int)(offset >> this->page_shift);    this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask);    ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT                      | NAND_LOCK_STATUS_LOCK                      | NAND_LOCK_STATUS_UNLOCK); out:    /* de-select the NAND device */    this->select_chip(meminfo, -1);    return ret;}/** * nand_unlock: - Unlock area of NAND pages *        only one consecutive area can be unlocked at one time! * * @param meminfo   nand mtd instance * @param start     start byte address * @param length    number of bytes to unlock (must be a multiple of *          page size nand->oobblock) * * @return      0 on success, -1 in case of error */int nand_unlock(nand_info_t *meminfo, ulong start, ulong length){    int ret = 0;    int chipnr;    int status;    int page;    struct nand_chip *this = meminfo->priv;    printf ("nand_unlock: start: %08x, length: %d!\n",        (int)start, (int)length);    /* select the NAND device */    chipnr = (int)(start >> this->chip_shift);    this->select_chip(meminfo, chipnr);    /* check the WP bit */    this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1);    if ((this->read_byte(meminfo) & 0x80) == 0) {        printf ("nand_unlock: Device is write protected!\n");        ret = -1;        goto out;    }    if ((start & (meminfo->oobblock - 1)) != 0) {        printf ("nand_unlock: Start address must be beginning of "            "nand page!\n");        ret = -1;        goto out;    }    if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) {        printf ("nand_unlock: Length must be a multiple of nand page "            "size!\n");        ret = -1;        goto out;    }    /* submit address of first page to unlock */    page = (int)(start >> this->page_shift);    this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask);    /* submit ADDRESS of LAST page to unlock */    page += (int)(length >> this->page_shift) - 1;    this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask);    /* call wait ready function */    status = this->waitfunc(meminfo, this, FL_WRITING);    /* see if device thinks it succeeded */    if (status & 0x01) {        /* there was an error */        ret = -1;        goto out;    } out:    /* de-select the NAND device */    this->select_chip(meminfo, -1);    return ret;}#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -