xref: /rk3399_rockchip-uboot/common/hwconfig.c (revision 93f9dcf9e8b8182e97aeb7965c687176cbd0b933)
1*93f9dcf9SAnton Vorontsov /*
2*93f9dcf9SAnton Vorontsov  * An inteface for configuring a hardware via u-boot environment.
3*93f9dcf9SAnton Vorontsov  *
4*93f9dcf9SAnton Vorontsov  * Copyright (c) 2009  MontaVista Software, Inc.
5*93f9dcf9SAnton Vorontsov  *
6*93f9dcf9SAnton Vorontsov  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
7*93f9dcf9SAnton Vorontsov  *
8*93f9dcf9SAnton Vorontsov  * This program is free software; you can redistribute it and/or
9*93f9dcf9SAnton Vorontsov  * modify it under the terms of the GNU General Public License as
10*93f9dcf9SAnton Vorontsov  * published by the Free Software Foundation; either version 2 of
11*93f9dcf9SAnton Vorontsov  * the License, or (at your option) any later version.
12*93f9dcf9SAnton Vorontsov  */
13*93f9dcf9SAnton Vorontsov 
14*93f9dcf9SAnton Vorontsov #include <config.h>
15*93f9dcf9SAnton Vorontsov #include <common.h>
16*93f9dcf9SAnton Vorontsov #include <exports.h>
17*93f9dcf9SAnton Vorontsov #include <hwconfig.h>
18*93f9dcf9SAnton Vorontsov #include <linux/types.h>
19*93f9dcf9SAnton Vorontsov #include <linux/string.h>
20*93f9dcf9SAnton Vorontsov 
21*93f9dcf9SAnton Vorontsov static const char *hwconfig_parse(const char *opts, size_t maxlen,
22*93f9dcf9SAnton Vorontsov 				  const char *opt, char stopch, char eqch,
23*93f9dcf9SAnton Vorontsov 				  size_t *arglen)
24*93f9dcf9SAnton Vorontsov {
25*93f9dcf9SAnton Vorontsov 	size_t optlen = strlen(opt);
26*93f9dcf9SAnton Vorontsov 	char *str;
27*93f9dcf9SAnton Vorontsov 	const char *start = opts;
28*93f9dcf9SAnton Vorontsov 	const char *end;
29*93f9dcf9SAnton Vorontsov 
30*93f9dcf9SAnton Vorontsov next:
31*93f9dcf9SAnton Vorontsov 	str = strstr(opts, opt);
32*93f9dcf9SAnton Vorontsov 	end = str + optlen;
33*93f9dcf9SAnton Vorontsov 	if (end - start > maxlen)
34*93f9dcf9SAnton Vorontsov 		return NULL;
35*93f9dcf9SAnton Vorontsov 
36*93f9dcf9SAnton Vorontsov 	if (str && (str == opts || str[-1] == stopch) &&
37*93f9dcf9SAnton Vorontsov 			(*end == stopch || *end == eqch || *end == '\0')) {
38*93f9dcf9SAnton Vorontsov 		const char *arg_end;
39*93f9dcf9SAnton Vorontsov 
40*93f9dcf9SAnton Vorontsov 		if (!arglen)
41*93f9dcf9SAnton Vorontsov 			return str;
42*93f9dcf9SAnton Vorontsov 
43*93f9dcf9SAnton Vorontsov 		if (*end != eqch)
44*93f9dcf9SAnton Vorontsov 			return NULL;
45*93f9dcf9SAnton Vorontsov 
46*93f9dcf9SAnton Vorontsov 		arg_end = strchr(str, stopch);
47*93f9dcf9SAnton Vorontsov 		if (!arg_end)
48*93f9dcf9SAnton Vorontsov 			*arglen = min(maxlen, strlen(str)) - optlen - 1;
49*93f9dcf9SAnton Vorontsov 		else
50*93f9dcf9SAnton Vorontsov 			*arglen = arg_end - end - 1;
51*93f9dcf9SAnton Vorontsov 
52*93f9dcf9SAnton Vorontsov 		return end + 1;
53*93f9dcf9SAnton Vorontsov 	} else if (str) {
54*93f9dcf9SAnton Vorontsov 		opts = end;
55*93f9dcf9SAnton Vorontsov 		goto next;
56*93f9dcf9SAnton Vorontsov 	}
57*93f9dcf9SAnton Vorontsov 	return NULL;
58*93f9dcf9SAnton Vorontsov }
59*93f9dcf9SAnton Vorontsov 
60*93f9dcf9SAnton Vorontsov const char *cpu_hwconfig __attribute__((weak));
61*93f9dcf9SAnton Vorontsov const char *board_hwconfig __attribute__((weak));
62*93f9dcf9SAnton Vorontsov 
63*93f9dcf9SAnton Vorontsov static const char *__hwconfig(const char *opt, size_t *arglen)
64*93f9dcf9SAnton Vorontsov {
65*93f9dcf9SAnton Vorontsov 	const char *env_hwconfig = getenv("hwconfig");
66*93f9dcf9SAnton Vorontsov 
67*93f9dcf9SAnton Vorontsov 	if (env_hwconfig)
68*93f9dcf9SAnton Vorontsov 		return hwconfig_parse(env_hwconfig, strlen(env_hwconfig),
69*93f9dcf9SAnton Vorontsov 				      opt, ';', ':', arglen);
70*93f9dcf9SAnton Vorontsov 
71*93f9dcf9SAnton Vorontsov 	if (board_hwconfig)
72*93f9dcf9SAnton Vorontsov 		return hwconfig_parse(board_hwconfig, strlen(board_hwconfig),
73*93f9dcf9SAnton Vorontsov 				      opt, ';', ':', arglen);
74*93f9dcf9SAnton Vorontsov 
75*93f9dcf9SAnton Vorontsov 	if (cpu_hwconfig)
76*93f9dcf9SAnton Vorontsov 		return hwconfig_parse(cpu_hwconfig, strlen(cpu_hwconfig),
77*93f9dcf9SAnton Vorontsov 				      opt, ';', ':', arglen);
78*93f9dcf9SAnton Vorontsov 
79*93f9dcf9SAnton Vorontsov 	return NULL;
80*93f9dcf9SAnton Vorontsov }
81*93f9dcf9SAnton Vorontsov 
82*93f9dcf9SAnton Vorontsov /*
83*93f9dcf9SAnton Vorontsov  * hwconfig - query if a particular hwconfig option is specified
84*93f9dcf9SAnton Vorontsov  * @opt:	a string representing an option
85*93f9dcf9SAnton Vorontsov  *
86*93f9dcf9SAnton Vorontsov  * This call can be used to find out whether U-Boot should configure
87*93f9dcf9SAnton Vorontsov  * a particular hardware option.
88*93f9dcf9SAnton Vorontsov  *
89*93f9dcf9SAnton Vorontsov  * Returns non-zero value if the hardware option can be used and thus
90*93f9dcf9SAnton Vorontsov  * should be configured, 0 otherwise.
91*93f9dcf9SAnton Vorontsov  *
92*93f9dcf9SAnton Vorontsov  * This function also returns non-zero value if CONFIG_HWCONFIG is
93*93f9dcf9SAnton Vorontsov  * undefined.
94*93f9dcf9SAnton Vorontsov  *
95*93f9dcf9SAnton Vorontsov  * Returning non-zero value without CONFIG_HWCONFIG has its crucial
96*93f9dcf9SAnton Vorontsov  * purpose: the hwconfig() call should be a "transparent" interface,
97*93f9dcf9SAnton Vorontsov  * e.g. if a board doesn't need hwconfig facility, then we assume
98*93f9dcf9SAnton Vorontsov  * that the board file only calls things that are actually used, so
99*93f9dcf9SAnton Vorontsov  * hwconfig() will always return true result.
100*93f9dcf9SAnton Vorontsov  */
101*93f9dcf9SAnton Vorontsov int hwconfig(const char *opt)
102*93f9dcf9SAnton Vorontsov {
103*93f9dcf9SAnton Vorontsov 	return !!__hwconfig(opt, NULL);
104*93f9dcf9SAnton Vorontsov }
105*93f9dcf9SAnton Vorontsov 
106*93f9dcf9SAnton Vorontsov /*
107*93f9dcf9SAnton Vorontsov  * hwconfig_arg - get hwconfig option's argument
108*93f9dcf9SAnton Vorontsov  * @opt:	a string representing an option
109*93f9dcf9SAnton Vorontsov  * @arglen:	a pointer to an allocated size_t variable
110*93f9dcf9SAnton Vorontsov  *
111*93f9dcf9SAnton Vorontsov  * Unlike hwconfig() function, this function returns a pointer to the
112*93f9dcf9SAnton Vorontsov  * start of the hwconfig arguments, if option is not found or it has
113*93f9dcf9SAnton Vorontsov  * no specified arguments, the function returns NULL pointer.
114*93f9dcf9SAnton Vorontsov  *
115*93f9dcf9SAnton Vorontsov  * If CONFIG_HWCONFIG is undefined, the function returns "", and
116*93f9dcf9SAnton Vorontsov  * arglen is set to 0.
117*93f9dcf9SAnton Vorontsov  */
118*93f9dcf9SAnton Vorontsov const char *hwconfig_arg(const char *opt, size_t *arglen)
119*93f9dcf9SAnton Vorontsov {
120*93f9dcf9SAnton Vorontsov 	return __hwconfig(opt, arglen);
121*93f9dcf9SAnton Vorontsov }
122*93f9dcf9SAnton Vorontsov 
123*93f9dcf9SAnton Vorontsov /*
124*93f9dcf9SAnton Vorontsov  * hwconfig_arg_cmp - compare hwconfig option's argument
125*93f9dcf9SAnton Vorontsov  * @opt:	a string representing an option
126*93f9dcf9SAnton Vorontsov  * @arg:	a string for comparing an option's argument
127*93f9dcf9SAnton Vorontsov  *
128*93f9dcf9SAnton Vorontsov  * This call is similar to hwconfig_arg, but instead of returning
129*93f9dcf9SAnton Vorontsov  * hwconfig argument and its length, it is comparing it to @arg.
130*93f9dcf9SAnton Vorontsov  *
131*93f9dcf9SAnton Vorontsov  * Returns non-zero value if @arg matches, 0 otherwise.
132*93f9dcf9SAnton Vorontsov  *
133*93f9dcf9SAnton Vorontsov  * If CONFIG_HWCONFIG is undefined, the function returns a non-zero
134*93f9dcf9SAnton Vorontsov  * value, i.e. the argument matches.
135*93f9dcf9SAnton Vorontsov  */
136*93f9dcf9SAnton Vorontsov int hwconfig_arg_cmp(const char *opt, const char *arg)
137*93f9dcf9SAnton Vorontsov {
138*93f9dcf9SAnton Vorontsov 	const char *argstr;
139*93f9dcf9SAnton Vorontsov 	size_t arglen;
140*93f9dcf9SAnton Vorontsov 
141*93f9dcf9SAnton Vorontsov 	argstr = hwconfig_arg(opt, &arglen);
142*93f9dcf9SAnton Vorontsov 	if (!argstr || arglen != strlen(arg))
143*93f9dcf9SAnton Vorontsov 		return 0;
144*93f9dcf9SAnton Vorontsov 
145*93f9dcf9SAnton Vorontsov 	return !strncmp(argstr, arg, arglen);
146*93f9dcf9SAnton Vorontsov }
147*93f9dcf9SAnton Vorontsov 
148*93f9dcf9SAnton Vorontsov /*
149*93f9dcf9SAnton Vorontsov  * hwconfig_sub - query if a particular hwconfig sub-option is specified
150*93f9dcf9SAnton Vorontsov  * @opt:	a string representing an option
151*93f9dcf9SAnton Vorontsov  * @subopt:	a string representing a sub-option
152*93f9dcf9SAnton Vorontsov  *
153*93f9dcf9SAnton Vorontsov  * This call is similar to hwconfig(), except that it takes additional
154*93f9dcf9SAnton Vorontsov  * argument @subopt. In this example:
155*93f9dcf9SAnton Vorontsov  * 	"dr_usb:mode=peripheral"
156*93f9dcf9SAnton Vorontsov  * "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its
157*93f9dcf9SAnton Vorontsov  * argument.
158*93f9dcf9SAnton Vorontsov  */
159*93f9dcf9SAnton Vorontsov int hwconfig_sub(const char *opt, const char *subopt)
160*93f9dcf9SAnton Vorontsov {
161*93f9dcf9SAnton Vorontsov 	size_t arglen;
162*93f9dcf9SAnton Vorontsov 	const char *arg;
163*93f9dcf9SAnton Vorontsov 
164*93f9dcf9SAnton Vorontsov 	arg = __hwconfig(opt, &arglen);
165*93f9dcf9SAnton Vorontsov 	if (!arg)
166*93f9dcf9SAnton Vorontsov 		return 0;
167*93f9dcf9SAnton Vorontsov 	return !!hwconfig_parse(arg, arglen, subopt, ',', '=', NULL);
168*93f9dcf9SAnton Vorontsov }
169*93f9dcf9SAnton Vorontsov 
170*93f9dcf9SAnton Vorontsov /*
171*93f9dcf9SAnton Vorontsov  * hwconfig_subarg - get hwconfig sub-option's argument
172*93f9dcf9SAnton Vorontsov  * @opt:	a string representing an option
173*93f9dcf9SAnton Vorontsov  * @subopt:	a string representing a sub-option
174*93f9dcf9SAnton Vorontsov  * @subarglen:	a pointer to an allocated size_t variable
175*93f9dcf9SAnton Vorontsov  *
176*93f9dcf9SAnton Vorontsov  * This call is similar to hwconfig_arg(), except that it takes an additional
177*93f9dcf9SAnton Vorontsov  * argument @subopt, and so works with sub-options.
178*93f9dcf9SAnton Vorontsov  */
179*93f9dcf9SAnton Vorontsov const char *hwconfig_subarg(const char *opt, const char *subopt,
180*93f9dcf9SAnton Vorontsov 			    size_t *subarglen)
181*93f9dcf9SAnton Vorontsov {
182*93f9dcf9SAnton Vorontsov 	size_t arglen;
183*93f9dcf9SAnton Vorontsov 	const char *arg;
184*93f9dcf9SAnton Vorontsov 
185*93f9dcf9SAnton Vorontsov 	arg = __hwconfig(opt, &arglen);
186*93f9dcf9SAnton Vorontsov 	if (!arg)
187*93f9dcf9SAnton Vorontsov 		return NULL;
188*93f9dcf9SAnton Vorontsov 	return hwconfig_parse(arg, arglen, subopt, ',', '=', subarglen);
189*93f9dcf9SAnton Vorontsov }
190*93f9dcf9SAnton Vorontsov 
191*93f9dcf9SAnton Vorontsov /*
192*93f9dcf9SAnton Vorontsov  * hwconfig_arg_cmp - compare hwconfig sub-option's argument
193*93f9dcf9SAnton Vorontsov  * @opt:	a string representing an option
194*93f9dcf9SAnton Vorontsov  * @subopt:	a string representing a sub-option
195*93f9dcf9SAnton Vorontsov  * @subarg:	a string for comparing an sub-option's argument
196*93f9dcf9SAnton Vorontsov  *
197*93f9dcf9SAnton Vorontsov  * This call is similar to hwconfig_arg_cmp, except that it takes an additional
198*93f9dcf9SAnton Vorontsov  * argument @subopt, and so works with sub-options.
199*93f9dcf9SAnton Vorontsov  */
200*93f9dcf9SAnton Vorontsov int hwconfig_subarg_cmp(const char *opt, const char *subopt, const char *subarg)
201*93f9dcf9SAnton Vorontsov {
202*93f9dcf9SAnton Vorontsov 	const char *argstr;
203*93f9dcf9SAnton Vorontsov 	size_t arglen;
204*93f9dcf9SAnton Vorontsov 
205*93f9dcf9SAnton Vorontsov 	argstr = hwconfig_subarg(opt, subopt, &arglen);
206*93f9dcf9SAnton Vorontsov 	if (!argstr || arglen != strlen(subarg))
207*93f9dcf9SAnton Vorontsov 		return 0;
208*93f9dcf9SAnton Vorontsov 
209*93f9dcf9SAnton Vorontsov 	return !strncmp(argstr, subarg, arglen);
210*93f9dcf9SAnton Vorontsov }
211