]> mj.ucw.cz Git - pciutils.git/blob - lib/init.c
8c8f9732692acfd3bb5bc4ac6274d091396e2a23
[pciutils.git] / lib / init.c
1 /*
2  *      The PCI Library -- Initialization and related things
3  *
4  *      Copyright (c) 1997--2018 Martin Mares <mj@ucw.cz>
5  *
6  *      Can be freely distributed and used under the terms of the GNU GPL.
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <string.h>
13
14 #include "internal.h"
15
16 #ifdef PCI_OS_DJGPP
17 #include <crt0.h> /* for __dos_argv0 */
18 #endif
19
20 #ifdef PCI_OS_WINDOWS
21
22 #include <windows.h>
23
24 /* Force usage of ANSI (char*) variant of GetModuleFileName() function */
25 #ifdef _WIN32
26 #ifdef GetModuleFileName
27 #undef GetModuleFileName
28 #endif
29 #define GetModuleFileName GetModuleFileNameA
30 #endif
31
32 /* Define __ImageBase for all linkers */
33 #ifdef _WIN32
34 /* GNU LD provides __ImageBase symbol since 2.19, in previous versions it is
35  * under name _image_base__, so add weak alias for compatibility. */
36 #ifdef __GNUC__
37 asm(".weak\t" PCI_STRINGIFY(__MINGW_USYMBOL(__ImageBase)) "\n\t"
38     ".set\t"  PCI_STRINGIFY(__MINGW_USYMBOL(__ImageBase)) "," PCI_STRINGIFY(__MINGW_USYMBOL(_image_base__)));
39 #endif
40 /*
41  * MSVC link.exe provides __ImageBase symbol since 12.00 (MSVC 6.0), for
42  * previous versions resolve it at runtime via GetModuleHandleA() which
43  * returns base for main executable or via VirtualQuery() for DLL builds.
44  */
45 #if defined(_MSC_VER) && _MSC_VER < 1200
46 static HMODULE
47 get_current_module_handle(void)
48 {
49 #ifdef PCI_SHARED_LIB
50   MEMORY_BASIC_INFORMATION info;
51   size_t len = VirtualQuery(&get_current_module_handle, &info, sizeof(info));
52   if (len != sizeof(info))
53     return NULL;
54   return (HMODULE)info.AllocationBase;
55 #else
56   return GetModuleHandleA(NULL);
57 #endif
58 }
59 #define __ImageBase (*(IMAGE_DOS_HEADER *)get_current_module_handle())
60 #else
61 extern IMAGE_DOS_HEADER __ImageBase;
62 #endif
63 #endif
64
65 #if defined(_WINDLL)
66 extern HINSTANCE _hModule;
67 #elif defined(_WINDOWS)
68 extern HINSTANCE _hInstance;
69 #endif
70
71 #endif
72
73 static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
74   NULL,
75 #ifdef PCI_HAVE_PM_LINUX_SYSFS
76   &pm_linux_sysfs,
77 #else
78   NULL,
79 #endif
80 #ifdef PCI_HAVE_PM_LINUX_PROC
81   &pm_linux_proc,
82 #else
83   NULL,
84 #endif
85 #ifdef PCI_HAVE_PM_INTEL_CONF
86   &pm_intel_conf1,
87   &pm_intel_conf2,
88 #else
89   NULL,
90   NULL,
91 #endif
92 #ifdef PCI_HAVE_PM_FBSD_DEVICE
93   &pm_fbsd_device,
94 #else
95   NULL,
96 #endif
97 #ifdef PCI_HAVE_PM_AIX_DEVICE
98   &pm_aix_device,
99 #else
100   NULL,
101 #endif
102 #ifdef PCI_HAVE_PM_NBSD_LIBPCI
103   &pm_nbsd_libpci,
104 #else
105   NULL,
106 #endif
107 #ifdef PCI_HAVE_PM_OBSD_DEVICE
108   &pm_obsd_device,
109 #else
110   NULL,
111 #endif
112 #ifdef PCI_HAVE_PM_DUMP
113   &pm_dump,
114 #else
115   NULL,
116 #endif
117 #ifdef PCI_HAVE_PM_DARWIN_DEVICE
118   &pm_darwin,
119 #else
120   NULL,
121 #endif
122 #ifdef PCI_HAVE_PM_SYLIXOS_DEVICE
123   &pm_sylixos_device,
124 #else
125   NULL,
126 #endif
127 #ifdef PCI_HAVE_PM_HURD_CONF
128   &pm_hurd,
129 #else
130   NULL,
131 #endif
132 #ifdef PCI_HAVE_PM_WIN32_CFGMGR32
133   &pm_win32_cfgmgr32,
134 #else
135   NULL,
136 #endif
137 #ifdef PCI_HAVE_PM_WIN32_KLDBG
138   &pm_win32_kldbg,
139 #else
140   NULL,
141 #endif
142 #ifdef PCI_HAVE_PM_WIN32_SYSDBG
143   &pm_win32_sysdbg,
144 #else
145   NULL,
146 #endif
147 #ifdef PCI_HAVE_PM_MMIO_CONF
148   &pm_mmio_conf1,
149   &pm_mmio_conf1_ext,
150 #else
151   NULL,
152   NULL,
153 #endif
154 };
155
156 // If PCI_ACCESS_AUTO is selected, we probe the access methods in this order
157 static int probe_sequence[] = {
158   // System-specific methods
159   PCI_ACCESS_SYS_BUS_PCI,
160   PCI_ACCESS_PROC_BUS_PCI,
161   PCI_ACCESS_FBSD_DEVICE,
162   PCI_ACCESS_AIX_DEVICE,
163   PCI_ACCESS_NBSD_LIBPCI,
164   PCI_ACCESS_OBSD_DEVICE,
165   PCI_ACCESS_DARWIN,
166   PCI_ACCESS_SYLIXOS_DEVICE,
167   PCI_ACCESS_HURD,
168   PCI_ACCESS_WIN32_CFGMGR32,
169   PCI_ACCESS_WIN32_KLDBG,
170   PCI_ACCESS_WIN32_SYSDBG,
171   // Low-level methods poking the hardware directly
172   PCI_ACCESS_I386_TYPE1,
173   PCI_ACCESS_I386_TYPE2,
174   PCI_ACCESS_MMIO_TYPE1_EXT,
175   PCI_ACCESS_MMIO_TYPE1,
176   -1,
177 };
178
179 static void PCI_NONRET
180 pci_generic_error(char *msg, ...)
181 {
182   va_list args;
183
184   va_start(args, msg);
185   fputs("pcilib: ", stderr);
186   vfprintf(stderr, msg, args);
187   va_end(args);
188   fputc('\n', stderr);
189   exit(1);
190 }
191
192 static void
193 pci_generic_warn(char *msg, ...)
194 {
195   va_list args;
196
197   va_start(args, msg);
198   fputs("pcilib: ", stderr);
199   vfprintf(stderr, msg, args);
200   va_end(args);
201   fputc('\n', stderr);
202 }
203
204 static void
205 pci_generic_debug(char *msg, ...)
206 {
207   va_list args;
208
209   va_start(args, msg);
210   vfprintf(stdout, msg, args);
211   va_end(args);
212 }
213
214 static void
215 pci_null_debug(char *msg UNUSED, ...)
216 {
217 }
218
219 // Memory allocation functions are safe to call if pci_access is not fully initalized or even NULL
220
221 void *
222 pci_malloc(struct pci_access *a, int size)
223 {
224   void *x = malloc(size);
225
226   if (!x)
227     (a && a->error ? a->error : pci_generic_error)("Out of memory (allocation of %d bytes failed)", size);
228   return x;
229 }
230
231 void
232 pci_mfree(void *x)
233 {
234   if (x)
235     free(x);
236 }
237
238 char *
239 pci_strdup(struct pci_access *a, const char *s)
240 {
241   int len = strlen(s) + 1;
242   char *t = pci_malloc(a, len);
243   memcpy(t, s, len);
244   return t;
245 }
246
247 int
248 pci_lookup_method(char *name)
249 {
250   int i;
251
252   for (i=0; i<PCI_ACCESS_MAX; i++)
253     if (pci_methods[i] && !strcmp(pci_methods[i]->name, name))
254       return i;
255   return -1;
256 }
257
258 char *
259 pci_get_method_name(int index)
260 {
261   if (index < 0 || index >= PCI_ACCESS_MAX)
262     return NULL;
263   else if (!pci_methods[index])
264     return "";
265   else
266     return pci_methods[index]->name;
267 }
268
269 #if defined(PCI_OS_WINDOWS) || defined(PCI_OS_DJGPP)
270
271 static void
272 pci_init_name_list_path(struct pci_access *a)
273 {
274   if ((PCI_PATH_IDS_DIR)[0])
275     pci_set_name_list_path(a, PCI_PATH_IDS_DIR "\\" PCI_IDS, 0);
276   else
277     {
278       char *path, *sep;
279       size_t len;
280
281 #if defined(PCI_OS_WINDOWS) && (defined(_WIN32) || defined(_WINDLL) || defined(_WINDOWS))
282
283       HMODULE module;
284       size_t size;
285
286 #if defined(_WIN32)
287       module = (HINSTANCE)&__ImageBase;
288 #elif defined(_WINDLL)
289       module = _hModule;
290 #elif defined(_WINDOWS)
291       module = _hInstance;
292 #endif
293
294       /*
295        * Module file name can have arbitrary length despite all MS examples say
296        * about MAX_PATH upper limit. This limit does not apply for example when
297        * executable is running from network disk with very long UNC paths or
298        * when using "\\??\\" prefix for specifying executable binary path.
299        * Function GetModuleFileName() returns passed size argument when passed
300        * buffer is too small and does not signal any error. In this case retry
301        * again with larger buffer.
302        */
303       size = 256; /* initial buffer size (more than sizeof(PCI_IDS)) */
304 retry:
305       path = pci_malloc(a, size);
306       len = GetModuleFileName(module, path, size-sizeof(PCI_IDS));
307       if (len >= size-sizeof(PCI_IDS))
308         {
309           free(path);
310           size *= 2;
311           goto retry;
312         }
313       else if (len == 0)
314         path[0] = '\0';
315
316 #elif defined(PCI_OS_DJGPP) || defined(PCI_OS_WINDOWS)
317
318       const char *exe_path;
319
320 #ifdef PCI_OS_DJGPP
321       exe_path = __dos_argv0;
322 #else
323       exe_path = _pgmptr;
324 #endif
325
326       len = strlen(exe_path);
327       path = pci_malloc(a, len+sizeof(PCI_IDS));
328       memcpy(path, exe_path, len+1);
329
330 #endif
331
332       sep = strrchr(path, '\\');
333       if (!sep)
334         {
335           /*
336            * If current module path (current executable for static builds or
337            * current DLL library for shared build) cannot be determined then
338            * fallback to the current directory.
339            */
340           free(path);
341           pci_set_name_list_path(a, PCI_IDS, 0);
342         }
343       else
344         {
345           memcpy(sep+1, PCI_IDS, sizeof(PCI_IDS));
346           pci_set_name_list_path(a, path, 1);
347         }
348     }
349 }
350
351 #else
352
353 static void
354 pci_init_name_list_path(struct pci_access *a)
355 {
356   pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0);
357 }
358
359 #endif
360
361 struct pci_access *
362 pci_alloc(void)
363 {
364   struct pci_access *a = pci_malloc(NULL, sizeof(struct pci_access));
365   int i;
366
367   memset(a, 0, sizeof(*a));
368   pci_init_name_list_path(a);
369 #ifdef PCI_USE_DNS
370   pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's");
371   pci_define_param(a, "net.cache_name", "~/.pciids-cache", "Name of the ID cache file");
372   a->id_lookup_mode = PCI_LOOKUP_CACHE;
373 #endif
374 #ifdef PCI_HAVE_HWDB
375   pci_define_param(a, "hwdb.disable", "0", "Do not look up names in UDEV's HWDB if non-zero");
376 #endif
377   for (i=0; i<PCI_ACCESS_MAX; i++)
378     if (pci_methods[i] && pci_methods[i]->config)
379       pci_methods[i]->config(a);
380   return a;
381 }
382
383 void
384 pci_init_v35(struct pci_access *a)
385 {
386   if (!a->error)
387     a->error = pci_generic_error;
388   if (!a->warning)
389     a->warning = pci_generic_warn;
390   if (!a->debug)
391     a->debug = pci_generic_debug;
392   if (!a->debugging)
393     a->debug = pci_null_debug;
394
395   if (a->method)
396     {
397       if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method])
398         a->error("This access method is not supported.");
399       a->methods = pci_methods[a->method];
400     }
401   else
402     {
403       unsigned int i;
404       for (i=0; probe_sequence[i] >= 0; i++)
405         {
406           struct pci_methods *m = pci_methods[probe_sequence[i]];
407           if (!m)
408             continue;
409           a->debug("Trying method %s...", m->name);
410           if (m->detect(a))
411             {
412               a->debug("...OK\n");
413               a->methods = m;
414               a->method = probe_sequence[i];
415               break;
416             }
417           a->debug("...No.\n");
418         }
419       if (!a->methods)
420         a->error("Cannot find any working access method.");
421     }
422   a->debug("Decided to use %s\n", a->methods->name);
423   a->methods->init(a);
424 }
425
426 STATIC_ALIAS(void pci_init(struct pci_access *a), pci_init_v35(a));
427 DEFINE_ALIAS(void pci_init_v30(struct pci_access *a), pci_init_v35);
428 SYMBOL_VERSION(pci_init_v30, pci_init@LIBPCI_3.0);
429 SYMBOL_VERSION(pci_init_v35, pci_init@@LIBPCI_3.5);
430
431 void
432 pci_cleanup(struct pci_access *a)
433 {
434   struct pci_dev *d, *e;
435
436   for (d=a->devices; d; d=e)
437     {
438       e = d->next;
439       pci_free_dev(d);
440     }
441   if (a->methods)
442     a->methods->cleanup(a);
443   pci_free_name_list(a);
444   pci_free_params(a);
445   pci_set_name_list_path(a, NULL, 0);
446   pci_mfree(a);
447 }