📄 yaffs.c
字号:
/* * vivi/drivers/mtd/nand/bon.c * * Based on vivi/util/imagewrite * * $Id: bon.c,v 1.13 2003/06/12 11:14:01 nandy Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Description: Simple management routines for the bon file system. * */#include <config.h>#include <mtd/mtd.h>#include <mtd/nand_ecc.h>#include <printk.h>#include <errno.h>#include <heap.h>#include <string.h>#include <command.h>#include <ctype.h>#include <mtd/bonfs.h>#include <priv_data.h>#ifdef CONFIG_MTD_YAFFS// countBits is a quick way of counting the number of bits in a byte.// ie. countBits[n] holds the number of 1 bits in a byte with the value n.static const char countBits[256] ={ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};/* * OOB layout */struct nand_oobinfo yaffs_oobinfo = { useecc: 1, eccpos: {8, 9, 10, 13, 14, 15}};#if 1struct nand_oobinfo yaffs_noeccinfo = { useecc: 0,};static voidmark_bad_yaffs(struct mtd_info *mtd, ulong offset){ char oobbuf[NAND_OOB_SIZE]; memset (oobbuf, 0xff, NAND_OOB_SIZE); oobbuf[5] = 0; mtd->write_oob(mtd, offset, NAND_OOB_SIZE, NULL, oobbuf);}static intis_bad_yaffs_block(struct mtd_info *mtd, ulong offset){ unsigned char oobbuf[NAND_OOB_SIZE]; char buf[NAND_SECTOR_SIZE]; struct erase_info erase; size_t retlen; erase.addr = offset; erase.len = mtd->erasesize; if (mtd->erase(mtd, &erase) < 0) {printk("erase error\n");return 1;} if (mtd->read_oob(mtd, offset, NAND_OOB_SIZE, &retlen, oobbuf)) { printk("read oob error\n"); return -1; } if (countBits[oobbuf[5]] < 7) {printk("countbit error\n");return -1;} if (mtd->read(mtd, offset, NAND_SECTOR_SIZE, &retlen, buf)) { printk("read error 1\n"); return -1; } if (retlen != NAND_SECTOR_SIZE) { printk("read error\n"); mark_bad_yaffs(mtd, offset); return -1; } return 0;}static intwrite_oob_yaffs(struct mtd_info *mtd, char *buf, ulong offset){ char oob_buf[NAND_OOB_SIZE];// unsigned char ecc[3]; memset(oob_buf, 0xFF, NAND_OOB_SIZE);/* calc_ecc(mtd,buf, ecc); memcpy(oob_buf + 8, ecc, 3); calc_ecc(mtd,buf + 256, ecc); memcpy(oob_buf + 11, ecc, 3);*/ memcpy(oob_buf, buf+NAND_SECTOR_SIZE, 8); if (mtd->write_oob(mtd, offset, NAND_OOB_SIZE, NULL, oob_buf)) return 1; else return 0;}/** Use NAND write ECC*/static int nand_write_ecc_yaffs (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, char * buf){#if 0/* int i=0,cnt=len; int col; col=(mtd->oobblock-1) & len; if(col){ cnt=len+mtd->oobblock-col; } for(i=len;i<cnt;i++) buf[i]=0xff;*/ char tmp[NAND_SECTOR_SIZE]; int i; size_t retlen; mtd->read(mtd, to, NAND_SECTOR_SIZE, &retlen, tmp); printk("read 0x%s\n", to); return 0;#else printk("1write to 0x%x buf=0x%x\n", buf, to); mtd->write_ecc(mtd, to, len, retlen, (u_char *)buf, NULL, &yaffs_oobinfo); if(len == (int)(*retlen)){ *retlen=len; return 0; }else{ printk("here nand write error\n"); return (*retlen); }#endif} static intwrite_block_yaffs(struct mtd_info *mtd, ulong offset, char *buf){ int i; size_t retlen = 0; //printk("offset=0x%x buf=0x%x\n", offset, buf); if (is_bad_yaffs_block(mtd, offset)) {printk("bad block\n"); return 1;} for (i = 0; i < (mtd->erasesize/NAND_SECTOR_SIZE); i++) {// printk("buf=0x%x\n", buf); mtd->write(mtd, offset, NAND_SECTOR_SIZE, &retlen, buf);// mtd->write_ecc(mtd, offset, NAND_SECTOR_SIZE, &retlen, buf, NULL, &yaffs_oobinfo);// if (nand_write_ecc_yaffs(mtd, offset, NAND_SECTOR_SIZE, &retlen, buf))// {printk("write_ecc error\n"); return 1;} if (retlen != NAND_SECTOR_SIZE) {printk("size error\n");return 1;} // if (write_oob_yaffs(mtd, buf, offset)) return 1; offset += NAND_SECTOR_SIZE; buf += NAND_SECTOR_SIZE+NAND_OOB_SIZE; }}char yaffs_bon_block[(NAND_SECTOR_SIZE+NAND_OOB_SIZE)*32];#endifint yaffs_led_flag=0;extern mtd_partition_t *mtd_parts;extern int *nb_mtd_parts;write_bon_yaffs(struct mtd_info *mtd, ulong offset, char *src, long size){ char *buf=src;// unsigned short *bad; ulong addr, mtdsize, mtdstart; int i; mtd_partition_t *parts = mtd_parts; int num = *nb_mtd_parts; unsigned long sum=0; size -= size%528 ; //printk("write_bon_yaffs,offset = 0x%x \n",offset); //printk("write_bon_yaffs,size = 0x%x \n",size); if (offset % mtd->erasesize) { printk("bad alignment\n"); return -1; } if (!(mtd->oobsize==NAND_OOB_SIZE)&&mtd->oobblock==NAND_SECTOR_SIZE){ printk("Unknow flash (not normal NAND flash)\n"); return -1; } for (i = 0; i < num; i++) { if (parts[i].offset == offset) break; } if (i == num) i = num - 1; //printk ("i = %d \n",i); //printk ("part name is 0x%s\n",parts[i].name); //printk ("part offset is 0x%x\n",parts[i].offset); //printk ("part size is 0x%x\n",parts[i].size); //printk ("part flag is 0x%x\n",parts[i].flag); if (offset + size > parts[i].offset + parts[i].size) { printk("image is too big for this partition\n"); return -1; } if ((size/(mtd->oobblock+mtd->oobsize)+32)*mtd->oobblock> parts[i].size) { printk("image is too big for this partition for yaffs\n"); return -1; }// block = (offset - parts[i].offset) / mtd->erasesize;// bad = parts[i].bad_blocks;// if (bad) {// while (*bad++ <= block) block++;// }// offset = parts[i].offset + block * mtd->erasesize; mtdsize = parts[i].size; mtdstart = parts[i].offset; //printk ("addr is 0x%x ,mtdsize is 0x%x\n",mtdstart,mtdsize); /* for (i = 0; i < 32; i ++) printk("buf[%d] = 0x%x ",i,buf[i] ); printk("\n"); while(1); */ for (addr=mtdstart; addr<mtdsize+mtdstart; addr+=mtd->erasesize) { char oob_buf[NAND_OOB_SIZE]; struct erase_info erase; erase.addr = addr; erase.len = mtd->erasesize; //printk("Erase block at 0x%x\n", addr); if (mtd->erase(mtd, &erase) < 0) { printk("addr 0x%x erase error\n",erase.addr); //mark_bad_yaffs(mtd,addr); //return 1; continue; } //if (yaffs_led_flag%50==0)Led_Display(0x6); //if (yaffs_led_flag%50==25)Led_Display(0x9); //yaffs_led_flag++; mtd->read_oob(mtd, addr, NAND_OOB_SIZE, NULL, oob_buf); if (countBits[oob_buf[5]]<7) { printk("block at 0x%lx is damaged\n", addr); //mark_bad_yaffs(mtd,addr); } else { if (addr>mtdstart) { ulong tmp=addr; for (tmp=0; tmp<mtd->erasesize; tmp+=NAND_SECTOR_SIZE) { if (size > 0){ char oobbuf[NAND_OOB_SIZE]; memcpy(oobbuf, buf+NAND_SECTOR_SIZE, 16); oobbuf[8]=0xff; oobbuf[9]=0xff; oobbuf[10]=0xff; oobbuf[13]=0xff; oobbuf[14]=0xff; oobbuf[15]=0xff; mtd->write_oob(mtd, tmp+addr, NAND_OOB_SIZE, NULL, oobbuf); mtd->write_ecc(mtd, tmp+addr, NAND_SECTOR_SIZE, NULL, buf, NULL, &yaffs_oobinfo); buf+=NAND_SECTOR_SIZE+NAND_OOB_SIZE; size -= NAND_SECTOR_SIZE+NAND_OOB_SIZE; sum+= 528; if (size <= 0) { printk("yaffs wiriter has write %d byte\n",sum); return; } } } } } } return 0;}#endif /* CONFIG_CMD_BONFS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -