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); }
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); }
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; }
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; }