xref: /openbmc/u-boot/board/synopsys/hsdk/env-lib.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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