diff options
Diffstat (limited to 'fs/jffs2/jffs2_1pass.c')
| -rw-r--r-- | fs/jffs2/jffs2_1pass.c | 630 | 
1 files changed, 350 insertions, 280 deletions
| diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index bacec8e30..a5d958359 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -1,3 +1,4 @@ +/* vi: set sw=4 ts=4: */  /*  -------------------------------------------------------------------------   * Filename:      jffs2.c @@ -75,6 +76,42 @@   *   */ +/* + * Bugfixing by Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>, (C) Mar/2003 + * + * - overhaul of the memory management. Removed much of the "paper-bagging" + *   in that part of the code, fixed several bugs, now frees memory when + *   partition is changed. + *   It's still ugly :-( + * - fixed a bug in jffs2_1pass_read_inode where the file length calculation + *   was incorrect. Removed a bit of the paper-bagging as well. + * - removed double crc calculation for fragment headers in jffs2_private.h + *   for speedup. + * - scan_empty rewritten in a more "standard" manner (non-paperbag, that is). + * - spinning wheel now spins depending on how much memory has been scanned + * - lots of small changes all over the place to "improve" readability. + * - implemented fragment sorting to ensure that the newest data is copied + *   if there are multiple copies of fragments for a certain file offset. + * + * The fragment sorting feature must be enabled by CFG_JFFS2_SORT_FRAGMENTS. + * Sorting is done while adding fragments to the lists, which is more or less a + * bubble sort. This takes a lot of time, and is most probably not an issue if + * the boot filesystem is always mounted readonly. + * + * You should define it if the boot filesystem is mounted writable, and updates + * to the boot files are done by copying files to that filesystem. + * + * + * There's a big issue left: endianess is completely ignored in this code. Duh! + * + * + * You still should have paper bags at hand :-(. The code lacks more or less + * any comment, and is still arcane and difficult to read in places. As this + * is incompatible with any new code from the jffs2 maintainers anyway, it + * should probably be dumped and replaced by something like jffs2reader! + */ + +  #include <common.h>  #include <config.h>  #include <malloc.h> @@ -88,124 +125,197 @@  #include "jffs2_private.h" -/* Compression names */ -static char *compr_names[] = { -        "NONE", -        "ZERO", -        "RTIME", -        "RUBINMIPS", -        "COPY", -        "DYNRUBIN", -        "ZLIB" }; -static char spinner[] = { '|', '\\', '-', '/' }; +#define	NODE_CHUNK  	1024	/* size of memory allocation chunk in b_nodes */ +#define	SPIN_BLKSIZE	18  	/* spin after having scanned 1<<BLKSIZE bytes */ + +/* Debugging switches */ +#undef	DEBUG_DIRENTS		/* print directory entry list after scan */ +#undef	DEBUG_FRAGMENTS		/* print fragment list after scan */ +#undef	DEBUG   			/* enable debugging messages */ + -#define DEBUG  #ifdef  DEBUG  # define DEBUGF(fmt,args...)	printf(fmt ,##args)  #else  # define DEBUGF(fmt,args...)  #endif -#define MALLOC_CHUNK (10*1024) +/* Compression names */ +static char *compr_names[] = { +	"NONE", +	"ZERO", +	"RTIME", +	"RUBINMIPS", +	"COPY", +	"DYNRUBIN", +	"ZLIB" +}; + +/* Spinning wheel */ +static char spinner[] = { '|', '/', '-', '\\' }; + +/* Memory management */ +struct mem_block { +	u32	index; +	struct mem_block *next; +	struct b_node nodes[NODE_CHUNK]; +}; + + +static void +free_nodes(struct b_list *list) +{ +	while (list->listMemBase != NULL) { +		struct mem_block *next = list->listMemBase->next; +		free( list->listMemBase ); +		list->listMemBase = next; +	} +}  static struct b_node * -add_node(struct b_node *tail, u32 * count, u32 * memBase) +add_node(struct b_list *list)  { -	u32 index; -	u32 memLimit; +	u32 index = 0; +	struct mem_block *memBase;  	struct b_node *b; -	index = (*count) * sizeof(struct b_node) % MALLOC_CHUNK; -	memLimit = MALLOC_CHUNK; - +	memBase = list->listMemBase; +	if (memBase != NULL) +		index = memBase->index;  #if 0  	putLabeledWord("add_node: index = ", index); -	putLabeledWord("add_node: memLimit = ", memLimit); -	putLabeledWord("add_node: memBase = ", *memBase); +	putLabeledWord("add_node: memBase = ", list->listMemBase);  #endif -	/* we need not keep a list of bases since we'll never free the */ -	/* memory, just jump the the kernel */ -	if ((index == 0) || (index > memLimit)) {	/* we need mode space before we continue */ -		if ((*memBase = (u32) mmalloc(MALLOC_CHUNK)) == (u32) NULL) { +	if (memBase == NULL || index >= NODE_CHUNK) { +		/* we need more space before we continue */ +		memBase = mmalloc(sizeof(struct mem_block)); +		if (memBase == NULL) {  			putstr("add_node: malloc failed\n");  			return NULL;  		} +		memBase->next = list->listMemBase; +		index = 0;  #if 0  		putLabeledWord("add_node: alloced a new membase at ", *memBase);  #endif  	}  	/* now we have room to add it. */ -	b = (struct b_node *) (*memBase + index); - -	/* null on first call */ -	if (tail) -		tail->next = b; +	b = &memBase->nodes[index]; +	index ++; -#if 0 -	putLabeledWord("add_node: tail = ", (u32) tail); -	if (tail) -		putLabeledWord("add_node: tail->next = ", (u32) tail->next); +	memBase->index = index; +	list->listMemBase = memBase; +	list->listCount++; +	return b; +} +static struct b_node * +insert_node(struct b_list *list, u32 offset) +{ +	struct b_node *new; +#ifdef CFG_JFFS2_SORT_FRAGMENTS +	struct b_node *b, *prev;  #endif -#if 0 -	putLabeledWord("add_node: mb+i = ", (u32) (*memBase + index)); -	putLabeledWord("add_node: b = ", (u32) b); +	if (!(new = add_node(list))) { +		putstr("add_node failed!\r\n"); +		return NULL; +	} +	new->offset = offset; + +#ifdef CFG_JFFS2_SORT_FRAGMENTS +	if (list->listTail != NULL && list->listCompare(new, list->listTail)) +		prev = list->listTail; +	else if (list->listLast != NULL && list->listCompare(new, list->listLast)) +		prev = list->listLast; +	else +		prev = NULL; + +	for (b = (prev ? prev->next : list->listHead); +	     b != NULL && list->listCompare(new, b); +	     prev = b, b = b->next) { +		list->listLoops++; +	} +	if (b != NULL) +		list->listLast = prev; + +	if (b != NULL) { +		new->next = b; +		if (prev != NULL) +			prev->next = new; +		else +			list->listHead = new; +	} else  #endif -	(*count)++; -	b->next = (struct b_node *) NULL; -	return b; +	{ +		new->next = (struct b_node *) NULL; +		if (list->listTail != NULL) { +			list->listTail->next = new; +			list->listTail = new; +		} else { +			list->listTail = list->listHead = new; +		} +	} +	return new;  } -/* we know we have empties at the start offset so we will hop */ -/* t points that would be non F if there were a node here to speed this up. */ -struct jffs2_empty_node { -	u32 first; -	u32 second; -}; +#ifdef CFG_JFFS2_SORT_FRAGMENTS +static int compare_inodes(struct b_node *new, struct b_node *old) +{ +	struct jffs2_raw_inode *jNew = (struct jffs2_raw_inode *)new->offset; +	struct jffs2_raw_inode *jOld = (struct jffs2_raw_inode *)old->offset; + +	return jNew->version < jOld->version; +} + +static int compare_dirents(struct b_node *new, struct b_node *old) +{ +	struct jffs2_raw_dirent *jNew = (struct jffs2_raw_dirent *)new->offset; +	struct jffs2_raw_dirent *jOld = (struct jffs2_raw_dirent *)old->offset; + +	return jNew->version > jOld->version; +} +#endif  static u32  jffs2_scan_empty(u32 start_offset, struct part_info *part)  { -	u32 max = part->size - sizeof(struct jffs2_raw_inode); - -	/* this would be either dir node_crc or frag isize */ -	u32 offset = start_offset + 32; -	struct jffs2_empty_node *node; +	char *max = part->offset + part->size - sizeof(struct jffs2_raw_inode); +	char *offset = part->offset + start_offset; -	start_offset += 4; -	while (offset < max) { -		node = (struct jffs2_empty_node *) (part->offset + offset); -		if ((node->first == 0xFFFFFFFF) && (node->second == 0xFFFFFFFF)) { -			/* we presume that there were no nodes in between and advance in a hop */ -			/* putLabeledWord("\t\tjffs2_scan_empty: empty at offset=",offset); */ -			start_offset = offset + 4; -			offset = start_offset + 32;	/* orig 32 + 4 bytes for the second==0xfffff */ -		} else { -			return start_offset; -		} +	while (offset < max && *(u32 *)offset == 0xFFFFFFFF) { +		offset += sizeof(u32); +		/* return if spinning is due */ +		if (((u32)offset & ((1 << SPIN_BLKSIZE)-1)) == 0) break;  	} -	return start_offset; + +	return offset - part->offset;  }  static u32  jffs_init_1pass_list(struct part_info *part)  { -	if ( 0 != ( part->jffs2_priv=malloc(sizeof(struct b_lists)))){ -		struct b_lists *pL =(struct b_lists *)part->jffs2_priv; +	struct b_lists *pL; + +	if (part->jffs2_priv != NULL) { +		pL = (struct b_lists *)part->jffs2_priv; +		free_nodes(&pL->frag); +		free_nodes(&pL->dir); +		free(pL); +	} +	if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) { +		pL = (struct b_lists *)part->jffs2_priv; -		pL->dirListHead = pL->dirListTail = NULL; -		pL->fragListHead = pL->fragListTail = NULL; -		pL->dirListCount = 0; -		pL->dirListMemBase = 0; -		pL->fragListCount = 0; -		pL->fragListMemBase = 0; -		pL->partOffset = 0x0; +		memset(pL, 0, sizeof(*pL)); +#ifdef CFG_JFFS2_SORT_FRAGMENTS +		pL->dir.listCompare = compare_dirents; +		pL->frag.listCompare = compare_inodes; +#endif  	}  	return 0;  } @@ -216,21 +326,18 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)  {  	struct b_node *b;  	struct jffs2_raw_inode *jNode; -	u32 totalSize = 1; -	u32 oldTotalSize = 0; -	u32 size = 0; -	char *lDest = (char *) dest; +	u32 totalSize = 0; +	u16 latestVersion = 0; +	char *lDest;  	char *src;  	long ret;  	int i;  	u32 counter = 0; -	char totalSizeSet = 0; -#if 0 -	b = pL->fragListHead; -	while (b) { +	for (b = pL->frag.listHead; b != NULL; b = b->next) {  		jNode = (struct jffs2_raw_inode *) (b->offset);  		if ((inode == jNode->ino)) { +#if 0  			putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen);  			putLabeledWord("read_inode: inode = ", jNode->ino);  			putLabeledWord("read_inode: version = ", jNode->version); @@ -241,58 +348,26 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)  			putLabeledWord("read_inode: compr = ", jNode->compr);  			putLabeledWord("read_inode: usercompr = ", jNode->usercompr);  			putLabeledWord("read_inode: flags = ", jNode->flags); -		} - -		b = b->next; -	} -  #endif - -#if 1 -	b = pL->fragListHead; -	while (b && (size < totalSize)) { -		jNode = (struct jffs2_raw_inode *) (b->offset); -		if ((inode == jNode->ino)) { -			if ((jNode->isize == oldTotalSize) && (jNode->isize > totalSize)) { -				/* 2 consecutive isizes indicate file length */ +			/* get actual file length from the newest node */ +			if (jNode->version >= latestVersion) {  				totalSize = jNode->isize; -				totalSizeSet = 1; -			} else if (!totalSizeSet) { -				totalSize = size + jNode->dsize + 1; +				latestVersion = jNode->version;  			} -			oldTotalSize = jNode->isize;  			if(dest) {  				src = ((char *) jNode) + sizeof(struct jffs2_raw_inode); -				/* lDest = (char *) (dest + (jNode->offset & ~3)); */ +				/* ignore data behind latest known EOF */ +				if (jNode->offset > totalSize) +					continue; +  				lDest = (char *) (dest + jNode->offset);  #if 0 -				putLabeledWord("\r\n\r\nread_inode: src = ", src); +				putLabeledWord("read_inode: src = ", src);  				putLabeledWord("read_inode: dest = ", lDest); -				putLabeledWord("read_inode: dsize = ", jNode->dsize); -				putLabeledWord("read_inode: csize = ", jNode->csize); -				putLabeledWord("read_inode: version = ", jNode->version); -				putLabeledWord("read_inode: isize = ", jNode->isize); -				putLabeledWord("read_inode: offset = ", jNode->offset); -				putLabeledWord("read_inode: compr = ", jNode->compr); -				putLabeledWord("read_inode: flags = ", jNode->flags);  #endif  				switch (jNode->compr) {  				case JFFS2_COMPR_NONE: -#if 0 -					{ -						int i; - -						if ((dest > 0xc0092ff0) && (dest < 0xc0093000)) -							for (i = 0; i < first->length; i++) { -								putLabeledWord("\tCOMPR_NONE: src =", src + i); -								putLabeledWord("\tCOMPR_NONE: length =", first->length); -								putLabeledWord("\tCOMPR_NONE: dest =", dest + i); -								putLabeledWord("\tCOMPR_NONE: data =", (unsigned char) *(src + i)); -							} -					} -#endif -  					ret = (unsigned long) ldr_memcpy(lDest, src, jNode->dsize);  					break;  				case JFFS2_COMPR_ZERO: @@ -320,22 +395,18 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)  				}  			} -			size += jNode->dsize;  #if 0 -			putLabeledWord("read_inode: size = ", size);  			putLabeledWord("read_inode: totalSize = ", totalSize);  			putLabeledWord("read_inode: compr ret = ", ret);  #endif  		} -		b = b->next;  		counter++;  	} -#endif  #if 0 -	putLabeledWord("read_inode: returning = ", size); +	putLabeledWord("read_inode: returning = ", totalSize);  #endif -	return size; +	return totalSize;  }  /* find the inode from the slashless name given a parent */ @@ -354,18 +425,19 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)  	counter = 0;  	/* we need to search all and return the inode with the highest version */ -	for(b = pL->dirListHead;b;b=b->next,counter++) { +	for(b = pL->dir.listHead; b; b = b->next, counter++) {  		jDir = (struct jffs2_raw_dirent *) (b->offset); -		if ((pino == jDir->pino) && (len == jDir->nsize) && (jDir->ino) &&	/* 0 for unlink */ +		if ((pino == jDir->pino) && (len == jDir->nsize) && +		    (jDir->ino) &&	/* 0 for unlink */  		    (!strncmp(jDir->name, name, len))) {	/* a match */  			if (jDir->version < version) continue; -		        if(jDir->version==0) { +		        if(jDir->version == 0) {  			    	/* Is this legal? */  				putstr(" ** WARNING ** ");  				putnstr(jDir->name, jDir->nsize);  				putstr(" is version 0 (in find, ignoring)\r\n"); -			} else if(jDir->version==version) { +			} else if(jDir->version == version) {  			    	/* Im pretty sure this isn't ... */  				putstr(" ** ERROR ** ");  				putnstr(jDir->name, jDir->nsize); @@ -389,53 +461,53 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)  static char *mkmodestr(unsigned long mode, char *str)  { -    static const char *l="xwr"; -    int mask=1, i; -    char c; +	static const char *l = "xwr"; +	int mask = 1, i; +	char c; -    switch (mode & S_IFMT) { -        case S_IFDIR:    str[0]='d'; break; -        case S_IFBLK:    str[0]='b'; break; -        case S_IFCHR:    str[0]='c'; break; -        case S_IFIFO:    str[0]='f'; break; -        case S_IFLNK:    str[0]='l'; break; -        case S_IFSOCK:   str[0]='s'; break; -        case S_IFREG:    str[0]='-'; break; -        default:        str[0]='?'; -    } +	switch (mode & S_IFMT) { +		case S_IFDIR:    str[0] = 'd'; break; +		case S_IFBLK:    str[0] = 'b'; break; +		case S_IFCHR:    str[0] = 'c'; break; +		case S_IFIFO:    str[0] = 'f'; break; +		case S_IFLNK:    str[0] = 'l'; break; +		case S_IFSOCK:   str[0] = 's'; break; +		case S_IFREG:    str[0] = '-'; break; +		default:         str[0] = '?'; +	} -    for(i=0;i<9;i++) { -        c=l[i%3]; -        str[9-i]=(mode & mask)?c:'-'; -        mask=mask<<1; -    } +	for(i = 0; i < 9; i++) { +		c = l[i%3]; +		str[9-i] = (mode & mask)?c:'-'; +		mask = mask<<1; +	} -    if(mode & S_ISUID) str[3]=(mode & S_IXUSR)?'s':'S'; -    if(mode & S_ISGID) str[6]=(mode & S_IXGRP)?'s':'S'; -    if(mode & S_ISVTX) str[9]=(mode & S_IXOTH)?'t':'T'; -    str[10]='\0'; -    return str; +	if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S'; +	if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S'; +	if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T'; +	str[10] = '\0'; +	return str;  }  static inline void dump_stat(struct stat *st, const char *name)  { -    char str[20]; -    char s[64], *p; +	char str[20]; +	char s[64], *p; -    if (st->st_mtime == (time_t)(-1))	/* some ctimes really hate -1 */ -        st->st_mtime = 1; +	if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */ +		st->st_mtime = 1; -    ctime_r(&st->st_mtime, s/*, 64*/);   /* newlib ctime doesn't have buflen */ +	ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */ -    if((p=strchr(s,'\n'))!=NULL) *p='\0'; -    if((p=strchr(s,'\r'))!=NULL) *p='\0'; +	if ((p = strchr(s,'\n')) != NULL) *p = '\0'; +	if ((p = strchr(s,'\r')) != NULL) *p = '\0';  /* -    printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str), -        st->st_size, s, name); +	printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str), +		st->st_size, s, name);  */ -    printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name); +	printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);  }  static inline u32 dump_inode(struct b_lists * pL, struct jffs2_raw_dirent *d, struct jffs2_raw_inode *i) @@ -446,16 +518,16 @@ static inline u32 dump_inode(struct b_lists * pL, struct jffs2_raw_dirent *d, st  	if(!d || !i) return -1;  	strncpy(fname, d->name, d->nsize); -	fname[d->nsize]='\0'; +	fname[d->nsize] = '\0';  	memset(&st,0,sizeof(st)); -	st.st_mtime=i->mtime; -	st.st_mode=i->mode; -	st.st_ino=i->ino; +	st.st_mtime = i->mtime; +	st.st_mode = i->mode; +	st.st_ino = i->ino;  	/* neither dsize nor isize help us.. do it the long way */ -	st.st_size=jffs2_1pass_read_inode(pL, i->ino, NULL); +	st.st_size = jffs2_1pass_read_inode(pL, i->ino, NULL);  	dump_stat(&st, fname); @@ -477,18 +549,18 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)  	struct b_node *b;  	struct jffs2_raw_dirent *jDir; -	for(b = pL->dirListHead;b;b=b->next) { +	for (b = pL->dir.listHead; b; b = b->next) {  		jDir = (struct jffs2_raw_dirent *) (b->offset); -		if ((pino == jDir->pino) && (jDir->ino)) {	/* 0 inode for unlink */ -			u32 i_version=0; -			struct jffs2_raw_inode *jNode, *i=NULL; -			struct b_node *b2 = pL->fragListHead; +		if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */ +			u32 i_version = 0; +			struct jffs2_raw_inode *jNode, *i = NULL; +			struct b_node *b2 = pL->frag.listHead;  			while (b2) {  				jNode = (struct jffs2_raw_inode *) (b2->offset);  				if (jNode->ino == jDir->ino -				    && jNode->version>=i_version) -					i=jNode; +				    && jNode->version >= i_version) +					i = jNode;  				b2 = b2->next;  			} @@ -568,7 +640,7 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)  	unsigned char *src;  	/* we need to search all and return the inode with the highest version */ -	for(b = pL->dirListHead; b; b=b->next) { +	for(b = pL->dir.listHead; b; b = b->next) {  		jDir = (struct jffs2_raw_dirent *) (b->offset);  		if (ino == jDir->ino) {  		    	if(jDir->version < version) continue; @@ -593,8 +665,9 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)  	/* now we found the right entry again. (shoulda returned inode*) */  	if (jDirFound->type != DT_LNK)  		return jDirFound->ino; -	/* so its a soft link so we follow it again. */ -	b2 = pL->fragListHead; + +	/* it's a soft link so we follow it again. */ +	b2 = pL->frag.listHead;  	while (b2) {  		jNode = (struct jffs2_raw_inode *) (b2->offset);  		if (jNode->ino == jDirFound->ino) { @@ -644,7 +717,8 @@ jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino)  			tmp[i] = c[i + 1];  		tmp[i] = '\0';  		/* only a failure if we arent looking at top level */ -		if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && (working_tmp[0])) { +		if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && +		    (working_tmp[0])) {  			putstr("find_inode failed for name=");  			putstr(working_tmp);  			putstr("\r\n"); @@ -674,29 +748,30 @@ jffs2_1pass_rescan_needed(struct part_info *part)  {  	struct b_node *b;  	struct jffs2_unknown_node *node; -	struct b_lists *pL=(struct b_lists *)part->jffs2_priv; +	struct b_lists *pL = (struct b_lists *)part->jffs2_priv;  	if (part->jffs2_priv == 0){  		DEBUGF ("rescan: First time in use\n");  		return 1;  	}  	/* if we have no list, we need to rescan */ -	if (pL->fragListCount == 0) { +	if (pL->frag.listCount == 0) {  		DEBUGF ("rescan: fraglist zero\n");  		return 1;  	} -	/* or if we are scanninga new partition */ +	/* or if we are scanning a new partition */  	if (pL->partOffset != part->offset) {  		DEBUGF ("rescan: different partition\n");  		return 1;  	} -	/* but suppose someone reflashed the root partition at the same offset... */ -	b = pL->dirListHead; +	/* but suppose someone reflashed a partition at the same offset... */ +	b = pL->dir.listHead;  	while (b) {  		node = (struct jffs2_unknown_node *) (b->offset);  		if (node->nodetype != JFFS2_NODETYPE_DIRENT) { -			DEBUGF ("rescan: fs changed beneath me? (%lx)\n", (unsigned long) b->offset); +			DEBUGF ("rescan: fs changed beneath me? (%lx)\n", +					(unsigned long) b->offset);  			return 1;  		}  		b = b->next; @@ -704,12 +779,71 @@ jffs2_1pass_rescan_needed(struct part_info *part)  	return 0;  } +#ifdef DEBUG_FRAGMENTS +static void +dump_fragments(struct b_lists *pL) +{ +	struct b_node *b; +	struct jffs2_raw_inode *jNode; + +	putstr("\r\n\r\n******The fragment Entries******\r\n"); +	b = pL->frag.listHead; +	while (b) { +		jNode = (struct jffs2_raw_inode *) (b->offset); +		putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset); +		putLabeledWord("\tbuild_list: totlen = ", jNode->totlen); +		putLabeledWord("\tbuild_list: inode = ", jNode->ino); +		putLabeledWord("\tbuild_list: version = ", jNode->version); +		putLabeledWord("\tbuild_list: isize = ", jNode->isize); +		putLabeledWord("\tbuild_list: atime = ", jNode->atime); +		putLabeledWord("\tbuild_list: offset = ", jNode->offset); +		putLabeledWord("\tbuild_list: csize = ", jNode->csize); +		putLabeledWord("\tbuild_list: dsize = ", jNode->dsize); +		putLabeledWord("\tbuild_list: compr = ", jNode->compr); +		putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr); +		putLabeledWord("\tbuild_list: flags = ", jNode->flags); +		putLabeledWord("\tbuild_list: offset = ", b->offset);	// FIXME: ? [RS] +		b = b->next; +	} +} +#endif + +#ifdef DEBUG_DIRENTS +static void +dump_dirents(struct b_lists *pL) +{ +	struct b_node *b; +	struct jffs2_raw_dirent *jDir; + +	putstr("\r\n\r\n******The directory Entries******\r\n"); +	b = pL->dir.listHead; +	while (b) { +		jDir = (struct jffs2_raw_dirent *) (b->offset); +		putstr("\r\n"); +		putnstr(jDir->name, jDir->nsize); +		putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic); +		putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype); +		putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc); +		putLabeledWord("\tbuild_list: pino = ", jDir->pino); +		putLabeledWord("\tbuild_list: version = ", jDir->version); +		putLabeledWord("\tbuild_list: ino = ", jDir->ino); +		putLabeledWord("\tbuild_list: mctime = ", jDir->mctime); +		putLabeledWord("\tbuild_list: nsize = ", jDir->nsize); +		putLabeledWord("\tbuild_list: type = ", jDir->type); +		putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc); +		putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc); +		putLabeledWord("\tbuild_list: offset = ", b->offset); 	// FIXME: ? [RS] +		b = b->next; +	} +} +#endif +  static u32  jffs2_1pass_build_lists(struct part_info * part)  {  	struct b_lists *pL;  	struct jffs2_unknown_node *node; -	u32 offset; +	u32 offset, oldoffset = 0;  	u32 max = part->size - sizeof(struct jffs2_raw_inode);  	u32 counter = 0;  	u32 counter4 = 0; @@ -722,71 +856,52 @@ jffs2_1pass_build_lists(struct part_info * part)  	/* lcd_off(); */  	/* if we are building a list we need to refresh the cache. */ -	/* note that since we don't free our memory, eventually this will be bad. */ -	/* but we're a bootldr so what the hell. */  	jffs_init_1pass_list(part); -	pL=(struct b_lists *)part->jffs2_priv; +	pL = (struct b_lists *)part->jffs2_priv;  	pL->partOffset = part->offset;  	offset = 0;  	printf("Scanning JFFS2 FS:   ");  	/* start at the beginning of the partition */  	while (offset < max) { -	    	if (! (++counter%10000)) -			printf("\b\b%c ", spinner[(counter / 10000) % 4]); +	    	if ((oldoffset >> SPIN_BLKSIZE) != (offset >> SPIN_BLKSIZE)) { +			printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]); +			oldoffset = offset; +		}  		node = (struct jffs2_unknown_node *) (part->offset + offset);  		if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) {  			/* if its a fragment add it */ -			if (node->nodetype == JFFS2_NODETYPE_INODE && inode_crc((struct jffs2_raw_inode *) node)) { -				if (!(pL->fragListTail = add_node(pL->fragListTail, &(pL->fragListCount), -								  &(pL->fragListMemBase)))) { -					putstr("add_node failed!\r\n"); +			if (node->nodetype == JFFS2_NODETYPE_INODE && +				    inode_crc((struct jffs2_raw_inode *) node)) { +				if (insert_node(&pL->frag, (u32) part->offset + +								offset) == NULL)  					return 0; -				} -				pL->fragListTail->offset = (u32) (part->offset + offset); -				if (!pL->fragListHead) -					pL->fragListHead = pL->fragListTail;  			} else if (node->nodetype == JFFS2_NODETYPE_DIRENT &&  				   dirent_crc((struct jffs2_raw_dirent *) node)  &&  				   dirent_name_crc((struct jffs2_raw_dirent *) node)) {  				if (! (counterN%100))  					printf("\b\b.  "); -#if 0 -				printf("Found DIRENT @ 0x%lx\n", offset); -				putstr("\r\nbuild_lists:p&l ->"); -				putnstr(((struct jffs2_raw_dirent *) node)->name, ((struct jffs2_raw_dirent *) node)->nsize); -				putstr("\r\n"); -				putLabeledWord("\tpino = ", ((struct jffs2_raw_dirent *) node)->pino); -				putLabeledWord("\tnsize = ", ((struct jffs2_raw_dirent *) node)->nsize); -#endif - -				if (!(pL->dirListTail = add_node(pL->dirListTail, &(pL->dirListCount), &(pL->dirListMemBase)))) { -					putstr("add_node failed!\r\n"); +				if (insert_node(&pL->dir, (u32) part->offset + +								offset) == NULL)  					return 0; -				} -				pL->dirListTail->offset = (u32) (part->offset + offset); -#if 0 -				putLabeledWord("\ttail = ", (u32) pL->dirListTail); -				putstr("\ttailName ->"); -				putnstr(((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->name, -					((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->nsize); -				putstr("\r\n"); -#endif -				if (!pL->dirListHead) -					pL->dirListHead = pL->dirListTail;  				counterN++;  			} else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) {  				if (node->totlen != sizeof(struct jffs2_unknown_node)) -					printf("OOPS Cleanmarker has bad size %d != %d\n", node->totlen, sizeof(struct jffs2_unknown_node)); +					printf("OOPS Cleanmarker has bad size " +						"%d != %d\n", node->totlen, +						sizeof(struct jffs2_unknown_node));  			} else { -				printf("Unknown node type: %x len %d offset 0x%x\n", node->nodetype, node->totlen, offset); +				printf("Unknown node type: %x len %d " +					"offset 0x%x\n", node->nodetype, +					node->totlen, offset);  			}  			offset += ((node->totlen + 3) & ~3);  			counterF++; -		} else if (node->magic == JFFS2_EMPTY_BITMASK && node->nodetype == JFFS2_EMPTY_BITMASK) { +		} else if (node->magic == JFFS2_EMPTY_BITMASK && +			   node->nodetype == JFFS2_EMPTY_BITMASK) {  			offset = jffs2_scan_empty(offset, part); -		} else {	/* if we know nothing of the filesystem, we just step and look. */ +		} else {	/* if we know nothing, we just step and look. */  			offset += 4;  			counter4++;  		} @@ -799,66 +914,21 @@ jffs2_1pass_build_lists(struct part_info * part)  	/* splash(); */  #if 0 -	putLabeledWord("dir entries = ", pL->dirListCount); -	putLabeledWord("frag entries = ", pL->fragListCount); +	putLabeledWord("dir entries = ", pL->dir.listCount); +	putLabeledWord("frag entries = ", pL->frag.listCount);  	putLabeledWord("+4 increments = ", counter4);  	putLabeledWord("+file_offset increments = ", counterF);  #endif -#undef SHOW_ALL -#undef SHOW_ALL_FRAGMENTS - -#ifdef SHOW_ALL -	{ -		struct b_node *b; -		struct b_node *b2; -		struct jffs2_raw_dirent *jDir; -		struct jffs2_raw_inode *jNode; - -		putstr("\r\n\r\n******The directory Entries******\r\n"); -		b = pL->dirListHead; -		while (b) { -			jDir = (struct jffs2_raw_dirent *) (b->offset); -			putstr("\r\n"); -			putnstr(jDir->name, jDir->nsize); -			putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic); -			putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype); -			putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc); -			putLabeledWord("\tbuild_list: pino = ", jDir->pino); -			putLabeledWord("\tbuild_list: version = ", jDir->version); -			putLabeledWord("\tbuild_list: ino = ", jDir->ino); -			putLabeledWord("\tbuild_list: mctime = ", jDir->mctime); -			putLabeledWord("\tbuild_list: nsize = ", jDir->nsize); -			putLabeledWord("\tbuild_list: type = ", jDir->type); -			putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc); -			putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc); -			b = b->next; -		} +#ifdef DEBUG_DIRENTS +	dump_dirents(pL); +#endif -#ifdef SHOW_ALL_FRAGMENTS -		putstr("\r\n\r\n******The fragment Entries******\r\n"); -		b = pL->fragListHead; -		while (b) { -			jNode = (struct jffs2_raw_inode *) (b->offset); -			putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset); -			putLabeledWord("\tbuild_list: totlen = ", jNode->totlen); -			putLabeledWord("\tbuild_list: inode = ", jNode->ino); -			putLabeledWord("\tbuild_list: version = ", jNode->version); -			putLabeledWord("\tbuild_list: isize = ", jNode->isize); -			putLabeledWord("\tbuild_list: atime = ", jNode->atime); -			putLabeledWord("\tbuild_list: offset = ", jNode->offset); -			putLabeledWord("\tbuild_list: csize = ", jNode->csize); -			putLabeledWord("\tbuild_list: dsize = ", jNode->dsize); -			putLabeledWord("\tbuild_list: compr = ", jNode->compr); -			putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr); -			putLabeledWord("\tbuild_list: flags = ", jNode->flags); -			b = b->next; -		} -#endif /* SHOW_ALL_FRAGMENTS */ -	} +#ifdef DEBUG_FRAGMENTS +	dump_fragments(pL); +#endif -#endif	/* SHOW_ALL */  	/* give visual feedback that we are done scanning the flash */  	led_blink(0x0, 0x0, 0x1, 0x1);	/* off, forever, on 100ms, off 100ms */  	return 1; @@ -875,13 +945,13 @@ jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL)  	struct jffs2_raw_inode *jNode;  	int i; -	b = pL->fragListHead;  	for (i = 0; i < JFFS2_NUM_COMPR; i++) {  		piL->compr_info[i].num_frags = 0;  		piL->compr_info[i].compr_sum = 0;  		piL->compr_info[i].decompr_sum = 0;  	} +	b = pL->frag.listHead;  	while (b) {  		jNode = (struct jffs2_raw_inode *) (b->offset);  		if (jNode->compr < JFFS2_NUM_COMPR) { @@ -917,7 +987,7 @@ jffs2_1pass_ls(struct part_info * part, const char *fname)  	long ret = 0;  	u32 inode; -	if (! (pl  = jffs2_get_list(part, "ls"))) +	if (! (pl = jffs2_get_list(part, "ls")))  		return 0;  	if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) { @@ -983,7 +1053,7 @@ jffs2_1pass_info(struct part_info * part)  		return 0;  	jffs2_1pass_fill_info(pl, &info); -	for (i=0; i < JFFS2_NUM_COMPR; i++) { +	for (i = 0; i < JFFS2_NUM_COMPR; i++) {  		printf("Compression: %s\n", compr_names[i]);  		printf("\tfrag count: %d\n", info.compr_info[i].num_frags);  		printf("\tcompressed sum: %d\n", info.compr_info[i].compr_sum); |