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