1
/* $XFree86: xc/programs/Xserver/hw/xfree86/loader/loadmod.c,v 1.73 2003/11/03 05:11:51 tsi Exp $ */
5
* Copyright 1995-1998 by Metro Link, Inc.
7
* Permission to use, copy, modify, distribute, and sell this software and its
8
* documentation for any purpose is hereby granted without fee, provided that
9
* the above copyright notice appear in all copies and that both that
10
* copyright notice and this permission notice appear in supporting
11
* documentation, and that the name of Metro Link, Inc. not be used in
12
* advertising or publicity pertaining to distribution of the software without
13
* specific, written prior permission. Metro Link, Inc. makes no
14
* representations about the suitability of this software for any purpose.
15
* It is provided "as is" without express or implied warranty.
17
* METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19
* EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23
* PERFORMANCE OF THIS SOFTWARE.
26
* Copyright (c) 1997-2002 by The XFree86 Project, Inc.
28
* Permission is hereby granted, free of charge, to any person obtaining a
29
* copy of this software and associated documentation files (the "Software"),
30
* to deal in the Software without restriction, including without limitation
31
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
32
* and/or sell copies of the Software, and to permit persons to whom the
33
* Software is furnished to do so, subject to the following conditions:
35
* The above copyright notice and this permission notice shall be included in
36
* all copies or substantial portions of the Software.
38
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
42
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
43
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
44
* OTHER DEALINGS IN THE SOFTWARE.
46
* Except as contained in this notice, the name of the copyright holder(s)
47
* and author(s) shall not be used in advertising or otherwise to promote
48
* the sale, use or other dealings in this Software without prior written
49
* authorization from the copyright holder(s) and author(s).
52
#ifdef HAVE_XORG_CONFIG_H
53
#include <xorg-config.h>
57
/* For stat() and related stuff */
58
#define NO_OSLIB_PROTOTYPES
59
#include "xf86_OSlib.h"
60
#define LOADERDECLARATIONS
61
#include "loaderProcs.h"
66
#include "xf86Xinput.h"
69
#include "xf86Optrec.h"
71
#include <sys/types.h>
76
extern int check_unresolved_sema;
78
typedef struct _pattern {
81
} PatternRec, *PatternPtr;
83
/* Prototypes for static functions */
84
static char *FindModule(const char *, const char *, const char **,
86
static Bool CheckVersion(const char *, XF86ModuleVersionInfo *,
87
const XF86ModReqInfo *);
88
static void UnloadModuleOrDriver(ModuleDescPtr mod);
89
static char *LoaderGetCanonicalName(const char *, PatternPtr);
90
static void RemoveChild(ModuleDescPtr);
92
ModuleVersions LoaderVersionInfo = {
97
ABI_EXTENSION_VERSION,
105
/* Need to call LRS here because the frame buffers get loaded last,
106
* and the drivers depend on them. */
108
LoaderResolveSymbols();
113
FreeStringList(char **paths)
120
for (p = paths; *p; p++)
126
static char **defaultPathList = NULL;
129
* Convert a comma-separated path into a NULL-terminated array of path
130
* elements, rejecting any that are not full absolute paths, and appending
131
* a '/' when it isn't already present.
134
InitPathList(const char *path)
136
char *fullpath = NULL;
138
char **list = NULL, **save = NULL;
144
return defaultPathList;
146
fullpath = xstrdup(path);
149
elem = strtok(fullpath, ",");
151
/* Only allow fully specified paths */
155
if (*elem == '/' || (strlen(elem) > 2 && isalpha(elem[0]) &&
156
elem[1] == ':' && elem[2] == '/'))
160
addslash = (elem[len - 1] != '/');
164
list = xrealloc(list, (n + 2) * sizeof(char *));
168
FreeStringList(save);
173
list[n] = xalloc(len + 1);
175
FreeStringList(list);
179
strcpy(list[n], elem);
181
list[n][len - 1] = '/';
186
elem = strtok(NULL, ",");
194
FreePathList(char **pathlist)
196
if (pathlist && pathlist != defaultPathList)
197
FreeStringList(pathlist);
201
LoaderSetPath(const char *path)
206
defaultPathList = InitPathList(path);
209
/* Standard set of module subdirectories to search, in order of preference */
210
static const char *stdSubdirs[] = {
222
* Standard set of module name patterns to check, in order of preference
223
* These are regular expressions (suitable for use with POSIX regex(3)).
225
static PatternRec stdPatterns[] = {
237
InitPatterns(const char **patternlist)
241
PatternPtr patterns = NULL;
243
static int firstTime = 1;
247
/* precompile stdPatterns */
249
for (p = stdPatterns; p->pattern; p++)
250
if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) {
251
regerror(e, &p->rex, errmsg, sizeof(errmsg));
252
FatalError("InitPatterns: regcomp error for `%s': %s\n",
258
for (i = 0, s = patternlist; *s; i++, s++)
259
if (*s == DEFAULT_LIST)
260
i += sizeof(stdPatterns) / sizeof(stdPatterns[0]) - 1 - 1;
261
patterns = xalloc((i + 1) * sizeof(PatternRec));
265
for (i = 0, s = patternlist; *s; i++, s++)
266
if (*s != DEFAULT_LIST) {
269
if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) {
270
regerror(e, &p->rex, errmsg, sizeof(errmsg));
271
ErrorF("InitPatterns: regcomp error for `%s': %s\n",
276
for (p = stdPatterns; p->pattern; p++, i++)
278
if (p != stdPatterns)
281
patterns[i].pattern = NULL;
283
patterns = stdPatterns;
288
FreePatterns(PatternPtr patterns)
290
if (patterns && patterns != stdPatterns)
295
InitSubdirs(const char **subdirlist)
298
const char **tmp_subdirlist = NULL;
299
char **subdirs = NULL;
300
const char **s, **stmp = NULL;
306
if (subdirlist == NULL) {
307
subdirlist = tmp_subdirlist = xalloc(2 * sizeof(char *));
308
if (subdirlist == NULL)
310
subdirlist[0] = DEFAULT_LIST;
311
subdirlist[1] = NULL;
314
LoaderGetOS(&osname, NULL, NULL, NULL);
315
oslen = strlen(osname);
318
/* Count number of entries and check for invalid paths */
319
for (i = 0, s = subdirlist; *s; i++, s++) {
320
if (*s == DEFAULT_LIST) {
321
i += sizeof(stdSubdirs) / sizeof(stdSubdirs[0]) - 1 - 1;
324
* Path validity check. Don't allow absolute paths, or
325
* paths containing "..". To catch absolute paths on
326
* platforms that use driver letters, don't allow the ':'
327
* character to appear at all.
329
if (**s == '/' || **s == '\\' || strchr(*s, ':') ||
331
xf86Msg(X_ERROR, "InitSubdirs: Bad subdir: \"%s\"\n", *s);
333
xfree(tmp_subdirlist);
338
subdirs = xalloc((i * 2 + 1) * sizeof(char *));
341
xfree(tmp_subdirlist);
348
if (*s == DEFAULT_LIST) {
349
/* Divert to the default list */
355
if (**s && (*s)[len - 1] != '/') {
361
if (!(subdirs[i] = xalloc(len))) {
366
xfree(tmp_subdirlist);
369
/* tack on the OS name */
370
sprintf(subdirs[i], "%s%s%s/", *s, slash, osname);
373
subdirs[i] = xstrdup(*s);
376
if (indefault && !s) {
377
/* revert back to the main list */
385
xfree(tmp_subdirlist);
386
return (const char **)subdirs;
390
FreeSubdirs(const char **subdirs)
395
for (s = subdirs; *s; s++)
402
FindModule(const char *module, const char *dir, const char **subdirlist,
405
char buf[PATH_MAX + 1], tmpBuf[PATH_MAX + 1];
406
char *dirpath = NULL;
408
struct stat stat_buf;
411
const char **subdirs = NULL;
414
const char suffix[3][3] = { "so", "a", "o" };
416
const char suffix[3][3] = { "a", "o", "so" };
419
subdirs = InitSubdirs(subdirlist);
424
dirpath = (char *)dir;
426
dirpath = xalloc(strlen(dir) + 10);
427
strcpy(dirpath, (char *)__XOS2RedirRoot(dir));
429
if (strlen(dirpath) > PATH_MAX)
431
/*xf86Msg(X_INFO,"OS2DIAG: FindModule: dirpath=%s\n",dirpath); */
433
for (s = subdirs; *s; s++) {
434
if ((dirlen = strlen(dirpath) + strlen(*s)) > PATH_MAX)
436
strcpy(buf, dirpath);
438
/*xf86Msg(X_INFO,"OS2DIAG: FindModule: buf=%s\n",buf); */
439
if ((stat(buf, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) {
442
if (buf[dirlen - 1] != '/') {
447
for (i = 0; i < 3 && !name; i++) {
448
snprintf(tmpBuf, PATH_MAX, "%slib%s.%s", buf, module,
450
if (stat(tmpBuf, &stat_buf) == 0) {
454
snprintf(tmpBuf, PATH_MAX, "%s%s_drv.%s", buf, module,
456
if (stat(tmpBuf, &stat_buf) == 0) {
460
snprintf(tmpBuf, PATH_MAX, "%s%s.%s", buf, module,
462
if (stat(tmpBuf, &stat_buf) == 0) {
471
FreeSubdirs(subdirs);
476
return xstrdup(name);
482
LoaderListDirs(const char **subdirlist, const char **patternlist)
484
char buf[PATH_MAX + 1];
487
const char **subdirs;
494
struct stat stat_buf;
497
char **listing = NULL;
501
if (!(pathlist = InitPathList(NULL)))
503
if (!(subdirs = InitSubdirs(subdirlist))) {
504
FreePathList(pathlist);
507
if (!(patterns = InitPatterns(patternlist))) {
508
FreePathList(pathlist);
509
FreeSubdirs(subdirs);
513
for (elem = pathlist; *elem; elem++) {
514
for (s = subdirs; *s; s++) {
515
if ((dirlen = strlen(*elem) + strlen(*s)) > PATH_MAX)
520
if (stat(buf, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode) &&
521
(d = opendir(buf))) {
522
if (buf[dirlen - 1] != '/') {
526
while ((dp = readdir(d))) {
527
if (dirlen + strlen(dp->d_name) > PATH_MAX)
529
strcpy(fp, dp->d_name);
530
if (!(stat(buf, &stat_buf) == 0 &&
531
S_ISREG(stat_buf.st_mode)))
533
for (p = patterns; p->pattern; p++) {
534
if (regexec(&p->rex, dp->d_name, 2, match, 0) == 0 &&
535
match[1].rm_so != -1) {
536
len = match[1].rm_eo - match[1].rm_so;
538
listing = xrealloc(listing,
539
(n + 2) * sizeof(char *));
543
FreeStringList(save);
545
FreePathList(pathlist);
546
FreeSubdirs(subdirs);
547
FreePatterns(patterns);
550
listing[n] = xalloc(len + 1);
552
FreeStringList(listing);
553
FreePathList(pathlist);
554
FreeSubdirs(subdirs);
555
FreePatterns(patterns);
558
strncpy(listing[n], dp->d_name + match[1].rm_so,
560
listing[n][len] = '\0';
576
LoaderFreeDirList(char **list)
578
FreeStringList(list);
582
CheckVersion(const char *module, XF86ModuleVersionInfo * data,
583
const XF86ModReqInfo * req)
587
long ver = data->xf86version;
590
xf86Msg(X_INFO, "Module %s: vendor=\"%s\"\n",
591
data->modname ? data->modname : "UNKNOWN!",
592
data->vendor ? data->vendor : "UNKNOWN!");
594
/* Check for the different scheme used in XFree86 4.0.x releases:
595
* ((((((((major << 7) | minor) << 7) | subminor) << 5) | beta) << 5) | alpha)
596
* Since it wasn't used in 4.1.0 or later, limit to versions in the 4.0.x
597
* range, which limits the overlap with the new version scheme to conflicts
598
* with 6.71.8.764 through 6.72.39.934.
600
if ((ver > (4 << 24)) && (ver < ( (4 << 24) + (1 << 17)))) {
601
/* 4.0.x and earlier */
602
verstr[1] = verstr[3] = 0;
603
verstr[2] = (ver & 0x1f) ? (ver & 0x1f) + 'a' - 1 : 0;
605
verstr[0] = (ver & 0x1f) ? (ver & 0x1f) + 'A' - 1 : 0;
607
vercode[2] = ver & 0x7f;
609
vercode[1] = ver & 0x7f;
612
xf86ErrorF("\tcompiled for %d.%d", vercode[0], vercode[1]);
614
xf86ErrorF(".%d", vercode[2]);
615
xf86ErrorF("%s%s, module version = %d.%d.%d\n", verstr, verstr + 2,
616
data->majorversion, data->minorversion, data->patchlevel);
618
vercode[0] = ver / 10000000;
619
vercode[1] = (ver / 100000) % 100;
620
vercode[2] = (ver / 1000) % 100;
621
vercode[3] = ver % 1000;
622
xf86ErrorF("\tcompiled for %d.%d.%d", vercode[0], vercode[1],
625
xf86ErrorF(".%d", vercode[3]);
626
xf86ErrorF(", module version = %d.%d.%d\n", data->majorversion,
627
data->minorversion, data->patchlevel);
630
if (data->moduleclass)
631
xf86ErrorFVerb(2, "\tModule class: %s\n", data->moduleclass);
634
if (data->abiclass) {
638
if (!strcmp(data->abiclass, ABI_CLASS_ANSIC))
639
ver = LoaderVersionInfo.ansicVersion;
640
else if (!strcmp(data->abiclass, ABI_CLASS_VIDEODRV))
641
ver = LoaderVersionInfo.videodrvVersion;
642
else if (!strcmp(data->abiclass, ABI_CLASS_XINPUT))
643
ver = LoaderVersionInfo.xinputVersion;
644
else if (!strcmp(data->abiclass, ABI_CLASS_EXTENSION))
645
ver = LoaderVersionInfo.extensionVersion;
646
else if (!strcmp(data->abiclass, ABI_CLASS_FONT))
647
ver = LoaderVersionInfo.fontVersion;
649
abimaj = GET_ABI_MAJOR(data->abiversion);
650
abimin = GET_ABI_MINOR(data->abiversion);
651
xf86ErrorFVerb(2, "\tABI class: %s, version %d.%d\n",
652
data->abiclass, abimaj, abimin);
654
vermaj = GET_ABI_MAJOR(ver);
655
vermin = GET_ABI_MINOR(ver);
656
if (abimaj != vermaj) {
657
if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)
661
xf86MsgVerb(errtype, 0,
662
"module ABI major version (%d) doesn't"
663
" match the server's version (%d)\n",
665
if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL))
667
} else if (abimin > vermin) {
668
if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)
672
xf86MsgVerb(errtype, 0,
673
"module ABI minor version (%d) is "
674
"newer than the server's version "
675
"(%d)\n", abimin, vermin);
676
if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL))
682
/* Check against requirements that the caller has specified */
684
if (req->majorversion != MAJOR_UNSPEC) {
685
if (data->majorversion != req->majorversion) {
686
xf86MsgVerb(X_WARNING, 2, "module major version (%d) "
687
"doesn't match required major version (%d)\n",
688
data->majorversion, req->majorversion);
690
} else if (req->minorversion != MINOR_UNSPEC) {
691
if (data->minorversion < req->minorversion) {
692
xf86MsgVerb(X_WARNING, 2, "module minor version (%d) "
693
"is less than the required minor version (%d)\n",
694
data->minorversion, req->minorversion);
696
} else if (data->minorversion == req->minorversion &&
697
req->patchlevel != PATCH_UNSPEC) {
698
if (data->patchlevel < req->patchlevel) {
699
xf86MsgVerb(X_WARNING, 2, "module patch level (%d) "
700
"is less than the required patch level (%d)\n",
701
data->patchlevel, req->patchlevel);
707
if (req->moduleclass) {
708
if (!data->moduleclass ||
709
strcmp(req->moduleclass, data->moduleclass)) {
710
xf86MsgVerb(X_WARNING, 2, "Module class (%s) doesn't match "
711
"the required class (%s)\n",
712
data->moduleclass ? data->moduleclass : "<NONE>",
716
} else if (req->abiclass != ABI_CLASS_NONE) {
717
if (!data->abiclass || strcmp(req->abiclass, data->moduleclass)) {
718
xf86MsgVerb(X_WARNING, 2, "ABI class (%s) doesn't match the "
719
"required ABI class (%s)\n",
720
data->abiclass ? data->abiclass : "<NONE>",
725
if ((req->abiclass != ABI_CLASS_NONE) &&
726
req->abiversion != ABI_VERS_UNSPEC) {
727
int reqmaj, reqmin, maj, min;
729
reqmaj = GET_ABI_MAJOR(req->abiversion);
730
reqmin = GET_ABI_MINOR(req->abiversion);
731
maj = GET_ABI_MAJOR(data->abiversion);
732
min = GET_ABI_MINOR(data->abiversion);
734
xf86MsgVerb(X_WARNING, 2, "ABI major version (%d) doesn't "
735
"match the required ABI major version (%d)\n",
739
/* XXX Maybe this should be the other way around? */
741
xf86MsgVerb(X_WARNING, 2, "module ABI minor version (%d) "
742
"is new than that available (%d)\n", min, reqmin);
748
if (data->checksum) {
749
/* verify the checksum field */
752
ErrorF("\t*** Checksum field is 0 - this module is untrusted!\n");
759
LoadSubModule(ModuleDescPtr parent, const char *module,
760
const char **subdirlist, const char **patternlist,
761
pointer options, const XF86ModReqInfo * modreq,
762
int *errmaj, int *errmin)
764
ModuleDescPtr submod;
766
xf86MsgVerb(X_INFO, 3, "Loading sub module \"%s\"\n", module);
768
/* Absolute module paths are not allowed here */
770
if (module[0] == '/')
772
if (isalpha(module[0]) && module[1] == ':' && module[2] == '/')
776
"LoadSubModule: Absolute module path not permitted: \"%s\"\n",
779
*errmaj = LDR_BADUSAGE;
785
submod = LoadModule(module, NULL, subdirlist, patternlist, options,
786
modreq, errmaj, errmin);
788
parent->child = AddSibling(parent->child, submod);
789
submod->parent = parent;
795
DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
802
ret = NewModuleDesc(mod->name);
806
if (LoaderHandleOpen(mod->handle) == -1)
809
ret->filename = xstrdup(mod->filename);
810
ret->identifier = mod->identifier;
811
ret->client_id = mod->client_id;
812
ret->in_use = mod->in_use;
813
ret->handle = mod->handle;
814
ret->SetupProc = mod->SetupProc;
815
ret->TearDownProc = mod->TearDownProc;
816
ret->TearDownData = NULL;
817
ret->path = mod->path;
818
ret->child = DuplicateModule(mod->child, ret);
819
ret->sib = DuplicateModule(mod->sib, parent);
820
ret->parent = parent;
821
ret->VersionInfo = mod->VersionInfo;
827
* LoadModule: load a module
829
* module The module name. Normally this is not a filename but the
830
* module's "canonical name. A full pathname is, however,
832
* path A comma separated list of module directories.
833
* subdirlist A NULL terminated list of subdirectories to search. When
834
* NULL, the default "stdSubdirs" list is used. The default
835
* list is also substituted for entries with value DEFAULT_LIST.
836
* patternlist A NULL terminated list of regular expressions used to find
837
* module filenames. Each regex should contain exactly one
838
* subexpression that corresponds to the canonical module name.
839
* When NULL, the default "stdPatterns" list is used. The
840
* default list is also substituted for entries with value
842
* options A NULL terminated list of Options that are passed to the
843
* module's SetupProc function.
844
* modreq An optional XF86ModReqInfo* containing
845
* version/ABI/vendor-ABI requirements to check for when
846
* loading the module. The following fields of the
847
* XF86ModReqInfo struct are checked:
848
* majorversion - must match the module's majorversion exactly
849
* minorversion - the module's minorversion must be >= this
850
* patchlevel - the module's minorversion.patchlevel must be
851
* >= this. Patchlevel is ignored when
852
* minorversion is not set.
853
* abiclass - (string) must match the module's abiclass
854
* abiversion - must be consistent with the module's
855
* abiversion (major equal, minor no older)
856
* moduleclass - string must match the module's moduleclass
858
* "don't care" values are ~0 for numbers, and NULL for strings
859
* errmaj Major error return.
860
* errmin Minor error return.
865
LoadModule(const char *module, const char *path, const char **subdirlist,
866
const char **patternlist, pointer options,
867
const XF86ModReqInfo * modreq, int *errmaj, int *errmin)
869
XF86ModuleData *initdata = NULL;
870
char **pathlist = NULL;
873
char **path_elem = NULL;
875
ModuleDescPtr ret = NULL;
877
PatternPtr patterns = NULL;
878
int noncanonical = 0;
881
/*xf86Msg(X_INFO,"OS2DIAG: LoadModule: %s\n",module); */
882
xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module);
884
patterns = InitPatterns(patternlist);
885
name = LoaderGetCanonicalName(module, patterns);
886
noncanonical = (name && strcmp(module, name) != 0);
888
xf86ErrorFVerb(3, " (%s)\n", name);
889
xf86MsgVerb(X_WARNING, 1,
890
"LoadModule: given non-canonical module name \"%s\"\n",
894
xf86ErrorFVerb(3, "\n");
899
*errmaj = LDR_BADUSAGE;
902
goto LoadModule_fail;
904
ret = NewModuleDesc(name);
910
goto LoadModule_fail;
913
pathlist = InitPathList(path);
915
/* This could be a malloc failure too */
917
*errmaj = LDR_BADUSAGE;
920
goto LoadModule_fail;
924
* if the module name is not a full pathname, we need to
925
* check the elements in the path
928
if (module[0] == '/')
929
found = xstrdup(module);
931
/* accept a drive name here */
932
if (isalpha(module[0]) && module[1] == ':' && module[2] == '/')
933
found = xstrdup(module);
935
path_elem = pathlist;
936
while (!found && *path_elem != NULL) {
937
found = FindModule(m, *path_elem, subdirlist, patterns);
940
* When the module name isn't the canonical name, search for the
941
* former if no match was found for the latter.
943
if (!*path_elem && m == name) {
944
path_elem = pathlist;
950
* did we find the module?
953
xf86Msg(X_WARNING, "Warning, couldn't open module %s\n", module);
958
goto LoadModule_fail;
960
ret->handle = LoaderOpen(found, name, 0, errmaj, errmin, &wasLoaded);
962
goto LoadModule_fail;
964
ret->filename = xstrdup(found);
966
/* drop any explicit suffix from the module name */
967
p = strchr(name, '.');
972
* now check if the special data object <modulename>ModuleData is
975
p = xalloc(strlen(name) + strlen("ModuleData") + 1);
981
goto LoadModule_fail;
984
strcat(p, "ModuleData");
985
initdata = LoaderSymbol(p);
987
ModuleSetupProc setup;
988
ModuleTearDownProc teardown;
989
XF86ModuleVersionInfo *vers;
991
vers = initdata->vers;
992
setup = initdata->setup;
993
teardown = initdata->teardown;
997
if (!CheckVersion(module, vers, modreq)) {
999
*errmaj = LDR_MISMATCH;
1002
goto LoadModule_fail;
1006
"LoadModule: Module %s does not supply"
1007
" version information\n", module);
1009
*errmaj = LDR_INVALID;
1012
goto LoadModule_fail;
1016
ret->SetupProc = setup;
1018
ret->TearDownProc = teardown;
1020
ret->VersionInfo = vers;
1022
/* No initdata is OK for external modules */
1023
if (options == EXTERN_MODULE)
1024
goto LoadModule_exit;
1026
/* no initdata, fail the load */
1027
xf86Msg(X_ERROR, "LoadModule: Module %s does not have a %s "
1028
"data object.\n", module, p);
1030
*errmaj = LDR_INVALID;
1033
goto LoadModule_fail;
1035
if (ret->SetupProc) {
1036
ret->TearDownData = ret->SetupProc(ret, options, errmaj, errmin);
1037
if (!ret->TearDownData) {
1038
goto LoadModule_fail;
1040
} else if (options) {
1041
xf86Msg(X_WARNING, "Module Options present, but no SetupProc "
1042
"available for %s\n", module);
1044
goto LoadModule_exit;
1051
FreePathList(pathlist);
1052
FreePatterns(patterns);
1058
* If you need to do something to keep the
1059
* instruction cache in sync with the main
1060
* memory before jumping to that code, you may
1064
istream_mem_barrier();
1070
LoadDriver(const char *module, const char *path, int handle, pointer options,
1071
int *errmaj, int *errmin)
1073
return LoadModule(module, path, NULL, NULL, options, NULL, errmaj,
1078
UnloadModule(ModuleDescPtr mod)
1080
UnloadModuleOrDriver(mod);
1084
UnloadDriver(ModuleDescPtr mod)
1086
UnloadModuleOrDriver(mod);
1090
UnloadModuleOrDriver(ModuleDescPtr mod)
1092
if (mod == NULL || mod->name == NULL)
1095
xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
1097
if ((mod->TearDownProc) && (mod->TearDownData))
1098
mod->TearDownProc(mod->TearDownData);
1099
LoaderUnload(mod->handle);
1102
UnloadModuleOrDriver(mod->child);
1104
UnloadModuleOrDriver(mod->sib);
1105
TestFree(mod->name);
1106
TestFree(mod->filename);
1109
istream_mem_barrier();
1114
UnloadSubModule(ModuleDescPtr mod)
1116
if (mod == NULL || mod->name == NULL)
1119
xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name);
1121
if ((mod->TearDownProc) && (mod->TearDownData))
1122
mod->TearDownProc(mod->TearDownData);
1123
LoaderUnload(mod->handle);
1128
UnloadModuleOrDriver(mod->child);
1130
TestFree(mod->name);
1131
TestFree(mod->filename);
1136
FreeModuleDesc(ModuleDescPtr head)
1138
ModuleDescPtr sibs, prev;
1141
* only free it if it's not marked as in use. In use means that it may
1142
* be unloaded someday, and UnloadModule or UnloadDriver will free it
1147
FreeModuleDesc(head->child);
1152
TestFree(prev->name);
1158
NewModuleDesc(const char *name)
1160
ModuleDescPtr mdp = xalloc(sizeof(ModuleDesc));
1166
mdp->demand_next = NULL;
1167
mdp->name = xstrdup(name);
1168
mdp->filename = NULL;
1169
mdp->identifier = NULL;
1173
mdp->SetupProc = NULL;
1174
mdp->TearDownProc = NULL;
1175
mdp->TearDownData = NULL;
1182
AddSibling(ModuleDescPtr head, ModuleDescPtr new)
1190
RemoveChild(ModuleDescPtr child)
1193
ModuleDescPtr prevsib;
1194
ModuleDescPtr parent;
1199
parent = child->parent;
1200
if (parent->child == child) {
1201
parent->child = child->sib;
1205
prevsib = parent->child;
1207
while (mdp && mdp != child) {
1212
prevsib->sib = child->sib;
1217
LoaderErrorMsg(const char *name, const char *modname, int errmaj, int errmin)
1220
MessageType type = X_ERROR;
1227
msg = "out of memory";
1230
msg = "module does not exist";
1233
msg = "a required submodule could not be loaded";
1236
msg = "too many modules";
1239
msg = "open failed";
1242
msg = "unknown module type";
1245
msg = "loader failed";
1248
msg = "already loaded";
1251
case LDR_NOPORTOPEN:
1252
msg = "port open failed";
1254
case LDR_NOHARDWARE:
1255
msg = "no hardware found";
1258
msg = "module requirement mismatch";
1261
msg = "invalid argument(s) to LoadModule()";
1264
msg = "invalid module";
1267
msg = "module doesn't support this OS";
1269
case LDR_MODSPECIFIC:
1270
msg = "module-specific error";
1273
msg = "uknown error";
1276
xf86Msg(type, "%s: Failed to load module \"%s\" (%s, %d)\n",
1277
name, modname, msg, errmin);
1279
xf86Msg(type, "Failed to load module \"%s\" (%s, %d)\n",
1280
modname, msg, errmin);
1283
/* Given a module path or file name, return the module's canonical name */
1285
LoaderGetCanonicalName(const char *modname, PatternPtr patterns)
1291
regmatch_t match[2];
1293
/* Strip off any leading path */
1294
s = strrchr(modname, '/');
1300
/* Find the first regex that is matched */
1301
for (p = patterns; p->pattern; p++)
1302
if (regexec(&p->rex, s, 2, match, 0) == 0 && match[1].rm_so != -1) {
1303
len = match[1].rm_eo - match[1].rm_so;
1304
str = xalloc(len + 1);
1307
strncpy(str, s + match[1].rm_so, len);
1312
/* If there is no match, return the whole name minus the leading path */
1317
* Return the module version information.
1320
LoaderGetModuleVersion(ModuleDescPtr mod)
1322
if (!mod || !mod->VersionInfo)
1325
return MODULE_VERSION_NUMERIC(mod->VersionInfo->majorversion,
1326
mod->VersionInfo->minorversion,
1327
mod->VersionInfo->patchlevel);