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