[U-Boot] [PATCH 3/5] nand_util: drop trailing all-0xff pages if requested
Ben Gardiner
bengardiner at nanometrics.ca
Thu Apr 28 23:47:53 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. Without this
behaviour, UBI images flashed to NAND where either 1) the ECC used
does not map all-0xff to 0xff or 2) the number of times a page
can be written is limited by the NAND will not be successfully
attached after flashing.
Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
CC: Artem Bityutskiy <dedekind1 at gmail.com>
---
This behaviour was found to fix both UBI and JFFS2 images written to
cleanly erased NAND partitions on da850evm.
---
drivers/mtd/nand/nand_util.c | 29 ++++++++++++++++++++++++++---
include/nand.h | 3 ++-
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 2bd8758..c9bb930 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -436,6 +436,22 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
return ret;
}
+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 (((const uint8_t *)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;
+ return l;
+}
+
/**
* nand_write_skip_bad:
*
@@ -499,7 +515,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;
@@ -512,7 +528,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 ();
@@ -558,7 +574,14 @@ 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);
+ if (flags & WITH_DROP_FFS)
+ truncated_write_size = drop_ffs(nand, p_buffer,
+ &write_size);
+ else
+ truncated_write_size = write_size;
+
+ 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 628317a..b58a82d 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -115,7 +115,8 @@ typedef struct nand_erase_options nand_erase_options_t;
int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
u_char *buffer);
-#define WITH_OOB (1 << 0) /* whether write with yaffs format */
+#define WITH_OOB (1 << 0) /* whether write with yaffs format */
+#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.1
More information about the U-Boot
mailing list