// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 */

#include "env-lib.h"
#include <env.h>
#include <log.h>

#define MAX_CMD_LEN	25

static void env_clear_common(u32 index, const struct env_map_common *map)
{
	map[index].val->val = 0;
	map[index].val->set = false;
}

static int env_read_common(u32 index, const struct env_map_common *map)
{
	u32 val;

	if (!env_get_yesno(map[index].env_name)) {
		if (map[index].type == ENV_HEX) {
			val = (u32)env_get_hex(map[index].env_name, 0);
			debug("ENV: %s: = %#x\n", map[index].env_name, val);
		} else {
			val = (u32)env_get_ulong(map[index].env_name, 10, 0);
			debug("ENV: %s: = %d\n", map[index].env_name, val);
		}

		map[index].val->val = val;
		map[index].val->set = true;
	}

	return 0;
}

static void env_clear_core(u32 index, const struct env_map_percpu *map)
{
	for (u32 i = 0; i < NR_CPUS; i++) {
		(*map[index].val)[i].val = 0;
		(*map[index].val)[i].set = false;
	}
}

static int env_read_core(u32 index, const struct env_map_percpu *map)
{
	u32 val;
	char command[MAX_CMD_LEN];

	for (u32 i = 0; i < NR_CPUS; i++) {
		sprintf(command, "%s_%u", map[index].env_name, i);
		if (!env_get_yesno(command)) {
			if (map[index].type == ENV_HEX) {
				val = (u32)env_get_hex(command, 0);
				debug("ENV: %s: = %#x\n", command, val);
			} else {
				val = (u32)env_get_ulong(command, 10, 0);
				debug("ENV: %s: = %d\n", command, val);
			}

			(*map[index].val)[i].val = val;
			(*map[index].val)[i].set = true;
		}
	}

	return 0;
}

static int env_validate_common(u32 index, const struct env_map_common *map)
{
	u32 value = map[index].val->val;
	bool set = map[index].val->set;
	u32 min = map[index].min;
	u32 max = map[index].max;

	/* Check if environment is mandatory */
	if (map[index].mandatory && !set) {
		pr_err("Variable \'%s\' is mandatory, but it is not defined\n",
		       map[index].env_name);

		return -EINVAL;
	}

	/* Check environment boundary */
	if (set && (value < min || value > max)) {
		if (map[index].type == ENV_HEX)
			pr_err("Variable \'%s\' must be between %#x and %#x\n",
			       map[index].env_name, min, max);
		else
			pr_err("Variable \'%s\' must be between %u and %u\n",
			       map[index].env_name, min, max);

		return -EINVAL;
	}

	return 0;
}

static int env_validate_core(u32 index, const struct env_map_percpu *map,
			     bool (*cpu_used)(u32))
{
	u32 value;
	bool set;
	bool mandatory = map[index].mandatory;
	u32 min, max;

	for (u32 i = 0; i < NR_CPUS; i++) {
		set = (*map[index].val)[i].set;
		value = (*map[index].val)[i].val;

		/* Check if environment is mandatory */
		if (cpu_used(i) && mandatory && !set) {
			pr_err("CPU %u is used, but \'%s_%u\' is not defined\n",
			       i, map[index].env_name, i);

			return -EINVAL;
		}

		min = map[index].min[i];
		max = map[index].max[i];

		/* Check environment boundary */
		if (set && (value < min || value > max)) {
			if (map[index].type == ENV_HEX)
				pr_err("Variable \'%s_%u\' must be between %#x and %#x\n",
				       map[index].env_name, i, min, max);
			else
				pr_err("Variable \'%s_%u\' must be between %d and %d\n",
				       map[index].env_name, i, min, max);

			return -EINVAL;
		}
	}

	return 0;
}

void envs_cleanup_core(const struct env_map_percpu *map)
{
	/* Cleanup env struct first */
	for (u32 i = 0; map[i].env_name; i++)
		env_clear_core(i, map);
}

void envs_cleanup_common(const struct env_map_common *map)
{
	/* Cleanup env struct first */
	for (u32 i = 0; map[i].env_name; i++)
		env_clear_common(i, map);
}

int envs_read_common(const struct env_map_common *map)
{
	int ret;

	for (u32 i = 0; map[i].env_name; i++) {
		ret = env_read_common(i, map);
		if (ret)
			return ret;
	}

	return 0;
}

int envs_validate_common(const struct env_map_common *map)
{
	int ret;

	for (u32 i = 0; map[i].env_name; i++) {
		ret = env_validate_common(i, map);
		if (ret)
			return ret;
	}

	return 0;
}

int envs_read_validate_common(const struct env_map_common *map)
{
	int ret;

	envs_cleanup_common(map);

	ret = envs_read_common(map);
	if (ret)
		return ret;

	ret = envs_validate_common(map);
	if (ret)
		return ret;

	return 0;
}

int envs_read_validate_core(const struct env_map_percpu *map,
			    bool (*cpu_used)(u32))
{
	int ret;

	envs_cleanup_core(map);

	for (u32 i = 0; map[i].env_name; i++) {
		ret = env_read_core(i, map);
		if (ret)
			return ret;
	}

	for (u32 i = 0; map[i].env_name; i++) {
		ret = env_validate_core(i, map, cpu_used);
		if (ret)
			return ret;
	}

	return 0;
}

int envs_process_and_validate(const struct env_map_common *common,
			      const struct env_map_percpu *core,
			      bool (*cpu_used)(u32))
{
	int ret;

	ret = envs_read_validate_common(common);
	if (ret)
		return ret;

	ret = envs_read_validate_core(core, cpu_used);
	if (ret)
		return ret;

	return 0;
}

static int args_envs_read_search(const struct env_map_common *map,
				 int argc, char *const argv[])
{
	for (int i = 0; map[i].env_name; i++) {
		if (!strcmp(argv[0], map[i].env_name))
			return i;
	}

	pr_err("Unexpected argument '%s', can't parse\n", argv[0]);

	return -ENOENT;
}

static int arg_read_set(const struct env_map_common *map, u32 i, int argc,
			char *const argv[])
{
	char *endp = argv[1];

	if (map[i].type == ENV_HEX)
		map[i].val->val = hextoul(argv[1], &endp);
	else
		map[i].val->val = dectoul(argv[1], &endp);

	map[i].val->set = true;

	if (*endp == '\0')
		return 0;

	pr_err("Unexpected argument '%s', can't parse\n", argv[1]);

	map[i].val->set = false;

	return -EINVAL;
}

int args_envs_enumerate(const struct env_map_common *map, int enum_by,
			int argc, char *const argv[])
{
	u32 i;

	if (argc % enum_by) {
		pr_err("unexpected argument number: %d\n", argc);
		return -EINVAL;
	}

	while (argc > 0) {
		i = args_envs_read_search(map, argc, argv);
		if (i < 0)
			return i;

		debug("ARG: found '%s' with index %d\n", map[i].env_name, i);

		if (i < 0) {
			pr_err("unknown arg: %s\n", argv[0]);
			return -EINVAL;
		}

		if (arg_read_set(map, i, argc, argv))
			return -EINVAL;

		debug("ARG: value.s '%s' == %#x\n", argv[1], map[i].val->val);

		argc -= enum_by;
		argv += enum_by;
	}

	return 0;
}
