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