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