1ddi_modopen(9F)          Kernel Functions for Drivers          ddi_modopen(9F)
2
3
4

NAME

6       ddi_modopen,  ddi_modsym, ddi_modclose - dynamically-loaded kernel mod‐
7       ule functions
8

SYNOPSIS

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

INTERFACE LEVEL

24       Solaris DDI specific (Solaris DDI).
25

PARAMETERS

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

DESCRIPTION

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

RETURN VALUES

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

CONTEXT

140       ddi_modopen() can be called from user context only.
141

EXAMPLES

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

SEE ALSO

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

WARNINGS

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)
Impressum