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