summaryrefslogtreecommitdiffstats
path: root/sbin/modload
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1994-08-19 12:07:23 +0000
committerdg <dg@FreeBSD.org>1994-08-19 12:07:23 +0000
commitaf3f714addb5ee7de74ce27b39d8de8aa3c62752 (patch)
treeafae7211c5e1cfae02b4c13cba0f060f91012b60 /sbin/modload
parent6b1e97340f82d737dbaca8bb01e7ba5e944ca3e1 (diff)
downloadFreeBSD-src-af3f714addb5ee7de74ce27b39d8de8aa3c62752.zip
FreeBSD-src-af3f714addb5ee7de74ce27b39d8de8aa3c62752.tar.gz
Terry Lambert's loadable kernel module support - modload & modunload
utilities w/improvements from the NetBSD group.
Diffstat (limited to 'sbin/modload')
-rw-r--r--sbin/modload/Makefile42
-rw-r--r--sbin/modload/modload.8115
-rw-r--r--sbin/modload/modload.c335
-rw-r--r--sbin/modload/pathnames.h3
4 files changed, 495 insertions, 0 deletions
diff --git a/sbin/modload/Makefile b/sbin/modload/Makefile
new file mode 100644
index 0000000..265869f
--- /dev/null
+++ b/sbin/modload/Makefile
@@ -0,0 +1,42 @@
+#
+# 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.4 1994/02/09 15:00:32 deraadt Exp $
+#
+
+PROG= modload
+MAN8= modload.8
+
+.include <bsd.prog.mk>
diff --git a/sbin/modload/modload.8 b/sbin/modload/modload.8
new file mode 100644
index 0000000..e9e9315
--- /dev/null
+++ b/sbin/modload/modload.8
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1993 Christopher G. Demetriou
+.\" 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. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.8,v 1.3 1994/01/29 01:43:30 jtc Exp $
+.\"
+.Dd June 7, 1993
+.Dt MODLOAD 8
+.Os NetBSD 0.8a
+.Sh NAME
+.Nm modload
+.Nd load a kernel module
+.Sh SYNOPSIS
+.Nm modload
+.Op Fl dv
+.Op Fl A Ar kernel
+.Op Fl e Ar entry
+.Op Fl p Ar postinstall
+.Op Fl o Ar output_file
+.Ar input_file
+.Sh DESCRIPTION
+The
+.Nm
+utility loads a loadable kernel module into a running system.
+The input file is an object file (.o file).
+.Pp
+The options to
+.Nm
+are as follows:
+.Bl -tag -width indent
+.It Fl d
+Debug. Used to debug
+.Nm
+itself.
+.It Fl v
+Print comments about the loading process.
+.It Fl A Ar kernel
+Specify the file that is passed to the linker
+to resolve module references to external symbols.
+The symbol file must be for the currently running
+kernel or the module is likely to crash the system.
+.It Fl e Ar entry
+Specify the module entry point.
+This is passed by
+.Nm
+to
+.Xr ld 1
+when the module is linked.
+The default module entry point name is `xxxinit'.
+.It Fl p Ar postinstall
+Specify the name of a shell script or program that will
+be executed if the module is successfully loaded. It
+is always passed the module id (in decimal) and module
+type (in hexadecimal) as the first two arguments.
+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.
+.It Fl o Ar output_file
+Specify the name of the output file that is produced by
+the linker.
+.El
+.Sh FILES
+.Bl -tag -width /usr/include/sys/lkm.h -compact
+.It Pa /netbsd
+default file passed to the linker to resolve external
+references in the module
+.It Pa /usr/include/sys/lkm.h
+file containing definitions of module types
+.\" .It Pa output file.
+.\" default output file name
+.Sh DIAGNOSTICS
+The
+.Nm
+utility exits with a status of 0 on success
+and with a nonzero status if an error occurs.
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr lkm 4 ,
+.Xr modunload 8 ,
+.Xr modstat 8
+.Sh HISTORY
+The
+.Nm
+command was designed to be similar in functionality
+to the corresponding command in
+.Tn "SunOS 4.1.3" .
+.Sh AUTHOR
+.Bl -tag
+Terrence R. Lambert, terry@cs.weber.edu
+.El
+.Sh BUGS
+Loadable streams modules and loadable execution interpreters
+are not currently supported.
diff --git a/sbin/modload/modload.c b/sbin/modload/modload.c
new file mode 100644
index 0000000..256d1f3
--- /dev/null
+++ b/sbin/modload/modload.c
@@ -0,0 +1,335 @@
+/*
+ * 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.9 1994/05/23 05:42:41 cgd Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <a.out.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/conf.h>
+#include <sys/mount.h>
+#include <sys/lkm.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+#include "pathnames.h"
+
+#ifndef DFLT_ENTRY
+#define DFLT_ENTRY "xxxinit"
+#endif /* !DFLT_ENTRY */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ * 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 -A %s -e _%s -o %s -T %x %s"
+
+int debug = 0;
+int verbose = 0;
+
+int
+linkcmd(kernel, entry, outfile, address, object)
+ char *kernel, *entry, *outfile;
+ u_int address; /* XXX */
+ char *object;
+{
+ char cmdbuf[1024];
+ int error = 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 NetBSD
+ * 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:
+ error = 1;
+ break;
+ }
+
+ return error;
+}
+
+void
+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 fileopen = 0;
+#define DEV_OPEN 0x01
+#define MOD_OPEN 0x02
+#define PART_RESRV 0x04
+int devfd, modfd;
+struct lmc_resrv resrv;
+
+void
+cleanup()
+{
+ if (fileopen & PART_RESRV) {
+ /*
+ * Free up kernel memory
+ */
+ if (ioctl(devfd, LMUNRESRV, 0) == -1)
+ warn("can't release slot 0x%08x memory", resrv.slot);
+ }
+
+ if (fileopen & DEV_OPEN)
+ close(devfd);
+
+ if (fileopen & MOD_OPEN)
+ close(modfd);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int c;
+ char *kname = _PATH_UNIX;
+ char *entry = DFLT_ENTRY;
+ char *post = NULL;
+ char *out = NULL;
+ char *modobj;
+ char modout[80], *p;
+ struct exec info_buf;
+ u_int modsize; /* XXX */
+ u_int modentry; /* XXX */
+
+ struct lmc_loadbuf ldbuf;
+ int sz, bytesleft;
+ char buf[MODIOBUF];
+
+ while ((c = getopt(argc, argv, "dvA:e:p:o:")) != EOF) {
+ switch (c) {
+ 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");
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ modobj = argv[0];
+
+ atexit(cleanup);
+
+ /*
+ * 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(_PATH_LKM, O_RDWR, 0)) == -1)
+ err(3, _PATH_LKM);
+ fileopen |= DEV_OPEN;
+
+ strcpy(modout, modobj);
+
+ p = strchr(modout, '.');
+ if (!p || strcmp(p, ".o"))
+ errx(2, "module object must end in .o");
+ if (out == NULL) {
+ out = modout;
+ *p == 0;
+ }
+
+ /*
+ * Prelink to get file size
+ */
+ if (linkcmd(kname, entry, out, 0, modobj))
+ errx(1, "can't prelink `%s' creating `%s'", modobj, out);
+
+ /*
+ * Pre-open the 0-linked module to get the size information
+ */
+ if ((modfd = open(out, O_RDONLY, 0)) == -1)
+ err(4, out);
+ fileopen |= 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)
+ err(3, "read `%s'", out);
+
+ /*
+ * Close the dummy module -- we have our sizing information.
+ */
+ close(modfd);
+ fileopen &= ~MOD_OPEN;
+
+ /*
+ * Magic number...
+ */
+ if (N_BADMAG(info_buf))
+ errx(4, "not an a.out format file");
+
+ /*
+ * Calculate the size of the module
+ */
+ modsize = info_buf.a_text + info_buf.a_data + info_buf.a_bss;
+
+ /*
+ * 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)
+ err(9, "can't reserve memory");
+ fileopen |= PART_RESRV;
+
+ /*
+ * Relink at kernel load address
+ */
+ if (linkcmd(kname, entry, out, resrv.addr, modobj))
+ errx(1, "can't link `%s' creating `%s' bound to 0x%08x",
+ modobj, out, resrv.addr);
+
+ /*
+ * Open the relinked module to load it...
+ */
+ if ((modfd = open(out, O_RDONLY, 0)) == -1)
+ err(4, out);
+ fileopen |= MOD_OPEN;
+
+ /*
+ * Reread the header to get the actual entry point *after* the
+ * relink.
+ */
+ if (read(modfd, &info_buf, sizeof(struct exec)) == -1)
+ err(3, "read `%s'", out);
+
+ /*
+ * 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)
+ err(12, "lseek");
+
+ /*
+ * Transfer the relinked module to kernel memory in chunks of
+ * MODIOBUF size at a time.
+ */
+ for (bytesleft = info_buf.a_text + info_buf.a_data;
+ bytesleft > 0;
+ bytesleft -= sz) {
+ sz = min(bytesleft, MODIOBUF);
+ read(modfd, buf, sz);
+ ldbuf.cnt = sz;
+ ldbuf.data = buf;
+ if (ioctl(devfd, LMLOADBUF, &ldbuf) == -1)
+ err(11, "error transferring buffer");
+ }
+
+ /*
+ * 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)
+ err(14, "error initializing module");
+
+ /*
+ * Success!
+ */
+ fileopen &= ~PART_RESRV; /* loaded */
+ printf("Module loaded as ID %d\n", resrv.slot);
+
+ return 0;
+}
diff --git a/sbin/modload/pathnames.h b/sbin/modload/pathnames.h
new file mode 100644
index 0000000..81f70f2
--- /dev/null
+++ b/sbin/modload/pathnames.h
@@ -0,0 +1,3 @@
+#include <paths.h>
+
+#define _PATH_LKM "/dev/lkm"
OpenPOWER on IntegriCloud