patman: make run results better visible
[platform/kernel/u-boot.git] / common / env_ubi.c
1 /*
2  * (c) Copyright 2012 by National Instruments,
3  *        Joe Hershberger <joe.hershberger@ni.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 #include <command.h>
11 #include <environment.h>
12 #include <errno.h>
13 #include <malloc.h>
14 #include <search.h>
15 #include <ubi_uboot.h>
16 #undef crc32
17
18 char *env_name_spec = "UBI";
19
20 env_t *env_ptr;
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 int env_init(void)
25 {
26         /* use default */
27         gd->env_addr = (ulong)&default_environment[0];
28         gd->env_valid = 1;
29
30         return 0;
31 }
32
33 #ifdef CONFIG_CMD_SAVEENV
34 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
35 static unsigned char env_flags;
36
37 int saveenv(void)
38 {
39         ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
40         int ret;
41
42         ret = env_export(env_new);
43         if (ret)
44                 return ret;
45
46         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
47                 printf("\n** Cannot find mtd partition \"%s\"\n",
48                        CONFIG_ENV_UBI_PART);
49                 return 1;
50         }
51
52         env_new->flags = ++env_flags; /* increase the serial */
53
54         if (gd->env_valid == 1) {
55                 puts("Writing to redundant UBI... ");
56                 if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND,
57                                      (void *)env_new, CONFIG_ENV_SIZE)) {
58                         printf("\n** Unable to write env to %s:%s **\n",
59                                CONFIG_ENV_UBI_PART,
60                                CONFIG_ENV_UBI_VOLUME_REDUND);
61                         return 1;
62                 }
63         } else {
64                 puts("Writing to UBI... ");
65                 if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME,
66                                      (void *)env_new, CONFIG_ENV_SIZE)) {
67                         printf("\n** Unable to write env to %s:%s **\n",
68                                CONFIG_ENV_UBI_PART,
69                                CONFIG_ENV_UBI_VOLUME);
70                         return 1;
71                 }
72         }
73
74         puts("done\n");
75
76         gd->env_valid = gd->env_valid == 2 ? 1 : 2;
77
78         return 0;
79 }
80 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
81 int saveenv(void)
82 {
83         ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
84         int ret;
85
86         ret = env_export(env_new);
87         if (ret)
88                 return ret;
89
90         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
91                 printf("\n** Cannot find mtd partition \"%s\"\n",
92                        CONFIG_ENV_UBI_PART);
93                 return 1;
94         }
95
96         if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
97                              CONFIG_ENV_SIZE)) {
98                 printf("\n** Unable to write env to %s:%s **\n",
99                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
100                 return 1;
101         }
102
103         puts("done\n");
104         return 0;
105 }
106 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
107 #endif /* CONFIG_CMD_SAVEENV */
108
109 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
110 void env_relocate_spec(void)
111 {
112         ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE);
113         ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE);
114         int crc1_ok = 0, crc2_ok = 0;
115         env_t *ep, *tmp_env1, *tmp_env2;
116
117         tmp_env1 = (env_t *)env1_buf;
118         tmp_env2 = (env_t *)env2_buf;
119
120         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
121                 printf("\n** Cannot find mtd partition \"%s\"\n",
122                        CONFIG_ENV_UBI_PART);
123                 set_default_env(NULL);
124                 return;
125         }
126
127         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1,
128                             CONFIG_ENV_SIZE)) {
129                 printf("\n** Unable to read env from %s:%s **\n",
130                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
131         }
132
133         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)tmp_env2,
134                             CONFIG_ENV_SIZE)) {
135                 printf("\n** Unable to read redundant env from %s:%s **\n",
136                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND);
137         }
138
139         crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc;
140         crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc;
141
142         if (!crc1_ok && !crc2_ok) {
143                 set_default_env("!bad CRC");
144                 return;
145         } else if (crc1_ok && !crc2_ok) {
146                 gd->env_valid = 1;
147         } else if (!crc1_ok && crc2_ok) {
148                 gd->env_valid = 2;
149         } else {
150                 /* both ok - check serial */
151                 if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
152                         gd->env_valid = 2;
153                 else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
154                         gd->env_valid = 1;
155                 else if (tmp_env1->flags > tmp_env2->flags)
156                         gd->env_valid = 1;
157                 else if (tmp_env2->flags > tmp_env1->flags)
158                         gd->env_valid = 2;
159                 else /* flags are equal - almost impossible */
160                         gd->env_valid = 1;
161         }
162
163         if (gd->env_valid == 1)
164                 ep = tmp_env1;
165         else
166                 ep = tmp_env2;
167
168         env_flags = ep->flags;
169         env_import((char *)ep, 0);
170 }
171 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
172 void env_relocate_spec(void)
173 {
174         ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
175
176         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
177                 printf("\n** Cannot find mtd partition \"%s\"\n",
178                        CONFIG_ENV_UBI_PART);
179                 set_default_env(NULL);
180                 return;
181         }
182
183         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)&buf,
184                             CONFIG_ENV_SIZE)) {
185                 printf("\n** Unable to read env from %s:%s **\n",
186                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
187                 set_default_env(NULL);
188                 return;
189         }
190
191         env_import(buf, 1);
192 }
193 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */