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