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
  10#define MAX_CMD_LEN     25
  11
  12static 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
  18static 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
  38static 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
  46static 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
  70static 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
 100static 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
 139void 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
 146void 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
 153int 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
 166int 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
 179int 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
 196int 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
 218int 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
 235static 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
 248static 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
 270int 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