blob: ebe73a2e393d7f590a926a2d12f5c443e54780ec [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2018 MediaTek Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <env.h>
25#include <errno.h>
26#include <lib/bio.h>
27#include <lib/mempool.h>
28#include <malloc.h>
29#include <printf.h>
30#include <stdint.h>
31#include <string.h>
32#include <sys/types.h>
33#define ENV_PART "para"
34
35#define MODULE_NAME "LK_ENV"
36env_t g_env;
37static int env_valid;
38static char *env_buffer;
39static char env_get_char(int index);
40static char *env_get_addr(int index);
41static int envmatch(uchar *s1, int i2);
42static int write_env_area(char *env_buf);
43static int read_env_area(char *env_buf);
44
45#ifndef min
46#define min(x, y) (x < y ? x : y)
47#endif
48
49void env_init(void)
50{
51 int ret, i;
52 env_buffer = (char *)mempool_alloc(CFG_ENV_SIZE, MEMPOOL_ANY);
53 memset(env_buffer, 0x00, CFG_ENV_SIZE);
54 g_env.env_data = env_buffer + CFG_ENV_DATA_OFFSET;
55 ret = read_env_area(env_buffer);
56 int checksum = 0;
57 if (ret < 0) {
58 printf("[%s]read_env_area fail, ret = %x\n", MODULE_NAME, ret);
59 env_valid = 0;
60 goto end;
61 }
62
63 memcpy(g_env.sig, env_buffer, sizeof(g_env.sig));
64 memcpy(g_env.sig_1, env_buffer + CFG_ENV_SIG_1_OFFSET, sizeof(g_env.sig_1));
65
66 if (!strcmp(g_env.sig, ENV_SIG) && !strcmp(g_env.sig_1, ENV_SIG)) {
67 g_env.checksum = *((int *)env_buffer + CFG_ENV_CHECKSUM_OFFSET / 4);
68 for (i = 0; i < (int)(CFG_ENV_DATA_SIZE); i++) {
69 checksum += g_env.env_data[i];
70 }
71 if (checksum != g_env.checksum) {
72 printf("[%s]checksum mismatch s %d d %d!\n", MODULE_NAME, g_env.checksum, checksum);
73 env_valid = 0;
74 goto end;
75 } else {
76 printf("[%s]ENV initialize sucess\n", MODULE_NAME);
77 env_valid = 1;
78 }
79
80 } else {
81 printf("[%s]ENV SIG Wrong\n", MODULE_NAME);
82 env_valid = 0;
83 goto end;
84 }
85end:
86 if (!env_valid) {
87 memset(env_buffer, 0x00, CFG_ENV_SIZE);
88 }
89
90}
91
92char *get_env(char *name)
93{
94 int i, nxt;
95 printf("[%s]get_env %s\n", MODULE_NAME, name);
96 if (!env_valid)
97 return NULL;
98
99 for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
100 int val;
101
102 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
103 if (nxt >= CFG_ENV_SIZE) {
104 return (NULL);
105 }
106 }
107 if ((val = envmatch((uchar *) name, i)) < 0)
108 continue;
109 return ((char *)env_get_addr(val));
110 }
111
112 return (NULL);
113}
114
115static char env_get_char(int index)
116{
117 return *(g_env.env_data + index);
118}
119
120static char *env_get_addr(int index)
121{
122 return (g_env.env_data + index);
123
124}
125
126static int envmatch(uchar *s1, int i2)
127{
128
129 while (*s1 == env_get_char(i2++))
130 if (*s1++ == '=')
131 return (i2);
132 if (*s1 == '\0' && env_get_char(i2 - 1) == '=')
133 return (i2);
134 return (-1);
135}
136
137int set_env(char *name, char *value)
138{
139 int len, oldval;
140 uchar *env, *nxt = NULL;
141
142 int ret;
143
144 uchar *env_data = (uchar *) g_env.env_data;
145
146 printf("[%s]set_env %s %s\n", MODULE_NAME, name, value);
147
148 oldval = -1;
149
150 if (!env_valid) {
151 env = env_data;
152 goto add;
153 }
154
155 for (env = env_data; *env; env = nxt + 1) {
156 for (nxt = env; *nxt; ++nxt);
157 if ((oldval = envmatch((uchar *) name, env - env_data)) >= 0)
158 break;
159 }
160
161 if (oldval > 0) {
162 if (*++nxt == '\0') {
163 if (env > env_data) {
164 env--;
165 } else {
166 *env = '\0';
167 }
168 } else {
169 for (;;) {
170 *env = *nxt++;
171 if ((*env == '\0') && (*nxt == '\0'))
172 break;
173 ++env;
174 }
175 }
176 *++env = '\0';
177 }
178
179 for (env = env_data; *env || *(env + 1); ++env);
180 if (env > env_data)
181 ++env;
182
183add:
184 /*
185 * Overflow when:
186 * "name" + "=" + "val" +"\0\0" > ENV_SIZE - (env-env_data)
187 */
188 len = strlen(name) + 2;
189 /* add '=' for first arg, ' ' for all others */
190 len += strlen(value) + 1;
191
192 if (len > (&env_data[CFG_ENV_DATA_SIZE] - env)) {
193 printf("## Error: environment overflow, \"%s\" deleted\n", name);
194 return -1;
195 }
196 while ((*env = *name++) != '\0')
197 env++;
198
199 *env = '=';
200
201 while ((*++env = *value++) != '\0');
202
203 /* end is marked with double '\0' */
204 *++env = '\0';
205 memset(env, 0x00, CFG_ENV_DATA_SIZE - (env - env_data));
206 ret = write_env_area(env_buffer);
207 if (ret < 0) {
208 printf("[%s]write env fail\n", MODULE_NAME);
209 memset(env_buffer, 0x00, CFG_ENV_SIZE);
210 return -1;
211 }
212 env_valid = 1;
213 return 0;
214
215}
216
217void print_env()
218{
219 int i, nxt;
220 uchar *env = (uchar *) g_env.env_data;
221 if (!env_valid) {
222 printf("[%s]no valid env\n", MODULE_NAME);
223 return;
224 }
225 printf("[%s]env:\n", MODULE_NAME);
226 for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
227 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) {
228 if (nxt >= (int)(CFG_ENV_DATA_SIZE)) {
229 return;
230 }
231 }
232 printf("%s\n", env + i);
233 }
234}
235
236static int write_env_area(char *env_buf)
237{
238#if 0 //nelson
239 part_t *part;
240 part_dev_t *dev;
241 size_t count;
242 long len;
243 int i, checksum = 0;
244 unsigned long long start_addr;
245
246 dev = mt_part_get_device();
247 if (!dev) {
248 return -ENODEV;
249 }
250
251 part = mt_part_get_partition(ENV_PART);
252 if (!part) {
253 return -ENOENT;
254 }
255
256 start_addr = (u64) part->start_sect * dev->blkdev->blksz;
257
258 count = min(sizeof(ENV_SIG), sizeof(g_env.sig));
259 memcpy(env_buf, ENV_SIG, count);
260 memcpy(env_buf + CFG_ENV_SIG_1_OFFSET, ENV_SIG, count);
261
262 for (i = 0; i < (int)CFG_ENV_DATA_SIZE; i++) {
263 checksum += *(env_buf + CFG_ENV_DATA_OFFSET + i);
264 }
265 printf("checksum %d\n", checksum);
266
267 *((int *)env_buf + CFG_ENV_CHECKSUM_OFFSET / 4) = checksum;
268
269 len = dev->write(dev, (uchar *) env_buf, start_addr + CFG_ENV_OFFSET, CFG_ENV_SIZE, part->part_id);
270 if (len < 0) {
271 return -EIO;
272 }
273#else
274 size_t count;
275 long len;
276 int i, checksum = 0;
277
278 bdev_t *bdev;
279
280 bdev = bio_open_by_label(ENV_PART);
281 if (!bdev) {
282 return -ENODEV;
283 }
284
285 count = min(sizeof(ENV_SIG), sizeof(g_env.sig));
286 memcpy(env_buf, ENV_SIG, count);
287 memcpy(env_buf + CFG_ENV_SIG_1_OFFSET, ENV_SIG, count);
288
289 for (i = 0; i < (int)CFG_ENV_DATA_SIZE; i++) {
290 checksum += *(env_buf + CFG_ENV_DATA_OFFSET + i);
291 }
292 dprintf(CRITICAL, "checksum %d\n", checksum);
293
294 *((int *)env_buf + CFG_ENV_CHECKSUM_OFFSET / 4) = checksum;
295 len = bio_write(bdev, (uchar *) env_buf, CFG_ENV_OFFSET, CFG_ENV_SIZE);
296 if (len < 0) {
297 return -EIO;
298 }
299
300#endif
301 return 0;
302
303}
304
305static int read_env_area(char *env_buf)
306{
307#if 0 //nelson
308 part_t *part;
309 part_dev_t *dev;
310 long len;
311 unsigned long long start_addr;
312
313 dev = mt_part_get_device();
314 if (!dev) {
315 return -ENODEV;
316 }
317
318 part = mt_part_get_partition(ENV_PART);
319 if (!part) {
320 return -ENOENT;
321 }
322
323 start_addr = (u64) part->start_sect * dev->blkdev->blksz;
324
325 len = dev->read(dev, start_addr + CFG_ENV_OFFSET, (uchar *) env_buf, CFG_ENV_SIZE, part->part_id);
326 if (len < 0) {
327 return -EIO;
328 }
329#else
330
331 long len;
332 bdev_t *bdev;
333
334 bdev = bio_open_by_label(ENV_PART);
335 if (!bdev) {
336 return -ENODEV;
337 }
338
339 len = bio_read(bdev, (uchar *) env_buf, CFG_ENV_OFFSET, CFG_ENV_SIZE);
340 if (len < 0) {
341 return -EIO;
342 }
343
344#endif
345 return 0;
346}