1 /*	$OpenBSD: lkm.h,v 1.11 2002/01/09 18:20:52 ericj Exp $	*/
2 /*	$NetBSD: lkm.h,v 1.12 1996/02/09 18:25:13 christos Exp $	*/
3 
4 /*
5  * Header file used by loadable kernel modules and loadable kernel module
6  * utilities.
7  *
8  * 23 Jan 93	Terry Lambert		Original
9  *
10  * Copyright (c) 1996 Michael Shalayeff
11  * Copyright (c) 1992 Terrence R. Lambert.
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  *    must display the following acknowledgement:
24  *      This product includes software developed by Terrence R. Lambert.
25  * 4. The name Terrence R. Lambert may not be used to endorse or promote
26  *    products derived from this software without specific prior written
27  *    permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
30  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  */
41 
42 #ifndef _SYS_LKM_H_
43 #define _SYS_LKM_H_
44 
45 #include <sys/queue.h>
46 
47 /*
48  * Supported module types
49  */
50 typedef enum loadmod {
51 	LM_SYSCALL,
52 	LM_VFS,
53 	LM_DEV,
54 	LM_EXEC,
55 	LM_MISC
56 } MODTYPE;
57 
58 
59 #define	LKM_OLDVERSION	1		/* version of module loader */
60 #define	LKM_VERSION	2		/* version of module loader */
61 #define	MAXLKMNAME	32
62 
63 /****************************************************************************/
64 
65 #ifdef _KERNEL
66 
67 /*
68  * Loadable system call
69  */
70 struct lkm_syscall {
71 	MODTYPE		lkm_type;
72 	int		lkm_ver;
73 	char	       *lkm_name;
74 	u_long		lkm_offset;	/* save/assign area */
75 	struct sysent  *lkm_sysent;
76 	struct sysent	lkm_oldent;	/* save area for unload */
77 };
78 
79 /*
80  * Loadable file system
81  */
82 struct lkm_vfs {
83 	MODTYPE		lkm_type;
84 	int		lkm_ver;
85 	char	       *lkm_name;
86 	u_long		lkm_offset;
87 	struct vfsconf *lkm_vfsconf;
88 };
89 
90 /*
91  * Supported device module types
92  */
93 typedef enum devtype {
94 	LM_DT_BLOCK,
95 	LM_DT_CHAR
96 } DEVTYPE;
97 
98 /*
99  * Loadable device driver
100  */
101 struct lkm_dev {
102 	MODTYPE		lkm_type;
103 	int		lkm_ver;
104 	char	       *lkm_name;
105 	u_long		lkm_offset;
106 	DEVTYPE		lkm_devtype;
107 	union {
108 		void		*anon;
109 		struct bdevsw	*bdev;
110 		struct cdevsw	*cdev;
111 	} lkm_dev;
112 	union {
113 		struct bdevsw	bdev;
114 		struct cdevsw	cdev;
115 	} lkm_olddev;
116 };
117 
118 /*
119  * Exec loader
120  */
121 struct lkm_exec {
122 	MODTYPE		lkm_type;
123 	int		lkm_ver;
124 	char	       *lkm_name;
125 	u_long		lkm_offset;
126 	struct execsw  *lkm_exec;
127 	struct execsw	lkm_oldexec;
128 };
129 
130 /*
131  * Miscellaneous module (complex load/unload, potentially complex stat
132  */
133 struct lkm_misc {
134 	MODTYPE		lkm_type;
135 	int		lkm_ver;
136 	char	       *lkm_name;
137 	u_long		lkm_offset;
138 };
139 
140 /*
141  * Any module (to get type and name info without knowing type)
142  */
143 struct lkm_any {
144 	MODTYPE		lkm_type;
145 	int		lkm_ver;
146 	char	       *lkm_name;
147 	u_long		lkm_offset;
148 };
149 
150 
151 /*
152  * Generic reference ala XEvent to allow single entry point in the xxxinit()
153  * routine.
154  */
155 union lkm_generic {
156 	struct lkm_any		*lkm_any;
157 	struct lkm_syscall	*lkm_syscall;
158 	struct lkm_vfs		*lkm_vfs;
159 	struct lkm_dev		*lkm_dev;
160 	struct lkm_exec		*lkm_exec;
161 	struct lkm_misc		*lkm_misc;
162 };
163 
164 /*
165  * Per module information structure
166  */
167 struct lkm_table {
168 	TAILQ_ENTRY(lkm_table)	list;
169 	int	type;
170 	u_long	size;
171 	u_long	offset;
172 	u_long	area;
173 
174 	int	ver;		/* version (INIT) */
175 	int	refcnt;		/* reference count (INIT) */
176 	int	depcnt;		/* dependency count (INIT) */
177 	int	id;		/* identifier (INIT) */
178 
179 	int	(*entry)(struct lkm_table *, int, int);	/* entry function */
180 	union lkm_generic	private;	/* module private data */
181 
182 				/* ddb support */
183 	char	*syms;		/* ? start of symbol table */
184 	u_long	sym_size;	/* ? size of symbol table */
185 	u_long	sym_offset;	/* ? offset */
186 	u_long	sym_symsize;	/* ? symsize */
187 	char	*sym_addr;	/* ? addr */
188 	int	sym_id;		/* ? symtab id from ddb */
189 };
190 
191 
192 #define	LKM_E_LOAD	1
193 #define	LKM_E_UNLOAD	2
194 #define	LKM_E_STAT	3
195 
196 
197 #define	MOD_SYSCALL(name,callslot,sysentp)	\
198 	static struct lkm_syscall _module = {	\
199 		LM_SYSCALL,			\
200 		LKM_VERSION,			\
201 		name,				\
202 		callslot,			\
203 		sysentp				\
204 	};
205 
206 #define	MOD_VFS(name,vfsslot,vfsconf)		\
207 	static struct lkm_vfs _module = {	\
208 		LM_VFS,				\
209 		LKM_VERSION,			\
210 		name,				\
211 		vfsslot,			\
212 		vfsconf				\
213 	};
214 
215 #define	MOD_DEV(name,devtype,devslot,devp)	\
216 	static struct lkm_dev _module = {	\
217 		LM_DEV,				\
218 		LKM_VERSION,			\
219 		name,				\
220 		devslot,			\
221 		devtype,			\
222 		{(void *)devp}			\
223 	};
224 
225 #define	MOD_EXEC(name,execslot,execsw)		\
226 	static struct lkm_exec _module = {	\
227 		LM_EXEC,			\
228 		LKM_VERSION,			\
229 		name,				\
230 		execslot,			\
231 		execsw				\
232 	};
233 
234 #define	MOD_MISC(name)				\
235 	static struct lkm_misc _module = {	\
236 		LM_MISC,			\
237 		LKM_VERSION,			\
238 		name				\
239 	};
240 
241 
242 extern int lkm_nofunc(struct lkm_table *lkmtp, int cmd);
243 extern struct lkm_table *lkm_list(struct lkm_table *);
244 extern int lkmdispatch(struct lkm_table *, int);
245 
246 /*
247  * DISPATCH -- body function for use in module entry point function;
248  * generally, the function body will consist entirely of a single
249  * DISPATCH line.
250  *
251  * If load/unload/stat are called on each corresponding entry instance.
252  * If no function is desired for load/stat/unload, lkm_nofunc() should
253  * be specified.  "cmd" is passed to each function so that a single
254  * function can be used if desired.
255  */
256 #define	DISPATCH(lkmtp,cmd,ver,load,unload,stat)			\
257 	if (ver != LKM_VERSION)						\
258 		return EINVAL;	/* version mismatch */			\
259 	switch (cmd) {							\
260 	int	error;							\
261 	case LKM_E_LOAD:						\
262 		lkmtp->private.lkm_any = (struct lkm_any *)&_module;	\
263 		if ((error = load(lkmtp, cmd)) != 0)			\
264 			return error;					\
265 		break;							\
266 	case LKM_E_UNLOAD:						\
267 		if ((error = unload(lkmtp, cmd)) != 0)			\
268 			return error;					\
269 		break;							\
270 	case LKM_E_STAT:						\
271 		if ((error = stat(lkmtp, cmd)) != 0)			\
272 			return error;					\
273 		break;							\
274 	}								\
275 	return lkmdispatch(lkmtp, cmd);
276 
277 #endif /* _KERNEL */
278 
279 /****************************************************************************/
280 
281 /*
282  * IOCTL's recognized by /dev/lkm
283  */
284 #define	LMRESERV_O	_IOWR('K', 0, struct lmc_resrv)
285 #define	LMLOADBUF	_IOW('K', 1, struct lmc_loadbuf)
286 #define	LMUNRESRV	_IO('K', 2)
287 #define	LMREADY		_IOW('K', 3, u_long)
288 #define	LMRESERV	_IOWR('K', 4, struct lmc_resrv)
289 
290 #define	LMLOAD		_IOW('K', 9, struct lmc_load)
291 #define	LMUNLOAD	_IOWR('K', 10, struct lmc_unload)
292 #define	LMSTAT		_IOWR('K', 11, struct lmc_stat)
293 #define	LMLOADSYMS	_IOW('K', 12, struct lmc_loadbuf)
294 
295 #define	MODIOBUF	512		/* # of bytes at a time to loadbuf */
296 
297 /*
298  * IOCTL arguments
299  */
300 
301 
302 /*
303  * Reserve a page-aligned block of kernel memory for the module
304  */
305 struct lmc_resrv {
306 	u_long	size;		/* IN: size of module to reserve */
307 	char	*name;		/* IN: name (must be provided */
308 	int	slot;		/* OUT: allocated slot (module ID) */
309 	u_long	addr;		/* OUT: Link-to address */
310 				/* ddb support */
311 	char	*syms;		/* ? start of symbol table */
312 	u_long	sym_size;	/* ? size of symbol table */
313 	u_long	sym_offset;	/* ? offset */
314 	u_long	sym_symsize;	/* ? symsize */
315 	char	*sym_addr;	/* ? addr */
316 };
317 
318 
319 /*
320  * Copy a buffer at a time into the allocated area in the kernel; writes
321  * are assumed to occur contiguously.
322  */
323 struct lmc_loadbuf {
324 	int	cnt;		/* IN: # of chars pointed to by data */
325 	char	*data;		/* IN: pointer to data buffer */
326 };
327 
328 
329 /*
330  * Load a module (assumes it's been mmapped to address before call)
331  */
332 struct lmc_load {
333 	caddr_t	address;	/* IN: user space mmap address */
334 	int	status;		/* OUT: status of operation */
335 	int	id;		/* OUT: module ID if loaded */
336 };
337 
338 /*
339  * Unload a module (by name/id)
340  */
341 struct lmc_unload {
342 	int	id;		/* IN: module ID to unload */
343 	char	*name;		/* IN: module name to unload if id -1 */
344 	int	status;		/* OUT: status of operation */
345 };
346 
347 
348 /*
349  * Get module information for a given id (or name if id == -1).
350  */
351 struct lmc_stat {
352 	int	id;		/* IN: module ID to unload */
353 	char	*name;		/* IN/OUT: name of module */
354 	u_long	offset;		/* OUT: target table offset */
355 	MODTYPE	type;		/* OUT: type of module */
356 	u_long	area;		/* OUT: kernel load addr */
357 	u_long	size;		/* OUT: module size (pages) */
358 	u_long	private;	/* OUT: module private data */
359 	int	ver;		/* OUT: lkm compile version */
360 };
361 
362 #endif	/* !_SYS_LKM_H_ */
363