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