Back to home page

LXR

 
 

    


0001 /* Helpers for initial module or kernel cmdline parsing
0002    Copyright (C) 2001 Rusty Russell.
0003 
0004     This program is free software; you can redistribute it and/or modify
0005     it under the terms of the GNU General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or
0007     (at your option) any later version.
0008 
0009     This program is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012     GNU General Public License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program; if not, write to the Free Software
0016     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017 */
0018 #include <linux/kernel.h>
0019 #include <linux/string.h>
0020 #include <linux/errno.h>
0021 #include <linux/module.h>
0022 #include <linux/moduleparam.h>
0023 #include <linux/device.h>
0024 #include <linux/err.h>
0025 #include <linux/slab.h>
0026 #include <linux/ctype.h>
0027 
0028 #ifdef CONFIG_SYSFS
0029 /* Protects all built-in parameters, modules use their own param_lock */
0030 static DEFINE_MUTEX(param_lock);
0031 
0032 /* Use the module's mutex, or if built-in use the built-in mutex */
0033 #ifdef CONFIG_MODULES
0034 #define KPARAM_MUTEX(mod)   ((mod) ? &(mod)->param_lock : &param_lock)
0035 #else
0036 #define KPARAM_MUTEX(mod)   (&param_lock)
0037 #endif
0038 
0039 static inline void check_kparam_locked(struct module *mod)
0040 {
0041     BUG_ON(!mutex_is_locked(KPARAM_MUTEX(mod)));
0042 }
0043 #else
0044 static inline void check_kparam_locked(struct module *mod)
0045 {
0046 }
0047 #endif /* !CONFIG_SYSFS */
0048 
0049 /* This just allows us to keep track of which parameters are kmalloced. */
0050 struct kmalloced_param {
0051     struct list_head list;
0052     char val[];
0053 };
0054 static LIST_HEAD(kmalloced_params);
0055 static DEFINE_SPINLOCK(kmalloced_params_lock);
0056 
0057 static void *kmalloc_parameter(unsigned int size)
0058 {
0059     struct kmalloced_param *p;
0060 
0061     p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
0062     if (!p)
0063         return NULL;
0064 
0065     spin_lock(&kmalloced_params_lock);
0066     list_add(&p->list, &kmalloced_params);
0067     spin_unlock(&kmalloced_params_lock);
0068 
0069     return p->val;
0070 }
0071 
0072 /* Does nothing if parameter wasn't kmalloced above. */
0073 static void maybe_kfree_parameter(void *param)
0074 {
0075     struct kmalloced_param *p;
0076 
0077     spin_lock(&kmalloced_params_lock);
0078     list_for_each_entry(p, &kmalloced_params, list) {
0079         if (p->val == param) {
0080             list_del(&p->list);
0081             kfree(p);
0082             break;
0083         }
0084     }
0085     spin_unlock(&kmalloced_params_lock);
0086 }
0087 
0088 static char dash2underscore(char c)
0089 {
0090     if (c == '-')
0091         return '_';
0092     return c;
0093 }
0094 
0095 bool parameqn(const char *a, const char *b, size_t n)
0096 {
0097     size_t i;
0098 
0099     for (i = 0; i < n; i++) {
0100         if (dash2underscore(a[i]) != dash2underscore(b[i]))
0101             return false;
0102     }
0103     return true;
0104 }
0105 
0106 bool parameq(const char *a, const char *b)
0107 {
0108     return parameqn(a, b, strlen(a)+1);
0109 }
0110 
0111 static void param_check_unsafe(const struct kernel_param *kp)
0112 {
0113     if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
0114         pr_warn("Setting dangerous option %s - tainting kernel\n",
0115             kp->name);
0116         add_taint(TAINT_USER, LOCKDEP_STILL_OK);
0117     }
0118 }
0119 
0120 static int parse_one(char *param,
0121              char *val,
0122              const char *doing,
0123              const struct kernel_param *params,
0124              unsigned num_params,
0125              s16 min_level,
0126              s16 max_level,
0127              void *arg,
0128              int (*handle_unknown)(char *param, char *val,
0129                      const char *doing, void *arg))
0130 {
0131     unsigned int i;
0132     int err;
0133 
0134     /* Find parameter */
0135     for (i = 0; i < num_params; i++) {
0136         if (parameq(param, params[i].name)) {
0137             if (params[i].level < min_level
0138                 || params[i].level > max_level)
0139                 return 0;
0140             /* No one handled NULL, so do it here. */
0141             if (!val &&
0142                 !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG))
0143                 return -EINVAL;
0144             pr_debug("handling %s with %p\n", param,
0145                 params[i].ops->set);
0146             kernel_param_lock(params[i].mod);
0147             param_check_unsafe(&params[i]);
0148             err = params[i].ops->set(val, &params[i]);
0149             kernel_param_unlock(params[i].mod);
0150             return err;
0151         }
0152     }
0153 
0154     if (handle_unknown) {
0155         pr_debug("doing %s: %s='%s'\n", doing, param, val);
0156         return handle_unknown(param, val, doing, arg);
0157     }
0158 
0159     pr_debug("Unknown argument '%s'\n", param);
0160     return -ENOENT;
0161 }
0162 
0163 /* You can use " around spaces, but can't escape ". */
0164 /* Hyphens and underscores equivalent in parameter names. */
0165 static char *next_arg(char *args, char **param, char **val)
0166 {
0167     unsigned int i, equals = 0;
0168     int in_quote = 0, quoted = 0;
0169     char *next;
0170 
0171     if (*args == '"') {
0172         args++;
0173         in_quote = 1;
0174         quoted = 1;
0175     }
0176 
0177     for (i = 0; args[i]; i++) {
0178         if (isspace(args[i]) && !in_quote)
0179             break;
0180         if (equals == 0) {
0181             if (args[i] == '=')
0182                 equals = i;
0183         }
0184         if (args[i] == '"')
0185             in_quote = !in_quote;
0186     }
0187 
0188     *param = args;
0189     if (!equals)
0190         *val = NULL;
0191     else {
0192         args[equals] = '\0';
0193         *val = args + equals + 1;
0194 
0195         /* Don't include quotes in value. */
0196         if (**val == '"') {
0197             (*val)++;
0198             if (args[i-1] == '"')
0199                 args[i-1] = '\0';
0200         }
0201     }
0202     if (quoted && args[i-1] == '"')
0203         args[i-1] = '\0';
0204 
0205     if (args[i]) {
0206         args[i] = '\0';
0207         next = args + i + 1;
0208     } else
0209         next = args + i;
0210 
0211     /* Chew up trailing spaces. */
0212     return skip_spaces(next);
0213 }
0214 
0215 /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
0216 char *parse_args(const char *doing,
0217          char *args,
0218          const struct kernel_param *params,
0219          unsigned num,
0220          s16 min_level,
0221          s16 max_level,
0222          void *arg,
0223          int (*unknown)(char *param, char *val,
0224                 const char *doing, void *arg))
0225 {
0226     char *param, *val, *err = NULL;
0227 
0228     /* Chew leading spaces */
0229     args = skip_spaces(args);
0230 
0231     if (*args)
0232         pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args);
0233 
0234     while (*args) {
0235         int ret;
0236         int irq_was_disabled;
0237 
0238         args = next_arg(args, &param, &val);
0239         /* Stop at -- */
0240         if (!val && strcmp(param, "--") == 0)
0241             return err ?: args;
0242         irq_was_disabled = irqs_disabled();
0243         ret = parse_one(param, val, doing, params, num,
0244                 min_level, max_level, arg, unknown);
0245         if (irq_was_disabled && !irqs_disabled())
0246             pr_warn("%s: option '%s' enabled irq's!\n",
0247                 doing, param);
0248 
0249         switch (ret) {
0250         case 0:
0251             continue;
0252         case -ENOENT:
0253             pr_err("%s: Unknown parameter `%s'\n", doing, param);
0254             break;
0255         case -ENOSPC:
0256             pr_err("%s: `%s' too large for parameter `%s'\n",
0257                    doing, val ?: "", param);
0258             break;
0259         default:
0260             pr_err("%s: `%s' invalid for parameter `%s'\n",
0261                    doing, val ?: "", param);
0262             break;
0263         }
0264 
0265         err = ERR_PTR(ret);
0266     }
0267 
0268     return err;
0269 }
0270 
0271 /* Lazy bastard, eh? */
0272 #define STANDARD_PARAM_DEF(name, type, format, strtolfn)            \
0273     int param_set_##name(const char *val, const struct kernel_param *kp) \
0274     {                               \
0275         return strtolfn(val, 0, (type *)kp->arg);       \
0276     }                               \
0277     int param_get_##name(char *buffer, const struct kernel_param *kp) \
0278     {                               \
0279         return scnprintf(buffer, PAGE_SIZE, format,     \
0280                 *((type *)kp->arg));            \
0281     }                               \
0282     const struct kernel_param_ops param_ops_##name = {          \
0283         .set = param_set_##name,                \
0284         .get = param_get_##name,                \
0285     };                              \
0286     EXPORT_SYMBOL(param_set_##name);                \
0287     EXPORT_SYMBOL(param_get_##name);                \
0288     EXPORT_SYMBOL(param_ops_##name)
0289 
0290 
0291 STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
0292 STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
0293 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
0294 STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
0295 STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
0296 STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
0297 STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
0298 STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull);
0299 
0300 int param_set_charp(const char *val, const struct kernel_param *kp)
0301 {
0302     if (strlen(val) > 1024) {
0303         pr_err("%s: string parameter too long\n", kp->name);
0304         return -ENOSPC;
0305     }
0306 
0307     maybe_kfree_parameter(*(char **)kp->arg);
0308 
0309     /* This is a hack.  We can't kmalloc in early boot, and we
0310      * don't need to; this mangled commandline is preserved. */
0311     if (slab_is_available()) {
0312         *(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
0313         if (!*(char **)kp->arg)
0314             return -ENOMEM;
0315         strcpy(*(char **)kp->arg, val);
0316     } else
0317         *(const char **)kp->arg = val;
0318 
0319     return 0;
0320 }
0321 EXPORT_SYMBOL(param_set_charp);
0322 
0323 int param_get_charp(char *buffer, const struct kernel_param *kp)
0324 {
0325     return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
0326 }
0327 EXPORT_SYMBOL(param_get_charp);
0328 
0329 void param_free_charp(void *arg)
0330 {
0331     maybe_kfree_parameter(*((char **)arg));
0332 }
0333 EXPORT_SYMBOL(param_free_charp);
0334 
0335 const struct kernel_param_ops param_ops_charp = {
0336     .set = param_set_charp,
0337     .get = param_get_charp,
0338     .free = param_free_charp,
0339 };
0340 EXPORT_SYMBOL(param_ops_charp);
0341 
0342 /* Actually could be a bool or an int, for historical reasons. */
0343 int param_set_bool(const char *val, const struct kernel_param *kp)
0344 {
0345     /* No equals means "set"... */
0346     if (!val) val = "1";
0347 
0348     /* One of =[yYnN01] */
0349     return strtobool(val, kp->arg);
0350 }
0351 EXPORT_SYMBOL(param_set_bool);
0352 
0353 int param_get_bool(char *buffer, const struct kernel_param *kp)
0354 {
0355     /* Y and N chosen as being relatively non-coder friendly */
0356     return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
0357 }
0358 EXPORT_SYMBOL(param_get_bool);
0359 
0360 const struct kernel_param_ops param_ops_bool = {
0361     .flags = KERNEL_PARAM_OPS_FL_NOARG,
0362     .set = param_set_bool,
0363     .get = param_get_bool,
0364 };
0365 EXPORT_SYMBOL(param_ops_bool);
0366 
0367 int param_set_bool_enable_only(const char *val, const struct kernel_param *kp)
0368 {
0369     int err = 0;
0370     bool new_value;
0371     bool orig_value = *(bool *)kp->arg;
0372     struct kernel_param dummy_kp = *kp;
0373 
0374     dummy_kp.arg = &new_value;
0375 
0376     err = param_set_bool(val, &dummy_kp);
0377     if (err)
0378         return err;
0379 
0380     /* Don't let them unset it once it's set! */
0381     if (!new_value && orig_value)
0382         return -EROFS;
0383 
0384     if (new_value)
0385         err = param_set_bool(val, kp);
0386 
0387     return err;
0388 }
0389 EXPORT_SYMBOL_GPL(param_set_bool_enable_only);
0390 
0391 const struct kernel_param_ops param_ops_bool_enable_only = {
0392     .flags = KERNEL_PARAM_OPS_FL_NOARG,
0393     .set = param_set_bool_enable_only,
0394     .get = param_get_bool,
0395 };
0396 EXPORT_SYMBOL_GPL(param_ops_bool_enable_only);
0397 
0398 /* This one must be bool. */
0399 int param_set_invbool(const char *val, const struct kernel_param *kp)
0400 {
0401     int ret;
0402     bool boolval;
0403     struct kernel_param dummy;
0404 
0405     dummy.arg = &boolval;
0406     ret = param_set_bool(val, &dummy);
0407     if (ret == 0)
0408         *(bool *)kp->arg = !boolval;
0409     return ret;
0410 }
0411 EXPORT_SYMBOL(param_set_invbool);
0412 
0413 int param_get_invbool(char *buffer, const struct kernel_param *kp)
0414 {
0415     return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y');
0416 }
0417 EXPORT_SYMBOL(param_get_invbool);
0418 
0419 const struct kernel_param_ops param_ops_invbool = {
0420     .set = param_set_invbool,
0421     .get = param_get_invbool,
0422 };
0423 EXPORT_SYMBOL(param_ops_invbool);
0424 
0425 int param_set_bint(const char *val, const struct kernel_param *kp)
0426 {
0427     /* Match bool exactly, by re-using it. */
0428     struct kernel_param boolkp = *kp;
0429     bool v;
0430     int ret;
0431 
0432     boolkp.arg = &v;
0433 
0434     ret = param_set_bool(val, &boolkp);
0435     if (ret == 0)
0436         *(int *)kp->arg = v;
0437     return ret;
0438 }
0439 EXPORT_SYMBOL(param_set_bint);
0440 
0441 const struct kernel_param_ops param_ops_bint = {
0442     .flags = KERNEL_PARAM_OPS_FL_NOARG,
0443     .set = param_set_bint,
0444     .get = param_get_int,
0445 };
0446 EXPORT_SYMBOL(param_ops_bint);
0447 
0448 /* We break the rule and mangle the string. */
0449 static int param_array(struct module *mod,
0450                const char *name,
0451                const char *val,
0452                unsigned int min, unsigned int max,
0453                void *elem, int elemsize,
0454                int (*set)(const char *, const struct kernel_param *kp),
0455                s16 level,
0456                unsigned int *num)
0457 {
0458     int ret;
0459     struct kernel_param kp;
0460     char save;
0461 
0462     /* Get the name right for errors. */
0463     kp.name = name;
0464     kp.arg = elem;
0465     kp.level = level;
0466 
0467     *num = 0;
0468     /* We expect a comma-separated list of values. */
0469     do {
0470         int len;
0471 
0472         if (*num == max) {
0473             pr_err("%s: can only take %i arguments\n", name, max);
0474             return -EINVAL;
0475         }
0476         len = strcspn(val, ",");
0477 
0478         /* nul-terminate and parse */
0479         save = val[len];
0480         ((char *)val)[len] = '\0';
0481         check_kparam_locked(mod);
0482         ret = set(val, &kp);
0483 
0484         if (ret != 0)
0485             return ret;
0486         kp.arg += elemsize;
0487         val += len+1;
0488         (*num)++;
0489     } while (save == ',');
0490 
0491     if (*num < min) {
0492         pr_err("%s: needs at least %i arguments\n", name, min);
0493         return -EINVAL;
0494     }
0495     return 0;
0496 }
0497 
0498 static int param_array_set(const char *val, const struct kernel_param *kp)
0499 {
0500     const struct kparam_array *arr = kp->arr;
0501     unsigned int temp_num;
0502 
0503     return param_array(kp->mod, kp->name, val, 1, arr->max, arr->elem,
0504                arr->elemsize, arr->ops->set, kp->level,
0505                arr->num ?: &temp_num);
0506 }
0507 
0508 static int param_array_get(char *buffer, const struct kernel_param *kp)
0509 {
0510     int i, off, ret;
0511     const struct kparam_array *arr = kp->arr;
0512     struct kernel_param p = *kp;
0513 
0514     for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
0515         if (i)
0516             buffer[off++] = ',';
0517         p.arg = arr->elem + arr->elemsize * i;
0518         check_kparam_locked(p.mod);
0519         ret = arr->ops->get(buffer + off, &p);
0520         if (ret < 0)
0521             return ret;
0522         off += ret;
0523     }
0524     buffer[off] = '\0';
0525     return off;
0526 }
0527 
0528 static void param_array_free(void *arg)
0529 {
0530     unsigned int i;
0531     const struct kparam_array *arr = arg;
0532 
0533     if (arr->ops->free)
0534         for (i = 0; i < (arr->num ? *arr->num : arr->max); i++)
0535             arr->ops->free(arr->elem + arr->elemsize * i);
0536 }
0537 
0538 const struct kernel_param_ops param_array_ops = {
0539     .set = param_array_set,
0540     .get = param_array_get,
0541     .free = param_array_free,
0542 };
0543 EXPORT_SYMBOL(param_array_ops);
0544 
0545 int param_set_copystring(const char *val, const struct kernel_param *kp)
0546 {
0547     const struct kparam_string *kps = kp->str;
0548 
0549     if (strlen(val)+1 > kps->maxlen) {
0550         pr_err("%s: string doesn't fit in %u chars.\n",
0551                kp->name, kps->maxlen-1);
0552         return -ENOSPC;
0553     }
0554     strcpy(kps->string, val);
0555     return 0;
0556 }
0557 EXPORT_SYMBOL(param_set_copystring);
0558 
0559 int param_get_string(char *buffer, const struct kernel_param *kp)
0560 {
0561     const struct kparam_string *kps = kp->str;
0562     return strlcpy(buffer, kps->string, kps->maxlen);
0563 }
0564 EXPORT_SYMBOL(param_get_string);
0565 
0566 const struct kernel_param_ops param_ops_string = {
0567     .set = param_set_copystring,
0568     .get = param_get_string,
0569 };
0570 EXPORT_SYMBOL(param_ops_string);
0571 
0572 /* sysfs output in /sys/modules/XYZ/parameters/ */
0573 #define to_module_attr(n) container_of(n, struct module_attribute, attr)
0574 #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
0575 
0576 struct param_attribute
0577 {
0578     struct module_attribute mattr;
0579     const struct kernel_param *param;
0580 };
0581 
0582 struct module_param_attrs
0583 {
0584     unsigned int num;
0585     struct attribute_group grp;
0586     struct param_attribute attrs[0];
0587 };
0588 
0589 #ifdef CONFIG_SYSFS
0590 #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
0591 
0592 static ssize_t param_attr_show(struct module_attribute *mattr,
0593                    struct module_kobject *mk, char *buf)
0594 {
0595     int count;
0596     struct param_attribute *attribute = to_param_attr(mattr);
0597 
0598     if (!attribute->param->ops->get)
0599         return -EPERM;
0600 
0601     kernel_param_lock(mk->mod);
0602     count = attribute->param->ops->get(buf, attribute->param);
0603     kernel_param_unlock(mk->mod);
0604     if (count > 0) {
0605         strcat(buf, "\n");
0606         ++count;
0607     }
0608     return count;
0609 }
0610 
0611 /* sysfs always hands a nul-terminated string in buf.  We rely on that. */
0612 static ssize_t param_attr_store(struct module_attribute *mattr,
0613                 struct module_kobject *mk,
0614                 const char *buf, size_t len)
0615 {
0616     int err;
0617     struct param_attribute *attribute = to_param_attr(mattr);
0618 
0619     if (!attribute->param->ops->set)
0620         return -EPERM;
0621 
0622     kernel_param_lock(mk->mod);
0623     param_check_unsafe(attribute->param);
0624     err = attribute->param->ops->set(buf, attribute->param);
0625     kernel_param_unlock(mk->mod);
0626     if (!err)
0627         return len;
0628     return err;
0629 }
0630 #endif
0631 
0632 #ifdef CONFIG_MODULES
0633 #define __modinit
0634 #else
0635 #define __modinit __init
0636 #endif
0637 
0638 #ifdef CONFIG_SYSFS
0639 void kernel_param_lock(struct module *mod)
0640 {
0641     mutex_lock(KPARAM_MUTEX(mod));
0642 }
0643 
0644 void kernel_param_unlock(struct module *mod)
0645 {
0646     mutex_unlock(KPARAM_MUTEX(mod));
0647 }
0648 
0649 EXPORT_SYMBOL(kernel_param_lock);
0650 EXPORT_SYMBOL(kernel_param_unlock);
0651 
0652 /*
0653  * add_sysfs_param - add a parameter to sysfs
0654  * @mk: struct module_kobject
0655  * @kparam: the actual parameter definition to add to sysfs
0656  * @name: name of parameter
0657  *
0658  * Create a kobject if for a (per-module) parameter if mp NULL, and
0659  * create file in sysfs.  Returns an error on out of memory.  Always cleans up
0660  * if there's an error.
0661  */
0662 static __modinit int add_sysfs_param(struct module_kobject *mk,
0663                      const struct kernel_param *kp,
0664                      const char *name)
0665 {
0666     struct module_param_attrs *new_mp;
0667     struct attribute **new_attrs;
0668     unsigned int i;
0669 
0670     /* We don't bother calling this with invisible parameters. */
0671     BUG_ON(!kp->perm);
0672 
0673     if (!mk->mp) {
0674         /* First allocation. */
0675         mk->mp = kzalloc(sizeof(*mk->mp), GFP_KERNEL);
0676         if (!mk->mp)
0677             return -ENOMEM;
0678         mk->mp->grp.name = "parameters";
0679         /* NULL-terminated attribute array. */
0680         mk->mp->grp.attrs = kzalloc(sizeof(mk->mp->grp.attrs[0]),
0681                         GFP_KERNEL);
0682         /* Caller will cleanup via free_module_param_attrs */
0683         if (!mk->mp->grp.attrs)
0684             return -ENOMEM;
0685     }
0686 
0687     /* Enlarge allocations. */
0688     new_mp = krealloc(mk->mp,
0689               sizeof(*mk->mp) +
0690               sizeof(mk->mp->attrs[0]) * (mk->mp->num + 1),
0691               GFP_KERNEL);
0692     if (!new_mp)
0693         return -ENOMEM;
0694     mk->mp = new_mp;
0695 
0696     /* Extra pointer for NULL terminator */
0697     new_attrs = krealloc(mk->mp->grp.attrs,
0698                  sizeof(mk->mp->grp.attrs[0]) * (mk->mp->num + 2),
0699                  GFP_KERNEL);
0700     if (!new_attrs)
0701         return -ENOMEM;
0702     mk->mp->grp.attrs = new_attrs;
0703 
0704     /* Tack new one on the end. */
0705     memset(&mk->mp->attrs[mk->mp->num], 0, sizeof(mk->mp->attrs[0]));
0706     sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr);
0707     mk->mp->attrs[mk->mp->num].param = kp;
0708     mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show;
0709     /* Do not allow runtime DAC changes to make param writable. */
0710     if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
0711         mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store;
0712     else
0713         mk->mp->attrs[mk->mp->num].mattr.store = NULL;
0714     mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name;
0715     mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm;
0716     mk->mp->num++;
0717 
0718     /* Fix up all the pointers, since krealloc can move us */
0719     for (i = 0; i < mk->mp->num; i++)
0720         mk->mp->grp.attrs[i] = &mk->mp->attrs[i].mattr.attr;
0721     mk->mp->grp.attrs[mk->mp->num] = NULL;
0722     return 0;
0723 }
0724 
0725 #ifdef CONFIG_MODULES
0726 static void free_module_param_attrs(struct module_kobject *mk)
0727 {
0728     if (mk->mp)
0729         kfree(mk->mp->grp.attrs);
0730     kfree(mk->mp);
0731     mk->mp = NULL;
0732 }
0733 
0734 /*
0735  * module_param_sysfs_setup - setup sysfs support for one module
0736  * @mod: module
0737  * @kparam: module parameters (array)
0738  * @num_params: number of module parameters
0739  *
0740  * Adds sysfs entries for module parameters under
0741  * /sys/module/[mod->name]/parameters/
0742  */
0743 int module_param_sysfs_setup(struct module *mod,
0744                  const struct kernel_param *kparam,
0745                  unsigned int num_params)
0746 {
0747     int i, err;
0748     bool params = false;
0749 
0750     for (i = 0; i < num_params; i++) {
0751         if (kparam[i].perm == 0)
0752             continue;
0753         err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
0754         if (err) {
0755             free_module_param_attrs(&mod->mkobj);
0756             return err;
0757         }
0758         params = true;
0759     }
0760 
0761     if (!params)
0762         return 0;
0763 
0764     /* Create the param group. */
0765     err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
0766     if (err)
0767         free_module_param_attrs(&mod->mkobj);
0768     return err;
0769 }
0770 
0771 /*
0772  * module_param_sysfs_remove - remove sysfs support for one module
0773  * @mod: module
0774  *
0775  * Remove sysfs entries for module parameters and the corresponding
0776  * kobject.
0777  */
0778 void module_param_sysfs_remove(struct module *mod)
0779 {
0780     if (mod->mkobj.mp) {
0781         sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
0782         /* We are positive that no one is using any param
0783          * attrs at this point.  Deallocate immediately. */
0784         free_module_param_attrs(&mod->mkobj);
0785     }
0786 }
0787 #endif
0788 
0789 void destroy_params(const struct kernel_param *params, unsigned num)
0790 {
0791     unsigned int i;
0792 
0793     for (i = 0; i < num; i++)
0794         if (params[i].ops->free)
0795             params[i].ops->free(params[i].arg);
0796 }
0797 
0798 static struct module_kobject * __init locate_module_kobject(const char *name)
0799 {
0800     struct module_kobject *mk;
0801     struct kobject *kobj;
0802     int err;
0803 
0804     kobj = kset_find_obj(module_kset, name);
0805     if (kobj) {
0806         mk = to_module_kobject(kobj);
0807     } else {
0808         mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
0809         BUG_ON(!mk);
0810 
0811         mk->mod = THIS_MODULE;
0812         mk->kobj.kset = module_kset;
0813         err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
0814                        "%s", name);
0815 #ifdef CONFIG_MODULES
0816         if (!err)
0817             err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
0818 #endif
0819         if (err) {
0820             kobject_put(&mk->kobj);
0821             pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",
0822                 name, err);
0823             return NULL;
0824         }
0825 
0826         /* So that we hold reference in both cases. */
0827         kobject_get(&mk->kobj);
0828     }
0829 
0830     return mk;
0831 }
0832 
0833 static void __init kernel_add_sysfs_param(const char *name,
0834                       const struct kernel_param *kparam,
0835                       unsigned int name_skip)
0836 {
0837     struct module_kobject *mk;
0838     int err;
0839 
0840     mk = locate_module_kobject(name);
0841     if (!mk)
0842         return;
0843 
0844     /* We need to remove old parameters before adding more. */
0845     if (mk->mp)
0846         sysfs_remove_group(&mk->kobj, &mk->mp->grp);
0847 
0848     /* These should not fail at boot. */
0849     err = add_sysfs_param(mk, kparam, kparam->name + name_skip);
0850     BUG_ON(err);
0851     err = sysfs_create_group(&mk->kobj, &mk->mp->grp);
0852     BUG_ON(err);
0853     kobject_uevent(&mk->kobj, KOBJ_ADD);
0854     kobject_put(&mk->kobj);
0855 }
0856 
0857 /*
0858  * param_sysfs_builtin - add sysfs parameters for built-in modules
0859  *
0860  * Add module_parameters to sysfs for "modules" built into the kernel.
0861  *
0862  * The "module" name (KBUILD_MODNAME) is stored before a dot, the
0863  * "parameter" name is stored behind a dot in kernel_param->name. So,
0864  * extract the "module" name for all built-in kernel_param-eters,
0865  * and for all who have the same, call kernel_add_sysfs_param.
0866  */
0867 static void __init param_sysfs_builtin(void)
0868 {
0869     const struct kernel_param *kp;
0870     unsigned int name_len;
0871     char modname[MODULE_NAME_LEN];
0872 
0873     for (kp = __start___param; kp < __stop___param; kp++) {
0874         char *dot;
0875 
0876         if (kp->perm == 0)
0877             continue;
0878 
0879         dot = strchr(kp->name, '.');
0880         if (!dot) {
0881             /* This happens for core_param() */
0882             strcpy(modname, "kernel");
0883             name_len = 0;
0884         } else {
0885             name_len = dot - kp->name + 1;
0886             strlcpy(modname, kp->name, name_len);
0887         }
0888         kernel_add_sysfs_param(modname, kp, name_len);
0889     }
0890 }
0891 
0892 ssize_t __modver_version_show(struct module_attribute *mattr,
0893                   struct module_kobject *mk, char *buf)
0894 {
0895     struct module_version_attribute *vattr =
0896         container_of(mattr, struct module_version_attribute, mattr);
0897 
0898     return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
0899 }
0900 
0901 extern const struct module_version_attribute *__start___modver[];
0902 extern const struct module_version_attribute *__stop___modver[];
0903 
0904 static void __init version_sysfs_builtin(void)
0905 {
0906     const struct module_version_attribute **p;
0907     struct module_kobject *mk;
0908     int err;
0909 
0910     for (p = __start___modver; p < __stop___modver; p++) {
0911         const struct module_version_attribute *vattr = *p;
0912 
0913         mk = locate_module_kobject(vattr->module_name);
0914         if (mk) {
0915             err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
0916             WARN_ON_ONCE(err);
0917             kobject_uevent(&mk->kobj, KOBJ_ADD);
0918             kobject_put(&mk->kobj);
0919         }
0920     }
0921 }
0922 
0923 /* module-related sysfs stuff */
0924 
0925 static ssize_t module_attr_show(struct kobject *kobj,
0926                 struct attribute *attr,
0927                 char *buf)
0928 {
0929     struct module_attribute *attribute;
0930     struct module_kobject *mk;
0931     int ret;
0932 
0933     attribute = to_module_attr(attr);
0934     mk = to_module_kobject(kobj);
0935 
0936     if (!attribute->show)
0937         return -EIO;
0938 
0939     ret = attribute->show(attribute, mk, buf);
0940 
0941     return ret;
0942 }
0943 
0944 static ssize_t module_attr_store(struct kobject *kobj,
0945                 struct attribute *attr,
0946                 const char *buf, size_t len)
0947 {
0948     struct module_attribute *attribute;
0949     struct module_kobject *mk;
0950     int ret;
0951 
0952     attribute = to_module_attr(attr);
0953     mk = to_module_kobject(kobj);
0954 
0955     if (!attribute->store)
0956         return -EIO;
0957 
0958     ret = attribute->store(attribute, mk, buf, len);
0959 
0960     return ret;
0961 }
0962 
0963 static const struct sysfs_ops module_sysfs_ops = {
0964     .show = module_attr_show,
0965     .store = module_attr_store,
0966 };
0967 
0968 static int uevent_filter(struct kset *kset, struct kobject *kobj)
0969 {
0970     struct kobj_type *ktype = get_ktype(kobj);
0971 
0972     if (ktype == &module_ktype)
0973         return 1;
0974     return 0;
0975 }
0976 
0977 static const struct kset_uevent_ops module_uevent_ops = {
0978     .filter = uevent_filter,
0979 };
0980 
0981 struct kset *module_kset;
0982 int module_sysfs_initialized;
0983 
0984 static void module_kobj_release(struct kobject *kobj)
0985 {
0986     struct module_kobject *mk = to_module_kobject(kobj);
0987     complete(mk->kobj_completion);
0988 }
0989 
0990 struct kobj_type module_ktype = {
0991     .release   =    module_kobj_release,
0992     .sysfs_ops =    &module_sysfs_ops,
0993 };
0994 
0995 /*
0996  * param_sysfs_init - wrapper for built-in params support
0997  */
0998 static int __init param_sysfs_init(void)
0999 {
1000     module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
1001     if (!module_kset) {
1002         printk(KERN_WARNING "%s (%d): error creating kset\n",
1003             __FILE__, __LINE__);
1004         return -ENOMEM;
1005     }
1006     module_sysfs_initialized = 1;
1007 
1008     version_sysfs_builtin();
1009     param_sysfs_builtin();
1010 
1011     return 0;
1012 }
1013 subsys_initcall(param_sysfs_init);
1014 
1015 #endif /* CONFIG_SYSFS */