Prepare v2023.10
[platform/kernel/u-boot.git] / tools / env / fw_env.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2000-2010
4  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5  *
6  * (C) Copyright 2008
7  * Guennadi Liakhovetski, DENX Software Engineering, lg@denx.de.
8  */
9
10 #define _GNU_SOURCE
11
12 #include <compiler.h>
13 #include <env.h>
14 #include <errno.h>
15 #include <env_flags.h>
16 #include <fcntl.h>
17 #include <libgen.h>
18 #include <linux/fs.h>
19 #include <linux/stringify.h>
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/ioctl.h>
27 #include <sys/stat.h>
28 #include <u-boot/crc.h>
29 #include <unistd.h>
30 #include <dirent.h>
31
32 #ifdef MTD_OLD
33 # include <stdint.h>
34 # include <linux/mtd/mtd.h>
35 #else
36 # define  __user        /* nothing */
37 # include <mtd/mtd-user.h>
38 #endif
39
40 #include <mtd/ubi-user.h>
41
42 #include "fw_env_private.h"
43 #include "fw_env.h"
44
45 struct env_opts default_opts = {
46 #ifdef CONFIG_FILE
47         .config_file = CONFIG_FILE
48 #endif
49 };
50
51 #define DIV_ROUND_UP(n, d)      (((n) + (d) - 1) / (d))
52
53 #define min(x, y) ({                            \
54         typeof(x) _min1 = (x);                  \
55         typeof(y) _min2 = (y);                  \
56         (void) (&_min1 == &_min2);              \
57         _min1 < _min2 ? _min1 : _min2; })
58
59 struct envdev_s {
60         const char *devname;            /* Device name */
61         long long devoff;               /* Device offset */
62         ulong env_size;                 /* environment size */
63         ulong erase_size;               /* device erase size */
64         ulong env_sectors;              /* number of environment sectors */
65         uint8_t mtd_type;               /* type of the MTD device */
66         int is_ubi;                     /* set if we use UBI volume */
67 };
68
69 static struct envdev_s envdevices[2] = {
70         {
71                 .mtd_type = MTD_ABSENT,
72         }, {
73                 .mtd_type = MTD_ABSENT,
74         },
75 };
76
77 static int dev_current;
78
79 #define DEVNAME(i)    envdevices[(i)].devname
80 #define DEVOFFSET(i)  envdevices[(i)].devoff
81 #define ENVSIZE(i)    envdevices[(i)].env_size
82 #define DEVESIZE(i)   envdevices[(i)].erase_size
83 #define ENVSECTORS(i) envdevices[(i)].env_sectors
84 #define DEVTYPE(i)    envdevices[(i)].mtd_type
85 #define IS_UBI(i)     envdevices[(i)].is_ubi
86
87 #define CUR_ENVSIZE ENVSIZE(dev_current)
88
89 static unsigned long usable_envsize;
90 #define ENV_SIZE      usable_envsize
91
92 struct env_image_single {
93         uint32_t crc;           /* CRC32 over data bytes    */
94         char data[];
95 };
96
97 struct env_image_redundant {
98         uint32_t crc;           /* CRC32 over data bytes    */
99         unsigned char flags;    /* active or obsolete */
100         char data[];
101 };
102
103 enum flag_scheme {
104         FLAG_NONE,
105         FLAG_BOOLEAN,
106         FLAG_INCREMENTAL,
107 };
108
109 struct environment {
110         void *image;
111         uint32_t *crc;
112         unsigned char *flags;
113         char *data;
114         enum flag_scheme flag_scheme;
115         int dirty;
116 };
117
118 static struct environment environment = {
119         .flag_scheme = FLAG_NONE,
120 };
121
122 static int have_redund_env;
123
124 #define DEFAULT_ENV_INSTANCE_STATIC
125 #include <env_default.h>
126
127 #define UBI_DEV_START "/dev/ubi"
128 #define UBI_SYSFS "/sys/class/ubi"
129 #define UBI_VOL_NAME_PATT "ubi%d_%d"
130
131 static int is_ubi_devname(const char *devname)
132 {
133         return !strncmp(devname, UBI_DEV_START, sizeof(UBI_DEV_START) - 1);
134 }
135
136 static int ubi_check_volume_sysfs_name(const char *volume_sysfs_name,
137                                        const char *volname)
138 {
139         char path[256];
140         FILE *file;
141         char *name;
142         int ret;
143
144         strcpy(path, UBI_SYSFS "/");
145         strcat(path, volume_sysfs_name);
146         strcat(path, "/name");
147
148         file = fopen(path, "r");
149         if (!file)
150                 return -1;
151
152         ret = fscanf(file, "%ms", &name);
153         fclose(file);
154         if (ret <= 0 || !name) {
155                 fprintf(stderr,
156                         "Failed to read from file %s, ret = %d, name = %s\n",
157                         path, ret, name);
158                 return -1;
159         }
160
161         if (!strcmp(name, volname)) {
162                 free(name);
163                 return 0;
164         }
165         free(name);
166
167         return -1;
168 }
169
170 static int ubi_get_volnum_by_name(int devnum, const char *volname)
171 {
172         DIR *sysfs_ubi;
173         struct dirent *dirent;
174         int ret;
175         int tmp_devnum;
176         int volnum;
177
178         sysfs_ubi = opendir(UBI_SYSFS);
179         if (!sysfs_ubi)
180                 return -1;
181
182 #ifdef DEBUG
183         fprintf(stderr, "Looking for volume name \"%s\"\n", volname);
184 #endif
185
186         while (1) {
187                 dirent = readdir(sysfs_ubi);
188                 if (!dirent)
189                         return -1;
190
191                 ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT,
192                              &tmp_devnum, &volnum);
193                 if (ret == 2 && devnum == tmp_devnum) {
194                         if (ubi_check_volume_sysfs_name(dirent->d_name,
195                                                         volname) == 0) {
196                                 closedir(sysfs_ubi);
197                                 return volnum;
198                         }
199                 }
200         }
201         closedir(sysfs_ubi);
202
203         return -1;
204 }
205
206 static int ubi_get_devnum_by_devname(const char *devname)
207 {
208         int devnum;
209         int ret;
210
211         ret = sscanf(devname + sizeof(UBI_DEV_START) - 1, "%d", &devnum);
212         if (ret != 1)
213                 return -1;
214
215         return devnum;
216 }
217
218 static const char *ubi_get_volume_devname(const char *devname,
219                                           const char *volname)
220 {
221         char *volume_devname;
222         int volnum;
223         int devnum;
224         int ret;
225
226         devnum = ubi_get_devnum_by_devname(devname);
227         if (devnum < 0)
228                 return NULL;
229
230         volnum = ubi_get_volnum_by_name(devnum, volname);
231         if (volnum < 0)
232                 return NULL;
233
234         ret = asprintf(&volume_devname, "%s_%d", devname, volnum);
235         if (ret < 0)
236                 return NULL;
237
238 #ifdef DEBUG
239         fprintf(stderr, "Found ubi volume \"%s:%s\" -> %s\n",
240                 devname, volname, volume_devname);
241 #endif
242
243         return volume_devname;
244 }
245
246 static void ubi_check_dev(unsigned int dev_id)
247 {
248         char *devname = (char *)DEVNAME(dev_id);
249         char *pname;
250         const char *volname = NULL;
251         const char *volume_devname;
252
253         if (!is_ubi_devname(DEVNAME(dev_id)))
254                 return;
255
256         IS_UBI(dev_id) = 1;
257
258         for (pname = devname; *pname != '\0'; pname++) {
259                 if (*pname == ':') {
260                         *pname = '\0';
261                         volname = pname + 1;
262                         break;
263                 }
264         }
265
266         if (volname) {
267                 /* Let's find real volume device name */
268                 volume_devname = ubi_get_volume_devname(devname, volname);
269                 if (!volume_devname) {
270                         fprintf(stderr, "Didn't found ubi volume \"%s\"\n",
271                                 volname);
272                         return;
273                 }
274
275                 free(devname);
276                 DEVNAME(dev_id) = volume_devname;
277         }
278 }
279
280 static int ubi_update_start(int fd, int64_t bytes)
281 {
282         if (ioctl(fd, UBI_IOCVOLUP, &bytes))
283                 return -1;
284         return 0;
285 }
286
287 static int ubi_read(int fd, void *buf, size_t count)
288 {
289         ssize_t ret;
290
291         while (count > 0) {
292                 ret = read(fd, buf, count);
293                 if (ret > 0) {
294                         count -= ret;
295                         buf += ret;
296
297                         continue;
298                 }
299
300                 if (ret == 0) {
301                         /*
302                          * Happens in case of too short volume data size. If we
303                          * return error status we will fail it will be treated
304                          * as UBI device error.
305                          *
306                          * Leave catching this error to CRC check.
307                          */
308                         fprintf(stderr, "Warning: end of data on ubi volume\n");
309                         return 0;
310                 } else if (errno == EBADF) {
311                         /*
312                          * Happens in case of corrupted volume. The same as
313                          * above, we cannot return error now, as we will still
314                          * be able to successfully write environment later.
315                          */
316                         fprintf(stderr, "Warning: corrupted volume?\n");
317                         return 0;
318                 } else if (errno == EINTR) {
319                         continue;
320                 }
321
322                 fprintf(stderr, "Cannot read %u bytes from ubi volume, %s\n",
323                         (unsigned int)count, strerror(errno));
324                 return -1;
325         }
326
327         return 0;
328 }
329
330 static int ubi_write(int fd, const void *buf, size_t count)
331 {
332         ssize_t ret;
333
334         while (count > 0) {
335                 ret = write(fd, buf, count);
336                 if (ret <= 0) {
337                         if (ret < 0 && errno == EINTR)
338                                 continue;
339
340                         fprintf(stderr, "Cannot write %u bytes to ubi volume\n",
341                                 (unsigned int)count);
342                         return -1;
343                 }
344
345                 count -= ret;
346                 buf += ret;
347         }
348
349         return 0;
350 }
351
352 static int flash_io(int mode, void *buf, size_t count);
353 static int parse_config(struct env_opts *opts);
354
355 #if defined(CONFIG_FILE)
356 static int get_config(char *);
357 #endif
358
359 static char *skip_chars(char *s)
360 {
361         for (; *s != '\0'; s++) {
362                 if (isblank(*s) || *s == '=')
363                         return s;
364         }
365         return NULL;
366 }
367
368 static char *skip_blanks(char *s)
369 {
370         for (; *s != '\0'; s++) {
371                 if (!isblank(*s))
372                         return s;
373         }
374         return NULL;
375 }
376
377 /*
378  * s1 is either a simple 'name', or a 'name=value' pair.
379  * s2 is a 'name=value' pair.
380  * If the names match, return the value of s2, else NULL.
381  */
382 static char *envmatch(char *s1, char *s2)
383 {
384         if (s1 == NULL || s2 == NULL)
385                 return NULL;
386
387         while (*s1 == *s2++)
388                 if (*s1++ == '=')
389                         return s2;
390         if (*s1 == '\0' && *(s2 - 1) == '=')
391                 return s2;
392         return NULL;
393 }
394
395 /**
396  * Search the environment for a variable.
397  * Return the value, if found, or NULL, if not found.
398  */
399 char *fw_getenv(char *name)
400 {
401         char *env, *nxt;
402
403         for (env = environment.data; *env; env = nxt + 1) {
404                 char *val;
405
406                 for (nxt = env; *nxt; ++nxt) {
407                         if (nxt >= &environment.data[ENV_SIZE]) {
408                                 fprintf(stderr, "## Error: "
409                                         "environment not terminated\n");
410                                 return NULL;
411                         }
412                 }
413                 val = envmatch(name, env);
414                 if (!val)
415                         continue;
416                 return val;
417         }
418         return NULL;
419 }
420
421 /*
422  * Search the default environment for a variable.
423  * Return the value, if found, or NULL, if not found.
424  */
425 char *fw_getdefenv(char *name)
426 {
427         char *env, *nxt;
428
429         for (env = default_environment; *env; env = nxt + 1) {
430                 char *val;
431
432                 for (nxt = env; *nxt; ++nxt) {
433                         if (nxt >= &default_environment[ENV_SIZE]) {
434                                 fprintf(stderr, "## Error: "
435                                         "default environment not terminated\n");
436                                 return NULL;
437                         }
438                 }
439                 val = envmatch(name, env);
440                 if (!val)
441                         continue;
442                 return val;
443         }
444         return NULL;
445 }
446
447 /*
448  * Print the current definition of one, or more, or all
449  * environment variables
450  */
451 int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts)
452 {
453         int i, rc = 0;
454
455         if (value_only && argc != 1) {
456                 fprintf(stderr,
457                         "## Error: `-n'/`--noheader' option requires exactly one argument\n");
458                 return -1;
459         }
460
461         if (!opts)
462                 opts = &default_opts;
463
464         if (fw_env_open(opts))
465                 return -1;
466
467         if (argc == 0) {        /* Print all env variables  */
468                 char *env, *nxt;
469                 for (env = environment.data; *env; env = nxt + 1) {
470                         for (nxt = env; *nxt; ++nxt) {
471                                 if (nxt >= &environment.data[ENV_SIZE]) {
472                                         fprintf(stderr, "## Error: "
473                                                 "environment not terminated\n");
474                                         return -1;
475                                 }
476                         }
477
478                         printf("%s\n", env);
479                 }
480                 fw_env_close(opts);
481                 return 0;
482         }
483
484         for (i = 0; i < argc; ++i) {    /* print a subset of env variables */
485                 char *name = argv[i];
486                 char *val = NULL;
487
488                 val = fw_getenv(name);
489                 if (!val) {
490                         fprintf(stderr, "## Error: \"%s\" not defined\n", name);
491                         rc = -1;
492                         continue;
493                 }
494
495                 if (value_only) {
496                         puts(val);
497                         break;
498                 }
499
500                 printf("%s=%s\n", name, val);
501         }
502
503         fw_env_close(opts);
504
505         return rc;
506 }
507
508 int fw_env_flush(struct env_opts *opts)
509 {
510         if (!opts)
511                 opts = &default_opts;
512
513         if (!environment.dirty)
514                 return 0;
515
516         /*
517          * Update CRC
518          */
519         *environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE);
520
521         /* write environment back to flash */
522         if (flash_io(O_RDWR, environment.image, CUR_ENVSIZE)) {
523                 fprintf(stderr, "Error: can't write fw_env to flash\n");
524                 return -1;
525         }
526
527         return 0;
528 }
529
530 /*
531  * Set/Clear a single variable in the environment.
532  * This is called in sequence to update the environment
533  * in RAM without updating the copy in flash after each set
534  */
535 int fw_env_write(char *name, char *value)
536 {
537         int len;
538         char *env, *nxt;
539         char *oldval = NULL;
540         int deleting, creating, overwriting;
541
542         /*
543          * search if variable with this name already exists
544          */
545         for (nxt = env = environment.data; *env; env = nxt + 1) {
546                 for (nxt = env; *nxt; ++nxt) {
547                         if (nxt >= &environment.data[ENV_SIZE]) {
548                                 fprintf(stderr, "## Error: "
549                                         "environment not terminated\n");
550                                 errno = EINVAL;
551                                 return -1;
552                         }
553                 }
554                 oldval = envmatch(name, env);
555                 if (oldval)
556                         break;
557         }
558
559         deleting = (oldval && !(value && strlen(value)));
560         creating = (!oldval && (value && strlen(value)));
561         overwriting = (oldval && (value && strlen(value) &&
562                                   strcmp(oldval, value)));
563
564         /* check for permission */
565         if (deleting) {
566                 if (env_flags_validate_varaccess(name,
567                     ENV_FLAGS_VARACCESS_PREVENT_DELETE)) {
568                         printf("Can't delete \"%s\"\n", name);
569                         errno = EROFS;
570                         return -1;
571                 }
572         } else if (overwriting) {
573                 if (env_flags_validate_varaccess(name,
574                     ENV_FLAGS_VARACCESS_PREVENT_OVERWR)) {
575                         printf("Can't overwrite \"%s\"\n", name);
576                         errno = EROFS;
577                         return -1;
578                 } else if (env_flags_validate_varaccess(name,
579                            ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR)) {
580                         const char *defval = fw_getdefenv(name);
581
582                         if (defval == NULL)
583                                 defval = "";
584                         if (strcmp(oldval, defval)
585                             != 0) {
586                                 printf("Can't overwrite \"%s\"\n", name);
587                                 errno = EROFS;
588                                 return -1;
589                         }
590                 }
591         } else if (creating) {
592                 if (env_flags_validate_varaccess(name,
593                     ENV_FLAGS_VARACCESS_PREVENT_CREATE)) {
594                         printf("Can't create \"%s\"\n", name);
595                         errno = EROFS;
596                         return -1;
597                 }
598         } else
599                 /* Nothing to do */
600                 return 0;
601
602         environment.dirty = 1;
603         if (deleting || overwriting) {
604                 if (*++nxt == '\0') {
605                         *env = '\0';
606                 } else {
607                         for (;;) {
608                                 *env = *nxt++;
609                                 if ((*env == '\0') && (*nxt == '\0'))
610                                         break;
611                                 ++env;
612                         }
613                 }
614                 *++env = '\0';
615         }
616
617         /* Delete only ? */
618         if (!value || !strlen(value))
619                 return 0;
620
621         /*
622          * Append new definition at the end
623          */
624         for (env = environment.data; *env || *(env + 1); ++env)
625                 ;
626         if (env > environment.data)
627                 ++env;
628         /*
629          * Overflow when:
630          * "name" + "=" + "val" +"\0\0"  > CUR_ENVSIZE - (env-environment)
631          */
632         len = strlen(name) + 2;
633         /* add '=' for first arg, ' ' for all others */
634         len += strlen(value) + 1;
635
636         if (len > (&environment.data[ENV_SIZE] - env)) {
637                 fprintf(stderr,
638                         "Error: environment overflow, \"%s\" deleted\n", name);
639                 return -1;
640         }
641
642         while ((*env = *name++) != '\0')
643                 env++;
644         *env = '=';
645         while ((*++env = *value++) != '\0')
646                 ;
647
648         /* end is marked with double '\0' */
649         *++env = '\0';
650
651         return 0;
652 }
653
654 /*
655  * Deletes or sets environment variables. Returns -1 and sets errno error codes:
656  * 0      - OK
657  * EINVAL - need at least 1 argument
658  * EROFS  - certain variables ("ethaddr", "serial#") cannot be
659  *          modified or deleted
660  *
661  */
662 int fw_env_set(int argc, char *argv[], struct env_opts *opts)
663 {
664         int i;
665         size_t len;
666         char *name, **valv;
667         char *oldval;
668         char *value = NULL;
669         int valc;
670         int ret;
671
672         if (!opts)
673                 opts = &default_opts;
674
675         if (argc < 1) {
676                 fprintf(stderr, "## Error: variable name missing\n");
677                 errno = EINVAL;
678                 return -1;
679         }
680
681         if (fw_env_open(opts)) {
682                 fprintf(stderr, "Error: environment not initialized\n");
683                 return -1;
684         }
685
686         name = argv[0];
687         valv = argv + 1;
688         valc = argc - 1;
689
690         if (env_flags_validate_env_set_params(name, valv, valc) < 0) {
691                 fw_env_close(opts);
692                 return -1;
693         }
694
695         len = 0;
696         for (i = 0; i < valc; ++i) {
697                 char *val = valv[i];
698                 size_t val_len = strlen(val);
699
700                 if (value)
701                         value[len - 1] = ' ';
702                 oldval = value;
703                 value = realloc(value, len + val_len + 1);
704                 if (!value) {
705                         fprintf(stderr,
706                                 "Cannot malloc %zu bytes: %s\n",
707                                 len, strerror(errno));
708                         free(oldval);
709                         return -1;
710                 }
711
712                 memcpy(value + len, val, val_len);
713                 len += val_len;
714                 value[len++] = '\0';
715         }
716
717         fw_env_write(name, value);
718
719         free(value);
720
721         ret = fw_env_flush(opts);
722         fw_env_close(opts);
723
724         return ret;
725 }
726
727 /*
728  * Parse  a file  and configure the u-boot variables.
729  * The script file has a very simple format, as follows:
730  *
731  * Each line has a couple with name, value:
732  * <white spaces>variable_name<white spaces>variable_value
733  *
734  * Both variable_name and variable_value are interpreted as strings.
735  * Any character after <white spaces> and before ending \r\n is interpreted
736  * as variable's value (no comment allowed on these lines !)
737  *
738  * Comments are allowed if the first character in the line is #
739  *
740  * Returns -1 and sets errno error codes:
741  * 0      - OK
742  * -1     - Error
743  */
744 int fw_parse_script(char *fname, struct env_opts *opts)
745 {
746         FILE *fp;
747         char *line = NULL;
748         size_t linesize = 0;
749         char *name;
750         char *val;
751         int lineno = 0;
752         int len;
753         int ret = 0;
754
755         if (!opts)
756                 opts = &default_opts;
757
758         if (fw_env_open(opts)) {
759                 fprintf(stderr, "Error: environment not initialized\n");
760                 return -1;
761         }
762
763         if (strcmp(fname, "-") == 0)
764                 fp = stdin;
765         else {
766                 fp = fopen(fname, "r");
767                 if (fp == NULL) {
768                         fprintf(stderr, "I cannot open %s for reading\n",
769                                 fname);
770                         return -1;
771                 }
772         }
773
774         while ((len = getline(&line, &linesize, fp)) != -1) {
775                 lineno++;
776
777                 /*
778                  * Read a whole line from the file. If the line is not
779                  * terminated, reports an error and exit.
780                  */
781                 if (line[len - 1] != '\n') {
782                         fprintf(stderr,
783                                 "Line %d not correctly terminated\n",
784                                 lineno);
785                         ret = -1;
786                         break;
787                 }
788
789                 /* Drop ending line feed / carriage return */
790                 line[--len] = '\0';
791                 if (len && line[len - 1] == '\r')
792                         line[--len] = '\0';
793
794                 /* Skip comment or empty lines */
795                 if (len == 0 || line[0] == '#')
796                         continue;
797
798                 /*
799                  * Search for variable's name remove leading whitespaces
800                  */
801                 name = skip_blanks(line);
802                 if (!name)
803                         continue;
804
805                 /* The first white space is the end of variable name */
806                 val = skip_chars(name);
807                 len = strlen(name);
808                 if (val) {
809                         *val++ = '\0';
810                         if ((val - name) < len)
811                                 val = skip_blanks(val);
812                         else
813                                 val = NULL;
814                 }
815 #ifdef DEBUG
816                 fprintf(stderr, "Setting %s : %s\n",
817                         name, val ? val : " removed");
818 #endif
819
820                 if (env_flags_validate_type(name, val) < 0) {
821                         ret = -1;
822                         break;
823                 }
824
825                 /*
826                  * If there is an error setting a variable,
827                  * try to save the environment and returns an error
828                  */
829                 if (fw_env_write(name, val)) {
830                         fprintf(stderr,
831                                 "fw_env_write returns with error : %s\n",
832                                 strerror(errno));
833                         ret = -1;
834                         break;
835                 }
836
837         }
838         free(line);
839
840         /* Close file if not stdin */
841         if (strcmp(fname, "-") != 0)
842                 fclose(fp);
843
844         ret |= fw_env_flush(opts);
845
846         fw_env_close(opts);
847
848         return ret;
849 }
850
851 /**
852  * environment_end() - compute offset of first byte right after environment
853  * @dev - index of enviroment buffer
854  * Return:
855  *  device offset of first byte right after environment
856  */
857 off_t environment_end(int dev)
858 {
859         /* environment is block aligned */
860         return DEVOFFSET(dev) + ENVSECTORS(dev) * DEVESIZE(dev);
861 }
862
863 /*
864  * Test for bad block on NAND, just returns 0 on NOR, on NAND:
865  * 0    - block is good
866  * > 0  - block is bad
867  * < 0  - failed to test
868  */
869 static int flash_bad_block(int fd, uint8_t mtd_type, loff_t blockstart)
870 {
871         if (mtd_type == MTD_NANDFLASH) {
872                 int badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart);
873
874                 if (badblock < 0) {
875                         perror("Cannot read bad block mark");
876                         return badblock;
877                 }
878
879                 if (badblock) {
880 #ifdef DEBUG
881                         fprintf(stderr, "Bad block at 0x%llx, skipping\n",
882                                 (unsigned long long)blockstart);
883 #endif
884                         return badblock;
885                 }
886         }
887
888         return 0;
889 }
890
891 /*
892  * Read data from flash at an offset into a provided buffer. On NAND it skips
893  * bad blocks but makes sure it stays within ENVSECTORS (dev) starting from
894  * the DEVOFFSET (dev) block. On NOR the loop is only run once.
895  */
896 static int flash_read_buf(int dev, int fd, void *buf, size_t count,
897                           off_t offset)
898 {
899         size_t blocklen;        /* erase / write length - one block on NAND,
900                                    0 on NOR */
901         size_t processed = 0;   /* progress counter */
902         size_t readlen = count; /* current read length */
903         off_t block_seek;       /* offset inside the current block to the start
904                                    of the data */
905         loff_t blockstart;      /* running start of the current block -
906                                    MEMGETBADBLOCK needs 64 bits */
907         int rc;
908
909         blockstart = (offset / DEVESIZE(dev)) * DEVESIZE(dev);
910
911         /* Offset inside a block */
912         block_seek = offset - blockstart;
913
914         if (DEVTYPE(dev) == MTD_NANDFLASH) {
915                 /*
916                  * NAND: calculate which blocks we are reading. We have
917                  * to read one block at a time to skip bad blocks.
918                  */
919                 blocklen = DEVESIZE(dev);
920
921                 /* Limit to one block for the first read */
922                 if (readlen > blocklen - block_seek)
923                         readlen = blocklen - block_seek;
924         } else {
925                 blocklen = 0;
926         }
927
928         /* This only runs once on NOR flash */
929         while (processed < count) {
930                 rc = flash_bad_block(fd, DEVTYPE(dev), blockstart);
931                 if (rc < 0)     /* block test failed */
932                         return -1;
933
934                 if (blockstart + block_seek + readlen > environment_end(dev)) {
935                         /* End of range is reached */
936                         fprintf(stderr, "Too few good blocks within range\n");
937                         return -1;
938                 }
939
940                 if (rc) {       /* block is bad */
941                         blockstart += blocklen;
942                         continue;
943                 }
944
945                 /*
946                  * If a block is bad, we retry in the next block at the same
947                  * offset - see env/nand.c::writeenv()
948                  */
949                 lseek(fd, blockstart + block_seek, SEEK_SET);
950
951                 rc = read(fd, buf + processed, readlen);
952                 if (rc == -1) {
953                         fprintf(stderr, "Read error on %s: %s\n",
954                                 DEVNAME(dev), strerror(errno));
955                         return -1;
956                 }
957 #ifdef DEBUG
958                 fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n",
959                         rc, (unsigned long long)blockstart + block_seek,
960                         DEVNAME(dev));
961 #endif
962                 processed += rc;
963                 if (rc != readlen) {
964                         fprintf(stderr,
965                                 "Warning on %s: Attempted to read %zd bytes but got %d\n",
966                                 DEVNAME(dev), readlen, rc);
967                         readlen -= rc;
968                         block_seek += rc;
969                 } else {
970                         blockstart += blocklen;
971                         readlen = min(blocklen, count - processed);
972                         block_seek = 0;
973                 }
974         }
975
976         return processed;
977 }
978
979 /*
980  * Write count bytes from begin of environment, but stay within
981  * ENVSECTORS(dev) sectors of
982  * DEVOFFSET (dev). Similar to the read case above, on NOR and dataflash we
983  * erase and write the whole data at once.
984  */
985 static int flash_write_buf(int dev, int fd, void *buf, size_t count)
986 {
987         void *data;
988         struct erase_info_user erase;
989         size_t blocklen;        /* length of NAND block / NOR erase sector */
990         size_t erase_len;       /* whole area that can be erased - may include
991                                    bad blocks */
992         size_t erasesize;       /* erase / write length - one block on NAND,
993                                    whole area on NOR */
994         size_t processed = 0;   /* progress counter */
995         size_t write_total;     /* total size to actually write - excluding
996                                    bad blocks */
997         off_t erase_offset;     /* offset to the first erase block (aligned)
998                                    below offset */
999         off_t block_seek;       /* offset inside the erase block to the start
1000                                    of the data */
1001         loff_t blockstart;      /* running start of the current block -
1002                                    MEMGETBADBLOCK needs 64 bits */
1003         int was_locked = 0;     /* flash lock flag */
1004         int rc;
1005
1006         /*
1007          * For mtd devices only offset and size of the environment do matter
1008          */
1009         if (DEVTYPE(dev) == MTD_ABSENT) {
1010                 blocklen = count;
1011                 erase_len = blocklen;
1012                 blockstart = DEVOFFSET(dev);
1013                 block_seek = 0;
1014                 write_total = blocklen;
1015         } else {
1016                 blocklen = DEVESIZE(dev);
1017
1018                 erase_offset = DEVOFFSET(dev);
1019
1020                 /* Maximum area we may use */
1021                 erase_len = environment_end(dev) - erase_offset;
1022
1023                 blockstart = erase_offset;
1024
1025                 /* Offset inside a block */
1026                 block_seek = DEVOFFSET(dev) - erase_offset;
1027
1028                 /*
1029                  * Data size we actually write: from the start of the block
1030                  * to the start of the data, then count bytes of data, and
1031                  * to the end of the block
1032                  */
1033                 write_total = ((block_seek + count + blocklen - 1) /
1034                                blocklen) * blocklen;
1035         }
1036
1037         /*
1038          * Support data anywhere within erase sectors: read out the complete
1039          * area to be erased, replace the environment image, write the whole
1040          * block back again.
1041          */
1042         if (write_total > count) {
1043                 data = malloc(erase_len);
1044                 if (!data) {
1045                         fprintf(stderr,
1046                                 "Cannot malloc %zu bytes: %s\n",
1047                                 erase_len, strerror(errno));
1048                         return -1;
1049                 }
1050
1051                 rc = flash_read_buf(dev, fd, data, write_total, erase_offset);
1052                 if (write_total != rc)
1053                         return -1;
1054
1055 #ifdef DEBUG
1056                 fprintf(stderr, "Preserving data ");
1057                 if (block_seek != 0)
1058                         fprintf(stderr, "0x%x - 0x%lx", 0, block_seek - 1);
1059                 if (block_seek + count != write_total) {
1060                         if (block_seek != 0)
1061                                 fprintf(stderr, " and ");
1062                         fprintf(stderr, "0x%lx - 0x%lx",
1063                                 (unsigned long)block_seek + count,
1064                                 (unsigned long)write_total - 1);
1065                 }
1066                 fprintf(stderr, "\n");
1067 #endif
1068                 /* Overwrite the old environment */
1069                 memcpy(data + block_seek, buf, count);
1070         } else {
1071                 /*
1072                  * We get here, iff offset is block-aligned and count is a
1073                  * multiple of blocklen - see write_total calculation above
1074                  */
1075                 data = buf;
1076         }
1077
1078         if (DEVTYPE(dev) == MTD_NANDFLASH) {
1079                 /*
1080                  * NAND: calculate which blocks we are writing. We have
1081                  * to write one block at a time to skip bad blocks.
1082                  */
1083                 erasesize = blocklen;
1084         } else {
1085                 erasesize = erase_len;
1086         }
1087
1088         erase.length = erasesize;
1089
1090         /* This only runs once on NOR flash and SPI-dataflash */
1091         while (processed < write_total) {
1092                 rc = flash_bad_block(fd, DEVTYPE(dev), blockstart);
1093                 if (rc < 0)     /* block test failed */
1094                         return rc;
1095
1096                 if (blockstart + erasesize > environment_end(dev)) {
1097                         fprintf(stderr, "End of range reached, aborting\n");
1098                         return -1;
1099                 }
1100
1101                 if (rc) {       /* block is bad */
1102                         blockstart += blocklen;
1103                         continue;
1104                 }
1105
1106                 if (DEVTYPE(dev) != MTD_ABSENT) {
1107                         erase.start = blockstart;
1108                         was_locked = ioctl(fd, MEMISLOCKED, &erase);
1109                         /* treat any errors as unlocked flash */
1110                         if (was_locked < 0)
1111                                         was_locked = 0;
1112                         if (was_locked)
1113                                 ioctl(fd, MEMUNLOCK, &erase);
1114                         /* These do not need an explicit erase cycle */
1115                         if (DEVTYPE(dev) != MTD_DATAFLASH)
1116                                 if (ioctl(fd, MEMERASE, &erase) != 0) {
1117                                         fprintf(stderr,
1118                                                 "MTD erase error on %s: %s\n",
1119                                                 DEVNAME(dev), strerror(errno));
1120                                         return -1;
1121                                 }
1122                 }
1123
1124                 if (lseek(fd, blockstart, SEEK_SET) == -1) {
1125                         fprintf(stderr,
1126                                 "Seek error on %s: %s\n",
1127                                 DEVNAME(dev), strerror(errno));
1128                         return -1;
1129                 }
1130 #ifdef DEBUG
1131                 fprintf(stderr, "Write 0x%llx bytes at 0x%llx\n",
1132                         (unsigned long long)erasesize,
1133                         (unsigned long long)blockstart);
1134 #endif
1135                 if (write(fd, data + processed, erasesize) != erasesize) {
1136                         fprintf(stderr, "Write error on %s: %s\n",
1137                                 DEVNAME(dev), strerror(errno));
1138                         return -1;
1139                 }
1140
1141                 if (DEVTYPE(dev) != MTD_ABSENT) {
1142                         if (was_locked)
1143                                 ioctl(fd, MEMLOCK, &erase);
1144                 }
1145
1146                 processed += erasesize;
1147                 block_seek = 0;
1148                 blockstart += erasesize;
1149         }
1150
1151         if (write_total > count)
1152                 free(data);
1153
1154         return processed;
1155 }
1156
1157 /*
1158  * Set obsolete flag at offset - NOR flash only
1159  */
1160 static int flash_flag_obsolete(int dev, int fd, off_t offset)
1161 {
1162         int rc;
1163         struct erase_info_user erase;
1164         char tmp = ENV_REDUND_OBSOLETE;
1165         int was_locked; /* flash lock flag */
1166
1167         erase.start = DEVOFFSET(dev);
1168         erase.length = DEVESIZE(dev);
1169         /* This relies on the fact, that ENV_REDUND_OBSOLETE == 0 */
1170         rc = lseek(fd, offset, SEEK_SET);
1171         if (rc < 0) {
1172                 fprintf(stderr, "Cannot seek to set the flag on %s\n",
1173                         DEVNAME(dev));
1174                 return rc;
1175         }
1176         was_locked = ioctl(fd, MEMISLOCKED, &erase);
1177         /* treat any errors as unlocked flash */
1178         if (was_locked < 0)
1179                 was_locked = 0;
1180         if (was_locked)
1181                 ioctl(fd, MEMUNLOCK, &erase);
1182         rc = write(fd, &tmp, sizeof(tmp));
1183         if (was_locked)
1184                 ioctl(fd, MEMLOCK, &erase);
1185         if (rc < 0)
1186                 perror("Could not set obsolete flag");
1187
1188         return rc;
1189 }
1190
1191 static int flash_write(int fd_current, int fd_target, int dev_target, void *buf,
1192                        size_t count)
1193 {
1194         int rc;
1195
1196         switch (environment.flag_scheme) {
1197         case FLAG_NONE:
1198                 break;
1199         case FLAG_INCREMENTAL:
1200                 (*environment.flags)++;
1201                 break;
1202         case FLAG_BOOLEAN:
1203                 *environment.flags = ENV_REDUND_ACTIVE;
1204                 break;
1205         default:
1206                 fprintf(stderr, "Unimplemented flash scheme %u\n",
1207                         environment.flag_scheme);
1208                 return -1;
1209         }
1210
1211 #ifdef DEBUG
1212         fprintf(stderr, "Writing new environment at 0x%llx on %s\n",
1213                 DEVOFFSET(dev_target), DEVNAME(dev_target));
1214 #endif
1215
1216         if (IS_UBI(dev_target)) {
1217                 if (ubi_update_start(fd_target, CUR_ENVSIZE) < 0)
1218                         return -1;
1219                 return ubi_write(fd_target, buf, count);
1220         }
1221
1222         rc = flash_write_buf(dev_target, fd_target, buf, count);
1223         if (rc < 0)
1224                 return rc;
1225
1226         if (environment.flag_scheme == FLAG_BOOLEAN) {
1227                 /* Have to set obsolete flag */
1228                 off_t offset = DEVOFFSET(dev_current) +
1229                     offsetof(struct env_image_redundant, flags);
1230 #ifdef DEBUG
1231                 fprintf(stderr,
1232                         "Setting obsolete flag in environment at 0x%llx on %s\n",
1233                         DEVOFFSET(dev_current), DEVNAME(dev_current));
1234 #endif
1235                 flash_flag_obsolete(dev_current, fd_current, offset);
1236         }
1237
1238         return 0;
1239 }
1240
1241 static int flash_read(int fd, void *buf, size_t count)
1242 {
1243         int rc;
1244
1245         if (IS_UBI(dev_current)) {
1246                 DEVTYPE(dev_current) = MTD_ABSENT;
1247
1248                 return ubi_read(fd, buf, count);
1249         }
1250
1251         rc = flash_read_buf(dev_current, fd, buf, count,
1252                             DEVOFFSET(dev_current));
1253         if (rc != CUR_ENVSIZE)
1254                 return -1;
1255
1256         return 0;
1257 }
1258
1259 static int flash_open_tempfile(const char **dname, const char **target_temp)
1260 {
1261         char *dup_name = strdup(DEVNAME(dev_current));
1262         char *temp_name = NULL;
1263         int rc = -1;
1264
1265         if (!dup_name)
1266                 return -1;
1267
1268         *dname = dirname(dup_name);
1269         if (!*dname)
1270                 goto err;
1271
1272         rc = asprintf(&temp_name, "%s/XXXXXX", *dname);
1273         if (rc == -1)
1274                 goto err;
1275
1276         rc = mkstemp(temp_name);
1277         if (rc == -1) {
1278                 /* fall back to in place write */
1279                 fprintf(stderr,
1280                         "Can't create %s: %s\n", temp_name, strerror(errno));
1281                 free(temp_name);
1282         } else {
1283                 *target_temp = temp_name;
1284                 /* deliberately leak dup_name as dname /might/ point into
1285                  * it and we need it for our caller
1286                  */
1287                 dup_name = NULL;
1288         }
1289
1290 err:
1291         if (dup_name)
1292                 free(dup_name);
1293
1294         return rc;
1295 }
1296
1297 static int flash_io_write(int fd_current, void *buf, size_t count)
1298 {
1299         int fd_target = -1, rc, dev_target;
1300         const char *dname, *target_temp = NULL;
1301
1302         if (have_redund_env) {
1303                 /* switch to next partition for writing */
1304                 dev_target = !dev_current;
1305                 /* dev_target: fd_target, erase_target */
1306                 fd_target = open(DEVNAME(dev_target), O_RDWR);
1307                 if (fd_target < 0) {
1308                         fprintf(stderr,
1309                                 "Can't open %s: %s\n",
1310                                 DEVNAME(dev_target), strerror(errno));
1311                         rc = -1;
1312                         goto exit;
1313                 }
1314         } else {
1315                 struct stat sb;
1316
1317                 if (fstat(fd_current, &sb) == 0 && S_ISREG(sb.st_mode)) {
1318                         /* if any part of flash_open_tempfile() fails we fall
1319                          * back to in-place writes
1320                          */
1321                         fd_target = flash_open_tempfile(&dname, &target_temp);
1322                 }
1323                 dev_target = dev_current;
1324                 if (fd_target == -1)
1325                         fd_target = fd_current;
1326         }
1327
1328         rc = flash_write(fd_current, fd_target, dev_target, buf, count);
1329
1330         if (fsync(fd_current) && !(errno == EINVAL || errno == EROFS)) {
1331                 fprintf(stderr,
1332                         "fsync failed on %s: %s\n",
1333                         DEVNAME(dev_current), strerror(errno));
1334         }
1335
1336         if (fd_current != fd_target) {
1337                 if (fsync(fd_target) &&
1338                     !(errno == EINVAL || errno == EROFS)) {
1339                         fprintf(stderr,
1340                                 "fsync failed on %s: %s\n",
1341                                 DEVNAME(dev_current), strerror(errno));
1342                 }
1343
1344                 if (close(fd_target)) {
1345                         fprintf(stderr,
1346                                 "I/O error on %s: %s\n",
1347                                 DEVNAME(dev_target), strerror(errno));
1348                         rc = -1;
1349                 }
1350
1351                 if (rc >= 0 && target_temp) {
1352                         int dir_fd;
1353
1354                         dir_fd = open(dname, O_DIRECTORY | O_RDONLY);
1355                         if (dir_fd == -1)
1356                                 fprintf(stderr,
1357                                         "Can't open %s: %s\n",
1358                                         dname, strerror(errno));
1359
1360                         if (rename(target_temp, DEVNAME(dev_target))) {
1361                                 fprintf(stderr,
1362                                         "rename failed %s => %s: %s\n",
1363                                         target_temp, DEVNAME(dev_target),
1364                                         strerror(errno));
1365                                 rc = -1;
1366                         }
1367
1368                         if (dir_fd != -1 && fsync(dir_fd))
1369                                 fprintf(stderr,
1370                                         "fsync failed on %s: %s\n",
1371                                         dname, strerror(errno));
1372
1373                         if (dir_fd != -1 && close(dir_fd))
1374                                 fprintf(stderr,
1375                                         "I/O error on %s: %s\n",
1376                                         dname, strerror(errno));
1377                 }
1378         }
1379  exit:
1380         return rc;
1381 }
1382
1383 static int flash_io(int mode, void *buf, size_t count)
1384 {
1385         int fd_current, rc;
1386
1387         /* dev_current: fd_current, erase_current */
1388         fd_current = open(DEVNAME(dev_current), mode);
1389         if (fd_current < 0) {
1390                 fprintf(stderr,
1391                         "Can't open %s: %s\n",
1392                         DEVNAME(dev_current), strerror(errno));
1393                 return -1;
1394         }
1395
1396         if (mode == O_RDWR) {
1397                 rc = flash_io_write(fd_current, buf, count);
1398         } else {
1399                 rc = flash_read(fd_current, buf, count);
1400         }
1401
1402         if (close(fd_current)) {
1403                 fprintf(stderr,
1404                         "I/O error on %s: %s\n",
1405                         DEVNAME(dev_current), strerror(errno));
1406                 return -1;
1407         }
1408
1409         return rc;
1410 }
1411
1412 /*
1413  * Prevent confusion if running from erased flash memory
1414  */
1415 int fw_env_open(struct env_opts *opts)
1416 {
1417         int crc0, crc0_ok;
1418         unsigned char flag0;
1419         void *addr0 = NULL;
1420
1421         int crc1, crc1_ok;
1422         unsigned char flag1;
1423         void *addr1 = NULL;
1424
1425         int ret;
1426
1427         if (!opts)
1428                 opts = &default_opts;
1429
1430         if (parse_config(opts)) /* should fill envdevices */
1431                 return -EINVAL;
1432
1433         addr0 = calloc(1, CUR_ENVSIZE);
1434         if (addr0 == NULL) {
1435                 fprintf(stderr,
1436                         "Not enough memory for environment (%ld bytes)\n",
1437                         CUR_ENVSIZE);
1438                 ret = -ENOMEM;
1439                 goto open_cleanup;
1440         }
1441
1442         dev_current = 0;
1443         if (flash_io(O_RDONLY, addr0, CUR_ENVSIZE)) {
1444                 ret = -EIO;
1445                 goto open_cleanup;
1446         }
1447
1448         if (!have_redund_env) {
1449                 struct env_image_single *single = addr0;
1450
1451                 crc0 = crc32(0, (uint8_t *)single->data, ENV_SIZE);
1452                 crc0_ok = (crc0 == single->crc);
1453                 if (!crc0_ok) {
1454                         fprintf(stderr,
1455                                 "Warning: Bad CRC, using default environment\n");
1456                         memcpy(single->data, default_environment,
1457                                sizeof(default_environment));
1458                         environment.dirty = 1;
1459                 }
1460
1461                 environment.image = addr0;
1462                 environment.crc = &single->crc;
1463                 environment.flags = NULL;
1464                 environment.data = single->data;
1465         } else {
1466                 struct env_image_redundant *redundant0 = addr0;
1467                 struct env_image_redundant *redundant1;
1468
1469                 crc0 = crc32(0, (uint8_t *)redundant0->data, ENV_SIZE);
1470                 crc0_ok = (crc0 == redundant0->crc);
1471
1472                 flag0 = redundant0->flags;
1473
1474                 dev_current = 1;
1475                 addr1 = calloc(1, CUR_ENVSIZE);
1476                 if (addr1 == NULL) {
1477                         fprintf(stderr,
1478                                 "Not enough memory for environment (%ld bytes)\n",
1479                                 CUR_ENVSIZE);
1480                         ret = -ENOMEM;
1481                         goto open_cleanup;
1482                 }
1483                 redundant1 = addr1;
1484
1485                 if (flash_io(O_RDONLY, addr1, CUR_ENVSIZE)) {
1486                         ret = -EIO;
1487                         goto open_cleanup;
1488                 }
1489
1490                 /* Check flag scheme compatibility */
1491                 if (DEVTYPE(dev_current) == MTD_NORFLASH &&
1492                     DEVTYPE(!dev_current) == MTD_NORFLASH) {
1493                         environment.flag_scheme = FLAG_BOOLEAN;
1494                 } else if (DEVTYPE(dev_current) == MTD_NANDFLASH &&
1495                            DEVTYPE(!dev_current) == MTD_NANDFLASH) {
1496                         environment.flag_scheme = FLAG_INCREMENTAL;
1497                 } else if (DEVTYPE(dev_current) == MTD_DATAFLASH &&
1498                            DEVTYPE(!dev_current) == MTD_DATAFLASH) {
1499                         environment.flag_scheme = FLAG_BOOLEAN;
1500                 } else if (DEVTYPE(dev_current) == MTD_UBIVOLUME &&
1501                            DEVTYPE(!dev_current) == MTD_UBIVOLUME) {
1502                         environment.flag_scheme = FLAG_INCREMENTAL;
1503                 } else if (DEVTYPE(dev_current) == MTD_ABSENT &&
1504                            DEVTYPE(!dev_current) == MTD_ABSENT &&
1505                            IS_UBI(dev_current) == IS_UBI(!dev_current)) {
1506                         environment.flag_scheme = FLAG_INCREMENTAL;
1507                 } else {
1508                         fprintf(stderr, "Incompatible flash types!\n");
1509                         ret = -EINVAL;
1510                         goto open_cleanup;
1511                 }
1512
1513                 crc1 = crc32(0, (uint8_t *)redundant1->data, ENV_SIZE);
1514
1515                 crc1_ok = (crc1 == redundant1->crc);
1516                 flag1 = redundant1->flags;
1517
1518                 if (memcmp(redundant0->data, redundant1->data, ENV_SIZE) ||
1519                     !crc0_ok || !crc1_ok)
1520                         environment.dirty = 1;
1521
1522                 if (crc0_ok && !crc1_ok) {
1523                         dev_current = 0;
1524                 } else if (!crc0_ok && crc1_ok) {
1525                         dev_current = 1;
1526                 } else if (!crc0_ok && !crc1_ok) {
1527                         fprintf(stderr,
1528                                 "Warning: Bad CRC, using default environment\n");
1529                         memcpy(redundant0->data, default_environment,
1530                                sizeof(default_environment));
1531                         environment.dirty = 1;
1532                         dev_current = 0;
1533                 } else {
1534                         switch (environment.flag_scheme) {
1535                         case FLAG_BOOLEAN:
1536                                 if (flag0 == ENV_REDUND_ACTIVE &&
1537                                     flag1 == ENV_REDUND_OBSOLETE) {
1538                                         dev_current = 0;
1539                                 } else if (flag0 == ENV_REDUND_OBSOLETE &&
1540                                            flag1 == ENV_REDUND_ACTIVE) {
1541                                         dev_current = 1;
1542                                 } else if (flag0 == flag1) {
1543                                         dev_current = 0;
1544                                 } else if (flag0 == 0xFF) {
1545                                         dev_current = 0;
1546                                 } else if (flag1 == 0xFF) {
1547                                         dev_current = 1;
1548                                 } else {
1549                                         dev_current = 0;
1550                                 }
1551                                 break;
1552                         case FLAG_INCREMENTAL:
1553                                 if (flag0 == 255 && flag1 == 0)
1554                                         dev_current = 1;
1555                                 else if ((flag1 == 255 && flag0 == 0) ||
1556                                          flag0 >= flag1)
1557                                         dev_current = 0;
1558                                 else    /* flag1 > flag0 */
1559                                         dev_current = 1;
1560                                 break;
1561                         default:
1562                                 fprintf(stderr, "Unknown flag scheme %u\n",
1563                                         environment.flag_scheme);
1564                                 return -1;
1565                         }
1566                 }
1567
1568                 /*
1569                  * If we are reading, we don't need the flag and the CRC any
1570                  * more, if we are writing, we will re-calculate CRC and update
1571                  * flags before writing out
1572                  */
1573                 if (dev_current) {
1574                         environment.image = addr1;
1575                         environment.crc = &redundant1->crc;
1576                         environment.flags = &redundant1->flags;
1577                         environment.data = redundant1->data;
1578                         free(addr0);
1579                 } else {
1580                         environment.image = addr0;
1581                         environment.crc = &redundant0->crc;
1582                         environment.flags = &redundant0->flags;
1583                         environment.data = redundant0->data;
1584                         free(addr1);
1585                 }
1586 #ifdef DEBUG
1587                 fprintf(stderr, "Selected env in %s\n", DEVNAME(dev_current));
1588 #endif
1589         }
1590         return 0;
1591
1592  open_cleanup:
1593         if (addr0)
1594                 free(addr0);
1595
1596         if (addr1)
1597                 free(addr1);
1598
1599         return ret;
1600 }
1601
1602 /*
1603  * Simply free allocated buffer with environment
1604  */
1605 int fw_env_close(struct env_opts *opts)
1606 {
1607         if (environment.image)
1608                 free(environment.image);
1609
1610         environment.image = NULL;
1611
1612         return 0;
1613 }
1614
1615 static int check_device_config(int dev)
1616 {
1617         struct stat st;
1618         int32_t lnum = 0;
1619         int fd, rc = 0;
1620
1621         /* Fills in IS_UBI(), converts DEVNAME() with ubi volume name */
1622         ubi_check_dev(dev);
1623
1624         fd = open(DEVNAME(dev), O_RDONLY);
1625         if (fd < 0) {
1626                 fprintf(stderr,
1627                         "Cannot open %s: %s\n", DEVNAME(dev), strerror(errno));
1628                 return -1;
1629         }
1630
1631         rc = fstat(fd, &st);
1632         if (rc < 0) {
1633                 fprintf(stderr, "Cannot stat the file %s\n", DEVNAME(dev));
1634                 goto err;
1635         }
1636
1637         if (IS_UBI(dev)) {
1638                 rc = ioctl(fd, UBI_IOCEBISMAP, &lnum);
1639                 if (rc < 0) {
1640                         fprintf(stderr, "Cannot get UBI information for %s\n",
1641                                 DEVNAME(dev));
1642                         goto err;
1643                 }
1644         } else if (S_ISCHR(st.st_mode)) {
1645                 struct mtd_info_user mtdinfo;
1646                 rc = ioctl(fd, MEMGETINFO, &mtdinfo);
1647                 if (rc < 0) {
1648                         fprintf(stderr, "Cannot get MTD information for %s\n",
1649                                 DEVNAME(dev));
1650                         goto err;
1651                 }
1652                 if (mtdinfo.type != MTD_NORFLASH &&
1653                     mtdinfo.type != MTD_NANDFLASH &&
1654                     mtdinfo.type != MTD_DATAFLASH &&
1655                     mtdinfo.type != MTD_UBIVOLUME) {
1656                         fprintf(stderr, "Unsupported flash type %u on %s\n",
1657                                 mtdinfo.type, DEVNAME(dev));
1658                         goto err;
1659                 }
1660                 DEVTYPE(dev) = mtdinfo.type;
1661                 if (DEVESIZE(dev) == 0 && ENVSECTORS(dev) == 0 &&
1662                     mtdinfo.type == MTD_NORFLASH)
1663                         DEVESIZE(dev) = mtdinfo.erasesize;
1664                 if (DEVESIZE(dev) == 0)
1665                         /* Assume the erase size is the same as the env-size */
1666                         DEVESIZE(dev) = ENVSIZE(dev);
1667         } else {
1668                 uint64_t size;
1669                 DEVTYPE(dev) = MTD_ABSENT;
1670                 if (DEVESIZE(dev) == 0)
1671                         /* Assume the erase size to be 512 bytes */
1672                         DEVESIZE(dev) = 0x200;
1673
1674                 /*
1675                  * Check for negative offsets, treat it as backwards offset
1676                  * from the end of the block device
1677                  */
1678                 if (DEVOFFSET(dev) < 0) {
1679                         rc = ioctl(fd, BLKGETSIZE64, &size);
1680                         if (rc < 0) {
1681                                 fprintf(stderr,
1682                                         "Could not get block device size on %s\n",
1683                                         DEVNAME(dev));
1684                                 goto err;
1685                         }
1686
1687                         DEVOFFSET(dev) = DEVOFFSET(dev) + size;
1688 #ifdef DEBUG
1689                         fprintf(stderr,
1690                                 "Calculated device offset 0x%llx on %s\n",
1691                                 DEVOFFSET(dev), DEVNAME(dev));
1692 #endif
1693                 }
1694         }
1695
1696         if (ENVSECTORS(dev) == 0)
1697                 /* Assume enough sectors to cover the environment */
1698                 ENVSECTORS(dev) = DIV_ROUND_UP(ENVSIZE(dev), DEVESIZE(dev));
1699
1700         if (DEVOFFSET(dev) % DEVESIZE(dev) != 0) {
1701                 fprintf(stderr,
1702                         "Environment does not start on (erase) block boundary\n");
1703                 errno = EINVAL;
1704                 return -1;
1705         }
1706
1707         if (ENVSIZE(dev) > ENVSECTORS(dev) * DEVESIZE(dev)) {
1708                 fprintf(stderr,
1709                         "Environment does not fit into available sectors\n");
1710                 errno = EINVAL;
1711                 return -1;
1712         }
1713
1714  err:
1715         close(fd);
1716         return rc;
1717 }
1718
1719 static int find_nvmem_device(void)
1720 {
1721         const char *path = "/sys/bus/nvmem/devices";
1722         struct dirent *dent;
1723         char *nvmem = NULL;
1724         char comp[256];
1725         char buf[32];
1726         int bytes;
1727         DIR *dir;
1728
1729         dir = opendir(path);
1730         if (!dir) {
1731                 return -EIO;
1732         }
1733
1734         while (!nvmem && (dent = readdir(dir))) {
1735                 FILE *fp;
1736                 size_t size;
1737
1738                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
1739                         continue;
1740                 }
1741
1742                 bytes = snprintf(comp, sizeof(comp), "%s/%s/of_node/compatible", path, dent->d_name);
1743                 if (bytes < 0 || bytes == sizeof(comp)) {
1744                         continue;
1745                 }
1746
1747                 fp = fopen(comp, "r");
1748                 if (!fp) {
1749                         continue;
1750                 }
1751
1752                 size = fread(buf, sizeof(buf), 1, fp);
1753                 if (size != 1) {
1754                         fprintf(stderr,
1755                                 "read failed about %s\n", comp);
1756                         fclose(fp);
1757                         return -EIO;
1758                 }
1759
1760
1761                 if (!strcmp(buf, "u-boot,env")) {
1762                         bytes = asprintf(&nvmem, "%s/%s/nvmem", path, dent->d_name);
1763                         if (bytes < 0) {
1764                                 nvmem = NULL;
1765                         }
1766                 }
1767
1768                 fclose(fp);
1769         }
1770
1771         closedir(dir);
1772
1773         if (nvmem) {
1774                 struct stat s;
1775
1776                 stat(nvmem, &s);
1777
1778                 DEVNAME(0) = nvmem;
1779                 DEVOFFSET(0) = 0;
1780                 ENVSIZE(0) = s.st_size;
1781
1782                 return 0;
1783         }
1784
1785         return -ENOENT;
1786 }
1787
1788 static int parse_config(struct env_opts *opts)
1789 {
1790         int rc;
1791
1792         if (!opts)
1793                 opts = &default_opts;
1794
1795 #if defined(CONFIG_FILE)
1796         /* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */
1797         if (get_config(opts->config_file)) {
1798                 if (find_nvmem_device()) {
1799                         fprintf(stderr, "Cannot parse config file '%s': %m\n",
1800                                 opts->config_file);
1801                         fprintf(stderr, "Failed to find NVMEM device\n");
1802                         return -1;
1803                 }
1804         }
1805 #else
1806         DEVNAME(0) = DEVICE1_NAME;
1807         DEVOFFSET(0) = DEVICE1_OFFSET;
1808         ENVSIZE(0) = ENV1_SIZE;
1809
1810         /* Set defaults for DEVESIZE, ENVSECTORS later once we
1811          * know DEVTYPE
1812          */
1813 #ifdef DEVICE1_ESIZE
1814         DEVESIZE(0) = DEVICE1_ESIZE;
1815 #endif
1816 #ifdef DEVICE1_ENVSECTORS
1817         ENVSECTORS(0) = DEVICE1_ENVSECTORS;
1818 #endif
1819
1820 #ifdef HAVE_REDUND
1821         DEVNAME(1) = DEVICE2_NAME;
1822         DEVOFFSET(1) = DEVICE2_OFFSET;
1823         ENVSIZE(1) = ENV2_SIZE;
1824
1825         /* Set defaults for DEVESIZE, ENVSECTORS later once we
1826          * know DEVTYPE
1827          */
1828 #ifdef DEVICE2_ESIZE
1829         DEVESIZE(1) = DEVICE2_ESIZE;
1830 #endif
1831 #ifdef DEVICE2_ENVSECTORS
1832         ENVSECTORS(1) = DEVICE2_ENVSECTORS;
1833 #endif
1834         have_redund_env = 1;
1835 #endif
1836 #endif
1837         rc = check_device_config(0);
1838         if (rc < 0)
1839                 return rc;
1840
1841         if (have_redund_env) {
1842                 rc = check_device_config(1);
1843                 if (rc < 0)
1844                         return rc;
1845
1846                 if (ENVSIZE(0) != ENVSIZE(1)) {
1847                         fprintf(stderr,
1848                                 "Redundant environments have unequal size\n");
1849                         return -1;
1850                 }
1851         }
1852
1853         usable_envsize = CUR_ENVSIZE - sizeof(uint32_t);
1854         if (have_redund_env)
1855                 usable_envsize -= sizeof(char);
1856
1857         return 0;
1858 }
1859
1860 #if defined(CONFIG_FILE)
1861 static int get_config(char *fname)
1862 {
1863         FILE *fp;
1864         int i = 0;
1865         int rc;
1866         char *line = NULL;
1867         size_t linesize = 0;
1868         char *devname;
1869
1870         fp = fopen(fname, "r");
1871         if (fp == NULL)
1872                 return -1;
1873
1874         while (i < 2 && getline(&line, &linesize, fp) != -1) {
1875                 /* Skip comment strings */
1876                 if (line[0] == '#')
1877                         continue;
1878
1879                 rc = sscanf(line, "%ms %lli %lx %lx %lx",
1880                             &devname,
1881                             &DEVOFFSET(i),
1882                             &ENVSIZE(i), &DEVESIZE(i), &ENVSECTORS(i));
1883
1884                 if (rc < 3)
1885                         continue;
1886
1887                 DEVNAME(i) = devname;
1888
1889                 /* Set defaults for DEVESIZE, ENVSECTORS later once we
1890                  * know DEVTYPE
1891                  */
1892
1893                 i++;
1894         }
1895         free(line);
1896         fclose(fp);
1897
1898         have_redund_env = i - 1;
1899         if (!i) {               /* No valid entries found */
1900                 errno = EINVAL;
1901                 return -1;
1902         } else
1903                 return 0;
1904 }
1905 #endif