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

📄 nand_util.c

📁 U-BOOT,著名的Bootloader程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (opts->pad && (imglen < readlen)) {			readlen = imglen;			memset(data_buf + readlen, 0xff,			       meminfo->oobblock - readlen);		}		/* read page data from input memory buffer */		memcpy(data_buf, buffer, readlen);		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) {			unsigned long long n = (unsigned long long)				 (opts->length-imglen) * 100;			int percent;			do_div(n, opts->length);			percent = (int)n;			/* 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%lx "				       "-- %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;	/* 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");	/* 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 */			do {				int ret = meminfo->block_isbad(meminfo, offs);				if (ret < 0) {					printf("Bad block check failed\n");					return -1;				}				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);			return -1;		}		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);				return -1;			}			if (imglen < readlen) {				readlen = imglen;			}			memcpy(buffer, oob_buf, readlen);			buffer += readlen;			imglen -= readlen;		}		if (!opts->quiet) {			unsigned long long n = (unsigned long long)				 (opts->length-imglen) * 100;			int percent;			do_div(n, opts->length);			percent = (int)n;			/* 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%lx "				       "-- %3d%% complete.",				       mtdoffset, percent);				percent_complete = percent;			}		}		mtdoffset += meminfo->oobblock;	}	if (!opts->quiet)		printf("\n");	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

⌨️ 快捷键说明

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