[U-Boot] [PATCH 2/3] [v4] nand_util: drop trailing all-0xff pages if requested

Ben Gardiner bengardiner at nanometrics.ca
Tue Jun 14 22:35:06 CEST 2011


Add a flag to nand_read_skip_bad() such that if true, any trailing
pages in an eraseblock whose contents are entirely 0xff will be
dropped.

The implementation is via a new drop_ffs() function which is
based on the function of the same name from the ubiformat
utility by Artem Bityutskiy.

This is as-per the reccomendations of the UBI FAQ [1]

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
CC: Artem Bityutskiy <dedekind1 at gmail.com>
Acked-by: Detlev Zundel <dzu at denx.de>
CC: Scott Wood <scottwood at freescale.com>

[1] http://www.linux-mtd.infradead.org/doc/ubi.html#L_flasher_algo

---

Scott,

I did not add your Acked-by because to handle the possible unaligned
input length I opted to return min() instead of dropping the alignment
fixup entire as had been agreed upon in correspondence. I found in
testing that removing the alignment resulted in corruption of the NAND.

This behaviour was found to fix both UBI and JFFS2 images written to
cleanly erased NAND partitions on da850evm.

Changes since v3:
 * rebased onto nand-flash/next
 * remove uneccessary cast (Scott Wood)
 * added Detlev's Acked-by
 * prevent access past end of buffer using min() (Scott Wood)
Changes since v2:
 * moved the copyright header addition of nand_util to this patch from
   patch 'cmd_nand: add nand write.trimffs command'
 * Did not add Detlev's Acked-by because of movement of copyright header
Changes since v1:
 * rebased to HEAD of git://git.denx.de/u-boot-nand-flash.git : ff7b4a0
   ("env_nand: zero-initialize variable nand_erase_options")
 * wrap the new functionality in a CONFIG_CMD_NAND_TRIMFFS ifdef to
   reduce size impact of new feature

---
 drivers/mtd/nand/nand_util.c |   40 +++++++++++++++++++++++++++++++++++++---
 include/nand.h               |    1 +
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index e4ef858..81bf366 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -11,6 +11,9 @@
  *		nandwrite.c by Steven J. Hill (sjhill at realitydiluted.com)
  *			       and Thomas Gleixner (tglx at linutronix.de)
  *
+ * Copyright (C) 2008 Nokia Corporation: drop_ffs() function by
+ * Artem Bityutskiy <dedekind1 at gmail.com> from mtd-utils
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -436,6 +439,29 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
 	return ret;
 }
 
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
+			const size_t *len)
+{
+	size_t i, l = *len;
+
+	for (i = l - 1; i >= 0; i--)
+		if (buf[i] != 0xFF)
+			break;
+
+	/* The resulting length must be aligned to the minimum flash I/O size */
+	l = i + 1;
+	l = (l + nand->writesize - 1) / nand->writesize;
+	l *=  nand->writesize;
+
+	/*
+	 * since the input length may be unaligned, prevent access past the end
+	 * of the buffer
+	 */
+	return min(l, *len);
+}
+#endif
+
 /**
  * nand_write_skip_bad:
  *
@@ -502,7 +528,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		return -EINVAL;
 	}
 
-	if (!need_skip) {
+	if (!need_skip && !(flags & WITH_DROP_FFS)) {
 		rval = nand_write (nand, offset, length, buffer);
 		if (rval == 0)
 			return 0;
@@ -515,7 +541,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 
 	while (left_to_write > 0) {
 		size_t block_offset = offset & (nand->erasesize - 1);
-		size_t write_size;
+		size_t write_size, truncated_write_size;
 
 		WATCHDOG_RESET ();
 
@@ -561,7 +587,15 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		else
 #endif
 		{
-			rval = nand_write (nand, offset, &write_size, p_buffer);
+			truncated_write_size = write_size;
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+			if (flags & WITH_DROP_FFS)
+				truncated_write_size = drop_ffs(nand, p_buffer,
+						&write_size);
+#endif
+
+			rval = nand_write(nand, offset, &truncated_write_size,
+					p_buffer);
 			offset += write_size;
 			p_buffer += write_size;
 		}
diff --git a/include/nand.h b/include/nand.h
index c5818f1..8d94b5c 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -118,6 +118,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 #define WITH_YAFFS_OOB	(1 << 0) /* whether write with yaffs format. This flag
 				  * is a 'mode' meaning it cannot be mixed with
 				  * other flags */
+#define WITH_DROP_FFS	(1 << 1) /* drop trailing all-0xff pages */
 
 int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 			u_char *buffer, int flags);
-- 
1.7.4.1



More information about the U-Boot mailing list