public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot-Users] [PATCH]env_nand.c Added bad block management for environment variables
@ 2008-05-27 14:01 Stuart Wood
  2008-05-28 17:57 ` Scott Wood
  0 siblings, 1 reply; 9+ messages in thread
From: Stuart Wood @ 2008-05-27 14:01 UTC (permalink / raw)
  To: u-boot

Hi All, This is my first attempt at submitting a change so please be
patient and kind.
This change allows for the environment variables to be stored in a
rand of nand flash.
If the first block is bad then the environment is stored in the next
one, and so on.
It introduces CFG_ENV_RANGE to define the size of the area that way contain the
environment data. This will allow the environment to be loaded over an
area with bad
blocks from the factory without a problem.

diff --git a/common/env_nand.c b/common/env_nand.c
index 49742f5..29aafa2 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -155,27 +155,53 @@ int env_init(void)
 int saveenv(void)
 {
 	size_t total;
+	size_t offset;
 	int ret = 0;

 	env_ptr->flags++;
 	total = CFG_ENV_SIZE;

+	if (CFG_ENV_RANGE < CFG_ENV_SIZE)
+		return 1;
 	if(gd->env_valid == 1) {
-		puts ("Erasing redundant Nand...");
-		if (nand_erase(&nand_info[0],
-			       CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE))
+		puts ("Erasing redundant Nand...\n");
+		for (offset = CFG_ENV_OFFSET_REDUND; offset <
+				CFG_ENV_OFFSET_REDUND + CFG_ENV_RANGE; )
+		{
+			if (nand_erase(&nand_info[0],
+					offset, CFG_ENV_SIZE)) {
+				offset += CFG_ENV_SIZE;
+			} else {
+				break;
+			}
+		}
+		if (offset >= CFG_ENV_OFFSET_REDUND + CFG_ENV_RANGE) {
+			puts ("Redundant Nand area is completely bad!\n");
+			gd->env_valid = 2;
 			return 1;
+		}
 		puts ("Writing to redundant Nand... ");
-		ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total,
+		ret = nand_write(&nand_info[0], offset, &total,
 				 (u_char*) env_ptr);
 	} else {
-		puts ("Erasing Nand...");
-		if (nand_erase(&nand_info[0],
-			       CFG_ENV_OFFSET, CFG_ENV_SIZE))
+		puts ("Erasing Nand...\n");
+		for (offset = CFG_ENV_OFFSET; offset <
+				CFG_ENV_OFFSET + CFG_ENV_RANGE; )
+		{
+			if (nand_erase(&nand_info[0],
+					offset, CFG_ENV_SIZE)) {
+				offset += CFG_ENV_SIZE;
+			} else {
+				break;
+			}
+		}
+		if (offset >= CFG_ENV_OFFSET + CFG_ENV_RANGE) {
+			puts ("Nand area is completely bad!\n");
+			gd->env_valid = 1;
 			return 1;
-
+		}
 		puts ("Writing to Nand... ");
-		ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total,
+		ret = nand_write(&nand_info[0], offset, &total,
 				 (u_char*) env_ptr);
 	}
 	if (ret || total != CFG_ENV_SIZE)
@@ -189,15 +215,30 @@ int saveenv(void)
 int saveenv(void)
 {
 	size_t total;
+	size_t offset;
 	int ret = 0;

-	puts ("Erasing Nand...");
-	if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE))
+	if (CFG_ENV_RANGE < CFG_ENV_SIZE)
 		return 1;
+	puts ("Erasing Nand...\n");
+	for (offset = CFG_ENV_OFFSET; offset <
+			CFG_ENV_OFFSET + CFG_ENV_RANGE; )
+	{
+		if (nand_erase(&nand_info[0],
+				offset, CFG_ENV_SIZE)) {
+			offset += CFG_ENV_SIZE;
+		} else {
+			break;
+		}
+	}
+	if (offset >= CFG_ENV_OFFSET + CFG_ENV_RANGE) {
+		puts ("Nand area is completely bad!\n");
+		return 1;
+	}

 	puts ("Writing to Nand... ");
 	total = CFG_ENV_SIZE;
-	ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
+	ret = nand_write(&nand_info[0], offset, &total, (u_char*)env_ptr);
 	if (ret || total != CFG_ENV_SIZE)
 		return 1;

@@ -212,6 +253,7 @@ void env_relocate_spec (void)
 {
 #if !defined(ENV_IS_EMBEDDED)
 	size_t total;
+	size_t offset;
 	int crc1_ok = 0, crc2_ok = 0;
 	env_t *tmp_env1, *tmp_env2;

@@ -220,10 +262,25 @@ void env_relocate_spec (void)
 	tmp_env1 = (env_t *) malloc(CFG_ENV_SIZE);
 	tmp_env2 = (env_t *) malloc(CFG_ENV_SIZE);

-	nand_read(&nand_info[0], CFG_ENV_OFFSET, &total,
-		  (u_char*) tmp_env1);
-	nand_read(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total,
-		  (u_char*) tmp_env2);
+	for (offset = CFG_ENV_OFFSET; offset < CFG_ENV_OFFSET + CFG_ENV_RANGE ; ) {
+		if (nand_block_isbad (&nand_info[0], offset)) {
+			offset += CFG_ENV_SIZE;
+		} else {
+			nand_read(&nand_info[0], offset, &total,
+				(u_char*) tmp_env1);
+			break;
+		}
+	}
+	for (offset = CFG_ENV_OFFSET_REDUND; offset <
+			CFG_ENV_OFFSET_REDUND + CFG_ENV_RANGE ; ) {
+		if (nand_block_isbad (&nand_info[0], offset)) {
+			offset += CFG_ENV_SIZE;
+		} else {
+			nand_read(&nand_info[0], offset, &total,
+				(u_char*) tmp_env2);
+			break;
+		}
+	}

 	crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
 	crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);


--
Stuart Wood

Lab X Technologies, LLC
176 Anderson Ave.
Suite 302
Rochester, NY 14607
Phone: (585) 271-7790 x207
Fax: (585) 473.4707

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-06-02 20:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-27 14:01 [U-Boot-Users] [PATCH]env_nand.c Added bad block management for environment variables Stuart Wood
2008-05-28 17:57 ` Scott Wood
2008-05-29 17:14   ` Stuart Wood
2008-05-29 17:30     ` Scott Wood
2008-05-29 17:32       ` Scott Wood
2008-05-30 15:14         ` Stuart Wood
2008-05-30 17:28           ` Scott Wood
2008-05-30 20:05             ` Stuart Wood
2008-06-02 20:03               ` Scott Wood

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox