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