Merge commit 'b31ca922c7346747131aed07c0c171ec2f573aac' into merges
[unleashed.git] / share / man / man9f / ddi_modopen.9f
blob75fe40f55acf1f5de8b49237b952d77725867181
1 '\" te
2 .\" Copyright (c) 2008, Sun Microsystems, Inc., All Rights Reserved
3 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
4 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
5 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
6 .TH DDI_MODOPEN 9F "Mar 17, 2008"
7 .SH NAME
8 ddi_modopen, ddi_modsym, ddi_modclose \- dynamically-loaded kernel module
9 functions
10 .SH SYNOPSIS
11 .LP
12 .nf
13 #include <sys/modctl.h>
15 \fBddi_modhandle_t\fR \fBddi_modopen\fR(\fBconst char\fR\fI*modname\fR, \fBint\fR \fImode\fR,
16      \fBint\fR \fI*errnop\fR);
17 .fi
19 .LP
20 .nf
21 \fBvoid\fR \fB*ddi_modsym\fR(\fBddi_modhandle_t\fR \fIhandle\fR, \fBconst char\fR \fI*symname\fR,
22      \fBint\fR \fI*errnop\fR);
23 .fi
25 .LP
26 .nf
27 \fBint\fR \fBddi_modclose\fR(\fBddi_modhandle_t\fR \fIhandle\fR);
28 .fi
30 .SH INTERFACE LEVEL
31 .sp
32 .LP
33 Solaris DDI specific (Solaris DDI).
34 .SH PARAMETERS
35 .sp
36 .ne 2
37 .na
38 \fB\fImodname\fR\fR
39 .ad
40 .RS 11n
41 The name of the dynamically-loaded kernel module (file) to be opened. The
42 \fImodname\fR string is of the form:
43 .sp
44 .in +2
45 .nf
46 "[\fInamespace\fR/[\fIdirspace\fR/]]\fImodulename\fR"
47 .fi
48 .in -2
49 .sp
51 Each "\fInamespace\fR/" directory along the standard kernel
52 moddir/\fImodule-path\fR path (\fBsystem\fR(4)) is searched to locate the
53 module. If "\fInamespace\fR/" is not specified, "misc/" is assumed. If
54 "\fIdirspace\fR" is specified, then "\fInamespace\fR/" must be explicitly
55 provided.
56 .RE
58 .sp
59 .ne 2
60 .na
61 \fB\fImode\fR\fR
62 .ad
63 .RS 11n
64 Currently, \fBKRTLD_MODE_FIRST\fR.
65 .RE
67 .sp
68 .ne 2
69 .na
70 \fB\fIerrnop\fR\fR
71 .ad
72 .RS 11n
73 Pointer to \fBerrno\fR returned on error, if \fBNULL\fR then no additional
74 error information is available.
75 .RE
77 .sp
78 .ne 2
79 .na
80 \fB\fIhandle\fR\fR
81 .ad
82 .RS 11n
83 Opaque handle returned from \fBddi_modopen()\fR, invalidated by
84 \fBddi_modclose()\fR.
85 .RE
87 .sp
88 .ne 2
89 .na
90 \fB\fIsymname\fR\fR
91 .ad
92 .RS 11n
93 Symbol's name as a character string.
94 .RE
96 .SH DESCRIPTION
97 .sp
98 .LP
99 The function prototypes for \fBddi_modopen()\fR, \fBddi_modsym()\fR, and
100 \fBddi_modclose()\fR are modeled after the userland \fBlibdl\fR(3LIB),
101 \fBdlopen\fR(3C), \fBdlsym\fR(3C), and \fBdlclose\fR(3C) interfaces, however
102 not all userland features are available and the kernel symbol resolution is
103 different. The \fBdlerror\fR(3C) interface is not appropriate for the kernel
104 environment, so the new \fIerrnop\fR return argument was added for
105 \fBddi_modopen()\fR and \fBddi_modsym()\fR.
108 The \fBddi_modopen()\fRfunction makes a dynamically-loaded kernel module named
109 by "modname" available to a running kernel. \fBddi_modopen()\fR returns a
110 handle that the caller can use on subsequent calls to \fBddi_modsym()\fR and
111 \fBddi_modclose()\fR. The value of this handle should not be interpreted in any
112 way by the caller.
115 The \fBddi_modopen()\fR interface works best as a dynamic component/object
116 plug-in mechanism when targeting kernel "misc" modules that contain a single
117 "struct modlmisc" module linkage, however non-"misc" modules and modules with
118 multiple linkage structures can also be targeted.
121 There are two different symbol resolution search orders associated with the
122 \fBddi_modopen()\fR function: one search order to resolve symbols during the
123 load of the targeted module, another search order o resolve \fBddi_modsym()\fR
124 calls against the handle returned by \fBddi_modopen()\fR. To resolve symbols
125 during module load, the standard kernel module load search order is used; to
126 resolve symbols during module "A" load, the order is as follows:
128 .in +2
130 A -> A's _depends_on -> unix -> unix's _depends_on
132 .in -2
137 A single-level, left-to-right search in \fB_depends_on\fR (or the "ld -N"
138 alternative) modules occurs. For \fBUNIX\fR on \fBSparc\fR, \fB_depends_on\fR
139 is similar to "genunix misc/platmod cpu/SUNW,UltraSPARC-III+  dtracestubs" for
140 \fBIntel\fR, it is "genunix dtracestubs". The \fBddi_modsym()\fR search is
141 limited to the module directly associated with the handle.
144 The \fBddi_modopen()\fR function increments the reference count on the named
145 kernel module. Upon the first load of a module, the \fB_init\fR(9E)
146 initialization code in the module is called; \fBddi_modopen()\fR does not
147 return until \fB_init\fR completes.
150 The \fBddi_modsym()\fR function allows a caller to obtain the address of a
151 symbol that is defined within a module. The \fIhandle\fR argument is a valid
152 \fBddi_modhandle_t\fR as returned by \fBddi_modopen()\fR, the \fIsymname\fR
153 argument is the symbol's name as a character string. The special handle values
154 supported by ddi_modsym(9F) are not supported.
157 The \fBddi_modclose()\fR function decrements the reference count of the kernel
158 module associated with the specified handle. After the \fBddi_modclose()\fR
159 function is called, all \fBddi_modsym()\fR resolutions obtained (either
160 directly or indirectly) using the now closed \fIhandle\fR are invalid; further
161 use of these resolutions can cause undefined behavior (that is, may lead to a
162 panic). When the last \fBddi_modclose()\fR of a module occurs, and there are no
163 further references to the module, the module \fB_fini\fR(9E)entry point may be
164 called. If \fB_fini\fR returns success then the module may be unloaded.
165 .SH RETURN VALUES
168 The \fBddi_modopen()\fR function returns a handle to the dynamically-loaded
169 kernel module. The \fBddi_modopen()\fR function returns \fBNULL\fR if the
170 module cannot be found, the object cannot be relocated, or an error occurs
171 during the process of resolving and relocating its symbolic references.
174 The \fBddi_modsym()\fR function returns \fBNULL\fR if the \fIsymname\fR symbol
175 cannot be found directly within the module associated with the \fIhandle\fR.
178 If the \fIhandle\fR was not referenced, \fBddi_modclose()\fR returns 0. If the
179 \fIhandle\fR is invalid, \fBddi_modclose()\fR may return a non-zero value.
182 When either \fBddi_modopen()\fR or \fBddi_modsym()\fR return \fBNULL\fR,
183 additional \fIerrno\fR information related to the failure is returned in
184 \fI*errnop\fR if it is not \fBNULL\fR.
185 .SH CONTEXT
188 \fBddi_modopen()\fR can be called from user context only.
189 .SH EXAMPLES
191 \fBExample 1 \fRCoding a Dynamically Loaded Kernel Module
194 The following example shows code to dynamically load and call a "\fBtest\fR"
195 interface in a module called "\fBdltest\fR". The "\fBtest\fR" interface  then
196 adds one to its integer argument.
199 .in +2
201 ddi_modhandle_t modh;
202 int             (*test)(int);
203 int             i = 0;
204 int             errno;
205 ---%<---
206 /* dynamically load "dltest" kernel 'misc' module */
207 modh = ddi_modopen("dltest", KRTLD_MODE_FIRST, &errno);
208 if (modh == NULL)
209          goto fail;      /* failed to open dltest module */
211 test = (int (*)())ddi_modsym(modh, "test", &errno);
212 if (test == NULL) {
213         (void) ddi_modclose(modh);
214         goto fail;      /* failed to find "test" interface */
217 /* invoke test interface and verify result */
218 i = (*test)(0);
219 ASSERT(i == 1);
221 (void) ddi_modclose(modh);
222 ---%<---
224 .in -2
228 The implementation of the "dltest" "misc" module is as follows:
231 .in +2
233 #include <sys/modctl.h>
234 static dltest_add = 0;
236 /* define the module linkage */
237 static struct modlmisc          modlmisc = {&mod_miscops, "dltest"};
238 static struct modlinkage        modlinkage = {
239         MODREV_1, (void *)&modmisc, NULL
242 _init(void)
244         int     i;
246         dltest_add = 1;                 /* initialization */
247         if ((i = mod_install(&modlinkage)) != 0)
248                 dltest_add = -1;        /* un-initialization */
249         return (i);
252 _fini()
254         int     i;
256         if ((i = mod_remove(&modlinkage)) == 0)
257                         dltest_add = -1;        /* un-initialization */
258         return (i);
261 _info(struct modinfo *modinfop)
263         return (mod_info(&modlinkage, modinfop));
266 /* "test" interface */
268 test(int i)
270         return (i + dltest_add);
273 .in -2
276 \fBExample 2 \fRDynamically Accessing a Kernel Module within a Drive
279 The following example shows driver code to dynamically load into the kernel a
280 module constructed via the \fBelfwrap\fR(1) utility and containing firmware
281 intended for download to a device. The "\fBstart\fR" and "\fBend\fR" pointers
282 provide the addresses of the beginning of the data and first byte beyond the
283 data.
286 .in +2
288 ddi_modhandle_t modp;
289 char *data_startp, *data_endp;
290 size_t nbytes;
291 int rv;
293 modp = ddi_modopen("firmware-rev1.2a", KRTLD_MODE_FIRST, &rv);
294 data_startp = (char *)ddi_modsym(modp, "fw-rev1.2a_start", &rv);
295 data_endp = (char *)ddi_modsym(modp, "fw-rev1.2a_end", &rv);
296 nbytes = data_endp - data_startp;
297 rv = ddi_modclose(modp);
299 .in -2
301 .SH SEE ALSO
304 \fBdlclose\fR(3C), \fBdlopen\fR(3C), \fBdlsym\fR(3C), \fBlibdl\fR(3LIB),
305 \fBboot\fR(8), \fBelfwrap\fR(1), \fBmodload\fR(8), \fBsystem\fR(4),
306 \fB_fini\fR(9E), \fB_info\fR(9E), \fB_init\fR(9E)
309 \fIWriting Device Drivers\fR
310 .SH WARNINGS
313 A \fBsystem\fR(4)forceload must be established for modules targeted by
314 \fBddi_modopen()\fR by code involved in the mount of root on "bootdev" during
315 machine \fBboot\fR(8).