+static int do_env_delete(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ printf("Not implemented yet\n");
+ return 0;
+}
+
+/*
+ * env export [-t | -b | -c] addr [size]
+ * -t: export as text format; if size is given, data will be
+ * padded with '\0' bytes; if not, one terminating '\0'
+ * will be added (which is included in the "filesize"
+ * setting so you can for exmple copy this to flash and
+ * keep the termination).
+ * -b: export as binary format (name=value pairs separated by
+ * '\0', list end marked by double "\0\0")
+ * -c: export as checksum protected environment format as
+ * used for example by "saveenv" command
+ * addr: memory address where environment gets stored
+ * size: size of output buffer
+ *
+ * With "-c" and size is NOT given, then the export command will
+ * format the data as currently used for the persistent storage,
+ * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and
+ * prepend a valid CRC32 checksum and, in case of resundant
+ * environment, a "current" redundancy flag. If size is given, this
+ * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32
+ * checksum and redundancy flag will be inserted.
+ *
+ * With "-b" and "-t", always only the real data (including a
+ * terminating '\0' byte) will be written; here the optional size
+ * argument will be used to make sure not to overflow the user
+ * provided buffer; the command will abort if the size is not
+ * sufficient. Any remainign space will be '\0' padded.
+ *
+ * On successful return, the variable "filesize" will be set.
+ * Note that filesize includes the trailing/terminating '\0' byte(s).
+ *
+ * Usage szenario: create a text snapshot/backup of the current settings:
+ *
+ * => env export -t 100000
+ * => era ${backup_addr} +${filesize}
+ * => cp.b 100000 ${backup_addr} ${filesize}
+ *
+ * Re-import this snapshot, deleting all other settings:
+ *
+ * => env import -d -t ${backup_addr}
+ */
+static int do_env_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ char buf[32];
+ char *addr, *cmd, *res;
+ size_t size;
+ ssize_t len;
+ env_t *envp;
+ char sep = '\n';
+ int chk = 0;
+ int fmt = 0;
+
+ cmd = *argv;
+
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+ while (*++arg) {
+ switch (*arg) {
+ case 'b': /* raw binary format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ break;
+ case 'c': /* external checksum format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ chk = 1;
+ break;
+ case 't': /* text format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\n';
+ break;
+ default:
+ cmd_usage(cmdtp);
+ return 1;
+ }
+ }
+ }
+
+ if (argc < 1) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ addr = (char *)simple_strtoul(argv[0], NULL, 16);
+
+ if (argc == 2) {
+ size = simple_strtoul(argv[1], NULL, 16);
+ memset(addr, '\0', size);
+ } else {
+ size = 0;
+ }
+
+ if (sep) { /* export as text file */
+ len = hexport(sep, &addr, size);
+ if (len < 0) {
+ error("Cannot export environment: errno = %d\n",
+ errno);
+ return 1;
+ }
+ sprintf(buf, "%zX", len);
+ setenv("filesize", buf);
+
+ return 0;
+ }
+
+ envp = (env_t *)addr;
+
+ if (chk) /* export as checksum protected block */
+ res = (char *)envp->data;
+ else /* export as raw binary data */
+ res = addr;
+
+ len = hexport('\0', &res, ENV_SIZE);
+ if (len < 0) {
+ error("Cannot export environment: errno = %d\n",
+ errno);
+ return 1;
+ }
+
+ if (chk) {
+ envp->crc = crc32(0, envp->data, ENV_SIZE);
+#ifdef CONFIG_ENV_ADDR_REDUND
+ envp->flags = ACTIVE_FLAG;
+#endif
+ }
+ sprintf(buf, "%zX", len + offsetof(env_t,data));
+ setenv("filesize", buf);
+
+ return 0;
+
+sep_err:
+ printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
+ cmd);
+ return 1;
+}
+
+/*
+ * env import [-d] [-t | -b | -c] addr [size]
+ * -d: delete existing environment before importing;
+ * otherwise overwrite / append to existion definitions
+ * -t: assume text format; either "size" must be given or the
+ * text data must be '\0' terminated
+ * -b: assume binary format ('\0' separated, "\0\0" terminated)
+ * -c: assume checksum protected environment format
+ * addr: memory address to read from
+ * size: length of input data; if missing, proper '\0'
+ * termination is mandatory
+ */
+static int do_env_import(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ char *cmd, *addr;
+ char sep = '\n';
+ int chk = 0;
+ int fmt = 0;
+ int del = 0;
+ size_t size;
+
+ cmd = *argv;
+
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+ while (*++arg) {
+ switch (*arg) {
+ case 'b': /* raw binary format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ break;
+ case 'c': /* external checksum format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ chk = 1;
+ break;
+ case 't': /* text format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\n';
+ break;
+ case 'd':
+ del = 1;
+ break;
+ default:
+ cmd_usage(cmdtp);
+ return 1;
+ }
+ }
+ }
+
+ if (argc < 1) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ if (!fmt)
+ printf("## Warning: defaulting to text format\n");
+
+ addr = (char *)simple_strtoul(argv[0], NULL, 16);
+
+ if (argc == 2) {
+ size = simple_strtoul(argv[1], NULL, 16);
+ } else {
+ char *s = addr;
+
+ size = 0;
+
+ while (size < MAX_ENV_SIZE) {
+ if ((*s == sep) && (*(s+1) == '\0'))
+ break;
+ ++s;
+ ++size;
+ }
+ if (size == MAX_ENV_SIZE) {
+ printf("## Warning: Input data exceeds %d bytes"
+ " - truncated\n", MAX_ENV_SIZE);
+ }
+ ++size;
+ printf("## Info: input data size = %zd = 0x%zX\n", size, size);
+ }
+
+ if (chk) {
+ uint32_t crc;
+ env_t *ep = (env_t *)addr;
+
+ size -= offsetof(env_t, data);
+ memcpy(&crc, &ep->crc, sizeof(crc));
+
+ if (crc32(0, ep->data, size) != crc) {
+ puts("## Error: bad CRC, import failed\n");
+ return 1;
+ }
+ addr = (char *)ep->data;
+ }
+
+ if (himport(addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
+ error("Environment import failed: errno = %d\n", errno);
+ return 1;
+ }
+ gd->flags |= GD_FLG_ENV_READY;
+
+ return 0;
+
+sep_err:
+ printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
+ cmd);
+ return 1;
+}
+
+#if defined(CONFIG_CMD_RUN)
+extern int do_run (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+#endif
+
+/*
+ * New command line interface: "env" command with subcommands
+ */
+static cmd_tbl_t cmd_env_sub[] = {
+#if defined(CONFIG_CMD_ASKENV)
+ U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""),
+ U_BOOT_CMD_MKENT(delete, 2, 0, do_env_delete, "", ""),
+#if defined(CONFIG_CMD_EDITENV)
+ U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
+ U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
+ U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
+#if defined(CONFIG_CMD_RUN)
+ U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
+#endif
+#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+ U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
+};
+
+#if !defined(CONFIG_RELOC_FIXUP_WORKS)
+void env_reloc(void)
+{
+ fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
+}
+#endif
+
+static int do_env (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ cmd_tbl_t *cp;
+
+ /* drop initial "env" arg */
+ argc--;
+ argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
+
+ if (cp)
+ return cp->cmd(cmdtp, flag, argc, argv);
+
+ cmd_usage(cmdtp);
+ return 1;
+}
+
+U_BOOT_CMD(
+ env, CONFIG_SYS_MAXARGS, 1, do_env,
+ "environment handling commands",
+#if defined(CONFIG_CMD_ASKENV)
+ "ask name [message] [size] - ask for environment variable\nenv "
+#endif
+ "default -f - reset default environment\n"
+#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 print [name ...] - print environment\n"
+#if defined(CONFIG_CMD_RUN)
+ "env run var [...] - run commands in an environment variable\n"
+#endif
+ "env save - save environment\n"
+ "env set [-f] name [arg ...]\n"
+);
+
+/*
+ * Old command line interface, kept for compatibility
+ */
+
+#if defined(CONFIG_CMD_EDITENV)
+U_BOOT_CMD(
+ editenv, 2, 0, do_env_edit,
+ "edit environment variable",
+ "name\n"
+ " - edit environment variable 'name'"
+);
+#endif