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