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