1 /* 2 * (C) Copyright 2000-2010 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * (C) Copyright 2008 6 * Guennadi Liakhovetski, DENX Software Engineering, lg@denx.de. 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #define _GNU_SOURCE 12 13 #include <compiler.h> 14 #include <errno.h> 15 #include <env_flags.h> 16 #include <fcntl.h> 17 #include <linux/stringify.h> 18 #include <ctype.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <stddef.h> 22 #include <string.h> 23 #include <sys/types.h> 24 #include <sys/ioctl.h> 25 #include <sys/stat.h> 26 #include <unistd.h> 27 28 #ifdef MTD_OLD 29 # include <stdint.h> 30 # include <linux/mtd/mtd.h> 31 #else 32 # define __user /* nothing */ 33 # include <mtd/mtd-user.h> 34 #endif 35 36 #include "fw_env.h" 37 38 struct common_args common_args; 39 struct printenv_args printenv_args; 40 struct setenv_args setenv_args; 41 42 #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 43 44 #define min(x, y) ({ \ 45 typeof(x) _min1 = (x); \ 46 typeof(y) _min2 = (y); \ 47 (void) (&_min1 == &_min2); \ 48 _min1 < _min2 ? _min1 : _min2; }) 49 50 struct envdev_s { 51 const char *devname; /* Device name */ 52 ulong devoff; /* Device offset */ 53 ulong env_size; /* environment size */ 54 ulong erase_size; /* device erase size */ 55 ulong env_sectors; /* number of environment sectors */ 56 uint8_t mtd_type; /* type of the MTD device */ 57 }; 58 59 static struct envdev_s envdevices[2] = 60 { 61 { 62 .mtd_type = MTD_ABSENT, 63 }, { 64 .mtd_type = MTD_ABSENT, 65 }, 66 }; 67 static int dev_current; 68 69 #define DEVNAME(i) envdevices[(i)].devname 70 #define DEVOFFSET(i) envdevices[(i)].devoff 71 #define ENVSIZE(i) envdevices[(i)].env_size 72 #define DEVESIZE(i) envdevices[(i)].erase_size 73 #define ENVSECTORS(i) envdevices[(i)].env_sectors 74 #define DEVTYPE(i) envdevices[(i)].mtd_type 75 76 #define CUR_ENVSIZE ENVSIZE(dev_current) 77 78 #define ENV_SIZE getenvsize() 79 80 struct env_image_single { 81 uint32_t crc; /* CRC32 over data bytes */ 82 char data[]; 83 }; 84 85 struct env_image_redundant { 86 uint32_t crc; /* CRC32 over data bytes */ 87 unsigned char flags; /* active or obsolete */ 88 char data[]; 89 }; 90 91 enum flag_scheme { 92 FLAG_NONE, 93 FLAG_BOOLEAN, 94 FLAG_INCREMENTAL, 95 }; 96 97 struct environment { 98 void *image; 99 uint32_t *crc; 100 unsigned char *flags; 101 char *data; 102 enum flag_scheme flag_scheme; 103 }; 104 105 static struct environment environment = { 106 .flag_scheme = FLAG_NONE, 107 }; 108 109 static int env_aes_cbc_crypt(char *data, const int enc); 110 111 static int HaveRedundEnv = 0; 112 113 static unsigned char active_flag = 1; 114 /* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */ 115 static unsigned char obsolete_flag = 0; 116 117 #define DEFAULT_ENV_INSTANCE_STATIC 118 #include <env_default.h> 119 120 static int flash_io (int mode); 121 static char *envmatch (char * s1, char * s2); 122 static int parse_config (void); 123 124 #if defined(CONFIG_FILE) 125 static int get_config (char *); 126 #endif 127 static inline ulong getenvsize (void) 128 { 129 ulong rc = CUR_ENVSIZE - sizeof(uint32_t); 130 131 if (HaveRedundEnv) 132 rc -= sizeof (char); 133 134 if (common_args.aes_flag) 135 rc &= ~(AES_KEY_LENGTH - 1); 136 137 return rc; 138 } 139 140 static char *skip_chars(char *s) 141 { 142 for (; *s != '\0'; s++) { 143 if (isblank(*s)) 144 return s; 145 } 146 return NULL; 147 } 148 149 static char *skip_blanks(char *s) 150 { 151 for (; *s != '\0'; s++) { 152 if (!isblank(*s)) 153 return s; 154 } 155 return NULL; 156 } 157 158 /* 159 * Search the environment for a variable. 160 * Return the value, if found, or NULL, if not found. 161 */ 162 char *fw_getenv (char *name) 163 { 164 char *env, *nxt; 165 166 for (env = environment.data; *env; env = nxt + 1) { 167 char *val; 168 169 for (nxt = env; *nxt; ++nxt) { 170 if (nxt >= &environment.data[ENV_SIZE]) { 171 fprintf (stderr, "## Error: " 172 "environment not terminated\n"); 173 return NULL; 174 } 175 } 176 val = envmatch (name, env); 177 if (!val) 178 continue; 179 return val; 180 } 181 return NULL; 182 } 183 184 /* 185 * Search the default environment for a variable. 186 * Return the value, if found, or NULL, if not found. 187 */ 188 char *fw_getdefenv(char *name) 189 { 190 char *env, *nxt; 191 192 for (env = default_environment; *env; env = nxt + 1) { 193 char *val; 194 195 for (nxt = env; *nxt; ++nxt) { 196 if (nxt >= &default_environment[ENV_SIZE]) { 197 fprintf(stderr, "## Error: " 198 "default environment not terminated\n"); 199 return NULL; 200 } 201 } 202 val = envmatch(name, env); 203 if (!val) 204 continue; 205 return val; 206 } 207 return NULL; 208 } 209 210 int parse_aes_key(char *key, uint8_t *bin_key) 211 { 212 char tmp[5] = { '0', 'x', 0, 0, 0 }; 213 unsigned long ul; 214 int i; 215 216 if (strnlen(key, 64) != 32) { 217 fprintf(stderr, 218 "## Error: '-a' option requires 16-byte AES key\n"); 219 return -1; 220 } 221 222 for (i = 0; i < 16; i++) { 223 tmp[2] = key[0]; 224 tmp[3] = key[1]; 225 errno = 0; 226 ul = strtoul(tmp, NULL, 16); 227 if (errno) { 228 fprintf(stderr, 229 "## Error: '-a' option requires valid AES key\n"); 230 return -1; 231 } 232 bin_key[i] = ul & 0xff; 233 key += 2; 234 } 235 return 0; 236 } 237 238 /* 239 * Print the current definition of one, or more, or all 240 * environment variables 241 */ 242 int fw_printenv (int argc, char *argv[]) 243 { 244 char *env, *nxt; 245 int i, rc = 0; 246 247 if (fw_env_open()) 248 return -1; 249 250 if (argc == 0) { /* Print all env variables */ 251 for (env = environment.data; *env; env = nxt + 1) { 252 for (nxt = env; *nxt; ++nxt) { 253 if (nxt >= &environment.data[ENV_SIZE]) { 254 fprintf (stderr, "## Error: " 255 "environment not terminated\n"); 256 return -1; 257 } 258 } 259 260 printf ("%s\n", env); 261 } 262 return 0; 263 } 264 265 if (printenv_args.name_suppress && argc != 1) { 266 fprintf(stderr, 267 "## Error: `-n' option requires exactly one argument\n"); 268 return -1; 269 } 270 271 for (i = 0; i < argc; ++i) { /* print single env variables */ 272 char *name = argv[i]; 273 char *val = NULL; 274 275 for (env = environment.data; *env; env = nxt + 1) { 276 277 for (nxt = env; *nxt; ++nxt) { 278 if (nxt >= &environment.data[ENV_SIZE]) { 279 fprintf (stderr, "## Error: " 280 "environment not terminated\n"); 281 return -1; 282 } 283 } 284 val = envmatch (name, env); 285 if (val) { 286 if (!printenv_args.name_suppress) { 287 fputs (name, stdout); 288 putc ('=', stdout); 289 } 290 puts (val); 291 break; 292 } 293 } 294 if (!val) { 295 fprintf (stderr, "## Error: \"%s\" not defined\n", name); 296 rc = -1; 297 } 298 } 299 300 return rc; 301 } 302 303 int fw_env_close(void) 304 { 305 int ret; 306 if (common_args.aes_flag) { 307 ret = env_aes_cbc_crypt(environment.data, 1); 308 if (ret) { 309 fprintf(stderr, 310 "Error: can't encrypt env for flash\n"); 311 return ret; 312 } 313 } 314 315 /* 316 * Update CRC 317 */ 318 *environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE); 319 320 /* write environment back to flash */ 321 if (flash_io(O_RDWR)) { 322 fprintf(stderr, 323 "Error: can't write fw_env to flash\n"); 324 return -1; 325 } 326 327 return 0; 328 } 329 330 331 /* 332 * Set/Clear a single variable in the environment. 333 * This is called in sequence to update the environment 334 * in RAM without updating the copy in flash after each set 335 */ 336 int fw_env_write(char *name, char *value) 337 { 338 int len; 339 char *env, *nxt; 340 char *oldval = NULL; 341 int deleting, creating, overwriting; 342 343 /* 344 * search if variable with this name already exists 345 */ 346 for (nxt = env = environment.data; *env; env = nxt + 1) { 347 for (nxt = env; *nxt; ++nxt) { 348 if (nxt >= &environment.data[ENV_SIZE]) { 349 fprintf(stderr, "## Error: " 350 "environment not terminated\n"); 351 errno = EINVAL; 352 return -1; 353 } 354 } 355 if ((oldval = envmatch (name, env)) != NULL) 356 break; 357 } 358 359 deleting = (oldval && !(value && strlen(value))); 360 creating = (!oldval && (value && strlen(value))); 361 overwriting = (oldval && (value && strlen(value))); 362 363 /* check for permission */ 364 if (deleting) { 365 if (env_flags_validate_varaccess(name, 366 ENV_FLAGS_VARACCESS_PREVENT_DELETE)) { 367 printf("Can't delete \"%s\"\n", name); 368 errno = EROFS; 369 return -1; 370 } 371 } else if (overwriting) { 372 if (env_flags_validate_varaccess(name, 373 ENV_FLAGS_VARACCESS_PREVENT_OVERWR)) { 374 printf("Can't overwrite \"%s\"\n", name); 375 errno = EROFS; 376 return -1; 377 } else if (env_flags_validate_varaccess(name, 378 ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR)) { 379 const char *defval = fw_getdefenv(name); 380 381 if (defval == NULL) 382 defval = ""; 383 if (strcmp(oldval, defval) 384 != 0) { 385 printf("Can't overwrite \"%s\"\n", name); 386 errno = EROFS; 387 return -1; 388 } 389 } 390 } else if (creating) { 391 if (env_flags_validate_varaccess(name, 392 ENV_FLAGS_VARACCESS_PREVENT_CREATE)) { 393 printf("Can't create \"%s\"\n", name); 394 errno = EROFS; 395 return -1; 396 } 397 } else 398 /* Nothing to do */ 399 return 0; 400 401 if (deleting || overwriting) { 402 if (*++nxt == '\0') { 403 *env = '\0'; 404 } else { 405 for (;;) { 406 *env = *nxt++; 407 if ((*env == '\0') && (*nxt == '\0')) 408 break; 409 ++env; 410 } 411 } 412 *++env = '\0'; 413 } 414 415 /* Delete only ? */ 416 if (!value || !strlen(value)) 417 return 0; 418 419 /* 420 * Append new definition at the end 421 */ 422 for (env = environment.data; *env || *(env + 1); ++env); 423 if (env > environment.data) 424 ++env; 425 /* 426 * Overflow when: 427 * "name" + "=" + "val" +"\0\0" > CUR_ENVSIZE - (env-environment) 428 */ 429 len = strlen (name) + 2; 430 /* add '=' for first arg, ' ' for all others */ 431 len += strlen(value) + 1; 432 433 if (len > (&environment.data[ENV_SIZE] - env)) { 434 fprintf (stderr, 435 "Error: environment overflow, \"%s\" deleted\n", 436 name); 437 return -1; 438 } 439 440 while ((*env = *name++) != '\0') 441 env++; 442 *env = '='; 443 while ((*++env = *value++) != '\0') 444 ; 445 446 /* end is marked with double '\0' */ 447 *++env = '\0'; 448 449 return 0; 450 } 451 452 /* 453 * Deletes or sets environment variables. Returns -1 and sets errno error codes: 454 * 0 - OK 455 * EINVAL - need at least 1 argument 456 * EROFS - certain variables ("ethaddr", "serial#") cannot be 457 * modified or deleted 458 * 459 */ 460 int fw_setenv(int argc, char *argv[]) 461 { 462 int i; 463 size_t len; 464 char *name, **valv; 465 char *value = NULL; 466 int valc; 467 468 if (argc < 1) { 469 fprintf(stderr, "## Error: variable name missing\n"); 470 errno = EINVAL; 471 return -1; 472 } 473 474 if (fw_env_open()) { 475 fprintf(stderr, "Error: environment not initialized\n"); 476 return -1; 477 } 478 479 name = argv[0]; 480 valv = argv + 1; 481 valc = argc - 1; 482 483 if (env_flags_validate_env_set_params(name, valv, valc) < 0) 484 return 1; 485 486 len = 0; 487 for (i = 0; i < valc; ++i) { 488 char *val = valv[i]; 489 size_t val_len = strlen(val); 490 491 if (value) 492 value[len - 1] = ' '; 493 value = realloc(value, len + val_len + 1); 494 if (!value) { 495 fprintf(stderr, 496 "Cannot malloc %zu bytes: %s\n", 497 len, strerror(errno)); 498 return -1; 499 } 500 501 memcpy(value + len, val, val_len); 502 len += val_len; 503 value[len++] = '\0'; 504 } 505 506 fw_env_write(name, value); 507 508 free(value); 509 510 return fw_env_close(); 511 } 512 513 /* 514 * Parse a file and configure the u-boot variables. 515 * The script file has a very simple format, as follows: 516 * 517 * Each line has a couple with name, value: 518 * <white spaces>variable_name<white spaces>variable_value 519 * 520 * Both variable_name and variable_value are interpreted as strings. 521 * Any character after <white spaces> and before ending \r\n is interpreted 522 * as variable's value (no comment allowed on these lines !) 523 * 524 * Comments are allowed if the first character in the line is # 525 * 526 * Returns -1 and sets errno error codes: 527 * 0 - OK 528 * -1 - Error 529 */ 530 int fw_parse_script(char *fname) 531 { 532 FILE *fp; 533 char dump[1024]; /* Maximum line length in the file */ 534 char *name; 535 char *val; 536 int lineno = 0; 537 int len; 538 int ret = 0; 539 540 if (fw_env_open()) { 541 fprintf(stderr, "Error: environment not initialized\n"); 542 return -1; 543 } 544 545 if (strcmp(fname, "-") == 0) 546 fp = stdin; 547 else { 548 fp = fopen(fname, "r"); 549 if (fp == NULL) { 550 fprintf(stderr, "I cannot open %s for reading\n", 551 fname); 552 return -1; 553 } 554 } 555 556 while (fgets(dump, sizeof(dump), fp)) { 557 lineno++; 558 len = strlen(dump); 559 560 /* 561 * Read a whole line from the file. If the line is too long 562 * or is not terminated, reports an error and exit. 563 */ 564 if (dump[len - 1] != '\n') { 565 fprintf(stderr, 566 "Line %d not corrected terminated or too long\n", 567 lineno); 568 ret = -1; 569 break; 570 } 571 572 /* Drop ending line feed / carriage return */ 573 dump[--len] = '\0'; 574 if (len && dump[len - 1] == '\r') 575 dump[--len] = '\0'; 576 577 /* Skip comment or empty lines */ 578 if (len == 0 || dump[0] == '#') 579 continue; 580 581 /* 582 * Search for variable's name, 583 * remove leading whitespaces 584 */ 585 name = skip_blanks(dump); 586 if (!name) 587 continue; 588 589 /* The first white space is the end of variable name */ 590 val = skip_chars(name); 591 len = strlen(name); 592 if (val) { 593 *val++ = '\0'; 594 if ((val - name) < len) 595 val = skip_blanks(val); 596 else 597 val = NULL; 598 } 599 600 #ifdef DEBUG 601 fprintf(stderr, "Setting %s : %s\n", 602 name, val ? val : " removed"); 603 #endif 604 605 if (env_flags_validate_type(name, val) < 0) { 606 ret = -1; 607 break; 608 } 609 610 /* 611 * If there is an error setting a variable, 612 * try to save the environment and returns an error 613 */ 614 if (fw_env_write(name, val)) { 615 fprintf(stderr, 616 "fw_env_write returns with error : %s\n", 617 strerror(errno)); 618 ret = -1; 619 break; 620 } 621 622 } 623 624 /* Close file if not stdin */ 625 if (strcmp(fname, "-") != 0) 626 fclose(fp); 627 628 ret |= fw_env_close(); 629 630 return ret; 631 632 } 633 634 /* 635 * Test for bad block on NAND, just returns 0 on NOR, on NAND: 636 * 0 - block is good 637 * > 0 - block is bad 638 * < 0 - failed to test 639 */ 640 static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart) 641 { 642 if (mtd_type == MTD_NANDFLASH) { 643 int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart); 644 645 if (badblock < 0) { 646 perror ("Cannot read bad block mark"); 647 return badblock; 648 } 649 650 if (badblock) { 651 #ifdef DEBUG 652 fprintf (stderr, "Bad block at 0x%llx, " 653 "skipping\n", *blockstart); 654 #endif 655 return badblock; 656 } 657 } 658 659 return 0; 660 } 661 662 /* 663 * Read data from flash at an offset into a provided buffer. On NAND it skips 664 * bad blocks but makes sure it stays within ENVSECTORS (dev) starting from 665 * the DEVOFFSET (dev) block. On NOR the loop is only run once. 666 */ 667 static int flash_read_buf (int dev, int fd, void *buf, size_t count, 668 off_t offset, uint8_t mtd_type) 669 { 670 size_t blocklen; /* erase / write length - one block on NAND, 671 0 on NOR */ 672 size_t processed = 0; /* progress counter */ 673 size_t readlen = count; /* current read length */ 674 off_t top_of_range; /* end of the last block we may use */ 675 off_t block_seek; /* offset inside the current block to the start 676 of the data */ 677 loff_t blockstart; /* running start of the current block - 678 MEMGETBADBLOCK needs 64 bits */ 679 int rc; 680 681 blockstart = (offset / DEVESIZE (dev)) * DEVESIZE (dev); 682 683 /* Offset inside a block */ 684 block_seek = offset - blockstart; 685 686 if (mtd_type == MTD_NANDFLASH) { 687 /* 688 * NAND: calculate which blocks we are reading. We have 689 * to read one block at a time to skip bad blocks. 690 */ 691 blocklen = DEVESIZE (dev); 692 693 /* 694 * To calculate the top of the range, we have to use the 695 * global DEVOFFSET (dev), which can be different from offset 696 */ 697 top_of_range = ((DEVOFFSET(dev) / blocklen) + 698 ENVSECTORS (dev)) * blocklen; 699 700 /* Limit to one block for the first read */ 701 if (readlen > blocklen - block_seek) 702 readlen = blocklen - block_seek; 703 } else { 704 blocklen = 0; 705 top_of_range = offset + count; 706 } 707 708 /* This only runs once on NOR flash */ 709 while (processed < count) { 710 rc = flash_bad_block (fd, mtd_type, &blockstart); 711 if (rc < 0) /* block test failed */ 712 return -1; 713 714 if (blockstart + block_seek + readlen > top_of_range) { 715 /* End of range is reached */ 716 fprintf (stderr, 717 "Too few good blocks within range\n"); 718 return -1; 719 } 720 721 if (rc) { /* block is bad */ 722 blockstart += blocklen; 723 continue; 724 } 725 726 /* 727 * If a block is bad, we retry in the next block at the same 728 * offset - see common/env_nand.c::writeenv() 729 */ 730 lseek (fd, blockstart + block_seek, SEEK_SET); 731 732 rc = read (fd, buf + processed, readlen); 733 if (rc != readlen) { 734 fprintf (stderr, "Read error on %s: %s\n", 735 DEVNAME (dev), strerror (errno)); 736 return -1; 737 } 738 #ifdef DEBUG 739 fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n", 740 rc, blockstart + block_seek, DEVNAME(dev)); 741 #endif 742 processed += readlen; 743 readlen = min (blocklen, count - processed); 744 block_seek = 0; 745 blockstart += blocklen; 746 } 747 748 return processed; 749 } 750 751 /* 752 * Write count bytes at offset, but stay within ENVSECTORS (dev) sectors of 753 * DEVOFFSET (dev). Similar to the read case above, on NOR and dataflash we 754 * erase and write the whole data at once. 755 */ 756 static int flash_write_buf (int dev, int fd, void *buf, size_t count, 757 off_t offset, uint8_t mtd_type) 758 { 759 void *data; 760 struct erase_info_user erase; 761 size_t blocklen; /* length of NAND block / NOR erase sector */ 762 size_t erase_len; /* whole area that can be erased - may include 763 bad blocks */ 764 size_t erasesize; /* erase / write length - one block on NAND, 765 whole area on NOR */ 766 size_t processed = 0; /* progress counter */ 767 size_t write_total; /* total size to actually write - excluding 768 bad blocks */ 769 off_t erase_offset; /* offset to the first erase block (aligned) 770 below offset */ 771 off_t block_seek; /* offset inside the erase block to the start 772 of the data */ 773 off_t top_of_range; /* end of the last block we may use */ 774 loff_t blockstart; /* running start of the current block - 775 MEMGETBADBLOCK needs 64 bits */ 776 int rc; 777 778 /* 779 * For mtd devices only offset and size of the environment do matter 780 */ 781 if (mtd_type == MTD_ABSENT) { 782 blocklen = count; 783 top_of_range = offset + count; 784 erase_len = blocklen; 785 blockstart = offset; 786 block_seek = 0; 787 write_total = blocklen; 788 } else { 789 blocklen = DEVESIZE(dev); 790 791 top_of_range = ((DEVOFFSET(dev) / blocklen) + 792 ENVSECTORS(dev)) * blocklen; 793 794 erase_offset = (offset / blocklen) * blocklen; 795 796 /* Maximum area we may use */ 797 erase_len = top_of_range - erase_offset; 798 799 blockstart = erase_offset; 800 /* Offset inside a block */ 801 block_seek = offset - erase_offset; 802 803 /* 804 * Data size we actually write: from the start of the block 805 * to the start of the data, then count bytes of data, and 806 * to the end of the block 807 */ 808 write_total = ((block_seek + count + blocklen - 1) / 809 blocklen) * blocklen; 810 } 811 812 /* 813 * Support data anywhere within erase sectors: read out the complete 814 * area to be erased, replace the environment image, write the whole 815 * block back again. 816 */ 817 if (write_total > count) { 818 data = malloc (erase_len); 819 if (!data) { 820 fprintf (stderr, 821 "Cannot malloc %zu bytes: %s\n", 822 erase_len, strerror (errno)); 823 return -1; 824 } 825 826 rc = flash_read_buf (dev, fd, data, write_total, erase_offset, 827 mtd_type); 828 if (write_total != rc) 829 return -1; 830 831 #ifdef DEBUG 832 fprintf(stderr, "Preserving data "); 833 if (block_seek != 0) 834 fprintf(stderr, "0x%x - 0x%lx", 0, block_seek - 1); 835 if (block_seek + count != write_total) { 836 if (block_seek != 0) 837 fprintf(stderr, " and "); 838 fprintf(stderr, "0x%lx - 0x%x", 839 block_seek + count, write_total - 1); 840 } 841 fprintf(stderr, "\n"); 842 #endif 843 /* Overwrite the old environment */ 844 memcpy (data + block_seek, buf, count); 845 } else { 846 /* 847 * We get here, iff offset is block-aligned and count is a 848 * multiple of blocklen - see write_total calculation above 849 */ 850 data = buf; 851 } 852 853 if (mtd_type == MTD_NANDFLASH) { 854 /* 855 * NAND: calculate which blocks we are writing. We have 856 * to write one block at a time to skip bad blocks. 857 */ 858 erasesize = blocklen; 859 } else { 860 erasesize = erase_len; 861 } 862 863 erase.length = erasesize; 864 865 /* This only runs once on NOR flash and SPI-dataflash */ 866 while (processed < write_total) { 867 rc = flash_bad_block (fd, mtd_type, &blockstart); 868 if (rc < 0) /* block test failed */ 869 return rc; 870 871 if (blockstart + erasesize > top_of_range) { 872 fprintf (stderr, "End of range reached, aborting\n"); 873 return -1; 874 } 875 876 if (rc) { /* block is bad */ 877 blockstart += blocklen; 878 continue; 879 } 880 881 if (mtd_type != MTD_ABSENT) { 882 erase.start = blockstart; 883 ioctl(fd, MEMUNLOCK, &erase); 884 /* These do not need an explicit erase cycle */ 885 if (mtd_type != MTD_DATAFLASH) 886 if (ioctl(fd, MEMERASE, &erase) != 0) { 887 fprintf(stderr, 888 "MTD erase error on %s: %s\n", 889 DEVNAME(dev), strerror(errno)); 890 return -1; 891 } 892 } 893 894 if (lseek (fd, blockstart, SEEK_SET) == -1) { 895 fprintf (stderr, 896 "Seek error on %s: %s\n", 897 DEVNAME (dev), strerror (errno)); 898 return -1; 899 } 900 901 #ifdef DEBUG 902 fprintf(stderr, "Write 0x%x bytes at 0x%llx\n", erasesize, 903 blockstart); 904 #endif 905 if (write (fd, data + processed, erasesize) != erasesize) { 906 fprintf (stderr, "Write error on %s: %s\n", 907 DEVNAME (dev), strerror (errno)); 908 return -1; 909 } 910 911 if (mtd_type != MTD_ABSENT) 912 ioctl(fd, MEMLOCK, &erase); 913 914 processed += erasesize; 915 block_seek = 0; 916 blockstart += erasesize; 917 } 918 919 if (write_total > count) 920 free (data); 921 922 return processed; 923 } 924 925 /* 926 * Set obsolete flag at offset - NOR flash only 927 */ 928 static int flash_flag_obsolete (int dev, int fd, off_t offset) 929 { 930 int rc; 931 struct erase_info_user erase; 932 933 erase.start = DEVOFFSET (dev); 934 erase.length = DEVESIZE (dev); 935 /* This relies on the fact, that obsolete_flag == 0 */ 936 rc = lseek (fd, offset, SEEK_SET); 937 if (rc < 0) { 938 fprintf (stderr, "Cannot seek to set the flag on %s \n", 939 DEVNAME (dev)); 940 return rc; 941 } 942 ioctl (fd, MEMUNLOCK, &erase); 943 rc = write (fd, &obsolete_flag, sizeof (obsolete_flag)); 944 ioctl (fd, MEMLOCK, &erase); 945 if (rc < 0) 946 perror ("Could not set obsolete flag"); 947 948 return rc; 949 } 950 951 /* Encrypt or decrypt the environment before writing or reading it. */ 952 static int env_aes_cbc_crypt(char *payload, const int enc) 953 { 954 uint8_t *data = (uint8_t *)payload; 955 const int len = getenvsize(); 956 uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; 957 uint32_t aes_blocks; 958 959 /* First we expand the key. */ 960 aes_expand_key(common_args.aes_key, key_exp); 961 962 /* Calculate the number of AES blocks to encrypt. */ 963 aes_blocks = DIV_ROUND_UP(len, AES_KEY_LENGTH); 964 965 if (enc) 966 aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks); 967 else 968 aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks); 969 970 return 0; 971 } 972 973 static int flash_write (int fd_current, int fd_target, int dev_target) 974 { 975 int rc; 976 977 switch (environment.flag_scheme) { 978 case FLAG_NONE: 979 break; 980 case FLAG_INCREMENTAL: 981 (*environment.flags)++; 982 break; 983 case FLAG_BOOLEAN: 984 *environment.flags = active_flag; 985 break; 986 default: 987 fprintf (stderr, "Unimplemented flash scheme %u \n", 988 environment.flag_scheme); 989 return -1; 990 } 991 992 #ifdef DEBUG 993 fprintf(stderr, "Writing new environment at 0x%lx on %s\n", 994 DEVOFFSET (dev_target), DEVNAME (dev_target)); 995 #endif 996 997 rc = flash_write_buf(dev_target, fd_target, environment.image, 998 CUR_ENVSIZE, DEVOFFSET(dev_target), 999 DEVTYPE(dev_target)); 1000 if (rc < 0) 1001 return rc; 1002 1003 if (environment.flag_scheme == FLAG_BOOLEAN) { 1004 /* Have to set obsolete flag */ 1005 off_t offset = DEVOFFSET (dev_current) + 1006 offsetof (struct env_image_redundant, flags); 1007 #ifdef DEBUG 1008 fprintf(stderr, 1009 "Setting obsolete flag in environment at 0x%lx on %s\n", 1010 DEVOFFSET (dev_current), DEVNAME (dev_current)); 1011 #endif 1012 flash_flag_obsolete (dev_current, fd_current, offset); 1013 } 1014 1015 return 0; 1016 } 1017 1018 static int flash_read (int fd) 1019 { 1020 struct mtd_info_user mtdinfo; 1021 struct stat st; 1022 int rc; 1023 1024 rc = fstat(fd, &st); 1025 if (rc < 0) { 1026 fprintf(stderr, "Cannot stat the file %s\n", 1027 DEVNAME(dev_current)); 1028 return -1; 1029 } 1030 1031 if (S_ISCHR(st.st_mode)) { 1032 rc = ioctl(fd, MEMGETINFO, &mtdinfo); 1033 if (rc < 0) { 1034 fprintf(stderr, "Cannot get MTD information for %s\n", 1035 DEVNAME(dev_current)); 1036 return -1; 1037 } 1038 if (mtdinfo.type != MTD_NORFLASH && 1039 mtdinfo.type != MTD_NANDFLASH && 1040 mtdinfo.type != MTD_DATAFLASH && 1041 mtdinfo.type != MTD_UBIVOLUME) { 1042 fprintf (stderr, "Unsupported flash type %u on %s\n", 1043 mtdinfo.type, DEVNAME(dev_current)); 1044 return -1; 1045 } 1046 } else { 1047 memset(&mtdinfo, 0, sizeof(mtdinfo)); 1048 mtdinfo.type = MTD_ABSENT; 1049 } 1050 1051 DEVTYPE(dev_current) = mtdinfo.type; 1052 1053 rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE, 1054 DEVOFFSET (dev_current), mtdinfo.type); 1055 if (rc != CUR_ENVSIZE) 1056 return -1; 1057 1058 return 0; 1059 } 1060 1061 static int flash_io (int mode) 1062 { 1063 int fd_current, fd_target, rc, dev_target; 1064 1065 /* dev_current: fd_current, erase_current */ 1066 fd_current = open (DEVNAME (dev_current), mode); 1067 if (fd_current < 0) { 1068 fprintf (stderr, 1069 "Can't open %s: %s\n", 1070 DEVNAME (dev_current), strerror (errno)); 1071 return -1; 1072 } 1073 1074 if (mode == O_RDWR) { 1075 if (HaveRedundEnv) { 1076 /* switch to next partition for writing */ 1077 dev_target = !dev_current; 1078 /* dev_target: fd_target, erase_target */ 1079 fd_target = open (DEVNAME (dev_target), mode); 1080 if (fd_target < 0) { 1081 fprintf (stderr, 1082 "Can't open %s: %s\n", 1083 DEVNAME (dev_target), 1084 strerror (errno)); 1085 rc = -1; 1086 goto exit; 1087 } 1088 } else { 1089 dev_target = dev_current; 1090 fd_target = fd_current; 1091 } 1092 1093 rc = flash_write (fd_current, fd_target, dev_target); 1094 1095 if (HaveRedundEnv) { 1096 if (close (fd_target)) { 1097 fprintf (stderr, 1098 "I/O error on %s: %s\n", 1099 DEVNAME (dev_target), 1100 strerror (errno)); 1101 rc = -1; 1102 } 1103 } 1104 } else { 1105 rc = flash_read (fd_current); 1106 } 1107 1108 exit: 1109 if (close (fd_current)) { 1110 fprintf (stderr, 1111 "I/O error on %s: %s\n", 1112 DEVNAME (dev_current), strerror (errno)); 1113 return -1; 1114 } 1115 1116 return rc; 1117 } 1118 1119 /* 1120 * s1 is either a simple 'name', or a 'name=value' pair. 1121 * s2 is a 'name=value' pair. 1122 * If the names match, return the value of s2, else NULL. 1123 */ 1124 1125 static char *envmatch (char * s1, char * s2) 1126 { 1127 if (s1 == NULL || s2 == NULL) 1128 return NULL; 1129 1130 while (*s1 == *s2++) 1131 if (*s1++ == '=') 1132 return s2; 1133 if (*s1 == '\0' && *(s2 - 1) == '=') 1134 return s2; 1135 return NULL; 1136 } 1137 1138 /* 1139 * Prevent confusion if running from erased flash memory 1140 */ 1141 int fw_env_open(void) 1142 { 1143 int crc0, crc0_ok; 1144 unsigned char flag0; 1145 void *addr0; 1146 1147 int crc1, crc1_ok; 1148 unsigned char flag1; 1149 void *addr1; 1150 1151 int ret; 1152 1153 struct env_image_single *single; 1154 struct env_image_redundant *redundant; 1155 1156 if (parse_config ()) /* should fill envdevices */ 1157 return -1; 1158 1159 addr0 = calloc(1, CUR_ENVSIZE); 1160 if (addr0 == NULL) { 1161 fprintf(stderr, 1162 "Not enough memory for environment (%ld bytes)\n", 1163 CUR_ENVSIZE); 1164 return -1; 1165 } 1166 1167 /* read environment from FLASH to local buffer */ 1168 environment.image = addr0; 1169 1170 if (HaveRedundEnv) { 1171 redundant = addr0; 1172 environment.crc = &redundant->crc; 1173 environment.flags = &redundant->flags; 1174 environment.data = redundant->data; 1175 } else { 1176 single = addr0; 1177 environment.crc = &single->crc; 1178 environment.flags = NULL; 1179 environment.data = single->data; 1180 } 1181 1182 dev_current = 0; 1183 if (flash_io (O_RDONLY)) 1184 return -1; 1185 1186 crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); 1187 1188 if (common_args.aes_flag) { 1189 ret = env_aes_cbc_crypt(environment.data, 0); 1190 if (ret) 1191 return ret; 1192 } 1193 1194 crc0_ok = (crc0 == *environment.crc); 1195 if (!HaveRedundEnv) { 1196 if (!crc0_ok) { 1197 fprintf (stderr, 1198 "Warning: Bad CRC, using default environment\n"); 1199 memcpy(environment.data, default_environment, sizeof default_environment); 1200 } 1201 } else { 1202 flag0 = *environment.flags; 1203 1204 dev_current = 1; 1205 addr1 = calloc(1, CUR_ENVSIZE); 1206 if (addr1 == NULL) { 1207 fprintf(stderr, 1208 "Not enough memory for environment (%ld bytes)\n", 1209 CUR_ENVSIZE); 1210 return -1; 1211 } 1212 redundant = addr1; 1213 1214 /* 1215 * have to set environment.image for flash_read(), careful - 1216 * other pointers in environment still point inside addr0 1217 */ 1218 environment.image = addr1; 1219 if (flash_io (O_RDONLY)) 1220 return -1; 1221 1222 /* Check flag scheme compatibility */ 1223 if (DEVTYPE(dev_current) == MTD_NORFLASH && 1224 DEVTYPE(!dev_current) == MTD_NORFLASH) { 1225 environment.flag_scheme = FLAG_BOOLEAN; 1226 } else if (DEVTYPE(dev_current) == MTD_NANDFLASH && 1227 DEVTYPE(!dev_current) == MTD_NANDFLASH) { 1228 environment.flag_scheme = FLAG_INCREMENTAL; 1229 } else if (DEVTYPE(dev_current) == MTD_DATAFLASH && 1230 DEVTYPE(!dev_current) == MTD_DATAFLASH) { 1231 environment.flag_scheme = FLAG_BOOLEAN; 1232 } else if (DEVTYPE(dev_current) == MTD_UBIVOLUME && 1233 DEVTYPE(!dev_current) == MTD_UBIVOLUME) { 1234 environment.flag_scheme = FLAG_INCREMENTAL; 1235 } else if (DEVTYPE(dev_current) == MTD_ABSENT && 1236 DEVTYPE(!dev_current) == MTD_ABSENT) { 1237 environment.flag_scheme = FLAG_INCREMENTAL; 1238 } else { 1239 fprintf (stderr, "Incompatible flash types!\n"); 1240 return -1; 1241 } 1242 1243 crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE); 1244 1245 if (common_args.aes_flag) { 1246 ret = env_aes_cbc_crypt(redundant->data, 0); 1247 if (ret) 1248 return ret; 1249 } 1250 1251 crc1_ok = (crc1 == redundant->crc); 1252 flag1 = redundant->flags; 1253 1254 if (crc0_ok && !crc1_ok) { 1255 dev_current = 0; 1256 } else if (!crc0_ok && crc1_ok) { 1257 dev_current = 1; 1258 } else if (!crc0_ok && !crc1_ok) { 1259 fprintf (stderr, 1260 "Warning: Bad CRC, using default environment\n"); 1261 memcpy (environment.data, default_environment, 1262 sizeof default_environment); 1263 dev_current = 0; 1264 } else { 1265 switch (environment.flag_scheme) { 1266 case FLAG_BOOLEAN: 1267 if (flag0 == active_flag && 1268 flag1 == obsolete_flag) { 1269 dev_current = 0; 1270 } else if (flag0 == obsolete_flag && 1271 flag1 == active_flag) { 1272 dev_current = 1; 1273 } else if (flag0 == flag1) { 1274 dev_current = 0; 1275 } else if (flag0 == 0xFF) { 1276 dev_current = 0; 1277 } else if (flag1 == 0xFF) { 1278 dev_current = 1; 1279 } else { 1280 dev_current = 0; 1281 } 1282 break; 1283 case FLAG_INCREMENTAL: 1284 if (flag0 == 255 && flag1 == 0) 1285 dev_current = 1; 1286 else if ((flag1 == 255 && flag0 == 0) || 1287 flag0 >= flag1) 1288 dev_current = 0; 1289 else /* flag1 > flag0 */ 1290 dev_current = 1; 1291 break; 1292 default: 1293 fprintf (stderr, "Unknown flag scheme %u \n", 1294 environment.flag_scheme); 1295 return -1; 1296 } 1297 } 1298 1299 /* 1300 * If we are reading, we don't need the flag and the CRC any 1301 * more, if we are writing, we will re-calculate CRC and update 1302 * flags before writing out 1303 */ 1304 if (dev_current) { 1305 environment.image = addr1; 1306 environment.crc = &redundant->crc; 1307 environment.flags = &redundant->flags; 1308 environment.data = redundant->data; 1309 free (addr0); 1310 } else { 1311 environment.image = addr0; 1312 /* Other pointers are already set */ 1313 free (addr1); 1314 } 1315 #ifdef DEBUG 1316 fprintf(stderr, "Selected env in %s\n", DEVNAME(dev_current)); 1317 #endif 1318 } 1319 return 0; 1320 } 1321 1322 1323 static int parse_config () 1324 { 1325 struct stat st; 1326 1327 #if defined(CONFIG_FILE) 1328 if (!common_args.config_file) 1329 common_args.config_file = CONFIG_FILE; 1330 1331 /* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */ 1332 if (get_config(common_args.config_file)) { 1333 fprintf(stderr, "Cannot parse config file '%s': %m\n", 1334 common_args.config_file); 1335 return -1; 1336 } 1337 #else 1338 DEVNAME (0) = DEVICE1_NAME; 1339 DEVOFFSET (0) = DEVICE1_OFFSET; 1340 ENVSIZE (0) = ENV1_SIZE; 1341 /* Default values are: erase-size=env-size */ 1342 DEVESIZE (0) = ENVSIZE (0); 1343 /* #sectors=env-size/erase-size (rounded up) */ 1344 ENVSECTORS (0) = (ENVSIZE(0) + DEVESIZE(0) - 1) / DEVESIZE(0); 1345 #ifdef DEVICE1_ESIZE 1346 DEVESIZE (0) = DEVICE1_ESIZE; 1347 #endif 1348 #ifdef DEVICE1_ENVSECTORS 1349 ENVSECTORS (0) = DEVICE1_ENVSECTORS; 1350 #endif 1351 1352 #ifdef HAVE_REDUND 1353 DEVNAME (1) = DEVICE2_NAME; 1354 DEVOFFSET (1) = DEVICE2_OFFSET; 1355 ENVSIZE (1) = ENV2_SIZE; 1356 /* Default values are: erase-size=env-size */ 1357 DEVESIZE (1) = ENVSIZE (1); 1358 /* #sectors=env-size/erase-size (rounded up) */ 1359 ENVSECTORS (1) = (ENVSIZE(1) + DEVESIZE(1) - 1) / DEVESIZE(1); 1360 #ifdef DEVICE2_ESIZE 1361 DEVESIZE (1) = DEVICE2_ESIZE; 1362 #endif 1363 #ifdef DEVICE2_ENVSECTORS 1364 ENVSECTORS (1) = DEVICE2_ENVSECTORS; 1365 #endif 1366 HaveRedundEnv = 1; 1367 #endif 1368 #endif 1369 if (stat (DEVNAME (0), &st)) { 1370 fprintf (stderr, 1371 "Cannot access MTD device %s: %s\n", 1372 DEVNAME (0), strerror (errno)); 1373 return -1; 1374 } 1375 1376 if (HaveRedundEnv && stat (DEVNAME (1), &st)) { 1377 fprintf (stderr, 1378 "Cannot access MTD device %s: %s\n", 1379 DEVNAME (1), strerror (errno)); 1380 return -1; 1381 } 1382 return 0; 1383 } 1384 1385 #if defined(CONFIG_FILE) 1386 static int get_config (char *fname) 1387 { 1388 FILE *fp; 1389 int i = 0; 1390 int rc; 1391 char dump[128]; 1392 char *devname; 1393 1394 fp = fopen (fname, "r"); 1395 if (fp == NULL) 1396 return -1; 1397 1398 while (i < 2 && fgets (dump, sizeof (dump), fp)) { 1399 /* Skip incomplete conversions and comment strings */ 1400 if (dump[0] == '#') 1401 continue; 1402 1403 rc = sscanf (dump, "%ms %lx %lx %lx %lx", 1404 &devname, 1405 &DEVOFFSET (i), 1406 &ENVSIZE (i), 1407 &DEVESIZE (i), 1408 &ENVSECTORS (i)); 1409 1410 if (rc < 3) 1411 continue; 1412 1413 DEVNAME(i) = devname; 1414 1415 if (rc < 4) 1416 /* Assume the erase size is the same as the env-size */ 1417 DEVESIZE(i) = ENVSIZE(i); 1418 1419 if (rc < 5) 1420 /* Assume enough env sectors to cover the environment */ 1421 ENVSECTORS (i) = (ENVSIZE(i) + DEVESIZE(i) - 1) / DEVESIZE(i); 1422 1423 i++; 1424 } 1425 fclose (fp); 1426 1427 HaveRedundEnv = i - 1; 1428 if (!i) { /* No valid entries found */ 1429 errno = EINVAL; 1430 return -1; 1431 } else 1432 return 0; 1433 } 1434 #endif 1435