void env_relocate_spec(void) { DECLARE_GLOBAL_DATA_PTR; unsigned long env_addr; int use_default = 0; int retlen; env_addr = CFG_ENV_ADDR; env_addr -= (unsigned long)onenand_chip.base; /* Check OneNAND exist */ if (onenand_mtd.oobblock) /* Ignore read fail */ onenand_read(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen, (u_char *) env_ptr); else onenand_mtd.oobblock = MAX_ONENAND_PAGESIZE; if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) != env_ptr->crc) use_default = 1; if (use_default) { memcpy(env_ptr->data, default_environment, ONENAND_ENV_SIZE(onenand_mtd)); env_ptr->crc = crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)); } gd->env_addr = (ulong) & env_ptr->data; gd->env_valid = 1; }
void env_relocate_spec(void) { unsigned long env_addr; int use_default = 0; size_t retlen; env_addr = CFG_ENV_ADDR; /* Check OneNAND exist */ if (onenand_mtd.writesize) /* Ignore read fail */ onenand_read(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen, (u_char *) env_ptr); else onenand_mtd.writesize = MAX_ONENAND_PAGESIZE; if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) != env_ptr->crc) use_default = 1; if (use_default) { memcpy(env_ptr->data, default_environment, ONENAND_ENV_SIZE(onenand_mtd)); env_ptr->crc = crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)); } gd->env_addr = (ulong) & env_ptr->data; gd->env_valid = 1; }
void env_relocate_spec_onenand(void) { struct mtd_info *onenand; /* the following commands operate on the current device */ if (onenand_curr_device < 0 || onenand_curr_device >= CFG_MAX_ONENAND_DEVICE || !onenand_info[onenand_curr_device].name) { puts("\nno devices available\n"); return 1; } onenand = &onenand_info[onenand_curr_device]; #if !defined(ENV_IS_EMBEDDED) size_t total; int ret, i; u_char *data; data = (u_char*)malloc(CFG_ENV_SIZE); total = CFG_ENV_SIZE; for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { if (onenand_scan(&onenand_info[i], 1) == 0) { ret = onenand_read(onenand, CFG_ENV_OFFSET, &total, (u_char*)data); env_ptr = data; if (ret || total != CFG_ENV_SIZE) return use_default(); if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) return use_default(); } else { printf("no devices available\n"); return use_default(); } } /* */ #endif /* ! ENV_IS_EMBEDDED */ }
int do_onenand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int ret = 0; switch (argc) { case 0: case 1: printf("Usage:\n%s\n", cmdtp->usage); return 1; case 2: onenand_print_device_info(onenand_chip.device_id, 1); return 0; default: /* At least 4 args */ if (strncmp(argv[1], "erase", 5) == 0) { struct erase_info instr; ulong start, end; char *endtail; ulong block; if (strncmp(argv[2], "block", 5) == 0) { start = simple_strtoul(argv[3], NULL, 10); endtail = strchr(argv[3], '-'); end = simple_strtoul(endtail+1, NULL, 10); } else { start = simple_strtoul(argv[2], NULL, 10); end = simple_strtoul(argv[3], NULL, 10); start -= (unsigned long) onenand_chip.base; end -= (unsigned long) onenand_chip.base; } if (!end || end < 0) end = start; printf("Erase block from %d to %d\n", start, end); for (block = start; block <= end; block++) { instr.addr = block << onenand_chip.erase_shift; instr.len = 1 << onenand_chip.erase_shift; ret = onenand_erase(&onenand_mtd, &instr); if (ret) { printf("erase failed %d\n", block); break; } } return 0; } if (strncmp(argv[1], "read", 4) == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); ulong ofs = simple_strtoul(argv[3], NULL, 16); size_t len = simple_strtoul(argv[4], NULL, 16); size_t retlen = 0; int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1; if (oob) onenand_read_oob(&onenand_mtd, ofs, len, &retlen, (u_char *) addr); else onenand_read(&onenand_mtd, ofs, len, &retlen, (u_char *) addr); printf("Done\n"); return 0; } if (strncmp(argv[1], "write", 5) == 0) { int ret ; ulong addr = simple_strtoul(argv[2], NULL, 16); ulong ofs = simple_strtoul(argv[3], NULL, 16); size_t len = simple_strtoul(argv[4], NULL, 16); size_t retlen = 0; printf("onenadwrite: addr = 0x%x, ofs = 0x%x, len = 0x%x\n", addr, ofs, len); ret = onenand_write(&onenand_mtd, ofs, len, &retlen, (u_char *) addr); if (ret) printf("Error writing oneNAND: ret = %d\n", ret); else printf("Done. ret = %d\n", ret); return 0; } if (strncmp(argv[1], "block", 5) == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); ulong block = simple_strtoul(argv[3], NULL, 10); ulong page = simple_strtoul(argv[4], NULL, 10); size_t len = simple_strtol(argv[5], NULL, 10); size_t retlen = 0; ulong ofs; int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1; ofs = block << onenand_chip.erase_shift; if (page) ofs += page << onenand_chip.page_shift; if (!len) { if (oob) len = 64; else len = 512; } if (oob) onenand_read_oob(&onenand_mtd, ofs, len, &retlen, (u_char *) addr); else onenand_read(&onenand_mtd, ofs, len, &retlen, (u_char *) addr); return 0; } if (strncmp(argv[1], "unlock", 6) == 0) { ulong start = simple_strtoul(argv[2], NULL, 10); ulong ofs = simple_strtoul(argv[3], NULL, 10); if (!ofs) ofs = (1 << onenand_chip.erase_shift); start = start << onenand_chip.erase_shift; printf("start = 0x%08x, ofs = 0x%08x\n", start, ofs); onenand_unlock(&onenand_mtd, start, start + ofs); return 0; } if (strncmp(argv[1], "save", 4) == 0 && strncmp(argv[2], "bootloader", 10) == 0) { ulong addr = simple_strtoul(argv[3], NULL, 16); struct erase_info instr; int ofs = 0; int len = 0x20000; size_t retlen; printf("save bootloader...\n"); if (!addr) break; onenand_unlock(&onenand_mtd, ofs, len); instr.addr = 0 << onenand_chip.erase_shift; instr.len = 1 << onenand_chip.erase_shift; onenand_erase(&onenand_mtd, &instr); onenand_write(&onenand_mtd, ofs, len, &retlen, (u_char *) addr); onenand_unlock(&onenand_mtd, CFG_ENV_ADDR, onenand_mtd.size - CFG_ENV_ADDR); return 0; } break; } return 0; }
int saveenv_onenand(void) { size_t total; int ret = 0, i; u32 erasebase; u32 eraselength; u32 eraseblock; u32 erasesize = onenand_info[0].erasesize; uint8_t *data; struct mtd_info *onenand; puts("Erasing Onenand...\n"); /* the following commands operate on the current device */ if (onenand_curr_device < 0 || onenand_curr_device >= CFG_MAX_ONENAND_DEVICE || !onenand_info[onenand_curr_device].name) { puts("\nno devices available\n"); return 1; } onenand = &onenand_info[onenand_curr_device]; /* If the value of CFG_ENV_OFFSET is not a NAND block boundary, the * NAND erase operation will fail. So first check if the CFG_ENV_OFFSET * is equal to a NAND block boundary */ if ((CFG_ENV_OFFSET % (erasesize - 1)) != 0 ) { /* CFG_ENV_OFFSET is not equal to block boundary address. So, read * the read the NAND block (in which ENV has to be stored), and * copy the ENV data into the copied block data. */ /* Step 1: Find out the starting address of the NAND block to * be erased. Also allocate memory whose size is equal to tbe * NAND block size (NAND erasesize). */ eraseblock = CFG_ENV_OFFSET / erasesize; erasebase = eraseblock * erasesize; printf("the baseaddr is 0x%08x ...\n", erasebase); data = (uint8_t*)malloc(erasesize); if (data == NULL) { printf("Could not save enviroment variables\n"); return 1; } /* Step 2: Read the NAND block into which the ENV data has * to be copied */ total = erasesize; printf("the total is 0x%08x ...\n", total); for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { if (onenand_scan(&onenand_info[i], 1) == 0) { ret = onenand_read(onenand, erasebase, &total, data); } else { printf("no devices available\n"); return 1; } } if (ret || total != erasesize) { printf("Could not save enviroment variables %d\n",ret); return 1; } /* Step 3: Copy the ENV data into the local copy of the block * contents. */ memcpy((data + (CFG_ENV_OFFSET - erasebase)), (void*)env_ptr, CFG_ENV_SIZE); } else { /* CFG_ENV_OFFSET is equal to a NAND block boundary. So * no special care is required when erasing and writing NAND * block */ data = env_ptr; erasebase = CFG_ENV_OFFSET; erasesize = CFG_ENV_SIZE; } /* Erase the NAND block which will hold the ENV data */ if (onenand_erase(onenand, erasebase, erasesize)) return 1; puts("Writing to onenand... \n"); total = erasesize; /* Write the ENV data to the NAND block */ printf("the baseaddr is 0x%08x ...\n", erasebase); printf("the baseaddr is 0x%08x ...\n", total); ret = onenand_write(onenand, erasebase, &total, (u_char*)data); if (ret || total != erasesize) { printf("Could not save enviroment variables\n"); return 1; } if ((CFG_ENV_OFFSET % (erasesize - 1)) != 0 ) free(data); puts("Saved enviroment variables\n"); return ret; return 1; }