LCOV - code coverage report
Current view: top level - kernel - params.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 306 0.0 %
Date: 2014-02-18 Functions: 0 54 0.0 %
Branches: 0 228 0.0 %

           Branch data     Line data    Source code
       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/kernel.h>
      19                 :            : #include <linux/string.h>
      20                 :            : #include <linux/errno.h>
      21                 :            : #include <linux/module.h>
      22                 :            : #include <linux/device.h>
      23                 :            : #include <linux/err.h>
      24                 :            : #include <linux/slab.h>
      25                 :            : #include <linux/ctype.h>
      26                 :            : 
      27                 :            : /* Protects all parameters, and incidentally kmalloced_param list. */
      28                 :            : static DEFINE_MUTEX(param_lock);
      29                 :            : 
      30                 :            : /* This just allows us to keep track of which parameters are kmalloced. */
      31                 :            : struct kmalloced_param {
      32                 :            :         struct list_head list;
      33                 :            :         char val[];
      34                 :            : };
      35                 :            : static LIST_HEAD(kmalloced_params);
      36                 :            : 
      37                 :          0 : static void *kmalloc_parameter(unsigned int size)
      38                 :            : {
      39                 :            :         struct kmalloced_param *p;
      40                 :            : 
      41                 :          0 :         p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
      42         [ #  # ]:          0 :         if (!p)
      43                 :            :                 return NULL;
      44                 :            : 
      45                 :          0 :         list_add(&p->list, &kmalloced_params);
      46                 :          0 :         return p->val;
      47                 :            : }
      48                 :            : 
      49                 :            : /* Does nothing if parameter wasn't kmalloced above. */
      50                 :          0 : static void maybe_kfree_parameter(void *param)
      51                 :            : {
      52                 :            :         struct kmalloced_param *p;
      53                 :            : 
      54         [ #  # ]:          0 :         list_for_each_entry(p, &kmalloced_params, list) {
      55         [ #  # ]:          0 :                 if (p->val == param) {
      56                 :            :                         list_del(&p->list);
      57                 :          0 :                         kfree(p);
      58                 :          0 :                         break;
      59                 :            :                 }
      60                 :            :         }
      61                 :          0 : }
      62                 :            : 
      63                 :            : static char dash2underscore(char c)
      64                 :            : {
      65 [ #  # ][ #  # ]:          0 :         if (c == '-')
         [ #  # ][ #  # ]
      66                 :            :                 return '_';
      67                 :            :         return c;
      68                 :            : }
      69                 :            : 
      70                 :          0 : bool parameqn(const char *a, const char *b, size_t n)
      71                 :            : {
      72                 :            :         size_t i;
      73                 :            : 
      74 [ #  # ][ #  # ]:          0 :         for (i = 0; i < n; i++) {
      75 [ #  # ][ #  # ]:          0 :                 if (dash2underscore(a[i]) != dash2underscore(b[i]))
      76                 :            :                         return false;
      77                 :            :         }
      78                 :            :         return true;
      79                 :            : }
      80                 :            : 
      81                 :          0 : bool parameq(const char *a, const char *b)
      82                 :            : {
      83                 :          0 :         return parameqn(a, b, strlen(a)+1);
      84                 :            : }
      85                 :            : 
      86                 :          0 : static int parse_one(char *param,
      87                 :            :                      char *val,
      88                 :            :                      const char *doing,
      89                 :            :                      const struct kernel_param *params,
      90                 :            :                      unsigned num_params,
      91                 :            :                      s16 min_level,
      92                 :            :                      s16 max_level,
      93                 :            :                      int (*handle_unknown)(char *param, char *val,
      94                 :            :                                      const char *doing))
      95                 :            : {
      96                 :            :         unsigned int i;
      97                 :            :         int err;
      98                 :            : 
      99                 :            :         /* Find parameter */
     100         [ #  # ]:          0 :         for (i = 0; i < num_params; i++) {
     101         [ #  # ]:          0 :                 if (parameq(param, params[i].name)) {
     102         [ #  # ]:          0 :                         if (params[i].level < min_level
     103         [ #  # ]:          0 :                             || params[i].level > max_level)
     104                 :            :                                 return 0;
     105                 :            :                         /* No one handled NULL, so do it here. */
     106 [ #  # ][ #  # ]:          0 :                         if (!val &&
     107                 :          0 :                             !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
     108                 :            :                                 return -EINVAL;
     109                 :            :                         pr_debug("handling %s with %p\n", param,
     110                 :            :                                 params[i].ops->set);
     111                 :          0 :                         mutex_lock(&param_lock);
     112                 :          0 :                         err = params[i].ops->set(val, &params[i]);
     113                 :          0 :                         mutex_unlock(&param_lock);
     114                 :          0 :                         return err;
     115                 :            :                 }
     116                 :            :         }
     117                 :            : 
     118         [ #  # ]:          0 :         if (handle_unknown) {
     119                 :            :                 pr_debug("doing %s: %s='%s'\n", doing, param, val);
     120                 :          0 :                 return handle_unknown(param, val, doing);
     121                 :            :         }
     122                 :            : 
     123                 :            :         pr_debug("Unknown argument '%s'\n", param);
     124                 :            :         return -ENOENT;
     125                 :            : }
     126                 :            : 
     127                 :            : /* You can use " around spaces, but can't escape ". */
     128                 :            : /* Hyphens and underscores equivalent in parameter names. */
     129                 :          0 : static char *next_arg(char *args, char **param, char **val)
     130                 :            : {
     131                 :            :         unsigned int i, equals = 0;
     132                 :            :         int in_quote = 0, quoted = 0;
     133                 :            :         char *next;
     134                 :            : 
     135         [ #  # ]:          0 :         if (*args == '"') {
     136                 :          0 :                 args++;
     137                 :            :                 in_quote = 1;
     138                 :            :                 quoted = 1;
     139                 :            :         }
     140                 :            : 
     141         [ #  # ]:          0 :         for (i = 0; args[i]; i++) {
     142 [ #  # ][ #  # ]:          0 :                 if (isspace(args[i]) && !in_quote)
     143                 :            :                         break;
     144         [ #  # ]:          0 :                 if (equals == 0) {
     145         [ #  # ]:          0 :                         if (args[i] == '=')
     146                 :            :                                 equals = i;
     147                 :            :                 }
     148         [ #  # ]:          0 :                 if (args[i] == '"')
     149                 :          0 :                         in_quote = !in_quote;
     150                 :            :         }
     151                 :            : 
     152                 :          0 :         *param = args;
     153         [ #  # ]:          0 :         if (!equals)
     154                 :          0 :                 *val = NULL;
     155                 :            :         else {
     156                 :          0 :                 args[equals] = '\0';
     157                 :          0 :                 *val = args + equals + 1;
     158                 :            : 
     159                 :            :                 /* Don't include quotes in value. */
     160         [ #  # ]:          0 :                 if (**val == '"') {
     161                 :          0 :                         (*val)++;
     162         [ #  # ]:          0 :                         if (args[i-1] == '"')
     163                 :          0 :                                 args[i-1] = '\0';
     164                 :            :                 }
     165 [ #  # ][ #  # ]:          0 :                 if (quoted && args[i-1] == '"')
     166                 :          0 :                         args[i-1] = '\0';
     167                 :            :         }
     168                 :            : 
     169         [ #  # ]:          0 :         if (args[i]) {
     170                 :          0 :                 args[i] = '\0';
     171                 :          0 :                 next = args + i + 1;
     172                 :            :         } else
     173                 :            :                 next = args + i;
     174                 :            : 
     175                 :            :         /* Chew up trailing spaces. */
     176                 :          0 :         return skip_spaces(next);
     177                 :            : }
     178                 :            : 
     179                 :            : /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
     180                 :          0 : int parse_args(const char *doing,
     181                 :            :                char *args,
     182                 :            :                const struct kernel_param *params,
     183                 :            :                unsigned num,
     184                 :            :                s16 min_level,
     185                 :            :                s16 max_level,
     186                 :            :                int (*unknown)(char *param, char *val, const char *doing))
     187                 :            : {
     188                 :            :         char *param, *val;
     189                 :            : 
     190                 :            :         /* Chew leading spaces */
     191                 :          0 :         args = skip_spaces(args);
     192                 :            : 
     193                 :            :         if (*args)
     194                 :            :                 pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args);
     195                 :            : 
     196         [ #  # ]:          0 :         while (*args) {
     197                 :            :                 int ret;
     198                 :            :                 int irq_was_disabled;
     199                 :            : 
     200                 :          0 :                 args = next_arg(args, &param, &val);
     201                 :            :                 irq_was_disabled = irqs_disabled();
     202                 :          0 :                 ret = parse_one(param, val, doing, params, num,
     203                 :            :                                 min_level, max_level, unknown);
     204   [ #  #  #  # ]:          0 :                 if (irq_was_disabled && !irqs_disabled())
     205                 :          0 :                         pr_warn("%s: option '%s' enabled irq's!\n",
     206                 :            :                                 doing, param);
     207                 :            : 
     208   [ #  #  #  # ]:          0 :                 switch (ret) {
     209                 :            :                 case -ENOENT:
     210                 :          0 :                         pr_err("%s: Unknown parameter `%s'\n", doing, param);
     211                 :          0 :                         return ret;
     212                 :            :                 case -ENOSPC:
     213         [ #  # ]:          0 :                         pr_err("%s: `%s' too large for parameter `%s'\n",
     214                 :            :                                doing, val ?: "", param);
     215                 :          0 :                         return ret;
     216                 :            :                 case 0:
     217                 :            :                         break;
     218                 :            :                 default:
     219         [ #  # ]:          0 :                         pr_err("%s: `%s' invalid for parameter `%s'\n",
     220                 :            :                                doing, val ?: "", param);
     221                 :          0 :                         return ret;
     222                 :            :                 }
     223                 :            :         }
     224                 :            : 
     225                 :            :         /* All parsed OK. */
     226                 :            :         return 0;
     227                 :            : }
     228                 :            : 
     229                 :            : /* Lazy bastard, eh? */
     230                 :            : #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn)       \
     231                 :            :         int param_set_##name(const char *val, const struct kernel_param *kp) \
     232                 :            :         {                                                               \
     233                 :            :                 tmptype l;                                              \
     234                 :            :                 int ret;                                                \
     235                 :            :                                                                         \
     236                 :            :                 ret = strtolfn(val, 0, &l);                         \
     237                 :            :                 if (ret < 0 || ((type)l != l))                               \
     238                 :            :                         return ret < 0 ? ret : -EINVAL;                      \
     239                 :            :                 *((type *)kp->arg) = l;                                      \
     240                 :            :                 return 0;                                               \
     241                 :            :         }                                                               \
     242                 :            :         int param_get_##name(char *buffer, const struct kernel_param *kp) \
     243                 :            :         {                                                               \
     244                 :            :                 return scnprintf(buffer, PAGE_SIZE, format,             \
     245                 :            :                                 *((type *)kp->arg));                 \
     246                 :            :         }                                                               \
     247                 :            :         struct kernel_param_ops param_ops_##name = {                    \
     248                 :            :                 .set = param_set_##name,                                \
     249                 :            :                 .get = param_get_##name,                                \
     250                 :            :         };                                                              \
     251                 :            :         EXPORT_SYMBOL(param_set_##name);                                \
     252                 :            :         EXPORT_SYMBOL(param_get_##name);                                \
     253                 :            :         EXPORT_SYMBOL(param_ops_##name)
     254                 :            : 
     255                 :            : 
     256 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, kstrtoul);
                 [ #  # ]
     257 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtol);
                 [ #  # ]
     258 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, kstrtoul);
                 [ #  # ]
     259 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(int, int, "%i", long, kstrtol);
     260 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, kstrtoul);
     261 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(long, long, "%li", long, kstrtol);
     262 [ #  # ][ #  # ]:          0 : STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, kstrtoul);
     263                 :            : 
     264                 :          0 : int param_set_charp(const char *val, const struct kernel_param *kp)
     265                 :            : {
     266         [ #  # ]:          0 :         if (strlen(val) > 1024) {
     267                 :          0 :                 pr_err("%s: string parameter too long\n", kp->name);
     268                 :          0 :                 return -ENOSPC;
     269                 :            :         }
     270                 :            : 
     271                 :          0 :         maybe_kfree_parameter(*(char **)kp->arg);
     272                 :            : 
     273                 :            :         /* This is a hack.  We can't kmalloc in early boot, and we
     274                 :            :          * don't need to; this mangled commandline is preserved. */
     275         [ #  # ]:          0 :         if (slab_is_available()) {
     276                 :          0 :                 *(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
     277         [ #  # ]:          0 :                 if (!*(char **)kp->arg)
     278                 :            :                         return -ENOMEM;
     279                 :          0 :                 strcpy(*(char **)kp->arg, val);
     280                 :            :         } else
     281                 :          0 :                 *(const char **)kp->arg = val;
     282                 :            : 
     283                 :            :         return 0;
     284                 :            : }
     285                 :            : EXPORT_SYMBOL(param_set_charp);
     286                 :            : 
     287                 :          0 : int param_get_charp(char *buffer, const struct kernel_param *kp)
     288                 :            : {
     289                 :          0 :         return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
     290                 :            : }
     291                 :            : EXPORT_SYMBOL(param_get_charp);
     292                 :            : 
     293                 :          0 : static void param_free_charp(void *arg)
     294                 :            : {
     295                 :          0 :         maybe_kfree_parameter(*((char **)arg));
     296                 :          0 : }
     297                 :            : 
     298                 :            : struct kernel_param_ops param_ops_charp = {
     299                 :            :         .set = param_set_charp,
     300                 :            :         .get = param_get_charp,
     301                 :            :         .free = param_free_charp,
     302                 :            : };
     303                 :            : EXPORT_SYMBOL(param_ops_charp);
     304                 :            : 
     305                 :            : /* Actually could be a bool or an int, for historical reasons. */
     306                 :          0 : int param_set_bool(const char *val, const struct kernel_param *kp)
     307                 :            : {
     308                 :            :         /* No equals means "set"... */
     309 [ #  # ][ #  # ]:          0 :         if (!val) val = "1";
                 [ #  # ]
     310                 :            : 
     311                 :            :         /* One of =[yYnN01] */
     312                 :          0 :         return strtobool(val, kp->arg);
     313                 :            : }
     314                 :            : EXPORT_SYMBOL(param_set_bool);
     315                 :            : 
     316                 :          0 : int param_get_bool(char *buffer, const struct kernel_param *kp)
     317                 :            : {
     318                 :            :         /* Y and N chosen as being relatively non-coder friendly */
     319         [ #  # ]:          0 :         return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
     320                 :            : }
     321                 :            : EXPORT_SYMBOL(param_get_bool);
     322                 :            : 
     323                 :            : struct kernel_param_ops param_ops_bool = {
     324                 :            :         .flags = KERNEL_PARAM_FL_NOARG,
     325                 :            :         .set = param_set_bool,
     326                 :            :         .get = param_get_bool,
     327                 :            : };
     328                 :            : EXPORT_SYMBOL(param_ops_bool);
     329                 :            : 
     330                 :            : /* This one must be bool. */
     331                 :          0 : int param_set_invbool(const char *val, const struct kernel_param *kp)
     332                 :            : {
     333                 :            :         int ret;
     334                 :            :         bool boolval;
     335                 :            :         struct kernel_param dummy;
     336                 :            : 
     337                 :            :         dummy.arg = &boolval;
     338                 :            :         ret = param_set_bool(val, &dummy);
     339         [ #  # ]:          0 :         if (ret == 0)
     340                 :          0 :                 *(bool *)kp->arg = !boolval;
     341                 :          0 :         return ret;
     342                 :            : }
     343                 :            : EXPORT_SYMBOL(param_set_invbool);
     344                 :            : 
     345                 :          0 : int param_get_invbool(char *buffer, const struct kernel_param *kp)
     346                 :            : {
     347         [ #  # ]:          0 :         return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y');
     348                 :            : }
     349                 :            : EXPORT_SYMBOL(param_get_invbool);
     350                 :            : 
     351                 :            : struct kernel_param_ops param_ops_invbool = {
     352                 :            :         .set = param_set_invbool,
     353                 :            :         .get = param_get_invbool,
     354                 :            : };
     355                 :            : EXPORT_SYMBOL(param_ops_invbool);
     356                 :            : 
     357                 :          0 : int param_set_bint(const char *val, const struct kernel_param *kp)
     358                 :            : {
     359                 :            :         struct kernel_param boolkp;
     360                 :            :         bool v;
     361                 :            :         int ret;
     362                 :            : 
     363                 :            :         /* Match bool exactly, by re-using it. */
     364                 :            :         boolkp = *kp;
     365                 :            :         boolkp.arg = &v;
     366                 :            : 
     367                 :            :         ret = param_set_bool(val, &boolkp);
     368         [ #  # ]:          0 :         if (ret == 0)
     369                 :          0 :                 *(int *)kp->arg = v;
     370                 :          0 :         return ret;
     371                 :            : }
     372                 :            : EXPORT_SYMBOL(param_set_bint);
     373                 :            : 
     374                 :            : struct kernel_param_ops param_ops_bint = {
     375                 :            :         .flags = KERNEL_PARAM_FL_NOARG,
     376                 :            :         .set = param_set_bint,
     377                 :            :         .get = param_get_int,
     378                 :            : };
     379                 :            : EXPORT_SYMBOL(param_ops_bint);
     380                 :            : 
     381                 :            : /* We break the rule and mangle the string. */
     382                 :          0 : static int param_array(const char *name,
     383                 :            :                        const char *val,
     384                 :            :                        unsigned int min, unsigned int max,
     385                 :            :                        void *elem, int elemsize,
     386                 :            :                        int (*set)(const char *, const struct kernel_param *kp),
     387                 :            :                        s16 level,
     388                 :            :                        unsigned int *num)
     389                 :            : {
     390                 :            :         int ret;
     391                 :            :         struct kernel_param kp;
     392                 :            :         char save;
     393                 :            : 
     394                 :            :         /* Get the name right for errors. */
     395                 :          0 :         kp.name = name;
     396                 :          0 :         kp.arg = elem;
     397                 :          0 :         kp.level = level;
     398                 :            : 
     399                 :          0 :         *num = 0;
     400                 :            :         /* We expect a comma-separated list of values. */
     401                 :            :         do {
     402                 :            :                 int len;
     403                 :            : 
     404         [ #  # ]:          0 :                 if (*num == max) {
     405                 :          0 :                         pr_err("%s: can only take %i arguments\n", name, max);
     406                 :          0 :                         return -EINVAL;
     407                 :            :                 }
     408                 :          0 :                 len = strcspn(val, ",");
     409                 :            : 
     410                 :            :                 /* nul-terminate and parse */
     411                 :          0 :                 save = val[len];
     412                 :          0 :                 ((char *)val)[len] = '\0';
     413         [ #  # ]:          0 :                 BUG_ON(!mutex_is_locked(&param_lock));
     414                 :          0 :                 ret = set(val, &kp);
     415                 :            : 
     416         [ #  # ]:          0 :                 if (ret != 0)
     417                 :            :                         return ret;
     418                 :          0 :                 kp.arg += elemsize;
     419                 :          0 :                 val += len+1;
     420                 :          0 :                 (*num)++;
     421         [ #  # ]:          0 :         } while (save == ',');
     422                 :            : 
     423         [ #  # ]:          0 :         if (*num < min) {
     424                 :          0 :                 pr_err("%s: needs at least %i arguments\n", name, min);
     425                 :          0 :                 return -EINVAL;
     426                 :            :         }
     427                 :            :         return 0;
     428                 :            : }
     429                 :            : 
     430                 :          0 : static int param_array_set(const char *val, const struct kernel_param *kp)
     431                 :            : {
     432                 :          0 :         const struct kparam_array *arr = kp->arr;
     433                 :            :         unsigned int temp_num;
     434                 :            : 
     435         [ #  # ]:          0 :         return param_array(kp->name, val, 1, arr->max, arr->elem,
     436                 :          0 :                            arr->elemsize, arr->ops->set, kp->level,
     437                 :          0 :                            arr->num ?: &temp_num);
     438                 :            : }
     439                 :            : 
     440                 :          0 : static int param_array_get(char *buffer, const struct kernel_param *kp)
     441                 :            : {
     442                 :            :         int i, off, ret;
     443                 :          0 :         const struct kparam_array *arr = kp->arr;
     444                 :            :         struct kernel_param p;
     445                 :            : 
     446                 :          0 :         p = *kp;
     447 [ #  # ][ #  # ]:          0 :         for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
     448         [ #  # ]:          0 :                 if (i)
     449                 :          0 :                         buffer[off++] = ',';
     450                 :          0 :                 p.arg = arr->elem + arr->elemsize * i;
     451         [ #  # ]:          0 :                 BUG_ON(!mutex_is_locked(&param_lock));
     452                 :          0 :                 ret = arr->ops->get(buffer + off, &p);
     453         [ #  # ]:          0 :                 if (ret < 0)
     454                 :            :                         return ret;
     455                 :          0 :                 off += ret;
     456                 :            :         }
     457                 :          0 :         buffer[off] = '\0';
     458                 :          0 :         return off;
     459                 :            : }
     460                 :            : 
     461                 :          0 : static void param_array_free(void *arg)
     462                 :            : {
     463                 :            :         unsigned int i;
     464                 :            :         const struct kparam_array *arr = arg;
     465                 :            : 
     466         [ #  # ]:          0 :         if (arr->ops->free)
     467 [ #  # ][ #  # ]:          0 :                 for (i = 0; i < (arr->num ? *arr->num : arr->max); i++)
     468                 :          0 :                         arr->ops->free(arr->elem + arr->elemsize * i);
     469                 :          0 : }
     470                 :            : 
     471                 :            : struct kernel_param_ops param_array_ops = {
     472                 :            :         .set = param_array_set,
     473                 :            :         .get = param_array_get,
     474                 :            :         .free = param_array_free,
     475                 :            : };
     476                 :            : EXPORT_SYMBOL(param_array_ops);
     477                 :            : 
     478                 :          0 : int param_set_copystring(const char *val, const struct kernel_param *kp)
     479                 :            : {
     480                 :          0 :         const struct kparam_string *kps = kp->str;
     481                 :            : 
     482         [ #  # ]:          0 :         if (strlen(val)+1 > kps->maxlen) {
     483                 :          0 :                 pr_err("%s: string doesn't fit in %u chars.\n",
     484                 :            :                        kp->name, kps->maxlen-1);
     485                 :          0 :                 return -ENOSPC;
     486                 :            :         }
     487                 :          0 :         strcpy(kps->string, val);
     488                 :          0 :         return 0;
     489                 :            : }
     490                 :            : EXPORT_SYMBOL(param_set_copystring);
     491                 :            : 
     492                 :          0 : int param_get_string(char *buffer, const struct kernel_param *kp)
     493                 :            : {
     494                 :          0 :         const struct kparam_string *kps = kp->str;
     495                 :          0 :         return strlcpy(buffer, kps->string, kps->maxlen);
     496                 :            : }
     497                 :            : EXPORT_SYMBOL(param_get_string);
     498                 :            : 
     499                 :            : struct kernel_param_ops param_ops_string = {
     500                 :            :         .set = param_set_copystring,
     501                 :            :         .get = param_get_string,
     502                 :            : };
     503                 :            : EXPORT_SYMBOL(param_ops_string);
     504                 :            : 
     505                 :            : /* sysfs output in /sys/modules/XYZ/parameters/ */
     506                 :            : #define to_module_attr(n) container_of(n, struct module_attribute, attr)
     507                 :            : #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
     508                 :            : 
     509                 :            : extern struct kernel_param __start___param[], __stop___param[];
     510                 :            : 
     511                 :            : struct param_attribute
     512                 :            : {
     513                 :            :         struct module_attribute mattr;
     514                 :            :         const struct kernel_param *param;
     515                 :            : };
     516                 :            : 
     517                 :            : struct module_param_attrs
     518                 :            : {
     519                 :            :         unsigned int num;
     520                 :            :         struct attribute_group grp;
     521                 :            :         struct param_attribute attrs[0];
     522                 :            : };
     523                 :            : 
     524                 :            : #ifdef CONFIG_SYSFS
     525                 :            : #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
     526                 :            : 
     527                 :          0 : static ssize_t param_attr_show(struct module_attribute *mattr,
     528                 :            :                                struct module_kobject *mk, char *buf)
     529                 :            : {
     530                 :            :         int count;
     531                 :            :         struct param_attribute *attribute = to_param_attr(mattr);
     532                 :            : 
     533         [ #  # ]:          0 :         if (!attribute->param->ops->get)
     534                 :            :                 return -EPERM;
     535                 :            : 
     536                 :          0 :         mutex_lock(&param_lock);
     537                 :          0 :         count = attribute->param->ops->get(buf, attribute->param);
     538                 :          0 :         mutex_unlock(&param_lock);
     539         [ #  # ]:          0 :         if (count > 0) {
     540                 :          0 :                 strcat(buf, "\n");
     541                 :          0 :                 ++count;
     542                 :            :         }
     543                 :          0 :         return count;
     544                 :            : }
     545                 :            : 
     546                 :            : /* sysfs always hands a nul-terminated string in buf.  We rely on that. */
     547                 :          0 : static ssize_t param_attr_store(struct module_attribute *mattr,
     548                 :            :                                 struct module_kobject *km,
     549                 :            :                                 const char *buf, size_t len)
     550                 :            : {
     551                 :            :         int err;
     552                 :            :         struct param_attribute *attribute = to_param_attr(mattr);
     553                 :            : 
     554         [ #  # ]:          0 :         if (!attribute->param->ops->set)
     555                 :            :                 return -EPERM;
     556                 :            : 
     557                 :          0 :         mutex_lock(&param_lock);
     558                 :          0 :         err = attribute->param->ops->set(buf, attribute->param);
     559                 :          0 :         mutex_unlock(&param_lock);
     560         [ #  # ]:          0 :         if (!err)
     561                 :          0 :                 return len;
     562                 :            :         return err;
     563                 :            : }
     564                 :            : #endif
     565                 :            : 
     566                 :            : #ifdef CONFIG_MODULES
     567                 :            : #define __modinit
     568                 :            : #else
     569                 :            : #define __modinit __init
     570                 :            : #endif
     571                 :            : 
     572                 :            : #ifdef CONFIG_SYSFS
     573                 :          0 : void __kernel_param_lock(void)
     574                 :            : {
     575                 :          0 :         mutex_lock(&param_lock);
     576                 :          0 : }
     577                 :            : EXPORT_SYMBOL(__kernel_param_lock);
     578                 :            : 
     579                 :          0 : void __kernel_param_unlock(void)
     580                 :            : {
     581                 :          0 :         mutex_unlock(&param_lock);
     582                 :          0 : }
     583                 :            : EXPORT_SYMBOL(__kernel_param_unlock);
     584                 :            : 
     585                 :            : /*
     586                 :            :  * add_sysfs_param - add a parameter to sysfs
     587                 :            :  * @mk: struct module_kobject
     588                 :            :  * @kparam: the actual parameter definition to add to sysfs
     589                 :            :  * @name: name of parameter
     590                 :            :  *
     591                 :            :  * Create a kobject if for a (per-module) parameter if mp NULL, and
     592                 :            :  * create file in sysfs.  Returns an error on out of memory.  Always cleans up
     593                 :            :  * if there's an error.
     594                 :            :  */
     595                 :          0 : static __modinit int add_sysfs_param(struct module_kobject *mk,
     596                 :            :                                      const struct kernel_param *kp,
     597                 :            :                                      const char *name)
     598                 :            : {
     599                 :            :         struct module_param_attrs *new;
     600                 :            :         struct attribute **attrs;
     601                 :            :         int err, num;
     602                 :            : 
     603                 :            :         /* We don't bother calling this with invisible parameters. */
     604         [ #  # ]:          0 :         BUG_ON(!kp->perm);
     605                 :            : 
     606         [ #  # ]:          0 :         if (!mk->mp) {
     607                 :            :                 num = 0;
     608                 :            :                 attrs = NULL;
     609                 :            :         } else {
     610                 :          0 :                 num = mk->mp->num;
     611                 :          0 :                 attrs = mk->mp->grp.attrs;
     612                 :            :         }
     613                 :            : 
     614                 :            :         /* Enlarge. */
     615                 :          0 :         new = krealloc(mk->mp,
     616                 :          0 :                        sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (num+1),
     617                 :            :                        GFP_KERNEL);
     618         [ #  # ]:          0 :         if (!new) {
     619                 :          0 :                 kfree(attrs);
     620                 :            :                 err = -ENOMEM;
     621                 :            :                 goto fail;
     622                 :            :         }
     623                 :            :         /* Despite looking like the typical realloc() bug, this is safe.
     624                 :            :          * We *want* the old 'attrs' to be freed either way, and we'll store
     625                 :            :          * the new one in the success case. */
     626                 :          0 :         attrs = krealloc(attrs, sizeof(new->grp.attrs[0])*(num+2), GFP_KERNEL);
     627         [ #  # ]:          0 :         if (!attrs) {
     628                 :            :                 err = -ENOMEM;
     629                 :            :                 goto fail_free_new;
     630                 :            :         }
     631                 :            : 
     632                 :            :         /* Sysfs wants everything zeroed. */
     633                 :          0 :         memset(new, 0, sizeof(*new));
     634                 :          0 :         memset(&new->attrs[num], 0, sizeof(new->attrs[num]));
     635                 :          0 :         memset(&attrs[num], 0, sizeof(attrs[num]));
     636                 :          0 :         new->grp.name = "parameters";
     637                 :          0 :         new->grp.attrs = attrs;
     638                 :            : 
     639                 :            :         /* Tack new one on the end. */
     640                 :            :         sysfs_attr_init(&new->attrs[num].mattr.attr);
     641                 :          0 :         new->attrs[num].param = kp;
     642                 :          0 :         new->attrs[num].mattr.show = param_attr_show;
     643                 :          0 :         new->attrs[num].mattr.store = param_attr_store;
     644                 :          0 :         new->attrs[num].mattr.attr.name = (char *)name;
     645                 :          0 :         new->attrs[num].mattr.attr.mode = kp->perm;
     646                 :          0 :         new->num = num+1;
     647                 :            : 
     648                 :            :         /* Fix up all the pointers, since krealloc can move us */
     649         [ #  # ]:          0 :         for (num = 0; num < new->num; num++)
     650                 :          0 :                 new->grp.attrs[num] = &new->attrs[num].mattr.attr;
     651                 :          0 :         new->grp.attrs[num] = NULL;
     652                 :            : 
     653                 :          0 :         mk->mp = new;
     654                 :            :         return 0;
     655                 :            : 
     656                 :            : fail_free_new:
     657                 :          0 :         kfree(new);
     658                 :            : fail:
     659                 :          0 :         mk->mp = NULL;
     660                 :            :         return err;
     661                 :            : }
     662                 :            : 
     663                 :            : #ifdef CONFIG_MODULES
     664                 :          0 : static void free_module_param_attrs(struct module_kobject *mk)
     665                 :            : {
     666                 :          0 :         kfree(mk->mp->grp.attrs);
     667                 :          0 :         kfree(mk->mp);
     668                 :          0 :         mk->mp = NULL;
     669                 :          0 : }
     670                 :            : 
     671                 :            : /*
     672                 :            :  * module_param_sysfs_setup - setup sysfs support for one module
     673                 :            :  * @mod: module
     674                 :            :  * @kparam: module parameters (array)
     675                 :            :  * @num_params: number of module parameters
     676                 :            :  *
     677                 :            :  * Adds sysfs entries for module parameters under
     678                 :            :  * /sys/module/[mod->name]/parameters/
     679                 :            :  */
     680                 :          0 : int module_param_sysfs_setup(struct module *mod,
     681                 :            :                              const struct kernel_param *kparam,
     682                 :            :                              unsigned int num_params)
     683                 :            : {
     684                 :            :         int i, err;
     685                 :            :         bool params = false;
     686                 :            : 
     687         [ #  # ]:          0 :         for (i = 0; i < num_params; i++) {
     688         [ #  # ]:          0 :                 if (kparam[i].perm == 0)
     689                 :          0 :                         continue;
     690                 :          0 :                 err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
     691         [ #  # ]:          0 :                 if (err)
     692                 :            :                         return err;
     693                 :            :                 params = true;
     694                 :            :         }
     695                 :            : 
     696         [ #  # ]:          0 :         if (!params)
     697                 :            :                 return 0;
     698                 :            : 
     699                 :            :         /* Create the param group. */
     700                 :          0 :         err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
     701         [ #  # ]:          0 :         if (err)
     702                 :          0 :                 free_module_param_attrs(&mod->mkobj);
     703                 :          0 :         return err;
     704                 :            : }
     705                 :            : 
     706                 :            : /*
     707                 :            :  * module_param_sysfs_remove - remove sysfs support for one module
     708                 :            :  * @mod: module
     709                 :            :  *
     710                 :            :  * Remove sysfs entries for module parameters and the corresponding
     711                 :            :  * kobject.
     712                 :            :  */
     713                 :          0 : void module_param_sysfs_remove(struct module *mod)
     714                 :            : {
     715         [ #  # ]:          0 :         if (mod->mkobj.mp) {
     716                 :          0 :                 sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
     717                 :            :                 /* We are positive that no one is using any param
     718                 :            :                  * attrs at this point.  Deallocate immediately. */
     719                 :          0 :                 free_module_param_attrs(&mod->mkobj);
     720                 :            :         }
     721                 :          0 : }
     722                 :            : #endif
     723                 :            : 
     724                 :          0 : void destroy_params(const struct kernel_param *params, unsigned num)
     725                 :            : {
     726                 :            :         unsigned int i;
     727                 :            : 
     728         [ #  # ]:          0 :         for (i = 0; i < num; i++)
     729         [ #  # ]:          0 :                 if (params[i].ops->free)
     730                 :          0 :                         params[i].ops->free(params[i].arg);
     731                 :          0 : }
     732                 :            : 
     733                 :          0 : static struct module_kobject * __init locate_module_kobject(const char *name)
     734                 :            : {
     735                 :            :         struct module_kobject *mk;
     736                 :            :         struct kobject *kobj;
     737                 :            :         int err;
     738                 :            : 
     739                 :          0 :         kobj = kset_find_obj(module_kset, name);
     740         [ #  # ]:          0 :         if (kobj) {
     741                 :            :                 mk = to_module_kobject(kobj);
     742                 :            :         } else {
     743                 :            :                 mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
     744         [ #  # ]:          0 :                 BUG_ON(!mk);
     745                 :            : 
     746                 :          0 :                 mk->mod = THIS_MODULE;
     747                 :          0 :                 mk->kobj.kset = module_kset;
     748                 :          0 :                 err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
     749                 :            :                                            "%s", name);
     750                 :            : #ifdef CONFIG_MODULES
     751         [ #  # ]:          0 :                 if (!err)
     752                 :            :                         err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
     753                 :            : #endif
     754         [ #  # ]:          0 :                 if (err) {
     755                 :          0 :                         kobject_put(&mk->kobj);
     756                 :          0 :                         pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",
     757                 :            :                                 name, err);
     758                 :          0 :                         return NULL;
     759                 :            :                 }
     760                 :            : 
     761                 :            :                 /* So that we hold reference in both cases. */
     762                 :          0 :                 kobject_get(&mk->kobj);
     763                 :            :         }
     764                 :            : 
     765                 :          0 :         return mk;
     766                 :            : }
     767                 :            : 
     768                 :          0 : static void __init kernel_add_sysfs_param(const char *name,
     769                 :            :                                           struct kernel_param *kparam,
     770                 :            :                                           unsigned int name_skip)
     771                 :            : {
     772                 :            :         struct module_kobject *mk;
     773                 :            :         int err;
     774                 :            : 
     775                 :          0 :         mk = locate_module_kobject(name);
     776         [ #  # ]:          0 :         if (!mk)
     777                 :          0 :                 return;
     778                 :            : 
     779                 :            :         /* We need to remove old parameters before adding more. */
     780         [ #  # ]:          0 :         if (mk->mp)
     781                 :          0 :                 sysfs_remove_group(&mk->kobj, &mk->mp->grp);
     782                 :            : 
     783                 :            :         /* These should not fail at boot. */
     784                 :          0 :         err = add_sysfs_param(mk, kparam, kparam->name + name_skip);
     785         [ #  # ]:          0 :         BUG_ON(err);
     786                 :          0 :         err = sysfs_create_group(&mk->kobj, &mk->mp->grp);
     787         [ #  # ]:          0 :         BUG_ON(err);
     788                 :          0 :         kobject_uevent(&mk->kobj, KOBJ_ADD);
     789                 :          0 :         kobject_put(&mk->kobj);
     790                 :            : }
     791                 :            : 
     792                 :            : /*
     793                 :            :  * param_sysfs_builtin - add sysfs parameters for built-in modules
     794                 :            :  *
     795                 :            :  * Add module_parameters to sysfs for "modules" built into the kernel.
     796                 :            :  *
     797                 :            :  * The "module" name (KBUILD_MODNAME) is stored before a dot, the
     798                 :            :  * "parameter" name is stored behind a dot in kernel_param->name. So,
     799                 :            :  * extract the "module" name for all built-in kernel_param-eters,
     800                 :            :  * and for all who have the same, call kernel_add_sysfs_param.
     801                 :            :  */
     802                 :          0 : static void __init param_sysfs_builtin(void)
     803                 :            : {
     804                 :            :         struct kernel_param *kp;
     805                 :            :         unsigned int name_len;
     806                 :            :         char modname[MODULE_NAME_LEN];
     807                 :            : 
     808         [ #  # ]:          0 :         for (kp = __start___param; kp < __stop___param; kp++) {
     809                 :            :                 char *dot;
     810                 :            : 
     811         [ #  # ]:          0 :                 if (kp->perm == 0)
     812                 :          0 :                         continue;
     813                 :            : 
     814                 :          0 :                 dot = strchr(kp->name, '.');
     815         [ #  # ]:          0 :                 if (!dot) {
     816                 :            :                         /* This happens for core_param() */
     817                 :          0 :                         strcpy(modname, "kernel");
     818                 :            :                         name_len = 0;
     819                 :            :                 } else {
     820                 :          0 :                         name_len = dot - kp->name + 1;
     821                 :          0 :                         strlcpy(modname, kp->name, name_len);
     822                 :            :                 }
     823                 :          0 :                 kernel_add_sysfs_param(modname, kp, name_len);
     824                 :            :         }
     825                 :          0 : }
     826                 :            : 
     827                 :          0 : ssize_t __modver_version_show(struct module_attribute *mattr,
     828                 :            :                               struct module_kobject *mk, char *buf)
     829                 :            : {
     830                 :            :         struct module_version_attribute *vattr =
     831                 :            :                 container_of(mattr, struct module_version_attribute, mattr);
     832                 :            : 
     833                 :          0 :         return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
     834                 :            : }
     835                 :            : 
     836                 :            : extern const struct module_version_attribute *__start___modver[];
     837                 :            : extern const struct module_version_attribute *__stop___modver[];
     838                 :            : 
     839                 :          0 : static void __init version_sysfs_builtin(void)
     840                 :            : {
     841                 :            :         const struct module_version_attribute **p;
     842                 :            :         struct module_kobject *mk;
     843                 :            :         int err;
     844                 :            : 
     845         [ #  # ]:          0 :         for (p = __start___modver; p < __stop___modver; p++) {
     846                 :          0 :                 const struct module_version_attribute *vattr = *p;
     847                 :            : 
     848                 :          0 :                 mk = locate_module_kobject(vattr->module_name);
     849         [ #  # ]:          0 :                 if (mk) {
     850                 :          0 :                         err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
     851                 :          0 :                         kobject_uevent(&mk->kobj, KOBJ_ADD);
     852                 :          0 :                         kobject_put(&mk->kobj);
     853                 :            :                 }
     854                 :            :         }
     855                 :          0 : }
     856                 :            : 
     857                 :            : /* module-related sysfs stuff */
     858                 :            : 
     859                 :          0 : static ssize_t module_attr_show(struct kobject *kobj,
     860                 :            :                                 struct attribute *attr,
     861                 :            :                                 char *buf)
     862                 :            : {
     863                 :            :         struct module_attribute *attribute;
     864                 :            :         struct module_kobject *mk;
     865                 :            :         int ret;
     866                 :            : 
     867                 :            :         attribute = to_module_attr(attr);
     868                 :            :         mk = to_module_kobject(kobj);
     869                 :            : 
     870         [ #  # ]:          0 :         if (!attribute->show)
     871                 :            :                 return -EIO;
     872                 :            : 
     873                 :          0 :         ret = attribute->show(attribute, mk, buf);
     874                 :            : 
     875                 :          0 :         return ret;
     876                 :            : }
     877                 :            : 
     878                 :          0 : static ssize_t module_attr_store(struct kobject *kobj,
     879                 :            :                                 struct attribute *attr,
     880                 :            :                                 const char *buf, size_t len)
     881                 :            : {
     882                 :            :         struct module_attribute *attribute;
     883                 :            :         struct module_kobject *mk;
     884                 :            :         int ret;
     885                 :            : 
     886                 :            :         attribute = to_module_attr(attr);
     887                 :            :         mk = to_module_kobject(kobj);
     888                 :            : 
     889         [ #  # ]:          0 :         if (!attribute->store)
     890                 :            :                 return -EIO;
     891                 :            : 
     892                 :          0 :         ret = attribute->store(attribute, mk, buf, len);
     893                 :            : 
     894                 :          0 :         return ret;
     895                 :            : }
     896                 :            : 
     897                 :            : static const struct sysfs_ops module_sysfs_ops = {
     898                 :            :         .show = module_attr_show,
     899                 :            :         .store = module_attr_store,
     900                 :            : };
     901                 :            : 
     902                 :          0 : static int uevent_filter(struct kset *kset, struct kobject *kobj)
     903                 :            : {
     904                 :            :         struct kobj_type *ktype = get_ktype(kobj);
     905                 :            : 
     906         [ #  # ]:          0 :         if (ktype == &module_ktype)
     907                 :            :                 return 1;
     908                 :          0 :         return 0;
     909                 :            : }
     910                 :            : 
     911                 :            : static const struct kset_uevent_ops module_uevent_ops = {
     912                 :            :         .filter = uevent_filter,
     913                 :            : };
     914                 :            : 
     915                 :            : struct kset *module_kset;
     916                 :            : int module_sysfs_initialized;
     917                 :            : 
     918                 :          0 : static void module_kobj_release(struct kobject *kobj)
     919                 :            : {
     920                 :            :         struct module_kobject *mk = to_module_kobject(kobj);
     921                 :          0 :         complete(mk->kobj_completion);
     922                 :          0 : }
     923                 :            : 
     924                 :            : struct kobj_type module_ktype = {
     925                 :            :         .release   =    module_kobj_release,
     926                 :            :         .sysfs_ops =    &module_sysfs_ops,
     927                 :            : };
     928                 :            : 
     929                 :            : /*
     930                 :            :  * param_sysfs_init - wrapper for built-in params support
     931                 :            :  */
     932                 :          0 : static int __init param_sysfs_init(void)
     933                 :            : {
     934                 :          0 :         module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
     935         [ #  # ]:          0 :         if (!module_kset) {
     936                 :          0 :                 printk(KERN_WARNING "%s (%d): error creating kset\n",
     937                 :            :                         __FILE__, __LINE__);
     938                 :          0 :                 return -ENOMEM;
     939                 :            :         }
     940                 :          0 :         module_sysfs_initialized = 1;
     941                 :            : 
     942                 :          0 :         version_sysfs_builtin();
     943                 :          0 :         param_sysfs_builtin();
     944                 :            : 
     945                 :          0 :         return 0;
     946                 :            : }
     947                 :            : subsys_initcall(param_sysfs_init);
     948                 :            : 
     949                 :            : #endif /* CONFIG_SYSFS */

Generated by: LCOV version 1.9