diff options
| -rw-r--r-- | common/Makefile | 1 | ||||
| -rw-r--r-- | common/hwconfig.c | 210 | ||||
| -rw-r--r-- | include/hwconfig.h | 69 | 
3 files changed, 280 insertions, 0 deletions
| diff --git a/common/Makefile b/common/Makefile index c8e5d2610..c8a997b0a 100644 --- a/common/Makefile +++ b/common/Makefile @@ -151,6 +151,7 @@ COBJS-$(CONFIG_VFD) += cmd_vfd.o  # others  COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o  COBJS-$(CONFIG_CMD_DOC) += docecc.o +COBJS-$(CONFIG_HWCONFIG) += hwconfig.o  COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o  COBJS-y += flash.o  COBJS-$(CONFIG_CMD_KGDB) += kgdb.o diff --git a/common/hwconfig.c b/common/hwconfig.c new file mode 100644 index 000000000..e5c60ba7a --- /dev/null +++ b/common/hwconfig.c @@ -0,0 +1,210 @@ +/* + * An inteface for configuring a hardware via u-boot environment. + * + * Copyright (c) 2009  MontaVista Software, Inc. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include <config.h> +#include <common.h> +#include <exports.h> +#include <hwconfig.h> +#include <linux/types.h> +#include <linux/string.h> + +static const char *hwconfig_parse(const char *opts, size_t maxlen, +				  const char *opt, char stopch, char eqch, +				  size_t *arglen) +{ +	size_t optlen = strlen(opt); +	char *str; +	const char *start = opts; +	const char *end; + +next: +	str = strstr(opts, opt); +	end = str + optlen; +	if (end - start > maxlen) +		return NULL; + +	if (str && (str == opts || str[-1] == stopch) && +			(*end == stopch || *end == eqch || *end == '\0')) { +		const char *arg_end; + +		if (!arglen) +			return str; + +		if (*end != eqch) +			return NULL; + +		arg_end = strchr(str, stopch); +		if (!arg_end) +			*arglen = min(maxlen, strlen(str)) - optlen - 1; +		else +			*arglen = arg_end - end - 1; + +		return end + 1; +	} else if (str) { +		opts = end; +		goto next; +	} +	return NULL; +} + +const char *cpu_hwconfig __attribute__((weak)); +const char *board_hwconfig __attribute__((weak)); + +static const char *__hwconfig(const char *opt, size_t *arglen) +{ +	const char *env_hwconfig = getenv("hwconfig"); + +	if (env_hwconfig) +		return hwconfig_parse(env_hwconfig, strlen(env_hwconfig), +				      opt, ';', ':', arglen); + +	if (board_hwconfig) +		return hwconfig_parse(board_hwconfig, strlen(board_hwconfig), +				      opt, ';', ':', arglen); + +	if (cpu_hwconfig) +		return hwconfig_parse(cpu_hwconfig, strlen(cpu_hwconfig), +				      opt, ';', ':', arglen); + +	return NULL; +} + +/* + * hwconfig - query if a particular hwconfig option is specified + * @opt:	a string representing an option + * + * This call can be used to find out whether U-Boot should configure + * a particular hardware option. + * + * Returns non-zero value if the hardware option can be used and thus + * should be configured, 0 otherwise. + * + * This function also returns non-zero value if CONFIG_HWCONFIG is + * undefined. + * + * Returning non-zero value without CONFIG_HWCONFIG has its crucial + * purpose: the hwconfig() call should be a "transparent" interface, + * e.g. if a board doesn't need hwconfig facility, then we assume + * that the board file only calls things that are actually used, so + * hwconfig() will always return true result. + */ +int hwconfig(const char *opt) +{ +	return !!__hwconfig(opt, NULL); +} + +/* + * hwconfig_arg - get hwconfig option's argument + * @opt:	a string representing an option + * @arglen:	a pointer to an allocated size_t variable + * + * Unlike hwconfig() function, this function returns a pointer to the + * start of the hwconfig arguments, if option is not found or it has + * no specified arguments, the function returns NULL pointer. + * + * If CONFIG_HWCONFIG is undefined, the function returns "", and + * arglen is set to 0. + */ +const char *hwconfig_arg(const char *opt, size_t *arglen) +{ +	return __hwconfig(opt, arglen); +} + +/* + * hwconfig_arg_cmp - compare hwconfig option's argument + * @opt:	a string representing an option + * @arg:	a string for comparing an option's argument + * + * This call is similar to hwconfig_arg, but instead of returning + * hwconfig argument and its length, it is comparing it to @arg. + * + * Returns non-zero value if @arg matches, 0 otherwise. + * + * If CONFIG_HWCONFIG is undefined, the function returns a non-zero + * value, i.e. the argument matches. + */ +int hwconfig_arg_cmp(const char *opt, const char *arg) +{ +	const char *argstr; +	size_t arglen; + +	argstr = hwconfig_arg(opt, &arglen); +	if (!argstr || arglen != strlen(arg)) +		return 0; + +	return !strncmp(argstr, arg, arglen); +} + +/* + * hwconfig_sub - query if a particular hwconfig sub-option is specified + * @opt:	a string representing an option + * @subopt:	a string representing a sub-option + * + * This call is similar to hwconfig(), except that it takes additional + * argument @subopt. In this example: + * 	"dr_usb:mode=peripheral" + * "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its + * argument. + */ +int hwconfig_sub(const char *opt, const char *subopt) +{ +	size_t arglen; +	const char *arg; + +	arg = __hwconfig(opt, &arglen); +	if (!arg) +		return 0; +	return !!hwconfig_parse(arg, arglen, subopt, ',', '=', NULL); +} + +/* + * hwconfig_subarg - get hwconfig sub-option's argument + * @opt:	a string representing an option + * @subopt:	a string representing a sub-option + * @subarglen:	a pointer to an allocated size_t variable + * + * This call is similar to hwconfig_arg(), except that it takes an additional + * argument @subopt, and so works with sub-options. + */ +const char *hwconfig_subarg(const char *opt, const char *subopt, +			    size_t *subarglen) +{ +	size_t arglen; +	const char *arg; + +	arg = __hwconfig(opt, &arglen); +	if (!arg) +		return NULL; +	return hwconfig_parse(arg, arglen, subopt, ',', '=', subarglen); +} + +/* + * hwconfig_arg_cmp - compare hwconfig sub-option's argument + * @opt:	a string representing an option + * @subopt:	a string representing a sub-option + * @subarg:	a string for comparing an sub-option's argument + * + * This call is similar to hwconfig_arg_cmp, except that it takes an additional + * argument @subopt, and so works with sub-options. + */ +int hwconfig_subarg_cmp(const char *opt, const char *subopt, const char *subarg) +{ +	const char *argstr; +	size_t arglen; + +	argstr = hwconfig_subarg(opt, subopt, &arglen); +	if (!argstr || arglen != strlen(subarg)) +		return 0; + +	return !strncmp(argstr, subarg, arglen); +} diff --git a/include/hwconfig.h b/include/hwconfig.h new file mode 100644 index 000000000..d517f782f --- /dev/null +++ b/include/hwconfig.h @@ -0,0 +1,69 @@ +/* + * An inteface for configuring a hardware via u-boot environment. + * + * Copyright (c) 2009  MontaVista Software, Inc. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#ifndef _HWCONFIG_H +#define _HWCONFIG_H + +#include <linux/types.h> +#include <asm/errno.h> + +#ifdef CONFIG_HWCONFIG + +extern int hwconfig(const char *opt); +extern const char *hwconfig_arg(const char *opt, size_t *arglen); +extern int hwconfig_arg_cmp(const char *opt, const char *arg); +extern int hwconfig_sub(const char *opt, const char *subopt); +extern const char *hwconfig_subarg(const char *opt, const char *subopt, +				   size_t *subarglen); +extern int hwconfig_subarg_cmp(const char *opt, const char *subopt, +			       const char *subarg); + +#else + +static inline int hwconfig(const char *opt) +{ +	return -ENOSYS; +} + +static inline const char *hwconfig_arg(const char *opt, size_t *arglen) +{ +	*arglen = 0; +	return ""; +} + +static inline int hwconfig_arg_cmp(const char *opt, const char *arg) +{ +	return -ENOSYS; +} + +static inline int hwconfig_sub(const char *opt, const char *subopt) +{ +	return -ENOSYS; +} + +static inline const char *hwconfig_subarg(const char *opt, const char *subopt, +					  size_t *subarglen) +{ +	*subarglen = 0; +	return ""; +} + +static inline int hwconfig_subarg_cmp(const char *opt, const char *subopt, +				      const char *subarg) +{ +	return -ENOSYS; +} + +#endif /* CONFIG_HWCONFIG */ + +#endif /* _HWCONFIG_H */ |