mtd/util flash_eraseall.c, 1.22, 1.23 jffs2dump.c, 1.10,
1.11 mkfs.jffs2.c, 1.45, 1.46
Forrest Zhao
forrest.zhao at intel.com
Fri Nov 4 03:06:31 EST 2005
Update of /home/cvs/mtd/util
In directory phoenix.infradead.org:/tmp/cvs-serv31513/util
Modified Files:
flash_eraseall.c jffs2dump.c mkfs.jffs2.c
Log Message:
Clean marker is gone! This patch introduce Erase Block Header(EBH) to JFFS2. EBH resides at the beginning of each eraseb block and carries the meta data for that erase block. If you want to add new per-erase-block information, you may use EBH to make extension. Now we record the erase count of each erase block in EBH.
Also this patch modified the user-space utilities to make them accormodate to EBH.
Index: flash_eraseall.c
===================================================================
RCS file: /home/cvs/mtd/util/flash_eraseall.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- flash_eraseall.c 17 Feb 2005 14:55:06 -0000 1.22
+++ flash_eraseall.c 4 Nov 2005 08:06:27 -0000 1.23
@@ -53,15 +53,16 @@
static void process_options (int argc, char *argv[]);
static void display_help (void);
static void display_version (void);
-static struct jffs2_unknown_node cleanmarker;
+static struct jffs2_raw_ebh ebh;
int target_endian = __BYTE_ORDER;
int main (int argc, char *argv[])
{
mtd_info_t meminfo;
- int fd, clmpos = 0, clmlen = 8;
+ int fd, ebhpos = 0, ebhlen = 0;
erase_info_t erase;
int isNAND, bbtest = 1;
+ uint32_t pages_per_eraseblock, available_oob_space;
process_options(argc, argv);
@@ -81,11 +82,19 @@
isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0;
if (jffs2) {
- cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
- cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
- if (!isNAND)
- cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
- else {
+ ebh.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
+ ebh.nodetype = cpu_to_je16 (JFFS2_NODETYPE_ERASEBLOCK_HEADER);
+ ebh.totlen = cpu_to_je32(sizeof(struct jffs2_raw_ebh));
+ ebh.hdr_crc = cpu_to_je32 (crc32 (0, &ebh, sizeof (struct jffs2_unknown_node) - 4));
+ ebh.reserved = 0;
+ ebh.compat_fset = JFFS2_EBH_COMPAT_FSET;
+ ebh.incompat_fset = JFFS2_EBH_INCOMPAT_FSET;
+ ebh.rocompat_fset = JFFS2_EBH_ROCOMPAT_FSET;
+ ebh.erase_count = cpu_to_je32(0);
+ ebh.node_crc = cpu_to_je32(crc32(0, (unsigned char *)&ebh + sizeof(struct jffs2_unknown_node) + 4,
+ sizeof(struct jffs2_raw_ebh) - sizeof(struct jffs2_unknown_node) - 4));
+
+ if (isNAND) {
struct nand_oobinfo oobinfo;
if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
@@ -100,30 +109,32 @@
fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
exit(1);
}
- clmpos = oobinfo.oobfree[0][0];
- clmlen = oobinfo.oobfree[0][1];
- if (clmlen > 8)
- clmlen = 8;
+ ebhpos = oobinfo.oobfree[0][0];
+ ebhlen = oobinfo.oobfree[0][1];
} else {
/* Legacy mode */
switch (meminfo.oobsize) {
case 8:
- clmpos = 6;
- clmlen = 2;
+ ebhpos = 6;
+ ebhlen = 2;
break;
case 16:
- clmpos = 8;
- clmlen = 8;
+ ebhpos = 8;
+ ebhlen = 8;
break;
case 64:
- clmpos = 16;
- clmlen = 8;
+ ebhpos = 16;
+ ebhlen = 8;
break;
}
}
- cleanmarker.totlen = cpu_to_je32(8);
+ pages_per_eraseblock = meminfo.erasesize/meminfo.oobblock;
+ available_oob_space = ebhlen * pages_per_eraseblock;
+ if (available_oob_space < sizeof(struct jffs2_raw_ebh)) {
+ fprintf(stderr, "The OOB area(%d) is not big enough to hold eraseblock_header(%d)", available_oob_space, sizeof(struct jffs2_raw_ebh));
+ exit(1);
+ }
}
- cleanmarker.hdr_crc = cpu_to_je32 (crc32 (0, &cleanmarker, sizeof (struct jffs2_unknown_node) - 4));
}
for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) {
@@ -169,11 +180,20 @@
/* write cleanmarker */
if (isNAND) {
struct mtd_oob_buf oob;
- oob.ptr = (unsigned char *) &cleanmarker;
- oob.start = erase.start + clmpos;
- oob.length = clmlen;
- if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
- fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
+ uint32_t i = 0, written = 0;
+
+ while (written < sizeof(struct jffs2_raw_ebh)) {
+ oob.ptr = (unsigned char *) &ebh + written;
+ oob.start = erase.start + meminfo.oobblock*i + ebhpos;
+ oob.length = (sizeof(struct jffs2_raw_ebh) - written) < ebhlen ? (sizeof(struct jffs2_raw_ebh) - written) : ebhlen;
+ if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
+ fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
+ break;
+ }
+ i++;
+ written += oob.length;
+ }
+ if (written < sizeof(struct jffs2_raw_ebh)) {
continue;
}
} else {
@@ -181,7 +201,7 @@
fprintf(stderr, "\n%s: %s: MTD lseek failure: %s\n", exe_name, mtd_device, strerror(errno));
continue;
}
- if (write (fd , &cleanmarker, sizeof (cleanmarker)) != sizeof (cleanmarker)) {
+ if (write (fd , &ebh, sizeof (ebh)) != sizeof (ebh)) {
fprintf(stderr, "\n%s: %s: MTD write failure: %s\n", exe_name, mtd_device, strerror(errno));
continue;
}
Index: jffs2dump.c
===================================================================
RCS file: /home/cvs/mtd/util/jffs2dump.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- jffs2dump.c 26 Sep 2005 11:49:39 -0000 1.10
+++ jffs2dump.c 4 Nov 2005 08:06:27 -0000 1.11
@@ -379,6 +379,22 @@
break;
}
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER:
+ printf ("%8s EBH node at 0x%08x, totlen 0x%08x, compat_fset 0x%02x, incompat_fset 0x%02x, rocompat_fset 0x%02x, erase_count 0x%08x\n",
+ obsolete ? "Obsolete" : "", p - data, je32_to_cpu (node->eh.totlen), node->eh.compat_fset,
+ node->eh.incompat_fset, node->eh.rocompat_fset, je32_to_cpu (node->eh.erase_count));
+
+ crc = crc32(0, p + sizeof(struct jffs2_unknown_node) + 4, je32_to_cpu(node->eh.totlen) - sizeof(struct jffs2_unknown_node) - 4);
+ if (crc != je32_to_cpu(node->eh.node_crc)) {
+ printf ("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->eh.node_crc), crc);
+ p += PAD(je32_to_cpu (node->eh.totlen));
+ dirty += PAD(je32_to_cpu (node->eh.totlen));;
+ continue;
+ }
+
+ p += PAD(je32_to_cpu (node->eh.totlen));
+ break;
+
case JFFS2_NODETYPE_CLEANMARKER:
if (verbose) {
printf ("%8s Cleanmarker at 0x%08x, totlen 0x%08x\n",
@@ -615,6 +631,23 @@
break;
}
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER:
+ newnode.eh.magic = cnv_e16 (node->eh.magic);
+ newnode.eh.nodetype = cnv_e16 (node->eh.nodetype);
+ newnode.eh.totlen = cnv_e32 (node->eh.totlen);
+ newnode.eh.hdr_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
+ newnode.eh.reserved = node->eh.reserved;
+ newnode.eh.compat_fset = node->eh.compat_fset;
+ newnode.eh.incompat_fset = node->eh.incompat_fset;
+ newnode.eh.rocompat_fset = node->eh.rocompat_fset;
+ newnode.eh.erase_count = cnv_e32 (node->eh.erase_count);
+ newnode.eh.node_crc = cpu_to_e32 (crc32 (0, (unsigned char *)&newnode + sizeof(struct jffs2_unknown_node) + 4,
+ je32_to_cpu(node->eh.totlen) - sizeof(struct jffs2_unknown_node) + 4));
+ write(fd, &newnode, sizeof(struct jffs2_raw_ebh));
+ write(fd, p + sizeof(struct jffs2_raw_ebh), PAD(je32_to_cpu(node->eh.totlen) - sizeof(struct jffs2_raw_ebh)));
+ p += PAD(je32_to_cpu (node->eh.totlen));
+ break;
+
case 0xffff:
write (fd, p, 4);
p += 4;
Index: mkfs.jffs2.c
===================================================================
RCS file: /home/cvs/mtd/util/mkfs.jffs2.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- mkfs.jffs2.c 14 Apr 2005 09:13:34 -0000 1.45
+++ mkfs.jffs2.c 4 Nov 2005 08:06:27 -0000 1.46
@@ -659,9 +659,9 @@
static int out_ofs = 0;
static int erase_block_size = 65536;
static int pad_fs_size = 0;
-static int add_cleanmarkers = 1;
-static struct jffs2_unknown_node cleanmarker;
-static int cleanmarker_size = sizeof(cleanmarker);
+static int add_ebhs = 1;
+static struct jffs2_raw_ebh ebh;
+static int ebh_size = sizeof(ebh);
static unsigned char ffbuf[16] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff
@@ -722,20 +722,20 @@
static inline void pad_block_if_less_than(int req)
{
- if (add_cleanmarkers) {
+ if (add_ebhs) {
if ((out_ofs % erase_block_size) == 0) {
- full_write(out_fd, &cleanmarker, sizeof(cleanmarker));
- pad(cleanmarker_size - sizeof(cleanmarker));
+ full_write(out_fd, &ebh, sizeof(ebh));
+ pad(ebh_size - sizeof(ebh));
padword();
}
}
if ((out_ofs % erase_block_size) + req > erase_block_size) {
padblock();
}
- if (add_cleanmarkers) {
+ if (add_ebhs) {
if ((out_ofs % erase_block_size) == 0) {
- full_write(out_fd, &cleanmarker, sizeof(cleanmarker));
- pad(cleanmarker_size - sizeof(cleanmarker));
+ full_write(out_fd, &ebh, sizeof(ebh));
+ pad(ebh_size - sizeof(ebh));
padword();
}
}
@@ -1112,10 +1112,17 @@
static void create_target_filesystem(struct filesystem_entry *root)
{
- cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
- cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
- cleanmarker.totlen = cpu_to_je32(cleanmarker_size);
- cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, sizeof(struct jffs2_unknown_node)-4));
+ ebh.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ ebh.nodetype = cpu_to_je16(JFFS2_NODETYPE_ERASEBLOCK_HEADER);
+ ebh.totlen = cpu_to_je32(sizeof(ebh));
+ ebh.hdr_crc = cpu_to_je32(crc32(0, &ebh, sizeof(struct jffs2_unknown_node)-4));
+ ebh.reserved = 0;
+ ebh.compat_fset = JFFS2_EBH_COMPAT_FSET;
+ ebh.incompat_fset = JFFS2_EBH_INCOMPAT_FSET;
+ ebh.rocompat_fset = JFFS2_EBH_ROCOMPAT_FSET;
+ ebh.erase_count = cpu_to_je32(0);
+ ebh.node_crc = cpu_to_je32(crc32(0, (unsigned char *)&ebh + sizeof(struct jffs2_unknown_node) + 4,
+ sizeof(struct jffs2_raw_ebh) - sizeof(struct jffs2_unknown_node) - 4));
if (ino == 0)
ino = 1;
@@ -1126,11 +1133,11 @@
if (pad_fs_size == -1) {
padblock();
} else {
- if (pad_fs_size && add_cleanmarkers){
+ if (pad_fs_size && add_ebhs){
padblock();
while (out_ofs < pad_fs_size) {
- full_write(out_fd, &cleanmarker, sizeof(cleanmarker));
- pad(cleanmarker_size - sizeof(cleanmarker));
+ full_write(out_fd, &ebh, sizeof(ebh));
+ pad(ebh_size - sizeof(ebh));
padblock();
}
} else {
@@ -1153,8 +1160,8 @@
{"version", 0, NULL, 'V'},
{"big-endian", 0, NULL, 'b'},
{"little-endian", 0, NULL, 'l'},
- {"no-cleanmarkers", 0, NULL, 'n'},
- {"cleanmarker", 1, NULL, 'c'},
+ {"no-eraseblock-headers", 0, NULL, 'n'},
+ {"eraseblock-header", 1, NULL, 'c'},
{"squash", 0, NULL, 'q'},
{"squash-uids", 0, NULL, 'U'},
{"squash-perms", 0, NULL, 'P'},
@@ -1178,7 +1185,7 @@
" -r, -d, --root=DIR Build file system from directory DIR (default: cwd)\n"
" -s, --pagesize=SIZE Use page size (max data node size) SIZE (default: 4KiB)\n"
" -e, --eraseblock=SIZE Use erase block size SIZE (default: 64KiB)\n"
- " -c, --cleanmarker=SIZE Size of cleanmarker (default 12)\n"
+ " -c, --eraseblock-header=SIZE Size of eraseblock header (default 28)\n"
" -m, --compr-mode=MODE Select compression mode (default: priortiry)\n"
" -x, --disable-compressor=COMPRESSOR_NAME\n"
" Disable a compressor\n"
@@ -1188,7 +1195,7 @@
" Set the priority of a compressor\n"
" -L, --list-compressors Show the list of the avaiable compressors\n"
" -t, --test-compression Call decompress and compare with the original (for test)\n"
- " -n, --no-cleanmarkers Don't add a cleanmarker to every eraseblock\n"
+ " -n, --no-eraseblock-headers Don't add a eraseblock header to every eraseblock\n"
" -o, --output=FILE Output to FILE (default: stdout)\n"
" -l, --little-endian Create a little-endian filesystem\n"
" -b, --big-endian Create a big-endian filesystem\n"
@@ -1291,6 +1298,15 @@
p += PAD(je32_to_cpu (node->u.totlen));
break;
+
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER:
+ if (verbose) {
+ printf ("%8s Eraseblock header at 0x%08x, totlen 0x%08\n",
+ obsolete ? "Obsolete" : "",
+ p - file_buffer, je32_to_cpu (node->eh.totlen));
+ }
+ p += PAD(je32_to_cpu (node->eh.totlen));
+ break;
case JFFS2_NODETYPE_PADDING:
if (verbose) {
@@ -1462,15 +1478,15 @@
pad_fs_size = -1;
break;
case 'n':
- add_cleanmarkers = 0;
+ add_ebhs = 0;
break;
case 'c':
- cleanmarker_size = strtol(optarg, NULL, 0);
- if (cleanmarker_size < sizeof(cleanmarker)) {
- error_msg_and_die("cleanmarker size must be >= 12");
+ ebh_size = strtol(optarg, NULL, 0);
+ if (ebh_size < sizeof(ebh)) {
+ error_msg_and_die("ebh size must be >= 28");
}
- if (cleanmarker_size >= erase_block_size) {
- error_msg_and_die("cleanmarker size must be < eraseblock size");
+ if (ebh_size >= erase_block_size) {
+ error_msg_and_die("ebh size must be < eraseblock size");
}
break;
case 'm':
More information about the linux-mtd-cvs
mailing list