[PATCH] mtd-utils: flash_erase: Skip bad blocks a-la flash_eraseall

Alex Landau landau.alex at gmail.com
Thu Jul 26 10:47:41 EDT 2007


flash_erase used to choke on the first bad block. This patch copies
the logic used to skip bad blocks in flash_eraseall to flash_erase.

Signed-off-by: Alex Landau <landau.alex at gmail.com>
---
 flash_erase.c |  130 ++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 95 insertions(+), 35 deletions(-)
---
diff --git a/flash_erase.c b/flash_erase.c
index fdf9918..a153cbf 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -3,6 +3,7 @@
  */

 #include <unistd.h>
+#include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <fcntl.h>
@@ -14,8 +15,17 @@

 int region_erase(int Fd, int start, int count, int unlock, int regcount)
 {
-	int i, j;
+	int i, j, isNAND;
 	region_info_t * reginfo;
+	mtd_info_t meminfo;
+	int bbtest = 1;
+
+	if (ioctl(Fd,MEMGETINFO,&meminfo) < 0) {
+		perror("Unable to get MTD device infos");
+		close(Fd);
+		return 8;
+	}
+	isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0;

 	reginfo = calloc(regcount, sizeof(region_info_t));

@@ -52,30 +62,55 @@

 	for(j = 0; (j < count)&&(i < regcount); j++)
 	{
+		int skip = 0;
 		erase_info_t erase;
 		region_info_t * r = &(reginfo[i]);

 		erase.start = start;
 		erase.length = r->erasesize;

-		if(unlock != 0)
-		{ //Unlock the sector first.
-			if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
+		if (bbtest) {
+			loff_t offset = erase.start;
+			int ret = ioctl(Fd, MEMGETBADBLOCK, &offset);
+			if (ret > 0) {
+				printf ("\nSkipping bad block at 0x%08x\n", erase.start);
+				skip = 1;
+			} else if (ret < 0) {
+				if (errno == EOPNOTSUPP) {
+					bbtest = 0;
+					if (isNAND) {
+						perror("\nBad block check not available");
+						close(Fd);
+						return 8;
+					}
+				} else {
+					perror("\nMTD get bad block failed");
+					close(Fd);
+					return 8;
+				}
+			}
+		}
+
+		if (!skip) {
+			if(unlock != 0)
+			{ //Unlock the sector first.
+				if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
+				{
+					perror("\nMTD Unlock failure");
+					close(Fd);
+					return 8;
+				}
+			}
+			printf("\rPerforming Flash Erase of length %u at offset 0x%x",
+					erase.length, erase.start);
+			fflush(stdout);
+			if(ioctl(Fd, MEMERASE, &erase) != 0)
 			{
-				perror("\nMTD Unlock failure");
+				perror("\nMTD Erase failure");
 				close(Fd);
 				return 8;
 			}
 		}
-		printf("\rPerforming Flash Erase of length %u at offset 0x%x",
-				erase.length, erase.start);
-		fflush(stdout);
-		if(ioctl(Fd, MEMERASE, &erase) != 0)
-		{
-			perror("\nMTD Erase failure");
-			close(Fd);
-			return 8;
-		}


 		start += erase.length;
@@ -94,42 +129,67 @@
 int non_region_erase(int Fd, int start, int count, int unlock)
 {
 	mtd_info_t meminfo;
+	erase_info_t erase;
+	int isNAND;
+	int bbtest = 1;

-	if (ioctl(Fd,MEMGETINFO,&meminfo) == 0)
-	{
-		erase_info_t erase;
-
-		erase.start = start;
+	if (ioctl(Fd,MEMGETINFO,&meminfo) < 0) {
+		perror("Unable to get MTD device infos");
+		close(Fd);
+		return 8;
+	}
+	isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0;

-		erase.length = meminfo.erasesize;
+	erase.start = start;
+	erase.length = meminfo.erasesize;

-		for (; count > 0; count--) {
-			printf("\rPerforming Flash Erase of length %u at offset 0x%x",
-					erase.length, erase.start);
-			fflush(stdout);
+	for (; count > 0; count--, erase.start += meminfo.erasesize) {
+		printf("\rPerforming Flash Erase of length %u at offset 0x%x",
+				erase.length, erase.start);
+		fflush(stdout);

-			if(unlock != 0)
-			{
-				//Unlock the sector first.
-				printf("\rPerforming Flash unlock at offset 0x%x",erase.start);
-				if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
-				{
-					perror("\nMTD Unlock failure");
+		if (bbtest) {
+			loff_t offset = erase.start;
+			int ret = ioctl(Fd, MEMGETBADBLOCK, &offset);
+			if (ret > 0) {
+				printf ("\nSkipping bad block at 0x%08x\n", erase.start);
+				continue;
+			} else if (ret < 0) {
+				if (errno == EOPNOTSUPP) {
+					bbtest = 0;
+					if (isNAND) {
+						perror("\nBad block check not available");
+						close(Fd);
+						return 8;
+					}
+				} else {
+					perror("\nMTD get bad block failed");
 					close(Fd);
 					return 8;
 				}
 			}
+		}

-			if (ioctl(Fd,MEMERASE,&erase) != 0)
+		if(unlock != 0)
+		{
+			//Unlock the sector first.
+			printf("\rPerforming Flash unlock at offset 0x%x",erase.start);
+			if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
 			{
-				perror("\nMTD Erase failure");
+				perror("\nMTD Unlock failure");
 				close(Fd);
 				return 8;
 			}
-			erase.start += meminfo.erasesize;
 		}
-		printf(" done\n");
+
+		if (ioctl(Fd,MEMERASE,&erase) != 0)
+		{
+			perror("\nMTD Erase failure");
+			close(Fd);
+			return 8;
+		}
 	}
+	printf(" done\n");
 	return 0;
 }



More information about the linux-mtd mailing list