usb, musb-new: add wdt trigger
[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  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25
26 #include <command.h>
27 #include <environment.h>
28 #include <errno.h>
29 #include <malloc.h>
30 #include <search.h>
31 #include <ubi_uboot.h>
32 #undef crc32
33
34 char *env_name_spec = "UBI";
35
36 env_t *env_ptr;
37
38 DECLARE_GLOBAL_DATA_PTR;
39
40 int env_init(void)
41 {
42         /* use default */
43         gd->env_addr = (ulong)&default_environment[0];
44         gd->env_valid = 1;
45
46         return 0;
47 }
48
49 #ifdef CONFIG_CMD_SAVEENV
50 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
51 static unsigned char env_flags;
52
53 int saveenv(void)
54 {
55         ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
56         ssize_t len;
57         char *res;
58
59         res = (char *)&env_new->data;
60         len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
61         if (len < 0) {
62                 error("Cannot export environment: errno = %d\n", errno);
63                 return 1;
64         }
65
66         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
67                 printf("\n** Cannot find mtd partition \"%s\"\n",
68                        CONFIG_ENV_UBI_PART);
69                 return 1;
70         }
71
72         env_new->crc = crc32(0, env_new->data, ENV_SIZE);
73         env_new->flags = ++env_flags; /* increase the serial */
74
75         if (gd->env_valid == 1) {
76                 puts("Writing to redundant UBI... ");
77                 if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND,
78                                      (void *)env_new, CONFIG_ENV_SIZE)) {
79                         printf("\n** Unable to write env to %s:%s **\n",
80                                CONFIG_ENV_UBI_PART,
81                                CONFIG_ENV_UBI_VOLUME_REDUND);
82                         return 1;
83                 }
84         } else {
85                 puts("Writing to UBI... ");
86                 if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME,
87                                      (void *)env_new, CONFIG_ENV_SIZE)) {
88                         printf("\n** Unable to write env to %s:%s **\n",
89                                CONFIG_ENV_UBI_PART,
90                                CONFIG_ENV_UBI_VOLUME);
91                         return 1;
92                 }
93         }
94
95         puts("done\n");
96
97         gd->env_valid = gd->env_valid == 2 ? 1 : 2;
98
99         return 0;
100 }
101 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
102 int saveenv(void)
103 {
104         ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
105         ssize_t len;
106         char *res;
107
108         res = (char *)&env_new->data;
109         len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
110         if (len < 0) {
111                 error("Cannot export environment: errno = %d\n", errno);
112                 return 1;
113         }
114
115         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
116                 printf("\n** Cannot find mtd partition \"%s\"\n",
117                        CONFIG_ENV_UBI_PART);
118                 return 1;
119         }
120
121         env_new->crc = crc32(0, env_new->data, ENV_SIZE);
122
123         if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
124                              CONFIG_ENV_SIZE)) {
125                 printf("\n** Unable to write env to %s:%s **\n",
126                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
127                 return 1;
128         }
129
130         puts("done\n");
131         return 0;
132 }
133 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
134 #endif /* CONFIG_CMD_SAVEENV */
135
136 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
137 void env_relocate_spec(void)
138 {
139         ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE);
140         ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE);
141         int crc1_ok = 0, crc2_ok = 0;
142         env_t *ep, *tmp_env1, *tmp_env2;
143
144         tmp_env1 = (env_t *)env1_buf;
145         tmp_env2 = (env_t *)env2_buf;
146
147         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
148                 printf("\n** Cannot find mtd partition \"%s\"\n",
149                        CONFIG_ENV_UBI_PART);
150                 set_default_env(NULL);
151                 return;
152         }
153
154         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1,
155                             CONFIG_ENV_SIZE)) {
156                 printf("\n** Unable to read env from %s:%s **\n",
157                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
158         }
159
160         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)tmp_env2,
161                             CONFIG_ENV_SIZE)) {
162                 printf("\n** Unable to read redundant env from %s:%s **\n",
163                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND);
164         }
165
166         crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc;
167         crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc;
168
169         if (!crc1_ok && !crc2_ok) {
170                 set_default_env("!bad CRC");
171                 return;
172         } else if (crc1_ok && !crc2_ok) {
173                 gd->env_valid = 1;
174         } else if (!crc1_ok && crc2_ok) {
175                 gd->env_valid = 2;
176         } else {
177                 /* both ok - check serial */
178                 if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
179                         gd->env_valid = 2;
180                 else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
181                         gd->env_valid = 1;
182                 else if (tmp_env1->flags > tmp_env2->flags)
183                         gd->env_valid = 1;
184                 else if (tmp_env2->flags > tmp_env1->flags)
185                         gd->env_valid = 2;
186                 else /* flags are equal - almost impossible */
187                         gd->env_valid = 1;
188         }
189
190         if (gd->env_valid == 1)
191                 ep = tmp_env1;
192         else
193                 ep = tmp_env2;
194
195         env_flags = ep->flags;
196         env_import((char *)ep, 0);
197 }
198 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
199 void env_relocate_spec(void)
200 {
201         ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
202
203         if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
204                 printf("\n** Cannot find mtd partition \"%s\"\n",
205                        CONFIG_ENV_UBI_PART);
206                 set_default_env(NULL);
207                 return;
208         }
209
210         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)&buf,
211                             CONFIG_ENV_SIZE)) {
212                 printf("\n** Unable to read env from %s:%s **\n",
213                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
214                 set_default_env(NULL);
215                 return;
216         }
217
218         env_import(buf, 1);
219 }
220 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */