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