注意:红色标记为修改内容
由于现在很多使用Nand Flash 的系统,在Linux 下都用Yaffs(2)作为存储数据的文件系统,甚至是根文件系统。所以在BootLoader 下能够烧写Yaffs(2) 映像文件变得很必要。
(1) 修改common/cmd_nand.c文件
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc,char *argv[])
{
……….
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);
#if defined(ENABLE_CMD_NAND_YAFFS)
}elseif ( s != NULL &&
(!strcmp(s,".yaffs") || !strcmp(s, ".yaffs1"))){
if(read) {
printf("nand read.yaffs[1] is notprovide temporarily!");
} else {
nand->rw_oob= 1;
#if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
nand->skipfirstblk= 1;
#else
nand->skipfirstblk= 0;
#endif
ret= nand_write_skip_bad(nand,off,&size,(u_char *)addr);
#if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
nand->skipfirstblk= 0;
#endif
nand->rw_oob= 0;
}
#endif
}else if (!strcmp(s, ".oob")) {
/*out-of-band data */
mtd_oob_ops_tops = {
.oobbuf= (u8 *)addr,
.ooblen= size,
.mode= MTD_OOB_RAW
};
……….
}
……….
U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand,
……….
"nand erase [clean] [off size] - erase 'size'bytes from\n"
" offset 'off' (entire device if notspecified)\n"
#if defined(ENABLE_CMD_NAND_YAFFS)
"nandread[.yaffs[1]] is not provide temporarily!\n"
"nandwrite[.yaffs[1]] addr off size - writethe `size' byte yaffs image starting\n"
" at offset `off' from memory address `addr'(.yaffs1 for 512+16 NAND)\n"
#endif
"nandbad - show bad blocks\n"
"nanddump[.oob] off - dump page\n"
"nandscrub - really clean NAND erasing bad blocks (UNSAFE)\n"
……….
(2)修改driver/mtd/nand/nand_base.c文件
static int nand_write(struct mtd_info *mtd, loff_t to,size_t len,
size_t *retlen, const uint8_t *buf)
{
structnand_chip *chip = mtd->priv;
int ret;
#if defined(ENABLE_CMD_NAND_YAFFS)
/*Thanksfor hugerat's code!*/
intoldopsmode = 0;
if(mtd->rw_oob==1) {
size_toobsize = mtd->oobsize;
size_tdatasize = mtd->writesize;
inti = 0;
uint8_toobtemp[oobsize];
intdatapages = 0;
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 notallow reads past end of device */
if ((to +len) > mtd->size)
…………
chip->ops.len= len;
chip->ops.datbuf= (uint8_t *)buf;
// chip->ops.oobbuf= NULL;
#if defined(ENABLE_CMD_NAND_YAFFS)
/*Thanksfor hugerat's code!*/
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(ENABLE_CMD_NAND_YAFFS)
/*Thanks for hugerat's code!*/
chip->ops.mode = oldopsmode;
#endif
return ret;
}
(3)修改driver/mtd/nand/nand_util.c文件
int nand_write_skip_bad(nand_info_t *nand, loff_toffset, size_t *length,
u_char*buffer)
{
int rval;
size_tleft_to_write = *length;
size_tlen_incl_bad;
u_char*p_buffer = buffer;
#if defined(ENABLE_CMD_NAND_YAFFS)
/*Thanksfor hugerat's code*/
if(nand->rw_oob==1) {
size_toobsize = nand->oobsize;
size_tdatasize = nand->writesize;
intdatapages = 0;
if(((*length)%(nand->oobsize+nand->writesize)) != 0) {
printf ("Attempt to write error lengthdata!\n");
return -EINVAL;
}
datapages= *length/(datasize+oobsize);
*length= datapages*datasize;
left_to_write= *length;
// nand->skipfirstblock=1;
}
#endif
/*Reject writes, which are not page aligned */
if((offset & (nand->writesize - 1)) != 0 ||
……….
printf ("Attempt to write outside the flasharea\n");
return-EINVAL;
}
#if !defined(ENABLE_CMD_NAND_YAFFS)
/*by hugerat */
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);
returnrval;
}
#endif
while(left_to_write > 0) {
size_tblock_offset = offset & (nand->erasesize - 1);
………
offset += nand->erasesize - block_offset;
continue;
}
#if defined(ENABLE_CMD_NAND_YAFFS)
/*Thanksfor hugerat's code*/
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); /*Thanks for hugerat's code*/
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;
returnrval;
}
left_to_write-= write_size;
printf("%d%% iscomplete.",100-(left_to_write/(*length/100)));/*Thanks for hugerat'scode*/
offset += write_size;
#if defined(ENABLE_CMD_NAND_YAFFS)
/*Thanksfor hugerat's code*/
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;
}
(4)修改include/linux/mtd/mtd.h文件
struct mtd_info {
u_char type;
u_int32_tflags;
………
u_int32_t writesize;
#if defined(ENABLE_CMD_NAND_YAFFS)
/*Thanksfor hugerat's code*/
u_charrw_oob;
u_charskipfirstblk;
#endif
u_int32_toobsize; /* Amount of OOB data perblock (e.g. 16) */
u_int32_toobavail; /* Available OOB bytes perblock */
(5)修改配置文件 include/configs/sunzl2440.h
#endif /*CONFIG_CMD_NAND */
/**********************添加yaffs功能******************/
#define ENABLE_CMD_NAND_YAFFS 1
#define ENABLE_CMD_NAND_YAFFS_SKIPFB 1
/***************************************************/
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_INITRD_TAG
#define CONFIG_CMDLINE_TAG