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