Blame view

common/hwconfig.c 7.74 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
2
3
4
5
  /*
   * An inteface for configuring a hardware via u-boot environment.
   *
   * Copyright (c) 2009  MontaVista Software, Inc.
dd50af251   Kumar Gala   powerpc/8xxx: Add...
6
   * Copyright 2011 Freescale Semiconductor, Inc.
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
7
8
   *
   * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
9
   */
3bf74a418   Anton Vorontsov   hwconfig: Add som...
10
  #ifndef HWCONFIG_TEST
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
11
12
13
14
15
16
  #include <config.h>
  #include <common.h>
  #include <exports.h>
  #include <hwconfig.h>
  #include <linux/types.h>
  #include <linux/string.h>
3bf74a418   Anton Vorontsov   hwconfig: Add som...
17
18
19
20
21
22
23
  #else
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <assert.h>
  #define min(a, b) (((a) < (b)) ? (a) : (b))
  #endif /* HWCONFIG_TEST */
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
24

c4b115f53   Kumar Gala   hwconfig: Utilize...
25
  DECLARE_GLOBAL_DATA_PTR;
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
26
  static const char *hwconfig_parse(const char *opts, size_t maxlen,
81f8d3b02   Anton Vorontsov   hwconfig: Fix sto...
27
  				  const char *opt, char *stopchs, char eqch,
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
28
29
30
31
32
33
34
35
36
37
38
39
  				  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;
81f8d3b02   Anton Vorontsov   hwconfig: Fix sto...
40
41
42
  	if (str && (str == opts || strpbrk(str - 1, stopchs) == str - 1) &&
  			(strpbrk(end, stopchs) == end || *end == eqch ||
  			 *end == '\0')) {
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
43
44
45
46
47
48
49
  		const char *arg_end;
  
  		if (!arglen)
  			return str;
  
  		if (*end != eqch)
  			return NULL;
81f8d3b02   Anton Vorontsov   hwconfig: Fix sto...
50
  		arg_end = strpbrk(str, stopchs);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
51
52
53
54
55
56
57
58
59
60
61
62
  		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;
  }
b194577b2   Kumar Gala   hwconfig: Fix dum...
63
64
  const char cpu_hwconfig[] __attribute__((weak)) = "";
  const char board_hwconfig[] __attribute__((weak)) = "";
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
65

dd50af251   Kumar Gala   powerpc/8xxx: Add...
66
67
  static const char *__hwconfig(const char *opt, size_t *arglen,
  			      const char *env_hwconfig)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
68
  {
dd50af251   Kumar Gala   powerpc/8xxx: Add...
69
  	const char *ret;
c4b115f53   Kumar Gala   hwconfig: Utilize...
70

dd50af251   Kumar Gala   powerpc/8xxx: Add...
71
72
73
74
  	/* if we are passed a buffer use it, otherwise try the environment */
  	if (!env_hwconfig) {
  		if (!(gd->flags & GD_FLG_ENV_READY)) {
  			printf("WARNING: Calling __hwconfig without a buffer "
d1a24f061   Wolfgang Denk   Minor Coding Styl...
75
76
77
  					"and before environment is ready
  ");
  			return NULL;
dd50af251   Kumar Gala   powerpc/8xxx: Add...
78
  		}
00caae6d4   Simon Glass   env: Rename geten...
79
  		env_hwconfig = env_get("hwconfig");
c4b115f53   Kumar Gala   hwconfig: Utilize...
80
  	}
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
81

bb141079d   Kumar Gala   hwconfig: Fix han...
82
83
  	if (env_hwconfig) {
  		ret = hwconfig_parse(env_hwconfig, strlen(env_hwconfig),
81f8d3b02   Anton Vorontsov   hwconfig: Fix sto...
84
  				      opt, ";", ':', arglen);
bb141079d   Kumar Gala   hwconfig: Fix han...
85
86
87
  		if (ret)
  			return ret;
  	}
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
88

bb141079d   Kumar Gala   hwconfig: Fix han...
89
  	ret = hwconfig_parse(board_hwconfig, strlen(board_hwconfig),
b194577b2   Kumar Gala   hwconfig: Fix dum...
90
  			opt, ";", ':', arglen);
bb141079d   Kumar Gala   hwconfig: Fix han...
91
92
  	if (ret)
  		return ret;
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
93

b194577b2   Kumar Gala   hwconfig: Fix dum...
94
95
  	return hwconfig_parse(cpu_hwconfig, strlen(cpu_hwconfig),
  			opt, ";", ':', arglen);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
96
97
98
  }
  
  /*
dd50af251   Kumar Gala   powerpc/8xxx: Add...
99
   * hwconfig_f - query if a particular hwconfig option is specified
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
100
   * @opt:	a string representing an option
dd50af251   Kumar Gala   powerpc/8xxx: Add...
101
   * @buf:	if non-NULL use this buffer to parse, otherwise try env
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
   *
   * 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.
   */
dd50af251   Kumar Gala   powerpc/8xxx: Add...
118
  int hwconfig_f(const char *opt, char *buf)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
119
  {
dd50af251   Kumar Gala   powerpc/8xxx: Add...
120
  	return !!__hwconfig(opt, NULL, buf);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
121
122
123
  }
  
  /*
dd50af251   Kumar Gala   powerpc/8xxx: Add...
124
   * hwconfig_arg_f - get hwconfig option's argument
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
125
126
   * @opt:	a string representing an option
   * @arglen:	a pointer to an allocated size_t variable
dd50af251   Kumar Gala   powerpc/8xxx: Add...
127
   * @buf:	if non-NULL use this buffer to parse, otherwise try env
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
128
   *
dd50af251   Kumar Gala   powerpc/8xxx: Add...
129
   * Unlike hwconfig_f() function, this function returns a pointer to the
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
130
131
132
133
134
135
   * 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.
   */
dd50af251   Kumar Gala   powerpc/8xxx: Add...
136
  const char *hwconfig_arg_f(const char *opt, size_t *arglen, char *buf)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
137
  {
dd50af251   Kumar Gala   powerpc/8xxx: Add...
138
  	return __hwconfig(opt, arglen, buf);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
139
140
141
  }
  
  /*
dd50af251   Kumar Gala   powerpc/8xxx: Add...
142
   * hwconfig_arg_cmp_f - compare hwconfig option's argument
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
143
144
   * @opt:	a string representing an option
   * @arg:	a string for comparing an option's argument
dd50af251   Kumar Gala   powerpc/8xxx: Add...
145
   * @buf:	if non-NULL use this buffer to parse, otherwise try env
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
146
   *
dd50af251   Kumar Gala   powerpc/8xxx: Add...
147
   * This call is similar to hwconfig_arg_f, but instead of returning
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
148
149
150
151
152
153
154
   * 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.
   */
dd50af251   Kumar Gala   powerpc/8xxx: Add...
155
  int hwconfig_arg_cmp_f(const char *opt, const char *arg, char *buf)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
156
157
158
  {
  	const char *argstr;
  	size_t arglen;
dd50af251   Kumar Gala   powerpc/8xxx: Add...
159
  	argstr = hwconfig_arg_f(opt, &arglen, buf);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
160
161
162
163
164
165
166
  	if (!argstr || arglen != strlen(arg))
  		return 0;
  
  	return !strncmp(argstr, arg, arglen);
  }
  
  /*
dd50af251   Kumar Gala   powerpc/8xxx: Add...
167
   * hwconfig_sub_f - query if a particular hwconfig sub-option is specified
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
168
169
   * @opt:	a string representing an option
   * @subopt:	a string representing a sub-option
dd50af251   Kumar Gala   powerpc/8xxx: Add...
170
   * @buf:	if non-NULL use this buffer to parse, otherwise try env
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
171
   *
dd50af251   Kumar Gala   powerpc/8xxx: Add...
172
   * This call is similar to hwconfig_f(), except that it takes additional
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
173
174
175
176
177
   * argument @subopt. In this example:
   * 	"dr_usb:mode=peripheral"
   * "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its
   * argument.
   */
dd50af251   Kumar Gala   powerpc/8xxx: Add...
178
  int hwconfig_sub_f(const char *opt, const char *subopt, char *buf)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
179
180
181
  {
  	size_t arglen;
  	const char *arg;
dd50af251   Kumar Gala   powerpc/8xxx: Add...
182
  	arg = __hwconfig(opt, &arglen, buf);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
183
184
  	if (!arg)
  		return 0;
81f8d3b02   Anton Vorontsov   hwconfig: Fix sto...
185
  	return !!hwconfig_parse(arg, arglen, subopt, ",;", '=', NULL);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
186
187
188
  }
  
  /*
dd50af251   Kumar Gala   powerpc/8xxx: Add...
189
   * hwconfig_subarg_f - get hwconfig sub-option's argument
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
190
191
192
   * @opt:	a string representing an option
   * @subopt:	a string representing a sub-option
   * @subarglen:	a pointer to an allocated size_t variable
dd50af251   Kumar Gala   powerpc/8xxx: Add...
193
   * @buf:	if non-NULL use this buffer to parse, otherwise try env
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
194
   *
dd50af251   Kumar Gala   powerpc/8xxx: Add...
195
196
   * This call is similar to hwconfig_arg_f(), except that it takes an
   * additional argument @subopt, and so works with sub-options.
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
197
   */
dd50af251   Kumar Gala   powerpc/8xxx: Add...
198
199
  const char *hwconfig_subarg_f(const char *opt, const char *subopt,
  			      size_t *subarglen, char *buf)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
200
201
202
  {
  	size_t arglen;
  	const char *arg;
dd50af251   Kumar Gala   powerpc/8xxx: Add...
203
  	arg = __hwconfig(opt, &arglen, buf);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
204
205
  	if (!arg)
  		return NULL;
81f8d3b02   Anton Vorontsov   hwconfig: Fix sto...
206
  	return hwconfig_parse(arg, arglen, subopt, ",;", '=', subarglen);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
207
208
209
  }
  
  /*
dd50af251   Kumar Gala   powerpc/8xxx: Add...
210
   * hwconfig_arg_cmp_f - compare hwconfig sub-option's argument
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
211
212
213
   * @opt:	a string representing an option
   * @subopt:	a string representing a sub-option
   * @subarg:	a string for comparing an sub-option's argument
dd50af251   Kumar Gala   powerpc/8xxx: Add...
214
   * @buf:	if non-NULL use this buffer to parse, otherwise try env
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
215
   *
dd50af251   Kumar Gala   powerpc/8xxx: Add...
216
217
   * This call is similar to hwconfig_arg_cmp_f, except that it takes an
   * additional argument @subopt, and so works with sub-options.
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
218
   */
dd50af251   Kumar Gala   powerpc/8xxx: Add...
219
220
  int hwconfig_subarg_cmp_f(const char *opt, const char *subopt,
  			  const char *subarg, char *buf)
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
221
222
223
  {
  	const char *argstr;
  	size_t arglen;
dd50af251   Kumar Gala   powerpc/8xxx: Add...
224
  	argstr = hwconfig_subarg_f(opt, subopt, &arglen, buf);
93f9dcf9e   Anton Vorontsov   Add simple hwconf...
225
226
227
228
229
  	if (!argstr || arglen != strlen(subarg))
  		return 0;
  
  	return !strncmp(argstr, subarg, arglen);
  }
3bf74a418   Anton Vorontsov   hwconfig: Add som...
230
231
232
233
234
235
  
  #ifdef HWCONFIG_TEST
  int main()
  {
  	const char *ret;
  	size_t len;
382bee57f   Simon Glass   env: Rename seten...
236
  	env_set("hwconfig", "key1:subkey1=value1,subkey2=value2;key2:value3;;;;"
3bf74a418   Anton Vorontsov   hwconfig: Add som...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  			   "key3;:,:=;key4", 1);
  
  	ret = hwconfig_arg("key1", &len);
  	printf("%zd %.*s
  ", len, (int)len, ret);
  	assert(len == 29);
  	assert(hwconfig_arg_cmp("key1", "subkey1=value1,subkey2=value2"));
  	assert(!strncmp(ret, "subkey1=value1,subkey2=value2", len));
  
  	ret = hwconfig_subarg("key1", "subkey1", &len);
  	printf("%zd %.*s
  ", len, (int)len, ret);
  	assert(len == 6);
  	assert(hwconfig_subarg_cmp("key1", "subkey1", "value1"));
  	assert(!strncmp(ret, "value1", len));
  
  	ret = hwconfig_subarg("key1", "subkey2", &len);
  	printf("%zd %.*s
  ", len, (int)len, ret);
  	assert(len == 6);
  	assert(hwconfig_subarg_cmp("key1", "subkey2", "value2"));
  	assert(!strncmp(ret, "value2", len));
  
  	ret = hwconfig_arg("key2", &len);
  	printf("%zd %.*s
  ", len, (int)len, ret);
  	assert(len == 6);
  	assert(hwconfig_arg_cmp("key2", "value3"));
  	assert(!strncmp(ret, "value3", len));
  
  	assert(hwconfig("key3"));
  	assert(hwconfig_arg("key4", &len) == NULL);
  	assert(hwconfig_arg("bogus", &len) == NULL);
382bee57f   Simon Glass   env: Rename seten...
270
  	unenv_set("hwconfig");
3bf74a418   Anton Vorontsov   hwconfig: Add som...
271
272
273
274
275
276
277
278
  
  	assert(hwconfig(NULL) == 0);
  	assert(hwconfig("") == 0);
  	assert(hwconfig("key3") == 0);
  
  	return 0;
  }
  #endif /* HWCONFIG_TEST */