Kernel Functions for Drivers ddimodopen(9F)
NAME
ddimodopen, ddimodsym, ddimodclose - dynamically-loaded
kernel module functions
SYNOPSIS
#include
ddimodhandlet ddimodopen(const char*modname, int mode,
int *errnop);
void *ddimodsym(ddimodhandlet handle, const char *symname,
int *errnop);
int ddimodclose(ddimodhandlet handle);
INTERFACE LEVEL
Solaris DI specific (Solaris DI).
PARAMETERS
modname The name of the dynamically-loaded kernel module
(file) to be opened. The modname string is of the
form:
"[namespace/[dirspace/]modulename"
Each "namespace/" directory along the standard
kernel moddir/module-path path (system(4)) is
searched to locate the module. If "namespace/" is
not specified, "misc/" is assumed. If "dirspace"
is specified, then "namespace/" must be expli-
citly provided.
mode Currently, KRTLDMODEFIRST.
errnop Pointer to errno returned on error, if NUL then
no additional error information is available.
handle Opaque handle returned from ddimodopen(),
invalidated by ddimodclose().
symname Symbol's name as a character string.
SunOS 5.11 Last change: 17 March 2008 1
Kernel Functions for Drivers ddimodopen(9F)
DESCRIPTION
The function prototypes for ddimodopen(), ddimodsym(), and
ddimodclose() are modeled after the userland libdl(3LIB),
dlopen(3C), dlsym(3C) , anddlclose(3C) interfaces, however
not all userland features are available and the kernel sym-
bol resolution is different. The dlerror(3C) interface is
not appropriate for the kernel environment, so the new
errnop return argument was added for ddimodopen() and
ddimodsym().
The ddimodopen()function makes a dynamically-loaded kernel
module named by "modname" available to a running kernel.
ddimodopen() returns a handle that the caller can use on
subsequent calls to ddimodsym() and ddimodclose(). The
value of this handle should not be interpreted in any way by
the caller.
The ddimodopen() interface works best as a dynamic
component/object plug-in mechanism when targeting kernel
"misc" modules that contain a single "struct modlmisc"
module linkage, however non-"misc" modules and modules with
multiple linkage structures can also be targeted.
There are two different symbol resolution search orders
associated with the ddimodopen() function: one search order
to resolve symbols during the load of the targeted module,
another search order o resolve ddimodsym() calls against
the handle returned by ddimodopen(). To resolve symbols
during module load, the standard kernel module load search
order is used; to resolve symbols during module "A" load,
the order is as follows:
A -> A's dependson -> unix -> unix's dependson
A single-level, left-to-right search in dependson (or the
"ld -N" alternative) modules occurs. For UNIX on Sparc,
dependson is similar to "genunix misc/platmod
cpu/SUNW,UltraSPARC-I] dtracestubs" for Intel, it is
"genunix dtracestubs". The ddimodsym() search is limited to
the module directly associated with the handle.
The ddimodopen() function increments the reference count on
the named kernel module. Upon the first load of a module,
theinit(9E) initialization code in the module is called;
ddimodopen() does not return until init completes.
SunOS 5.11 Last change: 17 March 2008 2
Kernel Functions for Drivers ddimodopen(9F)
The ddimodsym() function allows a caller to obtain the
address of a symbol that is defined within a module. The
handle argument is a valid ddimodhandlet as returned by
ddimodopen(), the symname argument is the symbol's name as
a character string. The special handle values supported by
ddimodsym(3C) are not supported.
The ddimodclose() function decrements the reference count
of the kernel module associated with the specified handle.
After the ddimodclose() function is called, all
ddimodsym() resolutions obtained (either directly or
indirectly) using the now closed handle are invalid; further
use of these resolutions can cause undefined behavior (that
is, may lead to a panic). When the last ddimodclose() of a
module occurs, and there are no further references to the
module, the module fini(9E)entry point may be called. If
fini returns success then the module may be unloaded.
RETURN VALUES
The ddimodopen() function returns a handle to the
dynamically-loaded kernel module. The ddimodopen() function
returns NUL if the module cannot be found, the object can-
not be relocated, or an error occurs during the process of
resolving and relocating its symbolic references.
The ddimodsym() function returns NUL if the symname symbol
cannot be found directly within the module associated with
the handle.
If the handle was not referenced, ddimodclose() returns 0.
If the handle is invalid, ddimodclose() may return a non-
zero value.
When either ddimodopen() or ddimodsym() return NUL, addi-
tional errno information related to the failure is returned
in *errnop if it is not NUL.
CONTEXT
ddimodopen() can be called from user context only.
EXAMPLES
Example 1 Coding a Dynamically Loaded Kernel Module
The following example shows code to dynamically load and
call a "test" interface in a module called "dltest". The
"test" interface then adds one to its integer argument.
SunOS 5.11 Last change: 17 March 2008 3
Kernel Functions for Drivers ddimodopen(9F)
ddimodhandlet modh;
int (*test)(int);
int i = 0;
int errno;
---%<---
/* dynamically load "dltest" kernel 'misc' module */
modh = ddimodopen("dltest", KRTLDMODEFIRST, &errno);
if (modh == NUL)
goto fail; /* failed to open dltest module */
test = (int (*)())ddimodsym(modh, "test", &errno);
if (test == NUL) {
(void) ddimodclose(modh);
goto fail; /* failed to find "test" interface */
}
/* invoke test interface and verify result */
i = (*test)(0);
ASERT(i == 1);
(void) ddimodclose(modh);
---%<---
The implementation of the "dltest" "misc" module is as fol-
lows:
#include
static dltestadd = 0;
/* define the module linkage */
static struct modlmisc modlmisc = {&modmiscops, "dltest"};
static struct modlinkage modlinkage = {
MODREV1, (void *)&modmisc, NUL
};
int
init(void)
{
int i;
dltestadd = 1; /* initialization */
if ((i = modinstall(&modlinkage)) != 0)
dltestadd = -1; /* un-initialization */
return (i);
}
int
fini()
{
int i;
SunOS 5.11 Last change: 17 March 2008 4
Kernel Functions for Drivers ddimodopen(9F)
if ((i = modremove(&modlinkage)) == 0)
dltestadd = -1; /* un-initialization */
return (i);
}
int
info(struct modinfo *modinfop)
{
return (modinfo(&modlinkage, modinfop));
}
/* "test" interface */
int
test(int i)
{
return (i ] dltestadd);
}
Example 2 Dynamically Accessing a Kernel Module within a
Drive
The following example shows driver code to dynamically load
into the kernel a module constructed via the elfwrap(1)
utility and containing firmware intended for download to a
device. The "start" and "end" pointers provide the addresses
of the beginning of the data and first byte beyond the data.
ddimodhandlet modp;
char *datastartp, *dataendp;
sizet nbytes;
int rv;
modp = ddimodopen("firmware-rev1.2a", KRTLDMODEFIRST, &rv);
datastartp = (char *)ddimodsym(modp, "fw-rev1.2astart", &rv);
dataendp = (char *)ddimodsym(modp, "fw-rev1.2aend", &rv);
nbytes = dataendp - datastartp;
rv = ddimodclose(modp);
SEE ALSO
dlclose(3C), dlopen(3C), dlsym(3C), libdl(3LIB), boot(1M),
elfwrap(1), modload(1M), system(4), fini(9E), info(9E),
init(9E)
Writing Device Drivers
WARNINGS
A system(4)forceload must be established for modules tar-
geted by ddimodopen() by code involved in the mount of root
SunOS 5.11 Last change: 17 March 2008 5
Kernel Functions for Drivers ddimodopen(9F)
on "bootdev" during machine boot(1M).
SunOS 5.11 Last change: 17 March 2008 6
|