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