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

📄 nand_util.c.l

📁 嵌入式试验箱S3C2410的bootloader源代码
💻 L
📖 第 1 页 / 共 2 页
字号:
437         readlen = meminfo->oobblock;438         if (opts->pad && (imglen < readlen)) {439             readlen = imglen;440             memset(data_buf + readlen, 0xff,441                    meminfo->oobblock - readlen);442         }443 444         /* read page data from input memory buffer */445         memcpy(data_buf, buffer, readlen);446         buffer += readlen;447 448         if (opts->writeoob) {449             /* read OOB data from input memory block, exit450              * on failure */451             memcpy(oob_buf, buffer, meminfo->oobsize);452             buffer += meminfo->oobsize;453 454             /* write OOB data first, as ecc will be placed455              * in there*/456             result = meminfo->write_oob(meminfo,457                             mtdoffset,458                             meminfo->oobsize,459                             &written,460                             (unsigned char *)461                             &oob_buf);462 463             if (result != 0) {464                 printf("\nMTD writeoob failure: %d\n",465                        result);466                 goto restoreoob;467             }468             imglen -= meminfo->oobsize;469         }470 471         /* write out the page data */472         result = meminfo->write(meminfo,473                     mtdoffset,474                     meminfo->oobblock,475                     &written,476                     (unsigned char *) &data_buf);477 478         if (result != 0) {479             printf("writing NAND page at offset 0x%lx failed\n",480                    mtdoffset);481             goto restoreoob;482         }483         imglen -= readlen;484 485         if (!opts->quiet) {486             int percent = (int)487                 ((unsigned long long)488                  (opts->length-imglen) * 100489                  / opts->length);490             /* output progress message only at whole percent491              * steps to reduce the number of messages printed492              * on (slow) serial consoles493              */494             if (percent != percent_complete) {495                 printf("\rWriting data at 0x%x "496                        "-- %3d%% complete.",497                        mtdoffset, percent);498                 percent_complete = percent;499             }500         }501 502         mtdoffset += meminfo->oobblock;503     }504 505     if (!opts->quiet)506         printf("\n");507 508 restoreoob:509     if (oobinfochanged) {510         memcpy(&meminfo->oobinfo, &old_oobinfo,511                sizeof(meminfo->oobinfo));512     }513 514     if (imglen > 0) {515         printf("Data did not fit into device, due to bad blocks\n");516         return -1;517     }518 519     /* return happy */520     return 0;521 }522 523 /**524  * nand_read_opts: - read image from NAND flash with support for various options525  *526  * @param meminfo   NAND device to erase527  * @param opts      read options (@see struct nand_read_options)528  * @return      0 in case of success529  *530  */531 int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)532 {533     int imglen = opts->length;534     int pagelen;535     int baderaseblock;536     int blockstart = -1;537     int percent_complete = -1;538     loff_t offs;539     size_t readlen;540     ulong mtdoffset = opts->offset;541     u_char *buffer = opts->buffer;542     int result;543 544     /* make sure device page sizes are valid */545     if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)546         && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)547         && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {548         printf("Unknown flash (not normal NAND)\n");549         return -1;550     }551 552     pagelen = meminfo->oobblock553         + ((opts->readoob != 0) ? meminfo->oobsize : 0);554 555     /* check, if length is not larger than device */556     if (((imglen / pagelen) * meminfo->oobblock)557          > (meminfo->size - opts->offset)) {558         printf("Image %d bytes, NAND page %d bytes, "559                "OOB area %u bytes, device size %u bytes\n",560                imglen, pagelen, meminfo->oobblock, meminfo->size);561         printf("Input block is larger than device\n");562         return -1;563     }564 565     if (!opts->quiet)566         printf("\n");567 568     /* get data from input and write to the device */569     while (imglen && (mtdoffset < meminfo->size)) {570 571         WATCHDOG_RESET ();572 573         /*574          * new eraseblock, check for bad block(s). Stay in the575          * loop to be sure if the offset changes because of576          * a bad block, that the next block that will be577          * written to is also checked. Thus avoiding errors if578          * the block(s) after the skipped block(s) is also bad579          * (number of blocks depending on the blockalign580          */581         while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) {582             blockstart = mtdoffset & (~meminfo->erasesize+1);583             offs = blockstart;584             baderaseblock = 0;585 586             /* check all the blocks in an erase block for587              * bad blocks */588             do {589                 int ret = meminfo->block_isbad(meminfo, offs);590 591                 if (ret < 0) {592                     printf("Bad block check failed\n");593                     return -1;594                 }595                 if (ret == 1) {596                     baderaseblock = 1;597                     if (!opts->quiet)598                         printf("\rBad block at 0x%lx "599                                "in erase block from "600                                "0x%x will be skipped\n",601                                (long) offs,602                                blockstart);603                 }604 605                 if (baderaseblock) {606                     mtdoffset = blockstart607                         + meminfo->erasesize;608                 }609                 offs +=  meminfo->erasesize;610 611             } while (offs < blockstart + meminfo->erasesize);612         }613 614 615         /* read page data to memory buffer */616         result = meminfo->read(meminfo,617                        mtdoffset,618                        meminfo->oobblock,619                        &readlen,620                        (unsigned char *) &data_buf);621 622         if (result != 0) {623             printf("reading NAND page at offset 0x%lx failed\n",624                    mtdoffset);625             return -1;626         }627 628         if (imglen < readlen) {629             readlen = imglen;630         }631 632         memcpy(buffer, data_buf, readlen);633         buffer += readlen;634         imglen -= readlen;635 636         if (opts->readoob) {637             result = meminfo->read_oob(meminfo,638                            mtdoffset,639                            meminfo->oobsize,640                            &readlen,641                            (unsigned char *)642                            &oob_buf);643 644             if (result != 0) {645                 printf("\nMTD readoob failure: %d\n",646                        result);647                 return -1;648             }649 650 651             if (imglen < readlen) {652                 readlen = imglen;653             }654 655             memcpy(buffer, oob_buf, readlen);656 657             buffer += readlen;658             imglen -= readlen;659         }660 661         if (!opts->quiet) {662             int percent = (int)663                 ((unsigned long long)664                  (opts->length-imglen) * 100665                  / opts->length);666             /* output progress message only at whole percent667              * steps to reduce the number of messages printed668              * on (slow) serial consoles669              */670             if (percent != percent_complete) {671             if (!opts->quiet)672                 printf("\rReading data from 0x%x "673                        "-- %3d%% complete.",674                        mtdoffset, percent);675                 percent_complete = percent;676             }677         }678 679         mtdoffset += meminfo->oobblock;680     }681 682     if (!opts->quiet)683         printf("\n");684 685     if (imglen > 0) {686         printf("Could not read entire image due to bad blocks\n");687         return -1;688     }689 690     /* return happy */691     return 0;692 }693 694 /******************************************************************************695  * Support for locking / unlocking operations of some NAND devices696  *****************************************************************************/697 698 #define NAND_CMD_LOCK       0x2a699 #define NAND_CMD_LOCK_TIGHT 0x2c700 #define NAND_CMD_UNLOCK1    0x23701 #define NAND_CMD_UNLOCK2    0x24702 #define NAND_CMD_LOCK_STATUS    0x7a703 704 /**705  * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT706  *        state707  *708  * @param meminfo   nand mtd instance709  * @param tight     bring device in lock tight mode710  *711  * @return      0 on success, -1 in case of error712  *713  * The lock / lock-tight command only applies to the whole chip. To get some714  * parts of the chip lock and others unlocked use the following sequence:715  *716  * - Lock all pages of the chip using nand_lock(mtd, 0) (or the lockpre pin)717  * - Call nand_unlock() once for each consecutive area to be unlocked718  * - If desired: Bring the chip to the lock-tight state using nand_lock(mtd, 1)719  *720  *   If the device is in lock-tight state software can't change the721  *   current active lock/unlock state of all pages. nand_lock() / nand_unlock()722  *   calls will fail. It is only posible to leave lock-tight state by723  *   an hardware signal (low pulse on _WP pin) or by power down.724  */725 int nand_lock(nand_info_t *meminfo, int tight)726 {727     int ret = 0;728     int status;729     struct nand_chip *this = meminfo->priv;730 731     /* select the NAND device */732     this->select_chip(meminfo, 0);733 734     this->cmdfunc(meminfo,735               (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),736               -1, -1);737 738     /* call wait ready function */739     status = this->waitfunc(meminfo, this, FL_WRITING);740 741     /* see if device thinks it succeeded */742     if (status & 0x01) {743         ret = -1;744     }745 746     /* de-select the NAND device */747     this->select_chip(meminfo, -1);748     return ret;749 }750 751 /**752  * nand_get_lock_status: - query current lock state from one page of NAND753  *             flash754  *755  * @param meminfo   nand mtd instance756  * @param offset    page address to query (muss be page aligned!)757  *758  * @return      -1 in case of error759  *          >0 lock status:760  *            bitfield with the following combinations:761  *            NAND_LOCK_STATUS_TIGHT: page in tight state762  *            NAND_LOCK_STATUS_LOCK:  page locked763  *            NAND_LOCK_STATUS_UNLOCK: page unlocked764  *765  */766 int nand_get_lock_status(nand_info_t *meminfo, ulong offset)767 {768     int ret = 0;769     int chipnr;770     int page;771     struct nand_chip *this = meminfo->priv;772 773     /* select the NAND device */774     chipnr = (int)(offset >> this->chip_shift);775     this->select_chip(meminfo, chipnr);776 777 778     if ((offset & (meminfo->oobblock - 1)) != 0) {779         printf ("nand_get_lock_status: "780             "Start address must be beginning of "781             "nand page!\n");782         ret = -1;783         goto out;784     }785 786     /* check the Lock Status */787     page = (int)(offset >> this->page_shift);788     this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask);789 790     ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT791                       | NAND_LOCK_STATUS_LOCK792                       | NAND_LOCK_STATUS_UNLOCK);793 794  out:795     /* de-select the NAND device */796     this->select_chip(meminfo, -1);797     return ret;798 }799 800 /**801  * nand_unlock: - Unlock area of NAND pages802  *        only one consecutive area can be unlocked at one time!803  *804  * @param meminfo   nand mtd instance805  * @param start     start byte address806  * @param length    number of bytes to unlock (must be a multiple of807  *          page size nand->oobblock)808  *809  * @return      0 on success, -1 in case of error810  */811 int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)812 {813     int ret = 0;814     int chipnr;815     int status;816     int page;817     struct nand_chip *this = meminfo->priv;818     printf ("nand_unlock: start: %08x, length: %d!\n",819         (int)start, (int)length);820 821     /* select the NAND device */822     chipnr = (int)(start >> this->chip_shift);823     this->select_chip(meminfo, chipnr);824 825     /* check the WP bit */826     this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1);827     if ((this->read_byte(meminfo) & 0x80) == 0) {828         printf ("nand_unlock: Device is write protected!\n");829         ret = -1;830         goto out;831     }832 833     if ((start & (meminfo->oobblock - 1)) != 0) {834         printf ("nand_unlock: Start address must be beginning of "835             "nand page!\n");836         ret = -1;837         goto out;838     }839 840     if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) {841         printf ("nand_unlock: Length must be a multiple of nand page "842             "size!\n");843         ret = -1;844         goto out;845     }846 847     /* submit address of first page to unlock */848     page = (int)(start >> this->page_shift);849     this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask);850 851     /* submit ADDRESS of LAST page to unlock */852     page += (int)(length >> this->page_shift) - 1;853     this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask);854 855     /* call wait ready function */856     status = this->waitfunc(meminfo, this, FL_WRITING);857     /* see if device thinks it succeeded */858     if (status & 0x01) {859         /* there was an error */860         ret = -1;861         goto out;862     }863 864  out:865     /* de-select the NAND device */866     this->select_chip(meminfo, -1);867     return ret;868 }869 870 #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) */

⌨️ 快捷键说明

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