common: Drop log.h from common header
[platform/kernel/u-boot.git] / board / synopsys / hsdk / env-lib.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
4  * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
5  */
6
7 #include "env-lib.h"
8 #include <env.h>
9 #include <log.h>
10
11 #define MAX_CMD_LEN     25
12
13 static void env_clear_common(u32 index, const struct env_map_common *map)
14 {
15         map[index].val->val = 0;
16         map[index].val->set = false;
17 }
18
19 static int env_read_common(u32 index, const struct env_map_common *map)
20 {
21         u32 val;
22
23         if (!env_get_yesno(map[index].env_name)) {
24                 if (map[index].type == ENV_HEX) {
25                         val = (u32)env_get_hex(map[index].env_name, 0);
26                         debug("ENV: %s: = %#x\n", map[index].env_name, val);
27                 } else {
28                         val = (u32)env_get_ulong(map[index].env_name, 10, 0);
29                         debug("ENV: %s: = %d\n", map[index].env_name, val);
30                 }
31
32                 map[index].val->val = val;
33                 map[index].val->set = true;
34         }
35
36         return 0;
37 }
38
39 static void env_clear_core(u32 index, const struct env_map_percpu *map)
40 {
41         for (u32 i = 0; i < NR_CPUS; i++) {
42                 (*map[index].val)[i].val = 0;
43                 (*map[index].val)[i].set = false;
44         }
45 }
46
47 static int env_read_core(u32 index, const struct env_map_percpu *map)
48 {
49         u32 val;
50         char command[MAX_CMD_LEN];
51
52         for (u32 i = 0; i < NR_CPUS; i++) {
53                 sprintf(command, "%s_%u", map[index].env_name, i);
54                 if (!env_get_yesno(command)) {
55                         if (map[index].type == ENV_HEX) {
56                                 val = (u32)env_get_hex(command, 0);
57                                 debug("ENV: %s: = %#x\n", command, val);
58                         } else {
59                                 val = (u32)env_get_ulong(command, 10, 0);
60                                 debug("ENV: %s: = %d\n", command, val);
61                         }
62
63                         (*map[index].val)[i].val = val;
64                         (*map[index].val)[i].set = true;
65                 }
66         }
67
68         return 0;
69 }
70
71 static int env_validate_common(u32 index, const struct env_map_common *map)
72 {
73         u32 value = map[index].val->val;
74         bool set = map[index].val->set;
75         u32 min = map[index].min;
76         u32 max = map[index].max;
77
78         /* Check if environment is mandatory */
79         if (map[index].mandatory && !set) {
80                 pr_err("Variable \'%s\' is mandatory, but it is not defined\n",
81                        map[index].env_name);
82
83                 return -EINVAL;
84         }
85
86         /* Check environment boundary */
87         if (set && (value < min || value > max)) {
88                 if (map[index].type == ENV_HEX)
89                         pr_err("Variable \'%s\' must be between %#x and %#x\n",
90                                map[index].env_name, min, max);
91                 else
92                         pr_err("Variable \'%s\' must be between %u and %u\n",
93                                map[index].env_name, min, max);
94
95                 return -EINVAL;
96         }
97
98         return 0;
99 }
100
101 static int env_validate_core(u32 index, const struct env_map_percpu *map,
102                              bool (*cpu_used)(u32))
103 {
104         u32 value;
105         bool set;
106         bool mandatory = map[index].mandatory;
107         u32 min, max;
108
109         for (u32 i = 0; i < NR_CPUS; i++) {
110                 set = (*map[index].val)[i].set;
111                 value = (*map[index].val)[i].val;
112
113                 /* Check if environment is mandatory */
114                 if (cpu_used(i) && mandatory && !set) {
115                         pr_err("CPU %u is used, but \'%s_%u\' is not defined\n",
116                                i, map[index].env_name, i);
117
118                         return -EINVAL;
119                 }
120
121                 min = map[index].min[i];
122                 max = map[index].max[i];
123
124                 /* Check environment boundary */
125                 if (set && (value < min || value > max)) {
126                         if (map[index].type == ENV_HEX)
127                                 pr_err("Variable \'%s_%u\' must be between %#x and %#x\n",
128                                        map[index].env_name, i, min, max);
129                         else
130                                 pr_err("Variable \'%s_%u\' must be between %d and %d\n",
131                                        map[index].env_name, i, min, max);
132
133                         return -EINVAL;
134                 }
135         }
136
137         return 0;
138 }
139
140 void envs_cleanup_core(const struct env_map_percpu *map)
141 {
142         /* Cleanup env struct first */
143         for (u32 i = 0; map[i].env_name; i++)
144                 env_clear_core(i, map);
145 }
146
147 void envs_cleanup_common(const struct env_map_common *map)
148 {
149         /* Cleanup env struct first */
150         for (u32 i = 0; map[i].env_name; i++)
151                 env_clear_common(i, map);
152 }
153
154 int envs_read_common(const struct env_map_common *map)
155 {
156         int ret;
157
158         for (u32 i = 0; map[i].env_name; i++) {
159                 ret = env_read_common(i, map);
160                 if (ret)
161                         return ret;
162         }
163
164         return 0;
165 }
166
167 int envs_validate_common(const struct env_map_common *map)
168 {
169         int ret;
170
171         for (u32 i = 0; map[i].env_name; i++) {
172                 ret = env_validate_common(i, map);
173                 if (ret)
174                         return ret;
175         }
176
177         return 0;
178 }
179
180 int envs_read_validate_common(const struct env_map_common *map)
181 {
182         int ret;
183
184         envs_cleanup_common(map);
185
186         ret = envs_read_common(map);
187         if (ret)
188                 return ret;
189
190         ret = envs_validate_common(map);
191         if (ret)
192                 return ret;
193
194         return 0;
195 }
196
197 int envs_read_validate_core(const struct env_map_percpu *map,
198                             bool (*cpu_used)(u32))
199 {
200         int ret;
201
202         envs_cleanup_core(map);
203
204         for (u32 i = 0; map[i].env_name; i++) {
205                 ret = env_read_core(i, map);
206                 if (ret)
207                         return ret;
208         }
209
210         for (u32 i = 0; map[i].env_name; i++) {
211                 ret = env_validate_core(i, map, cpu_used);
212                 if (ret)
213                         return ret;
214         }
215
216         return 0;
217 }
218
219 int envs_process_and_validate(const struct env_map_common *common,
220                               const struct env_map_percpu *core,
221                               bool (*cpu_used)(u32))
222 {
223         int ret;
224
225         ret = envs_read_validate_common(common);
226         if (ret)
227                 return ret;
228
229         ret = envs_read_validate_core(core, cpu_used);
230         if (ret)
231                 return ret;
232
233         return 0;
234 }
235
236 static int args_envs_read_search(const struct env_map_common *map,
237                                  int argc, char *const argv[])
238 {
239         for (int i = 0; map[i].env_name; i++) {
240                 if (!strcmp(argv[0], map[i].env_name))
241                         return i;
242         }
243
244         pr_err("Unexpected argument '%s', can't parse\n", argv[0]);
245
246         return -ENOENT;
247 }
248
249 static int arg_read_set(const struct env_map_common *map, u32 i, int argc,
250                         char *const argv[])
251 {
252         char *endp = argv[1];
253
254         if (map[i].type == ENV_HEX)
255                 map[i].val->val = simple_strtoul(argv[1], &endp, 16);
256         else
257                 map[i].val->val = simple_strtoul(argv[1], &endp, 10);
258
259         map[i].val->set = true;
260
261         if (*endp == '\0')
262                 return 0;
263
264         pr_err("Unexpected argument '%s', can't parse\n", argv[1]);
265
266         map[i].val->set = false;
267
268         return -EINVAL;
269 }
270
271 int args_envs_enumerate(const struct env_map_common *map, int enum_by,
272                         int argc, char *const argv[])
273 {
274         u32 i;
275
276         if (argc % enum_by) {
277                 pr_err("unexpected argument number: %d\n", argc);
278                 return -EINVAL;
279         }
280
281         while (argc > 0) {
282                 i = args_envs_read_search(map, argc, argv);
283                 if (i < 0)
284                         return i;
285
286                 debug("ARG: found '%s' with index %d\n", map[i].env_name, i);
287
288                 if (i < 0) {
289                         pr_err("unknown arg: %s\n", argv[0]);
290                         return -EINVAL;
291                 }
292
293                 if (arg_read_set(map, i, argc, argv))
294                         return -EINVAL;
295
296                 debug("ARG: value.s '%s' == %#x\n", argv[1], map[i].val->val);
297
298                 argc -= enum_by;
299                 argv += enum_by;
300         }
301
302         return 0;
303 }