mtd/util nftl_format.c,1.22,1.23

gleixner at infradead.org gleixner at infradead.org
Fri Aug 5 06:37:00 EDT 2005


Update of /home/cvs/mtd/util
In directory phoenix.infradead.org:/tmp/cvs-serv12086

Modified Files:
	nftl_format.c 
Log Message:
[MTD utils] INFTL format support

Provide INFTL format support for nftl_format.

Initial patch from Greg Ungerer <greg at snapgear.com>
Reworked by Chris Bryden <cjb at neonbox.org>



Index: nftl_format.c
===================================================================
RCS file: /home/cvs/mtd/util/nftl_format.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- nftl_format.c	5 May 2004 15:19:57 -0000	1.22
+++ nftl_format.c	5 Aug 2005 10:36:57 -0000	1.23
@@ -1,5 +1,5 @@
 /* 
- * nftl_format.c: Creating a NFTL partition on an MTD device
+ * nftl_format.c: Creating a NFTL/INFTL partition on an MTD device
  *
  *
  * $Id$
@@ -38,6 +38,7 @@
 #include <asm/types.h>
 #include <mtd/mtd-user.h>
 #include <mtd/nftl-user.h>
+#include <mtd/inftl-user.h>
 
 #define swab16(x) \
         ((__u16)( \
@@ -68,7 +69,9 @@
 erase_info_t erase;
 int fd;
 struct NFTLMediaHeader *NFTLhdr;
+struct INFTLMediaHeader *INFTLhdr;
 
+static int do_oobcheck = 1;
 static int do_rwecheck = 1;
 
 static unsigned char check_block_1(unsigned long block)
@@ -152,9 +155,10 @@
 
 static unsigned char erase_block(unsigned long block)
 {
-	unsigned char status = check_block_1(block);
+	unsigned char status;
 	int ret;
 
+	status = (do_oobcheck) ? check_block_1(block) : ZONE_GOOD;
 	erase.start = block * meminfo.erasesize;
 	
 	if (status != ZONE_GOOD) {
@@ -183,33 +187,84 @@
 	return status;
 }
 
+static int checkbbt(void)
+{
+	unsigned char bbt[512];
+	unsigned char bits;
+	int i, addr;
+
+	if (pread(fd, bbt, 512, 0x800) < 0) {
+		printf("nftl_format: failed to read BBT, errno=%d\n", errno);
+		return (-1);
+	}
+
+
+	for (i = 0; (i < 512); i++) {
+		addr = i / 4;
+		bits = 0x3 << ((i % 4) * 2);
+		if ((bbt[addr] & bits) == 0) {
+			BadUnitTable[i] = ZONE_BAD_ORIGINAL;
+		}
+	}
+
+	return (0);
+}
+
+void usage(int rc)
+{
+	fprintf(stderr, "Usage: nftl_format [-ib] <mtddevice> [<start offset> [<size>]]\n");
+	exit(rc);
+}
+
 int main(int argc, char **argv)
 {
 	unsigned long startofs = 0, part_size = 0;
 	unsigned long ezones = 0, ezone = 0, bad_zones = 0;
 	unsigned char unit_factor = 0xFF;
-
 	long MediaUnit1 = -1, MediaUnit2 = -1;
+	long MediaUnitOff1 = 0, MediaUnitOff2 = 0;
 	unsigned char oobbuf[16];
 	struct mtd_oob_buf oob = {0, 16, oobbuf};
+	char *mtddevice, *nftl;
+	int c, do_inftl = 0, do_bbt = 0;
+
 
 	printf("$Id$\n");
 
-	if (argc < 2) {
-		fprintf(stderr, "Usage: %s <mtddevice> [<start offset> [<size>]]\n",
-			argv[0]);
-		return 1;
+	if (argc < 2)
+        	usage(1);
+
+	nftl = "NFTL";
+
+	while ((c = getopt(argc, argv, "?hib")) > 0) {
+		switch (c) {
+		case 'i':
+			nftl = "INFTL";
+			do_inftl = 1;
+			break;
+		case 'b':
+			do_bbt = 1;
+			break;
+		case 'h':
+		case '?':
+			usage(0);
+			break;
+		default:
+			usage(1);
+			break;
+		}
 	}
 
-	if (argc > 2) {
-		startofs = strtoul(argv[2], NULL, 0);
+	mtddevice = argv[optind++];
+	if (argc > optind) {
+		startofs = strtoul(argv[optind++], NULL, 0);
 	}
-	if (argc > 3) {
-		part_size = strtoul(argv[3], NULL, 0);
+	if (argc > optind) {
+		part_size = strtoul(argv[optind++], NULL, 0);
 	}
 
 	// Open and size the device
-	if ((fd = open(argv[1], O_RDWR)) < 0) {
+	if ((fd = open(mtddevice, O_RDWR)) < 0) {
 		perror("Open flash device");
 		return 1;
 	}
@@ -224,6 +279,7 @@
 	case 0x1000:
 	case 0x2000:
 	case 0x4000:
+	case 0x8000:
 		break;
 	default:
 		printf("Unrecognized Erase size, 0x%x - I'm confused\n", 
@@ -261,12 +317,21 @@
 		unit_factor = 0xFF;
 	}
 
+	/* If using device BBT then parse that now */
+	if (do_bbt) {
+		checkbbt();
+		do_oobcheck = 0;
+		do_rwecheck = 0;
+	}
+
 	/* Phase 1. Erasing and checking each erase zones in the NFTL partition.
 	   N.B. Erase Zones not used by the NFTL partition are untouched and marked ZONE_GOOD */
 	printf("Phase 1. Checking and erasing Erase Zones from 0x%08lx to 0x%08lx\n",
 	       startofs, startofs + part_size);
 	for (ezone = startofs / meminfo.erasesize;
 	     ezone < (ezones + startofs / meminfo.erasesize); ezone++) {
+		if (BadUnitTable[ezone] != ZONE_GOOD)
+			continue;
 		if ((BadUnitTable[ezone] = erase_block(ezone)) == ZONE_GOOD) {
 			if (MediaUnit1 == -1) {
 				MediaUnit1 = ezone;
@@ -281,21 +346,63 @@
 
 	/* N.B. from dump of M-System original chips, NumEraseUnits counts the 2 Erase Unit used
 	   by MediaHeader and the FirstPhysicalEUN starts from the MediaHeader */
-	NFTLhdr = (struct NFTLMediaHeader *) (writebuf[0]);
-	strcpy(NFTLhdr->DataOrgID, "ANAND");
-	NFTLhdr->NumEraseUnits = cpu_to_le16(part_size / meminfo.erasesize);
-	NFTLhdr->FirstPhysicalEUN = cpu_to_le16(MediaUnit1);
-	/* N.B. we reserve 2 more Erase Units for "folding" of Virtual Unit Chain */
-	NFTLhdr->FormattedSize = cpu_to_le32(part_size - ( (5+bad_zones) * meminfo.erasesize));
-	NFTLhdr->UnitSizeFactor = unit_factor;
+	if (do_inftl) {
+		unsigned long maxzones, pezstart, pezend, numvunits;
+
+		INFTLhdr = (struct INFTLMediaHeader *) (writebuf[0]);
+		strcpy(INFTLhdr->bootRecordID, "BNAND");
+		INFTLhdr->NoOfBootImageBlocks = cpu_to_le32(0);
+		INFTLhdr->NoOfBinaryPartitions = cpu_to_le32(0);
+		INFTLhdr->NoOfBDTLPartitions = cpu_to_le32(1);
+		INFTLhdr->BlockMultiplierBits = cpu_to_le32(0);
+		INFTLhdr->FormatFlags = cpu_to_le32(0);
+		INFTLhdr->OsakVersion = cpu_to_le32(OSAK_VERSION);
+		INFTLhdr->PercentUsed = cpu_to_le32(PERCENTUSED);
+		/*
+		 * Calculate number of virtual units we will have to work
+		 * with. I am calculating out the known bad units here, not
+		 * sure if that is what M-Systems do...
+		 */
+		MediaUnit2 = MediaUnit1;
+		MediaUnitOff2 = 4096;
+		maxzones = meminfo.size / meminfo.erasesize;
+		pezstart = startofs / meminfo.erasesize + 1;
+		pezend = startofs / meminfo.erasesize + ezones - 1;
+		numvunits = (ezones - 2) * PERCENTUSED / 100;
+		for (ezone = pezstart; ezone < maxzones; ezone++) {
+			if (BadUnitTable[ezone] != ZONE_GOOD) {
+				if (numvunits > 1)
+					numvunits--;
+			}
+		}
+
+		INFTLhdr->Partitions[0].virtualUnits = cpu_to_le32(numvunits);
+		INFTLhdr->Partitions[0].firstUnit = cpu_to_le32(pezstart);
+		INFTLhdr->Partitions[0].lastUnit = cpu_to_le32(pezend);
+		INFTLhdr->Partitions[0].flags = cpu_to_le32(INFTL_BDTL);
+		INFTLhdr->Partitions[0].spareUnits = cpu_to_le32(0);
+		INFTLhdr->Partitions[0].Reserved0 = INFTLhdr->Partitions[0].firstUnit;
+		INFTLhdr->Partitions[0].Reserved1 = cpu_to_le32(0);
+		
+	} else {
+	
+		NFTLhdr = (struct NFTLMediaHeader *) (writebuf[0]);
+		strcpy(NFTLhdr->DataOrgID, "ANAND");
+		NFTLhdr->NumEraseUnits = cpu_to_le16(part_size / meminfo.erasesize);
+		NFTLhdr->FirstPhysicalEUN = cpu_to_le16(MediaUnit1);
+		/* N.B. we reserve 2 more Erase Units for "folding" of Virtual Unit Chain */
+		NFTLhdr->FormattedSize = cpu_to_le32(part_size - ( (5+bad_zones) * meminfo.erasesize));
+		NFTLhdr->UnitSizeFactor = unit_factor;
+	}
 
 	/* Phase 2. Writing NFTL Media Headers and Bad Unit Table */
-	printf("Phase 2.a Writing NFTL Media Header and Bad Unit Table\n");
-	pwrite(fd, writebuf[0], 512, MediaUnit1 * meminfo.erasesize);
+	printf("Phase 2.a Writing %s Media Header and Bad Unit Table\n", nftl);
+	pwrite(fd, writebuf[0], 512, MediaUnit1 * meminfo.erasesize + MediaUnitOff1);
 	for (ezone = 0; ezone < (meminfo.size / meminfo.erasesize); ezone += 512) {
 		pwrite(fd, BadUnitTable + ezone, 512,
-		       (MediaUnit1 * meminfo.erasesize) + 512 * (1 + ezone / 512));
+			(MediaUnit1 * meminfo.erasesize) + 512 * (1 + ezone / 512));
 	}
+
 #if 0
 	printf("  MediaHeader contents:\n");
 	printf("    NumEraseUnits: %d\n", le16_to_cpu(NFTLhdr->NumEraseUnits));
@@ -303,17 +410,17 @@
 	printf("    FormattedSize: %d (%d sectors)\n", le32_to_cpu(NFTLhdr->FormattedSize),
 	       le32_to_cpu(NFTLhdr->FormattedSize)/512);
 #endif
-	printf("Phase 2.b Writing Spare NFTL Media Header and Spare Bad Unit Table\n");
-	pwrite(fd, writebuf[0], 512, MediaUnit2 * meminfo.erasesize);
+	printf("Phase 2.b Writing Spare %s Media Header and Spare Bad Unit Table\n", nftl);
+	pwrite(fd, writebuf[0], 512, MediaUnit2 * meminfo.erasesize + MediaUnitOff2);
 	for (ezone = 0; ezone < (meminfo.size / meminfo.erasesize); ezone += 512) {
 		pwrite(fd, BadUnitTable + ezone, 512,
-		       (MediaUnit2 * meminfo.erasesize) + 512 * (1 + ezone / 512));
+			(MediaUnit2 * meminfo.erasesize + MediaUnitOff2) + 512 * (1 + ezone / 512));
 	}
 
 	/* UCI #1 for newly erased Erase Unit */
 	memset(oobbuf, 0xff, 16);
 	oobbuf[11] = oobbuf[10] = oobbuf[9] = 0;
-	oobbuf[8]  = 0x03;
+	oobbuf[8]  = (do_inftl) ? 0x00 : 0x03;
 	oobbuf[12] = oobbuf[14] = 0x69;
 	oobbuf[13] = oobbuf[15] = 0x3c;
 
@@ -322,12 +429,11 @@
 	   but their Block Status is BLOCK_USED (0x5555) in their Block Control Information */
 	/* Phase 3. Writing Unit Control Information for each Erase Unit */
 	printf("Phase 3. Writing Unit Control Information to each Erase Unit\n");
-	for (ezone = cpu_to_le16(NFTLhdr->FirstPhysicalEUN);
-	     ezone < (ezones + startofs / meminfo.erasesize); ezone++) {
+	for (ezone = MediaUnit1; ezone < (ezones + startofs / meminfo.erasesize); ezone++) {
 		/* write UCI #1 to each Erase Unit */
 		if (BadUnitTable[ezone] != ZONE_GOOD)
 			continue;
-		oob.start = (ezone * meminfo.erasesize) + 512;
+		oob.start = (ezone * meminfo.erasesize) + 512 + (do_inftl * 512);
 		if (ioctl(fd, MEMWRITEOOB, &oob))
 			printf("MEMWRITEOOB at %lx: %s\n", (unsigned long)oob.start, strerror(errno));
 	}





More information about the linux-mtd-cvs mailing list