Branch data Line data Source code
1 : : /* Helpers for initial module or kernel cmdline parsing
2 : : Copyright (C) 2001 Rusty Russell.
3 : :
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.
8 : :
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.
13 : :
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
17 : : */
18 : : #include <linux/kernel.h>
19 : : #include <linux/string.h>
20 : : #include <linux/errno.h>
21 : : #include <linux/module.h>
22 : : #include <linux/device.h>
23 : : #include <linux/err.h>
24 : : #include <linux/slab.h>
25 : : #include <linux/ctype.h>
26 : :
27 : : /* Protects all parameters, and incidentally kmalloced_param list. */
28 : : static DEFINE_MUTEX(param_lock);
29 : :
30 : : /* This just allows us to keep track of which parameters are kmalloced. */
31 : : struct kmalloced_param {
32 : : struct list_head list;
33 : : char val[];
34 : : };
35 : : static LIST_HEAD(kmalloced_params);
36 : :
37 : 0 : static void *kmalloc_parameter(unsigned int size)
38 : : {
39 : : struct kmalloced_param *p;
40 : :
41 : 0 : p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
42 [ # # ]: 0 : if (!p)
43 : : return NULL;
44 : :
45 : 0 : list_add(&p->list, &kmalloced_params);
46 : 0 : return p->val;
47 : : }
48 : :
49 : : /* Does nothing if parameter wasn't kmalloced above. */
50 : 0 : static void maybe_kfree_parameter(void *param)
51 : : {
52 : : struct kmalloced_param *p;
53 : :
54 [ # # ]: 0 : list_for_each_entry(p, &kmalloced_params, list) {
55 [ # # ]: 0 : if (p->val == param) {
56 : : list_del(&p->list);
57 : 0 : kfree(p);
58 : 0 : break;
59 : : }
60 : : }
61 : 0 : }
62 : :
63 : : static char dash2underscore(char c)
64 : : {
65 [ # # ][ # # ]: 0 : if (c == '-')
[ # # ][ # # ]
66 : : return '_';
67 : : return c;
68 : : }
69 : :
70 : 0 : bool parameqn(const char *a, const char *b, size_t n)
71 : : {
72 : : size_t i;
73 : :
74 [ # # ][ # # ]: 0 : for (i = 0; i < n; i++) {
75 [ # # ][ # # ]: 0 : if (dash2underscore(a[i]) != dash2underscore(b[i]))
76 : : return false;
77 : : }
78 : : return true;
79 : : }
80 : :
81 : 0 : bool parameq(const char *a, const char *b)
82 : : {
83 : 0 : return parameqn(a, b, strlen(a)+1);
84 : : }
85 : :
86 : 0 : static int parse_one(char *param,
87 : : char *val,
88 : : const char *doing,
89 : : const struct kernel_param *params,
90 : : unsigned num_params,
91 : : s16 min_level,
92 : : s16 max_level,
93 : : int (*handle_unknown)(char *param, char *val,
94 : : const char *doing))
95 : : {
96 : : unsigned int i;
97 : : int err;
98 : :
99 : : /* Find parameter */
100 [ # # ]: 0 : for (i = 0; i < num_params; i++) {
101 [ # # ]: 0 : if (parameq(param, params[i].name)) {
102 [ # # ]: 0 : if (params[i].level < min_level
103 [ # # ]: 0 : || params[i].level > max_level)
104 : : return 0;
105 : : /* No one handled NULL, so do it here. */
106 [ # # ][ # # ]: 0 : if (!val &&
107 : 0 : !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
108 : : return -EINVAL;
109 : : pr_debug("handling %s with %p\n", param,
110 : : params[i].ops->set);
111 : 0 : mutex_lock(¶m_lock);
112 : 0 : err = params[i].ops->set(val, ¶ms[i]);
113 : 0 : mutex_unlock(¶m_lock);
114 : 0 : return err;
115 : : }
116 : : }
117 : :
118 [ # # ]: 0 : if (handle_unknown) {
119 : : pr_debug("doing %s: %s='%s'\n", doing, param, val);
120 : 0 : return handle_unknown(param, val, doing);
121 : : }
122 : :
123 : : pr_debug("Unknown argument '%s'\n", param);
124 : : return -ENOENT;
125 : : }
126 : :
127 : : /* You can use " around spaces, but can't escape ". */
128 : : /* Hyphens and underscores equivalent in parameter names. */
129 : 0 : static char *next_arg(char *args, char **param, char **val)
130 : : {
131 : : unsigned int i, equals = 0;
132 : : int in_quote = 0, quoted = 0;
133 : : char *next;
134 : :
135 [ # # ]: 0 : if (*args == '"') {
136 : 0 : args++;
137 : : in_quote = 1;
138 : : quoted = 1;
139 : : }
140 : :
141 [ # # ]: 0 : for (i = 0; args[i]; i++) {
142 [ # # ][ # # ]: 0 : if (isspace(args[i]) && !in_quote)
143 : : break;
144 [ # # ]: 0 : if (equals == 0) {
145 [ # # ]: 0 : if (args[i] == '=')
146 : : equals = i;
147 : : }
148 [ # # ]: 0 : if (args[i] == '"')
149 : 0 : in_quote = !in_quote;
150 : : }
151 : :
152 : 0 : *param = args;
153 [ # # ]: 0 : if (!equals)
154 : 0 : *val = NULL;
155 : : else {
156 : 0 : args[equals] = '\0';
157 : 0 : *val = args + equals + 1;
158 : :
159 : : /* Don't include quotes in value. */
160 [ # # ]: 0 : if (**val == '"') {
161 : 0 : (*val)++;
162 [ # # ]: 0 : if (args[i-1] == '"')
163 : 0 : args[i-1] = '\0';
164 : : }
165 [ # # ][ # # ]: 0 : if (quoted && args[i-1] == '"')
166 : 0 : args[i-1] = '\0';
167 : : }
168 : :
169 [ # # ]: 0 : if (args[i]) {
170 : 0 : args[i] = '\0';
171 : 0 : next = args + i + 1;
172 : : } else
173 : : next = args + i;
174 : :
175 : : /* Chew up trailing spaces. */
176 : 0 : return skip_spaces(next);
177 : : }
178 : :
179 : : /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
180 : 0 : int parse_args(const char *doing,
181 : : char *args,
182 : : const struct kernel_param *params,
183 : : unsigned num,
184 : : s16 min_level,
185 : : s16 max_level,
186 : : int (*unknown)(char *param, char *val, const char *doing))
187 : : {
188 : : char *param, *val;
189 : :
190 : : /* Chew leading spaces */
191 : 0 : args = skip_spaces(args);
192 : :
193 : : if (*args)
194 : : pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args);
195 : :
196 [ # # ]: 0 : while (*args) {
197 : : int ret;
198 : : int irq_was_disabled;
199 : :
200 : 0 : args = next_arg(args, ¶m, &val);
201 : : irq_was_disabled = irqs_disabled();
202 : 0 : ret = parse_one(param, val, doing, params, num,
203 : : min_level, max_level, unknown);
204 [ # # # # ]: 0 : if (irq_was_disabled && !irqs_disabled())
205 : 0 : pr_warn("%s: option '%s' enabled irq's!\n",
206 : : doing, param);
207 : :
208 [ # # # # ]: 0 : switch (ret) {
209 : : case -ENOENT:
210 : 0 : pr_err("%s: Unknown parameter `%s'\n", doing, param);
211 : 0 : return ret;
212 : : case -ENOSPC:
213 [ # # ]: 0 : pr_err("%s: `%s' too large for parameter `%s'\n",
214 : : doing, val ?: "", param);
215 : 0 : return ret;
216 : : case 0:
217 : : break;
218 : : default:
219 [ # # ]: 0 : pr_err("%s: `%s' invalid for parameter `%s'\n",
220 : : doing, val ?: "", param);
221 : 0 : return ret;
222 : : }
223 : : }
224 : :
225 : : /* All parsed OK. */
226 : : return 0;
227 : : }
228 : :
229 : : /* Lazy bastard, eh? */
230 : : #define STANDARD_PARAM_DEF(name, type, format, strtolfn) \
231 : : int param_set_##name(const char *val, const struct kernel_param *kp) \
232 : : { \
233 : : return strtolfn(val, 0, (type *)kp->arg); \
234 : : } \
235 : : int param_get_##name(char *buffer, const struct kernel_param *kp) \
236 : : { \
237 : : return scnprintf(buffer, PAGE_SIZE, format, \
238 : : *((type *)kp->arg)); \
239 : : } \
240 : : struct kernel_param_ops param_ops_##name = { \
241 : : .set = param_set_##name, \
242 : : .get = param_get_##name, \
243 : : }; \
244 : : EXPORT_SYMBOL(param_set_##name); \
245 : : EXPORT_SYMBOL(param_get_##name); \
246 : : EXPORT_SYMBOL(param_ops_##name)
247 : :
248 : :
249 : 0 : STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
250 : 0 : STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
251 : 0 : STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
252 : 0 : STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
253 : 0 : STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
254 : 0 : STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
255 : 0 : STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
256 : :
257 : 0 : int param_set_charp(const char *val, const struct kernel_param *kp)
258 : : {
259 [ # # ]: 0 : if (strlen(val) > 1024) {
260 : 0 : pr_err("%s: string parameter too long\n", kp->name);
261 : 0 : return -ENOSPC;
262 : : }
263 : :
264 : 0 : maybe_kfree_parameter(*(char **)kp->arg);
265 : :
266 : : /* This is a hack. We can't kmalloc in early boot, and we
267 : : * don't need to; this mangled commandline is preserved. */
268 [ # # ]: 0 : if (slab_is_available()) {
269 : 0 : *(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
270 [ # # ]: 0 : if (!*(char **)kp->arg)
271 : : return -ENOMEM;
272 : 0 : strcpy(*(char **)kp->arg, val);
273 : : } else
274 : 0 : *(const char **)kp->arg = val;
275 : :
276 : : return 0;
277 : : }
278 : : EXPORT_SYMBOL(param_set_charp);
279 : :
280 : 0 : int param_get_charp(char *buffer, const struct kernel_param *kp)
281 : : {
282 : 0 : return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
283 : : }
284 : : EXPORT_SYMBOL(param_get_charp);
285 : :
286 : 0 : static void param_free_charp(void *arg)
287 : : {
288 : 0 : maybe_kfree_parameter(*((char **)arg));
289 : 0 : }
290 : :
291 : : struct kernel_param_ops param_ops_charp = {
292 : : .set = param_set_charp,
293 : : .get = param_get_charp,
294 : : .free = param_free_charp,
295 : : };
296 : : EXPORT_SYMBOL(param_ops_charp);
297 : :
298 : : /* Actually could be a bool or an int, for historical reasons. */
299 : 0 : int param_set_bool(const char *val, const struct kernel_param *kp)
300 : : {
301 : : /* No equals means "set"... */
302 [ # # ][ # # ]: 0 : if (!val) val = "1";
[ # # ]
303 : :
304 : : /* One of =[yYnN01] */
305 : 0 : return strtobool(val, kp->arg);
306 : : }
307 : : EXPORT_SYMBOL(param_set_bool);
308 : :
309 : 0 : int param_get_bool(char *buffer, const struct kernel_param *kp)
310 : : {
311 : : /* Y and N chosen as being relatively non-coder friendly */
312 [ # # ]: 0 : return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
313 : : }
314 : : EXPORT_SYMBOL(param_get_bool);
315 : :
316 : : struct kernel_param_ops param_ops_bool = {
317 : : .flags = KERNEL_PARAM_FL_NOARG,
318 : : .set = param_set_bool,
319 : : .get = param_get_bool,
320 : : };
321 : : EXPORT_SYMBOL(param_ops_bool);
322 : :
323 : : /* This one must be bool. */
324 : 0 : int param_set_invbool(const char *val, const struct kernel_param *kp)
325 : : {
326 : : int ret;
327 : : bool boolval;
328 : : struct kernel_param dummy;
329 : :
330 : : dummy.arg = &boolval;
331 : : ret = param_set_bool(val, &dummy);
332 [ # # ]: 0 : if (ret == 0)
333 : 0 : *(bool *)kp->arg = !boolval;
334 : 0 : return ret;
335 : : }
336 : : EXPORT_SYMBOL(param_set_invbool);
337 : :
338 : 0 : int param_get_invbool(char *buffer, const struct kernel_param *kp)
339 : : {
340 [ # # ]: 0 : return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y');
341 : : }
342 : : EXPORT_SYMBOL(param_get_invbool);
343 : :
344 : : struct kernel_param_ops param_ops_invbool = {
345 : : .set = param_set_invbool,
346 : : .get = param_get_invbool,
347 : : };
348 : : EXPORT_SYMBOL(param_ops_invbool);
349 : :
350 : 0 : int param_set_bint(const char *val, const struct kernel_param *kp)
351 : : {
352 : : struct kernel_param boolkp;
353 : : bool v;
354 : : int ret;
355 : :
356 : : /* Match bool exactly, by re-using it. */
357 : : boolkp = *kp;
358 : : boolkp.arg = &v;
359 : :
360 : : ret = param_set_bool(val, &boolkp);
361 [ # # ]: 0 : if (ret == 0)
362 : 0 : *(int *)kp->arg = v;
363 : 0 : return ret;
364 : : }
365 : : EXPORT_SYMBOL(param_set_bint);
366 : :
367 : : struct kernel_param_ops param_ops_bint = {
368 : : .flags = KERNEL_PARAM_FL_NOARG,
369 : : .set = param_set_bint,
370 : : .get = param_get_int,
371 : : };
372 : : EXPORT_SYMBOL(param_ops_bint);
373 : :
374 : : /* We break the rule and mangle the string. */
375 : 0 : static int param_array(const char *name,
376 : : const char *val,
377 : : unsigned int min, unsigned int max,
378 : : void *elem, int elemsize,
379 : : int (*set)(const char *, const struct kernel_param *kp),
380 : : s16 level,
381 : : unsigned int *num)
382 : : {
383 : : int ret;
384 : : struct kernel_param kp;
385 : : char save;
386 : :
387 : : /* Get the name right for errors. */
388 : 0 : kp.name = name;
389 : 0 : kp.arg = elem;
390 : 0 : kp.level = level;
391 : :
392 : 0 : *num = 0;
393 : : /* We expect a comma-separated list of values. */
394 : : do {
395 : : int len;
396 : :
397 [ # # ]: 0 : if (*num == max) {
398 : 0 : pr_err("%s: can only take %i arguments\n", name, max);
399 : 0 : return -EINVAL;
400 : : }
401 : 0 : len = strcspn(val, ",");
402 : :
403 : : /* nul-terminate and parse */
404 : 0 : save = val[len];
405 : 0 : ((char *)val)[len] = '\0';
406 [ # # ]: 0 : BUG_ON(!mutex_is_locked(¶m_lock));
407 : 0 : ret = set(val, &kp);
408 : :
409 [ # # ]: 0 : if (ret != 0)
410 : : return ret;
411 : 0 : kp.arg += elemsize;
412 : 0 : val += len+1;
413 : 0 : (*num)++;
414 [ # # ]: 0 : } while (save == ',');
415 : :
416 [ # # ]: 0 : if (*num < min) {
417 : 0 : pr_err("%s: needs at least %i arguments\n", name, min);
418 : 0 : return -EINVAL;
419 : : }
420 : : return 0;
421 : : }
422 : :
423 : 0 : static int param_array_set(const char *val, const struct kernel_param *kp)
424 : : {
425 : 0 : const struct kparam_array *arr = kp->arr;
426 : : unsigned int temp_num;
427 : :
428 [ # # ]: 0 : return param_array(kp->name, val, 1, arr->max, arr->elem,
429 : 0 : arr->elemsize, arr->ops->set, kp->level,
430 : 0 : arr->num ?: &temp_num);
431 : : }
432 : :
433 : 0 : static int param_array_get(char *buffer, const struct kernel_param *kp)
434 : : {
435 : : int i, off, ret;
436 : 0 : const struct kparam_array *arr = kp->arr;
437 : : struct kernel_param p;
438 : :
439 : 0 : p = *kp;
440 [ # # ][ # # ]: 0 : for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
441 [ # # ]: 0 : if (i)
442 : 0 : buffer[off++] = ',';
443 : 0 : p.arg = arr->elem + arr->elemsize * i;
444 [ # # ]: 0 : BUG_ON(!mutex_is_locked(¶m_lock));
445 : 0 : ret = arr->ops->get(buffer + off, &p);
446 [ # # ]: 0 : if (ret < 0)
447 : : return ret;
448 : 0 : off += ret;
449 : : }
450 : 0 : buffer[off] = '\0';
451 : 0 : return off;
452 : : }
453 : :
454 : 0 : static void param_array_free(void *arg)
455 : : {
456 : : unsigned int i;
457 : : const struct kparam_array *arr = arg;
458 : :
459 [ # # ]: 0 : if (arr->ops->free)
460 [ # # ][ # # ]: 0 : for (i = 0; i < (arr->num ? *arr->num : arr->max); i++)
461 : 0 : arr->ops->free(arr->elem + arr->elemsize * i);
462 : 0 : }
463 : :
464 : : struct kernel_param_ops param_array_ops = {
465 : : .set = param_array_set,
466 : : .get = param_array_get,
467 : : .free = param_array_free,
468 : : };
469 : : EXPORT_SYMBOL(param_array_ops);
470 : :
471 : 0 : int param_set_copystring(const char *val, const struct kernel_param *kp)
472 : : {
473 : 0 : const struct kparam_string *kps = kp->str;
474 : :
475 [ # # ]: 0 : if (strlen(val)+1 > kps->maxlen) {
476 : 0 : pr_err("%s: string doesn't fit in %u chars.\n",
477 : : kp->name, kps->maxlen-1);
478 : 0 : return -ENOSPC;
479 : : }
480 : 0 : strcpy(kps->string, val);
481 : 0 : return 0;
482 : : }
483 : : EXPORT_SYMBOL(param_set_copystring);
484 : :
485 : 0 : int param_get_string(char *buffer, const struct kernel_param *kp)
486 : : {
487 : 0 : const struct kparam_string *kps = kp->str;
488 : 0 : return strlcpy(buffer, kps->string, kps->maxlen);
489 : : }
490 : : EXPORT_SYMBOL(param_get_string);
491 : :
492 : : struct kernel_param_ops param_ops_string = {
493 : : .set = param_set_copystring,
494 : : .get = param_get_string,
495 : : };
496 : : EXPORT_SYMBOL(param_ops_string);
497 : :
498 : : /* sysfs output in /sys/modules/XYZ/parameters/ */
499 : : #define to_module_attr(n) container_of(n, struct module_attribute, attr)
500 : : #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
501 : :
502 : : extern struct kernel_param __start___param[], __stop___param[];
503 : :
504 : : struct param_attribute
505 : : {
506 : : struct module_attribute mattr;
507 : : const struct kernel_param *param;
508 : : };
509 : :
510 : : struct module_param_attrs
511 : : {
512 : : unsigned int num;
513 : : struct attribute_group grp;
514 : : struct param_attribute attrs[0];
515 : : };
516 : :
517 : : #ifdef CONFIG_SYSFS
518 : : #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
519 : :
520 : 0 : static ssize_t param_attr_show(struct module_attribute *mattr,
521 : : struct module_kobject *mk, char *buf)
522 : : {
523 : : int count;
524 : : struct param_attribute *attribute = to_param_attr(mattr);
525 : :
526 [ # # ]: 0 : if (!attribute->param->ops->get)
527 : : return -EPERM;
528 : :
529 : 0 : mutex_lock(¶m_lock);
530 : 0 : count = attribute->param->ops->get(buf, attribute->param);
531 : 0 : mutex_unlock(¶m_lock);
532 [ # # ]: 0 : if (count > 0) {
533 : 0 : strcat(buf, "\n");
534 : 0 : ++count;
535 : : }
536 : 0 : return count;
537 : : }
538 : :
539 : : /* sysfs always hands a nul-terminated string in buf. We rely on that. */
540 : 0 : static ssize_t param_attr_store(struct module_attribute *mattr,
541 : : struct module_kobject *km,
542 : : const char *buf, size_t len)
543 : : {
544 : : int err;
545 : : struct param_attribute *attribute = to_param_attr(mattr);
546 : :
547 [ # # ]: 0 : if (!attribute->param->ops->set)
548 : : return -EPERM;
549 : :
550 : 0 : mutex_lock(¶m_lock);
551 : 0 : err = attribute->param->ops->set(buf, attribute->param);
552 : 0 : mutex_unlock(¶m_lock);
553 [ # # ]: 0 : if (!err)
554 : 0 : return len;
555 : : return err;
556 : : }
557 : : #endif
558 : :
559 : : #ifdef CONFIG_MODULES
560 : : #define __modinit
561 : : #else
562 : : #define __modinit __init
563 : : #endif
564 : :
565 : : #ifdef CONFIG_SYSFS
566 : 0 : void __kernel_param_lock(void)
567 : : {
568 : 0 : mutex_lock(¶m_lock);
569 : 0 : }
570 : : EXPORT_SYMBOL(__kernel_param_lock);
571 : :
572 : 0 : void __kernel_param_unlock(void)
573 : : {
574 : 0 : mutex_unlock(¶m_lock);
575 : 0 : }
576 : : EXPORT_SYMBOL(__kernel_param_unlock);
577 : :
578 : : /*
579 : : * add_sysfs_param - add a parameter to sysfs
580 : : * @mk: struct module_kobject
581 : : * @kparam: the actual parameter definition to add to sysfs
582 : : * @name: name of parameter
583 : : *
584 : : * Create a kobject if for a (per-module) parameter if mp NULL, and
585 : : * create file in sysfs. Returns an error on out of memory. Always cleans up
586 : : * if there's an error.
587 : : */
588 : 0 : static __modinit int add_sysfs_param(struct module_kobject *mk,
589 : : const struct kernel_param *kp,
590 : : const char *name)
591 : : {
592 : : struct module_param_attrs *new;
593 : : struct attribute **attrs;
594 : : int err, num;
595 : :
596 : : /* We don't bother calling this with invisible parameters. */
597 [ # # ]: 0 : BUG_ON(!kp->perm);
598 : :
599 [ # # ]: 0 : if (!mk->mp) {
600 : : num = 0;
601 : : attrs = NULL;
602 : : } else {
603 : 0 : num = mk->mp->num;
604 : 0 : attrs = mk->mp->grp.attrs;
605 : : }
606 : :
607 : : /* Enlarge. */
608 : 0 : new = krealloc(mk->mp,
609 : 0 : sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (num+1),
610 : : GFP_KERNEL);
611 [ # # ]: 0 : if (!new) {
612 : 0 : kfree(attrs);
613 : : err = -ENOMEM;
614 : : goto fail;
615 : : }
616 : : /* Despite looking like the typical realloc() bug, this is safe.
617 : : * We *want* the old 'attrs' to be freed either way, and we'll store
618 : : * the new one in the success case. */
619 : 0 : attrs = krealloc(attrs, sizeof(new->grp.attrs[0])*(num+2), GFP_KERNEL);
620 [ # # ]: 0 : if (!attrs) {
621 : : err = -ENOMEM;
622 : : goto fail_free_new;
623 : : }
624 : :
625 : : /* Sysfs wants everything zeroed. */
626 : 0 : memset(new, 0, sizeof(*new));
627 : 0 : memset(&new->attrs[num], 0, sizeof(new->attrs[num]));
628 : 0 : memset(&attrs[num], 0, sizeof(attrs[num]));
629 : 0 : new->grp.name = "parameters";
630 : 0 : new->grp.attrs = attrs;
631 : :
632 : : /* Tack new one on the end. */
633 : : sysfs_attr_init(&new->attrs[num].mattr.attr);
634 : 0 : new->attrs[num].param = kp;
635 : 0 : new->attrs[num].mattr.show = param_attr_show;
636 : 0 : new->attrs[num].mattr.store = param_attr_store;
637 : 0 : new->attrs[num].mattr.attr.name = (char *)name;
638 : 0 : new->attrs[num].mattr.attr.mode = kp->perm;
639 : 0 : new->num = num+1;
640 : :
641 : : /* Fix up all the pointers, since krealloc can move us */
642 [ # # ]: 0 : for (num = 0; num < new->num; num++)
643 : 0 : new->grp.attrs[num] = &new->attrs[num].mattr.attr;
644 : 0 : new->grp.attrs[num] = NULL;
645 : :
646 : 0 : mk->mp = new;
647 : : return 0;
648 : :
649 : : fail_free_new:
650 : 0 : kfree(new);
651 : : fail:
652 : 0 : mk->mp = NULL;
653 : : return err;
654 : : }
655 : :
656 : : #ifdef CONFIG_MODULES
657 : 0 : static void free_module_param_attrs(struct module_kobject *mk)
658 : : {
659 : 0 : kfree(mk->mp->grp.attrs);
660 : 0 : kfree(mk->mp);
661 : 0 : mk->mp = NULL;
662 : 0 : }
663 : :
664 : : /*
665 : : * module_param_sysfs_setup - setup sysfs support for one module
666 : : * @mod: module
667 : : * @kparam: module parameters (array)
668 : : * @num_params: number of module parameters
669 : : *
670 : : * Adds sysfs entries for module parameters under
671 : : * /sys/module/[mod->name]/parameters/
672 : : */
673 : 0 : int module_param_sysfs_setup(struct module *mod,
674 : : const struct kernel_param *kparam,
675 : : unsigned int num_params)
676 : : {
677 : : int i, err;
678 : : bool params = false;
679 : :
680 [ # # ]: 0 : for (i = 0; i < num_params; i++) {
681 [ # # ]: 0 : if (kparam[i].perm == 0)
682 : 0 : continue;
683 : 0 : err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
684 [ # # ]: 0 : if (err)
685 : : return err;
686 : : params = true;
687 : : }
688 : :
689 [ # # ]: 0 : if (!params)
690 : : return 0;
691 : :
692 : : /* Create the param group. */
693 : 0 : err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
694 [ # # ]: 0 : if (err)
695 : 0 : free_module_param_attrs(&mod->mkobj);
696 : 0 : return err;
697 : : }
698 : :
699 : : /*
700 : : * module_param_sysfs_remove - remove sysfs support for one module
701 : : * @mod: module
702 : : *
703 : : * Remove sysfs entries for module parameters and the corresponding
704 : : * kobject.
705 : : */
706 : 0 : void module_param_sysfs_remove(struct module *mod)
707 : : {
708 [ # # ]: 0 : if (mod->mkobj.mp) {
709 : 0 : sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
710 : : /* We are positive that no one is using any param
711 : : * attrs at this point. Deallocate immediately. */
712 : 0 : free_module_param_attrs(&mod->mkobj);
713 : : }
714 : 0 : }
715 : : #endif
716 : :
717 : 0 : void destroy_params(const struct kernel_param *params, unsigned num)
718 : : {
719 : : unsigned int i;
720 : :
721 [ # # ]: 0 : for (i = 0; i < num; i++)
722 [ # # ]: 0 : if (params[i].ops->free)
723 : 0 : params[i].ops->free(params[i].arg);
724 : 0 : }
725 : :
726 : 0 : static struct module_kobject * __init locate_module_kobject(const char *name)
727 : : {
728 : : struct module_kobject *mk;
729 : : struct kobject *kobj;
730 : : int err;
731 : :
732 : 0 : kobj = kset_find_obj(module_kset, name);
733 [ # # ]: 0 : if (kobj) {
734 : : mk = to_module_kobject(kobj);
735 : : } else {
736 : : mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
737 [ # # ]: 0 : BUG_ON(!mk);
738 : :
739 : 0 : mk->mod = THIS_MODULE;
740 : 0 : mk->kobj.kset = module_kset;
741 : 0 : err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
742 : : "%s", name);
743 : : #ifdef CONFIG_MODULES
744 [ # # ]: 0 : if (!err)
745 : : err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
746 : : #endif
747 [ # # ]: 0 : if (err) {
748 : 0 : kobject_put(&mk->kobj);
749 : 0 : pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",
750 : : name, err);
751 : 0 : return NULL;
752 : : }
753 : :
754 : : /* So that we hold reference in both cases. */
755 : 0 : kobject_get(&mk->kobj);
756 : : }
757 : :
758 : 0 : return mk;
759 : : }
760 : :
761 : 0 : static void __init kernel_add_sysfs_param(const char *name,
762 : : struct kernel_param *kparam,
763 : : unsigned int name_skip)
764 : : {
765 : : struct module_kobject *mk;
766 : : int err;
767 : :
768 : 0 : mk = locate_module_kobject(name);
769 [ # # ]: 0 : if (!mk)
770 : 0 : return;
771 : :
772 : : /* We need to remove old parameters before adding more. */
773 [ # # ]: 0 : if (mk->mp)
774 : 0 : sysfs_remove_group(&mk->kobj, &mk->mp->grp);
775 : :
776 : : /* These should not fail at boot. */
777 : 0 : err = add_sysfs_param(mk, kparam, kparam->name + name_skip);
778 [ # # ]: 0 : BUG_ON(err);
779 : 0 : err = sysfs_create_group(&mk->kobj, &mk->mp->grp);
780 [ # # ]: 0 : BUG_ON(err);
781 : 0 : kobject_uevent(&mk->kobj, KOBJ_ADD);
782 : 0 : kobject_put(&mk->kobj);
783 : : }
784 : :
785 : : /*
786 : : * param_sysfs_builtin - add sysfs parameters for built-in modules
787 : : *
788 : : * Add module_parameters to sysfs for "modules" built into the kernel.
789 : : *
790 : : * The "module" name (KBUILD_MODNAME) is stored before a dot, the
791 : : * "parameter" name is stored behind a dot in kernel_param->name. So,
792 : : * extract the "module" name for all built-in kernel_param-eters,
793 : : * and for all who have the same, call kernel_add_sysfs_param.
794 : : */
795 : 0 : static void __init param_sysfs_builtin(void)
796 : : {
797 : : struct kernel_param *kp;
798 : : unsigned int name_len;
799 : : char modname[MODULE_NAME_LEN];
800 : :
801 [ # # ]: 0 : for (kp = __start___param; kp < __stop___param; kp++) {
802 : : char *dot;
803 : :
804 [ # # ]: 0 : if (kp->perm == 0)
805 : 0 : continue;
806 : :
807 : 0 : dot = strchr(kp->name, '.');
808 [ # # ]: 0 : if (!dot) {
809 : : /* This happens for core_param() */
810 : 0 : strcpy(modname, "kernel");
811 : : name_len = 0;
812 : : } else {
813 : 0 : name_len = dot - kp->name + 1;
814 : 0 : strlcpy(modname, kp->name, name_len);
815 : : }
816 : 0 : kernel_add_sysfs_param(modname, kp, name_len);
817 : : }
818 : 0 : }
819 : :
820 : 0 : ssize_t __modver_version_show(struct module_attribute *mattr,
821 : : struct module_kobject *mk, char *buf)
822 : : {
823 : : struct module_version_attribute *vattr =
824 : : container_of(mattr, struct module_version_attribute, mattr);
825 : :
826 : 0 : return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
827 : : }
828 : :
829 : : extern const struct module_version_attribute *__start___modver[];
830 : : extern const struct module_version_attribute *__stop___modver[];
831 : :
832 : 0 : static void __init version_sysfs_builtin(void)
833 : : {
834 : : const struct module_version_attribute **p;
835 : : struct module_kobject *mk;
836 : : int err;
837 : :
838 [ # # ]: 0 : for (p = __start___modver; p < __stop___modver; p++) {
839 : 0 : const struct module_version_attribute *vattr = *p;
840 : :
841 : 0 : mk = locate_module_kobject(vattr->module_name);
842 [ # # ]: 0 : if (mk) {
843 : 0 : err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
844 : 0 : kobject_uevent(&mk->kobj, KOBJ_ADD);
845 : 0 : kobject_put(&mk->kobj);
846 : : }
847 : : }
848 : 0 : }
849 : :
850 : : /* module-related sysfs stuff */
851 : :
852 : 0 : static ssize_t module_attr_show(struct kobject *kobj,
853 : : struct attribute *attr,
854 : : char *buf)
855 : : {
856 : : struct module_attribute *attribute;
857 : : struct module_kobject *mk;
858 : : int ret;
859 : :
860 : : attribute = to_module_attr(attr);
861 : : mk = to_module_kobject(kobj);
862 : :
863 [ # # ]: 0 : if (!attribute->show)
864 : : return -EIO;
865 : :
866 : 0 : ret = attribute->show(attribute, mk, buf);
867 : :
868 : 0 : return ret;
869 : : }
870 : :
871 : 0 : static ssize_t module_attr_store(struct kobject *kobj,
872 : : struct attribute *attr,
873 : : const char *buf, size_t len)
874 : : {
875 : : struct module_attribute *attribute;
876 : : struct module_kobject *mk;
877 : : int ret;
878 : :
879 : : attribute = to_module_attr(attr);
880 : : mk = to_module_kobject(kobj);
881 : :
882 [ # # ]: 0 : if (!attribute->store)
883 : : return -EIO;
884 : :
885 : 0 : ret = attribute->store(attribute, mk, buf, len);
886 : :
887 : 0 : return ret;
888 : : }
889 : :
890 : : static const struct sysfs_ops module_sysfs_ops = {
891 : : .show = module_attr_show,
892 : : .store = module_attr_store,
893 : : };
894 : :
895 : 0 : static int uevent_filter(struct kset *kset, struct kobject *kobj)
896 : : {
897 : : struct kobj_type *ktype = get_ktype(kobj);
898 : :
899 [ # # ]: 0 : if (ktype == &module_ktype)
900 : : return 1;
901 : 0 : return 0;
902 : : }
903 : :
904 : : static const struct kset_uevent_ops module_uevent_ops = {
905 : : .filter = uevent_filter,
906 : : };
907 : :
908 : : struct kset *module_kset;
909 : : int module_sysfs_initialized;
910 : :
911 : 0 : static void module_kobj_release(struct kobject *kobj)
912 : : {
913 : : struct module_kobject *mk = to_module_kobject(kobj);
914 : 0 : complete(mk->kobj_completion);
915 : 0 : }
916 : :
917 : : struct kobj_type module_ktype = {
918 : : .release = module_kobj_release,
919 : : .sysfs_ops = &module_sysfs_ops,
920 : : };
921 : :
922 : : /*
923 : : * param_sysfs_init - wrapper for built-in params support
924 : : */
925 : 0 : static int __init param_sysfs_init(void)
926 : : {
927 : 0 : module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
928 [ # # ]: 0 : if (!module_kset) {
929 : 0 : printk(KERN_WARNING "%s (%d): error creating kset\n",
930 : : __FILE__, __LINE__);
931 : 0 : return -ENOMEM;
932 : : }
933 : 0 : module_sysfs_initialized = 1;
934 : :
935 : 0 : version_sysfs_builtin();
936 : 0 : param_sysfs_builtin();
937 : :
938 : 0 : return 0;
939 : : }
940 : : subsys_initcall(param_sysfs_init);
941 : :
942 : : #endif /* CONFIG_SYSFS */
|