add support for terry lambert's loadable kernel modules.
needs a bit of cleanup, but overall: SLICK!
This commit is contained in:
parent
91016c92d6
commit
57d3a6d525
|
@ -59,6 +59,7 @@
|
|||
# bpf* packet filter
|
||||
# speaker pc speaker
|
||||
# dcf* dcf clock
|
||||
# lkm loadable kernel modules interface
|
||||
#
|
||||
|
||||
PATH=/sbin:/bin/:/usr/bin
|
||||
|
@ -69,7 +70,7 @@ case $i in
|
|||
|
||||
all)
|
||||
sh MAKEDEV std wt0 fd0 fd1 wd0 wd1 sd0 sd1 tty0 tty1 pty0 st0
|
||||
sh MAKEDEV ch0 cd0 lpt0 lpt1 lpt2 lpa0 lpa1 lpa2 speaker
|
||||
sh MAKEDEV ch0 cd0 lpt0 lpt1 lpt2 lpa0 lpa1 lpa2 speaker lkm
|
||||
;;
|
||||
|
||||
std)
|
||||
|
@ -300,6 +301,13 @@ speaker)
|
|||
chown root.wheel speaker
|
||||
;;
|
||||
|
||||
lkm)
|
||||
rm -f lkm
|
||||
mknod lkm c 28 0
|
||||
chown root.kmem lkm
|
||||
chmod 640 lkm
|
||||
;;
|
||||
|
||||
local)
|
||||
umask 0
|
||||
sh MAKEDEV.local
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
# @(#)Makefile 5.4.1.1 (Berkeley) 5/7/91
|
||||
#
|
||||
# $Header: /cvsroot/src/sbin/Makefile,v 1.8 1993/04/09 23:13:38 cgd Exp $
|
||||
# $Header: /cvsroot/src/sbin/Makefile,v 1.9 1993/06/07 19:52:08 cgd Exp $
|
||||
|
||||
# Not ported: XNSrouted enpload
|
||||
# Missing: icheck ncheck
|
||||
|
||||
SUBDIR= badsect chown clri disklabel dmesg dump dumpfs fastboot fsck \
|
||||
halt ifconfig init mknod mount mount_isofs mount_miscfs mount_pcfs \
|
||||
mountd newfs nfsd nfsiod ping quotacheck reboot restore route \
|
||||
routed savecore shutdown slattach swapon tunefs umount
|
||||
halt ifconfig init mknod modload modunload mount mount_isofs \
|
||||
mount_miscfs mount_pcfs mountd newfs nfsd nfsiod ping \
|
||||
quotacheck reboot restore route routed savecore shutdown \
|
||||
slattach swapon tunefs umount
|
||||
|
||||
.if make(clean) || make(cleandir)
|
||||
SUBDIR+= fdisk
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# Makefile for modload
|
||||
#
|
||||
# 25 May 93 Terry Lambert Original
|
||||
#
|
||||
# Copyright (c) 1993 Terrence R. Lambert.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by Terrence R. Lambert.
|
||||
# 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $Id: Makefile,v 1.1 1993/06/07 19:52:10 cgd Exp $
|
||||
#
|
||||
|
||||
PROG= modload
|
||||
CFLAGS=-DKERNEL
|
||||
NOMAN= noman
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,548 @@
|
|||
/*
|
||||
* modload.c
|
||||
*
|
||||
* This is the interface for the kernel module loader for statically
|
||||
* loadable kernel modules. The interface is nearly identical to the
|
||||
* SunOS 4.1.3 not because I lack imagination but because I liked Sun's
|
||||
* approach in this particular revision of their BSD-derived OS.
|
||||
*
|
||||
* modload [-d] [-v] [-A <kernel>] [-e <entry] [-p <postinstall>]
|
||||
* [-o <output file>] <input file>
|
||||
*
|
||||
* -d - debug
|
||||
* -v - verbose
|
||||
* -A <kernel> - specify symbol kernel (default="/386bsd")
|
||||
* -e <entry> - entry point (default="xxxinit")
|
||||
* -p <postinstall> - postinstall script or executable
|
||||
* -o <output file> - output file (default=<input file>-".o")
|
||||
*
|
||||
* Copyright (c) 1993 Terrence R. Lambert.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Terrence R. Lambert.
|
||||
* 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: modload.c,v 1.1 1993/06/07 19:52:11 cgd Exp $
|
||||
*/
|
||||
|
||||
#define printf I_HATE_ANSI
|
||||
#include <stdio.h>
|
||||
#undef printf
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/lkm.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/errno.h>
|
||||
#include <paths.h>
|
||||
|
||||
#ifdef sun
|
||||
/* these are defined in stdlib.h for everything but sun*/
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
#endif /* sun*/
|
||||
|
||||
#ifndef DFLT_KERNEL
|
||||
#define DFLT_KERNEL _PATH_UNIX
|
||||
#endif /* !DFLT_KERNEL*/
|
||||
|
||||
#ifndef DFLT_ENTRY
|
||||
#define DFLT_ENTRY "xxxinit"
|
||||
#endif /* !DFLT_ENTRY*/
|
||||
|
||||
/*
|
||||
* Expected linker options:
|
||||
*
|
||||
* -A executable to link against
|
||||
* -e entry point
|
||||
* -o output file
|
||||
* -T address to link to in hex (assumes it's a page boundry)
|
||||
* <target> object file
|
||||
*
|
||||
*/
|
||||
/*
|
||||
#define LINKCMD "ld -f %s -e _%s -o %s -T %x %s"
|
||||
*/
|
||||
#define LINKCMD "ld -A %s -e _%s -o %s -T %x %s"
|
||||
|
||||
#define LKM_DEV "/dev/lkm"
|
||||
|
||||
#ifdef MIN
|
||||
#undef MIN
|
||||
#endif /* MIN*/
|
||||
#define MIN(x,y) ((x)>(y) ? (y) : (x))
|
||||
|
||||
|
||||
int debug = 0;
|
||||
int verbose = 0;
|
||||
|
||||
|
||||
linkcmd( kernel, entry, outfile, address, object)
|
||||
char *kernel;
|
||||
char *entry;
|
||||
char *outfile;
|
||||
unsigned int address;
|
||||
char *object;
|
||||
{
|
||||
char cmdbuf[ 1024];
|
||||
int err = 0;
|
||||
|
||||
sprintf( cmdbuf, LINKCMD, kernel, entry, outfile, address, object);
|
||||
|
||||
if( debug)
|
||||
printf( "%s\n", cmdbuf);
|
||||
|
||||
switch( system( cmdbuf)) {
|
||||
case 0: /* SUCCESS!*/
|
||||
break;
|
||||
case 1: /* uninformitive error*/
|
||||
/*
|
||||
* Someone needs to fix the return values from the 386BSD
|
||||
* ld program -- it's totally uninformative.
|
||||
*
|
||||
* No such file (4 on SunOS)
|
||||
* Can't write output (2 on SunOS)
|
||||
* Undefined symbol (1 on SunOS)
|
||||
* etc.
|
||||
*/
|
||||
case 127: /* can't load shell*/
|
||||
case 32512:
|
||||
default:
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
||||
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf( stderr, "usage:\n");
|
||||
fprintf( stderr,
|
||||
"modload [-d] [-v] [-A <kernel>] [-e <entry]\n");
|
||||
fprintf( stderr,
|
||||
"[-p <postinstall>] [-o <output file>] <input file>\n");
|
||||
exit( 1);
|
||||
}
|
||||
|
||||
int filopen = 0;
|
||||
#define DEV_OPEN 0x01
|
||||
#define MOD_OPEN 0x02
|
||||
#define PART_RESRV 0x04
|
||||
|
||||
main( ac, av)
|
||||
int ac;
|
||||
char *av[];
|
||||
{
|
||||
int ch;
|
||||
char *kname = DFLT_KERNEL;
|
||||
char *entry = DFLT_ENTRY;
|
||||
char *post = NULL;
|
||||
char *out = NULL;
|
||||
char *modobj;
|
||||
int devfd;
|
||||
int modfd;
|
||||
char modout[ 80];
|
||||
char *p;
|
||||
struct exec info_buf;
|
||||
int err = 0;
|
||||
unsigned long modsize;
|
||||
unsigned long modentry;
|
||||
|
||||
struct lmc_resrv resrv;
|
||||
struct lmc_loadbuf ldbuf;
|
||||
int i;
|
||||
int sz;
|
||||
char buf[ MODIOBUF];
|
||||
int bytesleft;
|
||||
|
||||
|
||||
while( ( ch = getopt( ac, av, "dvA:e:p:o:")) != EOF) {
|
||||
switch(ch) {
|
||||
case 'd': debug = 1; break; /* debug*/
|
||||
case 'v': verbose = 1; break; /* verbose*/
|
||||
case 'A': kname = optarg; break; /* kernel*/
|
||||
case 'e': entry = optarg; break; /* entry point*/
|
||||
case 'p': post = optarg; break; /* postinstall*/
|
||||
case 'o': out = optarg; break; /* output file*/
|
||||
case '?': usage();
|
||||
default: printf( "default!\n");
|
||||
}
|
||||
}
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
if( ac != 1)
|
||||
usage();
|
||||
|
||||
modobj = av[ 0];
|
||||
|
||||
/*
|
||||
* Open the virtual device device driver for exclusive use (needed
|
||||
* to write the new module to it as our means of getting it in the
|
||||
* kernel).
|
||||
*/
|
||||
if( ( devfd = open( LKM_DEV, O_RDONLY, 0)) == -1) {
|
||||
perror( LKM_DEV);
|
||||
err = 3;
|
||||
goto done;
|
||||
}
|
||||
filopen |= DEV_OPEN;
|
||||
|
||||
strcpy( modout, modobj);
|
||||
|
||||
for( p = modout; *p && *p != '.'; p++)
|
||||
continue;
|
||||
|
||||
if( !*p || strcmp( p, ".o")) {
|
||||
fprintf( stderr, "Module object must end in .o\n");
|
||||
err = 2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( out == NULL) {
|
||||
out = modout;
|
||||
*p == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prelink to get file size
|
||||
*/
|
||||
if( linkcmd( kname, entry, out, 0, modobj)) {
|
||||
fprintf( stderr,
|
||||
"Can't prelink %s creating %s!\n", modobj, out);
|
||||
err = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-open the 0-linked module to get the size information
|
||||
*/
|
||||
if( ( modfd = open( out, O_RDONLY, 0)) == -1) {
|
||||
perror( out);
|
||||
err = 4;
|
||||
goto done;
|
||||
}
|
||||
filopen |= MOD_OPEN;
|
||||
|
||||
/*
|
||||
* Get the load module post load size... do this by reading the
|
||||
* header and doing page counts.
|
||||
*/
|
||||
if( read( modfd, &info_buf, sizeof(struct exec)) == -1) {
|
||||
perror( "read");
|
||||
err = 3;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the dummy module -- we have our sizing information.
|
||||
*/
|
||||
close( modfd);
|
||||
filopen &= ~MOD_OPEN;
|
||||
|
||||
|
||||
/*
|
||||
* Magic number...
|
||||
*/
|
||||
if( N_BADMAG( info_buf)) {
|
||||
fprintf( stderr, "Not an a.out format file\n");
|
||||
err = 4;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the size of the module
|
||||
*/
|
||||
modsize = info_buf.a_text + info_buf.a_data; /* amount to load*/
|
||||
|
||||
|
||||
/*
|
||||
* Reserve the required amount of kernel memory -- this may fail
|
||||
* to be successful.
|
||||
*/
|
||||
resrv.size = modsize; /* size in bytes*/
|
||||
resrv.name = modout; /* objname w/o ".o"*/
|
||||
resrv.slot = -1; /* returned*/
|
||||
resrv.addr = 0; /* returned*/
|
||||
if( ioctl( devfd, LMRESERV, &resrv) == -1) {
|
||||
perror( "LMRESERV");
|
||||
fprintf( stderr, "Can't reserve memory\n");
|
||||
err = 9;
|
||||
goto done;
|
||||
}
|
||||
filopen |= PART_RESRV;
|
||||
|
||||
/*
|
||||
* Relink at kernel load address
|
||||
*/
|
||||
if( linkcmd( kname, entry, out, resrv.addr, modobj)) {
|
||||
fprintf( stderr,
|
||||
"Can't link %s creating %s bound to 0x%08x!\n",
|
||||
modobj, out, resrv.addr);
|
||||
err = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the relinked module to load it...
|
||||
*/
|
||||
if( ( modfd = open( out, O_RDONLY, 0)) == -1) {
|
||||
perror( out);
|
||||
err = 4;
|
||||
goto done;
|
||||
}
|
||||
filopen |= MOD_OPEN;
|
||||
|
||||
|
||||
/*
|
||||
* Reread the header to get the actual entry point *after* the
|
||||
* relink.
|
||||
*/
|
||||
if( read( modfd, &info_buf, sizeof(struct exec)) == -1) {
|
||||
perror( "read");
|
||||
err = 3;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the entry point (for initialization)
|
||||
*/
|
||||
modentry = info_buf.a_entry; /* place to call*/
|
||||
|
||||
/*
|
||||
* Seek to the text offset to start loading...
|
||||
*/
|
||||
if( lseek( modfd, N_TXTOFF(info_buf), 0) == -1) {
|
||||
perror( "lseek");
|
||||
err = 12;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer the relinked module to kernel memory in chunks of
|
||||
* MODIOBUF size at a time.
|
||||
*/
|
||||
bytesleft = modsize;
|
||||
for( i = 0; i < (modsize + MODIOBUF-1)/MODIOBUF; i++) {
|
||||
sz = MIN(bytesleft,MODIOBUF);
|
||||
read( modfd, buf, sz);
|
||||
ldbuf.cnt = sz;
|
||||
ldbuf.data = buf;
|
||||
if( ioctl( devfd, LMLOADBUF, &ldbuf) == -1) {
|
||||
perror( "LMLOADBUF");
|
||||
/* error*/
|
||||
fprintf( stderr, "Error transferring buffer\n");
|
||||
err = 11;
|
||||
goto done;
|
||||
}
|
||||
bytesleft -= MODIOBUF;
|
||||
if( bytesleft < 1)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save ourselves before disaster (potentitally) strikes...
|
||||
*/
|
||||
sync();
|
||||
|
||||
/*
|
||||
* Trigger the module as loaded by calling the entry procedure;
|
||||
* this will do all necessary table fixup to ensure that state
|
||||
* is maintained on success, or blow everything back to ground
|
||||
* zero on failure.
|
||||
*/
|
||||
if( ioctl( devfd, LMREADY, &modentry) == -1) {
|
||||
perror( "LMREADY");
|
||||
err = 14;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Success!
|
||||
*/
|
||||
filopen &= ~PART_RESRV; /* loaded*/
|
||||
printf( "Module loaded as ID %d\n", resrv.slot);
|
||||
|
||||
done:
|
||||
if( filopen & PART_RESRV) {
|
||||
/*
|
||||
* Free up kernel memory
|
||||
*/
|
||||
if( ioctl( devfd, LMUNRESRV, 0) == -1) {
|
||||
fprintf( stderr, "Can't release slot 0x%08x memory\n",
|
||||
resrv.slot);
|
||||
}
|
||||
}
|
||||
|
||||
if( filopen & DEV_OPEN)
|
||||
close( devfd);
|
||||
|
||||
if( filopen & MOD_OPEN)
|
||||
close( modfd);
|
||||
|
||||
exit( err);
|
||||
}
|
||||
|
||||
#ifdef OMIT
|
||||
|
||||
MODLOAD(8) MAINTENANCE COMMANDS MODLOAD(8)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
modload - load a kernel module
|
||||
|
||||
SYNOPSIS
|
||||
modload filename [ -d ] [ -v ] [ -sym ] [ -A vmunix_file ] [
|
||||
-conf config_file ] [ -entry entry_point ] [ -exec exec_file
|
||||
] [ -o output_file ]
|
||||
|
||||
DESCRIPTION
|
||||
modload loads a loadable module into a running system. The
|
||||
input file filename is an object file (.o file).
|
||||
|
||||
OPTIONS
|
||||
-d Debug. Used to debug modload itself.
|
||||
|
||||
-v Verbose. Print comments on the loading process.
|
||||
|
||||
-sym Preserve symbols for use by kadb(8S).
|
||||
|
||||
-A vmunix_file
|
||||
Specify the file that is passd to the linker to resolve
|
||||
module references to kernel symbols. The default is
|
||||
/vmunix. The symbol file must be for the currently
|
||||
running kernel or the module is likely to crash the
|
||||
system.
|
||||
|
||||
-conf config_file
|
||||
Use this configuration file to configure the loadable
|
||||
driver being loaded. The commands in this file are the
|
||||
same as those that the config(8) program recognizes.
|
||||
There are two additional commands recognized, blockma-
|
||||
jor and charmajor. See the Writing Device Drivers for
|
||||
information on these commands.
|
||||
|
||||
-entry entry_point
|
||||
Specify the module entry point. This is passed by
|
||||
modload to ld(1) when the module is linked. The
|
||||
default module entry point name is `xxxinit`.
|
||||
|
||||
-exec exec_file
|
||||
Specify the name of a shell script or executable image
|
||||
file that will be executed if the module is success-
|
||||
fully loaded. It is always passed the module id (in
|
||||
decimal) and module type (in hexadecimal) as the first
|
||||
two arguments. Module types are listed in
|
||||
/usr/include/sun/vddrv.h. For loadable drivers, the
|
||||
third and fourth arguments are the block major and
|
||||
character major numbers respectively. For a loadable
|
||||
system call, the third argument is the system call
|
||||
number.
|
||||
|
||||
-o output_file
|
||||
|
||||
|
||||
|
||||
Sun Release 4.1 Last change: 31 May 1991 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MODLOAD(8) MAINTENANCE COMMANDS MODLOAD(8)
|
||||
|
||||
|
||||
|
||||
Specify the name of the output file that is produced by
|
||||
the linker. If this option is omitted, then the output
|
||||
file name is filename without the `.o`.
|
||||
|
||||
BUGS
|
||||
On Sun-3 machines, the config(8) program generates assembly
|
||||
language wrappers to provide the proper linkage to device
|
||||
interrupt handlers. modload does not generate these
|
||||
wrappers; on interrupt, control passes directly to the load-
|
||||
able drivers interrupt handler. Consequently, the driver
|
||||
must provide its own wrapper. See the ioconf.c file gen-
|
||||
erated by config(8) for examples of wrappers.
|
||||
|
||||
SEE ALSO
|
||||
ld(1), config(8), kadb(8S), modunload(8), modstat(8)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 4.1 Last change: 31 May 1991 2
|
||||
|
||||
|
||||
#endif /* OMIT*/
|
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# Makefile for modunload
|
||||
#
|
||||
# 25 May 93 Terry Lambert Original
|
||||
#
|
||||
# Copyright (c) 1993 Terrence R. Lambert.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by Terrence R. Lambert.
|
||||
# 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $Id: Makefile,v 1.1 1993/06/07 19:52:14 cgd Exp $
|
||||
#
|
||||
|
||||
PROG= modunload
|
||||
CFLAGS=-DKERNEL
|
||||
NOMAN= noman
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* modunload.c
|
||||
*
|
||||
* This is the loadable kernel module unload program. The interface
|
||||
* is nearly identical to the SunOS 4.1.3 not because I lack
|
||||
* imagination but because I liked Sun's approach in this particular
|
||||
* revision of their BSD-derived OS.
|
||||
*
|
||||
* modunload [-i <module id>] [-n <module name>]
|
||||
*
|
||||
* Default behaviour is to provide a usage message.
|
||||
*
|
||||
* -i <module id> - unload module by id
|
||||
* -n <module name> - unload module by name
|
||||
*
|
||||
* Copyright (c) 1993 Terrence R. Lambert.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Terrence R. Lambert.
|
||||
* 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: modunload.c,v 1.1 1993/06/07 19:52:16 cgd Exp $
|
||||
*/
|
||||
|
||||
#define printf I_HATE_ANSI
|
||||
#include <stdio.h>
|
||||
#undef printf
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/lkm.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
extern int errno; /* should be in errno.h*/
|
||||
|
||||
|
||||
#ifdef sun
|
||||
/* these are defined in stdlib.h for everything but sun*/
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
#endif /* sun*/
|
||||
|
||||
#define LKM_DEV "/dev/lkm"
|
||||
|
||||
|
||||
extern int dostat();
|
||||
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf( stderr, "usage:\n");
|
||||
fprintf( stderr,
|
||||
"modunload [-i <module id>] [-n <module name>]\n");
|
||||
exit( 1);
|
||||
}
|
||||
|
||||
|
||||
main( ac, av)
|
||||
int ac;
|
||||
char *av[];
|
||||
{
|
||||
int devfd;
|
||||
int ch;
|
||||
int err = 0;
|
||||
int modnum = -1;
|
||||
char *modname = NULL;
|
||||
struct lmc_unload ulbuf;
|
||||
|
||||
while( ( ch = getopt( ac, av, "i:n:")) != EOF) {
|
||||
switch(ch) {
|
||||
case 'i': modnum = atoi( optarg); break; /* number*/
|
||||
case 'n': modname = optarg; break; /* name*/
|
||||
case '?': usage();
|
||||
default: printf( "default!\n");
|
||||
}
|
||||
}
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
if( ac != 0)
|
||||
usage();
|
||||
|
||||
|
||||
/*
|
||||
* Open the virtual device device driver for exclusive use (needed
|
||||
* to ioctl() to retrive the loaded module(s) status).
|
||||
*/
|
||||
if( ( devfd = open( LKM_DEV, O_RDONLY, 0)) == -1) {
|
||||
perror( LKM_DEV);
|
||||
exit( 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Not specified?
|
||||
*/
|
||||
if( modnum == -1 && modname == NULL)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* Unload the requested module.
|
||||
*/
|
||||
|
||||
/*
|
||||
if( modname != NULL)
|
||||
strcpy( ulbuf.name, modname);
|
||||
*/
|
||||
ulbuf.name = modname;
|
||||
|
||||
ulbuf.id = modnum;
|
||||
|
||||
if( ioctl( devfd, LMUNLOAD, &ulbuf) == -1) {
|
||||
switch( errno) {
|
||||
case EINVAL: /* out of range*/
|
||||
fprintf( stderr, "modunload: id out of range\n");
|
||||
err = 3;
|
||||
break;
|
||||
case ENOENT: /* no such entry*/
|
||||
fprintf( stderr, "modunload: no such module\n");
|
||||
err = 4;
|
||||
break;
|
||||
default: /* other error (EFAULT, etc)*/
|
||||
perror( "LMUNLOAD");
|
||||
err = 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
close( devfd);
|
||||
exit( err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EOF -- This file has not been truncated.
|
||||
*/
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# BOAT_ANCHOR -- kernel for the 386-20 the gang uses for testing
|
||||
#
|
||||
# $Id: BOAT_ANCHOR,v 1.17 1993/06/03 01:30:23 cgd Exp $
|
||||
# $Id: BOAT_ANCHOR,v 1.18 1993/06/07 19:52:22 cgd Exp $
|
||||
#
|
||||
machine "i386"
|
||||
cpu "I386_CPU"
|
||||
|
@ -18,6 +18,7 @@ options KTRACE
|
|||
options DDB
|
||||
options FIFO
|
||||
options "COMPAT_NOMID"
|
||||
options LKM
|
||||
|
||||
options ACCOUNTING
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
revision 1.10 intentionally removed
|
||||
revision 1.11 intentionally removed
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.27 1993/06/06 04:16:14 cgd Exp $
|
||||
* $Id: machdep.c,v 1.28 1993/06/07 19:52:28 cgd Exp $
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -892,8 +892,11 @@ init386(first)
|
|||
|
||||
cninit (KERNBASE+0xa0000);
|
||||
|
||||
#ifndef LKM /* don't do this if we're using LKM's */
|
||||
/* make gdt memory segments */
|
||||
gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG);
|
||||
#endif
|
||||
|
||||
for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
|
||||
/* make ldt memory segments */
|
||||
ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: files,v 1.11 1993/05/31 01:40:53 cgd Exp $
|
||||
# $Id: files,v 1.12 1993/06/07 19:52:32 cgd Exp $
|
||||
#
|
||||
ddb/db_access.c optional ddb
|
||||
ddb/db_aout.c optional ddb
|
||||
|
@ -35,6 +35,7 @@ kern/kern_exit.c standard
|
|||
kern/kern_fork.c standard
|
||||
kern/kern_kinfo.c standard
|
||||
kern/kern_ktrace.c optional ktrace
|
||||
kern/kern_lkm.c optional lkm
|
||||
kern/kern_malloc.c standard
|
||||
kern/kern_proc.c standard
|
||||
kern/kern_prot.c standard
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: files.oldconf,v 1.11 1993/05/31 01:40:53 cgd Exp $
|
||||
# $Id: files.oldconf,v 1.12 1993/06/07 19:52:32 cgd Exp $
|
||||
#
|
||||
ddb/db_access.c optional ddb
|
||||
ddb/db_aout.c optional ddb
|
||||
|
@ -35,6 +35,7 @@ kern/kern_exit.c standard
|
|||
kern/kern_fork.c standard
|
||||
kern/kern_kinfo.c standard
|
||||
kern/kern_ktrace.c optional ktrace
|
||||
kern/kern_lkm.c optional lkm
|
||||
kern/kern_malloc.c standard
|
||||
kern/kern_proc.c standard
|
||||
kern/kern_prot.c standard
|
||||
|
|
|
@ -168,6 +168,19 @@ int shmsys();
|
|||
int setgid();
|
||||
int setegid();
|
||||
int seteuid();
|
||||
#ifdef LKM
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
int lkmnosys();
|
||||
#else /* !LKM*/
|
||||
#endif /* !LKM*/
|
||||
|
||||
#ifdef COMPAT_43
|
||||
#define compat(n, name) n, __CONCAT(o,name)
|
||||
|
@ -210,6 +223,9 @@ int ogetsockname();
|
|||
#ifdef SYSVSHM
|
||||
#else
|
||||
#endif
|
||||
#ifdef LKM
|
||||
#else /* !LKM*/
|
||||
#endif /* !LKM*/
|
||||
|
||||
#else /* COMPAT_43 */
|
||||
#define compat(n, name) 0, nosys
|
||||
|
@ -436,6 +452,38 @@ struct sysent sysent[] = {
|
|||
0, nosys, /* 188 = nosys */
|
||||
0, nosys, /* 189 = nosys */
|
||||
0, nosys, /* 190 = nosys */
|
||||
0, nosys, /* 191 = nosys */
|
||||
0, nosys, /* 192 = nosys */
|
||||
0, nosys, /* 193 = nosys */
|
||||
0, nosys, /* 194 = nosys */
|
||||
0, nosys, /* 195 = nosys */
|
||||
0, nosys, /* 196 = nosys */
|
||||
0, nosys, /* 197 = nosys */
|
||||
0, nosys, /* 198 = nosys */
|
||||
0, nosys, /* 199 = nosys */
|
||||
#ifdef LKM
|
||||
0, lkmnosys, /* 200 = lkmnosys */
|
||||
0, lkmnosys, /* 201 = lkmnosys */
|
||||
0, lkmnosys, /* 202 = lkmnosys */
|
||||
0, lkmnosys, /* 203 = lkmnosys */
|
||||
0, lkmnosys, /* 204 = lkmnosys */
|
||||
0, lkmnosys, /* 205 = lkmnosys */
|
||||
0, lkmnosys, /* 206 = lkmnosys */
|
||||
0, lkmnosys, /* 207 = lkmnosys */
|
||||
0, lkmnosys, /* 208 = lkmnosys */
|
||||
0, lkmnosys, /* 209 = lkmnosys */
|
||||
#else /* !LKM*/
|
||||
0, nosys, /* 200 = nosys */
|
||||
0, nosys, /* 201 = nosys */
|
||||
0, nosys, /* 202 = nosys */
|
||||
0, nosys, /* 203 = nosys */
|
||||
0, nosys, /* 204 = nosys */
|
||||
0, nosys, /* 205 = nosys */
|
||||
0, nosys, /* 206 = nosys */
|
||||
0, nosys, /* 207 = nosys */
|
||||
0, nosys, /* 208 = nosys */
|
||||
0, nosys, /* 209 = nosys */
|
||||
#endif /* !LKM*/
|
||||
};
|
||||
|
||||
int nsysent = sizeof(sysent) / sizeof(sysent[0]);
|
||||
|
|
|
@ -0,0 +1,865 @@
|
|||
/*
|
||||
* kern_lkm.c
|
||||
*
|
||||
* functions and pseudo-device for loadable kernel modules
|
||||
*
|
||||
* 05 Jun 93 Terry Lambert Release cleanup
|
||||
* 10 Feb 93 Terry Lambert Original
|
||||
*
|
||||
* Copyright (c) 1992 Terrence R. Lambert.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Terrence R. Lambert.
|
||||
* 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kern_lkm.c,v 1.1 1993/06/07 19:52:39 cgd Exp $
|
||||
*/
|
||||
|
||||
#include "param.h"
|
||||
#include "systm.h"
|
||||
#include "ioctl.h"
|
||||
#include "tty.h"
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "proc.h"
|
||||
#include "uio.h"
|
||||
#include "kernel.h"
|
||||
#include "vnode.h"
|
||||
#include "malloc.h"
|
||||
#include "vm/vm.h"
|
||||
#include "vm/vm_param.h"
|
||||
#include "vm/vm_kern.h"
|
||||
#include "mount.h"
|
||||
#include "exec.h"
|
||||
#include "lkm.h"
|
||||
|
||||
#define PAGESIZE 1024 /* kmem_alloc() allocation quantum*/
|
||||
|
||||
#define LKM_ALLOC 0x01
|
||||
#define LKM_WANT 0x02
|
||||
|
||||
|
||||
#define LKMS_IDLE 0x00
|
||||
#define LKMS_RESERVED 0x01
|
||||
#define LKMS_LOADING 0x02
|
||||
#define LKMS_LOADED 0x04
|
||||
#define LKMS_UNLOADING 0x08
|
||||
|
||||
static int lkm_v = 0;
|
||||
static int lkm_state = LKMS_IDLE;
|
||||
|
||||
#ifndef MAXLKMS
|
||||
#define MAXLKMS 20
|
||||
#endif
|
||||
|
||||
static struct lkm_table lkmods[ MAXLKMS]; /* table of loaded modules*/
|
||||
static struct lkm_table *curp; /* global for in-progress ops*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
lkmopen( dev, flag, devtype, p)
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int devtype;
|
||||
struct proc *p;
|
||||
{
|
||||
int error;
|
||||
|
||||
if( minor( dev) != 0)
|
||||
return( ENXIO); /* bad minor #*/
|
||||
|
||||
/*
|
||||
* Use of the loadable kernel module device must be exclusive; we
|
||||
* may try to remove this restriction later, but it's really no
|
||||
* hardship.
|
||||
*/
|
||||
while( lkm_v & LKM_ALLOC) {
|
||||
if( flag & FNONBLOCK) /* don't hang*/
|
||||
return( EBUSY);
|
||||
lkm_v |= LKM_WANT;
|
||||
/*
|
||||
* Sleep pending unlock; we use tsleep() to allow
|
||||
* an alarm out of the open.
|
||||
*/
|
||||
if( error = tsleep( (caddr_t)&lkm_v, TTIPRI|PCATCH, "LKM", 0))
|
||||
return( error); /* leave LKM_WANT set -- no problem*/
|
||||
}
|
||||
lkm_v |= LKM_ALLOC;
|
||||
|
||||
return( 0); /* pseudo-device open*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* l k m u n r e s e r v e
|
||||
*
|
||||
* Unreserve the memory associated with the current loaded module; done on
|
||||
* a coerced close of the lkm device (close on premature exit of modload)
|
||||
* or explicitly by modload as a result of a link failure.
|
||||
*/
|
||||
static int
|
||||
lkmunreserve()
|
||||
{
|
||||
if( lkm_state == LKMS_IDLE)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Actually unreserve the memory
|
||||
*/
|
||||
kmem_free( buffer_map, curp->area, curp->size);/**/
|
||||
|
||||
lkm_state = LKMS_IDLE;
|
||||
}
|
||||
|
||||
|
||||
lkmclose( dev, flag, mode, p)
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int mode;
|
||||
struct proc *p;
|
||||
{
|
||||
if( !( lkm_v & LKM_ALLOC)) {
|
||||
#ifdef DEBUG
|
||||
printf( "LKM: close before open!\n");
|
||||
#endif /* DEBUG*/
|
||||
return( EBADF);
|
||||
}
|
||||
|
||||
/* do this before waking the herd...*/
|
||||
if( !curp->used) {
|
||||
/*
|
||||
* If we close before setting used, we have aborted
|
||||
* by way of error or by way of close-on-exit from
|
||||
* a premature exit of "modload".
|
||||
*/
|
||||
lkmunreserve(); /* coerce state to LKM_IDLE*/
|
||||
}
|
||||
|
||||
lkm_v &= ~LKM_ALLOC;
|
||||
wakeup( (caddr_t)&lkm_v); /* thundering herd "problem" here*/
|
||||
|
||||
return( 0); /* pseudo-device closed*/
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
lkmioctl( dev, cmd, data, flag)
|
||||
dev_t dev;
|
||||
int cmd;
|
||||
caddr_t data;
|
||||
int flag;
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
struct lmc_resrv *resrvp;
|
||||
struct lmc_loadbuf *loadbufp;
|
||||
struct lmc_unload *unloadp;
|
||||
struct lmc_stat *statp;
|
||||
int (*funcp)();
|
||||
char istr[ MAXLKMNAME];
|
||||
|
||||
switch( cmd) {
|
||||
case LMRESERV: /* reserve pages for a module*/
|
||||
|
||||
resrvp = (struct lmc_resrv *)data;
|
||||
|
||||
/*
|
||||
* Find a free slot.
|
||||
*/
|
||||
for( i = 0; i < MAXLKMS; i++) {
|
||||
if( !lkmods[ i].used)
|
||||
break;
|
||||
}
|
||||
if( i == MAXLKMS) {
|
||||
err = ENOMEM; /* no slots available*/
|
||||
break;
|
||||
}
|
||||
curp = &lkmods[ i];
|
||||
curp->id = i; /* self reference slot offset*/
|
||||
|
||||
resrvp->slot = i; /* return slot*/
|
||||
|
||||
/*
|
||||
* Get memory for module
|
||||
*/
|
||||
curp->size = resrvp->size;
|
||||
|
||||
curp->area = (char *)kmem_alloc( buffer_map, curp->size);/**/
|
||||
|
||||
curp->offset = 0; /* load offset*/
|
||||
|
||||
resrvp->addr = (unsigned long)curp->area; /* ret kernel addr*/
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "LKM: LMRESERV (actual = 0x%08x)\n", curp->area);
|
||||
printf( "LKM: LMRESERV (adjusted = 0x%08x)\n",
|
||||
trunc_page(curp->area));
|
||||
#endif /* DEBUG*/
|
||||
lkm_state = LKMS_RESERVED;
|
||||
break;
|
||||
|
||||
case LMLOADBUF: /* Copy in; stateful, follows LMRESERV*/
|
||||
loadbufp = (struct lmc_loadbuf *)data;
|
||||
if( lkm_state != LKMS_RESERVED && lkm_state != LKMS_LOADING) {
|
||||
err = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* account for odd size (non-page multiple) copyin*/
|
||||
i = MIN( curp->size - curp->offset, MODIOBUF);
|
||||
|
||||
/* copy in buffer full of data*/
|
||||
if( err = copyin( (caddr_t)loadbufp->data, (caddr_t)curp->area + curp->offset, i))
|
||||
break;
|
||||
|
||||
if( ( curp->offset + i) < curp->size) {
|
||||
lkm_state = LKMS_LOADING;
|
||||
#ifdef DEBUG
|
||||
printf( "LKM: LMLOADBUF (loading @ %d of %d, i = %d)\n",
|
||||
curp->offset, curp->size, i);
|
||||
#endif /* DEBUG*/
|
||||
} else {
|
||||
lkm_state = LKMS_LOADED;
|
||||
#ifdef DEBUG
|
||||
printf( "LKM: LMLOADBUF (loaded)\n");
|
||||
#endif /* DEBUG*/
|
||||
}
|
||||
curp->offset += MODIOBUF;
|
||||
break;
|
||||
|
||||
case LMUNRESRV: /* discard reserved pages for a module*/
|
||||
lkmunreserve(); /* coerce state to LKM_IDLE*/
|
||||
#ifdef DEBUG
|
||||
printf( "LKM: LMUNRESERV\n");
|
||||
#endif /* DEBUG*/
|
||||
break;
|
||||
|
||||
case LMREADY: /* module loaded: call entry*/
|
||||
if( lkm_state != LKMS_LOADED) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "lkm_state is %02x\n", lkm_state);
|
||||
#endif /* DEBUG*/
|
||||
err = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
curp->entry = (int (*)()) (*((int *) ( data)));
|
||||
|
||||
/* call entry(load)... (assigns "private" portion)*/
|
||||
if( err = (*(curp->entry))( curp, LKM_E_LOAD, LKM_VERSION)) {
|
||||
/*
|
||||
* Module may refuse loading or may have a
|
||||
* version mismatch...
|
||||
*/
|
||||
lkm_state = LKMS_UNLOADING; /* for lkmunreserve*/
|
||||
lkmunreserve(); /* free memory*/
|
||||
curp->used = 0; /* free slot*/
|
||||
break;
|
||||
}
|
||||
|
||||
curp->used = 1;
|
||||
#ifdef DEBUG
|
||||
printf( "LKM: LMREADY\n");
|
||||
#endif /* DEBUG*/
|
||||
lkm_state = LKMS_IDLE;
|
||||
break;
|
||||
|
||||
case LMUNLOAD: /* unload a module*/
|
||||
unloadp = (struct lmc_unload *)data;
|
||||
|
||||
if( ( i = unloadp->id) == -1) { /* unload by name*/
|
||||
/*
|
||||
* Copy name in and lookup id from all loaded
|
||||
* modules. May fail.
|
||||
*/
|
||||
if( err = copyinstr( unloadp->name, istr, MAXLKMNAME-1, NULL))
|
||||
break;
|
||||
/*
|
||||
* look up id...
|
||||
*/
|
||||
for( i = 0; i < MAXLKMS; i++) {
|
||||
if( !lkmods[ i].used)
|
||||
continue;
|
||||
if( !strcmp( istr,
|
||||
lkmods[ i].private.lkm_any->lkm_name))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Range check the value; on failure, return EINVAL
|
||||
*/
|
||||
if( i < 0 || i >= MAXLKMS) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
curp = &lkmods[ i];
|
||||
|
||||
/* call entry(unload)*/
|
||||
if( (*(curp->entry))( curp, LKM_E_UNLOAD, LKM_VERSION)) {
|
||||
err = EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
lkm_state = LKMS_UNLOADING; /* non-idle for lkmunreserve*/
|
||||
lkmunreserve(); /* free memory*/
|
||||
curp->used = 0; /* free slot*/
|
||||
break;
|
||||
|
||||
case LMSTAT: /* stat a module by id/name*/
|
||||
statp = (struct lmc_stat *)data;
|
||||
|
||||
if( ( i = statp->id) == -1) { /* stat by name*/
|
||||
/*
|
||||
* Copy name in and lookup id from all loaded
|
||||
* modules. May fail.
|
||||
*/
|
||||
if( err = copyinstr( statp->name, istr, MAXLKMNAME-1, NULL))
|
||||
break;
|
||||
/*
|
||||
* look up id...
|
||||
*/
|
||||
for( i = 0; i < MAXLKMS; i++) {
|
||||
if( !lkmods[ i].used)
|
||||
continue;
|
||||
if( !strcmp( istr,
|
||||
lkmods[ i].private.lkm_any->lkm_name))
|
||||
break;
|
||||
}
|
||||
|
||||
if( i == MAXLKMS) { /* Not found*/
|
||||
err = ENOENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Range check the value; on failure, return EINVAL
|
||||
*/
|
||||
if( i < 0 || i >= MAXLKMS) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
curp = &lkmods[ i];
|
||||
|
||||
if( !curp->used) { /* Not found*/
|
||||
err = ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy out stat information for this module...
|
||||
*/
|
||||
statp->id = curp->id;
|
||||
statp->offset = curp->private.lkm_any->lkm_offset;
|
||||
statp->type = curp->private.lkm_any->lkm_type;
|
||||
statp->area = curp->area;
|
||||
statp->size = curp->size / PAGESIZE;
|
||||
statp->private = (unsigned long)curp->private.lkm_any;
|
||||
statp->ver = curp->private.lkm_any->lkm_ver;
|
||||
err = copyoutstr( curp->private.lkm_any->lkm_name,
|
||||
statp->name,
|
||||
MAXLKMNAME - 2,
|
||||
NULL);
|
||||
|
||||
break;
|
||||
|
||||
default: /* bad ioctl()...*/
|
||||
err = ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* l k m n o s y s
|
||||
*
|
||||
* Acts like "nosys" but can be identified in sysent for dynamic call
|
||||
* number assignment for a limited number of calls.
|
||||
*
|
||||
* Place holder for system call slots reserved for loadable modules.
|
||||
*/
|
||||
lkmnosys()
|
||||
{
|
||||
return( nosys());
|
||||
}
|
||||
|
||||
/*
|
||||
* l k m e n o d e v
|
||||
*
|
||||
* Acts like "enodev", but can be identified in cdevsw and bdevsw for
|
||||
* dynamic driver major number assignment for a limited number of
|
||||
* drivers.
|
||||
*
|
||||
* Place holder for device switch slots reserved for loadable modules.
|
||||
*/
|
||||
int
|
||||
lkmenodev()
|
||||
{
|
||||
return( enodev());
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
int
|
||||
lkmexists( lkmtp)
|
||||
struct lkm_table *lkmtp;
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* see if name exists...
|
||||
*/
|
||||
for( i = 0; i < MAXLKMS; i++) {
|
||||
/*
|
||||
* An unused module and the one we are testing are not
|
||||
* considered.
|
||||
*/
|
||||
if( !lkmods[ i].used || &lkmods[ i] == lkmtp)
|
||||
continue;
|
||||
if( !strcmp( lkmtp->private.lkm_any->lkm_name,
|
||||
lkmods[ i].private.lkm_any->lkm_name))
|
||||
return( 1); /* already loaded...*/
|
||||
}
|
||||
|
||||
return( 0); /* module not loaded...*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For the loadable system call described by the structure pointed to
|
||||
* by lkmtp, load/unload/stat it depending on the cmd requested.
|
||||
*/
|
||||
static int
|
||||
_lkm_syscall( lkmtp, cmd)
|
||||
struct lkm_table *lkmtp;
|
||||
int cmd;
|
||||
{
|
||||
struct lkm_syscall *args = lkmtp->private.lkm_syscall;
|
||||
int i;
|
||||
int err = 0;
|
||||
extern int nsysent; /* init_sysent.c*/
|
||||
|
||||
switch( cmd) {
|
||||
case LKM_E_LOAD:
|
||||
/* don't load twice!*/
|
||||
if( lkmexists( lkmtp))
|
||||
return( EEXIST);
|
||||
if( ( i = args->lkm_offset) == -1) { /* auto*/
|
||||
/*
|
||||
* Search the table looking for a slot...
|
||||
*/
|
||||
for( i = 0; i < nsysent; i++)
|
||||
if( sysent[ i].sy_call == lkmnosys)
|
||||
break; /* found it!*/
|
||||
/* out of allocable slots?*/
|
||||
if( i == nsysent) {
|
||||
err = ENFILE;
|
||||
break;
|
||||
}
|
||||
} else { /* assign*/
|
||||
if( i < 0 || i >= nsysent) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* save old*/
|
||||
bcopy( &sysent[ i], &(args->lkm_oldent), sizeof( struct sysent));
|
||||
|
||||
/* replace with new*/
|
||||
bcopy( args->lkm_sysent, &sysent[ i], sizeof( struct sysent));
|
||||
|
||||
/* done!*/
|
||||
args->lkm_offset = i; /* slot in sysent[]*/
|
||||
|
||||
break;
|
||||
|
||||
case LKM_E_UNLOAD:
|
||||
/* current slot...*/
|
||||
i = args->lkm_offset;
|
||||
|
||||
/* replace current slot contents with old contents*/
|
||||
bcopy( &(args->lkm_oldent), &sysent[ i], sizeof( struct sysent));
|
||||
|
||||
break;
|
||||
|
||||
case LKM_E_STAT: /* no special handling...*/
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For the loadable virtual file system described by the structure pointed
|
||||
* to by lkmtp, load/unload/stat it depending on the cmd requested.
|
||||
*/
|
||||
static int
|
||||
_lkm_vfs( lkmtp, cmd)
|
||||
struct lkm_table *lkmtp;
|
||||
int cmd;
|
||||
{
|
||||
struct lkm_vfs *args = lkmtp->private.lkm_vfs;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
switch( cmd) {
|
||||
case LKM_E_LOAD:
|
||||
/* don't load twice!*/
|
||||
if( lkmexists( lkmtp))
|
||||
return( EEXIST);
|
||||
/*
|
||||
* Currently, the VFS and mount code in 386BSD is malformed;
|
||||
* this means that the per volume file system identifier is
|
||||
* the index into the table rather than the name; this means
|
||||
* that only the file systems already known to 386BSD are
|
||||
* allowable, since all others don't have fixed offsets.
|
||||
* Interestingly, Dell UNIX has this same bug with their VFS
|
||||
* implementation, but generic AT&T SVR4 does not.
|
||||
*
|
||||
* I will correct the VFS code when I get a chance.
|
||||
*/
|
||||
i = args->lkm_offset;
|
||||
if( i < 0 || i > MOUNT_MAXTYPE) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if( vfssw[ i] != (struct vfsops *)0) {
|
||||
err = EEXIST;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up file system
|
||||
*/
|
||||
vfssw[ i] = args->lkm_vfsops;
|
||||
|
||||
/*
|
||||
* Call init function for this VFS...
|
||||
*/
|
||||
( *(vfssw[ i]->vfs_init))( args->lkm_flags);
|
||||
|
||||
/* done!*/
|
||||
args->lkm_offset = i; /* slot in sysent[]*/
|
||||
|
||||
break;
|
||||
|
||||
case LKM_E_UNLOAD:
|
||||
/* current slot...*/
|
||||
i = args->lkm_offset;
|
||||
|
||||
/* replace current slot contents with old contents*/
|
||||
vfssw[ i] = (struct vfsops *)0;
|
||||
|
||||
break;
|
||||
|
||||
case LKM_E_STAT: /* no special handling...*/
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For the loadable device driver described by the structure pointed to
|
||||
* by lkmtp, load/unload/stat it depending on the cmd requested.
|
||||
*/
|
||||
static int
|
||||
_lkm_dev( lkmtp, cmd)
|
||||
struct lkm_table *lkmtp;
|
||||
int cmd;
|
||||
{
|
||||
struct lkm_dev *args = lkmtp->private.lkm_dev;
|
||||
int i;
|
||||
int err = 0;
|
||||
extern int nblkdev; /* i386/i386/conf.c*/
|
||||
extern int nchrdev; /* i386/i386/conf.c*/
|
||||
|
||||
switch( cmd) {
|
||||
case LKM_E_LOAD:
|
||||
/* don't load twice!*/
|
||||
if( lkmexists( lkmtp))
|
||||
return( EEXIST);
|
||||
switch( args->lkm_devtype) {
|
||||
case LM_DT_BLOCK:
|
||||
if( ( i = args->lkm_offset) == -1) { /* auto*/
|
||||
/*
|
||||
* Search the table looking for a slot...
|
||||
*/
|
||||
for( i = 0; i < nblkdev; i++)
|
||||
if( bdevsw[ i].d_open == lkmenodev)
|
||||
break; /* found it!*/
|
||||
/* out of allocable slots?*/
|
||||
if( i == nblkdev) {
|
||||
err = ENFILE;
|
||||
break;
|
||||
}
|
||||
} else { /* assign*/
|
||||
if( i < 0 || i >= nblkdev) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* save old*/
|
||||
bcopy( &bdevsw[ i], &(args->lkm_olddev.bdev), sizeof( struct bdevsw));
|
||||
|
||||
/* replace with new*/
|
||||
bcopy( args->lkm_dev.bdev, &bdevsw[ i], sizeof( struct bdevsw));
|
||||
|
||||
/* done!*/
|
||||
args->lkm_offset = i; /* slot in bdevsw[]*/
|
||||
break;
|
||||
|
||||
case LM_DT_CHAR:
|
||||
if( ( i = args->lkm_offset) == -1) { /* auto*/
|
||||
/*
|
||||
* Search the table looking for a slot...
|
||||
*/
|
||||
for( i = 0; i < nchrdev; i++)
|
||||
if( cdevsw[ i].d_open == lkmenodev)
|
||||
break; /* found it!*/
|
||||
/* out of allocable slots?*/
|
||||
if( i == nchrdev) {
|
||||
err = ENFILE;
|
||||
break;
|
||||
}
|
||||
} else { /* assign*/
|
||||
if( i < 0 || i >= nchrdev) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* save old*/
|
||||
bcopy( &cdevsw[ i], &(args->lkm_olddev.cdev), sizeof( struct cdevsw));
|
||||
|
||||
/* replace with new*/
|
||||
bcopy( args->lkm_dev.cdev, &cdevsw[ i], sizeof( struct cdevsw));
|
||||
|
||||
/* done!*/
|
||||
args->lkm_offset = i; /* slot in cdevsw[]*/
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENODEV;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LKM_E_UNLOAD:
|
||||
/* current slot...*/
|
||||
i = args->lkm_offset;
|
||||
|
||||
switch( args->lkm_devtype) {
|
||||
case LM_DT_BLOCK:
|
||||
/* replace current slot contents with old contents*/
|
||||
bcopy( &(args->lkm_olddev.bdev), &bdevsw[ i], sizeof( struct bdevsw));
|
||||
break;
|
||||
|
||||
case LM_DT_CHAR:
|
||||
/* replace current slot contents with old contents*/
|
||||
bcopy( &(args->lkm_olddev.cdev), &cdevsw[ i], sizeof( struct cdevsw));
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENODEV;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LKM_E_STAT: /* no special handling...*/
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
||||
|
||||
|
||||
#ifdef STREAMS
|
||||
/*
|
||||
* For the loadable streams module described by the structure pointed to
|
||||
* by lkmtp, load/unload/stat it depending on the cmd requested.
|
||||
*/
|
||||
static int
|
||||
_lkm_strmod( lkmtp, cmd)
|
||||
struct lkm_table *lkmtp;
|
||||
int cmd;
|
||||
{
|
||||
struct lkm_strmod *args = lkmtp->private.lkm_strmod;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
switch( cmd) {
|
||||
case LKM_E_LOAD:
|
||||
/* don't load twice!*/
|
||||
if( lkmexists( lkmtp))
|
||||
return( EEXIST);
|
||||
break;
|
||||
|
||||
case LKM_E_UNLOAD:
|
||||
break;
|
||||
|
||||
case LKM_E_STAT: /* no special handling...*/
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
||||
#endif /* STREAMS*/
|
||||
|
||||
#ifdef LKM_EXEC /* XXX NOTDEF YET!!! - cgd */
|
||||
/*
|
||||
* For the loadable execution class described by the structure pointed to
|
||||
* by lkmtp, load/unload/stat it depending on the cmd requested.
|
||||
*/
|
||||
static int
|
||||
_lkm_exec( lkmtp, cmd)
|
||||
struct lkm_table *lkmtp;
|
||||
int cmd;
|
||||
{
|
||||
struct lkm_exec *args = lkmtp->private.lkm_exec;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
switch( cmd) {
|
||||
case LKM_E_LOAD:
|
||||
/* don't load twice!*/
|
||||
if( lkmexists( lkmtp))
|
||||
return( EEXIST);
|
||||
if( ( i = args->lkm_offset) == -1) { /* auto*/
|
||||
/*
|
||||
* Search the table looking for a slot...
|
||||
*/
|
||||
for( i = 0; i < nexecs; i++)
|
||||
if( execsw[ i].m_size == 0)
|
||||
break; /* found it!*/
|
||||
/* out of allocable slots?*/
|
||||
if( i == nexecs) {
|
||||
err = ENFILE;
|
||||
break;
|
||||
}
|
||||
} else { /* assign*/
|
||||
if( i < 0 || i >= nexecs) {
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* save old*/
|
||||
bcopy( &execsw[ i], &(args->lkm_oldexec), sizeof( struct execsw));
|
||||
|
||||
/* replace with new*/
|
||||
bcopy( args->lkm_exec, &execsw[ i], sizeof( struct execsw));
|
||||
|
||||
/* done!*/
|
||||
args->lkm_offset = i; /* slot in execsw[]*/
|
||||
|
||||
break;
|
||||
|
||||
case LKM_E_UNLOAD:
|
||||
/* current slot...*/
|
||||
i = args->lkm_offset;
|
||||
|
||||
/* replace current slot contents with old contents*/
|
||||
bcopy( &execsw[ i], &(args->lkm_oldexec), sizeof( struct execsw));
|
||||
|
||||
break;
|
||||
|
||||
case LKM_E_STAT: /* no special handling...*/
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
||||
#endif /* LKM_EXEC */
|
||||
|
||||
/*
|
||||
* This code handles the per-module type "wiring-in" of loadable modules
|
||||
* into existing kernel tables. For "LM_MISC" modules, wiring and unwiring
|
||||
* is assumed to be done in their entry routines internal to the module
|
||||
* itself.
|
||||
*/
|
||||
lkmdispatch( lkmtp, cmd)
|
||||
struct lkm_table *lkmtp;
|
||||
int cmd;
|
||||
{
|
||||
int err = 0; /* default = success*/
|
||||
|
||||
switch( lkmtp->private.lkm_any->lkm_type) {
|
||||
case LM_SYSCALL:
|
||||
err = _lkm_syscall( lkmtp, cmd);
|
||||
break;
|
||||
|
||||
case LM_VFS:
|
||||
err = _lkm_vfs( lkmtp, cmd);
|
||||
break;
|
||||
|
||||
case LM_DEV:
|
||||
{
|
||||
struct lkm_dev *args = lkmtp->private.lkm_dev;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef STREAMS
|
||||
case LM_STRMOD:
|
||||
{
|
||||
struct lkm_strmod *args = lkmtp->private.lkm_strmod;
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /* STREAMS*/
|
||||
|
||||
#ifdef LKM_EXEC
|
||||
case LM_EXEC:
|
||||
err = _lkm_exec( lkmtp, cmd);
|
||||
break;
|
||||
#endif /* LKM_EXEC */
|
||||
|
||||
case LM_MISC: /* ignore content -- no "misc-specific" procedure*/
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENXIO; /* unknown type*/
|
||||
break;
|
||||
}
|
||||
|
||||
return( err);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh -
|
||||
# from: @(#)makesyscalls.sh 7.6 (Berkeley) 4/20/91
|
||||
# $Id: makesyscalls.sh,v 1.4 1993/05/20 16:17:38 cgd Exp $
|
||||
# $Id: makesyscalls.sh,v 1.5 1993/06/07 19:52:40 cgd Exp $
|
||||
|
||||
set -e
|
||||
|
||||
|
@ -104,14 +104,15 @@ awk < $1 "
|
|||
if (NF < 5)
|
||||
$5 = $4
|
||||
}
|
||||
$2 == "STD" {
|
||||
$2 == "STD" || $2 == "NODEF" {
|
||||
printf("int\t%s();\n", $4) > sysdcl
|
||||
printf("\t%d, %s,\t\t\t/* %d = %s */\n", \
|
||||
$3, $4, syscall, $5) > sysent
|
||||
printf("\t\"%s\",\t\t\t/* %d = %s */\n", \
|
||||
$5, syscall, $5) > sysnames
|
||||
printf("#define\tSYS_%s\t%d\n", \
|
||||
$5, syscall) > syshdr
|
||||
if ($2 == "STD")
|
||||
printf("#define\tSYS_%s\t%d\n", \
|
||||
$5, syscall) > syshdr
|
||||
syscall++
|
||||
next
|
||||
}
|
||||
|
|
|
@ -226,4 +226,36 @@ char *syscallnames[] = {
|
|||
"#188", /* 188 = nosys */
|
||||
"#189", /* 189 = nosys */
|
||||
"#190", /* 190 = nosys */
|
||||
"#191", /* 191 = nosys */
|
||||
"#192", /* 192 = nosys */
|
||||
"#193", /* 193 = nosys */
|
||||
"#194", /* 194 = nosys */
|
||||
"#195", /* 195 = nosys */
|
||||
"#196", /* 196 = nosys */
|
||||
"#197", /* 197 = nosys */
|
||||
"#198", /* 198 = nosys */
|
||||
"#199", /* 199 = nosys */
|
||||
#ifdef LKM
|
||||
"lkmnosys", /* 200 = lkmnosys */
|
||||
"lkmnosys", /* 201 = lkmnosys */
|
||||
"lkmnosys", /* 202 = lkmnosys */
|
||||
"lkmnosys", /* 203 = lkmnosys */
|
||||
"lkmnosys", /* 204 = lkmnosys */
|
||||
"lkmnosys", /* 205 = lkmnosys */
|
||||
"lkmnosys", /* 206 = lkmnosys */
|
||||
"lkmnosys", /* 207 = lkmnosys */
|
||||
"lkmnosys", /* 208 = lkmnosys */
|
||||
"lkmnosys", /* 209 = lkmnosys */
|
||||
#else /* !LKM*/
|
||||
"#200", /* 200 = nosys */
|
||||
"#201", /* 201 = nosys */
|
||||
"#202", /* 202 = nosys */
|
||||
"#203", /* 203 = nosys */
|
||||
"#204", /* 204 = nosys */
|
||||
"#205", /* 205 = nosys */
|
||||
"#206", /* 206 = nosys */
|
||||
"#207", /* 207 = nosys */
|
||||
"#208", /* 208 = nosys */
|
||||
"#209", /* 209 = nosys */
|
||||
#endif /* !LKM*/
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
$Id: syscalls.master,v 1.5 1993/05/20 02:55:11 cgd Exp $
|
||||
$Id: syscalls.master,v 1.6 1993/06/07 19:52:42 cgd Exp $
|
||||
; from: @(#)syscalls.master 7.26 (Berkeley) 3/25/91
|
||||
; System call name/number master file.
|
||||
; Processed to created init_sysent.c, syscalls.c and syscall.h.
|
||||
|
||||
; Columns: number type nargs name altname/comments
|
||||
; number system call number, must be in order
|
||||
; type one of STD, OBSOL, UNIMPL, COMPAT
|
||||
; type one of STD, OBSOL, UNIMPL, NODEF, COMPAT
|
||||
; nargs number of arguments
|
||||
; name name of syscall routine
|
||||
; altname name of system call if different
|
||||
|
@ -16,6 +16,7 @@
|
|||
; COMPAT included on COMPAT #ifdef
|
||||
; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h
|
||||
; OBSOL obsolete, not included in system, only specifies name
|
||||
; NODEF do everything except include in syscall.h
|
||||
; UNIMPL not implemented, placeholder only
|
||||
|
||||
; #ifdef's, etc. may be included, and are copied to the output files.
|
||||
|
@ -253,3 +254,38 @@
|
|||
188 UNIMPL 0 nosys
|
||||
189 UNIMPL 0 nosys
|
||||
190 UNIMPL 0 nosys
|
||||
191 UNIMPL 0 nosys
|
||||
192 UNIMPL 0 nosys
|
||||
193 UNIMPL 0 nosys
|
||||
194 UNIMPL 0 nosys
|
||||
195 UNIMPL 0 nosys
|
||||
196 UNIMPL 0 nosys
|
||||
197 UNIMPL 0 nosys
|
||||
198 UNIMPL 0 nosys
|
||||
199 UNIMPL 0 nosys
|
||||
;
|
||||
; Syscalls 200-109 are reserved for dynamically loaded syscalls
|
||||
;
|
||||
#ifdef LKM
|
||||
200 NODEF 0 lkmnosys
|
||||
201 NODEF 0 lkmnosys
|
||||
202 NODEF 0 lkmnosys
|
||||
203 NODEF 0 lkmnosys
|
||||
204 NODEF 0 lkmnosys
|
||||
205 NODEF 0 lkmnosys
|
||||
206 NODEF 0 lkmnosys
|
||||
207 NODEF 0 lkmnosys
|
||||
208 NODEF 0 lkmnosys
|
||||
209 NODEF 0 lkmnosys
|
||||
#else /* !LKM */
|
||||
200 UNIMPL 0 nosys
|
||||
201 UNIMPL 0 nosys
|
||||
202 UNIMPL 0 nosys
|
||||
203 UNIMPL 0 nosys
|
||||
204 UNIMPL 0 nosys
|
||||
205 UNIMPL 0 nosys
|
||||
206 UNIMPL 0 nosys
|
||||
207 UNIMPL 0 nosys
|
||||
208 UNIMPL 0 nosys
|
||||
209 UNIMPL 0 nosys
|
||||
#endif /* !LKM */
|
||||
|
|
|
@ -1 +1 @@
|
|||
revision 1.10 intentionally removed
|
||||
revision 1.11 intentionally removed
|
||||
|
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* lkm.h
|
||||
*
|
||||
* Header file used by loadable kernel modules and loadable kernel module
|
||||
* utilities.
|
||||
*
|
||||
* 23 Jan 93 Terry Lambert Original
|
||||
*
|
||||
* Copyright (c) 1992 Terrence R. Lambert.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Terrence R. Lambert.
|
||||
* 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: lkm.h,v 1.1 1993/06/07 19:52:51 cgd Exp $
|
||||
*/
|
||||
#ifndef _SYS_LKM_H_
|
||||
#define _SYS_LKM_H_
|
||||
|
||||
|
||||
/*
|
||||
* Supported module types
|
||||
*/
|
||||
typedef enum loadmod {
|
||||
LM_SYSCALL,
|
||||
LM_VFS,
|
||||
LM_DEV,
|
||||
LM_STRMOD,
|
||||
LM_EXEC,
|
||||
LM_MISC
|
||||
} MODTYPE;
|
||||
|
||||
|
||||
#define LKM_VERSION 1 /* version of module loader*/
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Loadable system call
|
||||
*/
|
||||
struct lkm_syscall {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset; /* save/assign area*/
|
||||
struct sysent *lkm_sysent;
|
||||
struct sysent lkm_oldent; /* save area for unload*/
|
||||
};
|
||||
|
||||
/*
|
||||
* Loadable file system
|
||||
*/
|
||||
struct lkm_vfs {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset;
|
||||
unsigned long lkm_flags;
|
||||
struct vfsops *lkm_vfsops;
|
||||
};
|
||||
|
||||
/*
|
||||
* Supported device module types
|
||||
*/
|
||||
typedef enum devtype {
|
||||
LM_DT_BLOCK,
|
||||
LM_DT_CHAR
|
||||
} DEVTYPE;
|
||||
|
||||
/*
|
||||
* Loadable device driver
|
||||
*/
|
||||
struct lkm_dev {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset;
|
||||
DEVTYPE lkm_devtype;
|
||||
union {
|
||||
void *anon;
|
||||
struct bdevsw *bdev;
|
||||
struct cdevsw *cdev;
|
||||
} lkm_dev;
|
||||
union {
|
||||
struct bdevsw bdev;
|
||||
struct cdevsw cdev;
|
||||
} lkm_olddev;
|
||||
};
|
||||
|
||||
/*
|
||||
* Loadable streams module
|
||||
*/
|
||||
struct lkm_strmod {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset;
|
||||
/*
|
||||
* Removed: future release
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
* Exec loader
|
||||
*/
|
||||
struct lkm_exec {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset;
|
||||
struct execsw *lkm_exec;
|
||||
struct execsw lkm_oldexec;
|
||||
};
|
||||
|
||||
/*
|
||||
* Miscellaneous module (complex load/unload, potentially complex stat
|
||||
*/
|
||||
struct lkm_misc {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Any module (to get type and name info without knowing type)
|
||||
*/
|
||||
struct lkm_any {
|
||||
MODTYPE lkm_type;
|
||||
int lkm_ver;
|
||||
char *lkm_name;
|
||||
int lkm_offset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Generic reference ala XEvent to allow single entry point in the xxxinit()
|
||||
* routine.
|
||||
*/
|
||||
union lkm_generic {
|
||||
struct lkm_any *lkm_any;
|
||||
struct lkm_syscall *lkm_syscall;
|
||||
struct lkm_vfs *lkm_vfs;
|
||||
struct lkm_dev *lkm_dev;
|
||||
struct lkm_strmod *lkm_strmod;
|
||||
struct lkm_exec *lkm_exec;
|
||||
struct lkm_misc *lkm_misc;
|
||||
};
|
||||
|
||||
union lkm_all {
|
||||
struct lkm_any lkm_any;
|
||||
struct lkm_syscall lkm_syscall;
|
||||
struct lkm_vfs lkm_vfs;
|
||||
struct lkm_dev lkm_dev;
|
||||
struct lkm_strmod lkm_strmod;
|
||||
struct lkm_exec lkm_exec;
|
||||
struct lkm_misc lkm_misc;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per module information structure
|
||||
*/
|
||||
#define MAXLKMNAME 32
|
||||
struct lkm_table {
|
||||
int type;
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
char *area;
|
||||
char used;
|
||||
|
||||
int ver; /* version (INIT)*/
|
||||
int refcnt; /* reference count (INIT)*/
|
||||
int depcnt; /* dependency count (INIT)*/
|
||||
int id; /* identifier (INIT)*/
|
||||
|
||||
int (*entry)(); /* entry function*/
|
||||
union lkm_generic private; /* module private data*/
|
||||
};
|
||||
|
||||
|
||||
#define LKM_E_LOAD 1
|
||||
#define LKM_E_UNLOAD 2
|
||||
#define LKM_E_STAT 3
|
||||
|
||||
|
||||
#define MOD_SYSCALL(name,callslot,sysentp) \
|
||||
static struct lkm_syscall _module = { \
|
||||
LM_SYSCALL, \
|
||||
LKM_VERSION, \
|
||||
name, \
|
||||
callslot, \
|
||||
sysentp \
|
||||
};
|
||||
|
||||
#define MOD_VFS(name,vfsslot,flags,vfsopsp) \
|
||||
static struct lkm_vfs _module = { \
|
||||
LM_VFS, \
|
||||
LKM_VERSION, \
|
||||
name, \
|
||||
vfsslot, \
|
||||
flags, \
|
||||
vfsopsp \
|
||||
};
|
||||
|
||||
#define MOD_DEV(name,devtype,devslot,devp) \
|
||||
static struct lkm_dev _module = { \
|
||||
LM_DEV, \
|
||||
LKM_VERSION, \
|
||||
name, \
|
||||
devslot, \
|
||||
devtype, \
|
||||
(void *)devp \
|
||||
};
|
||||
|
||||
#define MOD_EXEC(name,execslot,execsw) \
|
||||
static struct lkm_exec _module = { \
|
||||
LM_EXEC, \
|
||||
LKM_VERSION, \
|
||||
name, \
|
||||
execslot, \
|
||||
execsw \
|
||||
};
|
||||
|
||||
#define MOD_MISC(name) \
|
||||
static struct lkm_misc _module = { \
|
||||
LM_MISC, \
|
||||
LKM_VERSION, \
|
||||
name \
|
||||
};
|
||||
|
||||
|
||||
extern int nosys();
|
||||
|
||||
/*
|
||||
* DISPATCH -- body function for use in module entry point function;
|
||||
* generally, the function body will consist entirely of a single
|
||||
* DISPATCH line.
|
||||
*
|
||||
* If load/unload/stat are not "nosys", then they are called on each
|
||||
* corresponding entry instance. "cmd" is passed to each function so
|
||||
* that a single function can be used if desired.
|
||||
*/
|
||||
#define DISPATCH(lkmtp,cmd,ver,load,unload,stat) \
|
||||
if( ver != LKM_VERSION) \
|
||||
return( EINVAL); /* version mismatch*/ \
|
||||
switch( cmd) { \
|
||||
int _err; \
|
||||
case LKM_E_LOAD: \
|
||||
lkmtp->private.lkm_any = (struct lkm_any *)&_module; \
|
||||
if( load != nosys && (_err = load( lkmtp, cmd))) \
|
||||
return( _err); \
|
||||
break; \
|
||||
case LKM_E_UNLOAD: \
|
||||
if( unload != nosys && (_err = unload( lkmtp, cmd))) \
|
||||
return( _err); \
|
||||
break; \
|
||||
case LKM_E_STAT: \
|
||||
if( stat != nosys && (_err = stat( lkmtp, cmd))) \
|
||||
return( _err); \
|
||||
break; \
|
||||
} \
|
||||
return( lkmdispatch( lkmtp, cmd));
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* IOCTL's recognized by /dev/lkm
|
||||
*/
|
||||
#define LMRESERV _IOWR( 'K', 0, struct lmc_resrv)
|
||||
#define LMLOADBUF _IOW( 'K', 1, struct lmc_loadbuf)
|
||||
#define LMUNRESRV _IO( 'K', 2)
|
||||
#define LMREADY _IOW( 'K', 3, int)
|
||||
|
||||
#define LMLOAD _IOW( 'K', 9, struct lmc_load)
|
||||
#define LMUNLOAD _IOWR( 'K', 10, struct lmc_unload)
|
||||
#define LMSTAT _IOWR( 'K', 11, struct lmc_stat)
|
||||
|
||||
#define MODIOBUF 512 /* # of bytes at a time to loadbuf*/
|
||||
|
||||
/*
|
||||
* IOCTL arguments
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Reserve a page-aligned block of kernel memory for the module
|
||||
*/
|
||||
struct lmc_resrv {
|
||||
unsigned long size; /* IN: size of module to reserve*/
|
||||
char *name; /* IN: name (must be provided*/
|
||||
int slot; /* OUT: allocated slot (module ID)*/
|
||||
unsigned long addr; /* OUT: Link-to address*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Copy a buffer at a time into the allocated area in the kernel; writes
|
||||
* are assumed to occur contiguously.
|
||||
*/
|
||||
struct lmc_loadbuf {
|
||||
int cnt; /* IN: # of chars pointed to by data*/
|
||||
char *data; /* IN: pointer to data buffer*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Load a module (assumes it's been mmapped to address before call)
|
||||
*/
|
||||
struct lmc_load {
|
||||
caddr_t address; /* IN: user space mmap address*/
|
||||
int status; /* OUT: status of operation*/
|
||||
int id; /* OUT: module ID if loaded*/
|
||||
};
|
||||
|
||||
/*
|
||||
* Unload a module (by name/id)
|
||||
*/
|
||||
struct lmc_unload {
|
||||
int id; /* IN: module ID to unload*/
|
||||
char *name; /* IN: module name to unload if id -1*/
|
||||
int status; /* OUT: status of operation*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Get module information for a given id (or name if id == -1).
|
||||
*/
|
||||
struct lmc_stat {
|
||||
int id; /* IN: module ID to unload*/
|
||||
char name[ MAXLKMNAME]; /* IN/OUT: name of module*/
|
||||
int offset; /* OUT: target table offset*/
|
||||
MODTYPE type; /* OUT: type of module*/
|
||||
char *area; /* OUT: kernel load addr*/
|
||||
int size; /* OUT: module size (pages)*/
|
||||
unsigned long private; /* OUT: module private data*/
|
||||
int ver; /* OUT: lkm compile version*/
|
||||
};
|
||||
|
||||
#endif /* !_SYS_LKM_H_ */
|
|
@ -1,6 +1,6 @@
|
|||
# @(#)Makefile 5.8.1.1 (Berkeley) 5/8/91
|
||||
#
|
||||
# $Id: Makefile,v 1.22 1993/06/03 19:32:26 brezak Exp $
|
||||
# $Id: Makefile,v 1.23 1993/06/07 19:52:54 cgd Exp $
|
||||
|
||||
SUBDIR= ar biff basename cal calendar cap_mkdb \
|
||||
checknr chpass cksum cmp col colcrt colrm column comm compress \
|
||||
|
@ -9,8 +9,8 @@ SUBDIR= ar biff basename cal calendar cap_mkdb \
|
|||
fsplit fstat ftp gprof groups head hexdump \
|
||||
id indent join ktrace last lastcomm leave locate lock logger \
|
||||
login logname look lorder m4 machine mail make man mesg mkdep mkfifo \
|
||||
mkstr more msgs netstat newsyslog nfsstat nice nm nohup pagesize \
|
||||
passwd paste patch printenv printf quota ranlib \
|
||||
mkstr modstat more msgs netstat newsyslog nfsstat nice nm nohup \
|
||||
pagesize passwd paste patch printenv printf quota ranlib \
|
||||
rdist ref renice rev rlogin rpcgen rpcinfo \
|
||||
rsh rup ruptime rusers rwall rwho \
|
||||
sccs script sed shar showmount size soelim split strings \
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
# Makefile for modstat
|
||||
#
|
||||
# 25 May 93 Terry Lambert Original
|
||||
#
|
||||
# Copyright (c) 1993 Terrence R. Lambert.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by Terrence R. Lambert.
|
||||
# 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $Id: Makefile,v 1.1 1993/06/07 19:52:57 cgd Exp $
|
||||
#
|
||||
|
||||
PROG= modstat
|
||||
CFLAGS=-DKERNEL
|
||||
NOMAN= noman
|
||||
BINGRP= kmem
|
||||
BINMODE=2555
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* modstat.c
|
||||
*
|
||||
* This is the loadable kernel module status display program. The
|
||||
* interface is nearly identical to the SunOS 4.1.3 not because I
|
||||
* lack imagination but because I liked Sun's approach in this
|
||||
* particular revision of their BSD-derived OS.
|
||||
*
|
||||
* modstat [-i <module id>] [-n <module name>]
|
||||
*
|
||||
* Default behaviour is to report status for all modules.
|
||||
*
|
||||
* -i <module id> - status for module by id
|
||||
* -n <module name> - status for module by name
|
||||
*
|
||||
* Copyright (c) 1993 Terrence R. Lambert.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Terrence R. Lambert.
|
||||
* 4. The name Terrence R. Lambert may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: modstat.c,v 1.1 1993/06/07 19:52:58 cgd Exp $
|
||||
*/
|
||||
|
||||
#define printf I_HATE_ANSI
|
||||
#include <stdio.h>
|
||||
#undef printf
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/lkm.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
extern int errno; /* should be in errno.h*/
|
||||
|
||||
|
||||
#ifdef sun
|
||||
/* these are defined in stdlib.h for everything but sun*/
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
#endif /* sun*/
|
||||
|
||||
#define LKM_DEV "/dev/lkm"
|
||||
|
||||
|
||||
extern int dostat();
|
||||
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf( stderr, "usage:\n");
|
||||
fprintf( stderr,
|
||||
"modstat [-i <module id>] [-n <module name>]\n");
|
||||
exit( 1);
|
||||
}
|
||||
|
||||
|
||||
main( ac, av)
|
||||
int ac;
|
||||
char *av[];
|
||||
{
|
||||
int devfd;
|
||||
int i;
|
||||
int ch;
|
||||
int err = 0;
|
||||
int modnum = -1;
|
||||
char *modname = NULL;
|
||||
|
||||
while( ( ch = getopt( ac, av, "i:n:")) != EOF) {
|
||||
switch(ch) {
|
||||
case 'i': modnum = atoi( optarg); break; /* number*/
|
||||
case 'n': modname = optarg; break; /* name*/
|
||||
case '?': usage();
|
||||
default: printf( "default!\n");
|
||||
}
|
||||
}
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
if( ac != 0)
|
||||
usage();
|
||||
|
||||
|
||||
/*
|
||||
* Open the virtual device device driver for exclusive use (needed
|
||||
* to ioctl() to retrive the loaded module(s) status).
|
||||
*/
|
||||
if( ( devfd = open( LKM_DEV, O_RDONLY, 0)) == -1) {
|
||||
perror( LKM_DEV);
|
||||
exit( 2);
|
||||
}
|
||||
|
||||
printf( "Type Id Off Loadaddr Size Info Rev Module Name\n");
|
||||
|
||||
/*
|
||||
* Oneshot?
|
||||
*/
|
||||
if( modnum != -1 || modname != NULL) {
|
||||
if( dostat( devfd, modnum, modname))
|
||||
err = 3;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start at 0 and work up until "EEXIST"
|
||||
*/
|
||||
for( modnum = 0; dostat( devfd, modnum, NULL) < 2; modnum++)
|
||||
continue;
|
||||
|
||||
done:
|
||||
close( devfd);
|
||||
exit( err);
|
||||
}
|
||||
|
||||
|
||||
static char *type_names[] = {
|
||||
"SYSCALL",
|
||||
"VFS",
|
||||
"DEV",
|
||||
"STRMOD",
|
||||
"EXEC",
|
||||
"MISC"
|
||||
};
|
||||
|
||||
int
|
||||
dostat( devfd, modnum, modname)
|
||||
int devfd;
|
||||
int modnum;
|
||||
char *modname;
|
||||
{
|
||||
struct lmc_stat sbuf;
|
||||
|
||||
if( modname != NULL)
|
||||
strcpy( sbuf.name, modname);
|
||||
|
||||
sbuf.id = modnum;
|
||||
|
||||
if( ioctl( devfd, LMSTAT, &sbuf) == -1) {
|
||||
switch( errno) {
|
||||
case EINVAL: /* out of range*/
|
||||
return( 2);
|
||||
case ENOENT: /* no such entry*/
|
||||
return( 1);
|
||||
default: /* other error (EFAULT, etc)*/
|
||||
perror( "LMSTAT");
|
||||
return( 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode this stat buffer...
|
||||
*/
|
||||
printf( "%-7s %3d %3d %08x %04x %8x %3d %s\n",
|
||||
type_names[ sbuf.type],
|
||||
sbuf.id, /* module id*/
|
||||
sbuf.offset, /* offset into modtype struct*/
|
||||
sbuf.area, /* address module loaded at*/
|
||||
sbuf.size, /* size in pages(K)*/
|
||||
sbuf.private, /* kernel address of private area*/
|
||||
sbuf.ver, /* Version; always 1 for now*/
|
||||
sbuf.name /* name from private area*/
|
||||
);
|
||||
|
||||
/*
|
||||
* Done (success).
|
||||
*/
|
||||
return( 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EOF -- This file has not been truncated.
|
||||
*/
|
Loading…
Reference in New Issue