From 1966d4942c2d91b225ddb820e6be01b9b1dc9652 Mon Sep 17 00:00:00 2001
From: John Crispin <john@openwrt.org>
Date: Sun, 30 Mar 2014 09:16:47 +0000
Subject: [PATCH] busybox: backport dd conv=swab from 1.22

Some boards have the WLAN EEPROM stored in flash in big-endian format,
whereas the driver requires the EEPROM in little-endian format. The
conv=swab option in dd is particularly useful in this case. This patch
backports this feature from busybox-1.22 based on the following commits:

commit    b941316ae5313be523b64f0a9151ee4decb2b35b dd: support conv=swab
commit    8395bd3f52f8ed46fa3ffc316b2d113afa748bae dd: fix example in a
comment. No code changes.
commit    5b9910f0a4a1b7976c46e6f849aaa263180e5521 dd: fail if swab is
attempted on odd-sized block
commit    0ff0b320a2dbb5e0b5fa245ffd9b2648d7026843 dd: code shrink

v2: include the commit messages from upstream

Signed-off-by: Matti Laakso <malaakso@elisanet.fi>

SVN-Revision: 40327
---
 .../patches/008-backport-dd-conv-swab.patch   | 97 +++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 package/utils/busybox/patches/008-backport-dd-conv-swab.patch

diff --git a/package/utils/busybox/patches/008-backport-dd-conv-swab.patch b/package/utils/busybox/patches/008-backport-dd-conv-swab.patch
new file mode 100644
index 0000000000..1e3cd15c93
--- /dev/null
+++ b/package/utils/busybox/patches/008-backport-dd-conv-swab.patch
@@ -0,0 +1,97 @@
+--- a/coreutils/dd.c
++++ b/coreutils/dd.c
+@@ -10,7 +10,7 @@
+ 
+ //usage:#define dd_trivial_usage
+ //usage:       "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
+-//usage:       "	[seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]")
++//usage:       "	[seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync|swab]")
+ //usage:#define dd_full_usage "\n\n"
+ //usage:       "Copy a file with converting and formatting\n"
+ //usage:     "\n	if=FILE		Read from FILE instead of stdin"
+@@ -30,6 +30,7 @@
+ //usage:     "\n	conv=noerror	Continue after read errors"
+ //usage:     "\n	conv=sync	Pad blocks with zeros"
+ //usage:     "\n	conv=fsync	Physically write data out before finishing"
++//usage:     "\n	conv=swab	Swap every pair of bytes"
+ //usage:	)
+ //usage:     "\n"
+ //usage:     "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),"
+@@ -155,9 +156,10 @@ int dd_main(int argc UNUSED_PARAM, char
+ 		FLAG_SYNC    = 1 << 1,
+ 		FLAG_NOERROR = 1 << 2,
+ 		FLAG_FSYNC   = 1 << 3,
++		FLAG_SWAB    = 1 << 4,
+ 		/* end of conv flags */
+-		FLAG_TWOBUFS = 1 << 4,
+-		FLAG_COUNT   = 1 << 5,
++		FLAG_TWOBUFS = 1 << 5,
++		FLAG_COUNT   = 1 << 6,
+ 	};
+ 	static const char keywords[] ALIGN1 =
+ 		"bs\0""count\0""seek\0""skip\0""if\0""of\0"
+@@ -167,7 +169,7 @@ int dd_main(int argc UNUSED_PARAM, char
+ 		;
+ #if ENABLE_FEATURE_DD_IBS_OBS
+ 	static const char conv_words[] ALIGN1 =
+-		"notrunc\0""sync\0""noerror\0""fsync\0";
++		"notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
+ #endif
+ 	enum {
+ 		OP_bs = 0,
+@@ -185,11 +187,11 @@ int dd_main(int argc UNUSED_PARAM, char
+ 		OP_conv_sync,
+ 		OP_conv_noerror,
+ 		OP_conv_fsync,
++		OP_conv_swab,
+ 	/* Unimplemented conv=XXX: */
+ 	//nocreat       do not create the output file
+ 	//excl          fail if the output file already exists
+ 	//fdatasync     physically write output file data before finishing
+-	//swab          swap every pair of input bytes
+ 	//lcase         change upper case to lower case
+ 	//ucase         change lower case to upper case
+ 	//block         pad newline-terminated records with spaces to cbs-size
+@@ -207,12 +209,14 @@ int dd_main(int argc UNUSED_PARAM, char
+ 	struct {
+ 		int flags;
+ 		size_t oc;
++		ssize_t prev_read_size; /* for detecting swab failure */
+ 		off_t count;
+ 		off_t seek, skip;
+ 		const char *infile, *outfile;
+ 	} Z;
+ #define flags   (Z.flags  )
+ #define oc      (Z.oc     )
++#define prev_read_size (Z.prev_read_size)
+ #define count   (Z.count  )
+ #define seek    (Z.seek   )
+ #define skip    (Z.skip   )
+@@ -375,6 +379,27 @@ int dd_main(int argc UNUSED_PARAM, char
+ 			 * conv=noerror just ignores input bad blocks */
+ 			n = 0;
+ 		}
++		if (flags & FLAG_SWAB) {
++			uint16_t *p16;
++			ssize_t n2;
++
++			/* Our code allows only last read to be odd-sized */
++			if (prev_read_size & 1)
++				bb_error_msg_and_die("can't swab %lu byte buffer",
++						(unsigned long)prev_read_size);
++			prev_read_size = n;
++
++			/* If n is odd, last byte is not swapped:
++			 *  echo -n "qwe" | dd conv=swab
++			 * prints "wqe".
++			 */
++			p16 = (void*) ibuf;
++			n2 = (n >> 1);
++			while (--n2 >= 0) {
++				*p16 = bswap_16(*p16);
++				p16++;
++			}
++		}
+ 		if ((size_t)n == ibs)
+ 			G.in_full++;
+ 		else {
-- 
2.30.2