diff --git a/common/Makefile b/common/Makefile index c8e5d26..c8a997b 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 0000000..e5c60ba --- /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 + * + * 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 +#include +#include +#include +#include +#include + +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 0000000..d517f78 --- /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 + * + * 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 +#include + +#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 */