xref: /f-stack/freebsd/sys/module.h (revision 22ce4aff)
1a9643ea8Slogwang /*-
2*22ce4affSfengbojiang  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*22ce4affSfengbojiang  *
4a9643ea8Slogwang  * Copyright (c) 1997 Doug Rabson
5a9643ea8Slogwang  * All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
8a9643ea8Slogwang  * modification, are permitted provided that the following conditions
9a9643ea8Slogwang  * are met:
10a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright
11a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer.
12a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
13a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer in the
14a9643ea8Slogwang  *    documentation and/or other materials provided with the distribution.
15a9643ea8Slogwang  *
16a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18a9643ea8Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19a9643ea8Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20a9643ea8Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21a9643ea8Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22a9643ea8Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23a9643ea8Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24a9643ea8Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25a9643ea8Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26a9643ea8Slogwang  * SUCH DAMAGE.
27a9643ea8Slogwang  *
28a9643ea8Slogwang  * $FreeBSD$
29a9643ea8Slogwang  */
30a9643ea8Slogwang 
31a9643ea8Slogwang #ifndef _SYS_MODULE_H_
32a9643ea8Slogwang #define _SYS_MODULE_H_
33a9643ea8Slogwang 
34a9643ea8Slogwang /*
35a9643ea8Slogwang  * Module metadata types
36a9643ea8Slogwang  */
37a9643ea8Slogwang #define	MDT_DEPEND	1		/* argument is a module name */
38a9643ea8Slogwang #define	MDT_MODULE	2		/* module declaration */
39a9643ea8Slogwang #define	MDT_VERSION	3		/* module version(s) */
40a9643ea8Slogwang #define	MDT_PNP_INFO	4		/* Plug and play hints record */
41a9643ea8Slogwang 
42a9643ea8Slogwang #define	MDT_STRUCT_VERSION	1	/* version of metadata structure */
43a9643ea8Slogwang #define	MDT_SETNAME	"modmetadata_set"
44a9643ea8Slogwang 
45a9643ea8Slogwang typedef enum modeventtype {
46a9643ea8Slogwang 	MOD_LOAD,
47a9643ea8Slogwang 	MOD_UNLOAD,
48a9643ea8Slogwang 	MOD_SHUTDOWN,
49a9643ea8Slogwang 	MOD_QUIESCE
50a9643ea8Slogwang } modeventtype_t;
51a9643ea8Slogwang 
52a9643ea8Slogwang typedef struct module *module_t;
53a9643ea8Slogwang typedef int (*modeventhand_t)(module_t, int /* modeventtype_t */, void *);
54a9643ea8Slogwang 
55a9643ea8Slogwang /*
56a9643ea8Slogwang  * Struct for registering modules statically via SYSINIT.
57a9643ea8Slogwang  */
58a9643ea8Slogwang typedef struct moduledata {
59a9643ea8Slogwang 	const char	*name;		/* module name */
60a9643ea8Slogwang 	modeventhand_t  evhand;		/* event handler */
61a9643ea8Slogwang 	void		*priv;		/* extra data */
62a9643ea8Slogwang } moduledata_t;
63a9643ea8Slogwang 
64a9643ea8Slogwang /*
65a9643ea8Slogwang  * A module can use this to report module specific data to the user via
66a9643ea8Slogwang  * kldstat(2).
67a9643ea8Slogwang  */
68a9643ea8Slogwang typedef union modspecific {
69a9643ea8Slogwang 	int	intval;
70a9643ea8Slogwang 	u_int	uintval;
71a9643ea8Slogwang 	long	longval;
72a9643ea8Slogwang 	u_long	ulongval;
73a9643ea8Slogwang } modspecific_t;
74a9643ea8Slogwang 
75a9643ea8Slogwang /*
76a9643ea8Slogwang  * Module dependency declaration
77a9643ea8Slogwang  */
78a9643ea8Slogwang struct mod_depend {
79a9643ea8Slogwang 	int	md_ver_minimum;
80a9643ea8Slogwang 	int	md_ver_preferred;
81a9643ea8Slogwang 	int	md_ver_maximum;
82a9643ea8Slogwang };
83a9643ea8Slogwang 
84a9643ea8Slogwang /*
85a9643ea8Slogwang  * Module version declaration
86a9643ea8Slogwang  */
87a9643ea8Slogwang struct mod_version {
88a9643ea8Slogwang 	int	mv_version;
89a9643ea8Slogwang };
90a9643ea8Slogwang 
91a9643ea8Slogwang struct mod_metadata {
92a9643ea8Slogwang 	int		md_version;	/* structure version MDTV_* */
93a9643ea8Slogwang 	int		md_type;	/* type of entry MDT_* */
94a9643ea8Slogwang 	const void	*md_data;	/* specific data */
95a9643ea8Slogwang 	const char	*md_cval;	/* common string label */
96a9643ea8Slogwang };
97a9643ea8Slogwang 
98a9643ea8Slogwang struct mod_pnp_match_info
99a9643ea8Slogwang {
100a9643ea8Slogwang 	const char *descr;	/* Description of the table */
101a9643ea8Slogwang 	const char *bus;	/* Name of the bus for this table */
102a9643ea8Slogwang 	const void *table;	/* Pointer to pnp table */
103a9643ea8Slogwang 	int entry_len;		/* Length of each entry in the table (may be */
104a9643ea8Slogwang 				/*   longer than descr describes). */
105a9643ea8Slogwang 	int num_entry;		/* Number of entries in the table */
106a9643ea8Slogwang };
107a9643ea8Slogwang #ifdef	_KERNEL
108a9643ea8Slogwang 
109a9643ea8Slogwang #include <sys/linker_set.h>
110a9643ea8Slogwang 
111*22ce4affSfengbojiang #define	MODULE_METADATA_CONCAT(uniquifier)	_mod_metadata##uniquifier
112a9643ea8Slogwang #define	MODULE_METADATA(uniquifier, type, data, cval)			\
113*22ce4affSfengbojiang 	static struct mod_metadata MODULE_METADATA_CONCAT(uniquifier) = {	\
114a9643ea8Slogwang 		MDT_STRUCT_VERSION,					\
115a9643ea8Slogwang 		type,							\
116a9643ea8Slogwang 		data,							\
117a9643ea8Slogwang 		cval							\
118a9643ea8Slogwang 	};								\
119*22ce4affSfengbojiang 	DATA_SET(modmetadata_set, MODULE_METADATA_CONCAT(uniquifier))
120a9643ea8Slogwang 
121a9643ea8Slogwang #define	MODULE_DEPEND(module, mdepend, vmin, vpref, vmax)		\
122a9643ea8Slogwang 	static struct mod_depend _##module##_depend_on_##mdepend	\
123a9643ea8Slogwang 	    __section(".data") = {					\
124a9643ea8Slogwang 		vmin,							\
125a9643ea8Slogwang 		vpref,							\
126a9643ea8Slogwang 		vmax							\
127a9643ea8Slogwang 	};								\
128a9643ea8Slogwang 	MODULE_METADATA(_md_##module##_on_##mdepend, MDT_DEPEND,	\
129a9643ea8Slogwang 	    &_##module##_depend_on_##mdepend, #mdepend)
130a9643ea8Slogwang 
131a9643ea8Slogwang /*
132a9643ea8Slogwang  * Every kernel has a 'kernel' module with the version set to
133a9643ea8Slogwang  * __FreeBSD_version.  We embed a MODULE_DEPEND() inside every module
134a9643ea8Slogwang  * that depends on the 'kernel' module.  It uses the current value of
135a9643ea8Slogwang  * __FreeBSD_version as the minimum and preferred versions.  For the
136a9643ea8Slogwang  * maximum version it rounds the version up to the end of its branch
137a9643ea8Slogwang  * (i.e. M99999 for M.x).  This allows a module built on M.x to work
138a9643ea8Slogwang  * on M.y systems where y >= x, but fail on M.z systems where z < x.
139a9643ea8Slogwang  */
140a9643ea8Slogwang #define	MODULE_KERNEL_MAXVER	(roundup(__FreeBSD_version, 100000) - 1)
141a9643ea8Slogwang 
142a9643ea8Slogwang #define	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, maxver)	\
143a9643ea8Slogwang 	MODULE_DEPEND(name, kernel, __FreeBSD_version,			\
144a9643ea8Slogwang 	    __FreeBSD_version, maxver);					\
145*22ce4affSfengbojiang 	MODULE_METADATA(_md_##name, MDT_MODULE, &data, __XSTRING(name));\
146a9643ea8Slogwang 	SYSINIT(name##module, sub, order, module_register_init, &data);	\
147a9643ea8Slogwang 	struct __hack
148a9643ea8Slogwang 
149*22ce4affSfengbojiang #ifdef KLD_TIED
150*22ce4affSfengbojiang #define	DECLARE_MODULE(name, data, sub, order)				\
151*22ce4affSfengbojiang 	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, __FreeBSD_version)
152*22ce4affSfengbojiang #else
153a9643ea8Slogwang #define	DECLARE_MODULE(name, data, sub, order)							\
154a9643ea8Slogwang 	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, MODULE_KERNEL_MAXVER)
155*22ce4affSfengbojiang #endif
156a9643ea8Slogwang 
157a9643ea8Slogwang /*
158a9643ea8Slogwang  * The module declared with DECLARE_MODULE_TIED can only be loaded
159a9643ea8Slogwang  * into the kernel with exactly the same __FreeBSD_version.
160a9643ea8Slogwang  *
161a9643ea8Slogwang  * Use it for modules that use kernel interfaces that are not stable
162a9643ea8Slogwang  * even on STABLE/X branches.
163a9643ea8Slogwang  */
164a9643ea8Slogwang #define	DECLARE_MODULE_TIED(name, data, sub, order)			\
165a9643ea8Slogwang 	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, __FreeBSD_version)
166a9643ea8Slogwang 
167*22ce4affSfengbojiang #define	MODULE_VERSION_CONCAT(module, version)	_##module##_version
168a9643ea8Slogwang #define	MODULE_VERSION(module, version)					\
169*22ce4affSfengbojiang 	static struct mod_version MODULE_VERSION_CONCAT(module, version)\
170a9643ea8Slogwang 	    __section(".data") = {					\
171a9643ea8Slogwang 		version							\
172a9643ea8Slogwang 	};								\
173*22ce4affSfengbojiang 	MODULE_METADATA(MODULE_VERSION_CONCAT(module, version), MDT_VERSION,\
174*22ce4affSfengbojiang 	    &MODULE_VERSION_CONCAT(module, version), __XSTRING(module))
175a9643ea8Slogwang 
176a9643ea8Slogwang /**
177a9643ea8Slogwang  * Generic macros to create pnp info hints that modules may export
178a9643ea8Slogwang  * to allow external tools to parse their internal device tables
179a9643ea8Slogwang  * to make an informed guess about what driver(s) to load.
180a9643ea8Slogwang  */
181*22ce4affSfengbojiang #define	MODULE_PNP_INFO(d, b, unique, t, n)				\
182a9643ea8Slogwang 	static const struct mod_pnp_match_info _module_pnp_##b##_##unique = {	\
183a9643ea8Slogwang 		.descr = d,						\
184a9643ea8Slogwang 		.bus = #b,						\
185a9643ea8Slogwang 		.table = t,						\
186*22ce4affSfengbojiang 		.entry_len = sizeof((t)[0]),				\
187a9643ea8Slogwang 		.num_entry = n						\
188a9643ea8Slogwang 	};								\
189a9643ea8Slogwang 	MODULE_METADATA(_md_##b##_pnpinfo_##unique, MDT_PNP_INFO,	\
190a9643ea8Slogwang 	    &_module_pnp_##b##_##unique, #b);
191a9643ea8Slogwang /**
192a9643ea8Slogwang  * descr is a string that describes each entry in the table. The general
193*22ce4affSfengbojiang  * form is the grammar (TYPE:pnp_name[/pnp_name];)*
194a9643ea8Slogwang  * where TYPE is one of the following:
195a9643ea8Slogwang  *	U8	uint8_t element
196a9643ea8Slogwang  *	V8	like U8 and 0xff means match any
197a9643ea8Slogwang  *	G16	uint16_t element, any value >= matches
198a9643ea8Slogwang  *	L16	uint16_t element, any value <= matches
199a9643ea8Slogwang  *	M16	uint16_t element, mask of which of the following fields to use.
200a9643ea8Slogwang  *	U16	uint16_t element
201a9643ea8Slogwang  *	V16	like U16 and 0xffff means match any
202a9643ea8Slogwang  *	U32	uint32_t element
203a9643ea8Slogwang  *	V32	like U32 and 0xffffffff means match any
204a9643ea8Slogwang  *	W32	Two 16-bit values with first pnp_name in LSW and second in MSW.
205a9643ea8Slogwang  *	Z	pointer to a string to match exactly
206*22ce4affSfengbojiang  *	D	pointer to a string to human readable description for device
207a9643ea8Slogwang  *	P	A pointer that should be ignored
208a9643ea8Slogwang  *	E	EISA PNP Identifier (in binary, but bus publishes string)
209*22ce4affSfengbojiang  *	T	Key for whole table. pnp_name=value. must be last, if present.
210a9643ea8Slogwang  *
211a9643ea8Slogwang  * The pnp_name "#" is reserved for other fields that should be ignored.
212*22ce4affSfengbojiang  * Otherwise pnp_name must match the name from the parent device's pnpinfo
213*22ce4affSfengbojiang  * output. The second pnp_name is used for the W32 type.
214a9643ea8Slogwang  */
215a9643ea8Slogwang 
216a9643ea8Slogwang extern struct sx modules_sx;
217a9643ea8Slogwang 
218a9643ea8Slogwang #define	MOD_XLOCK	sx_xlock(&modules_sx)
219a9643ea8Slogwang #define	MOD_SLOCK	sx_slock(&modules_sx)
220a9643ea8Slogwang #define	MOD_XUNLOCK	sx_xunlock(&modules_sx)
221a9643ea8Slogwang #define	MOD_SUNLOCK	sx_sunlock(&modules_sx)
222a9643ea8Slogwang #define	MOD_LOCK_ASSERT	sx_assert(&modules_sx, SX_LOCKED)
223a9643ea8Slogwang #define	MOD_XLOCK_ASSERT	sx_assert(&modules_sx, SX_XLOCKED)
224a9643ea8Slogwang 
225a9643ea8Slogwang struct linker_file;
226a9643ea8Slogwang 
227a9643ea8Slogwang void	module_register_init(const void *);
228a9643ea8Slogwang int	module_register(const struct moduledata *, struct linker_file *);
229a9643ea8Slogwang module_t	module_lookupbyname(const char *);
230a9643ea8Slogwang module_t	module_lookupbyid(int);
231a9643ea8Slogwang int	module_quiesce(module_t);
232a9643ea8Slogwang void	module_reference(module_t);
233a9643ea8Slogwang void	module_release(module_t);
234a9643ea8Slogwang int	module_unload(module_t);
235a9643ea8Slogwang int	module_getid(module_t);
236a9643ea8Slogwang module_t	module_getfnext(module_t);
237a9643ea8Slogwang const char *	module_getname(module_t);
238a9643ea8Slogwang void	module_setspecific(module_t, modspecific_t *);
239a9643ea8Slogwang struct linker_file *module_file(module_t);
240a9643ea8Slogwang 
241a9643ea8Slogwang #ifdef	MOD_DEBUG
242a9643ea8Slogwang extern int mod_debug;
243a9643ea8Slogwang #define	MOD_DEBUG_REFS	1
244a9643ea8Slogwang 
245a9643ea8Slogwang #define	MOD_DPF(cat, args) do {						\
246a9643ea8Slogwang 	if (mod_debug & MOD_DEBUG_##cat)				\
247*22ce4affSfengbojiang 		printf args;						\
248a9643ea8Slogwang } while (0)
249a9643ea8Slogwang 
250a9643ea8Slogwang #else	/* !MOD_DEBUG */
251a9643ea8Slogwang 
252a9643ea8Slogwang #define	MOD_DPF(cat, args)
253a9643ea8Slogwang #endif
254a9643ea8Slogwang #endif	/* _KERNEL */
255a9643ea8Slogwang 
256a9643ea8Slogwang #define	MAXMODNAME	32
257a9643ea8Slogwang 
258a9643ea8Slogwang struct module_stat {
259a9643ea8Slogwang 	int		version;	/* set to sizeof(struct module_stat) */
260a9643ea8Slogwang 	char		name[MAXMODNAME];
261a9643ea8Slogwang 	int		refs;
262a9643ea8Slogwang 	int		id;
263a9643ea8Slogwang 	modspecific_t	data;
264a9643ea8Slogwang };
265a9643ea8Slogwang 
266a9643ea8Slogwang #ifndef _KERNEL
267a9643ea8Slogwang 
268a9643ea8Slogwang #include <sys/cdefs.h>
269a9643ea8Slogwang 
270a9643ea8Slogwang __BEGIN_DECLS
271a9643ea8Slogwang int	modnext(int _modid);
272a9643ea8Slogwang int	modfnext(int _modid);
273a9643ea8Slogwang int	modstat(int _modid, struct module_stat *_stat);
274a9643ea8Slogwang int	modfind(const char *_name);
275a9643ea8Slogwang __END_DECLS
276a9643ea8Slogwang 
277a9643ea8Slogwang #endif
278a9643ea8Slogwang 
279a9643ea8Slogwang #endif	/* !_SYS_MODULE_H_ */
280