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