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