1
2
3
4
5
6
7
8
9
10
11
12#ifndef HWCONFIG_TEST
13#include <config.h>
14#include <common.h>
15#include <exports.h>
16#include <hwconfig.h>
17#include <linux/types.h>
18#include <linux/string.h>
19#else
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <assert.h>
24#define min(a, b) (((a) < (b)) ? (a) : (b))
25#endif
26
27DECLARE_GLOBAL_DATA_PTR;
28
29static const char *hwconfig_parse(const char *opts, size_t maxlen,
30 const char *opt, char *stopchs, char eqch,
31 size_t *arglen)
32{
33 size_t optlen = strlen(opt);
34 char *str;
35 const char *start = opts;
36 const char *end;
37
38next:
39 str = strstr(opts, opt);
40 end = str + optlen;
41 if (end - start > maxlen)
42 return NULL;
43
44 if (str && (str == opts || strpbrk(str - 1, stopchs) == str - 1) &&
45 (strpbrk(end, stopchs) == end || *end == eqch ||
46 *end == '\0')) {
47 const char *arg_end;
48
49 if (!arglen)
50 return str;
51
52 if (*end != eqch)
53 return NULL;
54
55 arg_end = strpbrk(str, stopchs);
56 if (!arg_end)
57 *arglen = min(maxlen, strlen(str)) - optlen - 1;
58 else
59 *arglen = arg_end - end - 1;
60
61 return end + 1;
62 } else if (str) {
63 opts = end;
64 goto next;
65 }
66 return NULL;
67}
68
69const char cpu_hwconfig[] __attribute__((weak)) = "";
70const char board_hwconfig[] __attribute__((weak)) = "";
71
72static const char *__hwconfig(const char *opt, size_t *arglen,
73 const char *env_hwconfig)
74{
75 const char *ret;
76
77
78 if (!env_hwconfig) {
79 if (!(gd->flags & GD_FLG_ENV_READY)) {
80 printf("WARNING: Calling __hwconfig without a buffer "
81 "and before environment is ready\n");
82 return NULL;
83 }
84 env_hwconfig = getenv("hwconfig");
85 }
86
87 if (env_hwconfig) {
88 ret = hwconfig_parse(env_hwconfig, strlen(env_hwconfig),
89 opt, ";", ':', arglen);
90 if (ret)
91 return ret;
92 }
93
94 ret = hwconfig_parse(board_hwconfig, strlen(board_hwconfig),
95 opt, ";", ':', arglen);
96 if (ret)
97 return ret;
98
99 return hwconfig_parse(cpu_hwconfig, strlen(cpu_hwconfig),
100 opt, ";", ':', arglen);
101}
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123int hwconfig_f(const char *opt, char *buf)
124{
125 return !!__hwconfig(opt, NULL, buf);
126}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141const char *hwconfig_arg_f(const char *opt, size_t *arglen, char *buf)
142{
143 return __hwconfig(opt, arglen, buf);
144}
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160int hwconfig_arg_cmp_f(const char *opt, const char *arg, char *buf)
161{
162 const char *argstr;
163 size_t arglen;
164
165 argstr = hwconfig_arg_f(opt, &arglen, buf);
166 if (!argstr || arglen != strlen(arg))
167 return 0;
168
169 return !strncmp(argstr, arg, arglen);
170}
171
172
173
174
175
176
177
178
179
180
181
182
183
184int hwconfig_sub_f(const char *opt, const char *subopt, char *buf)
185{
186 size_t arglen;
187 const char *arg;
188
189 arg = __hwconfig(opt, &arglen, buf);
190 if (!arg)
191 return 0;
192 return !!hwconfig_parse(arg, arglen, subopt, ",;", '=', NULL);
193}
194
195
196
197
198
199
200
201
202
203
204
205const char *hwconfig_subarg_f(const char *opt, const char *subopt,
206 size_t *subarglen, char *buf)
207{
208 size_t arglen;
209 const char *arg;
210
211 arg = __hwconfig(opt, &arglen, buf);
212 if (!arg)
213 return NULL;
214 return hwconfig_parse(arg, arglen, subopt, ",;", '=', subarglen);
215}
216
217
218
219
220
221
222
223
224
225
226
227int hwconfig_subarg_cmp_f(const char *opt, const char *subopt,
228 const char *subarg, char *buf)
229{
230 const char *argstr;
231 size_t arglen;
232
233 argstr = hwconfig_subarg_f(opt, subopt, &arglen, buf);
234 if (!argstr || arglen != strlen(subarg))
235 return 0;
236
237 return !strncmp(argstr, subarg, arglen);
238}
239
240#ifdef HWCONFIG_TEST
241int main()
242{
243 const char *ret;
244 size_t len;
245
246 setenv("hwconfig", "key1:subkey1=value1,subkey2=value2;key2:value3;;;;"
247 "key3;:,:=;key4", 1);
248
249 ret = hwconfig_arg("key1", &len);
250 printf("%zd %.*s\n", len, (int)len, ret);
251 assert(len == 29);
252 assert(hwconfig_arg_cmp("key1", "subkey1=value1,subkey2=value2"));
253 assert(!strncmp(ret, "subkey1=value1,subkey2=value2", len));
254
255 ret = hwconfig_subarg("key1", "subkey1", &len);
256 printf("%zd %.*s\n", len, (int)len, ret);
257 assert(len == 6);
258 assert(hwconfig_subarg_cmp("key1", "subkey1", "value1"));
259 assert(!strncmp(ret, "value1", len));
260
261 ret = hwconfig_subarg("key1", "subkey2", &len);
262 printf("%zd %.*s\n", len, (int)len, ret);
263 assert(len == 6);
264 assert(hwconfig_subarg_cmp("key1", "subkey2", "value2"));
265 assert(!strncmp(ret, "value2", len));
266
267 ret = hwconfig_arg("key2", &len);
268 printf("%zd %.*s\n", len, (int)len, ret);
269 assert(len == 6);
270 assert(hwconfig_arg_cmp("key2", "value3"));
271 assert(!strncmp(ret, "value3", len));
272
273 assert(hwconfig("key3"));
274 assert(hwconfig_arg("key4", &len) == NULL);
275 assert(hwconfig_arg("bogus", &len) == NULL);
276
277 unsetenv("hwconfig");
278
279 assert(hwconfig(NULL) == 0);
280 assert(hwconfig("") == 0);
281 assert(hwconfig("key3") == 0);
282
283 return 0;
284}
285#endif
286