Annotation of Net2/kern/kern_lkm.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.