Skip to content
Snippets Groups Projects
Commit 169d54d8 authored by Ben Gardiner's avatar Ben Gardiner Committed by Scott Wood
Browse files

nand_util: drop trailing all-0xff pages if requested

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]

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



Signed-off-by: default avatarBen Gardiner <bengardiner@nanometrics.ca>
CC: Artem Bityutskiy <dedekind1@gmail.com>
Acked-by: default avatarDetlev Zundel <dzu@denx.de>
CC: Scott Wood <scottwood@freescale.com>
Signed-off-by: default avatarScott Wood <scottwood@freescale.com>
parent c135456f
No related branches found
No related tags found
No related merge requests found
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
* nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com) * nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
* and Thomas Gleixner (tglx@linutronix.de) * and Thomas Gleixner (tglx@linutronix.de)
* *
* Copyright (C) 2008 Nokia Corporation: drop_ffs() function by
* Artem Bityutskiy <dedekind1@gmail.com> from mtd-utils
*
* See file CREDITS for list of people who contributed to this * See file CREDITS for list of people who contributed to this
* project. * project.
* *
...@@ -436,6 +439,29 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length) ...@@ -436,6 +439,29 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
return ret; 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: * nand_write_skip_bad:
* *
...@@ -502,7 +528,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, ...@@ -502,7 +528,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
return -EINVAL; return -EINVAL;
} }
if (!need_skip) { if (!need_skip && !(flags & WITH_DROP_FFS)) {
rval = nand_write (nand, offset, length, buffer); rval = nand_write (nand, offset, length, buffer);
if (rval == 0) if (rval == 0)
return 0; return 0;
...@@ -515,7 +541,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, ...@@ -515,7 +541,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
while (left_to_write > 0) { while (left_to_write > 0) {
size_t block_offset = offset & (nand->erasesize - 1); size_t block_offset = offset & (nand->erasesize - 1);
size_t write_size; size_t write_size, truncated_write_size;
WATCHDOG_RESET (); WATCHDOG_RESET ();
...@@ -561,7 +587,15 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, ...@@ -561,7 +587,15 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
else else
#endif #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; offset += write_size;
p_buffer += write_size; p_buffer += write_size;
} }
......
...@@ -118,6 +118,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, ...@@ -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 #define WITH_YAFFS_OOB (1 << 0) /* whether write with yaffs format. This flag
* is a 'mode' meaning it cannot be mixed with * is a 'mode' meaning it cannot be mixed with
* other flags */ * 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, int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
u_char *buffer, int flags); u_char *buffer, int flags);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment