Merge branch 'mem' of git://git.denx.de/u-boot-x86
diff --git a/README b/README
index 0070694..51eb71b 100644
--- a/README
+++ b/README
@@ -3811,6 +3811,15 @@
 		that is executed before the actual U-Boot. E.g. when
 		compiling a NAND SPL.
 
+- CONFIG_ARCH_MAP_SYSMEM
+		Generally U-Boot (and in particular the md command) uses
+		effective address. It is therefore not necessary to regard
+		U-Boot address as virtual addresses that need to be translated
+		to physical addresses. However, sandbox requires this, since
+		it maintains its own little RAM buffer which contains all
+		addressable memory. This option causes some memory accesses
+		to be mapped through map_sysmem() / unmap_sysmem().
+
 - CONFIG_USE_ARCH_MEMCPY
   CONFIG_USE_ARCH_MEMSET
 		If these options are used a optimized version of memcpy/memset will
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index 02ce4a4..4fd0d4e 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -18,4 +18,5 @@
 # MA 02111-1307 USA
 
 PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ -U_FORTIFY_SOURCE
+PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM
 PLATFORM_LIBS += -lrt
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 36637af..3e37c93 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -44,6 +44,14 @@
 	return read(fd, buf, count);
 }
 
+ssize_t os_read_no_block(int fd, void *buf, size_t count)
+{
+	const int flags = fcntl(fd, F_GETFL, 0);
+
+	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+	return os_read(fd, buf, count);
+}
+
 ssize_t os_write(int fd, const void *buf, size_t count)
 {
 	return write(fd, buf, count);
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 7603bf9..5287fd5 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -122,4 +122,7 @@
 	 * never return.
 	 */
 	board_init_f(0);
+
+	/* NOTREACHED - board_init_f() does not return */
+	return 0;
 }
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 0392d21..d8c0236 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -39,3 +39,13 @@
 {
 
 }
+
+/* For sandbox, we want addresses to point into our RAM buffer */
+static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
+{
+	return map_physmem(paddr, len, MAP_WRBACK);
+}
+
+static inline void unmap_sysmem(const void *vaddr)
+{
+}
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 1312a0d..b32991d 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -452,9 +452,7 @@
 
 	/* Don't start if "autostart" is set to "no" */
 	if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) {
-		char buf[32];
-		sprintf(buf, "%lX", images.os.image_len);
-		setenv("filesize", buf);
+		setenv_hex("filesize", images.os.image_len);
 		return 0;
 	}
 	appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
@@ -529,17 +527,14 @@
 		case BOOTM_STATE_RAMDISK:
 		{
 			ulong rd_len = images.rd_end - images.rd_start;
-			char str[17];
 
 			ret = boot_ramdisk_high(&images.lmb, images.rd_start,
 				rd_len, &images.initrd_start, &images.initrd_end);
 			if (ret)
 				return ret;
 
-			sprintf(str, "%lx", images.initrd_start);
-			setenv("initrd_start", str);
-			sprintf(str, "%lx", images.initrd_end);
-			setenv("initrd_end", str);
+			setenv_hex("initrd_start", images.initrd_start);
+			setenv_hex("initrd_end", images.initrd_end);
 		}
 			break;
 #endif
diff --git a/common/cmd_cbfs.c b/common/cmd_cbfs.c
index 3b6cfd8..f51534b 100644
--- a/common/cmd_cbfs.c
+++ b/common/cmd_cbfs.c
@@ -65,7 +65,6 @@
 	const struct cbfs_cachenode *file;
 	unsigned long offset;
 	unsigned long count;
-	char buf[12];
 	long size;
 
 	if (argc < 3) {
@@ -95,8 +94,7 @@
 
 	printf("\n%ld bytes read\n", size);
 
-	sprintf(buf, "%lX", size);
-	setenv("filesize", buf);
+	setenv_hex("filesize", size);
 
 	return 0;
 }
diff --git a/common/cmd_cramfs.c b/common/cmd_cramfs.c
index e7f496e..0e43ab6 100644
--- a/common/cmd_cramfs.c
+++ b/common/cmd_cramfs.c
@@ -146,11 +146,9 @@
 		size = cramfs_load ((char *) offset, &part, filename);
 
 	if (size > 0) {
-		char buf[10];
 		printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n",
 			size, offset);
-		sprintf(buf, "%x", size);
-		setenv("filesize", buf);
+		setenv_hex("filesize", size);
 	} else {
 		printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename);
 	}
diff --git a/common/cmd_fdos.c b/common/cmd_fdos.c
index fbee861..8ea1140 100644
--- a/common/cmd_fdos.c
+++ b/common/cmd_fdos.c
@@ -40,7 +40,6 @@
     char *name;
     char *ep;
     int size;
-    char buf [12];
     int drive = CONFIG_SYS_FDC_DRIVE_NUMBER;
 
     /* pre-set load_addr */
@@ -91,8 +90,7 @@
     }
     flush_cache (load_addr, size);
 
-    sprintf(buf, "%x", size);
-    setenv("filesize", buf);
+    setenv_hex("filesize", size);
 
     printf("Floppy DOS load complete: %d bytes loaded to 0x%lx\n",
 	   size, load_addr);
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index 6eec947..ac77a08 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -55,12 +55,8 @@
 
 void set_working_fdt_addr(void *addr)
 {
-	char buf[17];
-
 	working_fdt = addr;
-
-	sprintf(buf, "%lx", (unsigned long)addr);
-	setenv("fdtaddr", buf);
+	setenv_addr("fdtaddr", addr);
 }
 
 /*
@@ -347,10 +343,7 @@
 			}
 			if (subcmd[0] == 's') {
 				/* get the num nodes at this level */
-				char buf[11];
-
-				sprintf(buf, "%d", curIndex + 1);
-				setenv(var, buf);
+				setenv_ulong(var, curIndex + 1);
 			} else {
 				/* node index not found */
 				printf("libfdt node not found\n");
diff --git a/common/cmd_hash.c b/common/cmd_hash.c
index 689c608..4fe0e78 100644
--- a/common/cmd_hash.c
+++ b/common/cmd_hash.c
@@ -26,22 +26,30 @@
 #include <common.h>
 #include <command.h>
 #include <hash.h>
+#include <linux/ctype.h>
 
 static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
+	char *s;
 #ifdef CONFIG_HASH_VERIFY
-	int verify = 0;
+	int flags = HASH_FLAG_ENV;
 
+	if (argc < 4)
+		return CMD_RET_USAGE;
 	if (!strcmp(argv[1], "-v")) {
-		verify = 1;
+		flags |= HASH_FLAG_VERIFY;
 		argc--;
 		argv++;
 	}
+#else
+	const int flags = HASH_FLAG_ENV;
 #endif
 	/* Move forward to 'algorithm' parameter */
 	argc--;
 	argv++;
-	return hash_command(*argv, verify, cmdtp, flag, argc - 1, argv + 1);
+	for (s = *argv; *s; s++)
+		*s = tolower(*s);
+	return hash_command(*argv, flags, cmdtp, flag, argc - 1, argv + 1);
 }
 
 #ifdef CONFIG_HASH_VERIFY
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c
index 27296dd..4a4a000 100644
--- a/common/cmd_jffs2.c
+++ b/common/cmd_jffs2.c
@@ -525,11 +525,9 @@
 		}
 
 		if (size > 0) {
-			char buf[10];
 			printf("### %s load complete: %d bytes loaded to 0x%lx\n",
 				fsname, size, offset);
-			sprintf(buf, "%x", size);
-			setenv("filesize", buf);
+			setenv_hex("filesize", size);
 		} else {
 			printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename);
 		}
diff --git a/common/cmd_load.c b/common/cmd_load.c
index 46db962..0832e92 100644
--- a/common/cmd_load.c
+++ b/common/cmd_load.c
@@ -149,7 +149,6 @@
 	int	type;				/* return code for record type	*/
 	ulong	addr;				/* load address from S-Record	*/
 	ulong	size;				/* number of bytes transferred	*/
-	char	buf[32];
 	ulong	store_addr;
 	ulong	start_addr = ~0;
 	ulong	end_addr   =  0;
@@ -198,8 +197,7 @@
 			    start_addr, end_addr, size, size
 		    );
 		    flush_cache(start_addr, size);
-		    sprintf(buf, "%lX", size);
-		    setenv("filesize", buf);
+		    setenv_hex("filesize", size);
 		    return (addr);
 		case SREC_START:
 		    break;
@@ -519,7 +517,6 @@
 static ulong load_serial_bin(ulong offset)
 {
 	int size, i;
-	char buf[32];
 
 	set_kerm_bin_mode((ulong *) offset);
 	size = k_recv();
@@ -539,8 +536,7 @@
 	flush_cache(offset, size);
 
 	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
-	sprintf(buf, "%X", size);
-	setenv("filesize", buf);
+	setenv_hex("filesize", size);
 
 	return offset;
 }
@@ -965,7 +961,6 @@
 static ulong load_serial_ymodem(ulong offset)
 {
 	int size;
-	char buf[32];
 	int err;
 	int res;
 	connection_info_t info;
@@ -1012,8 +1007,7 @@
 	flush_cache(offset, size);
 
 	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
-	sprintf(buf, "%X", size);
-	setenv("filesize", buf);
+	setenv_hex("filesize", size);
 
 	return offset;
 }
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index d44aa1d..042c994 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -32,11 +32,17 @@
 #ifdef CONFIG_HAS_DATAFLASH
 #include <dataflash.h>
 #endif
+#include <hash.h>
 #include <watchdog.h>
+#include <asm/io.h>
 #include <linux/compiler.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_SYS_MEMTEST_SCRATCH
+#define CONFIG_SYS_MEMTEST_SCRATCH 0
+#endif
+
 static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
 
 /* Display values from last command.
@@ -138,9 +144,13 @@
 # endif
 
 	{
+		ulong bytes = size * length;
+		const void *buf = map_sysmem(addr, bytes);
+
 		/* Print the lines. */
-		print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size);
-		addr += size*length;
+		print_buffer(addr, buf, size, length, DISP_LINE_LEN / size);
+		addr += bytes;
+		unmap_sysmem(buf);
 	}
 #endif
 
@@ -163,6 +173,8 @@
 {
 	ulong	addr, writeval, count;
 	int	size;
+	void *buf;
+	ulong bytes;
 
 	if ((argc < 3) || (argc > 4))
 		return CMD_RET_USAGE;
@@ -188,15 +200,18 @@
 		count = 1;
 	}
 
+	bytes = size * count;
+	buf = map_sysmem(addr, bytes);
 	while (count-- > 0) {
 		if (size == 4)
-			*((ulong  *)addr) = (ulong )writeval;
+			*((ulong *)buf) = (ulong)writeval;
 		else if (size == 2)
-			*((ushort *)addr) = (ushort)writeval;
+			*((ushort *)buf) = (ushort)writeval;
 		else
-			*((u_char *)addr) = (u_char)writeval;
-		addr += size;
+			*((u_char *)buf) = (u_char)writeval;
+		buf += size;
 	}
+	unmap_sysmem(buf);
 	return 0;
 }
 
@@ -258,10 +273,11 @@
 
 static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong	addr1, addr2, count, ngood;
+	ulong	addr1, addr2, count, ngood, bytes;
 	int	size;
 	int     rcode = 0;
 	const char *type;
+	const void *buf1, *buf2, *base;
 
 	if (argc != 4)
 		return CMD_RET_USAGE;
@@ -294,33 +310,40 @@
 	}
 #endif
 
+	bytes = size * count;
+	base = buf1 = map_sysmem(addr1, bytes);
+	buf2 = map_sysmem(addr2, bytes);
 	for (ngood = 0; ngood < count; ++ngood) {
 		ulong word1, word2;
 		if (size == 4) {
-			word1 = *(ulong *)addr1;
-			word2 = *(ulong *)addr2;
+			word1 = *(ulong *)buf1;
+			word2 = *(ulong *)buf2;
 		} else if (size == 2) {
-			word1 = *(ushort *)addr1;
-			word2 = *(ushort *)addr2;
+			word1 = *(ushort *)buf1;
+			word2 = *(ushort *)buf2;
 		} else {
-			word1 = *(u_char *)addr1;
-			word2 = *(u_char *)addr2;
+			word1 = *(u_char *)buf1;
+			word2 = *(u_char *)buf2;
 		}
 		if (word1 != word2) {
+			ulong offset = buf1 - base;
+
 			printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
-				type, addr1, size, word1,
-				type, addr2, size, word2);
+				type, (ulong)(addr1 + offset), size, word1,
+				type, (ulong)(addr2 + offset), size, word2);
 			rcode = 1;
 			break;
 		}
 
-		addr1 += size;
-		addr2 += size;
+		buf1 += size;
+		buf2 += size;
 
 		/* reset watchdog from time to time */
 		if ((ngood % (64 << 10)) == 0)
 			WATCHDOG_RESET();
 	}
+	unmap_sysmem(buf1);
+	unmap_sysmem(buf2);
 
 	printf("Total of %ld %s(s) were the same\n", ngood, type);
 	return rcode;
@@ -328,8 +351,10 @@
 
 static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong	addr, dest, count;
+	ulong	addr, dest, count, bytes;
 	int	size;
+	const void *src;
+	void *buf;
 
 	if (argc != 4)
 		return CMD_RET_USAGE;
@@ -419,15 +444,18 @@
 	}
 #endif
 
+	bytes = size * count;
+	buf = map_sysmem(addr, bytes);
+	src = map_sysmem(addr, bytes);
 	while (count-- > 0) {
 		if (size == 4)
-			*((ulong  *)dest) = *((ulong  *)addr);
+			*((ulong *)buf) = *((ulong  *)src);
 		else if (size == 2)
-			*((ushort *)dest) = *((ushort *)addr);
+			*((ushort *)buf) = *((ushort *)src);
 		else
-			*((u_char *)dest) = *((u_char *)addr);
-		addr += size;
-		dest += size;
+			*((u_char *)buf) = *((u_char *)src);
+		src += size;
+		buf += size;
 
 		/* reset watchdog from time to time */
 		if ((count % (64 << 10)) == 0)
@@ -453,11 +481,12 @@
 static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 		       char * const argv[])
 {
-	ulong	addr, length, i;
+	ulong	addr, length, i, bytes;
 	int	size;
 	volatile uint	*longp;
 	volatile ushort *shortp;
 	volatile u_char	*cp;
+	const void *buf;
 
 	if (argc < 3)
 		return CMD_RET_USAGE;
@@ -477,28 +506,31 @@
 	*/
 	length = simple_strtoul(argv[2], NULL, 16);
 
+	bytes = size * length;
+	buf = map_sysmem(addr, bytes);
+
 	/* We want to optimize the loops to run as fast as possible.
 	 * If we have only one object, just run infinite loops.
 	 */
 	if (length == 1) {
 		if (size == 4) {
-			longp = (uint *)addr;
+			longp = (uint *)buf;
 			for (;;)
 				i = *longp;
 		}
 		if (size == 2) {
-			shortp = (ushort *)addr;
+			shortp = (ushort *)buf;
 			for (;;)
 				i = *shortp;
 		}
-		cp = (u_char *)addr;
+		cp = (u_char *)buf;
 		for (;;)
 			i = *cp;
 	}
 
 	if (size == 4) {
 		for (;;) {
-			longp = (uint *)addr;
+			longp = (uint *)buf;
 			i = length;
 			while (i-- > 0)
 				*longp++;
@@ -506,28 +538,30 @@
 	}
 	if (size == 2) {
 		for (;;) {
-			shortp = (ushort *)addr;
+			shortp = (ushort *)buf;
 			i = length;
 			while (i-- > 0)
 				*shortp++;
 		}
 	}
 	for (;;) {
-		cp = (u_char *)addr;
+		cp = (u_char *)buf;
 		i = length;
 		while (i-- > 0)
 			*cp++;
 	}
+	unmap_sysmem(buf);
 }
 
 #ifdef CONFIG_LOOPW
 int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong	addr, length, i, data;
+	ulong	addr, length, i, data, bytes;
 	int	size;
 	volatile uint	*longp;
 	volatile ushort *shortp;
 	volatile u_char	*cp;
+	void *buf;
 
 	if (argc < 4)
 		return CMD_RET_USAGE;
@@ -550,28 +584,31 @@
 	/* data to write */
 	data = simple_strtoul(argv[3], NULL, 16);
 
+	bytes = size * length;
+	buf = map_sysmem(addr, bytes);
+
 	/* We want to optimize the loops to run as fast as possible.
 	 * If we have only one object, just run infinite loops.
 	 */
 	if (length == 1) {
 		if (size == 4) {
-			longp = (uint *)addr;
+			longp = (uint *)buf;
 			for (;;)
 				*longp = data;
 					}
 		if (size == 2) {
-			shortp = (ushort *)addr;
+			shortp = (ushort *)buf;
 			for (;;)
 				*shortp = data;
 		}
-		cp = (u_char *)addr;
+		cp = (u_char *)buf;
 		for (;;)
 			*cp = data;
 	}
 
 	if (size == 4) {
 		for (;;) {
-			longp = (uint *)addr;
+			longp = (uint *)buf;
 			i = length;
 			while (i-- > 0)
 				*longp++ = data;
@@ -579,14 +616,14 @@
 	}
 	if (size == 2) {
 		for (;;) {
-			shortp = (ushort *)addr;
+			shortp = (ushort *)buf;
 			i = length;
 			while (i-- > 0)
 				*shortp++ = data;
 		}
 	}
 	for (;;) {
-		cp = (u_char *)addr;
+		cp = (u_char *)buf;
 		i = length;
 		while (i-- > 0)
 			*cp++ = data;
@@ -594,36 +631,19 @@
 }
 #endif /* CONFIG_LOOPW */
 
-/*
- * Perform a memory test. A more complete alternative test can be
- * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
- * interrupted by ctrl-c or by a failure of one of the sub-tests.
- */
-static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
-			char * const argv[])
+static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr,
+			  vu_long *dummy)
 {
-	vu_long	*addr, *start, *end;
-	ulong	val;
-	ulong	readback;
-	ulong	errs = 0;
-	int iterations = 1;
-	int iteration_limit;
-
-#if defined(CONFIG_SYS_ALT_MEMTEST)
-	vu_long	len;
-	vu_long	offset;
-	vu_long	test_offset;
-	vu_long	pattern;
-	vu_long	temp;
-	vu_long	anti_pattern;
-	vu_long	num_words;
-#if defined(CONFIG_SYS_MEMTEST_SCRATCH)
-	vu_long *dummy = (vu_long*)CONFIG_SYS_MEMTEST_SCRATCH;
-#else
-	vu_long *dummy = NULL;	/* yes, this is address 0x0, not NULL */
-#endif
-	int	j;
-
+	vu_long *addr;
+	ulong errs = 0;
+	ulong val, readback;
+	int j;
+	vu_long offset;
+	vu_long test_offset;
+	vu_long pattern;
+	vu_long temp;
+	vu_long anti_pattern;
+	vu_long num_words;
 	static const ulong bitpattern[] = {
 		0x00000001,	/* single bit */
 		0x00000003,	/* two adjacent bits */
@@ -634,20 +654,292 @@
 		0x00000055,	/* four non-adjacent bits */
 		0xaaaaaaaa,	/* alternating 1/0 */
 	};
+
+	num_words = (end_addr - start_addr) / sizeof(vu_long);
+
+	/*
+	 * Data line test: write a pattern to the first
+	 * location, write the 1's complement to a 'parking'
+	 * address (changes the state of the data bus so a
+	 * floating bus doesn't give a false OK), and then
+	 * read the value back. Note that we read it back
+	 * into a variable because the next time we read it,
+	 * it might be right (been there, tough to explain to
+	 * the quality guys why it prints a failure when the
+	 * "is" and "should be" are obviously the same in the
+	 * error message).
+	 *
+	 * Rather than exhaustively testing, we test some
+	 * patterns by shifting '1' bits through a field of
+	 * '0's and '0' bits through a field of '1's (i.e.
+	 * pattern and ~pattern).
+	 */
+	addr = buf;
+	for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
+		val = bitpattern[j];
+		for (; val != 0; val <<= 1) {
+			*addr = val;
+			*dummy  = ~val; /* clear the test data off the bus */
+			readback = *addr;
+			if (readback != val) {
+				printf("FAILURE (data line): "
+					"expected %08lx, actual %08lx\n",
+						val, readback);
+				errs++;
+				if (ctrlc())
+					return -1;
+			}
+			*addr  = ~val;
+			*dummy  = val;
+			readback = *addr;
+			if (readback != ~val) {
+				printf("FAILURE (data line): "
+					"Is %08lx, should be %08lx\n",
+						readback, ~val);
+				errs++;
+				if (ctrlc())
+					return -1;
+			}
+		}
+	}
+
+	/*
+	 * Based on code whose Original Author and Copyright
+	 * information follows: Copyright (c) 1998 by Michael
+	 * Barr. This software is placed into the public
+	 * domain and may be used for any purpose. However,
+	 * this notice must not be changed or removed and no
+	 * warranty is either expressed or implied by its
+	 * publication or distribution.
+	 */
+
+	/*
+	* Address line test
+
+	 * Description: Test the address bus wiring in a
+	 *              memory region by performing a walking
+	 *              1's test on the relevant bits of the
+	 *              address and checking for aliasing.
+	 *              This test will find single-bit
+	 *              address failures such as stuck-high,
+	 *              stuck-low, and shorted pins. The base
+	 *              address and size of the region are
+	 *              selected by the caller.
+
+	 * Notes:	For best results, the selected base
+	 *              address should have enough LSB 0's to
+	 *              guarantee single address bit changes.
+	 *              For example, to test a 64-Kbyte
+	 *              region, select a base address on a
+	 *              64-Kbyte boundary. Also, select the
+	 *              region size as a power-of-two if at
+	 *              all possible.
+	 *
+	 * Returns:     0 if the test succeeds, 1 if the test fails.
+	 */
+	pattern = (vu_long) 0xaaaaaaaa;
+	anti_pattern = (vu_long) 0x55555555;
+
+	debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words);
+	/*
+	 * Write the default pattern at each of the
+	 * power-of-two offsets.
+	 */
+	for (offset = 1; offset < num_words; offset <<= 1)
+		addr[offset] = pattern;
+
+	/*
+	 * Check for address bits stuck high.
+	 */
+	test_offset = 0;
+	addr[test_offset] = anti_pattern;
+
+	for (offset = 1; offset < num_words; offset <<= 1) {
+		temp = addr[offset];
+		if (temp != pattern) {
+			printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
+				" expected 0x%.8lx, actual 0x%.8lx\n",
+				start_addr + offset, pattern, temp);
+			errs++;
+			if (ctrlc())
+				return -1;
+		}
+	}
+	addr[test_offset] = pattern;
+	WATCHDOG_RESET();
+
+	/*
+	 * Check for addr bits stuck low or shorted.
+	 */
+	for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
+		addr[test_offset] = anti_pattern;
+
+		for (offset = 1; offset < num_words; offset <<= 1) {
+			temp = addr[offset];
+			if ((temp != pattern) && (offset != test_offset)) {
+				printf("\nFAILURE: Address bit stuck low or"
+					" shorted @ 0x%.8lx: expected 0x%.8lx,"
+					" actual 0x%.8lx\n",
+					start_addr + offset, pattern, temp);
+				errs++;
+				if (ctrlc())
+					return -1;
+			}
+		}
+		addr[test_offset] = pattern;
+	}
+
+	/*
+	 * Description: Test the integrity of a physical
+	 *		memory device by performing an
+	 *		increment/decrement test over the
+	 *		entire region. In the process every
+	 *		storage bit in the device is tested
+	 *		as a zero and a one. The base address
+	 *		and the size of the region are
+	 *		selected by the caller.
+	 *
+	 * Returns:     0 if the test succeeds, 1 if the test fails.
+	 */
+	num_words++;
+
+	/*
+	 * Fill memory with a known pattern.
+	 */
+	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+		WATCHDOG_RESET();
+		addr[offset] = pattern;
+	}
+
+	/*
+	 * Check each location and invert it for the second pass.
+	 */
+	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+		WATCHDOG_RESET();
+		temp = addr[offset];
+		if (temp != pattern) {
+			printf("\nFAILURE (read/write) @ 0x%.8lx:"
+				" expected 0x%.8lx, actual 0x%.8lx)\n",
+				start_addr + offset, pattern, temp);
+			errs++;
+			if (ctrlc())
+				return -1;
+		}
+
+		anti_pattern = ~pattern;
+		addr[offset] = anti_pattern;
+	}
+
+	/*
+	 * Check each location for the inverted pattern and zero it.
+	 */
+	for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+		WATCHDOG_RESET();
+		anti_pattern = ~pattern;
+		temp = addr[offset];
+		if (temp != anti_pattern) {
+			printf("\nFAILURE (read/write): @ 0x%.8lx:"
+				" expected 0x%.8lx, actual 0x%.8lx)\n",
+				start_addr + offset, anti_pattern, temp);
+			errs++;
+			if (ctrlc())
+				return -1;
+		}
+		addr[offset] = 0;
+	}
+
+	return 0;
+}
+
+static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr,
+			    vu_long pattern, int iteration)
+{
+	vu_long *end;
+	vu_long *addr;
+	ulong errs = 0;
+	ulong incr, length;
+	ulong val, readback;
+
+	/* Alternate the pattern */
+	incr = 1;
+	if (iteration & 1) {
+		incr = -incr;
+		/*
+		 * Flip the pattern each time to make lots of zeros and
+		 * then, the next time, lots of ones.  We decrement
+		 * the "negative" patterns and increment the "positive"
+		 * patterns to preserve this feature.
+		 */
+		if (pattern & 0x80000000)
+			pattern = -pattern;	/* complement & increment */
+		else
+			pattern = ~pattern;
+	}
+	length = (end_addr - start_addr) / sizeof(ulong);
+	end = buf + length;
+	printf("\rPattern %08lX  Writing..."
+		"%12s"
+		"\b\b\b\b\b\b\b\b\b\b",
+		pattern, "");
+
+	for (addr = buf, val = pattern; addr < end; addr++) {
+		WATCHDOG_RESET();
+		*addr = val;
+		val += incr;
+	}
+
+	puts("Reading...");
+
+	for (addr = buf, val = pattern; addr < end; addr++) {
+		WATCHDOG_RESET();
+		readback = *addr;
+		if (readback != val) {
+			ulong offset = addr - buf;
+
+			printf("\nMem error @ 0x%08X: "
+				"found %08lX, expected %08lX\n",
+				(uint)(uintptr_t)(start_addr + offset),
+				readback, val);
+			errs++;
+			if (ctrlc())
+				return -1;
+		}
+		val += incr;
+	}
+
+	return 0;
+}
+
+/*
+ * Perform a memory test. A more complete alternative test can be
+ * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
+ * interrupted by ctrl-c or by a failure of one of the sub-tests.
+ */
+static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[])
+{
+	ulong start, end;
+	vu_long *buf, *dummy;
+	int iteration_limit;
+	int ret;
+	ulong errs = 0;	/* number of errors, or -1 if interrupted */
+	ulong pattern;
+	int iteration;
+#if defined(CONFIG_SYS_ALT_MEMTEST)
+	const int alt_test = 1;
 #else
-	ulong	incr;
-	ulong	pattern;
+	const int alt_test = 0;
 #endif
 
 	if (argc > 1)
-		start = (ulong *)simple_strtoul(argv[1], NULL, 16);
+		start = simple_strtoul(argv[1], NULL, 16);
 	else
-		start = (ulong *)CONFIG_SYS_MEMTEST_START;
+		start = CONFIG_SYS_MEMTEST_START;
 
 	if (argc > 2)
-		end = (ulong *)simple_strtoul(argv[2], NULL, 16);
+		end = simple_strtoul(argv[2], NULL, 16);
 	else
-		end = (ulong *)(CONFIG_SYS_MEMTEST_END);
+		end = CONFIG_SYS_MEMTEST_END;
 
 	if (argc > 3)
 		pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
@@ -659,295 +951,56 @@
 	else
 		iteration_limit = 0;
 
-#if defined(CONFIG_SYS_ALT_MEMTEST)
-	printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
-	debug("%s:%d: start 0x%p end 0x%p\n",
-		__FUNCTION__, __LINE__, start, end);
+	printf("Testing %08x ... %08x:\n", (uint)start, (uint)end);
+	debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__,
+	      start, end);
 
-	for (;;) {
+	buf = map_sysmem(start, end - start);
+	dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
+	for (iteration = 0;
+			!iteration_limit || iteration < iteration_limit;
+			iteration++) {
 		if (ctrlc()) {
-			putc ('\n');
-			return 1;
+			errs = -1UL;
+			break;
 		}
 
-
-		if (iteration_limit && iterations > iteration_limit) {
-			printf("Tested %d iteration(s) with %lu errors.\n",
-				iterations-1, errs);
-			return errs != 0;
-		}
-
-		printf("Iteration: %6d\r", iterations);
+		printf("Iteration: %6d\r", iteration + 1);
 		debug("\n");
-		iterations++;
-
-		/*
-		 * Data line test: write a pattern to the first
-		 * location, write the 1's complement to a 'parking'
-		 * address (changes the state of the data bus so a
-		 * floating bus doesn't give a false OK), and then
-		 * read the value back. Note that we read it back
-		 * into a variable because the next time we read it,
-		 * it might be right (been there, tough to explain to
-		 * the quality guys why it prints a failure when the
-		 * "is" and "should be" are obviously the same in the
-		 * error message).
-		 *
-		 * Rather than exhaustively testing, we test some
-		 * patterns by shifting '1' bits through a field of
-		 * '0's and '0' bits through a field of '1's (i.e.
-		 * pattern and ~pattern).
-		 */
-		addr = start;
-		for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
-		    val = bitpattern[j];
-		    for(; val != 0; val <<= 1) {
-			*addr  = val;
-			*dummy  = ~val; /* clear the test data off of the bus */
-			readback = *addr;
-			if(readback != val) {
-			    printf ("FAILURE (data line): "
-				"expected %08lx, actual %08lx\n",
-					  val, readback);
-			    errs++;
-			    if (ctrlc()) {
-				putc ('\n');
-				return 1;
-			    }
-			}
-			*addr  = ~val;
-			*dummy  = val;
-			readback = *addr;
-			if(readback != ~val) {
-			    printf ("FAILURE (data line): "
-				"Is %08lx, should be %08lx\n",
-					readback, ~val);
-			    errs++;
-			    if (ctrlc()) {
-				putc ('\n');
-				return 1;
-			    }
-			}
-		    }
+		if (alt_test) {
+			errs = mem_test_alt(buf, start, end, dummy);
+		} else {
+			errs = mem_test_quick(buf, start, end, pattern,
+					      iteration);
 		}
-
-		/*
-		 * Based on code whose Original Author and Copyright
-		 * information follows: Copyright (c) 1998 by Michael
-		 * Barr. This software is placed into the public
-		 * domain and may be used for any purpose. However,
-		 * this notice must not be changed or removed and no
-		 * warranty is either expressed or implied by its
-		 * publication or distribution.
-		 */
-
-		/*
-		 * Address line test
-		 *
-		 * Description: Test the address bus wiring in a
-		 *              memory region by performing a walking
-		 *              1's test on the relevant bits of the
-		 *              address and checking for aliasing.
-		 *              This test will find single-bit
-		 *              address failures such as stuck-high,
-		 *              stuck-low, and shorted pins. The base
-		 *              address and size of the region are
-		 *              selected by the caller.
-		 *
-		 * Notes:	For best results, the selected base
-		 *              address should have enough LSB 0's to
-		 *              guarantee single address bit changes.
-		 *              For example, to test a 64-Kbyte
-		 *              region, select a base address on a
-		 *              64-Kbyte boundary. Also, select the
-		 *              region size as a power-of-two if at
-		 *              all possible.
-		 *
-		 * Returns:     0 if the test succeeds, 1 if the test fails.
-		 */
-		len = ((ulong)end - (ulong)start)/sizeof(vu_long);
-		pattern = (vu_long) 0xaaaaaaaa;
-		anti_pattern = (vu_long) 0x55555555;
-
-		debug("%s:%d: length = 0x%.8lx\n",
-			__FUNCTION__, __LINE__,
-			len);
-		/*
-		 * Write the default pattern at each of the
-		 * power-of-two offsets.
-		 */
-		for (offset = 1; offset < len; offset <<= 1) {
-			start[offset] = pattern;
-		}
-
-		/*
-		 * Check for address bits stuck high.
-		 */
-		test_offset = 0;
-		start[test_offset] = anti_pattern;
-
-		for (offset = 1; offset < len; offset <<= 1) {
-		    temp = start[offset];
-		    if (temp != pattern) {
-			printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
-				" expected 0x%.8lx, actual 0x%.8lx\n",
-				(ulong)&start[offset], pattern, temp);
-			errs++;
-			if (ctrlc()) {
-			    putc ('\n');
-			    return 1;
-			}
-		    }
-		}
-		start[test_offset] = pattern;
-		WATCHDOG_RESET();
-
-		/*
-		 * Check for addr bits stuck low or shorted.
-		 */
-		for (test_offset = 1; test_offset < len; test_offset <<= 1) {
-		    start[test_offset] = anti_pattern;
-
-		    for (offset = 1; offset < len; offset <<= 1) {
-			temp = start[offset];
-			if ((temp != pattern) && (offset != test_offset)) {
-			    printf ("\nFAILURE: Address bit stuck low or shorted @"
-				" 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
-				(ulong)&start[offset], pattern, temp);
-			    errs++;
-			    if (ctrlc()) {
-				putc ('\n');
-				return 1;
-			    }
-			}
-		    }
-		    start[test_offset] = pattern;
-		}
-
-		/*
-		 * Description: Test the integrity of a physical
-		 *		memory device by performing an
-		 *		increment/decrement test over the
-		 *		entire region. In the process every
-		 *		storage bit in the device is tested
-		 *		as a zero and a one. The base address
-		 *		and the size of the region are
-		 *		selected by the caller.
-		 *
-		 * Returns:     0 if the test succeeds, 1 if the test fails.
-		 */
-		num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
-
-		/*
-		 * Fill memory with a known pattern.
-		 */
-		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
-			WATCHDOG_RESET();
-			start[offset] = pattern;
-		}
-
-		/*
-		 * Check each location and invert it for the second pass.
-		 */
-		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
-		    WATCHDOG_RESET();
-		    temp = start[offset];
-		    if (temp != pattern) {
-			printf ("\nFAILURE (read/write) @ 0x%.8lx:"
-				" expected 0x%.8lx, actual 0x%.8lx)\n",
-				(ulong)&start[offset], pattern, temp);
-			errs++;
-			if (ctrlc()) {
-			    putc ('\n');
-			    return 1;
-			}
-		    }
-
-		    anti_pattern = ~pattern;
-		    start[offset] = anti_pattern;
-		}
-
-		/*
-		 * Check each location for the inverted pattern and zero it.
-		 */
-		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
-		    WATCHDOG_RESET();
-		    anti_pattern = ~pattern;
-		    temp = start[offset];
-		    if (temp != anti_pattern) {
-			printf ("\nFAILURE (read/write): @ 0x%.8lx:"
-				" expected 0x%.8lx, actual 0x%.8lx)\n",
-				(ulong)&start[offset], anti_pattern, temp);
-			errs++;
-			if (ctrlc()) {
-			    putc ('\n');
-			    return 1;
-			}
-		    }
-		    start[offset] = 0;
-		}
+		if (errs == -1UL)
+			break;
 	}
 
-#else /* The original, quickie test */
-	incr = 1;
-	for (;;) {
-		if (ctrlc()) {
-			putc ('\n');
-			return 1;
-		}
+	/*
+	 * Work-around for eldk-4.2 which gives this warning if we try to
+	 * case in the unmap_sysmem() call:
+	 * warning: initialization discards qualifiers from pointer target type
+	 */
+	{
+		void *vbuf = (void *)buf;
+		void *vdummy = (void *)dummy;
 
-		if (iteration_limit && iterations > iteration_limit) {
-			printf("Tested %d iteration(s) with %lu errors.\n",
-				iterations-1, errs);
-			return errs != 0;
-		}
-		++iterations;
-
-		printf ("\rPattern %08lX  Writing..."
-			"%12s"
-			"\b\b\b\b\b\b\b\b\b\b",
-			pattern, "");
-
-		for (addr=start,val=pattern; addr<end; addr++) {
-			WATCHDOG_RESET();
-			*addr = val;
-			val  += incr;
-		}
-
-		puts ("Reading...");
-
-		for (addr=start,val=pattern; addr<end; addr++) {
-			WATCHDOG_RESET();
-			readback = *addr;
-			if (readback != val) {
-				printf ("\nMem error @ 0x%08X: "
-					"found %08lX, expected %08lX\n",
-					(uint)(uintptr_t)addr, readback, val);
-				errs++;
-				if (ctrlc()) {
-					putc ('\n');
-					return 1;
-				}
-			}
-			val += incr;
-		}
-
-		/*
-		 * Flip the pattern each time to make lots of zeros and
-		 * then, the next time, lots of ones.  We decrement
-		 * the "negative" patterns and increment the "positive"
-		 * patterns to preserve this feature.
-		 */
-		if(pattern & 0x80000000) {
-			pattern = -pattern;	/* complement & increment */
-		}
-		else {
-			pattern = ~pattern;
-		}
-		incr = -incr;
+		unmap_sysmem(vbuf);
+		unmap_sysmem(vdummy);
 	}
-#endif
-	return 0;	/* not reached */
+
+	if (errs == -1UL) {
+		/* Memory test was aborted - write a newline to finish off */
+		putc('\n');
+		ret = 1;
+	} else {
+		printf("Tested %d iteration(s) with %lu errors.\n",
+			iteration, errs);
+		ret = errs != 0;
+	}
+
+	return ret;	/* not reached */
 }
 
 
@@ -962,6 +1015,7 @@
 {
 	ulong	addr, i;
 	int	nbytes, size;
+	void *ptr = NULL;
 
 	if (argc != 2)
 		return CMD_RET_USAGE;
@@ -1006,13 +1060,14 @@
 	 * the next value.  A non-converted value exits.
 	 */
 	do {
+		ptr = map_sysmem(addr, size);
 		printf("%08lx:", addr);
 		if (size == 4)
-			printf(" %08x", *((uint   *)addr));
+			printf(" %08x", *((uint *)ptr));
 		else if (size == 2)
-			printf(" %04x", *((ushort *)addr));
+			printf(" %04x", *((ushort *)ptr));
 		else
-			printf(" %02x", *((u_char *)addr));
+			printf(" %02x", *((u_char *)ptr));
 
 		nbytes = readline (" ? ");
 		if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
@@ -1042,16 +1097,18 @@
 				reset_cmd_timeout();
 #endif
 				if (size == 4)
-					*((uint   *)addr) = i;
+					*((uint *)ptr) = i;
 				else if (size == 2)
-					*((ushort *)addr) = i;
+					*((ushort *)ptr) = i;
 				else
-					*((u_char *)addr) = i;
+					*((u_char *)ptr) = i;
 				if (incrflag)
 					addr += size;
 			}
 		}
 	} while (nbytes);
+	if (ptr)
+		unmap_sysmem(ptr);
 
 	mm_last_addr = addr;
 	mm_last_size = size;
@@ -1060,89 +1117,27 @@
 
 #ifdef CONFIG_CMD_CRC32
 
-#ifndef CONFIG_CRC32_VERIFY
-
 static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong addr, length;
-	ulong crc;
-	ulong *ptr;
+	int flags = 0;
+	int ac;
+	char * const *av;
 
 	if (argc < 3)
 		return CMD_RET_USAGE;
 
-	addr = simple_strtoul (argv[1], NULL, 16);
-	addr += base_address;
-
-	length = simple_strtoul (argv[2], NULL, 16);
-
-	crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32);
-
-	printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
-			addr, addr + length - 1, crc);
-
-	if (argc > 3) {
-		ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
-		*ptr = crc;
-	}
-
-	return 0;
-}
-
-#else	/* CONFIG_CRC32_VERIFY */
-
-int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	ulong addr, length;
-	ulong crc;
-	ulong *ptr;
-	ulong vcrc;
-	int verify;
-	int ac;
-	char * const *av;
-
-	if (argc < 3) {
-usage:
-		return CMD_RET_USAGE;
-	}
-
 	av = argv + 1;
 	ac = argc - 1;
+#ifdef CONFIG_HASH_VERIFY
 	if (strcmp(*av, "-v") == 0) {
-		verify = 1;
+		flags |= HASH_FLAG_VERIFY;
 		av++;
 		ac--;
-		if (ac < 3)
-			goto usage;
-	} else
-		verify = 0;
-
-	addr = simple_strtoul(*av++, NULL, 16);
-	addr += base_address;
-	length = simple_strtoul(*av++, NULL, 16);
-
-	crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32);
-
-	if (!verify) {
-		printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
-				addr, addr + length - 1, crc);
-		if (ac > 2) {
-			ptr = (ulong *) simple_strtoul (*av++, NULL, 16);
-			*ptr = crc;
-		}
-	} else {
-		vcrc = simple_strtoul(*av++, NULL, 16);
-		if (vcrc != crc) {
-			printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n",
-					addr, addr + length - 1, crc, vcrc);
-			return 1;
-		}
 	}
+#endif
 
-	return 0;
-
+	return hash_command("crc32", flags, cmdtp, flag, ac, av);
 }
-#endif	/* CONFIG_CRC32_VERIFY */
 
 #endif
 
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 06fc171..0cfca0c 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -230,7 +230,6 @@
  */
 static void index_partitions(void)
 {
-	char buf[16];
 	u16 mtddevnum;
 	struct part_info *part;
 	struct list_head *dentry;
@@ -244,8 +243,7 @@
 			dev = list_entry(dentry, struct mtd_device, link);
 			if (dev == current_mtd_dev) {
 				mtddevnum += current_mtd_partnum;
-				sprintf(buf, "%d", mtddevnum);
-				setenv("mtddevnum", buf);
+				setenv_ulong("mtddevnum", mtddevnum);
 				break;
 			}
 			mtddevnum += dev->num_parts;
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 495610c..32348f3 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -373,7 +373,6 @@
 {
 	nand_info_t *nand = &nand_info[idx];
 	struct nand_chip *chip = nand->priv;
-	char buf[32];
 
 	printf("Device %d: ", idx);
 	if (chip->numchips > 1)
@@ -385,14 +384,9 @@
 	printf("  Erase size %8d b\n", nand->erasesize);
 
 	/* Set geometry info */
-	sprintf(buf, "%x", nand->writesize);
-	setenv("nand_writesize", buf);
-
-	sprintf(buf, "%x", nand->oobsize);
-	setenv("nand_oobsize", buf);
-
-	sprintf(buf, "%x", nand->erasesize);
-	setenv("nand_erasesize", buf);
+	setenv_hex("nand_writesize", nand->writesize);
+	setenv_hex("nand_oobsize", nand->oobsize);
+	setenv_hex("nand_erasesize", nand->erasesize);
 }
 
 static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 7633f0c..d646d90 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -295,17 +295,17 @@
 }
 
 /**
- * Set an environment variable to an address in hex
+ * Set an environment variable to an value in hex
  *
  * @param varname	Environmet variable to set
- * @param addr		Value to set it to
+ * @param value		Value to set it to
  * @return 0 if ok, 1 on error
  */
-int setenv_addr(const char *varname, const void *addr)
+int setenv_hex(const char *varname, ulong value)
 {
 	char str[17];
 
-	sprintf(str, "%lx", (uintptr_t)addr);
+	sprintf(str, "%lx", value);
 	return setenv(varname, str);
 }
 
@@ -891,8 +891,7 @@
 		envp->flags = ACTIVE_FLAG;
 #endif
 	}
-	sprintf(buf, "%zX", (size_t)(len + offsetof(env_t, data)));
-	setenv("filesize", buf);
+	setenv_hex("filesize", len + offsetof(env_t, data));
 
 	return 0;
 
diff --git a/common/cmd_reiser.c b/common/cmd_reiser.c
index e658618..717c7f6 100644
--- a/common/cmd_reiser.c
+++ b/common/cmd_reiser.c
@@ -100,7 +100,6 @@
 	ulong addr = 0, filelen;
 	disk_partition_t info;
 	block_dev_desc_t *dev_desc = NULL;
-	char buf [12];
 	unsigned long count;
 	char *addr_str;
 
@@ -175,8 +174,7 @@
 	load_addr = addr;
 
 	printf ("\n%ld bytes read\n", filelen);
-	sprintf(buf, "%lX", filelen);
-	setenv("filesize", buf);
+	setenv_hex("filesize", filelen);
 
 	return filelen;
 }
diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c
index 5a04295..7a38e94 100644
--- a/common/cmd_setexpr.c
+++ b/common/cmd_setexpr.c
@@ -53,7 +53,7 @@
 static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	ulong a, b;
-	char buf[16];
+	ulong value;
 	int w;
 
 	/* Validate arguments */
@@ -67,8 +67,7 @@
 	a = get_arg(argv[2], w);
 
 	if (argc == 3) {
-		sprintf(buf, "%lx", a);
-		setenv(argv[1], buf);
+		setenv_hex(argv[1], a);
 
 		return 0;
 	}
@@ -76,20 +75,36 @@
 	b = get_arg(argv[4], w);
 
 	switch (argv[3][0]) {
-	case '|': sprintf(buf, "%lx", (a | b)); break;
-	case '&': sprintf(buf, "%lx", (a & b)); break;
-	case '+': sprintf(buf, "%lx", (a + b)); break;
-	case '^': sprintf(buf, "%lx", (a ^ b)); break;
-	case '-': sprintf(buf, "%lx", (a - b)); break;
-	case '*': sprintf(buf, "%lx", (a * b)); break;
-	case '/': sprintf(buf, "%lx", (a / b)); break;
-	case '%': sprintf(buf, "%lx", (a % b)); break;
+	case '|':
+		value = a | b;
+		break;
+	case '&':
+		value = a & b;
+		break;
+	case '+':
+		value = a + b;
+		break;
+	case '^':
+		value = a ^ b;
+		break;
+	case '-':
+		value = a - b;
+		break;
+	case '*':
+		value = a * b;
+		break;
+	case '/':
+		value = a / b;
+		break;
+	case '%':
+		value = a % b;
+		break;
 	default:
 		printf("invalid op\n");
 		return 1;
 	}
 
-	setenv(argv[1], buf);
+	setenv_hex(argv[1], value);
 
 	return 0;
 }
diff --git a/common/cmd_sha1sum.c b/common/cmd_sha1sum.c
index fe927ab..9f08629 100644
--- a/common/cmd_sha1sum.c
+++ b/common/cmd_sha1sum.c
@@ -31,7 +31,7 @@
 
 int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int verify = 0;
+	int flags = HASH_FLAG_ENV;
 	int ac;
 	char * const *av;
 
@@ -42,13 +42,13 @@
 	ac = argc - 1;
 #ifdef CONFIG_SHA1SUM_VERIFY
 	if (strcmp(*av, "-v") == 0) {
-		verify = 1;
+		flags |= HASH_FLAG_VERIFY;
 		av++;
 		ac--;
 	}
 #endif
 
-	return hash_command("sha1", verify, cmdtp, flag, ac, av);
+	return hash_command("sha1", flags, cmdtp, flag, ac, av);
 }
 
 #ifdef CONFIG_SHA1SUM_VERIFY
diff --git a/common/cmd_unzip.c b/common/cmd_unzip.c
index 43ed791..7470c2b 100644
--- a/common/cmd_unzip.c
+++ b/common/cmd_unzip.c
@@ -28,7 +28,6 @@
 {
 	unsigned long src, dst;
 	unsigned long src_len = ~0UL, dst_len = ~0UL;
-	char buf[32];
 
 	switch (argc) {
 		case 4:
@@ -46,8 +45,7 @@
 		return 1;
 
 	printf("Uncompressed size: %ld = 0x%lX\n", src_len, src_len);
-	sprintf(buf, "%lX", src_len);
-	setenv("filesize", buf);
+	setenv_hex("filesize", src_len);
 
 	return 0;
 }
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index 42a7eba..ea0a26e 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -50,7 +50,6 @@
 	ulong		data, len, count;
 	int		verify;
 	int		part = 0;
-	char		pbuf[10];
 	image_header_t	*hdr;
 #if defined(CONFIG_FIT)
 	const char	*uname = NULL;
@@ -256,10 +255,8 @@
 		puts("OK\n");
 	}
 
-	sprintf(pbuf, "%8lx", data);
-	setenv("fileaddr", pbuf);
-	sprintf(pbuf, "%8lx", len);
-	setenv("filesize", pbuf);
+	setenv_hex("fileaddr", data);
+	setenv_hex("filesize", len);
 
 	return 0;
 }
diff --git a/common/cmd_zfs.c b/common/cmd_zfs.c
index 1df0c4d..900e977 100644
--- a/common/cmd_zfs.c
+++ b/common/cmd_zfs.c
@@ -129,8 +129,7 @@
 	load_addr = addr;
 
 	printf("%llu bytes read\n", zfile.size);
-	sprintf(buf, "%llX", zfile.size);
-	setenv("filesize", buf);
+	setenv_hex("filesize", zfile.size);
 
 	return 0;
 }
diff --git a/common/cmd_zip.c b/common/cmd_zip.c
index a73c86d..8607da8 100644
--- a/common/cmd_zip.c
+++ b/common/cmd_zip.c
@@ -28,7 +28,6 @@
 {
 	unsigned long src, dst;
 	unsigned long src_len, dst_len = ~0UL;
-	char buf[32];
 
 	switch (argc) {
 		case 5:
@@ -47,8 +46,7 @@
 		return 1;
 
 	printf("Compressed size: %ld = 0x%lX\n", dst_len, dst_len);
-	sprintf(buf, "%lX", dst_len);
-	setenv("filesize", buf);
+	setenv_hex("filesize", dst_len);
 
 	return 0;
 }
diff --git a/common/hash.c b/common/hash.c
index e3a6e43..f5badcb 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -28,49 +28,87 @@
 #include <hash.h>
 #include <sha1.h>
 #include <sha256.h>
+#include <asm/io.h>
 
 /*
  * These are the hash algorithms we support. Chips which support accelerated
- * crypto could perhaps add named version of these algorithms here.
+ * crypto could perhaps add named version of these algorithms here. Note that
+ * algorithm names must be in lower case.
  */
 static struct hash_algo hash_algo[] = {
-#ifdef CONFIG_SHA1
+	/*
+	 * This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise
+	 * it bloats the code for boards which use SHA1 but not the 'hash'
+	 * or 'sha1sum' commands.
+	 */
+#ifdef CONFIG_CMD_SHA1SUM
 	{
-		"SHA1",
+		"sha1",
 		SHA1_SUM_LEN,
 		sha1_csum_wd,
 		CHUNKSZ_SHA1,
 	},
+#define MULTI_HASH
 #endif
 #ifdef CONFIG_SHA256
 	{
-		"SHA256",
+		"sha256",
 		SHA256_SUM_LEN,
 		sha256_csum_wd,
 		CHUNKSZ_SHA256,
 	},
+#define MULTI_HASH
 #endif
+	{
+		"crc32",
+		4,
+		crc32_wd_buf,
+		CHUNKSZ_CRC32,
+	},
 };
 
+#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH)
+#define MULTI_HASH
+#endif
+
+/* Try to minimize code size for boards that don't want much hashing */
+#ifdef MULTI_HASH
+#define multi_hash()	1
+#else
+#define multi_hash()	0
+#endif
+
 /**
  * store_result: Store the resulting sum to an address or variable
  *
  * @algo:		Hash algorithm being used
  * @sum:		Hash digest (algo->digest_size bytes)
  * @dest:		Destination, interpreted as a hex address if it starts
- *			with * or otherwise as an environment variable.
+ *			with * (or allow_env_vars is 0) or otherwise as an
+ *			environment variable.
+ * @allow_env_vars:	non-zero to permit storing the result to an
+ *			variable environment
  */
 static void store_result(struct hash_algo *algo, const u8 *sum,
-			 const char *dest)
+			 const char *dest, int allow_env_vars)
 {
 	unsigned int i;
+	int env_var = 0;
 
-	if (*dest == '*') {
-		u8 *ptr;
+	/*
+	 * If environment variables are allowed, then we assume that 'dest'
+	 * is an environment variable, unless it starts with *, in which
+	 * case we assume it is an address. If not allowed, it is always an
+	 * address. This is to support the crc32 command.
+	 */
+	if (allow_env_vars) {
+		if (*dest == '*')
+			dest++;
+		else
+			env_var = 1;
+	}
 
-		ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16);
-		memcpy(ptr, sum, algo->digest_size);
-	} else {
+	if (env_var) {
 		char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];
 		char *str_ptr = str_output;
 
@@ -80,6 +118,14 @@
 		}
 		str_ptr = '\0';
 		setenv(dest, str_output);
+	} else {
+		ulong addr;
+		void *buf;
+
+		addr = simple_strtoul(dest, NULL, 16);
+		buf = map_sysmem(addr, algo->digest_size);
+		memcpy(buf, sum, algo->digest_size);
+		unmap_sysmem(buf);
 	}
 }
 
@@ -94,15 +140,31 @@
  *			Otherwise we assume it is an environment variable, and
  *			look up its value (it must contain a hex digest).
  * @vsum:		Returns binary digest value (algo->digest_size bytes)
+ * @allow_env_vars:	non-zero to permit storing the result to an environment
+ *			variable. If 0 then verify_str is assumed to be an
+ *			address, and the * prefix is not expected.
  * @return 0 if ok, non-zero on error
  */
-static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum)
+static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum,
+			    int allow_env_vars)
 {
-	if (*verify_str == '*') {
-		u8 *ptr;
+	int env_var = 0;
 
-		ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
-		memcpy(vsum, ptr, algo->digest_size);
+	/* See comment above in store_result() */
+	if (allow_env_vars) {
+		if (*verify_str == '*')
+			verify_str++;
+		else
+			env_var = 1;
+	}
+
+	if (env_var) {
+		ulong addr;
+		void *buf;
+
+		addr = simple_strtoul(verify_str, NULL, 16);
+		buf = map_sysmem(addr, algo->digest_size);
+		memcpy(vsum, buf, algo->digest_size);
 	} else {
 		unsigned int i;
 		char *vsum_str;
@@ -141,7 +203,7 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
-		if (!strcasecmp(name, hash_algo[i].name))
+		if (!strcmp(name, hash_algo[i].name))
 			return &hash_algo[i];
 	}
 
@@ -158,63 +220,87 @@
 		printf("%02x", output[i]);
 }
 
-int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
+int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 		 int argc, char * const argv[])
 {
-	struct hash_algo *algo;
 	ulong addr, len;
-	u8 output[HASH_MAX_DIGEST_SIZE];
-	u8 vsum[HASH_MAX_DIGEST_SIZE];
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	algo = find_hash_algo(algo_name);
-	if (!algo) {
-		printf("Unknown hash algorithm '%s'\n", algo_name);
-		return CMD_RET_USAGE;
-	}
 	addr = simple_strtoul(*argv++, NULL, 16);
 	len = simple_strtoul(*argv++, NULL, 16);
-	argc -= 2;
 
-	if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
-		puts("HASH_MAX_DIGEST_SIZE exceeded\n");
-		return 1;
-	}
+	if (multi_hash()) {
+		struct hash_algo *algo;
+		u8 output[HASH_MAX_DIGEST_SIZE];
+		u8 vsum[HASH_MAX_DIGEST_SIZE];
+		void *buf;
 
-	algo->hash_func_ws((const unsigned char *)addr, len, output,
-			   algo->chunk_size);
-
-	/* Try to avoid code bloat when verify is not needed */
-#ifdef CONFIG_HASH_VERIFY
-	if (verify) {
-#else
-	if (0) {
-#endif
-		if (!argc)
+		algo = find_hash_algo(algo_name);
+		if (!algo) {
+			printf("Unknown hash algorithm '%s'\n", algo_name);
 			return CMD_RET_USAGE;
-		if (parse_verify_sum(algo, *argv, vsum)) {
-			printf("ERROR: %s does not contain a valid %s sum\n",
-				*argv, algo->name);
+		}
+		argc -= 2;
+
+		if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
+			puts("HASH_MAX_DIGEST_SIZE exceeded\n");
 			return 1;
 		}
-		if (memcmp(output, vsum, algo->digest_size) != 0) {
-			int i;
 
+		buf = map_sysmem(addr, len);
+		algo->hash_func_ws(buf, len, output, algo->chunk_size);
+		unmap_sysmem(buf);
+
+		/* Try to avoid code bloat when verify is not needed */
+#ifdef CONFIG_HASH_VERIFY
+		if (flags & HASH_FLAG_VERIFY) {
+#else
+		if (0) {
+#endif
+			if (!argc)
+				return CMD_RET_USAGE;
+			if (parse_verify_sum(algo, *argv, vsum,
+					flags & HASH_FLAG_ENV)) {
+				printf("ERROR: %s does not contain a valid "
+					"%s sum\n", *argv, algo->name);
+				return 1;
+			}
+			if (memcmp(output, vsum, algo->digest_size) != 0) {
+				int i;
+
+				show_hash(algo, addr, len, output);
+				printf(" != ");
+				for (i = 0; i < algo->digest_size; i++)
+					printf("%02x", vsum[i]);
+				puts(" ** ERROR **\n");
+				return 1;
+			}
+		} else {
 			show_hash(algo, addr, len, output);
-			printf(" != ");
-			for (i = 0; i < algo->digest_size; i++)
-				printf("%02x", vsum[i]);
-			puts(" ** ERROR **\n");
-			return 1;
-		}
-	} else {
-		show_hash(algo, addr, len, output);
-		printf("\n");
+			printf("\n");
 
-		if (argc)
-			store_result(algo, output, *argv);
+			if (argc) {
+				store_result(algo, output, *argv,
+					flags & HASH_FLAG_ENV);
+			}
+		}
+
+	/* Horrible code size hack for boards that just want crc32 */
+	} else {
+		ulong crc;
+		ulong *ptr;
+
+		crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32);
+
+		printf("CRC32 for %08lx ... %08lx ==> %08lx\n",
+				addr, addr + len - 1, crc);
+
+		if (argc > 3) {
+			ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
+			*ptr = crc;
+		}
 	}
 
 	return 0;
diff --git a/common/image.c b/common/image.c
index ae1a9d3..6afbb40 100644
--- a/common/image.c
+++ b/common/image.c
@@ -74,6 +74,8 @@
 #include <image.h>
 #endif /* !USE_HOSTCC*/
 
+#include <u-boot/crc.h>
+
 static const table_entry_t uimage_arch[] = {
 	{	IH_ARCH_INVALID,	NULL,		"Invalid ARCH",	},
 	{	IH_ARCH_ALPHA,		"alpha",	"Alpha",	},
@@ -160,8 +162,6 @@
 	{	-1,		"",		"",			},
 };
 
-uint32_t crc32(uint32_t, const unsigned char *, uint);
-uint32_t crc32_wd(uint32_t, const unsigned char *, uint, uint);
 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
 static void genimg_print_time(time_t timestamp);
 #endif
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index 49c74c2..8d70586 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -362,7 +362,6 @@
 int fm_init_common(int index, struct ccsr_fman *reg)
 {
 	int rc;
-	char env_addr[32];
 #if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR)
 	void *addr = (void *)CONFIG_SYS_QE_FMAN_FW_ADDR;
 #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND)
@@ -416,8 +415,7 @@
 	rc = fman_upload_firmware(index, &reg->fm_imem, addr);
 	if (rc)
 		return rc;
-	sprintf(env_addr, "0x%lx", (long unsigned int)addr);
-	setenv("fman_ucode", env_addr);
+	setenv_addr("fman_ucode", addr);
 
 	fm_init_muram(index, &reg->muram);
 	fm_init_qmi(&reg->fm_qmi_common);
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index cb19401..b73520c 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -30,6 +30,19 @@
 #include <serial.h>
 #include <linux/compiler.h>
 
+/*
+ *
+ *   serial_buf: A buffer that holds keyboard characters for the
+ *		 Sandbox U-boot.
+ *
+ * invariants:
+ *   serial_buf_write		 == serial_buf_read -> empty buffer
+ *   (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer
+ */
+static char serial_buf[16];
+static unsigned int serial_buf_write;
+static unsigned int serial_buf_read;
+
 static int sandbox_serial_init(void)
 {
 	os_tty_raw(0);
@@ -50,18 +63,37 @@
 	os_write(1, str, strlen(str));
 }
 
-static int sandbox_serial_getc(void)
+static unsigned int increment_buffer_index(unsigned int index)
 {
-	char buf;
-	ssize_t count;
-
-	count = os_read(0, &buf, 1);
-	return count == 1 ? buf : 0;
+	return (index + 1) % ARRAY_SIZE(serial_buf);
 }
 
 static int sandbox_serial_tstc(void)
 {
-	return 0;
+	const unsigned int next_index =
+		increment_buffer_index(serial_buf_write);
+	ssize_t count;
+
+	os_usleep(100);
+	if (next_index == serial_buf_read)
+		return 1;	/* buffer full */
+
+	count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
+	if (count == 1)
+		serial_buf_write = next_index;
+	return serial_buf_write != serial_buf_read;
+}
+
+static int sandbox_serial_getc(void)
+{
+	int result;
+
+	while (!sandbox_serial_tstc())
+		;	/* buffer empty */
+
+	result = serial_buf[serial_buf_read];
+	serial_buf_read = increment_buffer_index(serial_buf_read);
+	return result;
 }
 
 static struct serial_device sandbox_serial_drv = {
diff --git a/fs/fs.c b/fs/fs.c
index 023e7ef..2c9f2c5 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -256,7 +256,6 @@
 	unsigned long bytes;
 	unsigned long pos;
 	int len_read;
-	char buf[12];
 	unsigned long time;
 
 	if (argc < 2)
@@ -308,8 +307,7 @@
 	}
 	puts("\n");
 
-	sprintf(buf, "0x%x", len_read);
-	setenv("filesize", buf);
+	setenv_hex("filesize", len_read);
 
 	return 0;
 }
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 44be3f5..273c0a9 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -687,7 +687,6 @@
 	int i;
 	int count;
 	int last_block_size = 0;
-	char buf [10];
 
 	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
 	/* ubifs_findfile will resolve symlinks, so we know that we get
@@ -740,8 +739,7 @@
 	if (err)
 		printf("Error reading file '%s'\n", filename);
 	else {
-	        sprintf(buf, "%X", size);
-		setenv("filesize", buf);
+		setenv_hex("filesize", size);
 		printf("Done\n");
 	}
 
diff --git a/include/common.h b/include/common.h
index 4ad17ea..6d52924 100644
--- a/include/common.h
+++ b/include/common.h
@@ -270,7 +270,8 @@
 phys_size_t initdram (int);
 int	display_options (void);
 void	print_size(unsigned long long, const char *);
-int	print_buffer (ulong addr, void* data, uint width, uint count, uint linelen);
+int print_buffer(ulong addr, const void *data, uint width, uint count,
+		 uint linelen);
 
 /* common/main.c */
 void	main_loop	(void);
@@ -357,7 +358,19 @@
 int	saveenv	     (void);
 int	setenv	     (const char *, const char *);
 int setenv_ulong(const char *varname, ulong value);
-int setenv_addr(const char *varname, const void *addr);
+int setenv_hex(const char *varname, ulong value);
+/**
+ * setenv_addr - Set an environment variable to an address in hex
+ *
+ * @varname:	Environmet variable to set
+ * @addr:	Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+static inline int setenv_addr(const char *varname, const void *addr)
+{
+	return setenv_hex(varname, (ulong)addr);
+}
+
 #ifdef CONFIG_ARM
 # include <asm/mach-types.h>
 # include <asm/setup.h>
@@ -869,6 +882,18 @@
 int cpu_release(int nr, int argc, char * const argv[]);
 #endif
 
+/* Define a null map_sysmem() if the architecture doesn't use it */
+# ifndef CONFIG_ARCH_MAP_SYSMEM
+static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
+{
+	return (void *)(uintptr_t)paddr;
+}
+
+static inline void unmap_sysmem(const void *vaddr)
+{
+}
+# endif
+
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9c431bf..9f51a0b 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -63,8 +63,8 @@
 #define CONFIG_SYS_HZ			1000
 
 /* Memory things - we don't really want a memory test */
-#define CONFIG_SYS_LOAD_ADDR		0x10000000
-#define CONFIG_SYS_MEMTEST_START	0x10000000
+#define CONFIG_SYS_LOAD_ADDR		0x00000000
+#define CONFIG_SYS_MEMTEST_START	0x00100000
 #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + 0x1000)
 #define CONFIG_PHYS_64BIT
 
@@ -85,6 +85,11 @@
 #undef CONFIG_CMD_NET
 #undef CONFIG_CMD_NFS
 
+#define CONFIG_CMD_HASH
+#define CONFIG_HASH_VERIFY
+#define CONFIG_SHA1
+#define CONFIG_SHA256
+
 #define CONFIG_BOOTARGS ""
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
diff --git a/include/hash.h b/include/hash.h
index 34ba558..2dbbd9b 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -22,7 +22,7 @@
 #ifndef _HASH_H
 #define _HASH_H
 
-#ifdef CONFIG_SHA1SUM_VERIFY
+#if defined(CONFIG_SHA1SUM_VERIFY) || defined(CONFIG_CRC32_VERIFY)
 #define CONFIG_HASH_VERIFY
 #endif
 
@@ -51,19 +51,24 @@
  */
 #define HASH_MAX_DIGEST_SIZE	32
 
+enum {
+	HASH_FLAG_VERIFY	= 1 << 0,	/* Enable verify mode */
+	HASH_FLAG_ENV		= 1 << 1,	/* Allow env vars */
+};
+
 /**
  * hash_command: Process a hash command for a particular algorithm
  *
  * This common function is used to implement specific hash commands.
  *
- * @algo_name:		Hash algorithm being used
- * @verify:		Non-zero to enable verify mode
+ * @algo_name:		Hash algorithm being used (lower case!)
+ * @flags:		Flags value (HASH_FLAG_...)
  * @cmdtp:		Pointer to command table entry
  * @flag:		Some flags normally 0 (see CMD_FLAG_.. above)
  * @argc:		Number of arguments (arg 0 must be the command text)
  * @argv:		Arguments
  */
-int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
+int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 		 int argc, char * const argv[]);
 
 #endif
diff --git a/include/os.h b/include/os.h
index 699682a..c452d1b 100644
--- a/include/os.h
+++ b/include/os.h
@@ -40,6 +40,16 @@
 ssize_t os_read(int fd, void *buf, size_t count);
 
 /**
+ * Access to the OS read() system call with non-blocking access
+ *
+ * \param fd	File descriptor as returned by os_open()
+ * \param buf	Buffer to place data
+ * \param count	Number of bytes to read
+ * \return number of bytes read, or -1 on error
+ */
+ssize_t os_read_no_block(int fd, void *buf, size_t count);
+
+/**
  * Access to the OS write() system call
  *
  * \param fd	File descriptor as returned by os_open()
diff --git a/include/u-boot/crc.h b/include/u-boot/crc.h
index 07badbf..08e509e 100644
--- a/include/u-boot/crc.h
+++ b/include/u-boot/crc.h
@@ -30,4 +30,15 @@
 uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint);
 uint32_t crc32_no_comp (uint32_t, const unsigned char *, uint);
 
+/**
+ * crc32_wd_buf - Perform CRC32 on a buffer and return result in buffer
+ *
+ * @input:	Input buffer
+ * @ilen:	Input buffer length
+ * @output:	Place to put checksum result (4 bytes)
+ * @chunk_sz:	Trigger watchdog after processing this many bytes
+ */
+void crc32_wd_buf(const unsigned char *input, uint ilen,
+		    unsigned char *output, uint chunk_sz);
+
 #endif /* _UBOOT_CRC_H */
diff --git a/lib/crc32.c b/lib/crc32.c
index 27335a3..76205da 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -249,3 +249,12 @@
 
 	return crc;
 }
+
+void crc32_wd_buf(const unsigned char *input, unsigned int ilen,
+		unsigned char *output, unsigned int chunk_sz)
+{
+	uint32_t crc;
+
+	crc = crc32_wd(0, input, ilen, chunk_sz);
+	memcpy(output, &crc, sizeof(crc));
+}
diff --git a/lib/display_options.c b/lib/display_options.c
index 694d2f2..0339970 100644
--- a/lib/display_options.c
+++ b/lib/display_options.c
@@ -98,7 +98,8 @@
  */
 #define MAX_LINE_LENGTH_BYTES (64)
 #define DEFAULT_LINE_LENGTH_BYTES (16)
-int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen)
+int print_buffer(ulong addr, const void *data, uint width, uint count,
+		 uint linelen)
 {
 	/* linebuf as a union causes proper alignment */
 	union linebuf {
diff --git a/net/net.c b/net/net.c
index a40cde1..df94789 100644
--- a/net/net.c
+++ b/net/net.c
@@ -528,15 +528,11 @@
 		case NETLOOP_SUCCESS:
 			net_cleanup_loop();
 			if (NetBootFileXferSize > 0) {
-				char buf[20];
 				printf("Bytes transferred = %ld (%lx hex)\n",
 					NetBootFileXferSize,
 					NetBootFileXferSize);
-				sprintf(buf, "%lX", NetBootFileXferSize);
-				setenv("filesize", buf);
-
-				sprintf(buf, "%lX", (unsigned long)load_addr);
-				setenv("fileaddr", buf);
+				setenv_hex("filesize", NetBootFileXferSize);
+				setenv_hex("fileaddr", load_addr);
 			}
 			if (protocol != NETCONS)
 				eth_halt();