*             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.
  *
        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:
  *
                return -EINVAL;
        }
 
-       if (!need_skip) {
+       if (!need_skip && !(flags & WITH_DROP_FFS)) {
                rval = nand_write (nand, offset, length, buffer);
                if (rval == 0)
                        return 0;
 
        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 ();
 
                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;
                }
 
 #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);