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