⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bon.c

📁 SMDK2440 boot code, base on vivi
💻 C
字号:
/*  * vivi/drivers/mtd/nand/bon.c * * Based on linux/drivers/mtd/nand/bon.c * * (C) 2002-2004 Mizi Research Inc. * Author: Hwang, Chideok <hwang@mizi.co.kr> */#include <config.h>#include <types.h>#include <mtd/mtd.h>#include <mtd/partitions.h>#include <mtd/nand_ecc.h>#include <errno.h>#include <vstring.h>#include <vmalloc.h>#include <progressbar.h>#include <command.h>#include <serial.h>#if BON_DEBUG#define DPRINTK(x...) printk(x)#else#define DPRINTK(x...) (void)(0)#endifstatic int PARTITION_OFFSET  = (~0);#define BONFS_OOB_ECCPOS0 8#define BONFS_OOB_ECCPOS1 9#define BONFS_OOB_ECCPOS2 10#define BONFS_OOB_ECCPOS3 11#define BONFS_OOB_ECCPOS4 12#define BONFS_OOB_ECCPOS5 13static struct nand_oobinfo bonfs_oob_8 = {	.useecc = MTD_NANDECC_AUTOPLACE,};static struct nand_oobinfo bonfs_oob_16 = {	.useecc = MTD_NANDECC_PLACE,	.eccbytes = 6,	.eccpos = {BONFS_OOB_ECCPOS0, BONFS_OOB_ECCPOS1, BONFS_OOB_ECCPOS2,		   BONFS_OOB_ECCPOS3, BONFS_OOB_ECCPOS4, BONFS_OOB_ECCPOS5},	.oobfree = { {0,4}, {6,2}, {14,2}},};static struct nand_oobinfo bonfs_oob_64 = {	.useecc = MTD_NANDECC_AUTOPLACE,};static struct nand_oobinfo yaffs_oobinfo = {	useecc: 1,	eccpos: {8, 9, 10, 13, 14, 15}};#define MAX_RETRY	(80)#define MAX_PART	(10)#define MAX_OOB_BUF	(16)typedef struct {	ulong offset;	ulong size;	ulong flag;	ulong num_bad_block;	ushort *bad_blocks;} partition_t;static struct {	struct mtd_info *mtd;	int num_part;	int num_mtd_part;	struct nand_oobinfo *oobinfo;	partition_t parts[MAX_PART];} bon;static const char BON_MAGIC[8] = {'M', 0, 0, 'I', 0, 'Z', 'I', 0};intbon_do_read(int npart, char *buf, unsigned long pos, size_t size){	int ret, retlen;	partition_t *part = &bon.parts[npart];	while(size > 0) {		unsigned long block = pos / bon.mtd->erasesize;		unsigned long start, start_in_block;		size_t this_size;		if (part->bad_blocks) {			unsigned short *bad = part->bad_blocks;			while(*bad++ <= block) {				block++;			}		}		start_in_block = pos % bon.mtd->erasesize;		start = block * bon.mtd->erasesize + start_in_block;		this_size = bon.mtd->erasesize - start_in_block;		if (this_size > size) this_size = size;		ret = MTD_READECC(bon.mtd, part->offset + start, 			       this_size, &retlen, buf, NULL, bon.oobinfo);		if (ret != 0) {			printk("%s(): retlen = %d, ECC error ? - [%d]\n", 			       __FUNCTION__, retlen, ret);				return ret;		}		if (this_size != retlen) {			printk("%s(): this_size = %d, retlen = %d\n", 			        __FUNCTION__, this_size, retlen);			return -EIO;		}		size -= this_size;		buf += this_size;		pos += this_size;	}	return 0;}intbon_do_write(int npart, char *buf, unsigned long pos, size_t size){	int ret, retlen;	partition_t *part = &bon.parts[npart];	/* allign by page size */	if (size % 512)		size = (((size >> 9)+1) << 9);	printk("writting... ");	progressbar_set_total(size);	while(size > 0) {		unsigned long block = pos / bon.mtd->erasesize;		unsigned long start, start_in_block;		size_t this_size;		struct erase_info ei;		if (part->bad_blocks) {			unsigned short *bad = part->bad_blocks;			while(*bad++ <= block) {				block++;			}		}		start_in_block = pos % bon.mtd->erasesize;		start = block * bon.mtd->erasesize + start_in_block;		this_size = bon.mtd->erasesize - start_in_block;		if (this_size > size) this_size = size;		ei.mtd = bon.mtd;		ei.addr = part->offset + start;		ei.len = bon.mtd->erasesize;		ei.time = 1000;		ei.retries = 0;		ei.callback = NULL;		ret = MTD_ERASE(bon.mtd, &ei);		ret = MTD_WRITEECC(bon.mtd, part->offset + start, 			       this_size, &retlen, buf, NULL, bon.oobinfo);		if (ret != 0) {			printk("\n%s(): retlen = %d, ECC error ? - [%d]\n", 			       __FUNCTION__, retlen, ret);				return ret;		}		if (this_size != retlen) {			printk("\n%s(): this_size = %d, retlen = %d\n", 			        __FUNCTION__, this_size, retlen);			return -EIO;		}		size -= this_size;		buf += this_size;		pos += this_size;		progressbar(size, BAR_DECREASE);	}	printk("ok\n");	return 0;}static void bon_display_info(void){	int i, j;	printk("      position          size       flag\n");	for (i = 0; i < bon.num_part; i++) {		partition_t *this = (partition_t *)&bon.parts[i];		printk("bon%d: %8.8lx-%8.8lx (%8.8lx) %8.8lx\n", i,		        this->offset, this->offset + this->size, 			this->size, this->flag);		printk("       bad blocks: %d\n", this->num_bad_block);		for (j = 0; j < this->num_bad_block; j++) {			printk("                    %d\n", this->bad_blocks[j]);		}	}}static inline void partinfo2buf(char *buf){	int i, j;	unsigned int *s;	memcpy(buf, BON_MAGIC, 8);	s = (unsigned int *)(buf + 8);	*s++ = bon.num_part;	for (i = 0; i < bon.num_part; i++) {		*s++ = bon.parts[i].offset;		*s++ = bon.parts[i].size;		*s++ = bon.parts[i].flag;	}	for (i = 0; i < bon.num_part; i++) {		*s++ = bon.parts[i].num_bad_block;		for (j = 0; j < bon.parts[i].num_bad_block; j++) {			*s++ = bon.parts[i].bad_blocks[j];		}	}}static inline int buf2partinfo(char *buf){	int i, j;	unsigned int *s;	s = (unsigned int *)(buf + 8);	bon.num_part = *s++;	if (bon.num_part > MAX_PART) {		printk("bon: too many partitions (%d)\n", bon.num_part);		return 1;	}	for (i = 0; i < bon.num_part; i++) {		bon.parts[i].offset = *s++;		bon.parts[i].size = *s++;		bon.parts[i].flag = *s++;	}	for (i = 0; i < bon.num_part; i++) {		partition_t *p = &bon.parts[i];		p->num_bad_block = *s++;		if (p->num_bad_block) {			p->bad_blocks = vmalloc(p->num_bad_block *					       sizeof(unsigned short));			if (!(p->bad_blocks))				return 1;			for (j = 0; j < p->num_bad_block; j++) {				p->bad_blocks[j] = *s++;			}		} else {			p->bad_blocks = NULL;		}	}	return 0;}static int_read_partition_info(struct mtd_info *mtd, char *buf, int verb){	unsigned long offset = PARTITION_OFFSET;	unsigned char oobbuf[MAX_OOB_BUF];	int retlen;	int retry_count = MAX_RETRY;	if (offset > mtd->size - mtd->erasesize) 		offset = mtd->size - mtd->erasesize;#if 1	DPRINTK("%s(): OOBSIZE = %d\n", __FUNCTION__, mtd->oobsize);	switch (mtd->oobsize) {	case 8:		bon.oobinfo = &bonfs_oob_8;		break;	case 16:		bon.oobinfo = &bonfs_oob_16;		break;	case 64:		bon.oobinfo = &bonfs_oob_64;		break;	default:		printk("BON does not yet know how to handle ECC\n");		return -EINVAL;	}#endif	while(retry_count-- > 0) {		if (MTD_READOOB(mtd, offset, 8, &retlen, oobbuf) < 0) {			goto next_block;		}		if (oobbuf[5] != 0xff) {			goto next_block;		}		if (MTD_READ(mtd, offset, 512, &retlen, buf) < 0) {			goto next_block;		}		if (strncmp(buf, BON_MAGIC, 8) == 0) break;		printk("bon:cannot find partition table\n");		return -1;next_block:		offset -= mtd->erasesize;	}	if (retry_count <= 0) {		printk("bon:cannot find partition table\n");		return -1;	}	buf2partinfo(buf);#if 0	for (i = 0; i < bon.num_part; i++) {		if (verb) {			printk("bon%d: %8.8lx-%8.8lx (%8.8lx) %8.8lx\n", i, 			        bon.parts[i].offset, 				bon.parts[i].offset + bon.parts[i].size,				bon.parts[i].size, bon.parts[i].flag);		}	}#endif	return bon.num_part;}intbon_read_partition_info(struct mtd_info *mtd){	char buf[512];	if (_read_partition_info(mtd, &buf[0], 1) < 0)		return -1;	return 0;}intbon_write_partition_info(struct mtd_info *mtd){	unsigned long offset = PARTITION_OFFSET;	unsigned char oobbuf[MAX_OOB_BUF];	u_char infobuf[512];	int retry_count = MAX_RETRY;	partition_t *p = NULL;	if (offset > mtd->size - mtd->erasesize) 		offset = mtd->size - mtd->erasesize;	memset(infobuf, 0xff, 512);	partinfo2buf(infobuf);	while(retry_count-- > 0) {		struct erase_info ei;		int ret, retlen;		if (MTD_READOOB(mtd, offset, 8, &retlen, oobbuf) < 0) {			goto next_block;		}		if (oobbuf[5] != 0xff) {			goto next_block;		}		ei.mtd = bon.mtd;		ei.addr = offset;		ei.len = bon.mtd->erasesize;		ei.time = 1000;		ei.retries = 0;		ei.callback = NULL;		ret = MTD_ERASE(mtd, &ei);		ret = MTD_WRITEECC(mtd, offset, 512, &retlen, infobuf, NULL, 				   bon.oobinfo);		if (ret != 0) {			printk("\n%s(): retlen = %d, ECC error ? - [%d]\n", 			       __FUNCTION__, retlen, ret);				goto next_block;		} else {			break;		}next_block:		offset -= mtd->erasesize;	}	if (retry_count <= 0) {		printk("too many bad blocks in this flash.\n");		return 1;	}	/* refresh size of last partition */	p = &bon.parts[bon.num_part-1];	if (offset < (p->offset + p->size)) {		p->size = (offset - p->offset);	}	return 0;}static voidcheck_bad_block(struct mtd_info *mtd){	int i;	unsigned short bad_block[1024];	int retlen;	ulong offset;	if ((bon.num_part <= 0) || (bon.num_part >= MAX_PART))		return;	offset = 0;	for (i = 0; i < bon.num_part; i++) {		ulong size = bon.parts[i].size;		int num_bad = 0;		offset = bon.parts[i].offset;		while (size > 0) {			u_char oobbuf[MAX_OOB_BUF];			if (MTD_READOOB(mtd, offset, 8, &retlen, oobbuf) < 0) {				goto found_bad;			}			if (oobbuf[5] != 0xff) {				goto found_bad;			}			size -= mtd->erasesize;			offset += mtd->erasesize;			continue;found_bad:			bad_block[num_bad] = (offset - bon.parts[i].offset) / mtd->erasesize;			num_bad++;			printk("%lX: is bad\n", offset);			offset += mtd->erasesize;		}		bon.parts[i].num_bad_block = num_bad;		if (num_bad) {			bon.parts[i].bad_blocks = vmalloc(num_bad * sizeof(unsigned short));			memcpy(bon.parts[i].bad_blocks, bad_block, num_bad * 2);		}	}}static intbon_partitioning(int argc, const char **argv){	int i, ret;	u_char c;	unsigned long max_bad_block;	printk("Doing partitioning...\n");	bon.mtd = mymtd;	bon.num_part = argc;	for (i = 0; i < bon.num_part; i++) {		char *s;		s = strchr((char *)argv[i], ':');		if (s) {			s++;			if (*s == 'm' || *s == 'M')				bon.parts[i].flag = 1;		} else {			bon.parts[i].flag = 0;		}		bon.parts[i].offset = simple_hstrtoul((char *)argv[i]);	}	max_bad_block = (((bon.mtd->size * 2UL) / 100UL) / bon.mtd->erasesize) * bon.mtd->erasesize;	printk("ttt = %d\n", max_bad_block);	for (i = 0; i < bon.num_part; i++) {		if (i == (bon.num_part - 1)) {			bon.parts[i].size = bon.mtd->size - max_bad_block;			bon.parts[i].size -= (bon.parts[i-1].offset + bon.parts[i-1].size);			break;		}		bon.parts[i].size = bon.parts[i+1].offset - bon.parts[i].offset;	}	printk("number of partitions: %d\n", bon.num_part);	for (i = 0; i < bon.num_part; i++) {		printk("[%d]: ofs = 0x%x, size = 0x%x, flag = %d\n",			i, bon.parts[i].offset, bon.parts[i].size,			bon.parts[i].flag);	}	printk("\nAre you sure (y/n) ? ");	c = getc();	printk("%s\n\n", c == 'y' ? "yes" : "no");	if (c != 'y')		return 0;	printk("checking bad blocks...\n");	check_bad_block(bon.mtd);	printk("writing partition table...\n");	ret = bon_write_partition_info(bon.mtd);#ifdef CONFIG_MTD_PARTITIONS_PARSER	printk("refresing partition table...\n");	mtdpart_refresh();#endif	return ret;}int bon_part_parser(void *ptr){	int i;	char name[16];	mtd_partition_t *tmp = (mtd_partition_t *)ptr;	if (bon_read_partition_info(bon.mtd)) {		printk("bon: invalid partition table\n");		return -1;	} else		printk("bon: found partition table\n");	for (i = 0; i < bon.num_part; i++) {		sprintf(name, "bon%d", i);		strcpy((tmp+i)->name, name);		(tmp+i)->offset = bon.parts[i].offset;		(tmp+i)->size = bon.parts[i].size;		if (bon.parts[i].flag == 1) {			(tmp+i)->flag = MF_YAFFS;			(tmp+i)->oobsel = &yaffs_oobinfo;		} else {			(tmp+i)->flag = MF_BON;			(tmp+i)->oobsel = bon.oobinfo;		}		(tmp+i)->priv = vmalloc(sizeof(int));		*(int *)(tmp+i)->priv = i;	}	strcpy((tmp+0)->name, "vivi");	strcpy((tmp+1)->name, "kernel");	strcpy((tmp+2)->name, "root");#ifdef CONFIG_S3C2440_MPORT3S	strcpy((tmp+3)->name, "module");	strcpy((tmp+4)->name, "disp");	strcpy((tmp+5)->name, "rp");	strcpy((tmp+6)->name, "bmp");	strcpy((tmp+7)->name, "xlib");	strcpy((tmp+8)->name, "usr");#endif#ifdef CONFIG_S3C2440_MPORT1S	strcpy((tmp+3)->name, "module");	strcpy((tmp+4)->name, "disp");	strcpy((tmp+5)->name, "network");	strcpy((tmp+6)->name, "guide");	strcpy((tmp+7)->name, "image");	strcpy((tmp+8)->name, "usr");#endif	return bon.num_part;}static void display_help(void){	printk("Usage:\n");	printk("\tbon info             -- Display bon partition info.\n");	printk("\tbon part <offsets>   -- Initialize bon partition info.\n");	printk("\tbon help             -- Display this message.\n");}static voidcommand_bon(int argc, const char **argv){	if (mymtd == NULL) {		printk("No mtd\n");		return;	}	switch (argc) {	case 2:		if (strncmp("help", argv[1], 4) == 0) {			display_help();			return;		}		if (strncmp("info", argv[1], 4) == 0) {			bon_display_info();			return;		}		break;	case 3:	case 4:	case 5:	case 6:	case 7:	case 8:	case 9:	case 10:	case 11:	case 12:	case 13:		if (strncmp("part", argv[1], 4) == 0) {			bon_partitioning(argc-2, argv+2);			return;		}		break;	default:		break;	}	display_help();}user_command_t bon_cmd =  {	"bon",	command_bon,	NULL};int bon_init(void){	memset(&bon, 0, sizeof(bon));	bon.mtd = mymtd;#ifdef CONFIG_MTD_PARTITIONS_PARSER	if (mtdpart_add_parser(bon_part_parser))		return 1;#else	if (bon_read_partition_info(bon.mtd)) {		printk("bon: invalid partition table\n");		return -1;	}#endif	add_command(&bon_cmd);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -