mirror of
https://github.com/X11Libre/xserver.git
synced 2026-01-26 05:57:53 +00:00
xfree86: make search paths configurable for certain modules
It is patch 1/2 of a series that provides a convenient way to specify module search paths on a per-driver basis. This patch allows to set ModulePath for certain modules, in particular, GPU drivers. Signed-off-by: Oleh Nykyforchyn <oleh.nyk@gmail.com>
This commit is contained in:
parent
d66dea68af
commit
9f25f5d3f1
16
config/10-nvidia.conf.in
Normal file
16
config/10-nvidia.conf.in
Normal file
@ -0,0 +1,16 @@
|
||||
# This xorg.conf.d configuration snippet configures the X server to
|
||||
# automatically load the nvidia X driver and nvidia GLX libraries
|
||||
# when it detects a device driven by nvidia-drm.ko kernel module.
|
||||
# Please note that this works on Linux kernels version 6.12 or higher
|
||||
# with CONFIG_DRM enabled, and only if the nvidia-drm.ko kernel module
|
||||
# is loaded before the X server is started.
|
||||
|
||||
Section "OutputClass"
|
||||
Identifier "NVidia"
|
||||
MatchDriver "nvidia-drm"
|
||||
Driver "nvidia"
|
||||
Module "glx"
|
||||
Module "glxserver_nvidia"
|
||||
Option "AllowEmptyInitialConfiguration"
|
||||
ModulePath "@libdir@/nvidia/xorg"
|
||||
EndSection
|
||||
@ -26,6 +26,14 @@ endif
|
||||
if build_xorg
|
||||
install_data('10-quirks.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'X11/xorg.conf.d'))
|
||||
nvidia_conf = configuration_data()
|
||||
nvidia_conf.set('libdir', join_paths(get_option('prefix'),get_option('libdir')))
|
||||
configure_file(
|
||||
input: '10-nvidia.conf.in',
|
||||
output: '10-nvidia.conf',
|
||||
configuration: nvidia_conf,
|
||||
install_dir: join_paths(get_option('datadir'), 'X11/xorg.conf.d'),
|
||||
)
|
||||
endif
|
||||
|
||||
libxserver_config = static_library('xserver_config',
|
||||
|
||||
@ -329,7 +329,7 @@ InitOutput(int argc, char **argv)
|
||||
LoaderInit();
|
||||
|
||||
/* Tell the loader the default module search path */
|
||||
LoaderSetPath(xf86ModulePath);
|
||||
LoaderSetPath(NULL, xf86ModulePath);
|
||||
|
||||
if (xf86Info.ignoreABI) {
|
||||
LoaderSetIgnoreAbi();
|
||||
@ -749,6 +749,8 @@ CloseInput(void)
|
||||
{
|
||||
config_fini();
|
||||
mieqFini();
|
||||
/* strictly speaking the below is not related to input, but ... */
|
||||
LoaderClose();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -197,9 +197,11 @@ xf86OutputClassDriverList(int index, XF86MatchedDrivers *md)
|
||||
|
||||
LogMessageVerb(X_INFO, 1, "Applying OutputClass \"%s\" to %s\n",
|
||||
cl->identifier, path);
|
||||
if (cl->driver != NULL && *(cl->driver)) {
|
||||
LogMessageVerb(X_NONE, 1, "\tloading driver: %s\n", cl->driver);
|
||||
|
||||
xf86AddMatchedDriver(md, cl->driver);
|
||||
} else
|
||||
LogMessageVerb(X_NONE, 1, "\tno driver specified\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,7 +263,8 @@ xf86platformProbe(void)
|
||||
Bool pci = TRUE;
|
||||
XF86ConfOutputClassPtr cl, cl_head = (xf86configptr) ?
|
||||
xf86configptr->conf_outputclass_lst : NULL;
|
||||
char *old_path, *path = NULL;
|
||||
char *driver_path, *path = NULL;
|
||||
char *curr, *next, *copy;
|
||||
|
||||
config_odev_probe(xf86PlatformDeviceProbe);
|
||||
|
||||
@ -284,19 +287,85 @@ xf86platformProbe(void)
|
||||
if (!OutputClassMatches(cl, &xf86_platform_devices[i]))
|
||||
continue;
|
||||
|
||||
if (cl->modulepath && xf86ModPathFrom != X_CMDLINE) {
|
||||
old_path = path;
|
||||
if (xf86ModPathFrom != X_CMDLINE) {
|
||||
if (cl->driver) {
|
||||
if (cl->modulepath) {
|
||||
if (*(cl->modulepath)) {
|
||||
XNFasprintf(&driver_path, "%s,%s", cl->modulepath, xf86ModulePath);
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for driver %s overridden with \"%s\"\n",
|
||||
cl->identifier, cl->driver, driver_path);
|
||||
} else {
|
||||
XNFasprintf(&driver_path, "%s", xf86ModulePath);
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for driver %s reset to standard \"%s\"\n",
|
||||
cl->identifier, cl->driver, driver_path);
|
||||
}
|
||||
} else {
|
||||
driver_path = NULL;
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for driver %s reset to default\n",
|
||||
cl->identifier, cl->driver);
|
||||
}
|
||||
if (*(cl->driver)) LoaderSetPath(cl->driver, driver_path);
|
||||
if (cl->modules) {
|
||||
LogMessageVerb(X_CONFIG, 1, " and for modules \"%s\" as well\n",
|
||||
cl->modules);
|
||||
XNFasprintf(©, "%s", cl->modules);
|
||||
curr = copy;
|
||||
while ((curr = strtok_r(curr, ",", &next))) {
|
||||
if (*curr) LoaderSetPath(curr, driver_path);
|
||||
curr = NULL;
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
free(driver_path);
|
||||
}
|
||||
else if (cl->modules) {
|
||||
if (cl->modulepath) {
|
||||
if (*(cl->modulepath)) {
|
||||
XNFasprintf(&driver_path, "%s,%s", cl->modulepath, xf86ModulePath);
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for modules %s overridden with \"%s\"\n",
|
||||
cl->identifier, cl->modules, driver_path);
|
||||
} else {
|
||||
XNFasprintf(&driver_path, "%s", xf86ModulePath);
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for modules %s reset to standard \"%s\"\n",
|
||||
cl->identifier, cl->modules, driver_path);
|
||||
}
|
||||
} else {
|
||||
driver_path = NULL;
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for modules %s reset to default\n",
|
||||
cl->identifier, cl->modules);
|
||||
}
|
||||
XNFasprintf(©, "%s", cl->modules);
|
||||
curr = copy;
|
||||
while ((curr = strtok_r(curr, ",", &next))) {
|
||||
if (*curr) LoaderSetPath(curr, driver_path);
|
||||
curr = NULL;
|
||||
}
|
||||
free(copy);
|
||||
} else {
|
||||
driver_path = path; /* Reuse for temporary storage */
|
||||
if (*(cl->modulepath)) {
|
||||
XNFasprintf(&path, "%s,%s", cl->modulepath,
|
||||
path ? path : xf86ModulePath);
|
||||
free(old_path);
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath extended to \"%s\"\n",
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" default ModulePath extended to \"%s\"\n",
|
||||
cl->identifier, path);
|
||||
LoaderSetPath(path);
|
||||
} else {
|
||||
XNFasprintf(&path, "%s", xf86ModulePath);
|
||||
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" default ModulePath reset to standard \"%s\"\n",
|
||||
cl->identifier, path);
|
||||
}
|
||||
}
|
||||
/* Otherwise global module search path is left unchanged */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xf86ModPathFrom != X_CMDLINE) {
|
||||
if (path) {
|
||||
LoaderSetPath(NULL, path);
|
||||
free(path);
|
||||
} else
|
||||
LoaderSetPath(NULL, xf86ModulePath);
|
||||
}
|
||||
|
||||
/* First see if there is an OutputClass match marking a device as primary */
|
||||
for (i = 0; i < xf86_num_platform_devices; i++) {
|
||||
|
||||
@ -4779,15 +4779,16 @@ XFree86 common layer.
|
||||
|
||||
<blockquote><para>
|
||||
<programlisting>
|
||||
void LoaderSetPath(const char *path);
|
||||
void LoaderSetPath(const char *driver, const char *path);
|
||||
</programlisting>
|
||||
<blockquote><para>
|
||||
The <function>LoaderSetPath()</function> function initialises a default
|
||||
module search path. This must be called if calls to other functions
|
||||
are to be made without explicitly specifying a module search path.
|
||||
The search path <parameter>path</parameter> must be a string of one or more
|
||||
comma separated absolute paths. Modules are expected to be located
|
||||
below these paths, possibly in subdirectories of these paths.
|
||||
The <function>LoaderSetPath()</function> function initialises a search path
|
||||
for <parameter>driver</parameter> module, if it is non-NULL,
|
||||
or a default module search path otherwise. This must be called if calls
|
||||
to other functions are to be made without explicitly specifying a module
|
||||
search path. The search path <parameter>path</parameter> must be a string
|
||||
of one or more comma separated absolute paths. Modules are expected to be
|
||||
located below these paths, possibly in subdirectories of these paths.
|
||||
</para>
|
||||
|
||||
</blockquote></para></blockquote>
|
||||
|
||||
@ -87,6 +87,14 @@ LoaderInit(void)
|
||||
LogMessageVerb(X_NONE, 2, "\t%s : %d.%d\n", ABI_CLASS_EXTENSION,
|
||||
GET_ABI_MAJOR(LoaderVersionInfo.extensionVersion),
|
||||
GET_ABI_MINOR(LoaderVersionInfo.extensionVersion));
|
||||
|
||||
LoaderInitPath();
|
||||
}
|
||||
|
||||
void
|
||||
LoaderClose(void)
|
||||
{
|
||||
LoaderClosePath();
|
||||
}
|
||||
|
||||
/* Public Interface to the loader. */
|
||||
|
||||
@ -69,11 +69,15 @@ typedef struct module_desc {
|
||||
/* External API for the loader */
|
||||
|
||||
void LoaderInit(void);
|
||||
void LoaderClose(void);
|
||||
|
||||
ModuleDescPtr LoadModule(const char *, void *, const XF86ModReqInfo *, int *);
|
||||
ModuleDescPtr DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent);
|
||||
void UnloadDriver(ModuleDescPtr);
|
||||
void LoaderSetPath(const char *path);
|
||||
|
||||
void LoaderSetPath(const char *driver, const char *path);
|
||||
void LoaderInitPath(void);
|
||||
void LoaderClosePath(void);
|
||||
|
||||
void LoaderUnload(const char *, void *);
|
||||
unsigned long LoaderGetModuleVersion(ModuleDescPtr mod);
|
||||
|
||||
@ -101,6 +101,32 @@ FreeStringList(char **paths)
|
||||
|
||||
static char **defaultPathList = NULL;
|
||||
|
||||
typedef struct {
|
||||
struct xorg_list entry;
|
||||
char *name;
|
||||
char **paths;
|
||||
} LoaderModulePathListItem;
|
||||
|
||||
struct xorg_list modulePathLists;
|
||||
|
||||
void LoaderInitPath(void) {
|
||||
/* defaultPathList is already set in xf86Init */
|
||||
xorg_list_init(&modulePathLists);
|
||||
}
|
||||
|
||||
void LoaderClosePath(void) {
|
||||
LoaderModulePathListItem *item, *next;
|
||||
xorg_list_for_each_entry_safe(item, next, &modulePathLists, entry) {
|
||||
xorg_list_del(&item->entry);
|
||||
free(item->name);
|
||||
if (item->paths)
|
||||
FreeStringList(item->paths);
|
||||
free(item);
|
||||
}
|
||||
xorg_list_del(&modulePathLists);
|
||||
FreeStringList(defaultPathList);
|
||||
}
|
||||
|
||||
static Bool
|
||||
PathIsAbsolute(const char *path)
|
||||
{
|
||||
@ -163,15 +189,73 @@ InitPathList(const char *path)
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a default search path or a search path for a specific driver
|
||||
*/
|
||||
void
|
||||
LoaderSetPath(const char *path)
|
||||
LoaderSetPath(const char *driver, const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return;
|
||||
LoaderModulePathListItem *item;
|
||||
|
||||
if (!driver) {
|
||||
if (path) {
|
||||
FreeStringList(defaultPathList);
|
||||
defaultPathList = InitPathList(path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
xorg_list_for_each_entry(item, &modulePathLists, entry) {
|
||||
if (!strcmp(item->name, driver)) {
|
||||
FreeStringList(item->paths);
|
||||
if (path)
|
||||
item->paths = InitPathList(path);
|
||||
else
|
||||
item->paths = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item = malloc(sizeof(LoaderModulePathListItem));
|
||||
if (item) {
|
||||
item->name = strdup(driver);
|
||||
if (path)
|
||||
item->paths = InitPathList(path);
|
||||
else
|
||||
item->paths = NULL;
|
||||
}
|
||||
if (item && item->name && (!path || item->paths))
|
||||
xorg_list_add(&item->entry, &modulePathLists);
|
||||
else {
|
||||
LogMessage(X_ERROR, "Failed to store module search path \"%s\" for module %s\n", path, driver);
|
||||
if (item) {
|
||||
if (item->name) free(item->name);
|
||||
if (item->paths) FreeStringList(item->paths);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a default search path or a search path for a specific driver
|
||||
* and make it effective
|
||||
*/
|
||||
static char **
|
||||
LoaderGetPath(const char *module)
|
||||
{
|
||||
LoaderModulePathListItem *item;
|
||||
|
||||
xorg_list_for_each_entry(item, &modulePathLists, entry) {
|
||||
if (!strcmp(item->name, module)) {
|
||||
if (item->paths)
|
||||
return item->paths;
|
||||
else
|
||||
return defaultPathList;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultPathList;
|
||||
}
|
||||
|
||||
/* Standard set of module subdirectories to search, in order of preference */
|
||||
static const char *stdSubdirs[] = {
|
||||
@ -725,7 +809,7 @@ LoadModule(const char *module, void *options, const XF86ModReqInfo *modreq,
|
||||
goto LoadModule_fail;
|
||||
}
|
||||
|
||||
pathlist = defaultPathList;
|
||||
pathlist = LoaderGetPath(name);
|
||||
if (!pathlist) {
|
||||
/* This could be a calloc failure too */
|
||||
if (errmaj)
|
||||
|
||||
@ -435,7 +435,7 @@ searches for loadable modules loading in the order specified.
|
||||
Multiple
|
||||
.B ModulePath
|
||||
entries may be specified, and they will be concatenated to build the
|
||||
module search path used by the server. The default module path is
|
||||
module search path used by the server. The standard default module path is
|
||||
.PP
|
||||
.RS 11
|
||||
@modulepath@
|
||||
@ -1327,11 +1327,11 @@ When an output device has been matched to the
|
||||
.B OutputClass
|
||||
section, any
|
||||
.B Option
|
||||
entries are applied to the device. One
|
||||
entries are applied to the device. Two
|
||||
.B OutputClass
|
||||
specific
|
||||
specific kinds of
|
||||
.B Option
|
||||
is recognized. See the
|
||||
are recognized. See the
|
||||
.B Device
|
||||
section below for a description of the remaining
|
||||
.B Option
|
||||
@ -1356,21 +1356,90 @@ If multiple output devices match an
|
||||
section with the
|
||||
.B HotplugDriver
|
||||
option, the first one enumerated becomes the hotplug driver.
|
||||
A
|
||||
.RE
|
||||
.PP
|
||||
.TP 7
|
||||
An
|
||||
.B OutputClass
|
||||
Section may contain
|
||||
.B ModulePath
|
||||
entries. When an output device matches an
|
||||
section may contain multiple
|
||||
.TP 7
|
||||
.BI "ModulePath \*q" path \*q
|
||||
entries. When an output device with DRM enabled matches an
|
||||
.B OutputClass
|
||||
section, any
|
||||
section and
|
||||
.B Driver
|
||||
.I \*qdriver\*q
|
||||
is set, then for this driver module, and all modules loaded until the next driver
|
||||
for a DRM-enabled GPU, a search path is created by prepending all
|
||||
.B ModulePath
|
||||
entries in that
|
||||
.B OutputClass
|
||||
are pre-pended to the search path for loadable Xorg server modules. See
|
||||
to the
|
||||
.I standard
|
||||
search path \(lq@modulepath@\(rq for loadable Xorg server modules (not the
|
||||
.I effective
|
||||
default set path, which can undergo changes, see below). If there is a single
|
||||
.PP
|
||||
.RS 11
|
||||
.nf
|
||||
.B " ModulePath \*q\*q
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
.RS 7
|
||||
entry in an
|
||||
.B OutputClass
|
||||
for a
|
||||
.I driver
|
||||
, then only the
|
||||
.I standard
|
||||
path \(lq@modulepath@\(rq is searched from now on. It there no
|
||||
.B ModulePath
|
||||
entries at all, then the
|
||||
.I effective
|
||||
default search path (set globally) becomes active. Note that each
|
||||
.B OutputClass
|
||||
.I overrides
|
||||
search path for a
|
||||
.I driver
|
||||
, not
|
||||
.I extends
|
||||
it.
|
||||
.PP
|
||||
If a matching
|
||||
.B OutputClass
|
||||
contains
|
||||
.B ModulePath
|
||||
entries, but not a
|
||||
.B Driver
|
||||
entry, then paths are
|
||||
.I prepended
|
||||
to the
|
||||
.I effective
|
||||
default search path, which initially is standard \(lq@modulepath@\(rq, thus extending it.
|
||||
.PP
|
||||
These entries have no effect if a search path for loadable modules is set through command line. See
|
||||
.B ModulePath
|
||||
in the
|
||||
.B Files
|
||||
section for more info.
|
||||
.RE
|
||||
.PP
|
||||
.B OutputClass
|
||||
section may contain an arbitrary number of
|
||||
.PP
|
||||
.RS 4
|
||||
.nf
|
||||
.BI " Module \*q" module\*q
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
entries, which are quite equivalent to
|
||||
.B Driver
|
||||
except that
|
||||
.I \*qmodule\*q
|
||||
is not added to the list of autoconfigured video drivers. This may be useful to extend
|
||||
ABI version ignoring and special search paths to modules like "glx".
|
||||
.SH "DEVICE SECTION"
|
||||
The config file may have multiple
|
||||
.B Device
|
||||
|
||||
@ -38,6 +38,7 @@ static const xf86ConfigSymTabRec OutputClassTab[] = {
|
||||
{ENDSECTION, "endsection"},
|
||||
{IDENTIFIER, "identifier"},
|
||||
{DRIVER, "driver"},
|
||||
{MODULE, "module"},
|
||||
{MODULEPATH, "modulepath"},
|
||||
{OPTION, "option"},
|
||||
{MATCH_DRIVER, "matchdriver"},
|
||||
@ -53,6 +54,7 @@ xf86freeOutputClassList(XF86ConfOutputClassPtr ptr)
|
||||
TestFree(ptr->identifier);
|
||||
TestFree(ptr->comment);
|
||||
TestFree(ptr->driver);
|
||||
TestFree(ptr->modules);
|
||||
TestFree(ptr->modulepath);
|
||||
|
||||
xf86freeMatchGroupList(&ptr->match_driver);
|
||||
@ -99,6 +101,19 @@ xf86parseOutputClassSection(void)
|
||||
else
|
||||
ptr->driver = xf86_lex_val.str;
|
||||
break;
|
||||
case MODULE:
|
||||
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
|
||||
Error(QUOTE_MSG, "Module");
|
||||
if (ptr->modules) {
|
||||
char *path;
|
||||
XNFasprintf(&path, "%s,%s", ptr->modules, xf86_lex_val.str);
|
||||
free(xf86_lex_val.str);
|
||||
free(ptr->modules);
|
||||
ptr->modules = path;
|
||||
} else {
|
||||
ptr->modules = xf86_lex_val.str;
|
||||
}
|
||||
break;
|
||||
case MODULEPATH:
|
||||
if (xf86getSubToken(&(ptr->comment)) != XF86_TOKEN_STRING)
|
||||
Error(QUOTE_MSG, "ModulePath");
|
||||
@ -159,6 +174,10 @@ xf86printOutputClassSection(FILE * cf, XF86ConfOutputClassPtr ptr)
|
||||
fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
|
||||
if (ptr->driver)
|
||||
fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
|
||||
if (ptr->modules)
|
||||
fprintf(cf, "\tModule \"%s\"\n", ptr->modules);
|
||||
if (ptr->modulepath)
|
||||
fprintf(cf, "\tModulePath \"%s\"\n", ptr->modulepath);
|
||||
|
||||
xorg_list_for_each_entry(group, &ptr->match_driver, entry) {
|
||||
fprintf(cf, "\tMatchDriver \"");
|
||||
|
||||
@ -359,6 +359,7 @@ typedef struct {
|
||||
GenericListRec list;
|
||||
char *identifier;
|
||||
char *driver;
|
||||
char *modules;
|
||||
char *modulepath;
|
||||
struct xorg_list match_driver;
|
||||
XF86OptionPtr option_lst;
|
||||
|
||||
@ -255,6 +255,9 @@ typedef enum {
|
||||
NOMATCH_DRIVER,
|
||||
NOMATCH_TAG,
|
||||
NOMATCH_LAYOUT,
|
||||
|
||||
/* OutputClass Tokens */
|
||||
MODULE,
|
||||
} ParserTokens;
|
||||
|
||||
#endif /* _xf86_tokens_h */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user