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 <linux/moduleparam.h>
19 #include <linux/kernel.h>
20 #include <linux/string.h>
21 #include <linux/errno.h>
22 #include <linux/module.h>
27 #define DEBUGP(fmt, a...)
30 static inline int dash2underscore(char c
)
37 static inline int parameq(const char *input
, const char *paramname
)
40 for (i
= 0; dash2underscore(input
[i
]) == paramname
[i
]; i
++)
46 static int parse_one(char *param
,
48 struct kernel_param
*params
,
50 int (*handle_unknown
)(char *param
, char *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 DEBUGP("Unknown argument `%s'\n", param
);
72 /* You can use " around spaces, but can't escape ". */
73 /* Hyphens and underscores equivalent in parameter names. */
74 static char *next_arg(char *args
, char **param
, char **val
)
76 unsigned int i
, equals
= 0;
79 /* Chew any extra spaces */
80 while (*args
== ' ') args
++;
82 for (i
= 0; args
[i
]; i
++) {
83 if (args
[i
] == ' ' && !in_quote
)
98 *val
= args
+ equals
+ 1;
108 /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
109 int parse_args(const char *name
,
111 struct kernel_param
*params
,
113 int (*unknown
)(char *param
, char *val
))
117 DEBUGP("Parsing ARGS: %s\n", args
);
122 args
= next_arg(args
, ¶m
, &val
);
123 ret
= parse_one(param
, val
, params
, num
, unknown
);
126 printk(KERN_ERR
"%s: Unknown parameter `%s'\n",
131 "%s: `%s' too large for parameter `%s'\n",
132 name
, val
?: "", param
);
138 "%s: `%s' invalid for parameter `%s'\n",
139 name
, val
?: "", param
);
148 /* Lazy bastard, eh? */
149 #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
150 int param_set_##name(const char *val, struct kernel_param *kp) \
155 if (!val) return -EINVAL; \
156 l = strtolfn(val, &endp, 0); \
157 if (endp == val || *endp || ((type)l != l)) \
159 *((type *)kp->arg) = l; \
162 int param_get_##name(char *buffer, struct kernel_param *kp) \
164 return sprintf(buffer, format, *((type *)kp->arg)); \
167 STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol
);
168 STANDARD_PARAM_DEF(ushort
, unsigned short, "%hu", long, simple_strtol
);
169 STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol
);
170 STANDARD_PARAM_DEF(uint
, unsigned int, "%u", long, simple_strtol
);
171 STANDARD_PARAM_DEF(long, long, "%li", long, simple_strtol
);
172 STANDARD_PARAM_DEF(ulong
, unsigned long, "%lu", unsigned long, simple_strtoul
);
174 int param_set_charp(const char *val
, struct kernel_param
*kp
)
177 printk(KERN_ERR
"%s: string parameter expected\n",
182 if (strlen(val
) > 1024) {
183 printk(KERN_ERR
"%s: string parameter too long\n",
188 *(char **)kp
->arg
= (char *)val
;
192 int param_get_charp(char *buffer
, struct kernel_param
*kp
)
194 return sprintf(buffer
, "%s", *((char **)kp
->arg
));
197 int param_set_bool(const char *val
, struct kernel_param
*kp
)
199 /* No equals means "set"... */
202 /* One of =[yYnN01] */
204 case 'y': case 'Y': case '1':
207 case 'n': case 'N': case '0':
214 int param_get_bool(char *buffer
, struct kernel_param
*kp
)
216 /* Y and N chosen as being relatively non-coder friendly */
217 return sprintf(buffer
, "%c", (*(int *)kp
->arg
) ? 'Y' : 'N');
220 int param_set_invbool(const char *val
, struct kernel_param
*kp
)
223 struct kernel_param dummy
= { .arg
= &boolval
};
225 ret
= param_set_bool(val
, &dummy
);
227 *(int *)kp
->arg
= !boolval
;
231 int param_get_invbool(char *buffer
, struct kernel_param
*kp
)
234 struct kernel_param dummy
= { .arg
= &val
};
236 val
= !*(int *)kp
->arg
;
237 return param_get_bool(buffer
, &dummy
);
240 /* We cheat here and temporarily mangle the string. */
241 int param_array(const char *name
,
243 unsigned int min
, unsigned int max
,
244 void *elem
, int elemsize
,
245 int (*set
)(const char *, struct kernel_param
*kp
))
248 unsigned int count
= 0;
249 struct kernel_param kp
;
252 /* Get the name right for errors. */
256 /* No equals sign? */
258 printk(KERN_ERR
"%s: expects arguments\n", name
);
262 /* We expect a comma-separated list of values. */
267 printk(KERN_ERR
"%s: can only take %i arguments\n",
271 len
= strcspn(val
, ",");
273 /* nul-terminate and parse */
275 ((char *)val
)[len
] = '\0';
283 } while (save
== ',');
286 printk(KERN_ERR
"%s: needs at least %i arguments\n",
293 /* First two elements are the max and min array length (which don't change) */
294 int param_set_intarray(const char *val
, struct kernel_param
*kp
)
298 /* Grab min and max as first two elements */
300 return param_array(kp
->name
, val
, array
[0], array
[1], &array
[2],
301 sizeof(int), param_set_int
);
304 int param_get_intarray(char *buffer
, struct kernel_param
*kp
)
313 for (i
= 2; i
< max
+ 2; i
++)
314 sprintf(buffer
, "%s%i", i
> 2 ? "," : "", array
[i
]);
315 return strlen(buffer
);
318 int param_set_copystring(const char *val
, struct kernel_param
*kp
)
320 struct kparam_string
*kps
= kp
->arg
;
322 if (strlen(val
)+1 > kps
->maxlen
) {
323 printk(KERN_ERR
"%s: string doesn't fit in %u chars.\n",
324 kp
->name
, kps
->maxlen
-1);
327 strcpy(kps
->string
, val
);
331 EXPORT_SYMBOL(param_set_short
);
332 EXPORT_SYMBOL(param_get_short
);
333 EXPORT_SYMBOL(param_set_ushort
);
334 EXPORT_SYMBOL(param_get_ushort
);
335 EXPORT_SYMBOL(param_set_int
);
336 EXPORT_SYMBOL(param_get_int
);
337 EXPORT_SYMBOL(param_set_uint
);
338 EXPORT_SYMBOL(param_get_uint
);
339 EXPORT_SYMBOL(param_set_long
);
340 EXPORT_SYMBOL(param_get_long
);
341 EXPORT_SYMBOL(param_set_ulong
);
342 EXPORT_SYMBOL(param_get_ulong
);
343 EXPORT_SYMBOL(param_set_charp
);
344 EXPORT_SYMBOL(param_get_charp
);
345 EXPORT_SYMBOL(param_set_bool
);
346 EXPORT_SYMBOL(param_get_bool
);
347 EXPORT_SYMBOL(param_set_invbool
);
348 EXPORT_SYMBOL(param_get_invbool
);
349 EXPORT_SYMBOL(param_set_intarray
);
350 EXPORT_SYMBOL(param_get_intarray
);
351 EXPORT_SYMBOL(param_set_copystring
);