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