|
|
1.1 root 1: /*
2: * kern_lkm.c
3: *
4: * functions and pseudo-device for loadable kernel modules
5: *
6: * 05 Jun 93 Terry Lambert Release cleanup
7: * 10 Feb 93 Terry Lambert Original
8: *
9: * Copyright (c) 1992 Terrence R. Lambert.
10: * All rights reserved.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by Terrence R. Lambert.
23: * 4. The name Terrence R. Lambert may not be used to endorse or promote
24: * products derived from this software without specific prior written
25: * permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
28: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30: * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
31: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37: * SUCH DAMAGE.
38: *
39: * kern_lkm.c,v 1.3.2.1 1993/07/22 13:01:55 cgd Exp
40: */
41:
42: #include "param.h"
43: #include "systm.h"
44: #include "ioctl.h"
45: #include "tty.h"
46: #include "conf.h"
47: #include "file.h"
48: #include "proc.h"
49: #include "uio.h"
50: #include "kernel.h"
51: #include "vnode.h"
52: #include "malloc.h"
53: #include "vm/vm.h"
54: #include "vm/vm_param.h"
55: #include "vm/vm_kern.h"
56: #include "mount.h"
57: #include "exec.h"
58: #include "lkm.h"
59:
60: #define PAGESIZE 1024 /* kmem_alloc() allocation quantum*/
61:
62: #define LKM_ALLOC 0x01
63: #define LKM_WANT 0x02
64:
65:
66: #define LKMS_IDLE 0x00
67: #define LKMS_RESERVED 0x01
68: #define LKMS_LOADING 0x02
69: #define LKMS_LOADED 0x04
70: #define LKMS_UNLOADING 0x08
71:
72: static int lkm_v = 0;
73: static int lkm_state = LKMS_IDLE;
74:
75: #ifndef MAXLKMS
76: #define MAXLKMS 20
77: #endif
78:
79: static struct lkm_table lkmods[ MAXLKMS]; /* table of loaded modules*/
80: static struct lkm_table *curp; /* global for in-progress ops*/
81:
82: /*ARGSUSED*/
83: lkmopen( dev, flag, devtype, p)
84: dev_t dev;
85: int flag;
86: int devtype;
87: struct proc *p;
88: {
89: int error;
90:
91: if( minor( dev) != 0)
92: return( ENXIO); /* bad minor #*/
93:
94: /*
95: * Use of the loadable kernel module device must be exclusive; we
96: * may try to remove this restriction later, but it's really no
97: * hardship.
98: */
99: while( lkm_v & LKM_ALLOC) {
100: if( flag & FNONBLOCK) /* don't hang*/
101: return( EBUSY);
102: lkm_v |= LKM_WANT;
103: /*
104: * Sleep pending unlock; we use tsleep() to allow
105: * an alarm out of the open.
106: */
107: if( error = tsleep( (caddr_t)&lkm_v, TTIPRI|PCATCH, "LKM", 0))
108: return( error); /* leave LKM_WANT set -- no problem*/
109: }
110: lkm_v |= LKM_ALLOC;
111:
112: return( 0); /* pseudo-device open*/
113: }
114:
115:
116: /*
117: * l k m u n r e s e r v e
118: *
119: * Unreserve the memory associated with the current loaded module; done on
120: * a coerced close of the lkm device (close on premature exit of modload)
121: * or explicitly by modload as a result of a link failure.
122: */
123: static int
124: lkmunreserve()
125: {
126: if( lkm_state == LKMS_IDLE)
127: return;
128:
129: /*
130: * Actually unreserve the memory
131: */
132: kmem_free( kmem_map, curp->area, curp->size);/**/
133:
134: lkm_state = LKMS_IDLE;
135: }
136:
137:
138: lkmclose( dev, flag, mode, p)
139: dev_t dev;
140: int flag;
141: int mode;
142: struct proc *p;
143: {
144: if( !( lkm_v & LKM_ALLOC)) {
145: #ifdef DEBUG
146: printf( "LKM: close before open!\n");
147: #endif /* DEBUG*/
148: return( EBADF);
149: }
150:
151: /* do this before waking the herd...*/
152: if( !curp->used) {
153: /*
154: * If we close before setting used, we have aborted
155: * by way of error or by way of close-on-exit from
156: * a premature exit of "modload".
157: */
158: lkmunreserve(); /* coerce state to LKM_IDLE*/
159: }
160:
161: lkm_v &= ~LKM_ALLOC;
162: wakeup( (caddr_t)&lkm_v); /* thundering herd "problem" here*/
163:
164: return( 0); /* pseudo-device closed*/
165: }
166:
167:
168: /*ARGSUSED*/
169: lkmioctl( dev, cmd, data, flag)
170: dev_t dev;
171: int cmd;
172: caddr_t data;
173: int flag;
174: {
175: int err = 0;
176: int i;
177: struct lmc_resrv *resrvp;
178: struct lmc_loadbuf *loadbufp;
179: struct lmc_unload *unloadp;
180: struct lmc_stat *statp;
181: int (*funcp)();
182: char istr[ MAXLKMNAME];
183:
184: switch( cmd) {
185: case LMRESERV: /* reserve pages for a module*/
186: if ((flag & FWRITE) == 0) /* only allow this if writing */
187: return EPERM;
188:
189: resrvp = (struct lmc_resrv *)data;
190:
191: /*
192: * Find a free slot.
193: */
194: for( i = 0; i < MAXLKMS; i++) {
195: if( !lkmods[ i].used)
196: break;
197: }
198: if( i == MAXLKMS) {
199: err = ENOMEM; /* no slots available*/
200: break;
201: }
202: curp = &lkmods[ i];
203: curp->id = i; /* self reference slot offset*/
204:
205: resrvp->slot = i; /* return slot*/
206:
207: /*
208: * Get memory for module
209: */
210: curp->size = resrvp->size;
211:
212: curp->area = (char *)kmem_alloc( kmem_map, curp->size);/**/
213:
214: curp->offset = 0; /* load offset*/
215:
216: resrvp->addr = (unsigned long)curp->area; /* ret kernel addr*/
217:
218: #ifdef DEBUG
219: printf( "LKM: LMRESERV (actual = 0x%08x)\n", curp->area);
220: printf( "LKM: LMRESERV (adjusted = 0x%08x)\n",
221: trunc_page(curp->area));
222: #endif /* DEBUG*/
223: lkm_state = LKMS_RESERVED;
224: break;
225:
226: case LMLOADBUF: /* Copy in; stateful, follows LMRESERV*/
227: if ((flag & FWRITE) == 0) /* only allow this if writing */
228: return EPERM;
229:
230: loadbufp = (struct lmc_loadbuf *)data;
231: if( lkm_state != LKMS_RESERVED && lkm_state != LKMS_LOADING) {
232: err = ENOMEM;
233: break;
234: }
235:
236: /* account for odd size (non-page multiple) copyin*/
237: i = MIN( curp->size - curp->offset, MODIOBUF);
238:
239: /* copy in buffer full of data*/
240: if( err = copyin( (caddr_t)loadbufp->data, (caddr_t)curp->area + curp->offset, i))
241: break;
242:
243: if( ( curp->offset + i) < curp->size) {
244: lkm_state = LKMS_LOADING;
245: #ifdef DEBUG
246: printf( "LKM: LMLOADBUF (loading @ %d of %d, i = %d)\n",
247: curp->offset, curp->size, i);
248: #endif /* DEBUG*/
249: } else {
250: lkm_state = LKMS_LOADED;
251: #ifdef DEBUG
252: printf( "LKM: LMLOADBUF (loaded)\n");
253: #endif /* DEBUG*/
254: }
255: curp->offset += MODIOBUF;
256: break;
257:
258: case LMUNRESRV: /* discard reserved pages for a module*/
259: if ((flag & FWRITE) == 0) /* only allow this if writing */
260: return EPERM;
261:
262: lkmunreserve(); /* coerce state to LKM_IDLE*/
263: #ifdef DEBUG
264: printf( "LKM: LMUNRESERV\n");
265: #endif /* DEBUG*/
266: break;
267:
268: case LMREADY: /* module loaded: call entry*/
269: if ((flag & FWRITE) == 0) /* only allow this if writing */
270: return EPERM;
271:
272: if( lkm_state != LKMS_LOADED) {
273:
274: #ifdef DEBUG
275: printf( "lkm_state is %02x\n", lkm_state);
276: #endif /* DEBUG*/
277: err = ENXIO;
278: break;
279: }
280:
281: curp->entry = (int (*)()) (*((int *) ( data)));
282:
283: /* call entry(load)... (assigns "private" portion)*/
284: if( err = (*(curp->entry))( curp, LKM_E_LOAD, LKM_VERSION)) {
285: /*
286: * Module may refuse loading or may have a
287: * version mismatch...
288: */
289: lkm_state = LKMS_UNLOADING; /* for lkmunreserve*/
290: lkmunreserve(); /* free memory*/
291: curp->used = 0; /* free slot*/
292: break;
293: }
294:
295: curp->used = 1;
296: #ifdef DEBUG
297: printf( "LKM: LMREADY\n");
298: #endif /* DEBUG*/
299: lkm_state = LKMS_IDLE;
300: break;
301:
302: case LMUNLOAD: /* unload a module*/
303: if ((flag & FWRITE) == 0) /* only allow this if writing */
304: return EPERM;
305:
306: unloadp = (struct lmc_unload *)data;
307:
308: if( ( i = unloadp->id) == -1) { /* unload by name*/
309: /*
310: * Copy name and lookup id from all loaded
311: * modules.
312: */
313: copystr( unloadp->name, istr, MAXLKMNAME-1, NULL);
314: /*
315: * look up id...
316: */
317: for( i = 0; i < MAXLKMS; i++) {
318: if( !lkmods[ i].used)
319: continue;
320: if( !strcmp( istr,
321: lkmods[ i].private.lkm_any->lkm_name))
322: break;
323: }
324: }
325:
326: /*
327: * Range check the value; on failure, return EINVAL
328: */
329: if( i < 0 || i >= MAXLKMS) {
330: err = EINVAL;
331: break;
332: }
333:
334: curp = &lkmods[ i];
335:
336: /* call entry(unload)*/
337: if( (*(curp->entry))( curp, LKM_E_UNLOAD, LKM_VERSION)) {
338: err = EBUSY;
339: break;
340: }
341:
342: lkm_state = LKMS_UNLOADING; /* non-idle for lkmunreserve*/
343: lkmunreserve(); /* free memory*/
344: curp->used = 0; /* free slot*/
345: break;
346:
347: case LMSTAT: /* stat a module by id/name*/
348: /* allow readers and writers to stat */
349:
350: statp = (struct lmc_stat *)data;
351:
352: if( ( i = statp->id) == -1) { /* stat by name*/
353: /*
354: * Copy name and lookup id from all loaded
355: * modules.
356: */
357: copystr( statp->name, istr, MAXLKMNAME-1, NULL);
358: /*
359: * look up id...
360: */
361: for( i = 0; i < MAXLKMS; i++) {
362: if( !lkmods[ i].used)
363: continue;
364: if( !strcmp( istr,
365: lkmods[ i].private.lkm_any->lkm_name))
366: break;
367: }
368:
369: if( i == MAXLKMS) { /* Not found*/
370: err = ENOENT;
371: break;
372: }
373: }
374:
375: /*
376: * Range check the value; on failure, return EINVAL
377: */
378: if( i < 0 || i >= MAXLKMS) {
379: err = EINVAL;
380: break;
381: }
382:
383: curp = &lkmods[ i];
384:
385: if( !curp->used) { /* Not found*/
386: err = ENOENT;
387: break;
388: }
389:
390: /*
391: * Copy out stat information for this module...
392: */
393: statp->id = curp->id;
394: statp->offset = curp->private.lkm_any->lkm_offset;
395: statp->type = curp->private.lkm_any->lkm_type;
396: statp->area = curp->area;
397: statp->size = curp->size / PAGESIZE;
398: statp->private = (unsigned long)curp->private.lkm_any;
399: statp->ver = curp->private.lkm_any->lkm_ver;
400: copystr( curp->private.lkm_any->lkm_name,
401: statp->name,
402: MAXLKMNAME - 2,
403: NULL);
404:
405: break;
406:
407: default: /* bad ioctl()...*/
408: err = ENOTTY;
409: break;
410: }
411:
412: return (err);
413: }
414:
415:
416: /*********************************************************************/
417:
418:
419: /*
420: * l k m n o s y s
421: *
422: * Acts like "nosys" but can be identified in sysent for dynamic call
423: * number assignment for a limited number of calls.
424: *
425: * Place holder for system call slots reserved for loadable modules.
426: */
427: lkmnosys()
428: {
429: return( nosys());
430: }
431:
432: /*
433: * l k m e n o d e v
434: *
435: * Acts like "enodev", but can be identified in cdevsw and bdevsw for
436: * dynamic driver major number assignment for a limited number of
437: * drivers.
438: *
439: * Place holder for device switch slots reserved for loadable modules.
440: */
441: int
442: lkmenodev()
443: {
444: return( enodev());
445: }
446:
447: /*********************************************************************/
448:
449:
450: int
451: lkmexists( lkmtp)
452: struct lkm_table *lkmtp;
453: {
454: int i;
455:
456: /*
457: * see if name exists...
458: */
459: for( i = 0; i < MAXLKMS; i++) {
460: /*
461: * An unused module and the one we are testing are not
462: * considered.
463: */
464: if( !lkmods[ i].used || &lkmods[ i] == lkmtp)
465: continue;
466: if( !strcmp( lkmtp->private.lkm_any->lkm_name,
467: lkmods[ i].private.lkm_any->lkm_name))
468: return( 1); /* already loaded...*/
469: }
470:
471: return( 0); /* module not loaded...*/
472: }
473:
474:
475: /*
476: * For the loadable system call described by the structure pointed to
477: * by lkmtp, load/unload/stat it depending on the cmd requested.
478: */
479: static int
480: _lkm_syscall( lkmtp, cmd)
481: struct lkm_table *lkmtp;
482: int cmd;
483: {
484: struct lkm_syscall *args = lkmtp->private.lkm_syscall;
485: int i;
486: int err = 0;
487: extern int nsysent; /* init_sysent.c*/
488:
489: switch( cmd) {
490: case LKM_E_LOAD:
491: /* don't load twice!*/
492: if( lkmexists( lkmtp))
493: return( EEXIST);
494: if( ( i = args->lkm_offset) == -1) { /* auto*/
495: /*
496: * Search the table looking for a slot...
497: */
498: for( i = 0; i < nsysent; i++)
499: if( sysent[ i].sy_call == lkmnosys)
500: break; /* found it!*/
501: /* out of allocable slots?*/
502: if( i == nsysent) {
503: err = ENFILE;
504: break;
505: }
506: } else { /* assign*/
507: if( i < 0 || i >= nsysent) {
508: err = EINVAL;
509: break;
510: }
511: }
512:
513: /* save old*/
514: bcopy( &sysent[ i], &(args->lkm_oldent), sizeof( struct sysent));
515:
516: /* replace with new*/
517: bcopy( args->lkm_sysent, &sysent[ i], sizeof( struct sysent));
518:
519: /* done!*/
520: args->lkm_offset = i; /* slot in sysent[]*/
521:
522: break;
523:
524: case LKM_E_UNLOAD:
525: /* current slot...*/
526: i = args->lkm_offset;
527:
528: /* replace current slot contents with old contents*/
529: bcopy( &(args->lkm_oldent), &sysent[ i], sizeof( struct sysent));
530:
531: break;
532:
533: case LKM_E_STAT: /* no special handling...*/
534: break;
535: }
536:
537: return( err);
538: }
539:
540:
541: /*
542: * For the loadable virtual file system described by the structure pointed
543: * to by lkmtp, load/unload/stat it depending on the cmd requested.
544: */
545: static int
546: _lkm_vfs( lkmtp, cmd)
547: struct lkm_table *lkmtp;
548: int cmd;
549: {
550: struct lkm_vfs *args = lkmtp->private.lkm_vfs;
551: int i;
552: int err = 0;
553:
554: switch( cmd) {
555: case LKM_E_LOAD:
556: /* don't load twice!*/
557: if( lkmexists( lkmtp))
558: return( EEXIST);
559: /*
560: * Currently, the VFS and mount code in 386BSD is malformed;
561: * this means that the per volume file system identifier is
562: * the index into the table rather than the name; this means
563: * that only the file systems already known to 386BSD are
564: * allowable, since all others don't have fixed offsets.
565: * Interestingly, Dell UNIX has this same bug with their VFS
566: * implementation, but generic AT&T SVR4 does not.
567: *
568: * I will correct the VFS code when I get a chance.
569: */
570: i = args->lkm_offset;
571: if( i < 0 || i > MOUNT_MAXTYPE) {
572: err = EINVAL;
573: break;
574: }
575:
576: if( vfssw[ i] != (struct vfsops *)0) {
577: err = EEXIST;
578: break;
579: }
580:
581: /*
582: * Set up file system
583: */
584: vfssw[ i] = args->lkm_vfsops;
585:
586: /*
587: * Call init function for this VFS...
588: */
589: ( *(vfssw[ i]->vfs_init))( args->lkm_flags);
590:
591: /* done!*/
592: args->lkm_offset = i; /* slot in sysent[]*/
593:
594: break;
595:
596: case LKM_E_UNLOAD:
597: /* current slot...*/
598: i = args->lkm_offset;
599:
600: /* replace current slot contents with old contents*/
601: vfssw[ i] = (struct vfsops *)0;
602:
603: break;
604:
605: case LKM_E_STAT: /* no special handling...*/
606: break;
607: }
608:
609: return( err);
610: }
611:
612:
613: /*
614: * For the loadable device driver described by the structure pointed to
615: * by lkmtp, load/unload/stat it depending on the cmd requested.
616: */
617: static int
618: _lkm_dev( lkmtp, cmd)
619: struct lkm_table *lkmtp;
620: int cmd;
621: {
622: struct lkm_dev *args = lkmtp->private.lkm_dev;
623: int i;
624: int err = 0;
625: extern int nblkdev; /* i386/i386/conf.c*/
626: extern int nchrdev; /* i386/i386/conf.c*/
627:
628: switch( cmd) {
629: case LKM_E_LOAD:
630: /* don't load twice!*/
631: if( lkmexists( lkmtp))
632: return( EEXIST);
633: switch( args->lkm_devtype) {
634: case LM_DT_BLOCK:
635: if( ( i = args->lkm_offset) == -1) { /* auto*/
636: /*
637: * Search the table looking for a slot...
638: */
639: for( i = 0; i < nblkdev; i++)
640: if( bdevsw[ i].d_open == lkmenodev)
641: break; /* found it!*/
642: /* out of allocable slots?*/
643: if( i == nblkdev) {
644: err = ENFILE;
645: break;
646: }
647: } else { /* assign*/
648: if( i < 0 || i >= nblkdev) {
649: err = EINVAL;
650: break;
651: }
652: }
653:
654: /* save old*/
655: bcopy( &bdevsw[ i], &(args->lkm_olddev.bdev), sizeof( struct bdevsw));
656:
657: /* replace with new*/
658: bcopy( args->lkm_dev.bdev, &bdevsw[ i], sizeof( struct bdevsw));
659:
660: /* done!*/
661: args->lkm_offset = i; /* slot in bdevsw[]*/
662: break;
663:
664: case LM_DT_CHAR:
665: if( ( i = args->lkm_offset) == -1) { /* auto*/
666: /*
667: * Search the table looking for a slot...
668: */
669: for( i = 0; i < nchrdev; i++)
670: if( cdevsw[ i].d_open == lkmenodev)
671: break; /* found it!*/
672: /* out of allocable slots?*/
673: if( i == nchrdev) {
674: err = ENFILE;
675: break;
676: }
677: } else { /* assign*/
678: if( i < 0 || i >= nchrdev) {
679: err = EINVAL;
680: break;
681: }
682: }
683:
684: /* save old*/
685: bcopy( &cdevsw[ i], &(args->lkm_olddev.cdev), sizeof( struct cdevsw));
686:
687: /* replace with new*/
688: bcopy( args->lkm_dev.cdev, &cdevsw[ i], sizeof( struct cdevsw));
689:
690: /* done!*/
691: args->lkm_offset = i; /* slot in cdevsw[]*/
692:
693: break;
694:
695: default:
696: err = ENODEV;
697: break;
698: }
699: break;
700:
701: case LKM_E_UNLOAD:
702: /* current slot...*/
703: i = args->lkm_offset;
704:
705: switch( args->lkm_devtype) {
706: case LM_DT_BLOCK:
707: /* replace current slot contents with old contents*/
708: bcopy( &(args->lkm_olddev.bdev), &bdevsw[ i], sizeof( struct bdevsw));
709: break;
710:
711: case LM_DT_CHAR:
712: /* replace current slot contents with old contents*/
713: bcopy( &(args->lkm_olddev.cdev), &cdevsw[ i], sizeof( struct cdevsw));
714: break;
715:
716: default:
717: err = ENODEV;
718: break;
719: }
720: break;
721:
722: case LKM_E_STAT: /* no special handling...*/
723: break;
724: }
725:
726: return( err);
727: }
728:
729:
730: #ifdef STREAMS
731: /*
732: * For the loadable streams module described by the structure pointed to
733: * by lkmtp, load/unload/stat it depending on the cmd requested.
734: */
735: static int
736: _lkm_strmod( lkmtp, cmd)
737: struct lkm_table *lkmtp;
738: int cmd;
739: {
740: struct lkm_strmod *args = lkmtp->private.lkm_strmod;
741: int i;
742: int err = 0;
743:
744: switch( cmd) {
745: case LKM_E_LOAD:
746: /* don't load twice!*/
747: if( lkmexists( lkmtp))
748: return( EEXIST);
749: break;
750:
751: case LKM_E_UNLOAD:
752: break;
753:
754: case LKM_E_STAT: /* no special handling...*/
755: break;
756: }
757:
758: return( err);
759: }
760: #endif /* STREAMS*/
761:
762: #ifdef LKM_EXEC /* XXX NOTDEF YET!!! - cgd */
763: /*
764: * For the loadable execution class described by the structure pointed to
765: * by lkmtp, load/unload/stat it depending on the cmd requested.
766: */
767: static int
768: _lkm_exec( lkmtp, cmd)
769: struct lkm_table *lkmtp;
770: int cmd;
771: {
772: struct lkm_exec *args = lkmtp->private.lkm_exec;
773: int i;
774: int err = 0;
775:
776: switch( cmd) {
777: case LKM_E_LOAD:
778: /* don't load twice!*/
779: if( lkmexists( lkmtp))
780: return( EEXIST);
781: if( ( i = args->lkm_offset) == -1) { /* auto*/
782: /*
783: * Search the table looking for a slot...
784: */
785: for( i = 0; i < nexecs; i++)
786: if( execsw[ i].m_size == 0)
787: break; /* found it!*/
788: /* out of allocable slots?*/
789: if( i == nexecs) {
790: err = ENFILE;
791: break;
792: }
793: } else { /* assign*/
794: if( i < 0 || i >= nexecs) {
795: err = EINVAL;
796: break;
797: }
798: }
799:
800: /* save old*/
801: bcopy( &execsw[ i], &(args->lkm_oldexec), sizeof( struct execsw));
802:
803: /* replace with new*/
804: bcopy( args->lkm_exec, &execsw[ i], sizeof( struct execsw));
805:
806: /* done!*/
807: args->lkm_offset = i; /* slot in execsw[]*/
808:
809: break;
810:
811: case LKM_E_UNLOAD:
812: /* current slot...*/
813: i = args->lkm_offset;
814:
815: /* replace current slot contents with old contents*/
816: bcopy( &execsw[ i], &(args->lkm_oldexec), sizeof( struct execsw));
817:
818: break;
819:
820: case LKM_E_STAT: /* no special handling...*/
821: break;
822: }
823:
824: return( err);
825: }
826: #endif /* LKM_EXEC */
827:
828: /*
829: * This code handles the per-module type "wiring-in" of loadable modules
830: * into existing kernel tables. For "LM_MISC" modules, wiring and unwiring
831: * is assumed to be done in their entry routines internal to the module
832: * itself.
833: */
834: lkmdispatch( lkmtp, cmd)
835: struct lkm_table *lkmtp;
836: int cmd;
837: {
838: int err = 0; /* default = success*/
839:
840: switch( lkmtp->private.lkm_any->lkm_type) {
841: case LM_SYSCALL:
842: err = _lkm_syscall( lkmtp, cmd);
843: break;
844:
845: case LM_VFS:
846: err = _lkm_vfs( lkmtp, cmd);
847: break;
848:
849: case LM_DEV:
850: {
851: struct lkm_dev *args = lkmtp->private.lkm_dev;
852: }
853: break;
854:
855: #ifdef STREAMS
856: case LM_STRMOD:
857: {
858: struct lkm_strmod *args = lkmtp->private.lkm_strmod;
859: }
860: break;
861:
862: #endif /* STREAMS*/
863:
864: #ifdef LKM_EXEC
865: case LM_EXEC:
866: err = _lkm_exec( lkmtp, cmd);
867: break;
868: #endif /* LKM_EXEC */
869:
870: case LM_MISC: /* ignore content -- no "misc-specific" procedure*/
871: break;
872:
873: default:
874: err = ENXIO; /* unknown type*/
875: break;
876: }
877:
878: return( err);
879: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.