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