diff options
| -rw-r--r-- | fs/jffs2/jffs2_1pass.c | 187 | ||||
| -rw-r--r-- | fs/jffs2/summary.h | 163 | ||||
| -rw-r--r-- | include/jffs2/jffs2.h | 19 | 
3 files changed, 368 insertions, 1 deletions
| diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 73d3ddc9e..4e49a0566 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -138,6 +138,8 @@  # define DEBUGF(fmt,args...)  #endif +#include "summary.h" +  /* keeps pointer to currentlu processed partition */  static struct part_info *current_part; @@ -1214,6 +1216,132 @@ jffs2_1pass_rescan_needed(struct part_info *part)  	return 0;  } +#define dbg_summary(...) do {} while (0); +/* Process the stored summary information - helper function for + * jffs2_sum_scan_sumnode() + */ + +static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset, +				struct jffs2_raw_summary *summary, +				struct b_lists *pL) +{ +	void *sp; +	int i; + +	sp = summary->sum; + +	for (i = 0; i < summary->sum_num; i++) { +		dbg_summary("processing summary index %d\n", i); + +		switch (((struct jffs2_sum_unknown_flash *)sp)->nodetype) { +			case JFFS2_NODETYPE_INODE: { +				struct jffs2_sum_inode_flash *spi; +				spi = sp; + +				dbg_summary("Inode at 0x%08x-0x%08x\n", +					    offset + spi->offset, +					    offset + spi->offset + spi->totlen); + +				if (insert_node(&pL->frag, (u32) part->offset + +						offset + spi->offset) == NULL) +					return -1; + +				sp += JFFS2_SUMMARY_INODE_SIZE; + +				break; +			} + +			case JFFS2_NODETYPE_DIRENT: { +				struct jffs2_sum_dirent_flash *spd; +				spd = sp; + +				dbg_summary("Dirent at 0x%08x-0x%08x\n", +					    offset + spd->offset, +					    offset + spd->offset + spd->totlen); + +				if (insert_node(&pL->dir, (u32) part->offset + +						offset + spd->offset) == NULL) +					return -1; + +				sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize); + +				break; +			} +			default : { +				uint16_t nodetype = +					((struct jffs2_sum_unknown_flash *) +					 sp)->nodetype; +				printf("Unsupported node type %x found in " +						"summary!\n", nodetype); +				break; +			} +		} +	} +	return 0; +} + +/* Process the summary node - called from jffs2_scan_eraseblock() */ +int jffs2_sum_scan_sumnode(struct part_info *part, uint32_t offset, +			   struct jffs2_raw_summary *summary, uint32_t sumsize, +			   struct b_lists *pL) +{ +	struct jffs2_unknown_node crcnode; +	int ret, ofs; +	uint32_t crc; + +	ofs = part->sector_size - sumsize; + +	dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", +		    offset, offset + ofs, sumsize); + +	/* OK, now check for node validity and CRC */ +	crcnode.magic = JFFS2_MAGIC_BITMASK; +	crcnode.nodetype = JFFS2_NODETYPE_SUMMARY; +	crcnode.totlen = summary->totlen; +	crc = crc32_no_comp(0, (uchar *)&crcnode, sizeof(crcnode)-4); + +	if (summary->hdr_crc != crc) { +		dbg_summary("Summary node header is corrupt (bad CRC or " +				"no summary at all)\n"); +		goto crc_err; +	} + +	if (summary->totlen != sumsize) { +		dbg_summary("Summary node is corrupt (wrong erasesize?)\n"); +		goto crc_err; +	} + +	crc = crc32_no_comp(0, (uchar *)summary, +			sizeof(struct jffs2_raw_summary)-8); + +	if (summary->node_crc != crc) { +		dbg_summary("Summary node is corrupt (bad CRC)\n"); +		goto crc_err; +	} + +	crc = crc32_no_comp(0, (uchar *)summary->sum, +			sumsize - sizeof(struct jffs2_raw_summary)); + +	if (summary->sum_crc != crc) { +		dbg_summary("Summary node data is corrupt (bad CRC)\n"); +		goto crc_err; +	} + +	if (summary->cln_mkr) +		dbg_summary("Summary : CLEANMARKER node \n"); + +	ret = jffs2_sum_process_sum_data(part, offset, summary, pL); +	if (ret) +		return ret;		/* real error */ + +	return 1; + +crc_err: +	putstr("Summary node crc error, skipping summary information.\n"); + +	return 0; +} +  #ifdef DEBUG_FRAGMENTS  static void  dump_fragments(struct b_lists *pL) @@ -1321,10 +1449,65 @@ jffs2_1pass_build_lists(struct part_info * part)  	for (i = 0; i < nr_sectors; i++) {  		uint32_t sector_ofs = i * part->sector_size;  		uint32_t buf_ofs = sector_ofs; -		uint32_t buf_len = EMPTY_SCAN_SIZE(part->sector_size); +		uint32_t buf_len;  		uint32_t ofs, prevofs; +		struct jffs2_sum_marker *sm; +		void *sumptr = NULL; +		uint32_t sumlen; +		int ret;  		WATCHDOG_RESET(); + +		buf_len = sizeof(*sm); + +		/* Read as much as we want into the _end_ of the preallocated +		 * buffer +		 */ +		get_fl_mem(part->offset + sector_ofs + part->sector_size - +				buf_len, buf_len, buf + buf_size - buf_len); + +		sm = (void *)buf + buf_size - sizeof(*sm); +		if (sm->magic == JFFS2_SUM_MAGIC) { +			sumlen = part->sector_size - sm->offset; +			sumptr = buf + buf_size - sumlen; + +			/* Now, make sure the summary itself is available */ +			if (sumlen > buf_size) { +				/* Need to kmalloc for this. */ +				sumptr = malloc(sumlen); +				if (!sumptr) { +					putstr("Can't get memory for summary " +							"node!\n"); +					return 0; +				} +				memcpy(sumptr + sumlen - buf_len, buf + +						buf_size - buf_len, buf_len); +			} +			if (buf_len < sumlen) { +				/* Need to read more so that the entire summary +				 * node is present +				 */ +				get_fl_mem(part->offset + sector_ofs + +						part->sector_size - sumlen, +						sumlen - buf_len, sumptr); +			} +		} + +		if (sumptr) { +			ret = jffs2_sum_scan_sumnode(part, sector_ofs, sumptr, +					sumlen, pL); + +			if (buf_size && sumlen > buf_size) +				free(sumptr); +			if (ret < 0) +				return 0; +			if (ret) +				continue; + +		} + +		buf_len = EMPTY_SCAN_SIZE(part->sector_size); +  		get_fl_mem((u32)part->offset + buf_ofs, buf_len, buf);  		/* We temporarily use 'ofs' as a pointer into the buffer/jeb */ @@ -1477,6 +1660,8 @@ jffs2_1pass_build_lists(struct part_info * part)  						node->totlen,  						sizeof(struct jffs2_unknown_node));  				break; +			case JFFS2_NODETYPE_SUMMARY: +				break;  			default:  				printf("Unknown node type: %x len %d offset 0x%x\n",  					node->nodetype, diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h new file mode 100644 index 000000000..834933cd1 --- /dev/null +++ b/fs/jffs2/summary.h @@ -0,0 +1,163 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright © 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>, + *		     Zoltan Sogor <weth@inf.u-szeged.hu>, + *		     Patrik Kluba <pajko@halom.u-szeged.hu>, + *		     University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ + +#ifndef JFFS2_SUMMARY_H +#define JFFS2_SUMMARY_H + +#define BLK_STATE_ALLFF		0 +#define BLK_STATE_CLEAN		1 +#define BLK_STATE_PARTDIRTY	2 +#define BLK_STATE_CLEANMARKER	3 +#define BLK_STATE_ALLDIRTY	4 +#define BLK_STATE_BADBLOCK	5 + +#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff +#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) +#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) +#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash)) +#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash)) + +/* Summary structures used on flash */ + +struct jffs2_sum_unknown_flash +{ +	__u16 nodetype;	/* node type */ +}; + +struct jffs2_sum_inode_flash +{ +	__u16 nodetype;	/* node type */ +	__u32 inode;		/* inode number */ +	__u32 version;	/* inode version */ +	__u32 offset;	/* offset on jeb */ +	__u32 totlen; 	/* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_flash +{ +	__u16 nodetype;	/* == JFFS_NODETYPE_DIRENT */ +	__u32 totlen;	/* record length */ +	__u32 offset;	/* offset on jeb */ +	__u32 pino;		/* parent inode */ +	__u32 version;	/* dirent version */ +	__u32 ino; 		/* == zero for unlink */ +	uint8_t nsize;		/* dirent name size */ +	uint8_t type;		/* dirent type */ +	uint8_t name[0];	/* dirent name */ +} __attribute__((packed)); + +struct jffs2_sum_xattr_flash +{ +	__u16 nodetype;	/* == JFFS2_NODETYPE_XATR */ +	__u32 xid;		/* xattr identifier */ +	__u32 version;	/* version number */ +	__u32 offset;	/* offset on jeb */ +	__u32 totlen;	/* node length */ +} __attribute__((packed)); + +struct jffs2_sum_xref_flash +{ +	__u16 nodetype;	/* == JFFS2_NODETYPE_XREF */ +	__u32 offset;	/* offset on jeb */ +} __attribute__((packed)); + +union jffs2_sum_flash +{ +	struct jffs2_sum_unknown_flash u; +	struct jffs2_sum_inode_flash i; +	struct jffs2_sum_dirent_flash d; +	struct jffs2_sum_xattr_flash x; +	struct jffs2_sum_xref_flash r; +}; + +/* Summary structures used in the memory */ + +struct jffs2_sum_unknown_mem +{ +	union jffs2_sum_mem *next; +	__u16 nodetype;	/* node type */ +}; + +struct jffs2_sum_inode_mem +{ +	union jffs2_sum_mem *next; +	__u16 nodetype;	/* node type */ +	__u32 inode;		/* inode number */ +	__u32 version;	/* inode version */ +	__u32 offset;	/* offset on jeb */ +	__u32 totlen; 	/* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_mem +{ +	union jffs2_sum_mem *next; +	__u16 nodetype;	/* == JFFS_NODETYPE_DIRENT */ +	__u32 totlen;	/* record length */ +	__u32 offset;	/* ofset on jeb */ +	__u32 pino;		/* parent inode */ +	__u32 version;	/* dirent version */ +	__u32 ino; 		/* == zero for unlink */ +	uint8_t nsize;		/* dirent name size */ +	uint8_t type;		/* dirent type */ +	uint8_t name[0];	/* dirent name */ +} __attribute__((packed)); + +struct jffs2_sum_xattr_mem +{ +	union jffs2_sum_mem *next; +	__u16 nodetype; +	__u32 xid; +	__u32 version; +	__u32 offset; +	__u32 totlen; +} __attribute__((packed)); + +struct jffs2_sum_xref_mem +{ +	union jffs2_sum_mem *next; +	__u16 nodetype; +	__u32 offset; +} __attribute__((packed)); + +union jffs2_sum_mem +{ +	struct jffs2_sum_unknown_mem u; +	struct jffs2_sum_inode_mem i; +	struct jffs2_sum_dirent_mem d; +	struct jffs2_sum_xattr_mem x; +	struct jffs2_sum_xref_mem r; +}; + +/* Summary related information stored in superblock */ + +struct jffs2_summary +{ +	uint32_t sum_size;      /* collected summary information for nextblock */ +	uint32_t sum_num; +	uint32_t sum_padded; +	union jffs2_sum_mem *sum_list_head; +	union jffs2_sum_mem *sum_list_tail; + +	__u32 *sum_buf;	/* buffer for writing out summary */ +}; + +/* Summary marker is stored at the end of every sumarized erase block */ + +struct jffs2_sum_marker +{ +	__u32 offset;	/* offset of the summary node in the jeb */ +	__u32 magic; 	/* == JFFS2_SUM_MAGIC */ +}; + +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker)) + +#endif /* JFFS2_SUMMARY_H */ diff --git a/include/jffs2/jffs2.h b/include/jffs2/jffs2.h index d142cd1bc..ed96babf6 100644 --- a/include/jffs2/jffs2.h +++ b/include/jffs2/jffs2.h @@ -50,6 +50,9 @@  #define JFFS2_EMPTY_BITMASK 0xffff  #define JFFS2_DIRTY_BITMASK 0x0000 +/* Summary node MAGIC marker */ +#define JFFS2_SUM_MAGIC	0x02851885 +  /* We only allow a single char for length, and 0xFF is empty flash so     we don't want it confused with a real length. Hence max 254.  */ @@ -89,6 +92,7 @@  #define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)  #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)  #define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) +#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)  /* Maybe later... */  /*#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) */ @@ -166,9 +170,24 @@ struct jffs2_raw_inode  /*	__u8 data[dsize]; */  } __attribute__((packed)); +struct jffs2_raw_summary +{ +	__u16 magic; +	__u16 nodetype; 	/* = JFFS2_NODETYPE_SUMMARY */ +	__u32 totlen; +	__u32 hdr_crc; +	__u32 sum_num;	/* number of sum entries*/ +	__u32 cln_mkr;	/* clean marker size, 0 = no cleanmarker */ +	__u32 padded;	/* sum of the size of padding nodes */ +	__u32 sum_crc;	/* summary information crc */ +	__u32 node_crc; 	/* node crc */ +	__u32 sum[0]; 	/* inode summary info */ +}; +  union jffs2_node_union {  	struct jffs2_raw_inode i;  	struct jffs2_raw_dirent d; +	struct jffs2_raw_summary s;  	struct jffs2_unknown_node u;  } __attribute__((packed)); |