master
  1/*	$NetBSD: module.h,v 1.48 2021/10/24 06:52:26 skrll Exp $	*/
  2
  3/*-
  4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
  5 * All rights reserved.
  6 *
  7 * Redistribution and use in source and binary forms, with or without
  8 * modification, are permitted provided that the following conditions
  9 * are met:
 10 * 1. Redistributions of source code must retain the above copyright
 11 *    notice, this list of conditions and the following disclaimer.
 12 * 2. Redistributions in binary form must reproduce the above copyright
 13 *    notice, this list of conditions and the following disclaimer in the
 14 *    documentation and/or other materials provided with the distribution.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 26 * POSSIBILITY OF SUCH DAMAGE.
 27 */
 28
 29#ifndef _SYS_MODULE_H_
 30#define _SYS_MODULE_H_
 31
 32#include <sys/types.h>
 33#include <sys/param.h>
 34#include <sys/cdefs.h>
 35#include <sys/uio.h>
 36
 37#define	MAXMODNAME	32
 38#define	MAXMODDEPS	10
 39
 40/* Module classes, provided only for system boot and module validation. */
 41typedef enum modclass {
 42	MODULE_CLASS_ANY,
 43	MODULE_CLASS_MISC,
 44	MODULE_CLASS_VFS,
 45	MODULE_CLASS_DRIVER,
 46	MODULE_CLASS_EXEC,
 47	MODULE_CLASS_SECMODEL,
 48	MODULE_CLASS_BUFQ,
 49	MODULE_CLASS_MAX
 50} modclass_t;
 51
 52/* Module sources: where did it come from? */
 53typedef enum modsrc {
 54	MODULE_SOURCE_KERNEL,
 55	MODULE_SOURCE_BOOT,
 56	MODULE_SOURCE_FILESYS
 57} modsrc_t;
 58
 59/* Commands passed to module control routine. */
 60typedef enum modcmd {
 61	MODULE_CMD_INIT,		/* mandatory */
 62	MODULE_CMD_FINI,		/* mandatory */
 63	MODULE_CMD_STAT,		/* optional */
 64	MODULE_CMD_AUTOUNLOAD,		/* optional */
 65} modcmd_t;
 66
 67#ifdef _KERNEL
 68
 69#include <sys/kernel.h>
 70#include <sys/mutex.h>
 71#include <sys/queue.h>
 72#include <sys/specificdata.h>
 73
 74#include <prop/proplib.h>
 75
 76/* Module header structure. */
 77typedef struct modinfo {
 78	u_int			mi_version;
 79	modclass_t		mi_class;
 80	int			(*mi_modcmd)(modcmd_t, void *);
 81	const char		*mi_name;
 82	const char		*mi_required;
 83} const modinfo_t;
 84
 85/* Per module information, maintained by kern_module.c */
 86
 87struct sysctllog;
 88
 89typedef struct module {
 90	u_int			mod_refcnt;
 91	int			mod_flags;
 92#define MODFLG_MUST_FORCE	0x01
 93#define MODFLG_AUTO_LOADED	0x02
 94	const modinfo_t		*mod_info;
 95	struct kobj		*mod_kobj;
 96	TAILQ_ENTRY(module)	mod_chain;
 97	struct module		*(*mod_required)[MAXMODDEPS];
 98	u_int			mod_nrequired;
 99	u_int			mod_arequired;
100	modsrc_t		mod_source;
101	time_t			mod_autotime;
102	specificdata_reference	mod_sdref;
103	struct sysctllog	*mod_sysctllog;
104} module_t;
105
106/*
107 * Per-module linkage.  Loadable modules have a `link_set_modules' section
108 * containing only one entry, pointing to the module's modinfo_t record.
109 * For the kernel, `link_set_modules' can contain multiple entries and
110 * records all modules built into the kernel at link time.
111 *
112 * Alternatively, in some environments rump kernels use
113 * __attribute__((constructor)) due to link sets being
114 * difficult (impossible?) to implement (e.g. GNU gold, OS X, etc.)
115 * If we're cold (read: rump_init() has not been called), we lob the
116 * module onto the list to be handled when rump_init() runs.
117 * nb. it's not possible to use in-kernel locking mechanisms here since
118 * the code runs before rump_init().  We solve the problem by decreeing
119 * that thou shalt not call dlopen()/dlclose() for rump kernel components
120 * from multiple threads before calling rump_init().
121 */
122
123#ifdef RUMP_USE_CTOR
124struct modinfo_chain {
125	const struct modinfo	*mc_info;
126	LIST_ENTRY(modinfo_chain) mc_entries;
127};
128LIST_HEAD(modinfo_boot_chain, modinfo_chain);
129#define _MODULE_REGISTER(name)						\
130static struct modinfo_chain __CONCAT(mc,name) = {			\
131	.mc_info = &__CONCAT(name,_modinfo),				\
132};									\
133static void __CONCAT(modctor_,name)(void) __attribute__((__constructor__));\
134static void __CONCAT(modctor_,name)(void)				\
135{									\
136	extern struct modinfo_boot_chain modinfo_boot_chain;		\
137	if (cold) {							\
138		struct modinfo_chain *mc = &__CONCAT(mc,name);		\
139		LIST_INSERT_HEAD(&modinfo_boot_chain, mc, mc_entries);	\
140	}								\
141}									\
142									\
143static void __CONCAT(moddtor_,name)(void) __attribute__((__destructor__));\
144static void __CONCAT(moddtor_,name)(void)				\
145{									\
146	struct modinfo_chain *mc = &__CONCAT(mc,name);			\
147	if (cold) {							\
148		LIST_REMOVE(mc, mc_entries);				\
149	}								\
150}
151
152#else /* RUMP_USE_CTOR */
153
154#define _MODULE_REGISTER(name) __link_set_add_rodata(modules, __CONCAT(name,_modinfo));
155
156#endif /* RUMP_USE_CTOR */
157
158#define	MODULE(class, name, required)				\
159static int __CONCAT(name,_modcmd)(modcmd_t, void *);		\
160static const modinfo_t __CONCAT(name,_modinfo) = {		\
161	.mi_version = __NetBSD_Version__,			\
162	.mi_class = (class),					\
163	.mi_modcmd = __CONCAT(name,_modcmd),			\
164	.mi_name = __STRING(name),				\
165	.mi_required = (required)				\
166}; 								\
167_MODULE_REGISTER(name)
168
169TAILQ_HEAD(modlist, module);
170
171extern struct vm_map	*module_map;
172extern u_int		module_count;
173extern u_int		module_builtinlist;
174extern struct modlist	module_list;
175extern struct modlist	module_builtins;
176extern u_int		module_gen;
177
178void	module_init(void);
179void	module_start_unload_thread(void);
180void	module_builtin_require_force(void);
181void	module_init_md(void);
182void	module_init_class(modclass_t);
183int	module_prime(const char *, void *, size_t);
184
185module_t *module_kernel(void);
186const char *module_name(struct module *);
187modsrc_t module_source(struct module *);
188bool	module_compatible(int, int);
189int	module_load(const char *, int, prop_dictionary_t, modclass_t);
190int	module_builtin_add(modinfo_t * const *, size_t, bool);
191int	module_builtin_remove(modinfo_t *, bool);
192int	module_autoload(const char *, modclass_t);
193int	module_unload(const char *);
194void	module_hold(module_t *);
195void	module_rele(module_t *);
196int	module_find_section(const char *, void **, size_t *);
197void	module_thread_kick(void);
198void	module_load_vfs_init(void);
199
200specificdata_key_t module_specific_key_create(specificdata_key_t *, specificdata_dtor_t);
201void	module_specific_key_delete(specificdata_key_t);
202void	*module_getspecific(module_t *, specificdata_key_t);
203void	module_setspecific(module_t *, specificdata_key_t, void *);
204void	*module_register_callbacks(void (*)(struct module *),
205				  void (*)(struct module *));
206void	module_unregister_callbacks(void *);
207
208void	module_whatis(uintptr_t, void (*)(const char *, ...)
209    __printflike(1, 2));
210void	module_print_list(void (*)(const char *, ...) __printflike(1, 2));
211
212#ifdef _MODULE_INTERNAL
213extern
214int	(*module_load_vfs_vec)(const char *, int, bool, module_t *,
215			       prop_dictionary_t *);
216int	module_load_vfs(const char *, int, bool, module_t *,
217			prop_dictionary_t *);
218void	module_error(const char *, ...) __printflike(1, 2);
219void	module_print(const char *, ...) __printflike(1, 2);
220#endif /* _MODULE_INTERNAL */
221
222#define MODULE_BASE_SIZE 64
223extern char	module_base[MODULE_BASE_SIZE];
224extern const char	*module_machine;
225
226struct netbsd32_modctl_args;
227extern int compat32_80_modctl_compat_stub(struct lwp *,
228    const struct netbsd32_modctl_args *, register_t *);
229
230#else	/* _KERNEL */
231
232#include <stdint.h>
233
234#endif	/* _KERNEL */
235
236typedef struct modctl_load {
237	const char *ml_filename;
238
239#define MODCTL_NO_PROP		0x2
240#define MODCTL_LOAD_FORCE	0x1
241	int ml_flags;
242
243	const char *ml_props;
244	size_t ml_propslen;
245} modctl_load_t;
246
247enum modctl {
248	MODCTL_LOAD,		/* modctl_load_t *ml */
249	MODCTL_UNLOAD,		/* char *name */
250	MODCTL_OSTAT,		/* struct iovec *buffer */
251	MODCTL_EXISTS,		/* enum: 0: load, 1: autoload */
252	MODCTL_STAT		/* struct iovec *buffer */
253};
254
255/*
256 * This structure is used with the newer version of MODCTL_STAT, which
257 * exports strings of arbitrary length for the list of required modules.
258 */
259typedef struct modstat {
260	char		ms_name[MAXMODNAME];
261	uint64_t	ms_addr;
262	modsrc_t	ms_source;
263	modclass_t	ms_class;
264	u_int		ms_size;
265	u_int		ms_refcnt;
266	u_int		ms_flags;
267	u_int		ms_reqoffset;	/* offset to module's required list
268					   from beginning of iovec buffer! */
269} modstat_t;
270
271int	modctl(int, void *);
272
273#ifdef _KERNEL
274/* attention: pointers passed are userland pointers!,
275   see modctl_load_t */
276int	handle_modctl_load(const char *, int, const char *, size_t);
277#endif
278
279#endif	/* !_SYS_MODULE_H_ */