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