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: Ben Gardiner <bengardiner@nanometrics.ca> CC: Artem Bityutskiy <dedekind1@gmail.com> Acked-by: Detlev Zundel <dzu@denx.de> CC: Scott Wood <scottwood@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
This commit is contained in:
parent
c135456ff5
commit
169d54d8b3
@ -11,6 +11,9 @@
|
||||
* nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user