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