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