1ddi_modopen(9F) Kernel Functions for Drivers ddi_modopen(9F)
2
3
4
6 ddi_modopen, ddi_modsym, ddi_modclose - dynamically-loaded kernel mod‐
7 ule functions
8
10 #include <sys/modctl.h>
11
12 ddi_modhandle_t ddi_modopen(const char*modname, int mode,
13 int *errnop);
14
15
16 void *ddi_modsym(ddi_modhandle_t handle, const char *symname,
17 int *errnop);
18
19
20 int ddi_modclose(ddi_modhandle_t handle);
21
22
24 Solaris DDI specific (Solaris DDI).
25
27 modname The name of the dynamically-loaded kernel module (file) to
28 be opened. The modname string is of the form:
29
30 "[namespace/[dirspace/]]modulename"
31
32
33 Each "namespace/" directory along the standard kernel mod‐
34 dir/module-path path (system(4)) is searched to locate the
35 module. If "namespace/" is not specified, "misc/" is
36 assumed. If "dirspace" is specified, then "namespace/" must
37 be explicitly provided.
38
39
40 mode Currently, KRTLD_MODE_FIRST.
41
42
43 errnop Pointer to errno returned on error, if NULL then no addi‐
44 tional error information is available.
45
46
47 handle Opaque handle returned from ddi_modopen(), invalidated by
48 ddi_modclose().
49
50
51 symname Symbol's name as a character string.
52
53
55 The function prototypes for ddi_modopen(), ddi_modsym(), and ddi_mod‐
56 close() are modeled after the userland libdl(3LIB), dlopen(3C),
57 dlsym(3C) , anddlclose(3C) interfaces, however not all userland fea‐
58 tures are available and the kernel symbol resolution is different. The
59 dlerror(3C) interface is not appropriate for the kernel environment, so
60 the new errnop return argument was added for ddi_modopen() and
61 ddi_modsym().
62
63
64 The ddi_modopen()function makes a dynamically-loaded kernel module
65 named by "modname" available to a running kernel. ddi_modopen() returns
66 a handle that the caller can use on subsequent calls to ddi_modsym()
67 and ddi_modclose(). The value of this handle should not be interpreted
68 in any way by the caller.
69
70
71 The ddi_modopen() interface works best as a dynamic component/object
72 plug-in mechanism when targeting kernel "misc" modules that contain a
73 single "struct modlmisc" module linkage, however non-"misc" modules and
74 modules with multiple linkage structures can also be targeted.
75
76
77 There are two different symbol resolution search orders associated with
78 the ddi_modopen() function: one search order to resolve symbols during
79 the load of the targeted module, another search order o resolve
80 ddi_modsym() calls against the handle returned by ddi_modopen(). To
81 resolve symbols during module load, the standard kernel module load
82 search order is used; to resolve symbols during module "A" load, the
83 order is as follows:
84
85 A -> A's _depends_on -> unix -> unix's _depends_on
86
87
88
89
90 A single-level, left-to-right search in _depends_on (or the "ld -N"
91 alternative) modules occurs. For UNIX on Sparc, _depends_on is similar
92 to "genunix misc/platmod cpu/SUNW,UltraSPARC-III+ dtracestubs" for
93 Intel, it is "genunix dtracestubs". The ddi_modsym() search is limited
94 to the module directly associated with the handle.
95
96
97 The ddi_modopen() function increments the reference count on the named
98 kernel module. Upon the first load of a module, the_init(9E) initial‐
99 ization code in the module is called; ddi_modopen() does not return
100 until _init completes.
101
102
103 The ddi_modsym() function allows a caller to obtain the address of a
104 symbol that is defined within a module. The handle argument is a valid
105 ddi_modhandle_t as returned by ddi_modopen(), the symname argument is
106 the symbol's name as a character string. The special handle values sup‐
107 ported by ddi_modsym(3C) are not supported.
108
109
110 The ddi_modclose() function decrements the reference count of the ker‐
111 nel module associated with the specified handle. After the ddi_mod‐
112 close() function is called, all ddi_modsym() resolutions obtained
113 (either directly or indirectly) using the now closed handle are
114 invalid; further use of these resolutions can cause undefined behavior
115 (that is, may lead to a panic). When the last ddi_modclose() of a mod‐
116 ule occurs, and there are no further references to the module, the mod‐
117 ule _fini(9E)entry point may be called. If _fini returns success then
118 the module may be unloaded.
119
121 The ddi_modopen() function returns a handle to the dynamically-loaded
122 kernel module. The ddi_modopen() function returns NULL if the module
123 cannot be found, the object cannot be relocated, or an error occurs
124 during the process of resolving and relocating its symbolic references.
125
126
127 The ddi_modsym() function returns NULL if the symname symbol cannot be
128 found directly within the module associated with the handle.
129
130
131 If the handle was not referenced, ddi_modclose() returns 0. If the han‐
132 dle is invalid, ddi_modclose() may return a non-zero value.
133
134
135 When either ddi_modopen() or ddi_modsym() return NULL, additional errno
136 information related to the failure is returned in *errnop if it is not
137 NULL.
138
140 ddi_modopen() can be called from user context only.
141
143 Example 1 Coding a Dynamically Loaded Kernel Module
144
145
146 The following example shows code to dynamically load and call a "test"
147 interface in a module called "dltest". The "test" interface then adds
148 one to its integer argument.
149
150
151 ddi_modhandle_t modh;
152 int (*test)(int);
153 int i = 0;
154 int errno;
155 ---%<---
156 /* dynamically load "dltest" kernel 'misc' module */
157 modh = ddi_modopen("dltest", KRTLD_MODE_FIRST, &errno);
158 if (modh == NULL)
159 goto fail; /* failed to open dltest module */
160
161 test = (int (*)())ddi_modsym(modh, "test", &errno);
162 if (test == NULL) {
163 (void) ddi_modclose(modh);
164 goto fail; /* failed to find "test" interface */
165 }
166
167 /* invoke test interface and verify result */
168 i = (*test)(0);
169 ASSERT(i == 1);
170
171 (void) ddi_modclose(modh);
172 ---%<---
173
174
175
176 The implementation of the "dltest" "misc" module is as follows:
177
178
179 #include <sys/modctl.h>
180 static dltest_add = 0;
181
182 /* define the module linkage */
183 static struct modlmisc modlmisc = {&mod_miscops, "dltest"};
184 static struct modlinkage modlinkage = {
185 MODREV_1, (void *)&modmisc, NULL
186 };
187 int
188 _init(void)
189 {
190 int i;
191
192 dltest_add = 1; /* initialization */
193 if ((i = mod_install(&modlinkage)) != 0)
194 dltest_add = -1; /* un-initialization */
195 return (i);
196 }
197 int
198 _fini()
199 {
200 int i;
201
202 if ((i = mod_remove(&modlinkage)) == 0)
203 dltest_add = -1; /* un-initialization */
204 return (i);
205 }
206 int
207 _info(struct modinfo *modinfop)
208 {
209 return (mod_info(&modlinkage, modinfop));
210 }
211
212 /* "test" interface */
213 int
214 test(int i)
215 {
216 return (i + dltest_add);
217 }
218
219
220 Example 2 Dynamically Accessing a Kernel Module within a Drive
221
222
223 The following example shows driver code to dynamically load into the
224 kernel a module constructed via the elfwrap(1) utility and containing
225 firmware intended for download to a device. The "start" and "end"
226 pointers provide the addresses of the beginning of the data and first
227 byte beyond the data.
228
229
230 ddi_modhandle_t modp;
231 char *data_startp, *data_endp;
232 size_t nbytes;
233 int rv;
234
235 modp = ddi_modopen("firmware-rev1.2a", KRTLD_MODE_FIRST, &rv);
236 data_startp = (char *)ddi_modsym(modp, "fw-rev1.2a_start", &rv);
237 data_endp = (char *)ddi_modsym(modp, "fw-rev1.2a_end", &rv);
238 nbytes = data_endp - data_startp;
239 rv = ddi_modclose(modp);
240
241
243 dlclose(3C), dlopen(3C), dlsym(3C), libdl(3LIB), boot(1M), elfwrap(1),
244 modload(1M), system(4), _fini(9E), _info(9E), _init(9E)
245
246
247 Writing Device Drivers
248
250 A system(4)forceload must be established for modules targeted by
251 ddi_modopen() by code involved in the mount of root on "bootdev" during
252 machine boot(1M).
253
254
255
256SunOS 5.11 17 March 2008 ddi_modopen(9F)