diff --git a/README b/README
index 0491b1109a265c77b6734176a1700628b53d77d2..157cc9e2b2cb185694a053703356427cf9d87aca 100644
--- a/README
+++ b/README
@@ -646,6 +646,7 @@ The following options need to be configured:
 		CONFIG_CMD_FLASH	  flinfo, erase, protect
 		CONFIG_CMD_FPGA		  FPGA device initialization support
 		CONFIG_CMD_GO		* the 'go' command (exec code)
+		CONFIG_CMD_GREPENV	* search environment
 		CONFIG_CMD_HWFLOW	* RTS/CTS hw flow control
 		CONFIG_CMD_I2C		* I2C serial bus support
 		CONFIG_CMD_IDE		* IDE harddisk support
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index df0e6dbafdaa63f70ebd17463e82c9f97e6a1446..817f39b5d908cf5d7fa323f27591bf0d3034b403 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -4,7 +4,9 @@
  *
  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Andreas Heppel <aheppel@sysgo.de>
-
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -160,6 +162,37 @@ int do_env_print (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return rcode;
 }
 
+#ifdef CONFIG_CMD_GREPENV
+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;
+
+	if (argc < 2)
+		return cmd_usage(cmdtp);
+
+	memset(matched, 0, env_htab.size / 8);
+
+	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");
+			}
+			matched[idx / 8] |= 1 << (idx & 7);
+			rcode = 0;
+		}
+		arg++;
+	}
+
+	return rcode;
+}
+#endif
+
 /*
  * Set a new environment variable,
  * or replace or delete an existing one.
@@ -829,6 +862,9 @@ static cmd_tbl_t cmd_env_sub[] = {
 #if defined(CONFIG_CMD_EXPORTENV)
 	U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
 #endif
+#if defined(CONFIG_CMD_GREPENV)
+	U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
+#endif
 #if defined(CONFIG_CMD_IMPORTENV)
 	U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
 #endif
@@ -878,8 +914,11 @@ U_BOOT_CMD(
 #if defined(CONFIG_CMD_EDITENV)
 	"env edit name - edit environment variable\n"
 #endif
-	"env export [-t | -b | -c] addr [size] - export environmnt\n"
-	"env import [-d] [-t | -b | -c] addr [size] - import environmnt\n"
+	"env export [-t | -b | -c] addr [size] - export environment\n"
+#if defined(CONFIG_CMD_GREPENV)
+	"env grep string [...] - search environment\n"
+#endif
+	"env import [-d] [-t | -b | -c] addr [size] - import environment\n"
 	"env print [name ...] - print environment\n"
 #if defined(CONFIG_CMD_RUN)
 	"env run var [...] - run commands in an environment variable\n"
@@ -911,6 +950,16 @@ U_BOOT_CMD_COMPLETE(
 	var_complete
 );
 
+#ifdef CONFIG_CMD_GREPENV
+U_BOOT_CMD_COMPLETE(
+	grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
+	"search environment variables",
+	"string ...\n"
+	"    - list environment name=value pairs matching 'string'",
+	var_complete
+);
+#endif
+
 U_BOOT_CMD_COMPLETE(
 	setenv, CONFIG_SYS_MAXARGS, 0,	do_env_set,
 	"set environment variables",
diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h
index 4e2b3fb983d53ce35106bb9d1f993c33594f8174..bec8cd1ce15ed61e9f2a5d7ef0b52996f71d30e6 100644
--- a/include/configs/corenet_ds.h
+++ b/include/configs/corenet_ds.h
@@ -476,14 +476,15 @@
  */
 #include <config_cmd_default.h>
 
+#define CONFIG_CMD_DHCP
 #define CONFIG_CMD_ELF
 #define CONFIG_CMD_ERRATA
+#define CONFIG_CMD_GREPENV
 #define CONFIG_CMD_IRQ
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_SETEXPR
-#define CONFIG_CMD_DHCP
 
 #ifdef CONFIG_PCI
 #define CONFIG_CMD_PCI
diff --git a/include/search.h b/include/search.h
index a7c129377092c260e78006ffc495ca5f54a21879..c827d4dbee946f3ffa39a2499a4b2da9dcbf350c 100644
--- a/include/search.h
+++ b/include/search.h
@@ -80,6 +80,12 @@ extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
  */
 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);
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 92eaa3881ca2e46a2743f59c5714695580b24b58..19d5b158eeff52bf74606d17e391901ddeb226d3 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -202,6 +202,29 @@ void hdestroy_r(struct hsearch_data *htab)
  *   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)
 {