e4b85167ecf71780fd734ee898854460c2cfd4a4
[oweals/u-boot.git] / env / ubi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (c) Copyright 2012 by National Instruments,
4  *        Joe Hershberger <joe.hershberger@ni.com>
5  */
6
7 #include <common.h>
8
9 #include <command.h>
10 #include <environment.h>
11 #include <errno.h>
12 #include <malloc.h>
13 #include <memalign.h>
14 #include <search.h>
15 #include <ubi_uboot.h>
16 #undef crc32
17
18 #define _QUOTE(x) #x
19 #define QUOTE(x) _QUOTE(x)
20
21 #if (CONFIG_ENV_UBI_VID_OFFSET == 0)
22  #define UBI_VID_OFFSET NULL
23 #else
24  #define UBI_VID_OFFSET QUOTE(CONFIG_ENV_UBI_VID_OFFSET)
25 #endif
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 #ifdef CONFIG_CMD_SAVEENV
30 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
31 static int env_ubi_save(void)
32 {
33         ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
34         int ret;
35
36         ret = env_export(env_new);
37         if (ret)
38                 return ret;
39
40         if (ubi_part(CONFIG_ENV_UBI_PART, UBI_VID_OFFSET)) {
41                 printf("\n** Cannot find mtd partition \"%s\"\n",
42                        CONFIG_ENV_UBI_PART);
43                 return 1;
44         }
45
46         if (gd->env_valid == ENV_VALID) {
47                 puts("Writing to redundant UBI... ");
48                 if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND,
49                                      (void *)env_new, CONFIG_ENV_SIZE)) {
50                         printf("\n** Unable to write env to %s:%s **\n",
51                                CONFIG_ENV_UBI_PART,
52                                CONFIG_ENV_UBI_VOLUME_REDUND);
53                         return 1;
54                 }
55         } else {
56                 puts("Writing to UBI... ");
57                 if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME,
58                                      (void *)env_new, CONFIG_ENV_SIZE)) {
59                         printf("\n** Unable to write env to %s:%s **\n",
60                                CONFIG_ENV_UBI_PART,
61                                CONFIG_ENV_UBI_VOLUME);
62                         return 1;
63                 }
64         }
65
66         puts("done\n");
67
68         gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
69
70         return 0;
71 }
72 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
73 static int env_ubi_save(void)
74 {
75         ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
76         int ret;
77
78         ret = env_export(env_new);
79         if (ret)
80                 return ret;
81
82         if (ubi_part(CONFIG_ENV_UBI_PART, UBI_VID_OFFSET)) {
83                 printf("\n** Cannot find mtd partition \"%s\"\n",
84                        CONFIG_ENV_UBI_PART);
85                 return 1;
86         }
87
88         if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
89                              CONFIG_ENV_SIZE)) {
90                 printf("\n** Unable to write env to %s:%s **\n",
91                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
92                 return 1;
93         }
94
95         puts("done\n");
96         return 0;
97 }
98 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
99 #endif /* CONFIG_CMD_SAVEENV */
100
101 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
102 static int env_ubi_load(void)
103 {
104         ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE);
105         ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE);
106         int read1_fail, read2_fail;
107         env_t *tmp_env1, *tmp_env2;
108
109         /*
110          * In case we have restarted u-boot there is a chance that buffer
111          * contains old environment (from the previous boot).
112          * If UBI volume is zero size, ubi_volume_read() doesn't modify the
113          * buffer.
114          * We need to clear buffer manually here, so the invalid CRC will
115          * cause setting default environment as expected.
116          */
117         memset(env1_buf, 0x0, CONFIG_ENV_SIZE);
118         memset(env2_buf, 0x0, CONFIG_ENV_SIZE);
119
120         tmp_env1 = (env_t *)env1_buf;
121         tmp_env2 = (env_t *)env2_buf;
122
123         if (ubi_part(CONFIG_ENV_UBI_PART, UBI_VID_OFFSET)) {
124                 printf("\n** Cannot find mtd partition \"%s\"\n",
125                        CONFIG_ENV_UBI_PART);
126                 set_default_env(NULL, 0);
127                 return -EIO;
128         }
129
130         read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1,
131                                      CONFIG_ENV_SIZE);
132         if (read1_fail)
133                 printf("\n** Unable to read env from %s:%s **\n",
134                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
135
136         read2_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND,
137                                      (void *)tmp_env2, CONFIG_ENV_SIZE);
138         if (read2_fail)
139                 printf("\n** Unable to read redundant env from %s:%s **\n",
140                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND);
141
142         return env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
143                                                          read2_fail);
144 }
145 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
146 static int env_ubi_load(void)
147 {
148         ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
149
150         /*
151          * In case we have restarted u-boot there is a chance that buffer
152          * contains old environment (from the previous boot).
153          * If UBI volume is zero size, ubi_volume_read() doesn't modify the
154          * buffer.
155          * We need to clear buffer manually here, so the invalid CRC will
156          * cause setting default environment as expected.
157          */
158         memset(buf, 0x0, CONFIG_ENV_SIZE);
159
160         if (ubi_part(CONFIG_ENV_UBI_PART, UBI_VID_OFFSET)) {
161                 printf("\n** Cannot find mtd partition \"%s\"\n",
162                        CONFIG_ENV_UBI_PART);
163                 set_default_env(NULL, 0);
164                 return -EIO;
165         }
166
167         if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, CONFIG_ENV_SIZE)) {
168                 printf("\n** Unable to read env from %s:%s **\n",
169                        CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
170                 set_default_env(NULL, 0);
171                 return -EIO;
172         }
173
174         return env_import(buf, 1);
175 }
176 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
177
178 U_BOOT_ENV_LOCATION(ubi) = {
179         .location       = ENVL_UBI,
180         ENV_NAME("UBI")
181         .load           = env_ubi_load,
182         .save           = env_save_ptr(env_ubi_save),
183 };