uboot/board/synopsys/hsdk/env-lib.c
<<
>>
Prefs
   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
  13static 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
  19static 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
  39static 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
  47static 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
  71static 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
 101static 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
 140void 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
 147void 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
 154int 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
 167int 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
 180int 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
 197int 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
 219int 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
 236static 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
 249static 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 = hextoul(argv[1], &endp);
 256        else
 257                map[i].val->val = dectoul(argv[1], &endp);
 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
 271int 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}
 304