Skip to content
Snippets Groups Projects
hwconfig.c 5.62 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * 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);
    }