Merge branch 'master' of git://git.denx.de/u-boot-mpc5xxx
diff --git a/README b/README
index 862bb3e..0d37d56 100644
--- a/README
+++ b/README
@@ -930,6 +930,13 @@
 
 		XXX - this list needs to get updated!
 
+- Regular expression support:
+		CONFIG_REGEX
+                If this variable is defined, U-Boot is linked against
+                the SLRE (Super Light Regular Expression) library,
+                which adds regex support to some commands, as for
+                example "env grep" and "setexpr".
+
 - Device tree:
 		CONFIG_OF_CONTROL
 		If this variable is defined, U-Boot will use a device tree
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
index 7e70440..ed525e5 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
@@ -148,10 +148,3 @@
 	for (;;)
 		;
 }
-
-void hang(void) __attribute__ ((noreturn));
-void hang(void)
-{
-	for (;;)
-		;
-}
diff --git a/arch/arm/cpu/arm926ejs/spear/spl.c b/arch/arm/cpu/arm926ejs/spear/spl.c
index 48e6efb..0101c5d 100644
--- a/arch/arm/cpu/arm926ejs/spear/spl.c
+++ b/arch/arm/cpu/arm926ejs/spear/spl.c
@@ -31,13 +31,6 @@
 #include <asm/arch/spr_misc.h>
 #include <asm/arch/spr_syscntl.h>
 
-inline void hang(void)
-{
-	serial_puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
-
 static void ddr_clock_init(void)
 {
 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 0521178..09ab4ad 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -706,9 +706,3 @@
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;);
-}
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index 57e07df..ccf862a 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -120,11 +120,6 @@
 	return 0;
 }
 
-void hang(void)
-{
-	for (;;) ;
-}
-
 static int display_dram_config (void)
 {
 	int i;
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index 75b6c46..ccea3b9 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -432,17 +432,3 @@
 	for (;;)
 		main_loop();
 }
-
-void hang(void)
-{
-#ifdef CONFIG_STATUS_LED
-	status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF);
-	status_led_set(STATUS_LED_CRASH, STATUS_LED_BLINKING);
-#endif
-	puts("### ERROR ### Please RESET the board ###\n");
-	while (1)
-		/* If a JTAG emulator is hooked up, we'll automatically trigger
-		 * a breakpoint in it.  If one isn't, this is just a NOP.
-		 */
-		asm("emuexcpt;");
-}
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index adaccfe..b2e3068 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -663,10 +663,3 @@
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-
-void hang(void)
-{
-	puts ("### ERROR ### Please RESET the board ###\n");
-	for (;;);
-}
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 815fb5a..bb40243 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -74,15 +74,15 @@
 {
 	bd_t *bd;
 	init_fnc_t **init_fnc_ptr;
-	gd = (gd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
-	bd = (bd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
+	gd = (gd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
+	bd = (bd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET
 						- GENERATED_BD_INFO_SIZE);
 #if defined(CONFIG_CMD_FLASH)
 	ulong flash_size = 0;
 #endif
 	asm ("nop");	/* FIXME gd is not initialize - wait */
-	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
-	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
+	memset((void *)bd, 0, GENERATED_BD_INFO_SIZE);
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
@@ -108,57 +108,55 @@
 	 * aka CONFIG_SYS_MONITOR_BASE - Note there is no need for reloc_off
 	 * as our monitory code is run from SDRAM
 	 */
-	mem_malloc_init (CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
 
 	serial_initialize();
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		WATCHDOG_RESET ();
-		if ((*init_fnc_ptr) () != 0) {
-			hang ();
-		}
+		WATCHDOG_RESET();
+		if ((*init_fnc_ptr) () != 0)
+			hang();
 	}
 
 #ifdef CONFIG_OF_CONTROL
 	/* For now, put this check after the console is ready */
-	if (fdtdec_prepare_fdt()) {
-		panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
-			"doc/README.fdt-control");
-	} else
+	if (fdtdec_prepare_fdt())
+		panic("** No FDT - please see doc/README.fdt-control");
+	else
 		printf("DTB: 0x%x\n", (u32)gd->fdt_blob);
 #endif
 
-	puts ("SDRAM :\n");
-	printf ("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
-	printf ("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
-	printf ("\tU-Boot Start:0x%08x\n", CONFIG_SYS_TEXT_BASE);
+	puts("SDRAM :\n");
+	printf("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
+	printf("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
+	printf("\tU-Boot Start:0x%08x\n", CONFIG_SYS_TEXT_BASE);
 
 #if defined(CONFIG_CMD_FLASH)
-	puts ("Flash: ");
+	puts("Flash: ");
 	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
 	flash_size = flash_init();
 	if (bd->bi_flashstart && flash_size > 0) {
 # ifdef CONFIG_SYS_FLASH_CHECKSUM
-		print_size (flash_size, "");
+		print_size(flash_size, "");
 		/*
 		 * Compute and print flash CRC if flashchecksum is set to 'y'
 		 *
 		 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
 		 */
 		if (getenv_yesno("flashchecksum") == 1) {
-			printf ("  CRC: %08X",
-				crc32(0, (const u8 *)bd->bi_flashstart,
-							flash_size)
+			printf("  CRC: %08X",
+			       crc32(0, (const u8 *)bd->bi_flashstart,
+				     flash_size)
 			);
 		}
-		putc ('\n');
+		putc('\n');
 # else	/* !CONFIG_SYS_FLASH_CHECKSUM */
-		print_size (flash_size, "\n");
+		print_size(flash_size, "\n");
 # endif /* CONFIG_SYS_FLASH_CHECKSUM */
 		bd->bi_flashsize = flash_size;
 		bd->bi_flashoffset = bd->bi_flashstart + flash_size;
 	} else {
-		puts ("Flash init FAILED");
+		puts("Flash init FAILED");
 		bd->bi_flashstart = 0;
 		bd->bi_flashsize = 0;
 		bd->bi_flashoffset = 0;
@@ -166,10 +164,10 @@
 #endif
 
 	/* relocate environment function pointers etc. */
-	env_relocate ();
+	env_relocate();
 
 	/* Initialize stdio devices */
-	stdio_init ();
+	stdio_init();
 
 	/* Initialize the jump table for applications */
 	jumptable_init();
@@ -193,13 +191,7 @@
 
 	/* main_loop */
 	for (;;) {
-		WATCHDOG_RESET ();
-		main_loop ();
+		WATCHDOG_RESET();
+		main_loop();
 	}
 }
-
-void hang (void)
-{
-	puts ("### ERROR ### Please RESET the board ###\n");
-	for (;;) ;
-}
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index f19f198..fac7915 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -344,10 +344,3 @@
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index a7d27fc..57af1be 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -404,10 +404,3 @@
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 1e495d4..f430ef0 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -64,7 +64,6 @@
  ***********************************************************************/
 
 init_fnc_t *init_sequence[] = {
-
 #if defined(CONFIG_BOARD_EARLY_INIT_F)
 	board_early_init_f,	/* Call board-specific init code early.*/
 #endif
@@ -83,7 +82,7 @@
 
 
 /***********************************************************************/
-void board_init (void)
+void board_init(void)
 {
 	bd_t *bd;
 	init_fnc_t **init_fnc_ptr;
@@ -93,7 +92,7 @@
 	/* Pointer is writable since we allocated a register for it. */
 	gd = &gd_data;
 	/* compiler optimization barrier needed for GCC >= 3.4 */
-	__asm__ __volatile__("": : :"memory");
+	__asm__ __volatile__("" : : : "memory");
 
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
@@ -106,25 +105,24 @@
 	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
 #endif
 #if	defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
-	bd->bi_sramstart= CONFIG_SYS_SRAM_BASE;
+	bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;
 	bd->bi_sramsize	= CONFIG_SYS_SRAM_SIZE;
 #endif
 	bd->bi_baudrate	= CONFIG_BAUDRATE;
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		WATCHDOG_RESET ();
-		if ((*init_fnc_ptr) () != 0) {
-			hang ();
-		}
+		WATCHDOG_RESET();
+		if ((*init_fnc_ptr) () != 0)
+			hang();
 	}
 
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 
 	/* The Malloc area is immediately below the monitor copy in RAM */
 	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
 
 #ifndef CONFIG_SYS_NO_FLASH
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 	bd->bi_flashsize = flash_init();
 #endif
 
@@ -138,39 +136,29 @@
 	mmc_initialize(bd);
 #endif
 
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 	env_relocate();
 
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 	stdio_init();
 	jumptable_init();
 	console_init_r();
 
-	WATCHDOG_RESET ();
-	interrupt_init ();
+	WATCHDOG_RESET();
+	interrupt_init();
 
 #if defined(CONFIG_BOARD_LATE_INIT)
-	board_late_init ();
+	board_late_init();
 #endif
 
 #if defined(CONFIG_CMD_NET)
-	puts ("Net:   ");
-	eth_initialize (bd);
+	puts("Net:   ");
+	eth_initialize(bd);
 #endif
 
 	/* main_loop */
 	for (;;) {
-		WATCHDOG_RESET ();
-		main_loop ();
+		WATCHDOG_RESET();
+		main_loop();
 	}
 }
-
-
-/***********************************************************************/
-
-void hang (void)
-{
-	disable_interrupts ();
-	puts("### ERROR ### Please reset board ###\n");
-	for (;;);
-}
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..630e45f 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -154,15 +154,3 @@
 		main_loop();
 	}
 }
-
-
-/***********************************************************************/
-
-void hang(void)
-{
-	disable_interrupts();
-	puts("### ERROR ### Please reset board ###\n");
-
-	for (;;)
-		;
-}
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 422b4a3..41b2294 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -1050,15 +1050,6 @@
 	/* NOTREACHED - no way out of command loop except booting */
 }
 
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
-	for (;;)
-		;
-}
-
-
 #if 0	/* We could use plain global data, but the resulting code is bigger */
 /*
  * Pointer to initial global data area
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 6e43acf..0789ed0 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -200,12 +200,3 @@
 		main_loop();
 	}
 }
-
-/***********************************************************************/
-
-void hang(void)
-{
-	puts("Board ERROR\n");
-	for (;;)
-		;
-}
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 79fb4c8..fbc535f 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -411,13 +411,4 @@
 
 }
 
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-#ifdef CONFIG_SHOW_BOOT_PROGRESS
-	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
-#endif
-	for (;;) ;
-}
-
 /************************************************************************/
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index f372898..228c2c8 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -264,10 +264,3 @@
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
diff --git a/board/freescale/common/sdhc_boot.c b/board/freescale/common/sdhc_boot.c
index e4323181..fd0e910 100644
--- a/board/freescale/common/sdhc_boot.c
+++ b/board/freescale/common/sdhc_boot.c
@@ -32,7 +32,7 @@
 #define ESDHC_BOOT_IMAGE_SIZE	0x48
 #define ESDHC_BOOT_IMAGE_ADDR	0x50
 
-int mmc_get_env_addr(struct mmc *mmc, u32 *env_addr)
+int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
 {
 	u8 *tmp_buf;
 	u32 blklen, code_offset, code_len, n;
diff --git a/common/board_f.c b/common/board_f.c
index 3a6638f..32e59fa 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -1087,13 +1087,3 @@
 	hang();
 }
 #endif /* CONFIG_X86 */
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-#ifdef CONFIG_SANDBOX
-	os_exit(0);
-#else
-	for (;;);
-#endif
-}
diff --git a/common/cmd_ide.c b/common/cmd_ide.c
index 0105bdb..78b4aa7 100644
--- a/common/cmd_ide.c
+++ b/common/cmd_ide.c
@@ -455,6 +455,8 @@
 		ide_dev_desc[i].dev = i;
 		ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
 		ide_dev_desc[i].blksz = 0;
+		ide_dev_desc[i].log2blksz =
+			LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
 		ide_dev_desc[i].lba = 0;
 		ide_dev_desc[i].block_read = ide_read;
 		ide_dev_desc[i].block_write = ide_write;
@@ -806,6 +808,7 @@
 	/* assuming HD */
 	dev_desc->type = DEV_TYPE_HARDDISK;
 	dev_desc->blksz = ATA_BLOCKSIZE;
+	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 	dev_desc->lun = 0;	/* just to fill something in... */
 
 #if 0				/* only used to test the powersaving mode,
@@ -1448,6 +1451,7 @@
 	dev_desc->lun = 0;
 	dev_desc->lba = 0;
 	dev_desc->blksz = 0;
+	dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
 	dev_desc->type = iobuf[0] & 0x1f;
 
 	if ((iobuf[1] & 0x80) == 0x80)
@@ -1492,6 +1496,7 @@
 	dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
 		((unsigned long) iobuf[5] << 16) +
 		((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
+	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 #ifdef CONFIG_LBA48
 	/* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
 	dev_desc->lba48 = 0;
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index d893aa1..f8dc38e 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000-2010
+ * (C) Copyright 2000-2013
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
@@ -164,31 +164,57 @@
 static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 		       int argc, char * const argv[])
 {
-	ENTRY *match;
-	unsigned char matched[env_htab.size / 8];
-	int rcode = 1, arg = 1, idx;
+	char *res = NULL;
+	int len, grep_how, grep_what;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
+	grep_how  = H_MATCH_SUBSTR;	/* default: substring search	*/
+	grep_what = H_MATCH_BOTH;	/* default: grep names and values */
+
-	memset(matched, 0, env_htab.size / 8);
+	while (argc > 1 && **(argv + 1) == '-') {
+		char *arg = *++argv;
 
-	while (arg <= argc) {
-		idx = 0;
-		while ((idx = hstrstr_r(argv[arg], idx, &match, &env_htab))) {
-			if (!(matched[idx / 8] & (1 << (idx & 7)))) {
-				puts(match->key);
-				puts("=");
-				puts(match->data);
-				puts("\n");
+		--argc;
+		while (*++arg) {
+			switch (*arg) {
+#ifdef CONFIG_REGEX
+			case 'e':		/* use regex matching */
+				grep_how  = H_MATCH_REGEX;
+				break;
+#endif
+			case 'n':		/* grep for name */
+				grep_what = H_MATCH_KEY;
+				break;
+			case 'v':		/* grep for value */
+				grep_what = H_MATCH_DATA;
+				break;
+			case 'b':		/* grep for both */
+				grep_what = H_MATCH_BOTH;
+				break;
+			case '-':
+				goto DONE;
+			default:
+				return CMD_RET_USAGE;
 			}
-			matched[idx / 8] |= 1 << (idx & 7);
-			rcode = 0;
 		}
-		arg++;
 	}
 
-	return rcode;
+DONE:
+	len = hexport_r(&env_htab, '\n',
+			flag | grep_what | grep_how,
+			&res, 0, argc, argv);
+
+	if (len > 0) {
+		puts(res);
+		free(res);
+	}
+
+	if (len < 2)
+		return 1;
+
+	return 0;
 }
 #endif
 #endif /* CONFIG_SPL_BUILD */
@@ -892,7 +918,9 @@
 	argv++;
 
 	if (sep) {		/* export as text file */
-		len = hexport_r(&env_htab, sep, 0, &addr, size, argc, argv);
+		len = hexport_r(&env_htab, sep,
+				H_MATCH_KEY | H_MATCH_IDENT,
+				&addr, size, argc, argv);
 		if (len < 0) {
 			error("Cannot export environment: errno = %d\n", errno);
 			return 1;
@@ -910,7 +938,9 @@
 	else			/* export as raw binary data */
 		res = addr;
 
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, argc, argv);
+	len = hexport_r(&env_htab, '\0',
+			H_MATCH_KEY | H_MATCH_IDENT,
+			&res, ENV_SIZE, argc, argv);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
@@ -1129,7 +1159,11 @@
 	"env flags - print variables that have non-default flags\n"
 #endif
 #if defined(CONFIG_CMD_GREPENV)
-	"env grep string [...] - search environment\n"
+#ifdef CONFIG_REGEX
+	"env grep [-e] [-n | -v | -b] string [...] - search environment\n"
+#else
+	"env grep [-n | -v | -b] string [...] - search environment\n"
+#endif
 #endif
 #if defined(CONFIG_CMD_IMPORTENV)
 	"env import [-d] [-t | -b | -c] addr [size] - import environment\n"
@@ -1176,8 +1210,17 @@
 U_BOOT_CMD_COMPLETE(
 	grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
 	"search environment variables",
-	"string ...\n"
-	"    - list environment name=value pairs matching 'string'",
+#ifdef CONFIG_REGEX
+	"[-e] [-n | -v | -b] string ...\n"
+#else
+	"[-n | -v | -b] string ...\n"
+#endif
+	"    - list environment name=value pairs matching 'string'\n"
+#ifdef CONFIG_REGEX
+	"      \"-e\": enable regular expressions;\n"
+#endif
+	"      \"-n\": search variable names; \"-v\": search values;\n"
+	"      \"-b\": search both names and values (default)",
 	var_complete
 );
 #endif
diff --git a/common/cmd_sata.c b/common/cmd_sata.c
index 8d57285..5a57a37 100644
--- a/common/cmd_sata.c
+++ b/common/cmd_sata.c
@@ -44,6 +44,7 @@
 		sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
 		sata_dev_desc[i].lba = 0;
 		sata_dev_desc[i].blksz = 512;
+		sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
 		sata_dev_desc[i].block_read = sata_read;
 		sata_dev_desc[i].block_write = sata_write;
 
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c
index 13b3d99..294d9f5 100644
--- a/common/cmd_scsi.c
+++ b/common/cmd_scsi.c
@@ -106,6 +106,8 @@
 		scsi_dev_desc[i].lun=0xff;
 		scsi_dev_desc[i].lba=0;
 		scsi_dev_desc[i].blksz=0;
+		scsi_dev_desc[i].log2blksz =
+			LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz));
 		scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN;
 		scsi_dev_desc[i].vendor[0]=0;
 		scsi_dev_desc[i].product[0]=0;
@@ -166,6 +168,8 @@
 			}
 			scsi_dev_desc[scsi_max_devs].lba=capacity;
 			scsi_dev_desc[scsi_max_devs].blksz=blksz;
+			scsi_dev_desc[scsi_max_devs].log2blksz =
+				LOG2(scsi_dev_desc[scsi_max_devs].blksz);
 			scsi_dev_desc[scsi_max_devs].type=perq;
 			init_part(&scsi_dev_desc[scsi_max_devs]);
 removable:
diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c
index 7a38e94..93cb255 100644
--- a/common/cmd_setexpr.c
+++ b/common/cmd_setexpr.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2013 Wolfgang Denk <wd@denx.de>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -50,28 +51,295 @@
 	}
 }
 
+#ifdef CONFIG_REGEX
+
+#include <slre.h>
+
+#define SLRE_BUFSZ	16384
+#define SLRE_PATSZ	4096
+
+/*
+ * memstr - Find the first substring in memory
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ *
+ * Similar to and based on strstr(),
+ * but strings do not need to be NUL terminated.
+ */
+static char *memstr(const char *s1, int l1, const char *s2, int l2)
+{
+	if (!l2)
+		return (char *)s1;
+
+	while (l1 >= l2) {
+		l1--;
+		if (!memcmp(s1, s2, l2))
+			return (char *)s1;
+		s1++;
+	}
+	return NULL;
+}
+
+static char *substitute(char *string,	/* string buffer */
+			int *slen,	/* current string length */
+			int ssize,	/* string bufer size */
+			const char *old,/* old (replaced) string */
+			int olen,	/* length of old string */
+			const char *new,/* new (replacement) string */
+			int nlen)	/* length of new string */
+{
+	char *p = memstr(string, *slen, old, olen);
+
+	if (p == NULL)
+		return NULL;
+
+	debug("## Match at pos %ld: match len %d, subst len %d\n",
+		(long)(p - string), olen, nlen);
+
+	/* make sure replacement matches */
+	if (*slen + nlen - olen > ssize) {
+		printf("## error: substitution buffer overflow\n");
+		return NULL;
+	}
+
+	/* move tail if needed */
+	if (olen != nlen) {
+		int tail, len;
+
+		len = (olen > nlen) ? olen : nlen;
+
+		tail = ssize - (p + len - string);
+
+		debug("## tail len %d\n", tail);
+
+		memmove(p + nlen, p + olen, tail);
+	}
+
+	/* insert substitue */
+	memcpy(p, new, nlen);
+
+	*slen += nlen - olen;
+
+	return p + nlen;
+}
+
+/*
+ * Perform regex operations on a environment variable
+ *
+ * Returns 0 if OK, 1 in case of errors.
+ */
+static int regex_sub(const char *name,
+	const char *r, const char *s, const char *t,
+	int global)
+{
+	struct slre slre;
+	char data[SLRE_BUFSZ];
+	char *datap = data;
+	const char *value;
+	int res, len, nlen, loop;
+
+	if (name == NULL)
+		return 1;
+
+	if (slre_compile(&slre, r) == 0) {
+		printf("Error compiling regex: %s\n", slre.err_str);
+		return 1;
+	}
+
+	if (t == NULL) {
+		value = getenv(name);
+
+		if (value == NULL) {
+			printf("## Error: variable \"%s\" not defined\n", name);
+			return 1;
+		}
+		t = value;
+	}
+
+	debug("REGEX on %s=%s\n", name, t);
+	debug("REGEX=\"%s\", SUBST=\"%s\", GLOBAL=%d\n",
+		r, s ? s : "<NULL>", global);
+
+	len = strlen(t);
+	if (len + 1 > SLRE_BUFSZ) {
+		printf("## error: subst buffer overflow: have %d, need %d\n",
+			SLRE_BUFSZ, len + 1);
+		return 1;
+	}
+
+	strcpy(data, t);
+
+	if (s == NULL)
+		nlen = 0;
+	else
+		nlen = strlen(s);
+
+	for (loop = 0;; loop++) {
+		struct cap caps[slre.num_caps + 2];
+		char nbuf[SLRE_PATSZ];
+		const char *old;
+		char *np;
+		int i, olen;
+
+		(void) memset(caps, 0, sizeof(caps));
+
+		res = slre_match(&slre, datap, len, caps);
+
+		debug("Result: %d\n", res);
+
+		for (i = 0; i < slre.num_caps; i++) {
+			if (caps[i].len > 0) {
+				debug("Substring %d: [%.*s]\n", i,
+					caps[i].len, caps[i].ptr);
+			}
+		}
+
+		if (res == 0) {
+			if (loop == 0) {
+				printf("%s: No match\n", t);
+				return 1;
+			} else {
+				break;
+			}
+		}
+
+		debug("## MATCH ## %s\n", data);
+
+		if (s == NULL) {
+			printf("%s=%s\n", name, t);
+			return 1;
+		}
+
+		old = caps[0].ptr;
+		olen = caps[0].len;
+
+		if (nlen + 1 >= SLRE_PATSZ) {
+			printf("## error: pattern buffer overflow: have %d, need %d\n",
+				SLRE_BUFSZ, nlen + 1);
+			return 1;
+		}
+		strcpy(nbuf, s);
+
+		debug("## SUBST(1) ## %s\n", nbuf);
+
+		/*
+		 * Handle back references
+		 *
+		 * Support for \0 ... \9, where \0 is the
+		 * whole matched pattern (similar to &).
+		 *
+		 * Implementation is a bit simpleminded as
+		 * backrefs are substituted sequentially, one
+		 * by one.  This will lead to somewhat
+		 * unexpected results if the replacement
+		 * strings contain any \N strings then then
+		 * may get substitued, too.  We accept this
+		 * restriction for the sake of simplicity.
+		 */
+		for (i = 0; i < 10; ++i) {
+			char backref[2] = {
+				'\\',
+				'0',
+			};
+
+			if (caps[i].len == 0)
+				break;
+
+			backref[1] += i;
+
+			debug("## BACKREF %d: replace \"%.*s\" by \"%.*s\" in \"%s\"\n",
+				i,
+				2, backref,
+				caps[i].len, caps[i].ptr,
+				nbuf);
+
+			for (np = nbuf;;) {
+				char *p = memstr(np, nlen, backref, 2);
+
+				if (p == NULL)
+					break;
+
+				np = substitute(np, &nlen,
+					SLRE_PATSZ,
+					backref, 2,
+					caps[i].ptr, caps[i].len);
+
+				if (np == NULL)
+					return 1;
+			}
+		}
+		debug("## SUBST(2) ## %s\n", nbuf);
+
+		datap = substitute(datap, &len, SLRE_BUFSZ,
+				old, olen,
+				nbuf, nlen);
+
+		if (datap == NULL)
+			return 1;
+
+		debug("## REMAINDER: %s\n", datap);
+
+		debug("## RESULT: %s\n", data);
+
+		if (!global)
+			break;
+	}
+	debug("## FINAL (now setenv()) :  %s\n", data);
+
+	printf("%s=%s\n", name, data);
+
+	return setenv(name, data);
+}
+#endif
+
 static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	ulong a, b;
 	ulong value;
 	int w;
 
-	/* Validate arguments */
-	if (argc != 5 && argc != 3)
-		return CMD_RET_USAGE;
-	if (argc == 5 && strlen(argv[3]) != 1)
+	/*
+	 * We take 3, 5, or 6 arguments:
+	 * 3 : setexpr name value
+	 * 5 : setexpr name val1 op val2
+	 *     setexpr name [g]sub r s
+	 * 6 : setexpr name [g]sub r s t
+	 */
+
+	/* > 6 already tested by max command args */
+	if ((argc < 3) || (argc == 4))
 		return CMD_RET_USAGE;
 
 	w = cmd_get_data_size(argv[0], 4);
 
 	a = get_arg(argv[2], w);
 
+	/* plain assignment: "setexpr name value" */
 	if (argc == 3) {
 		setenv_hex(argv[1], a);
-
 		return 0;
 	}
 
+	/* 5 or 6 args (6 args only with [g]sub) */
+#ifdef CONFIG_REGEX
+	/*
+	 * rexep handling: "setexpr name [g]sub r s [t]"
+	 * with 5 args, "t" will be NULL
+	 */
+	if (strcmp(argv[2], "gsub") == 0)
+		return regex_sub(argv[1], argv[3], argv[4], argv[5], 1);
+
+	if (strcmp(argv[2], "sub") == 0)
+		return regex_sub(argv[1], argv[3], argv[4], argv[5], 0);
+#endif
+
+	/* standard operators: "setexpr name val1 op val2" */
+	if (argc != 5)
+		return CMD_RET_USAGE;
+
+	if (strlen(argv[3]) != 1)
+		return CMD_RET_USAGE;
+
 	b = get_arg(argv[4], w);
 
 	switch (argv[3][0]) {
@@ -110,13 +378,23 @@
 }
 
 U_BOOT_CMD(
-	setexpr, 5, 0, do_setexpr,
+	setexpr, 6, 0, do_setexpr,
 	"set environment variable as the result of eval expression",
 	"[.b, .w, .l] name [*]value1 <op> [*]value2\n"
 	"    - set environment variable 'name' to the result of the evaluated\n"
-	"      express specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
+	"      expression specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
 	"      size argument is only meaningful if value1 and/or value2 are\n"
 	"      memory addresses (*)\n"
-	"setexpr[.b, .w, .l] name *value\n"
-	"    - load a memory address into a variable"
+	"setexpr[.b, .w, .l] name [*]value\n"
+	"    - load a value into a variable"
+#ifdef CONFIG_REGEX
+	"\n"
+	"setexpr name gsub r s [t]\n"
+	"    - For each substring matching the regular expression <r> in the\n"
+	"      string <t>, substitute the string <s>.  The result is\n"
+	"      assigned to <name>.  If <t> is not supplied, use the old\n"
+	"      value of <name>\n"
+	"setexpr name sub r s [t]\n"
+	"    - Just like gsub(), but replace only the first matching substring"
+#endif
 );
diff --git a/common/env_mmc.c b/common/env_mmc.c
index 02bd5ae..9ca098f 100644
--- a/common/env_mmc.c
+++ b/common/env_mmc.c
@@ -32,6 +32,11 @@
 #include <search.h>
 #include <errno.h>
 
+#if defined(CONFIG_ENV_SIZE_REDUND) &&  \
+	(CONFIG_ENV_SIZE_REDUND != CONFIG_ENV_SIZE)
+#error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE
+#endif
+
 char *env_name_spec = "MMC";
 
 #ifdef ENV_IS_EMBEDDED
@@ -46,9 +51,13 @@
 #define CONFIG_ENV_OFFSET 0
 #endif
 
-__weak int mmc_get_env_addr(struct mmc *mmc, u32 *env_addr)
+__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
 {
 	*env_addr = CONFIG_ENV_OFFSET;
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	if (copy)
+		*env_addr = CONFIG_ENV_OFFSET_REDUND;
+#endif
 	return 0;
 }
 
@@ -110,6 +119,10 @@
 	return (n == blk_cnt) ? 0 : -1;
 }
 
+#ifdef CONFIG_ENV_OFFSET_REDUND
+static unsigned char env_flags;
+#endif
+
 int saveenv(void)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
@@ -117,16 +130,11 @@
 	char	*res;
 	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
 	u32	offset;
-	int	ret;
+	int	ret, copy = 0;
 
 	if (init_mmc_for_env(mmc))
 		return 1;
 
-	if (mmc_get_env_addr(mmc, &offset)) {
-		ret = 1;
-		goto fini;
-	}
-
 	res = (char *)&env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
@@ -136,7 +144,21 @@
 	}
 
 	env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
-	printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	env_new->flags	= ++env_flags; /* increase the serial */
+
+	if (gd->env_valid == 1)
+		copy = 1;
+#endif
+
+	if (mmc_get_env_addr(mmc, copy, &offset)) {
+		ret = 1;
+		goto fini;
+	}
+
+	printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "",
+	       CONFIG_SYS_MMC_ENV_DEV);
 	if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) {
 		puts("failed\n");
 		ret = 1;
@@ -146,6 +168,10 @@
 	puts("done\n");
 	ret = 0;
 
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	gd->env_valid = gd->env_valid == 2 ? 1 : 2;
+#endif
+
 fini:
 	fini_mmc_for_env(mmc);
 	return ret;
@@ -166,6 +192,93 @@
 	return (n == blk_cnt) ? 0 : -1;
 }
 
+#ifdef CONFIG_ENV_OFFSET_REDUND
+void env_relocate_spec(void)
+{
+#if !defined(ENV_IS_EMBEDDED)
+	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+	u32 offset1, offset2;
+	int read1_fail = 0, read2_fail = 0;
+	int crc1_ok = 0, crc2_ok = 0;
+	env_t *ep, *tmp_env1, *tmp_env2;
+	int ret;
+
+	tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE);
+	tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE);
+	if (tmp_env1 == NULL || tmp_env2 == NULL) {
+		puts("Can't allocate buffers for environment\n");
+		ret = 1;
+		goto err;
+	}
+
+	if (init_mmc_for_env(mmc)) {
+		ret = 1;
+		goto err;
+	}
+
+	if (mmc_get_env_addr(mmc, 0, &offset1) ||
+	    mmc_get_env_addr(mmc, 1, &offset2)) {
+		ret = 1;
+		goto fini;
+	}
+
+	read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1);
+	read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2);
+
+	if (read1_fail && read2_fail)
+		puts("*** Error - No Valid Environment Area found\n");
+	else if (read1_fail || read2_fail)
+		puts("*** Warning - some problems detected "
+		     "reading environment; recovered successfully\n");
+
+	crc1_ok = !read1_fail &&
+		(crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
+	crc2_ok = !read2_fail &&
+		(crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
+
+	if (!crc1_ok && !crc2_ok) {
+		ret = 1;
+		goto fini;
+	} else if (crc1_ok && !crc2_ok) {
+		gd->env_valid = 1;
+	} else if (!crc1_ok && crc2_ok) {
+		gd->env_valid = 2;
+	} else {
+		/* both ok - check serial */
+		if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
+			gd->env_valid = 2;
+		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
+			gd->env_valid = 1;
+		else if (tmp_env1->flags > tmp_env2->flags)
+			gd->env_valid = 1;
+		else if (tmp_env2->flags > tmp_env1->flags)
+			gd->env_valid = 2;
+		else /* flags are equal - almost impossible */
+			gd->env_valid = 1;
+	}
+
+	free(env_ptr);
+
+	if (gd->env_valid == 1)
+		ep = tmp_env1;
+	else
+		ep = tmp_env2;
+
+	env_flags = ep->flags;
+	env_import((char *)ep, 0);
+	ret = 0;
+
+fini:
+	fini_mmc_for_env(mmc);
+err:
+	if (ret)
+		set_default_env(NULL);
+
+	free(tmp_env1);
+	free(tmp_env2);
+#endif
+}
+#else /* ! CONFIG_ENV_OFFSET_REDUND */
 void env_relocate_spec(void)
 {
 #if !defined(ENV_IS_EMBEDDED)
@@ -179,7 +292,7 @@
 		goto err;
 	}
 
-	if (mmc_get_env_addr(mmc, &offset)) {
+	if (mmc_get_env_addr(mmc, 0, &offset)) {
 		ret = 1;
 		goto fini;
 	}
@@ -199,3 +312,4 @@
 		set_default_env(NULL);
 #endif
 }
+#endif /* CONFIG_ENV_OFFSET_REDUND */
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 6715e0d..7ce2d5f 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -48,13 +48,6 @@
 /* Define board data structure */
 static bd_t bdata __attribute__ ((section(".data")));
 
-inline void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
-
 /*
  * Default function to determine if u-boot or the OS should
  * be started. This implementation always returns 1.
diff --git a/common/usb_storage.c b/common/usb_storage.c
index fb322b4..c5db044 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -1430,6 +1430,7 @@
 			*capacity, *blksz);
 	dev_desc->lba = *capacity;
 	dev_desc->blksz = *blksz;
+	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 	dev_desc->type = perq;
 	USB_STOR_PRINTF(" address %d\n", dev_desc->target);
 	USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
diff --git a/disk/part_dos.c b/disk/part_dos.c
index 37087a6..ab984cd 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -74,13 +74,26 @@
 
 static int test_block_type(unsigned char *buffer)
 {
+	int slot;
+	struct dos_partition *p;
+
 	if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
 	    (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
 		return (-1);
 	} /* no DOS Signature at all */
-	if (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0 ||
-	    strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],"FAT32",5)==0) {
-		return DOS_PBR; /* is PBR */
+	p = (struct dos_partition *)&buffer[DOS_PART_TBL_OFFSET];
+	for (slot = 0; slot < 3; slot++) {
+		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
+			if (!slot &&
+			    (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],
+				     "FAT", 3) == 0 ||
+			     strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],
+				     "FAT32", 5) == 0)) {
+				return DOS_PBR; /* is PBR */
+			} else {
+				return -1;
+			}
+		}
 	}
 	return DOS_MBR;	    /* Is MBR */
 }
diff --git a/disk/part_efi.c b/disk/part_efi.c
index e9987f0..5986589 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -115,7 +115,7 @@
 
 void print_part_efi(block_dev_desc_t * dev_desc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
 	gpt_entry *gpt_pte = NULL;
 	int i = 0;
 	char uuid[37];
@@ -162,7 +162,7 @@
 int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
 				disk_partition_t * info)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
 	gpt_entry *gpt_pte = NULL;
 
 	/* "part" argument must be at least 1 */
@@ -190,7 +190,7 @@
 	/* The ending LBA is inclusive, to calculate size, add 1 to it */
 	info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1)
 		     - info->start;
-	info->blksz = GPT_BLOCK_SIZE;
+	info->blksz = dev_desc->blksz;
 
 	sprintf((char *)info->name, "%s",
 			print_efiname(&gpt_pte[part - 1]));
@@ -210,7 +210,7 @@
 
 int test_part_efi(block_dev_desc_t * dev_desc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, legacymbr, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz);
 
 	/* Read legacy MBR from block 0 and validate it */
 	if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1)
@@ -311,9 +311,8 @@
 int write_gpt_table(block_dev_desc_t *dev_desc,
 		gpt_header *gpt_h, gpt_entry *gpt_e)
 {
-	const int pte_blk_num = (gpt_h->num_partition_entries
-		* sizeof(gpt_entry)) / dev_desc->blksz;
-
+	const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
+					   * sizeof(gpt_entry)), dev_desc);
 	u32 calc_crc32;
 	u64 val;
 
@@ -336,8 +335,8 @@
 	if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1)
 		goto err;
 
-	if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_num, gpt_e)
-	    != pte_blk_num)
+	if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_cnt, gpt_e)
+	    != pte_blk_cnt)
 		goto err;
 
 	/* recalculate the values for the Second GPT Header */
@@ -352,7 +351,7 @@
 
 	if (dev_desc->block_write(dev_desc->dev,
 				  le32_to_cpu(gpt_h->last_usable_lba + 1),
-				  pte_blk_num, gpt_e) != pte_blk_num)
+				  pte_blk_cnt, gpt_e) != pte_blk_cnt)
 		goto err;
 
 	if (dev_desc->block_write(dev_desc->dev,
@@ -462,13 +461,18 @@
 {
 	int ret;
 
-	gpt_header *gpt_h = calloc(1, sizeof(gpt_header));
+	gpt_header *gpt_h = calloc(1, PAD_TO_BLOCKSIZE(sizeof(gpt_header),
+						       dev_desc));
+	gpt_entry *gpt_e;
+
 	if (gpt_h == NULL) {
 		printf("%s: calloc failed!\n", __func__);
 		return -1;
 	}
 
-	gpt_entry *gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry));
+	gpt_e = calloc(1, PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS
+					       * sizeof(gpt_entry),
+					       dev_desc));
 	if (gpt_e == NULL) {
 		printf("%s: calloc failed!\n", __func__);
 		free(gpt_h);
@@ -652,7 +656,7 @@
 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
 					 gpt_header * pgpt_head)
 {
-	size_t count = 0;
+	size_t count = 0, blk_cnt;
 	gpt_entry *pte = NULL;
 
 	if (!dev_desc || !pgpt_head) {
@@ -669,7 +673,8 @@
 
 	/* Allocate memory for PTE, remember to FREE */
 	if (count != 0) {
-		pte = memalign(ARCH_DMA_MINALIGN, count);
+		pte = memalign(ARCH_DMA_MINALIGN,
+			       PAD_TO_BLOCKSIZE(count, dev_desc));
 	}
 
 	if (count == 0 || pte == NULL) {
@@ -680,10 +685,11 @@
 	}
 
 	/* Read GPT Entries from device */
+	blk_cnt = BLOCK_CNT(count, dev_desc);
 	if (dev_desc->block_read (dev_desc->dev,
 		le64_to_cpu(pgpt_head->partition_entry_lba),
-		(lbaint_t) (count / GPT_BLOCK_SIZE), pte)
-		!= (count / GPT_BLOCK_SIZE)) {
+		(lbaint_t) (blk_cnt), pte)
+		!= blk_cnt) {
 
 		printf("*** ERROR: Can't read GPT Entries ***\n");
 		free(pte);
diff --git a/disk/part_iso.c b/disk/part_iso.c
index 49639af..cc323b0 100644
--- a/disk/part_iso.c
+++ b/disk/part_iso.c
@@ -73,6 +73,9 @@
 	iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
 	iso_init_def_entry_t *pide;
 
+	if (dev_desc->blksz != CD_SECTSIZE)
+		return -1;
+
 	/* the first sector (sector 0x10) must be a primary volume desc */
 	blkaddr=PVD_OFFSET;
 	if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)
diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c
index 1e33a66..fcae448 100644
--- a/drivers/block/ata_piix.c
+++ b/drivers/block/ata_piix.c
@@ -406,6 +406,7 @@
 	/* assuming HD */
 	sata_dev_desc[devno].type = DEV_TYPE_HARDDISK;
 	sata_dev_desc[devno].blksz = ATA_BLOCKSIZE;
+	sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz);
 	sata_dev_desc[devno].lun = 0;	/* just to fill something in... */
 }
 
diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c
index b847dd9..27ecaf4 100644
--- a/drivers/block/pata_bfin.c
+++ b/drivers/block/pata_bfin.c
@@ -897,6 +897,8 @@
 	/* assuming HD */
 	sata_dev_desc[ap->port_no].type = DEV_TYPE_HARDDISK;
 	sata_dev_desc[ap->port_no].blksz = ATA_SECT_SIZE;
+	sata_dev_desc[ap->port_no].log2blksz =
+		LOG2(sata_dev_desc[ap->port_no].blksz);
 	sata_dev_desc[ap->port_no].lun = 0;	/* just to fill something in... */
 
 	printf("PATA device#%d %s is found on ata port#%d.\n",
diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c
index bf29cbb..b08715f 100644
--- a/drivers/block/systemace.c
+++ b/drivers/block/systemace.c
@@ -127,6 +127,7 @@
 		systemace_dev.part_type = PART_TYPE_UNKNOWN;
 		systemace_dev.type = DEV_TYPE_HARDDISK;
 		systemace_dev.blksz = 512;
+		systemace_dev.log2blksz = LOG2(systemace_dev.blksz);
 		systemace_dev.removable = 1;
 		systemace_dev.block_read = systemace_read;
 
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f65a7b0..2590f1b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -601,7 +601,7 @@
 
 	data.dest = (char *)ext_csd;
 	data.blocks = 1;
-	data.blocksize = 512;
+	data.blocksize = MMC_MAX_BLOCK_LEN;
 	data.flags = MMC_DATA_READ;
 
 	err = mmc_send_cmd(mmc, &cmd, &data);
@@ -634,7 +634,7 @@
 
 static int mmc_change_freq(struct mmc *mmc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
+	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
 	char cardtype;
 	int err;
 
@@ -899,8 +899,8 @@
 	uint mult, freq;
 	u64 cmult, csize, capacity;
 	struct mmc_cmd cmd;
-	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
-	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, 512);
+	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
+	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
 	int timeout = 1000;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
@@ -1016,11 +1016,11 @@
 	mmc->capacity = (csize + 1) << (cmult + 2);
 	mmc->capacity *= mmc->read_bl_len;
 
-	if (mmc->read_bl_len > 512)
-		mmc->read_bl_len = 512;
+	if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
+		mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
 
-	if (mmc->write_bl_len > 512)
-		mmc->write_bl_len = 512;
+	if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
+		mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
 
 	/* Select the card, and put it into Transfer Mode */
 	if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
@@ -1051,7 +1051,7 @@
 					| ext_csd[EXT_CSD_SEC_CNT + 1] << 8
 					| ext_csd[EXT_CSD_SEC_CNT + 2] << 16
 					| ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
-			capacity *= 512;
+			capacity *= MMC_MAX_BLOCK_LEN;
 			if ((capacity >> 20) > 2 * 1024)
 				mmc->capacity = capacity;
 		}
@@ -1079,10 +1079,11 @@
 		 * group size from ext_csd directly, or calculate
 		 * the group size from the csd value.
 		 */
-		if (ext_csd[EXT_CSD_ERASE_GROUP_DEF])
+		if (ext_csd[EXT_CSD_ERASE_GROUP_DEF]) {
 			mmc->erase_grp_size =
-			      ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 512 * 1024;
-		else {
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
+					MMC_MAX_BLOCK_LEN * 1024;
+		} else {
 			int erase_gsz, erase_gmul;
 			erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
 			erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
@@ -1202,6 +1203,7 @@
 	mmc->block_dev.lun = 0;
 	mmc->block_dev.type = 0;
 	mmc->block_dev.blksz = mmc->read_bl_len;
+	mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
 	mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
 	sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
 		mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
diff --git a/drivers/mmc/spl_mmc.c b/drivers/mmc/spl_mmc.c
index 753c6a0..7efdcb8 100644
--- a/drivers/mmc/spl_mmc.c
+++ b/drivers/mmc/spl_mmc.c
@@ -34,8 +34,9 @@
 
 static void mmc_load_image_raw(struct mmc *mmc)
 {
-	u32 image_size_sectors, err;
-	const struct image_header *header;
+	unsigned long err;
+	u32 image_size_sectors;
+	struct image_header *header;
 
 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
 						sizeof(struct image_header));
@@ -43,9 +44,9 @@
 	/* read image header to find the image size & load address */
 	err = mmc->block_dev.block_read(0,
 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1,
-			(void *)header);
+			header);
 
-	if (err <= 0)
+	if (err == 0)
 		goto end;
 
 	spl_parse_image_header(header);
@@ -60,8 +61,8 @@
 			image_size_sectors, (void *)spl_image.load_addr);
 
 end:
-	if (err <= 0) {
-		printf("spl: mmc blk read err - %d\n", err);
+	if (err == 0) {
+		printf("spl: mmc blk read err - %lu\n", err);
 		hang();
 	}
 }
@@ -69,7 +70,7 @@
 #ifdef CONFIG_SPL_FAT_SUPPORT
 static void mmc_load_image_fat(struct mmc *mmc)
 {
-	s32 err;
+	int err;
 	struct image_header *header;
 
 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
@@ -83,7 +84,7 @@
 	}
 
 	err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME,
-				(u8 *)header, sizeof(struct image_header));
+				header, sizeof(struct image_header));
 	if (err <= 0)
 		goto end;
 
diff --git a/drivers/mtd/nand/mxc_nand_spl.c b/drivers/mtd/nand/mxc_nand_spl.c
index 09f23c3..edc589e 100644
--- a/drivers/mtd/nand/mxc_nand_spl.c
+++ b/drivers/mtd/nand/mxc_nand_spl.c
@@ -355,12 +355,3 @@
 		hang();
 	}
 }
-
-/*
- * Called in case of an exception.
- */
-void hang(void)
-{
-	/* Loop forever */
-	while (1) ;
-}
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index b4022aa..fd07240 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -120,7 +120,6 @@
 	__u8 *bufptr = mydata->fatbuf;
 	__u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
 
-	fatlength *= mydata->sect_size;
 	startblock += mydata->fat_sect;
 
 	if (getsize > fatlength)
diff --git a/include/common.h b/include/common.h
index de75da2..8a1f3e4 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1008,10 +1008,17 @@
  * of a function scoped static buffer.  It can not be used to create a cache
  * line aligned global buffer.
  */
-#define ALLOC_ALIGN_BUFFER(type, name, size, align)			\
-	char __##name[ROUND(size * sizeof(type), align) + (align - 1)];	\
+#define PAD_COUNT(s, pad) ((s - 1) / pad + 1)
+#define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad)
+#define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad)		\
+	char __##name[ROUND(PAD_SIZE(size * sizeof(type), pad), align)  \
+		      + (align - 1)];					\
 									\
 	type *name = (type *) ALIGN((uintptr_t)__##name, align)
+#define ALLOC_ALIGN_BUFFER(type, name, size, align)		\
+	ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, 1)
+#define ALLOC_CACHE_ALIGN_BUFFER_PAD(type, name, size, pad)		\
+	ALLOC_ALIGN_BUFFER_PAD(type, name, size, ARCH_DMA_MINALIGN, pad)
 #define ALLOC_CACHE_ALIGN_BUFFER(type, name, size)			\
 	ALLOC_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
 
@@ -1022,7 +1029,7 @@
  */
 #define DEFINE_ALIGN_BUFFER(type, name, size, align)			\
 	static char __##name[roundup(size * sizeof(type), align)]	\
-			__attribute__((aligned(align)));				\
+			__aligned(align);				\
 									\
 	static type *name = (type *)__##name
 #define DEFINE_CACHE_ALIGN_BUFFER(type, name, size)			\
diff --git a/include/configs/amcc-common.h b/include/configs/amcc-common.h
index f2f522d..80e5735 100644
--- a/include/configs/amcc-common.h
+++ b/include/configs/amcc-common.h
@@ -71,6 +71,7 @@
 #define CONFIG_CMD_DIAG
 #define CONFIG_CMD_EEPROM
 #define CONFIG_CMD_ELF
+#define CONFIG_CMD_GREPENV
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_IRQ
 #define CONFIG_CMD_MII
@@ -78,6 +79,7 @@
 #define CONFIG_CMD_NFS
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_SETEXPR
 
 /*
  * Miscellaneous configurable options
@@ -108,13 +110,14 @@
 #define CONFIG_MX_CYCLIC		/* enable mdc/mwc commands      */
 #define CONFIG_ZERO_BOOTDELAY_CHECK	/* check for keypress on bootdelay==0 */
 #define CONFIG_VERSION_VARIABLE 	/* include version env variable */
-#define CONFIG_SYS_CONSOLE_INFO_QUIET		/* don't print console @ startup*/
+#define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup*/
 
-#define CONFIG_SYS_HUSH_PARSER			/* Use the HUSH parser		*/
+#define CONFIG_SYS_HUSH_PARSER		/* Use the HUSH parser		*/
 
 #define CONFIG_LOADS_ECHO		/* echo on for serial download	*/
-#define CONFIG_SYS_LOADS_BAUD_CHANGE		/* allow baudrate change	*/
+#define CONFIG_SYS_LOADS_BAUD_CHANGE	/* allow baudrate change	*/
 
+#define CONFIG_REGEX			/* Enable regular expression support */
 /*
  * BOOTP options
  */
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index f2725cc..4ce4058 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -23,71 +23,74 @@
 /*
  * SoC configurations
  */
-#define	CONFIG_MX28				/* i.MX28 SoC */
-#define	CONFIG_MXS_GPIO				/* GPIO control */
-#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+#define CONFIG_MX28				/* i.MX28 SoC */
+#define CONFIG_MXS_GPIO				/* GPIO control */
+#define CONFIG_SYS_HZ		1000		/* Ticks per second */
 
 /*
  * Define M28EVK machine type by hand until it lands in mach-types
  */
-#define	MACH_TYPE_M28EVK	3613
+#define MACH_TYPE_M28EVK	3613
 
-#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+#define CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
 
 #include <asm/arch/regs-base.h>
 
-#define	CONFIG_SYS_NO_FLASH
-#define	CONFIG_BOARD_EARLY_INIT_F
-#define	CONFIG_ARCH_MISC_INIT
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_MISC_INIT
 
 /*
  * SPL
  */
-#define	CONFIG_SPL
-#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
-#define	CONFIG_SPL_START_S_PATH		"arch/arm/cpu/arm926ejs/mxs"
-#define	CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds"
-#define	CONFIG_SPL_LIBCOMMON_SUPPORT
-#define	CONFIG_SPL_LIBGENERIC_SUPPORT
-#define	CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL
+#define CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define CONFIG_SPL_START_S_PATH		"arch/arm/cpu/arm926ejs/mxs"
+#define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds"
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
 
 /*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-#define	CONFIG_DISPLAY_CPUINFO
-#define	CONFIG_DOS_PARTITION
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DOS_PARTITION
 
-#define	CONFIG_CMD_CACHE
-#define	CONFIG_CMD_DATE
-#define	CONFIG_CMD_DHCP
-#define	CONFIG_CMD_EEPROM
-#define	CONFIG_CMD_EXT2
-#define	CONFIG_CMD_FAT
-#define	CONFIG_CMD_GPIO
-#define	CONFIG_CMD_I2C
-#define	CONFIG_CMD_MII
-#define	CONFIG_CMD_MMC
-#define	CONFIG_CMD_NAND
-#define	CONFIG_CMD_NET
-#define	CONFIG_CMD_NFS
-#define	CONFIG_CMD_PING
-#define	CONFIG_CMD_SETEXPR
-#define	CONFIG_CMD_SF
-#define	CONFIG_CMD_SPI
-#define	CONFIG_CMD_USB
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_GREPENV
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SETEXPR
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_USB
+
+#define CONFIG_REGEX			/* Enable regular expression support */
 
 /*
  * Memory configurations
  */
-#define	CONFIG_NR_DRAM_BANKS		1		/* 1 bank of DRAM */
-#define	PHYS_SDRAM_1			0x40000000	/* Base address */
-#define	PHYS_SDRAM_1_SIZE		0x20000000	/* Max 512 MB RAM */
-#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
-#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
-#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
-#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
-#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+#define CONFIG_NR_DRAM_BANKS		1		/* 1 bank of DRAM */
+#define PHYS_SDRAM_1			0x40000000	/* Base address */
+#define PHYS_SDRAM_1_SIZE		0x20000000	/* Max 512 MB RAM */
+#define CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
 /* Point initial SP in SRAM so SPL can use it too. */
 
 #define CONFIG_SYS_INIT_RAM_ADDR	0x00000000
@@ -102,42 +105,42 @@
  * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
  * binary. In case there was more of this mess, 0x100 bytes are skipped.
  */
-#define	CONFIG_SYS_TEXT_BASE		0x40000100
+#define CONFIG_SYS_TEXT_BASE		0x40000100
 
 /*
  * U-Boot general configurations
  */
-#define	CONFIG_SYS_LONGHELP
-#define	CONFIG_SYS_PROMPT	"=> "
-#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
-#define	CONFIG_SYS_PBSIZE	\
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_PROMPT	"=> "
+#define CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define CONFIG_SYS_PBSIZE	\
 	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 						/* Print buffer size */
-#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
-#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
 						/* Boot argument buffer size */
-#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
-#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
-#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
-#define	CONFIG_SYS_HUSH_PARSER
+#define CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define CONFIG_SYS_HUSH_PARSER
 
 /*
  * Serial Driver
  */
-#define	CONFIG_PL011_SERIAL
-#define	CONFIG_PL011_CLOCK		24000000
-#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
-#define	CONFIG_CONS_INDEX		0
-#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define CONFIG_PL011_SERIAL
+#define CONFIG_PL011_CLOCK		24000000
+#define CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define CONFIG_CONS_INDEX		0
+#define CONFIG_BAUDRATE			115200	/* Default baud rate */
 
 /*
  * MMC Driver
  */
 #ifdef	CONFIG_CMD_MMC
-#define	CONFIG_MMC
-#define	CONFIG_BOUNCE_BUFFER
-#define	CONFIG_GENERIC_MMC
-#define	CONFIG_MXS_MMC
+#define CONFIG_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXS_MMC
 #endif
 
 /*
@@ -148,31 +151,31 @@
 /*
  * NAND
  */
-#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define CONFIG_ENV_SIZE			(16 * 1024)
 #ifdef	CONFIG_CMD_NAND
-#define	CONFIG_NAND_MXS
-#define	CONFIG_SYS_MAX_NAND_DEVICE	1
-#define	CONFIG_SYS_NAND_BASE		0x60000000
-#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_NAND_MXS
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0x60000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
 
 /* Environment is in NAND */
-#define	CONFIG_ENV_IS_IN_NAND
-#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
-#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
-#define	CONFIG_ENV_RANGE		(512 * 1024)
-#define	CONFIG_ENV_OFFSET		0x300000
-#define	CONFIG_ENV_OFFSET_REDUND	\
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define CONFIG_ENV_RANGE		(512 * 1024)
+#define CONFIG_ENV_OFFSET		0x300000
+#define CONFIG_ENV_OFFSET_REDUND	\
 		(CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE)
 
-#define	CONFIG_CMD_UBI
-#define	CONFIG_CMD_UBIFS
-#define	CONFIG_CMD_MTDPARTS
-#define	CONFIG_RBTREE
-#define	CONFIG_LZO
-#define	CONFIG_MTD_DEVICE
-#define	CONFIG_MTD_PARTITIONS
-#define	MTDIDS_DEFAULT			"nand0=gpmi-nand"
-#define	MTDPARTS_DEFAULT			\
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_RBTREE
+#define CONFIG_LZO
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define MTDIDS_DEFAULT			"nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT			\
 	"mtdparts=gpmi-nand:"			\
 		"3m(bootloader)ro,"		\
 		"512k(environment),"		\
@@ -182,34 +185,34 @@
 		"8m(ramdisk),"			\
 		"-(filesystem)"
 #else
-#define	CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_IS_NOWHERE
 #endif
 
 /*
  * Ethernet on SOC (FEC)
  */
 #ifdef	CONFIG_CMD_NET
-#define	CONFIG_ETHPRIME			"FEC0"
-#define	CONFIG_FEC_MXC
-#define	CONFIG_MII
-#define	CONFIG_FEC_XCV_TYPE		RMII
+#define CONFIG_ETHPRIME			"FEC0"
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define CONFIG_FEC_XCV_TYPE		RMII
 #endif
 
 /*
  * I2C
  */
 #ifdef	CONFIG_CMD_I2C
-#define	CONFIG_I2C_MXS
-#define	CONFIG_HARD_I2C
-#define	CONFIG_SYS_I2C_SPEED		400000
+#define CONFIG_I2C_MXS
+#define CONFIG_HARD_I2C
+#define CONFIG_SYS_I2C_SPEED		400000
 #endif
 
 /*
  * EEPROM
  */
 #ifdef	CONFIG_CMD_EEPROM
-#define	CONFIG_SYS_I2C_MULTI_EEPROMS
-#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#define CONFIG_SYS_I2C_MULTI_EEPROMS
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
 #endif
 
 /*
@@ -217,13 +220,13 @@
  */
 #ifdef	CONFIG_CMD_DATE
 /* Use the internal RTC in the MXS chip */
-#define	CONFIG_RTC_INTERNAL
+#define CONFIG_RTC_INTERNAL
 #ifdef	CONFIG_RTC_INTERNAL
-#define	CONFIG_RTC_MXS
+#define CONFIG_RTC_MXS
 #else
-#define	CONFIG_RTC_M41T62
-#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
-#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#define CONFIG_RTC_M41T62
+#define CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define CONFIG_SYS_M41T11_BASE_YEAR	2000
 #endif
 #endif
 
@@ -231,59 +234,59 @@
  * USB
  */
 #ifdef	CONFIG_CMD_USB
-#define	CONFIG_USB_EHCI
-#define	CONFIG_USB_EHCI_MXS
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MXS
 #define CONFIG_EHCI_MXS_PORT0
 #define CONFIG_EHCI_MXS_PORT1
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
-#define	CONFIG_EHCI_IS_TDI
-#define	CONFIG_USB_STORAGE
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
 #endif
 
 /*
  * SPI
  */
 #ifdef	CONFIG_CMD_SPI
-#define	CONFIG_HARD_SPI
-#define	CONFIG_MXS_SPI
-#define	CONFIG_SPI_HALF_DUPLEX
-#define	CONFIG_DEFAULT_SPI_BUS		2
-#define	CONFIG_DEFAULT_SPI_CS		0
-#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+#define CONFIG_HARD_SPI
+#define CONFIG_MXS_SPI
+#define CONFIG_SPI_HALF_DUPLEX
+#define CONFIG_DEFAULT_SPI_BUS		2
+#define CONFIG_DEFAULT_SPI_CS		0
+#define CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
 
 /* SPI FLASH */
 #ifdef	CONFIG_CMD_SF
-#define	CONFIG_SPI_FLASH
-#define	CONFIG_SPI_FLASH_STMICRO
-#define	CONFIG_SF_DEFAULT_BUS		2
-#define	CONFIG_SF_DEFAULT_CS		0
-#define	CONFIG_SF_DEFAULT_SPEED		40000000
-#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SF_DEFAULT_BUS		2
+#define CONFIG_SF_DEFAULT_CS		0
+#define CONFIG_SF_DEFAULT_SPEED		40000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 
-#define	CONFIG_ENV_SPI_BUS		2
-#define	CONFIG_ENV_SPI_CS		0
-#define	CONFIG_ENV_SPI_MAX_HZ		40000000
-#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#define CONFIG_ENV_SPI_BUS		2
+#define CONFIG_ENV_SPI_CS		0
+#define CONFIG_ENV_SPI_MAX_HZ		40000000
+#define CONFIG_ENV_SPI_MODE		SPI_MODE_0
 #endif
 #endif
 
 /*
  * Boot Linux
  */
-#define	CONFIG_CMDLINE_TAG
-#define	CONFIG_SETUP_MEMORY_TAGS
-#define	CONFIG_BOOTDELAY	3
-#define	CONFIG_BOOTFILE		"uImage"
-#define	CONFIG_BOOTARGS		"console=ttyAMA0,115200n8 "
-#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
-#define	CONFIG_LOADADDR		0x42000000
-#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
-#define	CONFIG_OF_LIBFDT
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_BOOTDELAY	3
+#define CONFIG_BOOTFILE		"uImage"
+#define CONFIG_BOOTARGS		"console=ttyAMA0,115200n8 "
+#define CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define CONFIG_LOADADDR		0x42000000
+#define CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+#define CONFIG_OF_LIBFDT
 
 /*
  * Extra Environments
  */
-#define	CONFIG_EXTRA_ENV_SETTINGS					\
+#define CONFIG_EXTRA_ENV_SETTINGS					\
 	"update_nand_full_filename=u-boot.nand\0"			\
 	"update_nand_firmware_filename=u-boot.sb\0"			\
 	"update_sd_firmware_filename=u-boot.sd\0"			\
diff --git a/include/configs/mx28evk.h b/include/configs/mx28evk.h
index d470b47..3747955 100644
--- a/include/configs/mx28evk.h
+++ b/include/configs/mx28evk.h
@@ -138,14 +138,14 @@
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 
 /* Environment is in NAND */
+#ifdef CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
 #define CONFIG_ENV_SECT_SIZE		(128 * 1024)
 #define CONFIG_ENV_RANGE		(512 * 1024)
-#ifndef CONFIG_ENV_OFFSET
 #define CONFIG_ENV_OFFSET		0x300000
-#endif
 #define CONFIG_ENV_OFFSET_REDUND	\
 		(CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE)
+#endif
 
 #define CONFIG_CMD_UBI
 #define CONFIG_CMD_UBIFS
diff --git a/include/configs/mx31pdk.h b/include/configs/mx31pdk.h
index 1754595..82ea4fa 100644
--- a/include/configs/mx31pdk.h
+++ b/include/configs/mx31pdk.h
@@ -50,6 +50,7 @@
 #define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 #define CONFIG_SPL_MAX_SIZE	2048
 #define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
 
 #define CONFIG_SPL_TEXT_BASE	0x87dc0000
 #define CONFIG_SYS_TEXT_BASE	0x87e00000
diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h
index 240fdfc..550cabd 100644
--- a/include/configs/omap5_uevm.h
+++ b/include/configs/omap5_uevm.h
@@ -44,6 +44,8 @@
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_SYS_MMC_ENV_DEV		1	/* SLOT2: eMMC(1) */
 #define CONFIG_ENV_OFFSET		0xE0000
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
 #define CONFIG_CMD_SAVEENV
 
 /* Enhance our eMMC support / experience. */
diff --git a/include/configs/tx25.h b/include/configs/tx25.h
index e72f8f6..d61a218 100644
--- a/include/configs/tx25.h
+++ b/include/configs/tx25.h
@@ -37,6 +37,7 @@
 #define CONFIG_SPL_LDSCRIPT		"arch/$(ARCH)/cpu/u-boot-spl.lds"
 #define CONFIG_SPL_MAX_SIZE		2048
 #define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
 
 #define CONFIG_SPL_TEXT_BASE		0x810c0000
 #define CONFIG_SYS_TEXT_BASE		0x81200000
diff --git a/include/mmc.h b/include/mmc.h
index f0d4820..8bbc6b6 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -207,6 +207,9 @@
 #define PART_ACCESS_MASK	(0x7)
 #define PART_SUPPORT		(0x1)
 
+/* Maximum block size for MMC */
+#define MMC_MAX_BLOCK_LEN	512
+
 struct mmc_cid {
 	unsigned long psn;
 	unsigned short oid;
diff --git a/include/part.h b/include/part.h
index c58a734..f7c7cc5 100644
--- a/include/part.h
+++ b/include/part.h
@@ -38,6 +38,7 @@
 #endif
 	lbaint_t	lba;		/* number of blocks */
 	unsigned long	blksz;		/* block size */
+	int		log2blksz;	/* for convenience: log2(blksz) */
 	char		vendor [40+1];	/* IDE model, SCSI Vendor */
 	char		product[20+1];	/* IDE Serial no, SCSI product */
 	char		revision[8+1];	/* firmware revision */
@@ -55,6 +56,14 @@
 	void		*priv;		/* driver private struct pointer */
 }block_dev_desc_t;
 
+#define BLOCK_CNT(size, block_dev_desc) (PAD_COUNT(size, block_dev_desc->blksz))
+#define PAD_TO_BLOCKSIZE(size, block_dev_desc) \
+	(PAD_SIZE(size, block_dev_desc->blksz))
+#define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \
+		 ((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \
+		 ((x & 0xffff0000) ? 16 : 0))
+#define LOG2_INVALID(type) ((type)((sizeof(type)<<3)-1))
+
 /* Interface types: */
 #define IF_TYPE_UNKNOWN		0
 #define IF_TYPE_IDE		1
diff --git a/include/part_efi.h b/include/part_efi.h
index 6de0a32..95e4c8f 100644
--- a/include/part_efi.h
+++ b/include/part_efi.h
@@ -38,7 +38,6 @@
 #define EFI_PMBR_OSTYPE_EFI 0xEF
 #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
 
-#define GPT_BLOCK_SIZE 512
 #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
 #define GPT_HEADER_REVISION_V1 0x00010000
 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL
@@ -112,7 +111,6 @@
 	__le32 num_partition_entries;
 	__le32 sizeof_partition_entry;
 	__le32 partition_entry_array_crc32;
-	u8 reserved2[GPT_BLOCK_SIZE - 92];
 } __packed gpt_header;
 
 typedef union _gpt_entry_attributes {
diff --git a/include/search.h b/include/search.h
index 13d3be6..d9ac8df 100644
--- a/include/search.h
+++ b/include/search.h
@@ -22,7 +22,7 @@
 /*
  * Based on code from uClibc-0.9.30.3
  * Extensions for use within U-Boot
- * Copyright (C) 2010 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
  */
 
 #ifndef _SEARCH_H
@@ -98,12 +98,6 @@
  */
 extern int hmatch_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
-/*
- * Search for an entry whose key or data contains `MATCH'.  Otherwise,
- * Same semantics as hsearch_r().
- */
-extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
-		    struct hsearch_data *__htab);
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
 extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
@@ -131,5 +125,12 @@
 #define H_FORCE		(1 << 1) /* overwrite read-only/write-once variables */
 #define H_INTERACTIVE	(1 << 2) /* indicate that an import is user directed */
 #define H_HIDE_DOT	(1 << 3) /* don't print env vars that begin with '.' */
+#define H_MATCH_KEY	(1 << 4) /* search/grep key  = variable names	     */
+#define H_MATCH_DATA	(1 << 5) /* search/grep data = variable values	     */
+#define H_MATCH_BOTH	(H_MATCH_KEY | H_MATCH_DATA) /* search/grep both     */
+#define H_MATCH_IDENT	(1 << 6) /* search for indentical strings	     */
+#define H_MATCH_SUBSTR	(1 << 7) /* search for substring matches	     */
+#define H_MATCH_REGEX	(1 << 8) /* search for regular expression matches    */
+#define H_MATCH_METHOD	(H_MATCH_IDENT | H_MATCH_SUBSTR | H_MATCH_REGEX)
 
 #endif /* search.h */
diff --git a/include/slre.h b/include/slre.h
new file mode 100644
index 0000000..4b41a4b
--- /dev/null
+++ b/include/slre.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
+ * All rights reserved
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Sergey Lyubka wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ */
+
+/*
+ * Downloaded Sat Nov  5 17:42:08 CET 2011 at
+ * http://slre.sourceforge.net/1.0/slre.h
+ */
+
+/*
+ * This is a regular expression library that implements a subset of Perl RE.
+ * Please refer to http://slre.sourceforge.net for detailed description.
+ *
+ * Usage example (parsing HTTP request):
+ *
+ * struct slre	slre;
+ * struct cap	captures[4 + 1];  // Number of braket pairs + 1
+ * ...
+ *
+ * slre_compile(&slre,"^(GET|POST) (\S+) HTTP/(\S+?)\r\n");
+ *
+ * if (slre_match(&slre, buf, len, captures)) {
+ *	printf("Request line length: %d\n", captures[0].len);
+ *	printf("Method: %.*s\n", captures[1].len, captures[1].ptr);
+ *	printf("URI: %.*s\n", captures[2].len, captures[2].ptr);
+ * }
+ *
+ * Supported syntax:
+ *	^		Match beginning of a buffer
+ *	$		Match end of a buffer
+ *	()		Grouping and substring capturing
+ *	[...]		Match any character from set
+ *	[^...]		Match any character but ones from set
+ *	\s		Match whitespace
+ *	\S		Match non-whitespace
+ *	\d		Match decimal digit
+ *	\r		Match carriage return
+ *	\n		Match newline
+ *	+		Match one or more times (greedy)
+ *	+?		Match one or more times (non-greedy)
+ *	*		Match zero or more times (greedy)
+ *	*?		Match zero or more times (non-greedy)
+ *	?		Match zero or once
+ *	\xDD		Match byte with hex value 0xDD
+ *	\meta		Match one of the meta character: ^$().[*+?\
+ */
+
+#ifndef SLRE_HEADER_DEFINED
+#define	SLRE_HEADER_DEFINED
+
+/*
+ * Compiled regular expression
+ */
+struct slre {
+	unsigned char	code[256];
+	unsigned char	data[256];
+	int		code_size;
+	int		data_size;
+	int		num_caps;	/* Number of bracket pairs	*/
+	int		anchored;	/* Must match from string start	*/
+	const char	*err_str;	/* Error string			*/
+};
+
+/*
+ * Captured substring
+ */
+struct cap {
+	const char	*ptr;		/* Pointer to the substring	*/
+	int		len;		/* Substring length		*/
+};
+
+/*
+ * Compile regular expression. If success, 1 is returned.
+ * If error, 0 is returned and slre.err_str points to the error message.
+ */
+int slre_compile(struct slre *, const char *re);
+
+/*
+ * Return 1 if match, 0 if no match.
+ * If `captured_substrings' array is not NULL, then it is filled with the
+ * values of captured substrings. captured_substrings[0] element is always
+ * a full matched substring. The round bracket captures start from
+ * captured_substrings[1].
+ * It is assumed that the size of captured_substrings array is enough to
+ * hold all captures. The caller function must make sure it is! So, the
+ * array_size = number_of_round_bracket_pairs + 1
+ */
+int slre_match(const struct slre *, const char *buf, int buf_len,
+	struct cap *captured_substrings);
+
+#ifdef SLRE_TEST
+void slre_dump(const struct slre *r, FILE *fp);
+#endif /* SLRE_TEST */
+#endif /* SLRE_HEADER_DEFINED */
diff --git a/lib/Makefile b/lib/Makefile
index e901cc7..8f81862 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -71,7 +71,9 @@
 COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += div64.o
+COBJS-y += hang.o
 COBJS-y += linux_string.o
+COBJS-$(CONFIG_REGEX) += slre.o
 COBJS-y += string.o
 COBJS-y += time.o
 COBJS-$(CONFIG_BOOTP_PXE) += uuid.o
diff --git a/lib/hang.c b/lib/hang.c
new file mode 100644
index 0000000..fc1286c
--- /dev/null
+++ b/lib/hang.c
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2013
+ * Andreas Bießmann <andreas.devel@googlemail.com>
+ *
+ * This file consolidates all the different hang() functions implemented in
+ * u-boot.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <bootstage.h>
+
+/**
+ * hang - stop processing by staying in an endless loop
+ *
+ * The purpose of this function is to stop further execution of code cause
+ * something went completely wrong.  To catch this and give some feedback to
+ * the user one needs to catch the bootstage_error (see show_boot_progress())
+ * in the board code.
+ */
+void hang(void)
+{
+#if !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \
+		defined(CONFIG_SPL_SERIAL_SUPPORT))
+	puts("### ERROR ### Please RESET the board ###\n");
+#endif
+	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
+	for (;;)
+		;
+}
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 07ebfb2..6050dd0 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -2,7 +2,7 @@
  * This implementation is based on code from uClibc-0.9.30.3 but was
  * modified and extended for use within U-Boot.
  *
- * Copyright (C) 2010 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
  *
  * Original license header:
  *
@@ -57,6 +57,7 @@
 #include <env_callback.h>
 #include <env_flags.h>
 #include <search.h>
+#include <slre.h>
 
 /*
  * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -210,29 +211,6 @@
  *   example for functions like hdelete().
  */
 
-/*
- * hstrstr_r - return index to entry whose key and/or data contains match
- */
-int hstrstr_r(const char *match, int last_idx, ENTRY ** retval,
-	      struct hsearch_data *htab)
-{
-	unsigned int idx;
-
-	for (idx = last_idx + 1; idx < htab->size; ++idx) {
-		if (htab->table[idx].used <= 0)
-			continue;
-		if (strstr(htab->table[idx].entry.key, match) ||
-		    strstr(htab->table[idx].entry.data, match)) {
-			*retval = &htab->table[idx].entry;
-			return idx;
-		}
-	}
-
-	__set_errno(ESRCH);
-	*retval = NULL;
-	return 0;
-}
-
 int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
 	     struct hsearch_data *htab)
 {
@@ -563,6 +541,65 @@
 	return (strcmp(e1->key, e2->key));
 }
 
+static int match_string(int flag, const char *str, const char *pat, void *priv)
+{
+	switch (flag & H_MATCH_METHOD) {
+	case H_MATCH_IDENT:
+		if (strcmp(str, pat) == 0)
+			return 1;
+		break;
+	case H_MATCH_SUBSTR:
+		if (strstr(str, pat))
+			return 1;
+		break;
+#ifdef CONFIG_REGEX
+	case H_MATCH_REGEX:
+		{
+			struct slre *slrep = (struct slre *)priv;
+			struct cap caps[slrep->num_caps + 2];
+
+			if (slre_match(slrep, str, strlen(str), caps))
+				return 1;
+		}
+		break;
+#endif
+	default:
+		printf("## ERROR: unsupported match method: 0x%02x\n",
+			flag & H_MATCH_METHOD);
+		break;
+	}
+	return 0;
+}
+
+static int match_entry(ENTRY *ep, int flag,
+		 int argc, char * const argv[])
+{
+	int arg;
+	void *priv = NULL;
+
+	for (arg = 1; arg < argc; ++arg) {
+#ifdef CONFIG_REGEX
+		struct slre slre;
+
+		if (slre_compile(&slre, argv[arg]) == 0) {
+			printf("Error compiling regex: %s\n", slre.err_str);
+			return 0;
+		}
+
+		priv = (void *)&slre;
+#endif
+		if (flag & H_MATCH_KEY) {
+			if (match_string(flag, ep->key, argv[arg], priv))
+				return 1;
+		}
+		if (flag & H_MATCH_DATA) {
+			if (match_string(flag, ep->data, argv[arg], priv))
+				return 1;
+		}
+	}
+	return 0;
+}
+
 ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 		 char **resp, size_t size,
 		 int argc, char * const argv[])
@@ -589,14 +626,8 @@
 
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-			int arg, found = 0;
+			int found = match_entry(ep, flag, argc, argv);
 
-			for (arg = 0; arg < argc; ++arg) {
-				if (strcmp(argv[arg], ep->key) == 0) {
-					found = 1;
-					break;
-				}
-			}
 			if ((argc > 0) && (found == 0))
 				continue;
 
diff --git a/lib/slre.c b/lib/slre.c
new file mode 100644
index 0000000..8cdd192
--- /dev/null
+++ b/lib/slre.c
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
+ * All rights reserved
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Sergey Lyubka wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ */
+
+/*
+ * Downloaded Sat Nov  5 17:43:06 CET 2011 at
+ * http://slre.sourceforge.net/1.0/slre.c
+ */
+
+#ifdef SLRE_TEST
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#else
+#include <common.h>
+#include <linux/ctype.h>
+#endif /* SLRE_TEST */
+
+#include <errno.h>
+
+#include <slre.h>
+
+enum {END, BRANCH, ANY, EXACT, ANYOF, ANYBUT, OPEN, CLOSE, BOL, EOL,
+	STAR, PLUS, STARQ, PLUSQ, QUEST, SPACE, NONSPACE, DIGIT};
+
+#ifdef SLRE_TEST
+static struct {
+	const char	*name;
+	int		narg;
+	const char	*flags;
+} opcodes[] = {
+	{"END",		0, ""},		/* End of code block or program	*/
+	{"BRANCH",	2, "oo"},	/* Alternative operator, "|"	*/
+	{"ANY",		0, ""},		/* Match any character, "."	*/
+	{"EXACT",	2, "d"},	/* Match exact string		*/
+	{"ANYOF",	2, "D"},	/* Match any from set, "[]"	*/
+	{"ANYBUT",	2, "D"},	/* Match any but from set, "[^]"*/
+	{"OPEN ",	1, "i"},	/* Capture start, "("		*/
+	{"CLOSE",	1, "i"},	/* Capture end, ")"		*/
+	{"BOL",		0, ""},		/* Beginning of string, "^"	*/
+	{"EOL",		0, ""},		/* End of string, "$"		*/
+	{"STAR",	1, "o"},	/* Match zero or more times "*"	*/
+	{"PLUS",	1, "o"},	/* Match one or more times, "+"	*/
+	{"STARQ",	1, "o"},	/* Non-greedy STAR,  "*?"	*/
+	{"PLUSQ",	1, "o"},	/* Non-greedy PLUS, "+?"	*/
+	{"QUEST",	1, "o"},	/* Match zero or one time, "?"	*/
+	{"SPACE",	0, ""},		/* Match whitespace, "\s"	*/
+	{"NONSPACE",	0, ""},		/* Match non-space, "\S"	*/
+	{"DIGIT",	0, ""}		/* Match digit, "\d"		*/
+};
+#endif /* SLRE_TEST */
+
+/*
+ * Commands and operands are all unsigned char (1 byte long). All code offsets
+ * are relative to current address, and positive (always point forward). Data
+ * offsets are absolute. Commands with operands:
+ *
+ * BRANCH offset1 offset2
+ *	Try to match the code block that follows the BRANCH instruction
+ *	(code block ends with END). If no match, try to match code block that
+ *	starts at offset1. If either of these match, jump to offset2.
+ *
+ * EXACT data_offset data_length
+ *	Try to match exact string. String is recorded in data section from
+ *	data_offset, and has length data_length.
+ *
+ * OPEN capture_number
+ * CLOSE capture_number
+ *	If the user have passed 'struct cap' array for captures, OPEN
+ *	records the beginning of the matched substring (cap->ptr), CLOSE
+ *	sets the length (cap->len) for respective capture_number.
+ *
+ * STAR code_offset
+ * PLUS code_offset
+ * QUEST code_offset
+ *	*, +, ?, respectively. Try to gobble as much as possible from the
+ *	matched buffer, until code block that follows these instructions
+ *	matches. When the longest possible string is matched,
+ *	jump to code_offset
+ *
+ * STARQ, PLUSQ are non-greedy versions of STAR and PLUS.
+ */
+
+static const char *meta_chars = "|.^$*+?()[\\";
+
+#ifdef SLRE_TEST
+
+static void
+print_character_set(FILE *fp, const unsigned char *p, int len)
+{
+	int	i;
+
+	for (i = 0; i < len; i++) {
+		if (i > 0)
+			(void) fputc(',', fp);
+		if (p[i] == 0) {
+			i++;
+			if (p[i] == 0)
+				(void) fprintf(fp, "\\x%02x", p[i]);
+			else
+				(void) fprintf(fp, "%s", opcodes[p[i]].name);
+		} else if (isprint(p[i])) {
+			(void) fputc(p[i], fp);
+		} else {
+			(void) fprintf(fp, "\\x%02x", p[i]);
+		}
+	}
+}
+
+void
+slre_dump(const struct slre *r, FILE *fp)
+{
+	int	i, j, ch, op, pc;
+
+	for (pc = 0; pc < r->code_size; pc++) {
+
+		op = r->code[pc];
+		(void) fprintf(fp, "%3d %s ", pc, opcodes[op].name);
+
+		for (i = 0; opcodes[op].flags[i] != '\0'; i++)
+			switch (opcodes[op].flags[i]) {
+			case 'i':
+				(void) fprintf(fp, "%d ", r->code[pc + 1]);
+				pc++;
+				break;
+			case 'o':
+				(void) fprintf(fp, "%d ",
+				    pc + r->code[pc + 1] - i);
+				pc++;
+				break;
+			case 'D':
+				print_character_set(fp, r->data +
+				    r->code[pc + 1], r->code[pc + 2]);
+				pc += 2;
+				break;
+			case 'd':
+				(void) fputc('"', fp);
+				for (j = 0; j < r->code[pc + 2]; j++) {
+					ch = r->data[r->code[pc + 1] + j];
+					if (isprint(ch)) {
+						(void) fputc(ch, fp);
+					} else {
+						(void) fprintf(fp,
+							"\\x%02x", ch);
+					}
+				}
+				(void) fputc('"', fp);
+				pc += 2;
+				break;
+			}
+
+		(void) fputc('\n', fp);
+	}
+}
+#endif /* SLRE_TEST */
+
+static void
+set_jump_offset(struct slre *r, int pc, int offset)
+{
+	assert(offset < r->code_size);
+
+	if (r->code_size - offset > 0xff)
+		r->err_str = "Jump offset is too big";
+	else
+		r->code[pc] = (unsigned char) (r->code_size - offset);
+}
+
+static void
+emit(struct slre *r, int code)
+{
+	if (r->code_size >= (int) (sizeof(r->code) / sizeof(r->code[0])))
+		r->err_str = "RE is too long (code overflow)";
+	else
+		r->code[r->code_size++] = (unsigned char) code;
+}
+
+static void
+store_char_in_data(struct slre *r, int ch)
+{
+	if (r->data_size >= (int) sizeof(r->data))
+		r->err_str = "RE is too long (data overflow)";
+	else
+		r->data[r->data_size++] = ch;
+}
+
+static void
+exact(struct slre *r, const char **re)
+{
+	int	old_data_size = r->data_size;
+
+	while (**re != '\0' && (strchr(meta_chars, **re)) == NULL)
+		store_char_in_data(r, *(*re)++);
+
+	emit(r, EXACT);
+	emit(r, old_data_size);
+	emit(r, r->data_size - old_data_size);
+}
+
+static int
+get_escape_char(const char **re)
+{
+	int	res;
+
+	switch (*(*re)++) {
+	case 'n':
+		res = '\n';
+		break;
+	case 'r':
+		res = '\r';
+		break;
+	case 't':
+		res = '\t';
+		break;
+	case '0':
+		res = 0;
+		break;
+	case 'S':
+		res = NONSPACE << 8;
+		break;
+	case 's':
+		res = SPACE << 8;
+		break;
+	case 'd':
+		res = DIGIT << 8;
+		break;
+	default:
+		res = (*re)[-1];
+		break;
+	}
+
+	return res;
+}
+
+static void
+anyof(struct slre *r, const char **re)
+{
+	int	esc, old_data_size = r->data_size, op = ANYOF;
+
+	if (**re == '^') {
+		op = ANYBUT;
+		(*re)++;
+	}
+
+	while (**re != '\0')
+
+		switch (*(*re)++) {
+		case ']':
+			emit(r, op);
+			emit(r, old_data_size);
+			emit(r, r->data_size - old_data_size);
+			return;
+			/* NOTREACHED */
+			break;
+		case '\\':
+			esc = get_escape_char(re);
+			if ((esc & 0xff) == 0) {
+				store_char_in_data(r, 0);
+				store_char_in_data(r, esc >> 8);
+			} else {
+				store_char_in_data(r, esc);
+			}
+			break;
+		default:
+			store_char_in_data(r, (*re)[-1]);
+			break;
+		}
+
+	r->err_str = "No closing ']' bracket";
+}
+
+static void
+relocate(struct slre *r, int begin, int shift)
+{
+	emit(r, END);
+	memmove(r->code + begin + shift, r->code + begin, r->code_size - begin);
+	r->code_size += shift;
+}
+
+static void
+quantifier(struct slre *r, int prev, int op)
+{
+	if (r->code[prev] == EXACT && r->code[prev + 2] > 1) {
+		r->code[prev + 2]--;
+		emit(r, EXACT);
+		emit(r, r->code[prev + 1] + r->code[prev + 2]);
+		emit(r, 1);
+		prev = r->code_size - 3;
+	}
+	relocate(r, prev, 2);
+	r->code[prev] = op;
+	set_jump_offset(r, prev + 1, prev);
+}
+
+static void
+exact_one_char(struct slre *r, int ch)
+{
+	emit(r, EXACT);
+	emit(r, r->data_size);
+	emit(r, 1);
+	store_char_in_data(r, ch);
+}
+
+static void
+fixup_branch(struct slre *r, int fixup)
+{
+	if (fixup > 0) {
+		emit(r, END);
+		set_jump_offset(r, fixup, fixup - 2);
+	}
+}
+
+static void
+compile(struct slre *r, const char **re)
+{
+	int	op, esc, branch_start, last_op, fixup, cap_no, level;
+
+	fixup = 0;
+	level = r->num_caps;
+	branch_start = last_op = r->code_size;
+
+	for (;;)
+		switch (*(*re)++) {
+		case '\0':
+			(*re)--;
+			return;
+			/* NOTREACHED */
+			break;
+		case '^':
+			emit(r, BOL);
+			break;
+		case '$':
+			emit(r, EOL);
+			break;
+		case '.':
+			last_op = r->code_size;
+			emit(r, ANY);
+			break;
+		case '[':
+			last_op = r->code_size;
+			anyof(r, re);
+			break;
+		case '\\':
+			last_op = r->code_size;
+			esc = get_escape_char(re);
+			if (esc & 0xff00)
+				emit(r, esc >> 8);
+			else
+				exact_one_char(r, esc);
+			break;
+		case '(':
+			last_op = r->code_size;
+			cap_no = ++r->num_caps;
+			emit(r, OPEN);
+			emit(r, cap_no);
+
+			compile(r, re);
+			if (*(*re)++ != ')') {
+				r->err_str = "No closing bracket";
+				return;
+			}
+
+			emit(r, CLOSE);
+			emit(r, cap_no);
+			break;
+		case ')':
+			(*re)--;
+			fixup_branch(r, fixup);
+			if (level == 0) {
+				r->err_str = "Unbalanced brackets";
+				return;
+			}
+			return;
+			/* NOTREACHED */
+			break;
+		case '+':
+		case '*':
+			op = (*re)[-1] == '*' ? STAR : PLUS;
+			if (**re == '?') {
+				(*re)++;
+				op = op == STAR ? STARQ : PLUSQ;
+			}
+			quantifier(r, last_op, op);
+			break;
+		case '?':
+			quantifier(r, last_op, QUEST);
+			break;
+		case '|':
+			fixup_branch(r, fixup);
+			relocate(r, branch_start, 3);
+			r->code[branch_start] = BRANCH;
+			set_jump_offset(r, branch_start + 1, branch_start);
+			fixup = branch_start + 2;
+			r->code[fixup] = 0xff;
+			break;
+		default:
+			(*re)--;
+			last_op = r->code_size;
+			exact(r, re);
+			break;
+		}
+}
+
+int
+slre_compile(struct slre *r, const char *re)
+{
+	r->err_str = NULL;
+	r->code_size = r->data_size = r->num_caps = r->anchored = 0;
+
+	if (*re == '^')
+		r->anchored++;
+
+	emit(r, OPEN);	/* This will capture what matches full RE */
+	emit(r, 0);
+
+	while (*re != '\0')
+		compile(r, &re);
+
+	if (r->code[2] == BRANCH)
+		fixup_branch(r, 4);
+
+	emit(r, CLOSE);
+	emit(r, 0);
+	emit(r, END);
+
+	return (r->err_str == NULL ? 1 : 0);
+}
+
+static int match(const struct slre *, int,
+		const char *, int, int *, struct cap *);
+
+static void
+loop_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+	int	saved_offset, matched_offset;
+
+	saved_offset = matched_offset = *ofs;
+
+	while (match(r, pc + 2, s, len, ofs, NULL)) {
+		saved_offset = *ofs;
+		if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+			matched_offset = saved_offset;
+		*ofs = saved_offset;
+	}
+
+	*ofs = matched_offset;
+}
+
+static void
+loop_non_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+	int	saved_offset = *ofs;
+
+	while (match(r, pc + 2, s, len, ofs, NULL)) {
+		saved_offset = *ofs;
+		if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+			break;
+	}
+
+	*ofs = saved_offset;
+}
+
+static int
+is_any_of(const unsigned char *p, int len, const char *s, int *ofs)
+{
+	int	i, ch;
+
+	ch = s[*ofs];
+
+	for (i = 0; i < len; i++)
+		if (p[i] == ch) {
+			(*ofs)++;
+			return 1;
+		}
+
+	return 0;
+}
+
+static int
+is_any_but(const unsigned char *p, int len, const char *s, int *ofs)
+{
+	int	i, ch;
+
+	ch = s[*ofs];
+
+	for (i = 0; i < len; i++) {
+		if (p[i] == ch)
+			return 0;
+	}
+
+	(*ofs)++;
+	return 1;
+}
+
+static int
+match(const struct slre *r, int pc, const char *s, int len,
+		int *ofs, struct cap *caps)
+{
+	int	n, saved_offset, res = 1;
+
+	while (res && r->code[pc] != END) {
+
+		assert(pc < r->code_size);
+		assert(pc < (int) (sizeof(r->code) / sizeof(r->code[0])));
+
+		switch (r->code[pc]) {
+		case BRANCH:
+			saved_offset = *ofs;
+			res = match(r, pc + 3, s, len, ofs, caps);
+			if (res == 0) {
+				*ofs = saved_offset;
+				res = match(r, pc + r->code[pc + 1],
+				    s, len, ofs, caps);
+			}
+			pc += r->code[pc + 2];
+			break;
+		case EXACT:
+			res = 0;
+			n = r->code[pc + 2];	/* String length */
+			if (n <= len - *ofs && !memcmp(s + *ofs, r->data +
+			    r->code[pc + 1], n)) {
+				(*ofs) += n;
+				res = 1;
+			}
+			pc += 3;
+			break;
+		case QUEST:
+			res = 1;
+			saved_offset = *ofs;
+			if (!match(r, pc + 2, s, len, ofs, caps))
+				*ofs = saved_offset;
+			pc += r->code[pc + 1];
+			break;
+		case STAR:
+			res = 1;
+			loop_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case STARQ:
+			res = 1;
+			loop_non_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case PLUS:
+			res = match(r, pc + 2, s, len, ofs, caps);
+			if (res == 0)
+				break;
+
+			loop_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case PLUSQ:
+			res = match(r, pc + 2, s, len, ofs, caps);
+			if (res == 0)
+				break;
+
+			loop_non_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case SPACE:
+			res = 0;
+			if (*ofs < len && isspace(((unsigned char *)s)[*ofs])) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case NONSPACE:
+			res = 0;
+			if (*ofs < len &&
+					!isspace(((unsigned char *)s)[*ofs])) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case DIGIT:
+			res = 0;
+			if (*ofs < len && isdigit(((unsigned char *)s)[*ofs])) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case ANY:
+			res = 0;
+			if (*ofs < len) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case ANYOF:
+			res = 0;
+			if (*ofs < len)
+				res = is_any_of(r->data + r->code[pc + 1],
+					r->code[pc + 2], s, ofs);
+			pc += 3;
+			break;
+		case ANYBUT:
+			res = 0;
+			if (*ofs < len)
+				res = is_any_but(r->data + r->code[pc + 1],
+					r->code[pc + 2], s, ofs);
+			pc += 3;
+			break;
+		case BOL:
+			res = *ofs == 0 ? 1 : 0;
+			pc++;
+			break;
+		case EOL:
+			res = *ofs == len ? 1 : 0;
+			pc++;
+			break;
+		case OPEN:
+			if (caps != NULL)
+				caps[r->code[pc + 1]].ptr = s + *ofs;
+			pc += 2;
+			break;
+		case CLOSE:
+			if (caps != NULL)
+				caps[r->code[pc + 1]].len = (s + *ofs) -
+				    caps[r->code[pc + 1]].ptr;
+			pc += 2;
+			break;
+		case END:
+			pc++;
+			break;
+		default:
+			printf("unknown cmd (%d) at %d\n", r->code[pc], pc);
+			assert(0);
+			break;
+		}
+	}
+
+	return res;
+}
+
+int
+slre_match(const struct slre *r, const char *buf, int len,
+		struct cap *caps)
+{
+	int	i, ofs = 0, res = 0;
+
+	if (r->anchored) {
+		res = match(r, 0, buf, len, &ofs, caps);
+	} else {
+		for (i = 0; i < len && res == 0; i++) {
+			ofs = i;
+			res = match(r, 0, buf, len, &ofs, caps);
+		}
+	}
+
+	return res;
+}
+
+#ifdef SLRE_TEST
+#define N_CAPS	5
+
+int main(int argc, char *argv[])
+{
+	struct slre	slre;
+	struct cap	caps[N_CAPS];
+	unsigned char	data[1 * 1024 * 1024];
+	FILE		*fp;
+	int		i, res, len;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s 'slre' <file>\n", argv[0]);
+		return 1;
+	}
+
+	fp = fopen(argv[2], "rb");
+	if (fp == NULL) {
+		fprintf(stderr, "Error: cannot open %s:%s\n",
+			argv[2], strerror(errno));
+		return 1;
+	}
+
+	if (!slre_compile(&slre, argv[1])) {
+		fprintf(stderr, "Error compiling slre: %s\n", slre.err_str);
+		return 1;
+	}
+	
+	slre_dump(&slre, stderr);
+
+	while (fgets(data, sizeof(data), fp) != NULL) {
+		len = strlen(data);
+
+		if ((len > 0) && (data[len-1] == '\n')) {
+			data[len-1] = '\0';
+			--len;
+		}
+
+		printf("Data = \"%s\"\n", data);
+
+		(void) memset(caps, 0, sizeof(caps));
+
+		res = 0;
+
+		res = slre_match(&slre, data, len, caps);
+		printf("Result [%d]: %d\n", i, res);
+
+		for (i = 0; i < N_CAPS; i++) {
+			if (caps[i].len > 0) {
+				printf("Substring %d: len=%d  [%.*s]\n", i,
+					caps[i].len,
+					caps[i].len, caps[i].ptr);
+			}
+		}
+		printf("----------------------------------------------------\n");
+	}
+	(void) fclose(fp);
+
+	return 0;
+}
+#endif /* SLRE_TEST */