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