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