1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <common.h>
27#include <cli.h>
28#include <command.h>
29#include <console.h>
30#include <env.h>
31#include <env_internal.h>
32#include <log.h>
33#include <net.h>
34#include <search.h>
35#include <errno.h>
36#include <malloc.h>
37#include <mapmem.h>
38#include <asm/global_data.h>
39#include <linux/bitops.h>
40#include <u-boot/crc.h>
41#include <watchdog.h>
42#include <linux/stddef.h>
43#include <asm/byteorder.h>
44#include <asm/io.h>
45
46DECLARE_GLOBAL_DATA_PTR;
47
48#if defined(CONFIG_ENV_IS_IN_EEPROM) || \
49 defined(CONFIG_ENV_IS_IN_FLASH) || \
50 defined(CONFIG_ENV_IS_IN_MMC) || \
51 defined(CONFIG_ENV_IS_IN_FAT) || \
52 defined(CONFIG_ENV_IS_IN_EXT4) || \
53 defined(CONFIG_ENV_IS_IN_NAND) || \
54 defined(CONFIG_ENV_IS_IN_NVRAM) || \
55 defined(CONFIG_ENV_IS_IN_ONENAND) || \
56 defined(CONFIG_ENV_IS_IN_SATA) || \
57 defined(CONFIG_ENV_IS_IN_SPI_FLASH) || \
58 defined(CONFIG_ENV_IS_IN_REMOTE) || \
59 defined(CONFIG_ENV_IS_IN_UBI)
60
61#define ENV_IS_IN_DEVICE
62
63#endif
64
65#if !defined(ENV_IS_IN_DEVICE) && \
66 !defined(CONFIG_ENV_IS_NOWHERE)
67# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
68NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
69#endif
70
71
72
73
74#define MAX_ENV_SIZE (1 << 20)
75
76
77
78
79
80
81
82
83static int env_id = 1;
84
85int env_get_id(void)
86{
87 return env_id;
88}
89
90#ifndef CONFIG_SPL_BUILD
91
92
93
94
95
96static int env_print(char *name, int flag)
97{
98 char *res = NULL;
99 ssize_t len;
100
101 if (name) {
102 struct env_entry e, *ep;
103
104 e.key = name;
105 e.data = NULL;
106 hsearch_r(e, ENV_FIND, &ep, &env_htab, flag);
107 if (ep == NULL)
108 return 0;
109 len = printf("%s=%s\n", ep->key, ep->data);
110 return len;
111 }
112
113
114 len = hexport_r(&env_htab, '\n', flag, &res, 0, 0, NULL);
115
116 if (len > 0) {
117 puts(res);
118 free(res);
119 return len;
120 }
121
122
123 printf("## Error: cannot export environment\n");
124 return 0;
125}
126
127static int do_env_print(struct cmd_tbl *cmdtp, int flag, int argc,
128 char *const argv[])
129{
130 int i;
131 int rcode = 0;
132 int env_flag = H_HIDE_DOT;
133
134#if defined(CONFIG_CMD_NVEDIT_EFI)
135 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
136 return do_env_print_efi(cmdtp, flag, --argc, ++argv);
137#endif
138
139 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'a') {
140 argc--;
141 argv++;
142 env_flag &= ~H_HIDE_DOT;
143 }
144
145 if (argc == 1) {
146
147 rcode = env_print(NULL, env_flag);
148 if (!rcode)
149 return 1;
150 printf("\nEnvironment size: %d/%ld bytes\n",
151 rcode, (ulong)ENV_SIZE);
152 return 0;
153 }
154
155
156 env_flag &= ~H_HIDE_DOT;
157 for (i = 1; i < argc; ++i) {
158 int rc = env_print(argv[i], env_flag);
159 if (!rc) {
160 printf("## Error: \"%s\" not defined\n", argv[i]);
161 ++rcode;
162 }
163 }
164
165 return rcode;
166}
167
168#ifdef CONFIG_CMD_GREPENV
169static int do_env_grep(struct cmd_tbl *cmdtp, int flag,
170 int argc, char *const argv[])
171{
172 char *res = NULL;
173 int len, grep_how, grep_what;
174
175 if (argc < 2)
176 return CMD_RET_USAGE;
177
178 grep_how = H_MATCH_SUBSTR;
179 grep_what = H_MATCH_BOTH;
180
181 while (--argc > 0 && **++argv == '-') {
182 char *arg = *argv;
183 while (*++arg) {
184 switch (*arg) {
185#ifdef CONFIG_REGEX
186 case 'e':
187 grep_how = H_MATCH_REGEX;
188 break;
189#endif
190 case 'n':
191 grep_what = H_MATCH_KEY;
192 break;
193 case 'v':
194 grep_what = H_MATCH_DATA;
195 break;
196 case 'b':
197 grep_what = H_MATCH_BOTH;
198 break;
199 case '-':
200 goto DONE;
201 default:
202 return CMD_RET_USAGE;
203 }
204 }
205 }
206
207DONE:
208 len = hexport_r(&env_htab, '\n',
209 flag | grep_what | grep_how,
210 &res, 0, argc, argv);
211
212 if (len > 0) {
213 puts(res);
214 free(res);
215 }
216
217 if (len < 2)
218 return 1;
219
220 return 0;
221}
222#endif
223#endif
224
225
226
227
228
229static int _do_env_set(int flag, int argc, char *const argv[], int env_flag)
230{
231 int i, len;
232 char *name, *value, *s;
233 struct env_entry e, *ep;
234
235 debug("Initial value for argc=%d\n", argc);
236
237#if CONFIG_IS_ENABLED(CMD_NVEDIT_EFI)
238 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
239 return do_env_set_efi(NULL, flag, --argc, ++argv);
240#endif
241
242 while (argc > 1 && **(argv + 1) == '-') {
243 char *arg = *++argv;
244
245 --argc;
246 while (*++arg) {
247 switch (*arg) {
248 case 'f':
249 env_flag |= H_FORCE;
250 break;
251 default:
252 return CMD_RET_USAGE;
253 }
254 }
255 }
256 debug("Final value for argc=%d\n", argc);
257 name = argv[1];
258
259 if (strchr(name, '=')) {
260 printf("## Error: illegal character '='"
261 "in variable name \"%s\"\n", name);
262 return 1;
263 }
264
265 env_id++;
266
267
268 if (argc < 3 || argv[2] == NULL) {
269 int rc = hdelete_r(name, &env_htab, env_flag);
270
271
272 return rc && rc != -ENOENT ? 1 : 0;
273 }
274
275
276
277
278 for (i = 2, len = 0; i < argc; ++i)
279 len += strlen(argv[i]) + 1;
280
281 value = malloc(len);
282 if (value == NULL) {
283 printf("## Can't malloc %d bytes\n", len);
284 return 1;
285 }
286 for (i = 2, s = value; i < argc; ++i) {
287 char *v = argv[i];
288
289 while ((*s++ = *v++) != '\0')
290 ;
291 *(s - 1) = ' ';
292 }
293 if (s != value)
294 *--s = '\0';
295
296 e.key = name;
297 e.data = value;
298 hsearch_r(e, ENV_ENTER, &ep, &env_htab, env_flag);
299 free(value);
300 if (!ep) {
301 printf("## Error inserting \"%s\" variable, errno=%d\n",
302 name, errno);
303 return 1;
304 }
305
306 return 0;
307}
308
309int env_set(const char *varname, const char *varvalue)
310{
311 const char * const argv[4] = { "setenv", varname, varvalue, NULL };
312
313
314 if (!(gd->flags & GD_FLG_ENV_READY))
315 return 1;
316
317 if (varvalue == NULL || varvalue[0] == '\0')
318 return _do_env_set(0, 2, (char * const *)argv, H_PROGRAMMATIC);
319 else
320 return _do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
321}
322
323
324
325
326
327
328
329
330int env_set_ulong(const char *varname, ulong value)
331{
332
333 char *str = simple_itoa(value);
334
335 return env_set(varname, str);
336}
337
338
339
340
341
342
343
344
345int env_set_hex(const char *varname, ulong value)
346{
347 char str[17];
348
349 sprintf(str, "%lx", value);
350 return env_set(varname, str);
351}
352
353ulong env_get_hex(const char *varname, ulong default_val)
354{
355 const char *s;
356 ulong value;
357 char *endp;
358
359 s = env_get(varname);
360 if (s)
361 value = simple_strtoul(s, &endp, 16);
362 if (!s || endp == s)
363 return default_val;
364
365 return value;
366}
367
368int eth_env_get_enetaddr(const char *name, uint8_t *enetaddr)
369{
370 string_to_enetaddr(env_get(name), enetaddr);
371 return is_valid_ethaddr(enetaddr);
372}
373
374int eth_env_set_enetaddr(const char *name, const uint8_t *enetaddr)
375{
376 char buf[ARP_HLEN_ASCII + 1];
377
378 if (eth_env_get_enetaddr(name, (uint8_t *)buf))
379 return -EEXIST;
380
381 sprintf(buf, "%pM", enetaddr);
382
383 return env_set(name, buf);
384}
385
386#ifndef CONFIG_SPL_BUILD
387static int do_env_set(struct cmd_tbl *cmdtp, int flag, int argc,
388 char *const argv[])
389{
390 if (argc < 2)
391 return CMD_RET_USAGE;
392
393 return _do_env_set(flag, argc, argv, H_INTERACTIVE);
394}
395
396
397
398
399#if defined(CONFIG_CMD_ASKENV)
400int do_env_ask(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
401{
402 char message[CONFIG_SYS_CBSIZE];
403 int i, len, pos, size;
404 char *local_args[4];
405 char *endptr;
406
407 local_args[0] = argv[0];
408 local_args[1] = argv[1];
409 local_args[2] = NULL;
410 local_args[3] = NULL;
411
412
413
414
415
416
417 if (argc == 1)
418 return CMD_RET_USAGE;
419
420
421
422
423
424
425
426 i = simple_strtoul(argv[argc - 1], &endptr, 10);
427 if (*endptr != '\0') {
428 size = CONFIG_SYS_CBSIZE - 1;
429 } else {
430 size = i;
431 --argc;
432 }
433
434 if (argc <= 2) {
435 sprintf(message, "Please enter '%s': ", argv[1]);
436 } else {
437
438 for (i = 2, pos = 0; i < argc && pos+1 < sizeof(message); i++) {
439 if (pos)
440 message[pos++] = ' ';
441
442 strncpy(message + pos, argv[i], sizeof(message) - pos);
443 pos += strlen(argv[i]);
444 }
445 if (pos < sizeof(message) - 1) {
446 message[pos++] = ' ';
447 message[pos] = '\0';
448 } else
449 message[CONFIG_SYS_CBSIZE - 1] = '\0';
450 }
451
452 if (size >= CONFIG_SYS_CBSIZE)
453 size = CONFIG_SYS_CBSIZE - 1;
454
455 if (size <= 0)
456 return 1;
457
458
459 len = cli_readline(message);
460
461 if (size < len)
462 console_buffer[size] = '\0';
463
464 len = 2;
465 if (console_buffer[0] != '\0') {
466 local_args[2] = console_buffer;
467 len = 3;
468 }
469
470
471 return _do_env_set(flag, len, local_args, H_INTERACTIVE);
472}
473#endif
474
475#if defined(CONFIG_CMD_ENV_CALLBACK)
476static int print_static_binding(const char *var_name, const char *callback_name,
477 void *priv)
478{
479 printf("\t%-20s %-20s\n", var_name, callback_name);
480
481 return 0;
482}
483
484static int print_active_callback(struct env_entry *entry)
485{
486 struct env_clbk_tbl *clbkp;
487 int i;
488 int num_callbacks;
489
490 if (entry->callback == NULL)
491 return 0;
492
493
494 num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
495 for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
496 i < num_callbacks;
497 i++, clbkp++) {
498#if defined(CONFIG_NEEDS_MANUAL_RELOC)
499 if (entry->callback == clbkp->callback + gd->reloc_off)
500#else
501 if (entry->callback == clbkp->callback)
502#endif
503 break;
504 }
505
506 if (i == num_callbacks)
507
508 printf("\t%-20s %p\n", entry->key, entry->callback);
509 else
510 printf("\t%-20s %-20s\n", entry->key, clbkp->name);
511
512 return 0;
513}
514
515
516
517
518int do_env_callback(struct cmd_tbl *cmdtp, int flag, int argc,
519 char *const argv[])
520{
521 struct env_clbk_tbl *clbkp;
522 int i;
523 int num_callbacks;
524
525
526 puts("Available callbacks:\n");
527 puts("\tCallback Name\n");
528 puts("\t-------------\n");
529 num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
530 for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
531 i < num_callbacks;
532 i++, clbkp++)
533 printf("\t%s\n", clbkp->name);
534 puts("\n");
535
536
537 puts("Static callback bindings:\n");
538 printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
539 printf("\t%-20s %-20s\n", "-------------", "-------------");
540 env_attr_walk(ENV_CALLBACK_LIST_STATIC, print_static_binding, NULL);
541 puts("\n");
542
543
544 puts("Active callback bindings:\n");
545 printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
546 printf("\t%-20s %-20s\n", "-------------", "-------------");
547 hwalk_r(&env_htab, print_active_callback);
548 return 0;
549}
550#endif
551
552#if defined(CONFIG_CMD_ENV_FLAGS)
553static int print_static_flags(const char *var_name, const char *flags,
554 void *priv)
555{
556 enum env_flags_vartype type = env_flags_parse_vartype(flags);
557 enum env_flags_varaccess access = env_flags_parse_varaccess(flags);
558
559 printf("\t%-20s %-20s %-20s\n", var_name,
560 env_flags_get_vartype_name(type),
561 env_flags_get_varaccess_name(access));
562
563 return 0;
564}
565
566static int print_active_flags(struct env_entry *entry)
567{
568 enum env_flags_vartype type;
569 enum env_flags_varaccess access;
570
571 if (entry->flags == 0)
572 return 0;
573
574 type = (enum env_flags_vartype)
575 (entry->flags & ENV_FLAGS_VARTYPE_BIN_MASK);
576 access = env_flags_parse_varaccess_from_binflags(entry->flags);
577 printf("\t%-20s %-20s %-20s\n", entry->key,
578 env_flags_get_vartype_name(type),
579 env_flags_get_varaccess_name(access));
580
581 return 0;
582}
583
584
585
586
587int do_env_flags(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
588{
589
590 printf("Available variable type flags (position %d):\n",
591 ENV_FLAGS_VARTYPE_LOC);
592 puts("\tFlag\tVariable Type Name\n");
593 puts("\t----\t------------------\n");
594 env_flags_print_vartypes();
595 puts("\n");
596
597
598 printf("Available variable access flags (position %d):\n",
599 ENV_FLAGS_VARACCESS_LOC);
600 puts("\tFlag\tVariable Access Name\n");
601 puts("\t----\t--------------------\n");
602 env_flags_print_varaccess();
603 puts("\n");
604
605
606 puts("Static flags:\n");
607 printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
608 "Variable Access");
609 printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
610 "---------------");
611 env_attr_walk(ENV_FLAGS_LIST_STATIC, print_static_flags, NULL);
612 puts("\n");
613
614
615 puts("Active flags:\n");
616 printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
617 "Variable Access");
618 printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
619 "---------------");
620 hwalk_r(&env_htab, print_active_flags);
621 return 0;
622}
623#endif
624
625
626
627
628#if defined(CONFIG_CMD_EDITENV)
629static int do_env_edit(struct cmd_tbl *cmdtp, int flag, int argc,
630 char *const argv[])
631{
632 char buffer[CONFIG_SYS_CBSIZE];
633 char *init_val;
634
635 if (argc < 2)
636 return CMD_RET_USAGE;
637
638
639 if (!(gd->flags & GD_FLG_ENV_READY))
640 return 1;
641
642
643 init_val = env_get(argv[1]);
644 if (init_val)
645 snprintf(buffer, CONFIG_SYS_CBSIZE, "%s", init_val);
646 else
647 buffer[0] = '\0';
648
649 if (cli_readline_into_buffer("edit: ", buffer, 0) < 0)
650 return 1;
651
652 if (buffer[0] == '\0') {
653 const char * const _argv[3] = { "setenv", argv[1], NULL };
654
655 return _do_env_set(0, 2, (char * const *)_argv, H_INTERACTIVE);
656 } else {
657 const char * const _argv[4] = { "setenv", argv[1], buffer,
658 NULL };
659
660 return _do_env_set(0, 3, (char * const *)_argv, H_INTERACTIVE);
661 }
662}
663#endif
664#endif
665
666
667
668
669
670
671char *env_get(const char *name)
672{
673 if (gd->flags & GD_FLG_ENV_READY) {
674 struct env_entry e, *ep;
675
676 WATCHDOG_RESET();
677
678 e.key = name;
679 e.data = NULL;
680 hsearch_r(e, ENV_FIND, &ep, &env_htab, 0);
681
682 return ep ? ep->data : NULL;
683 }
684
685
686 if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
687 return (char *)(gd->env_buf);
688
689 return NULL;
690}
691
692
693
694
695
696
697char *from_env(const char *envvar)
698{
699 char *ret;
700
701 ret = env_get(envvar);
702
703 if (!ret)
704 printf("missing environment variable: %s\n", envvar);
705
706 return ret;
707}
708
709
710
711
712int env_get_f(const char *name, char *buf, unsigned len)
713{
714 int i, nxt, c;
715
716 for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
717 int val, n;
718
719 for (nxt = i; (c = env_get_char(nxt)) != '\0'; ++nxt) {
720 if (c < 0)
721 return c;
722 if (nxt >= CONFIG_ENV_SIZE)
723 return -1;
724 }
725
726 val = env_match((uchar *)name, i);
727 if (val < 0)
728 continue;
729
730
731 for (n = 0; n < len; ++n, ++buf) {
732 c = env_get_char(val++);
733 if (c < 0)
734 return c;
735 *buf = c;
736 if (*buf == '\0')
737 return n;
738 }
739
740 if (n)
741 *--buf = '\0';
742
743 printf("env_buf [%u bytes] too small for value of \"%s\"\n",
744 len, name);
745
746 return n;
747 }
748
749 return -1;
750}
751
752
753
754
755
756
757
758
759
760
761ulong env_get_ulong(const char *name, int base, ulong default_val)
762{
763
764
765
766
767 const char *str = env_get(name);
768
769 return str ? simple_strtoul(str, NULL, base) : default_val;
770}
771
772#ifndef CONFIG_SPL_BUILD
773#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
774static int do_env_save(struct cmd_tbl *cmdtp, int flag, int argc,
775 char *const argv[])
776{
777 return env_save() ? 1 : 0;
778}
779
780U_BOOT_CMD(
781 saveenv, 1, 0, do_env_save,
782 "save environment variables to persistent storage",
783 ""
784);
785
786#if defined(CONFIG_CMD_ERASEENV)
787static int do_env_erase(struct cmd_tbl *cmdtp, int flag, int argc,
788 char *const argv[])
789{
790 return env_erase() ? 1 : 0;
791}
792
793U_BOOT_CMD(
794 eraseenv, 1, 0, do_env_erase,
795 "erase environment variables from persistent storage",
796 ""
797);
798#endif
799#endif
800
801#if defined(CONFIG_CMD_NVEDIT_LOAD)
802static int do_env_load(struct cmd_tbl *cmdtp, int flag, int argc,
803 char *const argv[])
804{
805 return env_reload() ? 1 : 0;
806}
807#endif
808
809#if defined(CONFIG_CMD_NVEDIT_SELECT)
810static int do_env_select(struct cmd_tbl *cmdtp, int flag, int argc,
811 char *const argv[])
812{
813 return env_select(argv[1]) ? 1 : 0;
814}
815#endif
816
817#endif
818
819int env_match(uchar *s1, int i2)
820{
821 if (s1 == NULL)
822 return -1;
823
824 while (*s1 == env_get_char(i2++))
825 if (*s1++ == '=')
826 return i2;
827
828 if (*s1 == '\0' && env_get_char(i2-1) == '=')
829 return i2;
830
831 return -1;
832}
833
834#ifndef CONFIG_SPL_BUILD
835static int do_env_default(struct cmd_tbl *cmdtp, int flag,
836 int argc, char *const argv[])
837{
838 int all = 0, env_flag = H_INTERACTIVE;
839
840 debug("Initial value for argc=%d\n", argc);
841 while (--argc > 0 && **++argv == '-') {
842 char *arg = *argv;
843
844 while (*++arg) {
845 switch (*arg) {
846 case 'a':
847 all = 1;
848 break;
849 case 'f':
850 env_flag |= H_FORCE;
851 break;
852 default:
853 return cmd_usage(cmdtp);
854 }
855 }
856 }
857 debug("Final value for argc=%d\n", argc);
858 if (all && (argc == 0)) {
859
860 env_set_default("## Resetting to default environment\n",
861 env_flag);
862 return 0;
863 }
864 if (!all && (argc > 0)) {
865
866 env_set_default_vars(argc, argv, env_flag);
867 return 0;
868 }
869
870 return cmd_usage(cmdtp);
871}
872
873static int do_env_delete(struct cmd_tbl *cmdtp, int flag,
874 int argc, char *const argv[])
875{
876 int env_flag = H_INTERACTIVE;
877 int ret = 0;
878
879 debug("Initial value for argc=%d\n", argc);
880 while (argc > 1 && **(argv + 1) == '-') {
881 char *arg = *++argv;
882
883 --argc;
884 while (*++arg) {
885 switch (*arg) {
886 case 'f':
887 env_flag |= H_FORCE;
888 break;
889 default:
890 return CMD_RET_USAGE;
891 }
892 }
893 }
894 debug("Final value for argc=%d\n", argc);
895
896 env_id++;
897
898 while (--argc > 0) {
899 char *name = *++argv;
900
901 if (hdelete_r(name, &env_htab, env_flag))
902 ret = 1;
903 }
904
905 return ret;
906}
907
908#ifdef CONFIG_CMD_EXPORTENV
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954static int do_env_export(struct cmd_tbl *cmdtp, int flag,
955 int argc, char *const argv[])
956{
957 char buf[32];
958 ulong addr;
959 char *ptr, *cmd, *res;
960 size_t size = 0;
961 ssize_t len;
962 env_t *envp;
963 char sep = '\n';
964 int chk = 0;
965 int fmt = 0;
966
967 cmd = *argv;
968
969 while (--argc > 0 && **++argv == '-') {
970 char *arg = *argv;
971 while (*++arg) {
972 switch (*arg) {
973 case 'b':
974 if (fmt++)
975 goto sep_err;
976 sep = '\0';
977 break;
978 case 'c':
979 if (fmt++)
980 goto sep_err;
981 sep = '\0';
982 chk = 1;
983 break;
984 case 's':
985 if (--argc <= 0)
986 return cmd_usage(cmdtp);
987 size = simple_strtoul(*++argv, NULL, 16);
988 goto NXTARG;
989 case 't':
990 if (fmt++)
991 goto sep_err;
992 sep = '\n';
993 break;
994 default:
995 return CMD_RET_USAGE;
996 }
997 }
998NXTARG: ;
999 }
1000
1001 if (argc < 1)
1002 return CMD_RET_USAGE;
1003
1004 addr = simple_strtoul(argv[0], NULL, 16);
1005 ptr = map_sysmem(addr, size);
1006
1007 if (size)
1008 memset(ptr, '\0', size);
1009
1010 argc--;
1011 argv++;
1012
1013 if (sep) {
1014 len = hexport_r(&env_htab, sep,
1015 H_MATCH_KEY | H_MATCH_IDENT,
1016 &ptr, size, argc, argv);
1017 if (len < 0) {
1018 pr_err("## Error: Cannot export environment: errno = %d\n",
1019 errno);
1020 return 1;
1021 }
1022 sprintf(buf, "%zX", (size_t)len);
1023 env_set("filesize", buf);
1024
1025 return 0;
1026 }
1027
1028 envp = (env_t *)ptr;
1029
1030 if (chk)
1031 res = (char *)envp->data;
1032 else
1033 res = ptr;
1034
1035 len = hexport_r(&env_htab, '\0',
1036 H_MATCH_KEY | H_MATCH_IDENT,
1037 &res, ENV_SIZE, argc, argv);
1038 if (len < 0) {
1039 pr_err("## Error: Cannot export environment: errno = %d\n",
1040 errno);
1041 return 1;
1042 }
1043
1044 if (chk) {
1045 envp->crc = crc32(0, envp->data,
1046 size ? size - offsetof(env_t, data) : ENV_SIZE);
1047#ifdef CONFIG_ENV_ADDR_REDUND
1048 envp->flags = ENV_REDUND_ACTIVE;
1049#endif
1050 }
1051 env_set_hex("filesize", len + offsetof(env_t, data));
1052
1053 return 0;
1054
1055sep_err:
1056 printf("## Error: %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
1057 cmd);
1058 return 1;
1059}
1060#endif
1061
1062#ifdef CONFIG_CMD_IMPORTENV
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087static int do_env_import(struct cmd_tbl *cmdtp, int flag,
1088 int argc, char *const argv[])
1089{
1090 ulong addr;
1091 char *cmd, *ptr;
1092 char sep = '\n';
1093 int chk = 0;
1094 int fmt = 0;
1095 int del = 0;
1096 int crlf_is_lf = 0;
1097 int wl = 0;
1098 size_t size;
1099
1100 cmd = *argv;
1101
1102 while (--argc > 0 && **++argv == '-') {
1103 char *arg = *argv;
1104 while (*++arg) {
1105 switch (*arg) {
1106 case 'b':
1107 if (fmt++)
1108 goto sep_err;
1109 sep = '\0';
1110 break;
1111 case 'c':
1112 if (fmt++)
1113 goto sep_err;
1114 sep = '\0';
1115 chk = 1;
1116 break;
1117 case 't':
1118 if (fmt++)
1119 goto sep_err;
1120 sep = '\n';
1121 break;
1122 case 'r':
1123 crlf_is_lf = 1;
1124 break;
1125 case 'd':
1126 del = 1;
1127 break;
1128 default:
1129 return CMD_RET_USAGE;
1130 }
1131 }
1132 }
1133
1134 if (argc < 1)
1135 return CMD_RET_USAGE;
1136
1137 if (!fmt)
1138 printf("## Warning: defaulting to text format\n");
1139
1140 if (sep != '\n' && crlf_is_lf )
1141 crlf_is_lf = 0;
1142
1143 addr = simple_strtoul(argv[0], NULL, 16);
1144 ptr = map_sysmem(addr, 0);
1145
1146 if (argc >= 2 && strcmp(argv[1], "-")) {
1147 size = simple_strtoul(argv[1], NULL, 16);
1148 } else if (chk) {
1149 puts("## Error: external checksum format must pass size\n");
1150 return CMD_RET_FAILURE;
1151 } else {
1152 char *s = ptr;
1153
1154 size = 0;
1155
1156 while (size < MAX_ENV_SIZE) {
1157 if ((*s == sep) && (*(s+1) == '\0'))
1158 break;
1159 ++s;
1160 ++size;
1161 }
1162 if (size == MAX_ENV_SIZE) {
1163 printf("## Warning: Input data exceeds %d bytes"
1164 " - truncated\n", MAX_ENV_SIZE);
1165 }
1166 size += 2;
1167 printf("## Info: input data size = %zu = 0x%zX\n", size, size);
1168 }
1169
1170 if (argc > 2)
1171 wl = 1;
1172
1173 if (chk) {
1174 uint32_t crc;
1175 env_t *ep = (env_t *)ptr;
1176
1177 if (size <= offsetof(env_t, data)) {
1178 printf("## Error: Invalid size 0x%zX\n", size);
1179 return 1;
1180 }
1181
1182 size -= offsetof(env_t, data);
1183 memcpy(&crc, &ep->crc, sizeof(crc));
1184
1185 if (crc32(0, ep->data, size) != crc) {
1186 puts("## Error: bad CRC, import failed\n");
1187 return 1;
1188 }
1189 ptr = (char *)ep->data;
1190 }
1191
1192 if (!himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
1193 crlf_is_lf, wl ? argc - 2 : 0, wl ? &argv[2] : NULL)) {
1194 pr_err("## Error: Environment import failed: errno = %d\n",
1195 errno);
1196 return 1;
1197 }
1198 gd->flags |= GD_FLG_ENV_READY;
1199
1200 return 0;
1201
1202sep_err:
1203 printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
1204 cmd);
1205 return 1;
1206}
1207#endif
1208
1209#if defined(CONFIG_CMD_NVEDIT_INFO)
1210
1211
1212
1213static int print_env_info(void)
1214{
1215 const char *value;
1216
1217
1218 switch (gd->env_valid) {
1219 case ENV_INVALID:
1220 value = "invalid";
1221 break;
1222 case ENV_VALID:
1223 value = "valid";
1224 break;
1225 case ENV_REDUND:
1226 value = "redundant";
1227 break;
1228 default:
1229 value = "unknown";
1230 break;
1231 }
1232 printf("env_valid = %s\n", value);
1233
1234
1235 value = gd->flags & GD_FLG_ENV_READY ? "true" : "false";
1236 printf("env_ready = %s\n", value);
1237
1238
1239 value = gd->flags & GD_FLG_ENV_DEFAULT ? "true" : "false";
1240 printf("env_use_default = %s\n", value);
1241
1242 return CMD_RET_SUCCESS;
1243}
1244
1245#define ENV_INFO_IS_DEFAULT BIT(0)
1246#define ENV_INFO_IS_PERSISTED BIT(1)
1247
1248
1249
1250
1251
1252
1253
1254
1255static int do_env_info(struct cmd_tbl *cmdtp, int flag,
1256 int argc, char *const argv[])
1257{
1258 int eval_flags = 0;
1259 int eval_results = 0;
1260 bool quiet = false;
1261#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
1262 enum env_location loc;
1263#endif
1264
1265
1266 if (argc <= 1)
1267 return print_env_info();
1268
1269
1270 while (--argc > 0 && **++argv == '-') {
1271 char *arg = *argv;
1272
1273 while (*++arg) {
1274 switch (*arg) {
1275 case 'd':
1276 eval_flags |= ENV_INFO_IS_DEFAULT;
1277 break;
1278 case 'p':
1279 eval_flags |= ENV_INFO_IS_PERSISTED;
1280 break;
1281 case 'q':
1282 quiet = true;
1283 break;
1284 default:
1285 return CMD_RET_USAGE;
1286 }
1287 }
1288 }
1289
1290
1291 if (eval_flags & ENV_INFO_IS_DEFAULT) {
1292 if (gd->flags & GD_FLG_ENV_DEFAULT) {
1293 if (!quiet)
1294 printf("Default environment is used\n");
1295 eval_results |= ENV_INFO_IS_DEFAULT;
1296 } else {
1297 if (!quiet)
1298 printf("Environment was loaded from persistent storage\n");
1299 }
1300 }
1301
1302
1303 if (eval_flags & ENV_INFO_IS_PERSISTED) {
1304#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
1305 loc = env_get_location(ENVOP_SAVE, gd->env_load_prio);
1306 if (ENVL_NOWHERE != loc && ENVL_UNKNOWN != loc) {
1307 if (!quiet)
1308 printf("Environment can be persisted\n");
1309 eval_results |= ENV_INFO_IS_PERSISTED;
1310 } else {
1311 if (!quiet)
1312 printf("Environment cannot be persisted\n");
1313 }
1314#else
1315 if (!quiet)
1316 printf("Environment cannot be persisted\n");
1317#endif
1318 }
1319
1320
1321 if (eval_flags != eval_results)
1322 return CMD_RET_FAILURE;
1323
1324 return CMD_RET_SUCCESS;
1325}
1326#endif
1327
1328#if defined(CONFIG_CMD_ENV_EXISTS)
1329static int do_env_exists(struct cmd_tbl *cmdtp, int flag, int argc,
1330 char *const argv[])
1331{
1332 struct env_entry e, *ep;
1333
1334 if (argc < 2)
1335 return CMD_RET_USAGE;
1336
1337 e.key = argv[1];
1338 e.data = NULL;
1339 hsearch_r(e, ENV_FIND, &ep, &env_htab, 0);
1340
1341 return (ep == NULL) ? 1 : 0;
1342}
1343#endif
1344
1345
1346
1347
1348static struct cmd_tbl cmd_env_sub[] = {
1349#if defined(CONFIG_CMD_ASKENV)
1350 U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""),
1351#endif
1352 U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""),
1353 U_BOOT_CMD_MKENT(delete, CONFIG_SYS_MAXARGS, 0, do_env_delete, "", ""),
1354#if defined(CONFIG_CMD_EDITENV)
1355 U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""),
1356#endif
1357#if defined(CONFIG_CMD_ENV_CALLBACK)
1358 U_BOOT_CMD_MKENT(callbacks, 1, 0, do_env_callback, "", ""),
1359#endif
1360#if defined(CONFIG_CMD_ENV_FLAGS)
1361 U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""),
1362#endif
1363#if defined(CONFIG_CMD_EXPORTENV)
1364 U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
1365#endif
1366#if defined(CONFIG_CMD_GREPENV)
1367 U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
1368#endif
1369#if defined(CONFIG_CMD_IMPORTENV)
1370 U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
1371#endif
1372#if defined(CONFIG_CMD_NVEDIT_INFO)
1373 U_BOOT_CMD_MKENT(info, 3, 0, do_env_info, "", ""),
1374#endif
1375#if defined(CONFIG_CMD_NVEDIT_LOAD)
1376 U_BOOT_CMD_MKENT(load, 1, 0, do_env_load, "", ""),
1377#endif
1378 U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
1379#if defined(CONFIG_CMD_RUN)
1380 U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
1381#endif
1382#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
1383 U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
1384#if defined(CONFIG_CMD_ERASEENV)
1385 U_BOOT_CMD_MKENT(erase, 1, 0, do_env_erase, "", ""),
1386#endif
1387#endif
1388#if defined(CONFIG_CMD_NVEDIT_SELECT)
1389 U_BOOT_CMD_MKENT(select, 2, 0, do_env_select, "", ""),
1390#endif
1391 U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
1392#if defined(CONFIG_CMD_ENV_EXISTS)
1393 U_BOOT_CMD_MKENT(exists, 2, 0, do_env_exists, "", ""),
1394#endif
1395};
1396
1397#if defined(CONFIG_NEEDS_MANUAL_RELOC)
1398void env_reloc(void)
1399{
1400 fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
1401}
1402#endif
1403
1404static int do_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
1405{
1406 struct cmd_tbl *cp;
1407
1408 if (argc < 2)
1409 return CMD_RET_USAGE;
1410
1411
1412 argc--;
1413 argv++;
1414
1415 cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
1416
1417 if (cp)
1418 return cp->cmd(cmdtp, flag, argc, argv);
1419
1420 return CMD_RET_USAGE;
1421}
1422
1423#ifdef CONFIG_SYS_LONGHELP
1424static char env_help_text[] =
1425#if defined(CONFIG_CMD_ASKENV)
1426 "ask name [message] [size] - ask for environment variable\nenv "
1427#endif
1428#if defined(CONFIG_CMD_ENV_CALLBACK)
1429 "callbacks - print callbacks and their associated variables\nenv "
1430#endif
1431 "default [-f] -a - [forcibly] reset default environment\n"
1432 "env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
1433 "env delete [-f] var [...] - [forcibly] delete variable(s)\n"
1434#if defined(CONFIG_CMD_EDITENV)
1435 "env edit name - edit environment variable\n"
1436#endif
1437#if defined(CONFIG_CMD_ENV_EXISTS)
1438 "env exists name - tests for existence of variable\n"
1439#endif
1440#if defined(CONFIG_CMD_EXPORTENV)
1441 "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n"
1442#endif
1443#if defined(CONFIG_CMD_ENV_FLAGS)
1444 "env flags - print variables that have non-default flags\n"
1445#endif
1446#if defined(CONFIG_CMD_GREPENV)
1447#ifdef CONFIG_REGEX
1448 "env grep [-e] [-n | -v | -b] string [...] - search environment\n"
1449#else
1450 "env grep [-n | -v | -b] string [...] - search environment\n"
1451#endif
1452#endif
1453#if defined(CONFIG_CMD_IMPORTENV)
1454 "env import [-d] [-t [-r] | -b | -c] addr [size] [var ...] - import environment\n"
1455#endif
1456#if defined(CONFIG_CMD_NVEDIT_INFO)
1457 "env info - display environment information\n"
1458 "env info [-d] [-p] [-q] - evaluate environment information\n"
1459 " \"-d\": default environment is used\n"
1460 " \"-p\": environment can be persisted\n"
1461 " \"-q\": quiet output\n"
1462#endif
1463 "env print [-a | name ...] - print environment\n"
1464#if defined(CONFIG_CMD_NVEDIT_EFI)
1465 "env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n"
1466#endif
1467#if defined(CONFIG_CMD_RUN)
1468 "env run var [...] - run commands in an environment variable\n"
1469#endif
1470#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
1471 "env save - save environment\n"
1472#if defined(CONFIG_CMD_ERASEENV)
1473 "env erase - erase environment\n"
1474#endif
1475#endif
1476#if defined(CONFIG_CMD_NVEDIT_LOAD)
1477 "env load - load environment\n"
1478#endif
1479#if defined(CONFIG_CMD_NVEDIT_SELECT)
1480 "env select [target] - select environment target\n"
1481#endif
1482#if defined(CONFIG_CMD_NVEDIT_EFI)
1483 "env set -e [-nv][-bs][-rt][-at][-a][-i addr:size][-v] name [arg ...]\n"
1484 " - set UEFI variable; unset if '-i' or 'arg' not specified\n"
1485#endif
1486 "env set [-f] name [arg ...]\n";
1487#endif
1488
1489U_BOOT_CMD(
1490 env, CONFIG_SYS_MAXARGS, 1, do_env,
1491 "environment handling commands", env_help_text
1492);
1493
1494
1495
1496
1497
1498#if defined(CONFIG_CMD_EDITENV)
1499U_BOOT_CMD_COMPLETE(
1500 editenv, 2, 0, do_env_edit,
1501 "edit environment variable",
1502 "name\n"
1503 " - edit environment variable 'name'",
1504 var_complete
1505);
1506#endif
1507
1508U_BOOT_CMD_COMPLETE(
1509 printenv, CONFIG_SYS_MAXARGS, 1, do_env_print,
1510 "print environment variables",
1511 "[-a]\n - print [all] values of all environment variables\n"
1512#if defined(CONFIG_CMD_NVEDIT_EFI)
1513 "printenv -e [-guid guid][-n] [name ...]\n"
1514 " - print UEFI variable 'name' or all the variables\n"
1515 " \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
1516 " \"-n\": suppress dumping variable's value\n"
1517#endif
1518 "printenv name ...\n"
1519 " - print value of environment variable 'name'",
1520 var_complete
1521);
1522
1523#ifdef CONFIG_CMD_GREPENV
1524U_BOOT_CMD_COMPLETE(
1525 grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep,
1526 "search environment variables",
1527#ifdef CONFIG_REGEX
1528 "[-e] [-n | -v | -b] string ...\n"
1529#else
1530 "[-n | -v | -b] string ...\n"
1531#endif
1532 " - list environment name=value pairs matching 'string'\n"
1533#ifdef CONFIG_REGEX
1534 " \"-e\": enable regular expressions;\n"
1535#endif
1536 " \"-n\": search variable names; \"-v\": search values;\n"
1537 " \"-b\": search both names and values (default)",
1538 var_complete
1539);
1540#endif
1541
1542U_BOOT_CMD_COMPLETE(
1543 setenv, CONFIG_SYS_MAXARGS, 0, do_env_set,
1544 "set environment variables",
1545#if defined(CONFIG_CMD_NVEDIT_EFI)
1546 "-e [-guid guid][-nv][-bs][-rt][-at][-a][-v]\n"
1547 " [-i addr:size name], or [name [value ...]]\n"
1548 " - set UEFI variable 'name' to 'value' ...'\n"
1549 " \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
1550 " \"-nv\": set non-volatile attribute\n"
1551 " \"-bs\": set boot-service attribute\n"
1552 " \"-rt\": set runtime attribute\n"
1553 " \"-at\": set time-based authentication attribute\n"
1554 " \"-a\": append-write\n"
1555 " \"-i addr,size\": use <addr,size> as variable's value\n"
1556 " \"-v\": verbose message\n"
1557 " - delete UEFI variable 'name' if 'value' not specified\n"
1558#endif
1559 "setenv [-f] name value ...\n"
1560 " - [forcibly] set environment variable 'name' to 'value ...'\n"
1561 "setenv [-f] name\n"
1562 " - [forcibly] delete environment variable 'name'",
1563 var_complete
1564);
1565
1566#if defined(CONFIG_CMD_ASKENV)
1567
1568U_BOOT_CMD(
1569 askenv, CONFIG_SYS_MAXARGS, 1, do_env_ask,
1570 "get environment variables from stdin",
1571 "name [message] [size]\n"
1572 " - get environment variable 'name' from stdin (max 'size' chars)"
1573);
1574#endif
1575
1576#if defined(CONFIG_CMD_RUN)
1577U_BOOT_CMD_COMPLETE(
1578 run, CONFIG_SYS_MAXARGS, 1, do_run,
1579 "run commands in an environment variable",
1580 "var [...]\n"
1581 " - run the commands in the environment variable(s) 'var'",
1582 var_complete
1583);
1584#endif
1585#endif
1586