Skip to content

Commit 9f25f5d

Browse files
ONykyfmetux
authored andcommitted
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 <[email protected]>
1 parent d66dea6 commit 9f25f5d

File tree

12 files changed

+321
-37
lines changed

12 files changed

+321
-37
lines changed

config/10-nvidia.conf.in

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# This xorg.conf.d configuration snippet configures the X server to
2+
# automatically load the nvidia X driver and nvidia GLX libraries
3+
# when it detects a device driven by nvidia-drm.ko kernel module.
4+
# Please note that this works on Linux kernels version 6.12 or higher
5+
# with CONFIG_DRM enabled, and only if the nvidia-drm.ko kernel module
6+
# is loaded before the X server is started.
7+
8+
Section "OutputClass"
9+
Identifier "NVidia"
10+
MatchDriver "nvidia-drm"
11+
Driver "nvidia"
12+
Module "glx"
13+
Module "glxserver_nvidia"
14+
Option "AllowEmptyInitialConfiguration"
15+
ModulePath "@libdir@/nvidia/xorg"
16+
EndSection

config/meson.build

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ endif
2626
if build_xorg
2727
install_data('10-quirks.conf',
2828
install_dir: join_paths(get_option('datadir'), 'X11/xorg.conf.d'))
29+
nvidia_conf = configuration_data()
30+
nvidia_conf.set('libdir', join_paths(get_option('prefix'),get_option('libdir')))
31+
configure_file(
32+
input: '10-nvidia.conf.in',
33+
output: '10-nvidia.conf',
34+
configuration: nvidia_conf,
35+
install_dir: join_paths(get_option('datadir'), 'X11/xorg.conf.d'),
36+
)
2937
endif
3038

3139
libxserver_config = static_library('xserver_config',

hw/xfree86/common/xf86Init.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ InitOutput(int argc, char **argv)
329329
LoaderInit();
330330

331331
/* Tell the loader the default module search path */
332-
LoaderSetPath(xf86ModulePath);
332+
LoaderSetPath(NULL, xf86ModulePath);
333333

334334
if (xf86Info.ignoreABI) {
335335
LoaderSetIgnoreAbi();
@@ -749,6 +749,8 @@ CloseInput(void)
749749
{
750750
config_fini();
751751
mieqFini();
752+
/* strictly speaking the below is not related to input, but ... */
753+
LoaderClose();
752754
}
753755

754756
/*

hw/xfree86/common/xf86platformBus.c

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,11 @@ xf86OutputClassDriverList(int index, XF86MatchedDrivers *md)
197197

198198
LogMessageVerb(X_INFO, 1, "Applying OutputClass \"%s\" to %s\n",
199199
cl->identifier, path);
200-
LogMessageVerb(X_NONE, 1, "\tloading driver: %s\n", cl->driver);
201-
202-
xf86AddMatchedDriver(md, cl->driver);
200+
if (cl->driver != NULL && *(cl->driver)) {
201+
LogMessageVerb(X_NONE, 1, "\tloading driver: %s\n", cl->driver);
202+
xf86AddMatchedDriver(md, cl->driver);
203+
} else
204+
LogMessageVerb(X_NONE, 1, "\tno driver specified\n");
203205
}
204206
}
205207
}
@@ -261,7 +263,8 @@ xf86platformProbe(void)
261263
Bool pci = TRUE;
262264
XF86ConfOutputClassPtr cl, cl_head = (xf86configptr) ?
263265
xf86configptr->conf_outputclass_lst : NULL;
264-
char *old_path, *path = NULL;
266+
char *driver_path, *path = NULL;
267+
char *curr, *next, *copy;
265268

266269
config_odev_probe(xf86PlatformDeviceProbe);
267270

@@ -284,19 +287,85 @@ xf86platformProbe(void)
284287
if (!OutputClassMatches(cl, &xf86_platform_devices[i]))
285288
continue;
286289

287-
if (cl->modulepath && xf86ModPathFrom != X_CMDLINE) {
288-
old_path = path;
289-
XNFasprintf(&path, "%s,%s", cl->modulepath,
290-
path ? path : xf86ModulePath);
291-
free(old_path);
292-
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath extended to \"%s\"\n",
293-
cl->identifier, path);
294-
LoaderSetPath(path);
290+
if (xf86ModPathFrom != X_CMDLINE) {
291+
if (cl->driver) {
292+
if (cl->modulepath) {
293+
if (*(cl->modulepath)) {
294+
XNFasprintf(&driver_path, "%s,%s", cl->modulepath, xf86ModulePath);
295+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for driver %s overridden with \"%s\"\n",
296+
cl->identifier, cl->driver, driver_path);
297+
} else {
298+
XNFasprintf(&driver_path, "%s", xf86ModulePath);
299+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for driver %s reset to standard \"%s\"\n",
300+
cl->identifier, cl->driver, driver_path);
301+
}
302+
} else {
303+
driver_path = NULL;
304+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for driver %s reset to default\n",
305+
cl->identifier, cl->driver);
306+
}
307+
if (*(cl->driver)) LoaderSetPath(cl->driver, driver_path);
308+
if (cl->modules) {
309+
LogMessageVerb(X_CONFIG, 1, " and for modules \"%s\" as well\n",
310+
cl->modules);
311+
XNFasprintf(&copy, "%s", cl->modules);
312+
curr = copy;
313+
while ((curr = strtok_r(curr, ",", &next))) {
314+
if (*curr) LoaderSetPath(curr, driver_path);
315+
curr = NULL;
316+
}
317+
free(copy);
318+
}
319+
free(driver_path);
320+
}
321+
else if (cl->modules) {
322+
if (cl->modulepath) {
323+
if (*(cl->modulepath)) {
324+
XNFasprintf(&driver_path, "%s,%s", cl->modulepath, xf86ModulePath);
325+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for modules %s overridden with \"%s\"\n",
326+
cl->identifier, cl->modules, driver_path);
327+
} else {
328+
XNFasprintf(&driver_path, "%s", xf86ModulePath);
329+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for modules %s reset to standard \"%s\"\n",
330+
cl->identifier, cl->modules, driver_path);
331+
}
332+
} else {
333+
driver_path = NULL;
334+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" ModulePath for modules %s reset to default\n",
335+
cl->identifier, cl->modules);
336+
}
337+
XNFasprintf(&copy, "%s", cl->modules);
338+
curr = copy;
339+
while ((curr = strtok_r(curr, ",", &next))) {
340+
if (*curr) LoaderSetPath(curr, driver_path);
341+
curr = NULL;
342+
}
343+
free(copy);
344+
} else {
345+
driver_path = path; /* Reuse for temporary storage */
346+
if (*(cl->modulepath)) {
347+
XNFasprintf(&path, "%s,%s", cl->modulepath,
348+
path ? path : xf86ModulePath);
349+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" default ModulePath extended to \"%s\"\n",
350+
cl->identifier, path);
351+
} else {
352+
XNFasprintf(&path, "%s", xf86ModulePath);
353+
LogMessageVerb(X_CONFIG, 1, "OutputClass \"%s\" default ModulePath reset to standard \"%s\"\n",
354+
cl->identifier, path);
355+
}
356+
}
357+
/* Otherwise global module search path is left unchanged */
295358
}
296359
}
297360
}
298361

299-
free(path);
362+
if (xf86ModPathFrom != X_CMDLINE) {
363+
if (path) {
364+
LoaderSetPath(NULL, path);
365+
free(path);
366+
} else
367+
LoaderSetPath(NULL, xf86ModulePath);
368+
}
300369

301370
/* First see if there is an OutputClass match marking a device as primary */
302371
for (i = 0; i < xf86_num_platform_devices; i++) {

hw/xfree86/doc/ddxDesign.xml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4779,15 +4779,16 @@ XFree86 common layer.
47794779

47804780
<blockquote><para>
47814781
<programlisting>
4782-
void LoaderSetPath(const char *path);
4782+
void LoaderSetPath(const char *driver, const char *path);
47834783
</programlisting>
47844784
<blockquote><para>
4785-
The <function>LoaderSetPath()</function> function initialises a default
4786-
module search path. This must be called if calls to other functions
4787-
are to be made without explicitly specifying a module search path.
4788-
The search path <parameter>path</parameter> must be a string of one or more
4789-
comma separated absolute paths. Modules are expected to be located
4790-
below these paths, possibly in subdirectories of these paths.
4785+
The <function>LoaderSetPath()</function> function initialises a search path
4786+
for <parameter>driver</parameter> module, if it is non-NULL,
4787+
or a default module search path otherwise. This must be called if calls
4788+
to other functions are to be made without explicitly specifying a module
4789+
search path. The search path <parameter>path</parameter> must be a string
4790+
of one or more comma separated absolute paths. Modules are expected to be
4791+
located below these paths, possibly in subdirectories of these paths.
47914792
</para>
47924793

47934794
</blockquote></para></blockquote>

hw/xfree86/loader/loader.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ LoaderInit(void)
8787
LogMessageVerb(X_NONE, 2, "\t%s : %d.%d\n", ABI_CLASS_EXTENSION,
8888
GET_ABI_MAJOR(LoaderVersionInfo.extensionVersion),
8989
GET_ABI_MINOR(LoaderVersionInfo.extensionVersion));
90+
91+
LoaderInitPath();
92+
}
93+
94+
void
95+
LoaderClose(void)
96+
{
97+
LoaderClosePath();
9098
}
9199

92100
/* Public Interface to the loader. */

hw/xfree86/loader/loaderProcs.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,15 @@ typedef struct module_desc {
6969
/* External API for the loader */
7070

7171
void LoaderInit(void);
72+
void LoaderClose(void);
7273

7374
ModuleDescPtr LoadModule(const char *, void *, const XF86ModReqInfo *, int *);
7475
ModuleDescPtr DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent);
7576
void UnloadDriver(ModuleDescPtr);
76-
void LoaderSetPath(const char *path);
77+
78+
void LoaderSetPath(const char *driver, const char *path);
79+
void LoaderInitPath(void);
80+
void LoaderClosePath(void);
7781

7882
void LoaderUnload(const char *, void *);
7983
unsigned long LoaderGetModuleVersion(ModuleDescPtr mod);

hw/xfree86/loader/loadmod.c

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,32 @@ FreeStringList(char **paths)
101101

102102
static char **defaultPathList = NULL;
103103

104+
typedef struct {
105+
struct xorg_list entry;
106+
char *name;
107+
char **paths;
108+
} LoaderModulePathListItem;
109+
110+
struct xorg_list modulePathLists;
111+
112+
void LoaderInitPath(void) {
113+
/* defaultPathList is already set in xf86Init */
114+
xorg_list_init(&modulePathLists);
115+
}
116+
117+
void LoaderClosePath(void) {
118+
LoaderModulePathListItem *item, *next;
119+
xorg_list_for_each_entry_safe(item, next, &modulePathLists, entry) {
120+
xorg_list_del(&item->entry);
121+
free(item->name);
122+
if (item->paths)
123+
FreeStringList(item->paths);
124+
free(item);
125+
}
126+
xorg_list_del(&modulePathLists);
127+
FreeStringList(defaultPathList);
128+
}
129+
104130
static Bool
105131
PathIsAbsolute(const char *path)
106132
{
@@ -163,14 +189,72 @@ InitPathList(const char *path)
163189
return list;
164190
}
165191

192+
/*
193+
* Set a default search path or a search path for a specific driver
194+
*/
166195
void
167-
LoaderSetPath(const char *path)
196+
LoaderSetPath(const char *driver, const char *path)
168197
{
169-
if (!path)
198+
LoaderModulePathListItem *item;
199+
200+
if (!driver) {
201+
if (path) {
202+
FreeStringList(defaultPathList);
203+
defaultPathList = InitPathList(path);
204+
}
170205
return;
206+
}
171207

172-
FreeStringList(defaultPathList);
173-
defaultPathList = InitPathList(path);
208+
xorg_list_for_each_entry(item, &modulePathLists, entry) {
209+
if (!strcmp(item->name, driver)) {
210+
FreeStringList(item->paths);
211+
if (path)
212+
item->paths = InitPathList(path);
213+
else
214+
item->paths = NULL;
215+
return;
216+
}
217+
}
218+
219+
item = malloc(sizeof(LoaderModulePathListItem));
220+
if (item) {
221+
item->name = strdup(driver);
222+
if (path)
223+
item->paths = InitPathList(path);
224+
else
225+
item->paths = NULL;
226+
}
227+
if (item && item->name && (!path || item->paths))
228+
xorg_list_add(&item->entry, &modulePathLists);
229+
else {
230+
LogMessage(X_ERROR, "Failed to store module search path \"%s\" for module %s\n", path, driver);
231+
if (item) {
232+
if (item->name) free(item->name);
233+
if (item->paths) FreeStringList(item->paths);
234+
free(item);
235+
}
236+
}
237+
}
238+
239+
/*
240+
* Get a default search path or a search path for a specific driver
241+
* and make it effective
242+
*/
243+
static char **
244+
LoaderGetPath(const char *module)
245+
{
246+
LoaderModulePathListItem *item;
247+
248+
xorg_list_for_each_entry(item, &modulePathLists, entry) {
249+
if (!strcmp(item->name, module)) {
250+
if (item->paths)
251+
return item->paths;
252+
else
253+
return defaultPathList;
254+
}
255+
}
256+
257+
return defaultPathList;
174258
}
175259

176260
/* Standard set of module subdirectories to search, in order of preference */
@@ -725,7 +809,7 @@ LoadModule(const char *module, void *options, const XF86ModReqInfo *modreq,
725809
goto LoadModule_fail;
726810
}
727811

728-
pathlist = defaultPathList;
812+
pathlist = LoaderGetPath(name);
729813
if (!pathlist) {
730814
/* This could be a calloc failure too */
731815
if (errmaj)

0 commit comments

Comments
 (0)