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(const char *varname, const char *varvalue) 405 { 406 /* 'a_' means "varargs_'; 'v_' means 'varvalue_' */ 407 char *varargs; 408 char *a_title, *v_title; 409 char *a_string_tok, *a_item_tok = NULL; 410 char *v_string_tok, *v_item_tok = NULL; 411 char *a_item, *a_items[ARGS_ITEM_NUM] = { NULL }; 412 char *v_item, *v_items[ARGS_ITEM_NUM] = { NULL }; 413 bool match = false; 414 int i = 0, j = 0; 415 416 /* Before import into hashtable */ 417 if (!(gd->flags & GD_FLG_ENV_READY) || !varname) 418 return 1; 419 420 /* If varname doesn't exist, create it and set varvalue */ 421 varargs = env_get(varname); 422 if (!varargs) { 423 env_set(varname, varvalue); 424 return 0; 425 } 426 427 /* Malloc a temporary varargs for strtok */ 428 a_string_tok = strdup(varargs); 429 if (!a_string_tok) { 430 printf("Error: strdup in failed, line=%d\n", __LINE__); 431 return 1; 432 } 433 434 /* Malloc a temporary varvalue for strtok */ 435 v_string_tok = strdup(varvalue); 436 if (!v_string_tok) { 437 free(a_string_tok); 438 printf("Error: strdup in failed, line=%d\n", __LINE__); 439 return 1; 440 } 441 442 /* Splite varargs into items containing "=" by the blank */ 443 a_item = strtok(a_string_tok, " "); 444 while (a_item && i < ARGS_ITEM_NUM) { 445 debug("%s: [a_item %d]: %s\n", __func__, i, a_item); 446 if (strstr(a_item, "=")) 447 a_items[i++] = a_item; 448 a_item = strtok(NULL, " "); 449 } 450 451 /* 452 * Splite varvalue into items containing "=" by the blank. 453 * parse varvalue title, eg: "bootmode=emmc", title is "bootmode" 454 */ 455 v_item = strtok(v_string_tok, " "); 456 while (v_item && j < ARGS_ITEM_NUM) { 457 debug("%s: <v_item %d>: %s\n", __func__, j, v_item); 458 if (strstr(v_item, "=")) 459 v_items[j++] = v_item; 460 else 461 env_append(varname, v_item); 462 v_item = strtok(NULL, " "); 463 } 464 465 /* For every v_item, search its title */ 466 for (j = 0; j < ARGS_ITEM_NUM && v_items[j]; j++) { 467 v_item = v_items[j]; 468 /* Malloc a temporary a_item for strtok */ 469 v_item_tok = strdup(v_item); 470 if (!v_item_tok) { 471 printf("Error: strdup in failed, line=%d\n", __LINE__); 472 free(a_string_tok); 473 free(v_string_tok); 474 return 1; 475 } 476 v_title = strtok(v_item_tok, "="); 477 debug("%s: <v_title>: %s\n", __func__, v_title); 478 479 /* For every a_item, search its title */ 480 for (i = 0; i < ARGS_ITEM_NUM && a_items[i]; i++) { 481 a_item = a_items[i]; 482 /* Malloc a temporary a_item for strtok */ 483 a_item_tok = strdup(a_item); 484 if (!a_item_tok) { 485 printf("Error: strdup in failed, line=%d\n", __LINE__); 486 free(a_string_tok); 487 free(v_string_tok); 488 free(v_item_tok); 489 return 1; 490 } 491 492 a_title = strtok(a_item_tok, "="); 493 debug("%s: [a_title]: %s\n", __func__, a_title); 494 if (!strcmp(a_title, v_title)) { 495 /* Find! replace it */ 496 env_replace(varname, a_item, v_item); 497 free(a_item_tok); 498 match = true; 499 break; 500 } 501 free(a_item_tok); 502 } 503 504 /* Not find, just append */ 505 if (!match) { 506 debug("%s: append '%s' to the '%s' end\n", 507 __func__, v_item, varname); 508 env_append(varname, v_item); 509 } 510 match = false; 511 free(v_item_tok); 512 } 513 514 free(v_string_tok); 515 free(a_string_tok); 516 517 return 0; 518 } 519 520 int env_exist(const char *varname, const char *varvalue) 521 { 522 char *value; 523 int ret = 0; 524 525 /* before import into hashtable */ 526 if (!(gd->flags & GD_FLG_ENV_READY) || !varname) 527 return 1; 528 529 value = env_get(varname); 530 if (value) 531 ret = strstr(value, varvalue) ? 1 : 0; 532 533 return ret; 534 } 535 536 /** 537 * Set an environment variable to an integer value 538 * 539 * @param varname Environment variable to set 540 * @param value Value to set it to 541 * @return 0 if ok, 1 on error 542 */ 543 int env_set_ulong(const char *varname, ulong value) 544 { 545 /* TODO: this should be unsigned */ 546 char *str = simple_itoa(value); 547 548 return env_set(varname, str); 549 } 550 551 /** 552 * Set an environment variable to an value in hex 553 * 554 * @param varname Environment variable to set 555 * @param value Value to set it to 556 * @return 0 if ok, 1 on error 557 */ 558 int env_set_hex(const char *varname, ulong value) 559 { 560 char str[17]; 561 562 sprintf(str, "%lx", value); 563 return env_set(varname, str); 564 } 565 566 ulong env_get_hex(const char *varname, ulong default_val) 567 { 568 const char *s; 569 ulong value; 570 char *endp; 571 572 s = env_get(varname); 573 if (s) 574 value = simple_strtoul(s, &endp, 16); 575 if (!s || endp == s) 576 return default_val; 577 578 return value; 579 } 580 581 #ifndef CONFIG_SPL_BUILD 582 static int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 583 { 584 if (argc < 2) 585 return CMD_RET_USAGE; 586 587 return _do_env_set(flag, argc, argv, H_INTERACTIVE); 588 } 589 590 /* 591 * Prompt for environment variable 592 */ 593 #if defined(CONFIG_CMD_ASKENV) 594 int do_env_ask(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 595 { 596 char message[CONFIG_SYS_CBSIZE]; 597 int i, len, pos, size; 598 char *local_args[4]; 599 char *endptr; 600 601 local_args[0] = argv[0]; 602 local_args[1] = argv[1]; 603 local_args[2] = NULL; 604 local_args[3] = NULL; 605 606 /* 607 * Check the syntax: 608 * 609 * env_ask envname [message1 ...] [size] 610 */ 611 if (argc == 1) 612 return CMD_RET_USAGE; 613 614 /* 615 * We test the last argument if it can be converted 616 * into a decimal number. If yes, we assume it's 617 * the size. Otherwise we echo it as part of the 618 * message. 619 */ 620 i = simple_strtoul(argv[argc - 1], &endptr, 10); 621 if (*endptr != '\0') { /* no size */ 622 size = CONFIG_SYS_CBSIZE - 1; 623 } else { /* size given */ 624 size = i; 625 --argc; 626 } 627 628 if (argc <= 2) { 629 sprintf(message, "Please enter '%s': ", argv[1]); 630 } else { 631 /* env_ask envname message1 ... messagen [size] */ 632 for (i = 2, pos = 0; i < argc && pos+1 < sizeof(message); i++) { 633 if (pos) 634 message[pos++] = ' '; 635 636 strncpy(message + pos, argv[i], sizeof(message) - pos); 637 pos += strlen(argv[i]); 638 } 639 if (pos < sizeof(message) - 1) { 640 message[pos++] = ' '; 641 message[pos] = '\0'; 642 } else 643 message[CONFIG_SYS_CBSIZE - 1] = '\0'; 644 } 645 646 if (size >= CONFIG_SYS_CBSIZE) 647 size = CONFIG_SYS_CBSIZE - 1; 648 649 if (size <= 0) 650 return 1; 651 652 /* prompt for input */ 653 len = cli_readline(message); 654 655 if (size < len) 656 console_buffer[size] = '\0'; 657 658 len = 2; 659 if (console_buffer[0] != '\0') { 660 local_args[2] = console_buffer; 661 len = 3; 662 } 663 664 /* Continue calling setenv code */ 665 return _do_env_set(flag, len, local_args, H_INTERACTIVE); 666 } 667 #endif 668 669 #if defined(CONFIG_CMD_ENV_CALLBACK) 670 static int print_static_binding(const char *var_name, const char *callback_name, 671 void *priv) 672 { 673 printf("\t%-20s %-20s\n", var_name, callback_name); 674 675 return 0; 676 } 677 678 static int print_active_callback(ENTRY *entry) 679 { 680 struct env_clbk_tbl *clbkp; 681 int i; 682 int num_callbacks; 683 684 if (entry->callback == NULL) 685 return 0; 686 687 /* look up the callback in the linker-list */ 688 num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk); 689 for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk); 690 i < num_callbacks; 691 i++, clbkp++) { 692 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 693 if (entry->callback == clbkp->callback + gd->reloc_off) 694 #else 695 if (entry->callback == clbkp->callback) 696 #endif 697 break; 698 } 699 700 if (i == num_callbacks) 701 /* this should probably never happen, but just in case... */ 702 printf("\t%-20s %p\n", entry->key, entry->callback); 703 else 704 printf("\t%-20s %-20s\n", entry->key, clbkp->name); 705 706 return 0; 707 } 708 709 /* 710 * Print the callbacks available and what they are bound to 711 */ 712 int do_env_callback(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 713 { 714 struct env_clbk_tbl *clbkp; 715 int i; 716 int num_callbacks; 717 718 /* Print the available callbacks */ 719 puts("Available callbacks:\n"); 720 puts("\tCallback Name\n"); 721 puts("\t-------------\n"); 722 num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk); 723 for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk); 724 i < num_callbacks; 725 i++, clbkp++) 726 printf("\t%s\n", clbkp->name); 727 puts("\n"); 728 729 /* Print the static bindings that may exist */ 730 puts("Static callback bindings:\n"); 731 printf("\t%-20s %-20s\n", "Variable Name", "Callback Name"); 732 printf("\t%-20s %-20s\n", "-------------", "-------------"); 733 env_attr_walk(ENV_CALLBACK_LIST_STATIC, print_static_binding, NULL); 734 puts("\n"); 735 736 /* walk through each variable and print the callback if it has one */ 737 puts("Active callback bindings:\n"); 738 printf("\t%-20s %-20s\n", "Variable Name", "Callback Name"); 739 printf("\t%-20s %-20s\n", "-------------", "-------------"); 740 hwalk_r(&env_htab, print_active_callback); 741 return 0; 742 } 743 #endif 744 745 #if defined(CONFIG_CMD_ENV_FLAGS) 746 static int print_static_flags(const char *var_name, const char *flags, 747 void *priv) 748 { 749 enum env_flags_vartype type = env_flags_parse_vartype(flags); 750 enum env_flags_varaccess access = env_flags_parse_varaccess(flags); 751 752 printf("\t%-20s %-20s %-20s\n", var_name, 753 env_flags_get_vartype_name(type), 754 env_flags_get_varaccess_name(access)); 755 756 return 0; 757 } 758 759 static int print_active_flags(ENTRY *entry) 760 { 761 enum env_flags_vartype type; 762 enum env_flags_varaccess access; 763 764 if (entry->flags == 0) 765 return 0; 766 767 type = (enum env_flags_vartype) 768 (entry->flags & ENV_FLAGS_VARTYPE_BIN_MASK); 769 access = env_flags_parse_varaccess_from_binflags(entry->flags); 770 printf("\t%-20s %-20s %-20s\n", entry->key, 771 env_flags_get_vartype_name(type), 772 env_flags_get_varaccess_name(access)); 773 774 return 0; 775 } 776 777 /* 778 * Print the flags available and what variables have flags 779 */ 780 int do_env_flags(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 781 { 782 /* Print the available variable types */ 783 printf("Available variable type flags (position %d):\n", 784 ENV_FLAGS_VARTYPE_LOC); 785 puts("\tFlag\tVariable Type Name\n"); 786 puts("\t----\t------------------\n"); 787 env_flags_print_vartypes(); 788 puts("\n"); 789 790 /* Print the available variable access types */ 791 printf("Available variable access flags (position %d):\n", 792 ENV_FLAGS_VARACCESS_LOC); 793 puts("\tFlag\tVariable Access Name\n"); 794 puts("\t----\t--------------------\n"); 795 env_flags_print_varaccess(); 796 puts("\n"); 797 798 /* Print the static flags that may exist */ 799 puts("Static flags:\n"); 800 printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type", 801 "Variable Access"); 802 printf("\t%-20s %-20s %-20s\n", "-------------", "-------------", 803 "---------------"); 804 env_attr_walk(ENV_FLAGS_LIST_STATIC, print_static_flags, NULL); 805 puts("\n"); 806 807 /* walk through each variable and print the flags if non-default */ 808 puts("Active flags:\n"); 809 printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type", 810 "Variable Access"); 811 printf("\t%-20s %-20s %-20s\n", "-------------", "-------------", 812 "---------------"); 813 hwalk_r(&env_htab, print_active_flags); 814 return 0; 815 } 816 #endif 817 818 /* 819 * Interactively edit an environment variable 820 */ 821 #if defined(CONFIG_CMD_EDITENV) 822 static int do_env_edit(cmd_tbl_t *cmdtp, int flag, int argc, 823 char * const argv[]) 824 { 825 char buffer[CONFIG_SYS_CBSIZE]; 826 char *init_val; 827 828 if (argc < 2) 829 return CMD_RET_USAGE; 830 831 /* before import into hashtable */ 832 if (!(gd->flags & GD_FLG_ENV_READY)) 833 return 1; 834 835 /* Set read buffer to initial value or empty sting */ 836 init_val = env_get(argv[1]); 837 if (init_val) 838 snprintf(buffer, CONFIG_SYS_CBSIZE, "%s", init_val); 839 else 840 buffer[0] = '\0'; 841 842 if (cli_readline_into_buffer("edit: ", buffer, 0) < 0) 843 return 1; 844 845 if (buffer[0] == '\0') { 846 const char * const _argv[3] = { "setenv", argv[1], NULL }; 847 848 return _do_env_set(0, 2, (char * const *)_argv, H_INTERACTIVE); 849 } else { 850 const char * const _argv[4] = { "setenv", argv[1], buffer, 851 NULL }; 852 853 return _do_env_set(0, 3, (char * const *)_argv, H_INTERACTIVE); 854 } 855 } 856 #endif /* CONFIG_CMD_EDITENV */ 857 #endif /* CONFIG_SPL_BUILD */ 858 859 /* 860 * Look up variable from environment, 861 * return address of storage for that variable, 862 * or NULL if not found 863 */ 864 char *env_get(const char *name) 865 { 866 if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */ 867 ENTRY e, *ep; 868 869 WATCHDOG_RESET(); 870 871 e.key = name; 872 e.data = NULL; 873 hsearch_r(e, FIND, &ep, &env_htab, 0); 874 875 return ep ? ep->data : NULL; 876 } 877 878 /* restricted capabilities before import */ 879 if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0) 880 return (char *)(gd->env_buf); 881 882 return NULL; 883 } 884 885 /* 886 * Look up variable from environment for restricted C runtime env. 887 */ 888 int env_get_f(const char *name, char *buf, unsigned len) 889 { 890 int i, nxt; 891 892 for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { 893 int val, n; 894 895 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) { 896 if (nxt >= CONFIG_ENV_SIZE) 897 return -1; 898 } 899 900 val = envmatch((uchar *)name, i); 901 if (val < 0) 902 continue; 903 904 /* found; copy out */ 905 for (n = 0; n < len; ++n, ++buf) { 906 *buf = env_get_char(val++); 907 if (*buf == '\0') 908 return n; 909 } 910 911 if (n) 912 *--buf = '\0'; 913 914 printf("env_buf [%d bytes] too small for value of \"%s\"\n", 915 len, name); 916 917 return n; 918 } 919 920 return -1; 921 } 922 923 /** 924 * Decode the integer value of an environment variable and return it. 925 * 926 * @param name Name of environemnt variable 927 * @param base Number base to use (normally 10, or 16 for hex) 928 * @param default_val Default value to return if the variable is not 929 * found 930 * @return the decoded value, or default_val if not found 931 */ 932 ulong env_get_ulong(const char *name, int base, ulong default_val) 933 { 934 /* 935 * We can use env_get() here, even before relocation, since the 936 * environment variable value is an integer and thus short. 937 */ 938 const char *str = env_get(name); 939 940 return str ? simple_strtoul(str, NULL, base) : default_val; 941 } 942 943 #ifndef CONFIG_SPL_BUILD 944 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) 945 static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, 946 char * const argv[]) 947 { 948 struct env_driver *env = env_driver_lookup_default(); 949 950 printf("Saving Environment to %s...\n", env->name); 951 952 return env_save() ? 1 : 0; 953 } 954 955 U_BOOT_CMD( 956 saveenv, 1, 0, do_env_save, 957 "save environment variables to persistent storage", 958 "" 959 ); 960 #endif 961 #endif /* CONFIG_SPL_BUILD */ 962 963 964 /* 965 * Match a name / name=value pair 966 * 967 * s1 is either a simple 'name', or a 'name=value' pair. 968 * i2 is the environment index for a 'name2=value2' pair. 969 * If the names match, return the index for the value2, else -1. 970 */ 971 int envmatch(uchar *s1, int i2) 972 { 973 if (s1 == NULL) 974 return -1; 975 976 while (*s1 == env_get_char(i2++)) 977 if (*s1++ == '=') 978 return i2; 979 980 if (*s1 == '\0' && env_get_char(i2-1) == '=') 981 return i2; 982 983 return -1; 984 } 985 986 #ifndef CONFIG_SPL_BUILD 987 static int do_env_default(cmd_tbl_t *cmdtp, int __flag, 988 int argc, char * const argv[]) 989 { 990 int all = 0, flag = 0; 991 992 debug("Initial value for argc=%d\n", argc); 993 while (--argc > 0 && **++argv == '-') { 994 char *arg = *argv; 995 996 while (*++arg) { 997 switch (*arg) { 998 case 'a': /* default all */ 999 all = 1; 1000 break; 1001 case 'f': /* force */ 1002 flag |= H_FORCE; 1003 break; 1004 default: 1005 return cmd_usage(cmdtp); 1006 } 1007 } 1008 } 1009 debug("Final value for argc=%d\n", argc); 1010 if (all && (argc == 0)) { 1011 /* Reset the whole environment */ 1012 set_default_env("## Resetting to default environment\n"); 1013 return 0; 1014 } 1015 if (!all && (argc > 0)) { 1016 /* Reset individual variables */ 1017 set_default_vars(argc, argv); 1018 return 0; 1019 } 1020 1021 return cmd_usage(cmdtp); 1022 } 1023 1024 static int do_env_delete(cmd_tbl_t *cmdtp, int flag, 1025 int argc, char * const argv[]) 1026 { 1027 int env_flag = H_INTERACTIVE; 1028 int ret = 0; 1029 1030 debug("Initial value for argc=%d\n", argc); 1031 while (argc > 1 && **(argv + 1) == '-') { 1032 char *arg = *++argv; 1033 1034 --argc; 1035 while (*++arg) { 1036 switch (*arg) { 1037 case 'f': /* force */ 1038 env_flag |= H_FORCE; 1039 break; 1040 default: 1041 return CMD_RET_USAGE; 1042 } 1043 } 1044 } 1045 debug("Final value for argc=%d\n", argc); 1046 1047 env_id++; 1048 1049 while (--argc > 0) { 1050 char *name = *++argv; 1051 1052 if (!hdelete_r(name, &env_htab, env_flag)) 1053 ret = 1; 1054 } 1055 1056 return ret; 1057 } 1058 1059 #ifdef CONFIG_CMD_EXPORTENV 1060 /* 1061 * env export [-t | -b | -c] [-s size] addr [var ...] 1062 * -t: export as text format; if size is given, data will be 1063 * padded with '\0' bytes; if not, one terminating '\0' 1064 * will be added (which is included in the "filesize" 1065 * setting so you can for exmple copy this to flash and 1066 * keep the termination). 1067 * -b: export as binary format (name=value pairs separated by 1068 * '\0', list end marked by double "\0\0") 1069 * -c: export as checksum protected environment format as 1070 * used for example by "saveenv" command 1071 * -s size: 1072 * size of output buffer 1073 * addr: memory address where environment gets stored 1074 * var... List of variable names that get included into the 1075 * export. Without arguments, the whole environment gets 1076 * exported. 1077 * 1078 * With "-c" and size is NOT given, then the export command will 1079 * format the data as currently used for the persistent storage, 1080 * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and 1081 * prepend a valid CRC32 checksum and, in case of redundant 1082 * environment, a "current" redundancy flag. If size is given, this 1083 * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 1084 * checksum and redundancy flag will be inserted. 1085 * 1086 * With "-b" and "-t", always only the real data (including a 1087 * terminating '\0' byte) will be written; here the optional size 1088 * argument will be used to make sure not to overflow the user 1089 * provided buffer; the command will abort if the size is not 1090 * sufficient. Any remaining space will be '\0' padded. 1091 * 1092 * On successful return, the variable "filesize" will be set. 1093 * Note that filesize includes the trailing/terminating '\0' byte(s). 1094 * 1095 * Usage scenario: create a text snapshot/backup of the current settings: 1096 * 1097 * => env export -t 100000 1098 * => era ${backup_addr} +${filesize} 1099 * => cp.b 100000 ${backup_addr} ${filesize} 1100 * 1101 * Re-import this snapshot, deleting all other settings: 1102 * 1103 * => env import -d -t ${backup_addr} 1104 */ 1105 static int do_env_export(cmd_tbl_t *cmdtp, int flag, 1106 int argc, char * const argv[]) 1107 { 1108 char buf[32]; 1109 ulong addr; 1110 char *ptr, *cmd, *res; 1111 size_t size = 0; 1112 ssize_t len; 1113 env_t *envp; 1114 char sep = '\n'; 1115 int chk = 0; 1116 int fmt = 0; 1117 1118 cmd = *argv; 1119 1120 while (--argc > 0 && **++argv == '-') { 1121 char *arg = *argv; 1122 while (*++arg) { 1123 switch (*arg) { 1124 case 'b': /* raw binary format */ 1125 if (fmt++) 1126 goto sep_err; 1127 sep = '\0'; 1128 break; 1129 case 'c': /* external checksum format */ 1130 if (fmt++) 1131 goto sep_err; 1132 sep = '\0'; 1133 chk = 1; 1134 break; 1135 case 's': /* size given */ 1136 if (--argc <= 0) 1137 return cmd_usage(cmdtp); 1138 size = simple_strtoul(*++argv, NULL, 16); 1139 goto NXTARG; 1140 case 't': /* text format */ 1141 if (fmt++) 1142 goto sep_err; 1143 sep = '\n'; 1144 break; 1145 default: 1146 return CMD_RET_USAGE; 1147 } 1148 } 1149 NXTARG: ; 1150 } 1151 1152 if (argc < 1) 1153 return CMD_RET_USAGE; 1154 1155 addr = simple_strtoul(argv[0], NULL, 16); 1156 ptr = map_sysmem(addr, size); 1157 1158 if (size) 1159 memset(ptr, '\0', size); 1160 1161 argc--; 1162 argv++; 1163 1164 if (sep) { /* export as text file */ 1165 len = hexport_r(&env_htab, sep, 1166 H_MATCH_KEY | H_MATCH_IDENT, 1167 &ptr, size, argc, argv); 1168 if (len < 0) { 1169 pr_err("Cannot export environment: errno = %d\n", errno); 1170 return 1; 1171 } 1172 sprintf(buf, "%zX", (size_t)len); 1173 env_set("filesize", buf); 1174 1175 return 0; 1176 } 1177 1178 envp = (env_t *)ptr; 1179 1180 if (chk) /* export as checksum protected block */ 1181 res = (char *)envp->data; 1182 else /* export as raw binary data */ 1183 res = ptr; 1184 1185 len = hexport_r(&env_htab, '\0', 1186 H_MATCH_KEY | H_MATCH_IDENT, 1187 &res, ENV_SIZE, argc, argv); 1188 if (len < 0) { 1189 pr_err("Cannot export environment: errno = %d\n", errno); 1190 return 1; 1191 } 1192 1193 if (chk) { 1194 envp->crc = crc32(0, envp->data, ENV_SIZE); 1195 #ifdef CONFIG_ENV_ADDR_REDUND 1196 envp->flags = ACTIVE_FLAG; 1197 #endif 1198 } 1199 env_set_hex("filesize", len + offsetof(env_t, data)); 1200 1201 return 0; 1202 1203 sep_err: 1204 printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", cmd); 1205 return 1; 1206 } 1207 #endif 1208 1209 #ifdef CONFIG_CMD_IMPORTENV 1210 /* 1211 * env import [-d] [-t [-r] | -b | -c] addr [size] 1212 * -d: delete existing environment before importing; 1213 * otherwise overwrite / append to existing definitions 1214 * -t: assume text format; either "size" must be given or the 1215 * text data must be '\0' terminated 1216 * -r: handle CRLF like LF, that means exported variables with 1217 * a content which ends with \r won't get imported. Used 1218 * to import text files created with editors which are using CRLF 1219 * for line endings. Only effective in addition to -t. 1220 * -b: assume binary format ('\0' separated, "\0\0" terminated) 1221 * -c: assume checksum protected environment format 1222 * addr: memory address to read from 1223 * size: length of input data; if missing, proper '\0' 1224 * termination is mandatory 1225 */ 1226 static int do_env_import(cmd_tbl_t *cmdtp, int flag, 1227 int argc, char * const argv[]) 1228 { 1229 ulong addr; 1230 char *cmd, *ptr; 1231 char sep = '\n'; 1232 int chk = 0; 1233 int fmt = 0; 1234 int del = 0; 1235 int crlf_is_lf = 0; 1236 size_t size; 1237 1238 cmd = *argv; 1239 1240 while (--argc > 0 && **++argv == '-') { 1241 char *arg = *argv; 1242 while (*++arg) { 1243 switch (*arg) { 1244 case 'b': /* raw binary format */ 1245 if (fmt++) 1246 goto sep_err; 1247 sep = '\0'; 1248 break; 1249 case 'c': /* external checksum format */ 1250 if (fmt++) 1251 goto sep_err; 1252 sep = '\0'; 1253 chk = 1; 1254 break; 1255 case 't': /* text format */ 1256 if (fmt++) 1257 goto sep_err; 1258 sep = '\n'; 1259 break; 1260 case 'r': /* handle CRLF like LF */ 1261 crlf_is_lf = 1; 1262 break; 1263 case 'd': 1264 del = 1; 1265 break; 1266 default: 1267 return CMD_RET_USAGE; 1268 } 1269 } 1270 } 1271 1272 if (argc < 1) 1273 return CMD_RET_USAGE; 1274 1275 if (!fmt) 1276 printf("## Warning: defaulting to text format\n"); 1277 1278 if (sep != '\n' && crlf_is_lf ) 1279 crlf_is_lf = 0; 1280 1281 addr = simple_strtoul(argv[0], NULL, 16); 1282 ptr = map_sysmem(addr, 0); 1283 1284 if (argc == 2) { 1285 size = simple_strtoul(argv[1], NULL, 16); 1286 } else if (argc == 1 && chk) { 1287 puts("## Error: external checksum format must pass size\n"); 1288 return CMD_RET_FAILURE; 1289 } else { 1290 char *s = ptr; 1291 1292 size = 0; 1293 1294 while (size < MAX_ENV_SIZE) { 1295 if ((*s == sep) && (*(s+1) == '\0')) 1296 break; 1297 ++s; 1298 ++size; 1299 } 1300 if (size == MAX_ENV_SIZE) { 1301 printf("## Warning: Input data exceeds %d bytes" 1302 " - truncated\n", MAX_ENV_SIZE); 1303 } 1304 size += 2; 1305 printf("## Info: input data size = %zu = 0x%zX\n", size, size); 1306 } 1307 1308 if (chk) { 1309 uint32_t crc; 1310 env_t *ep = (env_t *)ptr; 1311 1312 size -= offsetof(env_t, data); 1313 memcpy(&crc, &ep->crc, sizeof(crc)); 1314 1315 if (crc32(0, ep->data, size) != crc) { 1316 puts("## Error: bad CRC, import failed\n"); 1317 return 1; 1318 } 1319 ptr = (char *)ep->data; 1320 } 1321 1322 if (himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR, 1323 crlf_is_lf, 0, NULL) == 0) { 1324 pr_err("Environment import failed: errno = %d\n", errno); 1325 return 1; 1326 } 1327 gd->flags |= GD_FLG_ENV_READY; 1328 1329 return 0; 1330 1331 sep_err: 1332 printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", 1333 cmd); 1334 return 1; 1335 } 1336 #endif 1337 1338 #if defined(CONFIG_CMD_ENV_EXISTS) 1339 static int do_env_exists(cmd_tbl_t *cmdtp, int flag, int argc, 1340 char * const argv[]) 1341 { 1342 ENTRY e, *ep; 1343 1344 if (argc < 2) 1345 return CMD_RET_USAGE; 1346 1347 e.key = argv[1]; 1348 e.data = NULL; 1349 hsearch_r(e, FIND, &ep, &env_htab, 0); 1350 1351 return (ep == NULL) ? 1 : 0; 1352 } 1353 #endif 1354 1355 /* 1356 * New command line interface: "env" command with subcommands 1357 */ 1358 static cmd_tbl_t cmd_env_sub[] = { 1359 #if defined(CONFIG_CMD_ASKENV) 1360 U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""), 1361 #endif 1362 U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""), 1363 U_BOOT_CMD_MKENT(delete, CONFIG_SYS_MAXARGS, 0, do_env_delete, "", ""), 1364 #if defined(CONFIG_CMD_EDITENV) 1365 U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""), 1366 #endif 1367 #if defined(CONFIG_CMD_ENV_CALLBACK) 1368 U_BOOT_CMD_MKENT(callbacks, 1, 0, do_env_callback, "", ""), 1369 #endif 1370 #if defined(CONFIG_CMD_ENV_FLAGS) 1371 U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""), 1372 #endif 1373 #if defined(CONFIG_CMD_EXPORTENV) 1374 U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""), 1375 #endif 1376 #if defined(CONFIG_CMD_GREPENV) 1377 U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""), 1378 #endif 1379 #if defined(CONFIG_CMD_IMPORTENV) 1380 U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""), 1381 #endif 1382 U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""), 1383 #if defined(CONFIG_CMD_RUN) 1384 U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""), 1385 #endif 1386 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) 1387 U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""), 1388 #endif 1389 U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""), 1390 #if defined(CONFIG_CMD_ENV_EXISTS) 1391 U_BOOT_CMD_MKENT(exists, 2, 0, do_env_exists, "", ""), 1392 #endif 1393 }; 1394 1395 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 1396 void env_reloc(void) 1397 { 1398 fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub)); 1399 } 1400 #endif 1401 1402 static int do_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 1403 { 1404 cmd_tbl_t *cp; 1405 1406 if (argc < 2) 1407 return CMD_RET_USAGE; 1408 1409 /* drop initial "env" arg */ 1410 argc--; 1411 argv++; 1412 1413 cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub)); 1414 1415 if (cp) 1416 return cp->cmd(cmdtp, flag, argc, argv); 1417 1418 return CMD_RET_USAGE; 1419 } 1420 1421 #ifdef CONFIG_SYS_LONGHELP 1422 static char env_help_text[] = 1423 #if defined(CONFIG_CMD_ASKENV) 1424 "ask name [message] [size] - ask for environment variable\nenv " 1425 #endif 1426 #if defined(CONFIG_CMD_ENV_CALLBACK) 1427 "callbacks - print callbacks and their associated variables\nenv " 1428 #endif 1429 "default [-f] -a - [forcibly] reset default environment\n" 1430 "env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n" 1431 "env delete [-f] var [...] - [forcibly] delete variable(s)\n" 1432 #if defined(CONFIG_CMD_EDITENV) 1433 "env edit name - edit environment variable\n" 1434 #endif 1435 #if defined(CONFIG_CMD_ENV_EXISTS) 1436 "env exists name - tests for existence of variable\n" 1437 #endif 1438 #if defined(CONFIG_CMD_EXPORTENV) 1439 "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n" 1440 #endif 1441 #if defined(CONFIG_CMD_ENV_FLAGS) 1442 "env flags - print variables that have non-default flags\n" 1443 #endif 1444 #if defined(CONFIG_CMD_GREPENV) 1445 #ifdef CONFIG_REGEX 1446 "env grep [-e] [-n | -v | -b] string [...] - search environment\n" 1447 #else 1448 "env grep [-n | -v | -b] string [...] - search environment\n" 1449 #endif 1450 #endif 1451 #if defined(CONFIG_CMD_IMPORTENV) 1452 "env import [-d] [-t [-r] | -b | -c] addr [size] - import environment\n" 1453 #endif 1454 "env print [-a | name ...] - print environment\n" 1455 #if defined(CONFIG_CMD_RUN) 1456 "env run var [...] - run commands in an environment variable\n" 1457 #endif 1458 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) 1459 "env save - save environment\n" 1460 #endif 1461 "env set [-f] name [arg ...]\n"; 1462 #endif 1463 1464 U_BOOT_CMD( 1465 env, CONFIG_SYS_MAXARGS, 1, do_env, 1466 "environment handling commands", env_help_text 1467 ); 1468 1469 /* 1470 * Old command line interface, kept for compatibility 1471 */ 1472 1473 #if defined(CONFIG_CMD_EDITENV) 1474 U_BOOT_CMD_COMPLETE( 1475 editenv, 2, 0, do_env_edit, 1476 "edit environment variable", 1477 "name\n" 1478 " - edit environment variable 'name'", 1479 var_complete 1480 ); 1481 #endif 1482 1483 U_BOOT_CMD_COMPLETE( 1484 printenv, CONFIG_SYS_MAXARGS, 1, do_env_print, 1485 "print environment variables", 1486 "[-a]\n - print [all] values of all environment variables\n" 1487 "printenv name ...\n" 1488 " - print value of environment variable 'name'", 1489 var_complete 1490 ); 1491 1492 #ifdef CONFIG_CMD_GREPENV 1493 U_BOOT_CMD_COMPLETE( 1494 grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep, 1495 "search environment variables", 1496 #ifdef CONFIG_REGEX 1497 "[-e] [-n | -v | -b] string ...\n" 1498 #else 1499 "[-n | -v | -b] string ...\n" 1500 #endif 1501 " - list environment name=value pairs matching 'string'\n" 1502 #ifdef CONFIG_REGEX 1503 " \"-e\": enable regular expressions;\n" 1504 #endif 1505 " \"-n\": search variable names; \"-v\": search values;\n" 1506 " \"-b\": search both names and values (default)", 1507 var_complete 1508 ); 1509 #endif 1510 1511 U_BOOT_CMD_COMPLETE( 1512 setenv, CONFIG_SYS_MAXARGS, 0, do_env_set, 1513 "set environment variables", 1514 "[-f] name value ...\n" 1515 " - [forcibly] set environment variable 'name' to 'value ...'\n" 1516 "setenv [-f] name\n" 1517 " - [forcibly] delete environment variable 'name'", 1518 var_complete 1519 ); 1520 1521 #if defined(CONFIG_CMD_ASKENV) 1522 1523 U_BOOT_CMD( 1524 askenv, CONFIG_SYS_MAXARGS, 1, do_env_ask, 1525 "get environment variables from stdin", 1526 "name [message] [size]\n" 1527 " - get environment variable 'name' from stdin (max 'size' chars)" 1528 ); 1529 #endif 1530 1531 #if defined(CONFIG_CMD_RUN) 1532 U_BOOT_CMD_COMPLETE( 1533 run, CONFIG_SYS_MAXARGS, 1, do_run, 1534 "run commands in an environment variable", 1535 "var [...]\n" 1536 " - run the commands in the environment variable(s) 'var'", 1537 var_complete 1538 ); 1539 #endif 1540 #endif /* CONFIG_SPL_BUILD */ 1541