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