Esempio n. 1
0
void env_relocate_spec(void)
{
	struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
	struct onenand_chip *this = &onenand_chip;
#endif
	int rc;
	size_t retlen;
#ifdef ENV_IS_EMBEDDED
	char *buf = (char *)&environment[0];
#else
	loff_t env_addr = CONFIG_ENV_ADDR;
	char onenand_env[ONENAND_MAX_ENV_SIZE];
	char *buf = (char *)&onenand_env[0];
#endif /* ENV_IS_EMBEDDED */

#ifndef ENV_IS_EMBEDDED
# ifdef CONFIG_ENV_ADDR_FLEX
	if (FLEXONENAND(this))
		env_addr = CONFIG_ENV_ADDR_FLEX;
# endif
	/* Check OneNAND exist */
	if (mtd->writesize)
		/* Ignore read fail */
		mtd->read(mtd, env_addr, ONENAND_MAX_ENV_SIZE,
			     &retlen, (u_char *)buf);
	else
		mtd->writesize = MAX_ONENAND_PAGESIZE;
#endif /* !ENV_IS_EMBEDDED */

	rc = env_import(buf, 1);
	if (rc)
		gd->env_valid = 1;
}
static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
{
	struct onenand_chip *this = mtd->priv;
	struct bbm_info *bbm = this->bbm;
	int i, j, numblocks, len, scanlen;
	int startblock;
	loff_t from;
	size_t readlen, ooblen;
	struct mtd_oob_ops ops;
	int rgn;

	printk(KERN_INFO "Scanning device for bad blocks\n");

	len = 2;

	/* We need only read few bytes from the OOB area */
	scanlen = ooblen = 0;
	readlen = bd->len;

	/* chip == -1 case only */
	/* Note that numblocks is 2 * (real numblocks) here;
	 * see i += 2 below as it makses shifting and masking less painful
	 */
	numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);
	startblock = 0;
	from = 0;

	ops.mode = MTD_OOB_PLACE;
	ops.ooblen = readlen;
	ops.oobbuf = buf;
	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;

	for (i = startblock; i < numblocks; ) {
		int ret;

		for (j = 0; j < len; j++) {
			/* No need to read pages fully,
			 * just read required OOB bytes */
			ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);

			/* If it is a initial bad block, just ignore it */
			if (ret == ONENAND_BBT_READ_FATAL_ERROR)
				return -EIO;

			if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
					i >> 1, (unsigned int) from);
				mtd->ecc_stats.badblocks++;
				break;
			}
		}
		i += 2;

		if (FLEXONENAND(this)) {
			rgn = flexonenand_region(mtd, from);
			from += mtd->eraseregions[rgn].erasesize;
		} else
			from += (1 << bbm->bbt_erase_shift);
	}
Esempio n. 3
0
static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
{
	struct onenand_chip *this = mtd->priv;
	struct bbm_info *bbm = this->bbm;
	int i, j, numblocks, len, scanlen;
	int startblock;
	loff_t from;
	size_t readlen, ooblen;
	struct mtd_oob_ops ops;
	int rgn;

	printk(KERN_INFO "Scanning device for bad blocks\n");

	len = 2;

	
	scanlen = ooblen = 0;
	readlen = bd->len;

	
	
	numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);
	startblock = 0;
	from = 0;

	ops.mode = MTD_OOB_PLACE;
	ops.ooblen = readlen;
	ops.oobbuf = buf;
	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;

	for (i = startblock; i < numblocks; ) {
		int ret;

		for (j = 0; j < len; j++) {
			
			ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);

			
			if (ret == ONENAND_BBT_READ_FATAL_ERROR)
				return -EIO;

			if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
					i >> 1, (unsigned int) from);
				mtd->ecc_stats.badblocks++;
				break;
			}
		}
		i += 2;

		if (FLEXONENAND(this)) {
			rgn = flexonenand_region(mtd, from);
			from += mtd->eraseregions[rgn].erasesize;
		} else
			from += (1 << bbm->bbt_erase_shift);
	}
Esempio n. 4
0
int saveenv(void)
{
	env_t	env_new;
	ssize_t	len;
	char	*res;
	struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
	struct onenand_chip *this = &onenand_chip;
#endif
	loff_t	env_addr = CONFIG_ENV_ADDR;
	size_t	retlen;
	struct erase_info instr = {
		.callback	= NULL,
	};

	res = (char *)&env_new.data;
	len = hexport_r(&env_htab, '\0', &res, ENV_SIZE);
	if (len < 0) {
		error("Cannot export environment: errno = %d\n", errno);
		return 1;
	}
	env_new.crc = crc32(0, env_new.data, ENV_SIZE);

	instr.len = CONFIG_ENV_SIZE;
#ifdef CONFIG_ENV_ADDR_FLEX
	if (FLEXONENAND(this)) {
		env_addr = CONFIG_ENV_ADDR_FLEX;
		instr.len = CONFIG_ENV_SIZE_FLEX;
		instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
				1 : 0;
	}
#endif
	instr.addr = env_addr;
	instr.mtd = mtd;
	if (mtd->erase(mtd, &instr)) {
		printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
		return 1;
	}

	if (mtd->write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
	     (u_char *)&env_new)) {
		printf("OneNAND: write failed at 0x%llx\n", instr.addr);
		return 2;
	}

	return 0;
}
Esempio n. 5
0
static int env_onenand_save(void)
{
	env_t	env_new;
	int ret;
	struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
	struct onenand_chip *this = &onenand_chip;
#endif
	loff_t	env_addr = CONFIG_ENV_ADDR;
	size_t	retlen;
	struct erase_info instr = {
		.callback	= NULL,
	};

	ret = env_export(&env_new);
	if (ret)
		return ret;

	instr.len = CONFIG_ENV_SIZE;
#ifdef CONFIG_ENV_ADDR_FLEX
	if (FLEXONENAND(this)) {
		env_addr = CONFIG_ENV_ADDR_FLEX;
		instr.len = CONFIG_ENV_SIZE_FLEX;
		instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
				1 : 0;
	}
#endif
	instr.addr = env_addr;
	instr.mtd = mtd;
	if (mtd_erase(mtd, &instr)) {
		printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
		return 1;
	}

	if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
			(u_char *)&env_new)) {
		printf("OneNAND: write failed at 0x%llx\n", instr.addr);
		return 2;
	}

	return 0;
}
int saveenv(void)
{
	struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
	struct onenand_chip *this = &onenand_chip;
#endif
	loff_t env_addr = CONFIG_ENV_ADDR;
	struct erase_info instr = {
		.callback	= NULL,
	};
	size_t retlen;

	instr.len = CONFIG_ENV_SIZE;
#ifdef CONFIG_ENV_ADDR_FLEX
	if (FLEXONENAND(this)) {
		env_addr = CONFIG_ENV_ADDR_FLEX;
		instr.len = CONFIG_ENV_SIZE_FLEX;
		instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
				1 : 0;
	}
#endif
	instr.addr = env_addr;
	instr.mtd = mtd;
	if (mtd->erase(mtd, &instr)) {
		printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
		return 1;
	}

	/* update crc */
	env_ptr->crc = crc32(0, env_ptr->data, ONENAND_ENV_SIZE(mtd));

	if (mtd->write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
	     (u_char *) env_ptr)) {
		printf("OneNAND: write failed at 0x%llx\n", instr.addr);
		return 2;
	}

	return 0;
}
void env_relocate_spec(void)
{
	struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
	struct onenand_chip *this = &onenand_chip;
#endif
	loff_t env_addr;
	int use_default = 0;
	size_t retlen;

	env_addr = CONFIG_ENV_ADDR;
#ifdef CONFIG_ENV_ADDR_FLEX
	if (FLEXONENAND(this))
		env_addr = CONFIG_ENV_ADDR_FLEX;
#endif
	/* Check OneNAND exist */
	if (mtd->writesize)
		/* Ignore read fail */
		mtd->read(mtd, env_addr, ONENAND_MAX_ENV_SIZE,
			     &retlen, (u_char *) env_ptr);
	else
		mtd->writesize = MAX_ONENAND_PAGESIZE;

	if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(mtd)) != env_ptr->crc)
		use_default = 1;

	if (use_default) {
		memcpy(env_ptr->data, default_environment,
		       ONENAND_ENV_SIZE(mtd));
		env_ptr->crc =
		    crc32(0, env_ptr->data, ONENAND_ENV_SIZE(mtd));
	}

	gd->env_addr = (ulong) & env_ptr->data;
	gd->env_valid = 1;
}