if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { int read;
if (argc < 4) goto usage;
addr = (ulong)simple_strtoul(argv[2], NULL, 16);
read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ printf("\nNAND %s: ", read ? "read" : "write"); if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) return 1;
s = strchr(cmd, '.'); if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { if (read) ret = nand_read_skip_bad(nand, off, &size, (u_char *)addr); else ret = nand_write_skip_bad(nand, off, &size, (u_char *)addr); }
//添加yaffs2相关操作,注意该处又关联到nand_write_skip_bad函数
#if defined(CONFIG_MTD_NAND_YAFFS2) else if (s != NULL && (!strcmp(s, ".yaffs2"))) { nand->rw_oob = 1; nand->skipfirstblk = 1; ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr); nand->skipfirstblk = 0; nand->rw_oob = 0; } #endif
else if (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { .oobbuf = (u8 *)addr, .ooblen = size, .mode = MTD_OOB_RAW };
if (read) ret = nand->read_oob(nand, off, &ops); else ret = nand->write_oob(nand, off, &ops); } else { printf("Unknown nand command suffix '%s'.\n", s); return 1; }
printf(" %zu bytes %s: %s\n", size, read ? "read" : "written", ret ? "ERROR" : "OK");
return ret == 0 ? 0 : 1; }
在include/linux/mtd/mtd.h头文件的mtd_info结构体中添加上面用到rw_oob和skipfirstblk数据成员,如下:
#vi include/linux/mtd/mtd.h //在mtd_info结构体中添加
|
#if defined(CONFIG_MTD_NAND_YAFFS2) u_char rw_oob; u_char skipfirstblk; #endif
|
在第二步关联的nand_write_skip_bad函数中添加对Nand OOB的相关操作,如下:
#vi drivers/mtd/nand/nand_util.c //在nand_write_skip_bad函数中添加
|
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer) { int rval; size_t left_to_write = *length; size_t len_incl_bad; u_char *p_buffer = buffer;
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if(nand->rw_oob==1) { size_t oobsize = nand->oobsize; size_t datasize = nand->writesize; int datapages = 0;
if (((*length)%(nand->oobsize+nand->writesize)) != 0) { printf ("Attempt to write error length data!\n"); return -EINVAL; }
datapages = *length/(datasize+oobsize); *length = datapages*datasize; left_to_write = *length; } #endif
/* Reject writes, which are not page aligned */ if ((offset & (nand->writesize - 1)) != 0 || (*length & (nand->writesize - 1)) != 0) { printf ("Attempt to write non page aligned data\n"); return -EINVAL; }
len_incl_bad = get_len_incl_bad (nand, offset, *length);
if ((offset + len_incl_bad) >= nand->size) { printf ("Attempt to write outside the flash area\n"); return -EINVAL; }
#if !defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if (len_incl_bad == *length) { rval = nand_write (nand, offset, length, buffer); if (rval != 0) printf ("NAND write to offset %llx failed %d\n", offset, rval);
return rval; } #endif
while (left_to_write > 0) { size_t block_offset = offset & (nand->erasesize - 1); size_t write_size;
WATCHDOG_RESET ();
if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { printf ("Skip bad block 0x%08llx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; }
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if(nand->skipfirstblk==1) { nand->skipfirstblk=0; printf ("Skip the first good block %llx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; } #endif
if (left_to_write < (nand->erasesize - block_offset)) write_size = left_to_write; else write_size = nand->erasesize - block_offset;
printf("\rWriting at 0x%llx -- ",offset); //add yaffs2 file system support
rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { printf ("NAND write to offset %llx failed %d\n", offset, rval); *length -= left_to_write; return rval; }
left_to_write -= write_size; printf("%d%% is complete.",100-(left_to_write/(*length/100))); offset += write_size;
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if(nand->rw_oob==1) { p_buffer += write_size+(write_size/nand->writesize*nand->oobsize); } else { p_buffer += write_size; } #else p_buffer += write_size; #endif
}
return 0; } |
在上一步nand_write_skip_bad函数中我们看到又对nand_write函数进行了访问,所以这一步是到nand_write函数中添加对yaffs2的支持,如下:
#gedit drivers/mtd/nand/nand_base.c //在nand_write函数中添加
|
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) { struct nand_chip *chip = mtd->priv; int ret;
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
int oldopsmode = 0;
if(mtd->rw_oob==1) { int i = 0; int datapages = 0;
size_t oobsize = mtd->oobsize; size_t datasize = mtd->writesize;
uint8_t oobtemp[oobsize]; datapages = len / (datasize);
for(i = 0; i < (datapages); i++) { memcpy((void *)oobtemp, (void *)(buf + datasize * (i + 1)), oobsize); memmove((void *)(buf + datasize * (i + 1)), (void *)(buf + datasize * (i + 1) + oobsize), (datapages - (i + 1)) * (datasize) + (datapages - 1) * oobsize); memcpy((void *)(buf+(datapages) * (datasize + oobsize) - oobsize), (void *)(oobtemp), oobsize); } } #endif
/* Do not allow reads past end of device */ if ((to + len) > mtd->size) return -EINVAL; if (!len) return 0;
nand_get_device(chip, mtd, FL_WRITING);
chip->ops.len = len; chip->ops.datbuf = (uint8_t *)buf;
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
if(mtd->rw_oob!=1) { chip->ops.oobbuf = NULL; } else { chip->ops.oobbuf = (uint8_t *)(buf + len); chip->ops.ooblen = mtd->oobsize; oldopsmode = chip->ops.mode; chip->ops.mode = MTD_OOB_RAW; } #else chip->ops.oobbuf = NULL; #endif
ret = nand_do_write_ops(mtd, to, &chip->ops);
*retlen = chip->ops.retlen;
nand_release_device(mtd);
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
chip->ops.mode = oldopsmode; #endif
return ret; }
| OK,对yaffs2支持的代码已修改完毕,重新编译u-boot并下载到nand中,启动开发板,在u-boot的命令行输入:nand help查看nand的命令,可以看到多了一个nand write[.yaffs2]的命令,这个就是用来下载yaffs2文件系统到nand中的命令了。
|