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