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