1 /* Helpers for initial module or kernel cmdline parsing
2 Copyright (C) 2001 Rusty Russell.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include <lwk/kernel.h>
19 #include <lwk/string.h>
20 #include <lwk/errno.h>
21 #include <lwk/params.h>
26 #define DEBUGP(fmt, a...)
29 static inline char dash2underscore(char c)
36 static inline int parameq(const char *input, const char *paramname)
39 for (i = 0; dash2underscore(input[i]) == paramname[i]; i++)
45 static int parse_one(char *param,
47 struct kernel_param *params,
49 int (*handle_unknown)(char *param, char *val))
52 printk("in parse_one(%s, %s)\n", param, val);
55 for (i = 0; i < num_params; i++) {
56 if (parameq(param, params[i].name)) {
57 DEBUGP("They are equal! Calling %p\n",
59 return params[i].set(val, ¶ms[i]);
64 DEBUGP("Unknown argument: calling %p\n", handle_unknown);
65 return handle_unknown(param, val);
68 /* Ignore unknown args if no handle_unknown function specified */
69 printk("Unknown argument `%s'\n", param);
73 /* You can use " around spaces, but can't escape ". */
74 /* Hyphens and underscores equivalent in parameter names. */
75 static char *next_arg(char *args, char **param, char **val)
77 unsigned int i, equals = 0;
78 int in_quote = 0, quoted = 0;
87 for (i = 0; args[i]; i++) {
88 if (args[i] == ' ' && !in_quote)
103 *val = args + equals + 1;
105 /* Don't include quotes in value. */
108 if (args[i-1] == '"')
111 if (quoted && args[i-1] == '"')
121 /* Chew up trailing spaces. */
127 /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
128 int parse_args(const char *name,
130 struct kernel_param *params,
132 int (*unknown)(char *param, char *val))
136 DEBUGP("Parsing ARGS: %s\n", args);
138 /* Chew leading spaces */
145 args = next_arg(args, ¶m, &val);
146 ret = parse_one(param, val, params, num, unknown);
149 printk(KERN_ERR "%s: Unknown parameter `%s'\n",
154 "%s: `%s' too large for parameter `%s'\n",
155 name, val ?: "", param);
161 "%s: `%s' invalid for parameter `%s'\n",
162 name, val ?: "", param);
171 /* Lazy bastard, eh? */
172 #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
173 int param_set_##name(const char *val, struct kernel_param *kp) \
178 if (!val) return -EINVAL; \
179 l = strtolfn(val, &endp, 0); \
180 if (endp == val || ((type)l != l)) \
182 *((type *)kp->arg) = l; \
185 int param_get_##name(char *buffer, struct kernel_param *kp) \
187 return sprintf(buffer, format, *((type *)kp->arg)); \
190 STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, simple_strtoul);
191 STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol);
192 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, simple_strtoul);
193 STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol);
194 STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, simple_strtoul);
195 STANDARD_PARAM_DEF(long, long, "%li", long, simple_strtol);
196 STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, simple_strtoul);
198 int param_set_charp(const char *val, struct kernel_param *kp)
201 printk(KERN_ERR "%s: string parameter expected\n",
206 if (strlen(val) > 1024) {
207 printk(KERN_ERR "%s: string parameter too long\n",
212 *(char **)kp->arg = (char *)val;
216 int param_get_charp(char *buffer, struct kernel_param *kp)
218 return sprintf(buffer, "%s", *((char **)kp->arg));
221 int param_set_bool(const char *val, struct kernel_param *kp)
223 /* No equals means "set"... */
226 /* One of =[yYnN01] */
228 case 'y': case 'Y': case '1':
231 case 'n': case 'N': case '0':
238 int param_get_bool(char *buffer, struct kernel_param *kp)
240 /* Y and N chosen as being relatively non-coder friendly */
241 return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N');
244 int param_set_invbool(const char *val, struct kernel_param *kp)
247 struct kernel_param dummy = { .arg = &boolval };
249 ret = param_set_bool(val, &dummy);
251 *(int *)kp->arg = !boolval;
255 int param_get_invbool(char *buffer, struct kernel_param *kp)
258 struct kernel_param dummy = { .arg = &val };
260 val = !*(int *)kp->arg;
261 return param_get_bool(buffer, &dummy);
264 /* We cheat here and temporarily mangle the string. */
265 static int _param_array(const char *name,
267 unsigned int min, unsigned int max,
268 void *elem, int elemsize,
269 int (*set)(const char *, struct kernel_param *kp),
273 struct kernel_param kp;
276 /* Get the name right for errors. */
280 /* No equals sign? */
282 printk(KERN_ERR "%s: expects arguments\n", name);
287 /* We expect a comma-separated list of values. */
292 printk(KERN_ERR "%s: can only take %i arguments\n",
296 len = strcspn(val, ",");
298 /* nul-terminate and parse */
300 ((char *)val)[len] = '\0';
308 } while (save == ',');
311 printk(KERN_ERR "%s: needs at least %i arguments\n",
318 int param_array_set(const char *val, struct kernel_param *kp)
320 struct kparam_array *arr = kp->arg;
321 unsigned int temp_num;
323 return _param_array(kp->name, val, 1, arr->max, arr->elem,
324 arr->elemsize, arr->set, arr->num ?: &temp_num);
327 int param_array_get(char *buffer, struct kernel_param *kp)
330 struct kparam_array *arr = kp->arg;
331 struct kernel_param p;
334 for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
337 p.arg = arr->elem + arr->elemsize * i;
338 ret = arr->get(buffer + off, &p);
347 int param_set_copystring(const char *val, struct kernel_param *kp)
349 struct kparam_string *kps = kp->arg;
351 if (strlen(val)+1 > kps->maxlen) {
352 printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
353 kp->name, kps->maxlen-1);
356 strcpy(kps->string, val);
360 int param_get_string(char *buffer, struct kernel_param *kp)
362 struct kparam_string *kps = kp->arg;
363 return strlcpy(buffer, kps->string, kps->maxlen);
367 * Parses all parameters from the input string.
369 int parse_params(const char *str)
371 struct kernel_param * params = __start___param;
372 unsigned int num_params = __stop___param - __start___param;
375 // Make a temporary copy of the string since parse_args modifies it
376 if (strlen(str)+1 > sizeof(tmp)) {
377 printk(KERN_ERR "parse_params: input string too large");
382 return parse_args("Parsing Arguments", tmp, params, num_params, NULL);
386 * Manually sets the specified parameter.
388 int param_set_by_name_int(char *param, int val)
390 struct kernel_param * params = __start___param;
391 unsigned int num_params = __stop___param - __start___param;
394 sprintf(valstr, "%d", val);
395 return parse_one(param, valstr, params, num_params, NULL);