xref: /openbmc/u-boot/cmd/nvedit.c (revision c68c03f52badc90951dbf8a054c0e500e04bf365)
1  /*
2   * (C) Copyright 2000-2013
3   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4   *
5   * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6   * Andreas Heppel <aheppel@sysgo.de>
7   *
8   * Copyright 2011 Freescale Semiconductor, Inc.
9   *
10   * SPDX-License-Identifier:	GPL-2.0+
11   */
12  
13  /*
14   * Support for persistent environment data
15   *
16   * The "environment" is stored on external storage as a list of '\0'
17   * terminated "name=value" strings. The end of the list is marked by
18   * a double '\0'. The environment is preceded by a 32 bit CRC over
19   * the data part and, in case of redundant environment, a byte of
20   * flags.
21   *
22   * This linearized representation will also be used before
23   * relocation, i. e. as long as we don't have a full C runtime
24   * environment. After that, we use a hash table.
25   */
26  
27  #include <common.h>
28  #include <cli.h>
29  #include <command.h>
30  #include <console.h>
31  #include <environment.h>
32  #include <search.h>
33  #include <errno.h>
34  #include <malloc.h>
35  #include <mapmem.h>
36  #include <watchdog.h>
37  #include <linux/stddef.h>
38  #include <asm/byteorder.h>
39  #include <asm/io.h>
40  
41  DECLARE_GLOBAL_DATA_PTR;
42  
43  #if	!defined(CONFIG_ENV_IS_IN_EEPROM)	&& \
44  	!defined(CONFIG_ENV_IS_IN_FLASH)	&& \
45  	!defined(CONFIG_ENV_IS_IN_MMC)		&& \
46  	!defined(CONFIG_ENV_IS_IN_FAT)		&& \
47  	!defined(CONFIG_ENV_IS_IN_EXT4)		&& \
48  	!defined(CONFIG_ENV_IS_IN_NAND)		&& \
49  	!defined(CONFIG_ENV_IS_IN_NVRAM)	&& \
50  	!defined(CONFIG_ENV_IS_IN_ONENAND)	&& \
51  	!defined(CONFIG_ENV_IS_IN_SATA)		&& \
52  	!defined(CONFIG_ENV_IS_IN_SPI_FLASH)	&& \
53  	!defined(CONFIG_ENV_IS_IN_REMOTE)	&& \
54  	!defined(CONFIG_ENV_IS_IN_UBI)		&& \
55  	!defined(CONFIG_ENV_IS_NOWHERE)
56  # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
57  NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
58  #endif
59  
60  /*
61   * Maximum expected input data size for import command
62   */
63  #define	MAX_ENV_SIZE	(1 << 20)	/* 1 MiB */
64  
65  /*
66   * This variable is incremented on each do_env_set(), so it can
67   * be used via get_env_id() as an indication, if the environment
68   * has changed or not. So it is possible to reread an environment
69   * variable only if the environment was changed ... done so for
70   * example in NetInitLoop()
71   */
72  static int env_id = 1;
73  
74  int get_env_id(void)
75  {
76  	return env_id;
77  }
78  
79  #ifndef CONFIG_SPL_BUILD
80  /*
81   * Command interface: print one or all environment variables
82   *
83   * Returns 0 in case of error, or length of printed string
84   */
85  static int env_print(char *name, int flag)
86  {
87  	char *res = NULL;
88  	ssize_t len;
89  
90  	if (name) {		/* print a single name */
91  		ENTRY e, *ep;
92  
93  		e.key = name;
94  		e.data = NULL;
95  		hsearch_r(e, FIND, &ep, &env_htab, flag);
96  		if (ep == NULL)
97  			return 0;
98  		len = printf("%s=%s\n", ep->key, ep->data);
99  		return len;
100  	}
101  
102  	/* print whole list */
103  	len = hexport_r(&env_htab, '\n', flag, &res, 0, 0, NULL);
104  
105  	if (len > 0) {
106  		puts(res);
107  		free(res);
108  		return len;
109  	}
110  
111  	/* should never happen */
112  	printf("## Error: cannot export environment\n");
113  	return 0;
114  }
115  
116  static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
117  			char * const argv[])
118  {
119  	int i;
120  	int rcode = 0;
121  	int env_flag = H_HIDE_DOT;
122  
123  	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'a') {
124  		argc--;
125  		argv++;
126  		env_flag &= ~H_HIDE_DOT;
127  	}
128  
129  	if (argc == 1) {
130  		/* print all env vars */
131  		rcode = env_print(NULL, env_flag);
132  		if (!rcode)
133  			return 1;
134  		printf("\nEnvironment size: %d/%ld bytes\n",
135  			rcode, (ulong)ENV_SIZE);
136  		return 0;
137  	}
138  
139  	/* print selected env vars */
140  	env_flag &= ~H_HIDE_DOT;
141  	for (i = 1; i < argc; ++i) {
142  		int rc = env_print(argv[i], env_flag);
143  		if (!rc) {
144  			printf("## Error: \"%s\" not defined\n", argv[i]);
145  			++rcode;
146  		}
147  	}
148  
149  	return rcode;
150  }
151  
152  #ifdef CONFIG_CMD_GREPENV
153  static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
154  		       int argc, char * const argv[])
155  {
156  	char *res = NULL;
157  	int len, grep_how, grep_what;
158  
159  	if (argc < 2)
160  		return CMD_RET_USAGE;
161  
162  	grep_how  = H_MATCH_SUBSTR;	/* default: substring search	*/
163  	grep_what = H_MATCH_BOTH;	/* default: grep names and values */
164  
165  	while (--argc > 0 && **++argv == '-') {
166  		char *arg = *argv;
167  		while (*++arg) {
168  			switch (*arg) {
169  #ifdef CONFIG_REGEX
170  			case 'e':		/* use regex matching */
171  				grep_how  = H_MATCH_REGEX;
172  				break;
173  #endif
174  			case 'n':		/* grep for name */
175  				grep_what = H_MATCH_KEY;
176  				break;
177  			case 'v':		/* grep for value */
178  				grep_what = H_MATCH_DATA;
179  				break;
180  			case 'b':		/* grep for both */
181  				grep_what = H_MATCH_BOTH;
182  				break;
183  			case '-':
184  				goto DONE;
185  			default:
186  				return CMD_RET_USAGE;
187  			}
188  		}
189  	}
190  
191  DONE:
192  	len = hexport_r(&env_htab, '\n',
193  			flag | grep_what | grep_how,
194  			&res, 0, argc, argv);
195  
196  	if (len > 0) {
197  		puts(res);
198  		free(res);
199  	}
200  
201  	if (len < 2)
202  		return 1;
203  
204  	return 0;
205  }
206  #endif
207  #endif /* CONFIG_SPL_BUILD */
208  
209  /*
210   * Set a new environment variable,
211   * or replace or delete an existing one.
212   */
213  static int _do_env_set(int flag, int argc, char * const argv[], int env_flag)
214  {
215  	int   i, len;
216  	char  *name, *value, *s;
217  	ENTRY e, *ep;
218  
219  	debug("Initial value for argc=%d\n", argc);
220  	while (argc > 1 && **(argv + 1) == '-') {
221  		char *arg = *++argv;
222  
223  		--argc;
224  		while (*++arg) {
225  			switch (*arg) {
226  			case 'f':		/* force */
227  				env_flag |= H_FORCE;
228  				break;
229  			default:
230  				return CMD_RET_USAGE;
231  			}
232  		}
233  	}
234  	debug("Final value for argc=%d\n", argc);
235  	name = argv[1];
236  
237  	if (strchr(name, '=')) {
238  		printf("## Error: illegal character '='"
239  		       "in variable name \"%s\"\n", name);
240  		return 1;
241  	}
242  
243  	env_id++;
244  
245  	/* Delete only ? */
246  	if (argc < 3 || argv[2] == NULL) {
247  		int rc = hdelete_r(name, &env_htab, env_flag);
248  		return !rc;
249  	}
250  
251  	/*
252  	 * Insert / replace new value
253  	 */
254  	for (i = 2, len = 0; i < argc; ++i)
255  		len += strlen(argv[i]) + 1;
256  
257  	value = malloc(len);
258  	if (value == NULL) {
259  		printf("## Can't malloc %d bytes\n", len);
260  		return 1;
261  	}
262  	for (i = 2, s = value; i < argc; ++i) {
263  		char *v = argv[i];
264  
265  		while ((*s++ = *v++) != '\0')
266  			;
267  		*(s - 1) = ' ';
268  	}
269  	if (s != value)
270  		*--s = '\0';
271  
272  	e.key	= name;
273  	e.data	= value;
274  	hsearch_r(e, ENTER, &ep, &env_htab, env_flag);
275  	free(value);
276  	if (!ep) {
277  		printf("## Error inserting \"%s\" variable, errno=%d\n",
278  			name, errno);
279  		return 1;
280  	}
281  
282  	return 0;
283  }
284  
285  int env_set(const char *varname, const char *varvalue)
286  {
287  	const char * const argv[4] = { "setenv", varname, varvalue, NULL };
288  
289  	/* before import into hashtable */
290  	if (!(gd->flags & GD_FLG_ENV_READY))
291  		return 1;
292  
293  	if (varvalue == NULL || varvalue[0] == '\0')
294  		return _do_env_set(0, 2, (char * const *)argv, H_PROGRAMMATIC);
295  	else
296  		return _do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
297  }
298  
299  /**
300   * Set an environment variable to an integer value
301   *
302   * @param varname	Environment variable to set
303   * @param value		Value to set it to
304   * @return 0 if ok, 1 on error
305   */
306  int env_set_ulong(const char *varname, ulong value)
307  {
308  	/* TODO: this should be unsigned */
309  	char *str = simple_itoa(value);
310  
311  	return env_set(varname, str);
312  }
313  
314  /**
315   * Set an environment variable to an value in hex
316   *
317   * @param varname	Environment variable to set
318   * @param value		Value to set it to
319   * @return 0 if ok, 1 on error
320   */
321  int env_set_hex(const char *varname, ulong value)
322  {
323  	char str[17];
324  
325  	sprintf(str, "%lx", value);
326  	return env_set(varname, str);
327  }
328  
329  ulong env_get_hex(const char *varname, ulong default_val)
330  {
331  	const char *s;
332  	ulong value;
333  	char *endp;
334  
335  	s = env_get(varname);
336  	if (s)
337  		value = simple_strtoul(s, &endp, 16);
338  	if (!s || endp == s)
339  		return default_val;
340  
341  	return value;
342  }
343  
344  #ifndef CONFIG_SPL_BUILD
345  static int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
346  {
347  	if (argc < 2)
348  		return CMD_RET_USAGE;
349  
350  	return _do_env_set(flag, argc, argv, H_INTERACTIVE);
351  }
352  
353  /*
354   * Prompt for environment variable
355   */
356  #if defined(CONFIG_CMD_ASKENV)
357  int do_env_ask(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
358  {
359  	char message[CONFIG_SYS_CBSIZE];
360  	int i, len, pos, size;
361  	char *local_args[4];
362  	char *endptr;
363  
364  	local_args[0] = argv[0];
365  	local_args[1] = argv[1];
366  	local_args[2] = NULL;
367  	local_args[3] = NULL;
368  
369  	/*
370  	 * Check the syntax:
371  	 *
372  	 * env_ask envname [message1 ...] [size]
373  	 */
374  	if (argc == 1)
375  		return CMD_RET_USAGE;
376  
377  	/*
378  	 * We test the last argument if it can be converted
379  	 * into a decimal number.  If yes, we assume it's
380  	 * the size.  Otherwise we echo it as part of the
381  	 * message.
382  	 */
383  	i = simple_strtoul(argv[argc - 1], &endptr, 10);
384  	if (*endptr != '\0') {			/* no size */
385  		size = CONFIG_SYS_CBSIZE - 1;
386  	} else {				/* size given */
387  		size = i;
388  		--argc;
389  	}
390  
391  	if (argc <= 2) {
392  		sprintf(message, "Please enter '%s': ", argv[1]);
393  	} else {
394  		/* env_ask envname message1 ... messagen [size] */
395  		for (i = 2, pos = 0; i < argc && pos+1 < sizeof(message); i++) {
396  			if (pos)
397  				message[pos++] = ' ';
398  
399  			strncpy(message + pos, argv[i], sizeof(message) - pos);
400  			pos += strlen(argv[i]);
401  		}
402  		if (pos < sizeof(message) - 1) {
403  			message[pos++] = ' ';
404  			message[pos] = '\0';
405  		} else
406  			message[CONFIG_SYS_CBSIZE - 1] = '\0';
407  	}
408  
409  	if (size >= CONFIG_SYS_CBSIZE)
410  		size = CONFIG_SYS_CBSIZE - 1;
411  
412  	if (size <= 0)
413  		return 1;
414  
415  	/* prompt for input */
416  	len = cli_readline(message);
417  
418  	if (size < len)
419  		console_buffer[size] = '\0';
420  
421  	len = 2;
422  	if (console_buffer[0] != '\0') {
423  		local_args[2] = console_buffer;
424  		len = 3;
425  	}
426  
427  	/* Continue calling setenv code */
428  	return _do_env_set(flag, len, local_args, H_INTERACTIVE);
429  }
430  #endif
431  
432  #if defined(CONFIG_CMD_ENV_CALLBACK)
433  static int print_static_binding(const char *var_name, const char *callback_name,
434  				void *priv)
435  {
436  	printf("\t%-20s %-20s\n", var_name, callback_name);
437  
438  	return 0;
439  }
440  
441  static int print_active_callback(ENTRY *entry)
442  {
443  	struct env_clbk_tbl *clbkp;
444  	int i;
445  	int num_callbacks;
446  
447  	if (entry->callback == NULL)
448  		return 0;
449  
450  	/* look up the callback in the linker-list */
451  	num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
452  	for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
453  	     i < num_callbacks;
454  	     i++, clbkp++) {
455  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
456  		if (entry->callback == clbkp->callback + gd->reloc_off)
457  #else
458  		if (entry->callback == clbkp->callback)
459  #endif
460  			break;
461  	}
462  
463  	if (i == num_callbacks)
464  		/* this should probably never happen, but just in case... */
465  		printf("\t%-20s %p\n", entry->key, entry->callback);
466  	else
467  		printf("\t%-20s %-20s\n", entry->key, clbkp->name);
468  
469  	return 0;
470  }
471  
472  /*
473   * Print the callbacks available and what they are bound to
474   */
475  int do_env_callback(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
476  {
477  	struct env_clbk_tbl *clbkp;
478  	int i;
479  	int num_callbacks;
480  
481  	/* Print the available callbacks */
482  	puts("Available callbacks:\n");
483  	puts("\tCallback Name\n");
484  	puts("\t-------------\n");
485  	num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
486  	for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
487  	     i < num_callbacks;
488  	     i++, clbkp++)
489  		printf("\t%s\n", clbkp->name);
490  	puts("\n");
491  
492  	/* Print the static bindings that may exist */
493  	puts("Static callback bindings:\n");
494  	printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
495  	printf("\t%-20s %-20s\n", "-------------", "-------------");
496  	env_attr_walk(ENV_CALLBACK_LIST_STATIC, print_static_binding, NULL);
497  	puts("\n");
498  
499  	/* walk through each variable and print the callback if it has one */
500  	puts("Active callback bindings:\n");
501  	printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
502  	printf("\t%-20s %-20s\n", "-------------", "-------------");
503  	hwalk_r(&env_htab, print_active_callback);
504  	return 0;
505  }
506  #endif
507  
508  #if defined(CONFIG_CMD_ENV_FLAGS)
509  static int print_static_flags(const char *var_name, const char *flags,
510  			      void *priv)
511  {
512  	enum env_flags_vartype type = env_flags_parse_vartype(flags);
513  	enum env_flags_varaccess access = env_flags_parse_varaccess(flags);
514  
515  	printf("\t%-20s %-20s %-20s\n", var_name,
516  		env_flags_get_vartype_name(type),
517  		env_flags_get_varaccess_name(access));
518  
519  	return 0;
520  }
521  
522  static int print_active_flags(ENTRY *entry)
523  {
524  	enum env_flags_vartype type;
525  	enum env_flags_varaccess access;
526  
527  	if (entry->flags == 0)
528  		return 0;
529  
530  	type = (enum env_flags_vartype)
531  		(entry->flags & ENV_FLAGS_VARTYPE_BIN_MASK);
532  	access = env_flags_parse_varaccess_from_binflags(entry->flags);
533  	printf("\t%-20s %-20s %-20s\n", entry->key,
534  		env_flags_get_vartype_name(type),
535  		env_flags_get_varaccess_name(access));
536  
537  	return 0;
538  }
539  
540  /*
541   * Print the flags available and what variables have flags
542   */
543  int do_env_flags(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
544  {
545  	/* Print the available variable types */
546  	printf("Available variable type flags (position %d):\n",
547  		ENV_FLAGS_VARTYPE_LOC);
548  	puts("\tFlag\tVariable Type Name\n");
549  	puts("\t----\t------------------\n");
550  	env_flags_print_vartypes();
551  	puts("\n");
552  
553  	/* Print the available variable access types */
554  	printf("Available variable access flags (position %d):\n",
555  		ENV_FLAGS_VARACCESS_LOC);
556  	puts("\tFlag\tVariable Access Name\n");
557  	puts("\t----\t--------------------\n");
558  	env_flags_print_varaccess();
559  	puts("\n");
560  
561  	/* Print the static flags that may exist */
562  	puts("Static flags:\n");
563  	printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
564  		"Variable Access");
565  	printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
566  		"---------------");
567  	env_attr_walk(ENV_FLAGS_LIST_STATIC, print_static_flags, NULL);
568  	puts("\n");
569  
570  	/* walk through each variable and print the flags if non-default */
571  	puts("Active flags:\n");
572  	printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
573  		"Variable Access");
574  	printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
575  		"---------------");
576  	hwalk_r(&env_htab, print_active_flags);
577  	return 0;
578  }
579  #endif
580  
581  /*
582   * Interactively edit an environment variable
583   */
584  #if defined(CONFIG_CMD_EDITENV)
585  static int do_env_edit(cmd_tbl_t *cmdtp, int flag, int argc,
586  		       char * const argv[])
587  {
588  	char buffer[CONFIG_SYS_CBSIZE];
589  	char *init_val;
590  
591  	if (argc < 2)
592  		return CMD_RET_USAGE;
593  
594  	/* before import into hashtable */
595  	if (!(gd->flags & GD_FLG_ENV_READY))
596  		return 1;
597  
598  	/* Set read buffer to initial value or empty sting */
599  	init_val = env_get(argv[1]);
600  	if (init_val)
601  		snprintf(buffer, CONFIG_SYS_CBSIZE, "%s", init_val);
602  	else
603  		buffer[0] = '\0';
604  
605  	if (cli_readline_into_buffer("edit: ", buffer, 0) < 0)
606  		return 1;
607  
608  	if (buffer[0] == '\0') {
609  		const char * const _argv[3] = { "setenv", argv[1], NULL };
610  
611  		return _do_env_set(0, 2, (char * const *)_argv, H_INTERACTIVE);
612  	} else {
613  		const char * const _argv[4] = { "setenv", argv[1], buffer,
614  			NULL };
615  
616  		return _do_env_set(0, 3, (char * const *)_argv, H_INTERACTIVE);
617  	}
618  }
619  #endif /* CONFIG_CMD_EDITENV */
620  #endif /* CONFIG_SPL_BUILD */
621  
622  /*
623   * Look up variable from environment,
624   * return address of storage for that variable,
625   * or NULL if not found
626   */
627  char *env_get(const char *name)
628  {
629  	if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */
630  		ENTRY e, *ep;
631  
632  		WATCHDOG_RESET();
633  
634  		e.key	= name;
635  		e.data	= NULL;
636  		hsearch_r(e, FIND, &ep, &env_htab, 0);
637  
638  		return ep ? ep->data : NULL;
639  	}
640  
641  	/* restricted capabilities before import */
642  	if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
643  		return (char *)(gd->env_buf);
644  
645  	return NULL;
646  }
647  
648  /*
649   * Look up variable from environment for restricted C runtime env.
650   */
651  int env_get_f(const char *name, char *buf, unsigned len)
652  {
653  	int i, nxt;
654  
655  	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
656  		int val, n;
657  
658  		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
659  			if (nxt >= CONFIG_ENV_SIZE)
660  				return -1;
661  		}
662  
663  		val = envmatch((uchar *)name, i);
664  		if (val < 0)
665  			continue;
666  
667  		/* found; copy out */
668  		for (n = 0; n < len; ++n, ++buf) {
669  			*buf = env_get_char(val++);
670  			if (*buf == '\0')
671  				return n;
672  		}
673  
674  		if (n)
675  			*--buf = '\0';
676  
677  		printf("env_buf [%d bytes] too small for value of \"%s\"\n",
678  			len, name);
679  
680  		return n;
681  	}
682  
683  	return -1;
684  }
685  
686  /**
687   * Decode the integer value of an environment variable and return it.
688   *
689   * @param name		Name of environemnt variable
690   * @param base		Number base to use (normally 10, or 16 for hex)
691   * @param default_val	Default value to return if the variable is not
692   *			found
693   * @return the decoded value, or default_val if not found
694   */
695  ulong env_get_ulong(const char *name, int base, ulong default_val)
696  {
697  	/*
698  	 * We can use env_get() here, even before relocation, since the
699  	 * environment variable value is an integer and thus short.
700  	 */
701  	const char *str = env_get(name);
702  
703  	return str ? simple_strtoul(str, NULL, base) : default_val;
704  }
705  
706  #ifndef CONFIG_SPL_BUILD
707  #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
708  static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc,
709  		       char * const argv[])
710  {
711  	struct env_driver *env = env_driver_lookup_default();
712  
713  	printf("Saving Environment to %s...\n", env->name);
714  
715  	return env_save() ? 1 : 0;
716  }
717  
718  U_BOOT_CMD(
719  	saveenv, 1, 0,	do_env_save,
720  	"save environment variables to persistent storage",
721  	""
722  );
723  #endif
724  #endif /* CONFIG_SPL_BUILD */
725  
726  
727  /*
728   * Match a name / name=value pair
729   *
730   * s1 is either a simple 'name', or a 'name=value' pair.
731   * i2 is the environment index for a 'name2=value2' pair.
732   * If the names match, return the index for the value2, else -1.
733   */
734  int envmatch(uchar *s1, int i2)
735  {
736  	if (s1 == NULL)
737  		return -1;
738  
739  	while (*s1 == env_get_char(i2++))
740  		if (*s1++ == '=')
741  			return i2;
742  
743  	if (*s1 == '\0' && env_get_char(i2-1) == '=')
744  		return i2;
745  
746  	return -1;
747  }
748  
749  #ifndef CONFIG_SPL_BUILD
750  static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
751  			  int argc, char * const argv[])
752  {
753  	int all = 0, flag = 0;
754  
755  	debug("Initial value for argc=%d\n", argc);
756  	while (--argc > 0 && **++argv == '-') {
757  		char *arg = *argv;
758  
759  		while (*++arg) {
760  			switch (*arg) {
761  			case 'a':		/* default all */
762  				all = 1;
763  				break;
764  			case 'f':		/* force */
765  				flag |= H_FORCE;
766  				break;
767  			default:
768  				return cmd_usage(cmdtp);
769  			}
770  		}
771  	}
772  	debug("Final value for argc=%d\n", argc);
773  	if (all && (argc == 0)) {
774  		/* Reset the whole environment */
775  		set_default_env("## Resetting to default environment\n");
776  		return 0;
777  	}
778  	if (!all && (argc > 0)) {
779  		/* Reset individual variables */
780  		set_default_vars(argc, argv);
781  		return 0;
782  	}
783  
784  	return cmd_usage(cmdtp);
785  }
786  
787  static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
788  			 int argc, char * const argv[])
789  {
790  	int env_flag = H_INTERACTIVE;
791  	int ret = 0;
792  
793  	debug("Initial value for argc=%d\n", argc);
794  	while (argc > 1 && **(argv + 1) == '-') {
795  		char *arg = *++argv;
796  
797  		--argc;
798  		while (*++arg) {
799  			switch (*arg) {
800  			case 'f':		/* force */
801  				env_flag |= H_FORCE;
802  				break;
803  			default:
804  				return CMD_RET_USAGE;
805  			}
806  		}
807  	}
808  	debug("Final value for argc=%d\n", argc);
809  
810  	env_id++;
811  
812  	while (--argc > 0) {
813  		char *name = *++argv;
814  
815  		if (!hdelete_r(name, &env_htab, env_flag))
816  			ret = 1;
817  	}
818  
819  	return ret;
820  }
821  
822  #ifdef CONFIG_CMD_EXPORTENV
823  /*
824   * env export [-t | -b | -c] [-s size] addr [var ...]
825   *	-t:	export as text format; if size is given, data will be
826   *		padded with '\0' bytes; if not, one terminating '\0'
827   *		will be added (which is included in the "filesize"
828   *		setting so you can for exmple copy this to flash and
829   *		keep the termination).
830   *	-b:	export as binary format (name=value pairs separated by
831   *		'\0', list end marked by double "\0\0")
832   *	-c:	export as checksum protected environment format as
833   *		used for example by "saveenv" command
834   *	-s size:
835   *		size of output buffer
836   *	addr:	memory address where environment gets stored
837   *	var...	List of variable names that get included into the
838   *		export. Without arguments, the whole environment gets
839   *		exported.
840   *
841   * With "-c" and size is NOT given, then the export command will
842   * format the data as currently used for the persistent storage,
843   * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and
844   * prepend a valid CRC32 checksum and, in case of redundant
845   * environment, a "current" redundancy flag. If size is given, this
846   * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32
847   * checksum and redundancy flag will be inserted.
848   *
849   * With "-b" and "-t", always only the real data (including a
850   * terminating '\0' byte) will be written; here the optional size
851   * argument will be used to make sure not to overflow the user
852   * provided buffer; the command will abort if the size is not
853   * sufficient. Any remaining space will be '\0' padded.
854   *
855   * On successful return, the variable "filesize" will be set.
856   * Note that filesize includes the trailing/terminating '\0' byte(s).
857   *
858   * Usage scenario:  create a text snapshot/backup of the current settings:
859   *
860   *	=> env export -t 100000
861   *	=> era ${backup_addr} +${filesize}
862   *	=> cp.b 100000 ${backup_addr} ${filesize}
863   *
864   * Re-import this snapshot, deleting all other settings:
865   *
866   *	=> env import -d -t ${backup_addr}
867   */
868  static int do_env_export(cmd_tbl_t *cmdtp, int flag,
869  			 int argc, char * const argv[])
870  {
871  	char	buf[32];
872  	ulong	addr;
873  	char	*ptr, *cmd, *res;
874  	size_t	size = 0;
875  	ssize_t	len;
876  	env_t	*envp;
877  	char	sep = '\n';
878  	int	chk = 0;
879  	int	fmt = 0;
880  
881  	cmd = *argv;
882  
883  	while (--argc > 0 && **++argv == '-') {
884  		char *arg = *argv;
885  		while (*++arg) {
886  			switch (*arg) {
887  			case 'b':		/* raw binary format */
888  				if (fmt++)
889  					goto sep_err;
890  				sep = '\0';
891  				break;
892  			case 'c':		/* external checksum format */
893  				if (fmt++)
894  					goto sep_err;
895  				sep = '\0';
896  				chk = 1;
897  				break;
898  			case 's':		/* size given */
899  				if (--argc <= 0)
900  					return cmd_usage(cmdtp);
901  				size = simple_strtoul(*++argv, NULL, 16);
902  				goto NXTARG;
903  			case 't':		/* text format */
904  				if (fmt++)
905  					goto sep_err;
906  				sep = '\n';
907  				break;
908  			default:
909  				return CMD_RET_USAGE;
910  			}
911  		}
912  NXTARG:		;
913  	}
914  
915  	if (argc < 1)
916  		return CMD_RET_USAGE;
917  
918  	addr = simple_strtoul(argv[0], NULL, 16);
919  	ptr = map_sysmem(addr, size);
920  
921  	if (size)
922  		memset(ptr, '\0', size);
923  
924  	argc--;
925  	argv++;
926  
927  	if (sep) {		/* export as text file */
928  		len = hexport_r(&env_htab, sep,
929  				H_MATCH_KEY | H_MATCH_IDENT,
930  				&ptr, size, argc, argv);
931  		if (len < 0) {
932  			pr_err("Cannot export environment: errno = %d\n", errno);
933  			return 1;
934  		}
935  		sprintf(buf, "%zX", (size_t)len);
936  		env_set("filesize", buf);
937  
938  		return 0;
939  	}
940  
941  	envp = (env_t *)ptr;
942  
943  	if (chk)		/* export as checksum protected block */
944  		res = (char *)envp->data;
945  	else			/* export as raw binary data */
946  		res = ptr;
947  
948  	len = hexport_r(&env_htab, '\0',
949  			H_MATCH_KEY | H_MATCH_IDENT,
950  			&res, ENV_SIZE, argc, argv);
951  	if (len < 0) {
952  		pr_err("Cannot export environment: errno = %d\n", errno);
953  		return 1;
954  	}
955  
956  	if (chk) {
957  		envp->crc = crc32(0, envp->data, ENV_SIZE);
958  #ifdef CONFIG_ENV_ADDR_REDUND
959  		envp->flags = ACTIVE_FLAG;
960  #endif
961  	}
962  	env_set_hex("filesize", len + offsetof(env_t, data));
963  
964  	return 0;
965  
966  sep_err:
967  	printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",	cmd);
968  	return 1;
969  }
970  #endif
971  
972  #ifdef CONFIG_CMD_IMPORTENV
973  /*
974   * env import [-d] [-t [-r] | -b | -c] addr [size]
975   *	-d:	delete existing environment before importing;
976   *		otherwise overwrite / append to existing definitions
977   *	-t:	assume text format; either "size" must be given or the
978   *		text data must be '\0' terminated
979   *	-r:	handle CRLF like LF, that means exported variables with
980   *		a content which ends with \r won't get imported. Used
981   *		to import text files created with editors which are using CRLF
982   *		for line endings. Only effective in addition to -t.
983   *	-b:	assume binary format ('\0' separated, "\0\0" terminated)
984   *	-c:	assume checksum protected environment format
985   *	addr:	memory address to read from
986   *	size:	length of input data; if missing, proper '\0'
987   *		termination is mandatory
988   */
989  static int do_env_import(cmd_tbl_t *cmdtp, int flag,
990  			 int argc, char * const argv[])
991  {
992  	ulong	addr;
993  	char	*cmd, *ptr;
994  	char	sep = '\n';
995  	int	chk = 0;
996  	int	fmt = 0;
997  	int	del = 0;
998  	int	crlf_is_lf = 0;
999  	size_t	size;
1000  
1001  	cmd = *argv;
1002  
1003  	while (--argc > 0 && **++argv == '-') {
1004  		char *arg = *argv;
1005  		while (*++arg) {
1006  			switch (*arg) {
1007  			case 'b':		/* raw binary format */
1008  				if (fmt++)
1009  					goto sep_err;
1010  				sep = '\0';
1011  				break;
1012  			case 'c':		/* external checksum format */
1013  				if (fmt++)
1014  					goto sep_err;
1015  				sep = '\0';
1016  				chk = 1;
1017  				break;
1018  			case 't':		/* text format */
1019  				if (fmt++)
1020  					goto sep_err;
1021  				sep = '\n';
1022  				break;
1023  			case 'r':		/* handle CRLF like LF */
1024  				crlf_is_lf = 1;
1025  				break;
1026  			case 'd':
1027  				del = 1;
1028  				break;
1029  			default:
1030  				return CMD_RET_USAGE;
1031  			}
1032  		}
1033  	}
1034  
1035  	if (argc < 1)
1036  		return CMD_RET_USAGE;
1037  
1038  	if (!fmt)
1039  		printf("## Warning: defaulting to text format\n");
1040  
1041  	if (sep != '\n' && crlf_is_lf )
1042  		crlf_is_lf = 0;
1043  
1044  	addr = simple_strtoul(argv[0], NULL, 16);
1045  	ptr = map_sysmem(addr, 0);
1046  
1047  	if (argc == 2) {
1048  		size = simple_strtoul(argv[1], NULL, 16);
1049  	} else if (argc == 1 && chk) {
1050  		puts("## Error: external checksum format must pass size\n");
1051  		return CMD_RET_FAILURE;
1052  	} else {
1053  		char *s = ptr;
1054  
1055  		size = 0;
1056  
1057  		while (size < MAX_ENV_SIZE) {
1058  			if ((*s == sep) && (*(s+1) == '\0'))
1059  				break;
1060  			++s;
1061  			++size;
1062  		}
1063  		if (size == MAX_ENV_SIZE) {
1064  			printf("## Warning: Input data exceeds %d bytes"
1065  				" - truncated\n", MAX_ENV_SIZE);
1066  		}
1067  		size += 2;
1068  		printf("## Info: input data size = %zu = 0x%zX\n", size, size);
1069  	}
1070  
1071  	if (chk) {
1072  		uint32_t crc;
1073  		env_t *ep = (env_t *)ptr;
1074  
1075  		size -= offsetof(env_t, data);
1076  		memcpy(&crc, &ep->crc, sizeof(crc));
1077  
1078  		if (crc32(0, ep->data, size) != crc) {
1079  			puts("## Error: bad CRC, import failed\n");
1080  			return 1;
1081  		}
1082  		ptr = (char *)ep->data;
1083  	}
1084  
1085  	if (himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
1086  			crlf_is_lf, 0, NULL) == 0) {
1087  		pr_err("Environment import failed: errno = %d\n", errno);
1088  		return 1;
1089  	}
1090  	gd->flags |= GD_FLG_ENV_READY;
1091  
1092  	return 0;
1093  
1094  sep_err:
1095  	printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
1096  		cmd);
1097  	return 1;
1098  }
1099  #endif
1100  
1101  #if defined(CONFIG_CMD_ENV_EXISTS)
1102  static int do_env_exists(cmd_tbl_t *cmdtp, int flag, int argc,
1103  		       char * const argv[])
1104  {
1105  	ENTRY e, *ep;
1106  
1107  	if (argc < 2)
1108  		return CMD_RET_USAGE;
1109  
1110  	e.key = argv[1];
1111  	e.data = NULL;
1112  	hsearch_r(e, FIND, &ep, &env_htab, 0);
1113  
1114  	return (ep == NULL) ? 1 : 0;
1115  }
1116  #endif
1117  
1118  /*
1119   * New command line interface: "env" command with subcommands
1120   */
1121  static cmd_tbl_t cmd_env_sub[] = {
1122  #if defined(CONFIG_CMD_ASKENV)
1123  	U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""),
1124  #endif
1125  	U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""),
1126  	U_BOOT_CMD_MKENT(delete, CONFIG_SYS_MAXARGS, 0, do_env_delete, "", ""),
1127  #if defined(CONFIG_CMD_EDITENV)
1128  	U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""),
1129  #endif
1130  #if defined(CONFIG_CMD_ENV_CALLBACK)
1131  	U_BOOT_CMD_MKENT(callbacks, 1, 0, do_env_callback, "", ""),
1132  #endif
1133  #if defined(CONFIG_CMD_ENV_FLAGS)
1134  	U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""),
1135  #endif
1136  #if defined(CONFIG_CMD_EXPORTENV)
1137  	U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
1138  #endif
1139  #if defined(CONFIG_CMD_GREPENV)
1140  	U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
1141  #endif
1142  #if defined(CONFIG_CMD_IMPORTENV)
1143  	U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
1144  #endif
1145  	U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
1146  #if defined(CONFIG_CMD_RUN)
1147  	U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
1148  #endif
1149  #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
1150  	U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
1151  #endif
1152  	U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
1153  #if defined(CONFIG_CMD_ENV_EXISTS)
1154  	U_BOOT_CMD_MKENT(exists, 2, 0, do_env_exists, "", ""),
1155  #endif
1156  };
1157  
1158  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
1159  void env_reloc(void)
1160  {
1161  	fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
1162  }
1163  #endif
1164  
1165  static int do_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1166  {
1167  	cmd_tbl_t *cp;
1168  
1169  	if (argc < 2)
1170  		return CMD_RET_USAGE;
1171  
1172  	/* drop initial "env" arg */
1173  	argc--;
1174  	argv++;
1175  
1176  	cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
1177  
1178  	if (cp)
1179  		return cp->cmd(cmdtp, flag, argc, argv);
1180  
1181  	return CMD_RET_USAGE;
1182  }
1183  
1184  #ifdef CONFIG_SYS_LONGHELP
1185  static char env_help_text[] =
1186  #if defined(CONFIG_CMD_ASKENV)
1187  	"ask name [message] [size] - ask for environment variable\nenv "
1188  #endif
1189  #if defined(CONFIG_CMD_ENV_CALLBACK)
1190  	"callbacks - print callbacks and their associated variables\nenv "
1191  #endif
1192  	"default [-f] -a - [forcibly] reset default environment\n"
1193  	"env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
1194  	"env delete [-f] var [...] - [forcibly] delete variable(s)\n"
1195  #if defined(CONFIG_CMD_EDITENV)
1196  	"env edit name - edit environment variable\n"
1197  #endif
1198  #if defined(CONFIG_CMD_ENV_EXISTS)
1199  	"env exists name - tests for existence of variable\n"
1200  #endif
1201  #if defined(CONFIG_CMD_EXPORTENV)
1202  	"env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n"
1203  #endif
1204  #if defined(CONFIG_CMD_ENV_FLAGS)
1205  	"env flags - print variables that have non-default flags\n"
1206  #endif
1207  #if defined(CONFIG_CMD_GREPENV)
1208  #ifdef CONFIG_REGEX
1209  	"env grep [-e] [-n | -v | -b] string [...] - search environment\n"
1210  #else
1211  	"env grep [-n | -v | -b] string [...] - search environment\n"
1212  #endif
1213  #endif
1214  #if defined(CONFIG_CMD_IMPORTENV)
1215  	"env import [-d] [-t [-r] | -b | -c] addr [size] - import environment\n"
1216  #endif
1217  	"env print [-a | name ...] - print environment\n"
1218  #if defined(CONFIG_CMD_RUN)
1219  	"env run var [...] - run commands in an environment variable\n"
1220  #endif
1221  #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
1222  	"env save - save environment\n"
1223  #endif
1224  	"env set [-f] name [arg ...]\n";
1225  #endif
1226  
1227  U_BOOT_CMD(
1228  	env, CONFIG_SYS_MAXARGS, 1, do_env,
1229  	"environment handling commands", env_help_text
1230  );
1231  
1232  /*
1233   * Old command line interface, kept for compatibility
1234   */
1235  
1236  #if defined(CONFIG_CMD_EDITENV)
1237  U_BOOT_CMD_COMPLETE(
1238  	editenv, 2, 0,	do_env_edit,
1239  	"edit environment variable",
1240  	"name\n"
1241  	"    - edit environment variable 'name'",
1242  	var_complete
1243  );
1244  #endif
1245  
1246  U_BOOT_CMD_COMPLETE(
1247  	printenv, CONFIG_SYS_MAXARGS, 1,	do_env_print,
1248  	"print environment variables",
1249  	"[-a]\n    - print [all] values of all environment variables\n"
1250  	"printenv name ...\n"
1251  	"    - print value of environment variable 'name'",
1252  	var_complete
1253  );
1254  
1255  #ifdef CONFIG_CMD_GREPENV
1256  U_BOOT_CMD_COMPLETE(
1257  	grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
1258  	"search environment variables",
1259  #ifdef CONFIG_REGEX
1260  	"[-e] [-n | -v | -b] string ...\n"
1261  #else
1262  	"[-n | -v | -b] string ...\n"
1263  #endif
1264  	"    - list environment name=value pairs matching 'string'\n"
1265  #ifdef CONFIG_REGEX
1266  	"      \"-e\": enable regular expressions;\n"
1267  #endif
1268  	"      \"-n\": search variable names; \"-v\": search values;\n"
1269  	"      \"-b\": search both names and values (default)",
1270  	var_complete
1271  );
1272  #endif
1273  
1274  U_BOOT_CMD_COMPLETE(
1275  	setenv, CONFIG_SYS_MAXARGS, 0,	do_env_set,
1276  	"set environment variables",
1277  	"[-f] name value ...\n"
1278  	"    - [forcibly] set environment variable 'name' to 'value ...'\n"
1279  	"setenv [-f] name\n"
1280  	"    - [forcibly] delete environment variable 'name'",
1281  	var_complete
1282  );
1283  
1284  #if defined(CONFIG_CMD_ASKENV)
1285  
1286  U_BOOT_CMD(
1287  	askenv,	CONFIG_SYS_MAXARGS,	1,	do_env_ask,
1288  	"get environment variables from stdin",
1289  	"name [message] [size]\n"
1290  	"    - get environment variable 'name' from stdin (max 'size' chars)"
1291  );
1292  #endif
1293  
1294  #if defined(CONFIG_CMD_RUN)
1295  U_BOOT_CMD_COMPLETE(
1296  	run,	CONFIG_SYS_MAXARGS,	1,	do_run,
1297  	"run commands in an environment variable",
1298  	"var [...]\n"
1299  	"    - run the commands in the environment variable(s) 'var'",
1300  	var_complete
1301  );
1302  #endif
1303  #endif /* CONFIG_SPL_BUILD */
1304