Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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 : &param_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)	(&param_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(&params[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 				err = params[i].ops->set(val, &params[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, &param, &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 */