博文后续
添加对nand write.yaffs和nand read.yaffs命令的支持
common/cmd_nand.c
U_BOOT_CMD(nand, 5, 1, do_nand,
"nand - NAND sub-system\n",
"info - show available NAND devices\n"
"nand device [dev] - show or set current device\n"
"nand read[.jffs2] - addr off|partition size\n"
"nand write[.jffs2] - addr off|partiton size - read/write `size' bytes starting\n"
" at offset `off' to/from memory address `addr'\n"
"nand read.yaffs addr off size - read the `size' byte yaffs image starting\n"
" at offset `off' to memory address `addr'\n"
"nand write.yaffs addr off size - write the `size' byte yaffs image starting\n"
" at offset `off' from memory address `addr'\n"
"nand read.raw addr off size - read the `size' bytes starting\n"
" at offset `off' to memory address `addr', without oob and ecc\n"
"nand write.raw addr off size - write the `size' bytes starting\n"
" at offset `off' from memory address `addr', without oob and ecc\n"
"nand erase [clean] [off size] - erase `size' bytes from\n"
" offset `off' (entire device if not specified)\n"
"nand bad - show bad blocks\n"
"nand dump[.oob] off - dump page\n"
"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
"nand markbad off - mark bad block at offset (UNSAFE)\n"
"nand biterr off - make a bit error at offset (UNSAFE)\n"
"nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
"nand unlock [offset] [size] - unlock section\n");
添加yaffs的两个变量,用于操作nandflash的oob控制符skipfirstblk,nocheckblk
include\nand.h
struct nand_write_options {
u_char *buffer; /* memory block containing image to write */
ulong length; /* number of bytes to write */
ulong offset; /* start address in NAND */
int quiet; /* don't display progress messages */
int autoplace; /* if true use auto oob layout */
int forcejffs2; /* force jffs2 oob layout */
int forceyaffs; /* force yaffs oob layout */
int noecc; /* write without ecc */
int writeoob; /* image contains oob data */
int pad; /* pad to page size */
int blockalign; /* 1|2|4 set multiple of eraseblocks
* to align to */
int skipfirstblk; /* if true, skip the first good block,
* set true when write the yaffs image,
*/
int nocheckbadblk; /* if true, don't check bad blockes,
* use them as good blockes
*/
};
struct nand_read_options {
u_char *buffer; /* memory block in which read image is written*/
ulong length; /* number of bytes to read */
ulong offset; /* start address in NAND */
int quiet; /* don't display progress messages */
int readoob; /* put oob data in image */
int noecc; /* read without ecc */
int nocheckbadblk; /* if true, don't check bad blockes,
* use them as good blockes
*/
};
添加对yaffs的读写支持,
common/cmd_nand.c
}else if ( s != NULL && !strcmp(s, ".yaffs")){
if (read) {
/* read */
nand_read_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
opts.readoob = 1;
opts.quiet = quiet;
ret = nand_read_opts(nand, &opts);
} else {
/* write */
nand_write_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
/* opts.forceyaffs = 1; */
opts.noecc = 1;
opts.writeoob = 1;
opts.blockalign = 1;
opts.quiet = quiet;
opts.skipfirstblk = 1;
ret = nand_write_opts(nand, &opts);
}
}
include\nand.h
#define NANDRW_YAFFS 0x08 /* to write yaffs image */
drivers\nand_legacy\nand_legacy.c
nand_legacy_rw函数添加如下:
int nand_legacy_rw (struct nand_chip* nand, int cmd,
size_t start, size_t len,
size_t * retlen, u_char * buf)
{
int ret = 0, n, total = 0;
char eccbuf[6];
/* eblk (once set) is the start of the erase block containing the
* data being processed.
*/
unsigned long eblk = ~0; /* force mismatch on first pass */
unsigned long erasesize = nand->erasesize;
int bfirstyaffsblk = 1;
int page;
unsigned long badblk=0, prgmblk=0;
unsigned long badblks=0, prgmblks = 0;
unsigned long allblks;
allblks = (erasesize/nand->oobblock)*(nand->oobblock+nand->oobsize);
allblks = (len + allblks - 1) / allblks;
if ((cmd & NANDRW_YAFFS) && (len % (nand->oobblock + nand->oobsize))) {
printf("Length of the yaffs image should be times of (%d +%d), now it is %d\n", nand->oobblock, nand->oobsize, len);
return -1;
}
if ((cmd & NANDRW_YAFFS) && (start % erasesize)) {
printf("Start address of the flash should be %d align\n", erasesize);
return -1;
}
if (cmd & (NANDRW_WRITE | NANDRW_YAFFS)) {
printf("Flash params: oobblock = %d, oobsize = %d, erasesize = %d\n", nand->oobblock, nand->oobsize, nand->erasesize);
printf("Programming NAND with yaffs image, length = %d\n", len);
printf(" Block Programming(addr/count) --- Block bad(addr/count) --- Block programed/All(%%)\n");
printf("------------------------------------------------------------------------------------\n");
}
drivers\nand\nand_util.c
/* for yaffs */
if (cmd & (NANDRW_WRITE | NANDRW_YAFFS)) {
/* Do some programming, but not in the first block */
if (!bfirstyaffsblk) {
prgmblk = start;
prgmblks++;
printf(" 0x%08x/%05d 0x%08x/%05d %05d/%05d=%02d%%\r", prgmblk, prgmblks, badblk, badblks, prgmblks, allblks, prgmblks*100/allblks);
for (page = 0; (page < erasesize/nand->oobblock) && (len - page*(nand->oobblock+nand->oobsize) > 0); page++) {
ret = nand_write_ecc(nand, start+page*nand->oobblock,
nand->oobblock, (size_t *)&n,
(u_char*)buf+page*(nand->oobblock+nand->oobsize), (u_char *)0); /* without ecc */
if (!ret)
ret = nand_write_oob(nand, start+page*nand->oobblock,
nand->oobsize, (size_t *)&n,
(u_char*)buf+page*(nand->oobblock+nand->oobsize)+nand->oobblock);
if (ret)
break;
}
n = page * (nand->oobblock+nand->oobsize);
} else {
bfirstyaffsblk = 0;
n = 0;
start += erasesize; /* skip first block */
ret = 0;
page = 0;
}
}
drivers\nand\nand_util.c
/* force OOB layout for jffs2 or yaffs? */
if (opts->forcejffs2 || opts->forceyaffs) {
struct nand_oobinfo *oobsel =
opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
if (meminfo->oobsize == 8) {
if (opts->forceyaffs) {
printf("YAFSS cannot operate on "
"256 Byte page size\n");
goto restoreoob;
}
/* Adjust number of ecc bytes */
jffs2_oobinfo.eccbytes = 3;
}
memcpy(&meminfo->oobinfo, oobsel, sizeof(meminfo->oobinfo));
}
drivers\nand\nand_util.c
/* skip the first good block when wirte yaffs image */
if (skipfirstblk) {
mtdoffset += erasesize_blockalign;
skipfirstblk = 0;
continue;
}