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