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 #if defined(PCI_HAVE_PM_AOS_EXPANSION) 162 &pm_aos_expansion, 163 #else 164 NULL, 165 #endif 166 #ifdef PCI_HAVE_PM_RT_THREAD_SMART_DM 167 &pm_rt_thread_smart_dm, 168 #else 169 NULL, 170 #endif 171 }; 172 173 // If PCI_ACCESS_AUTO is selected, we probe the access methods in this order 174 static int probe_sequence[] = { 175 // System-specific methods 176 PCI_ACCESS_SYS_BUS_PCI, 177 PCI_ACCESS_PROC_BUS_PCI, 178 PCI_ACCESS_FBSD_DEVICE, 179 PCI_ACCESS_AIX_DEVICE, 180 PCI_ACCESS_NBSD_LIBPCI, 181 PCI_ACCESS_OBSD_DEVICE, 182 PCI_ACCESS_DARWIN, 183 PCI_ACCESS_SYLIXOS_DEVICE, 184 PCI_ACCESS_HURD, 185 PCI_ACCESS_WIN32_CFGMGR32, 186 PCI_ACCESS_WIN32_KLDBG, 187 PCI_ACCESS_WIN32_SYSDBG, 188 PCI_ACCESS_AOS_EXPANSION, 189 PCI_ACCESS_RT_THREAD_SMART_DM, 190 // Low-level methods poking the hardware directly 191 PCI_ACCESS_ECAM, 192 PCI_ACCESS_I386_TYPE1, 193 PCI_ACCESS_I386_TYPE2, 194 PCI_ACCESS_MMIO_TYPE1_EXT, 195 PCI_ACCESS_MMIO_TYPE1, 196 -1, 197 }; 198 199 static void PCI_NONRET 200 pci_generic_error(char *msg, ...) 201 { 202 va_list args; 203 204 va_start(args, msg); 205 fputs("pcilib: ", stderr); 206 vfprintf(stderr, msg, args); 207 va_end(args); 208 fputc('\n', stderr); 209 exit(1); 210 } 211 212 static void 213 pci_generic_warn(char *msg, ...) 214 { 215 va_list args; 216 217 va_start(args, msg); 218 fputs("pcilib: ", stderr); 219 vfprintf(stderr, msg, args); 220 va_end(args); 221 fputc('\n', stderr); 222 } 223 224 static void 225 pci_generic_debug(char *msg, ...) 226 { 227 va_list args; 228 229 va_start(args, msg); 230 vfprintf(stdout, msg, args); 231 va_end(args); 232 } 233 234 static void 235 pci_null_debug(char *msg UNUSED, ...) 236 { 237 } 238 239 // Memory allocation functions are safe to call if pci_access is not fully initalized or even NULL 240 241 void * 242 pci_malloc(struct pci_access *a, int size) 243 { 244 void *x = malloc(size); 245 246 if (!x) 247 (a && a->error ? a->error : pci_generic_error)("Out of memory (allocation of %d bytes failed)", size); 248 return x; 249 } 250 251 void 252 pci_mfree(void *x) 253 { 254 if (x) 255 free(x); 256 } 257 258 char * 259 pci_strdup(struct pci_access *a, const char *s) 260 { 261 int len = strlen(s) + 1; 262 char *t = pci_malloc(a, len); 263 memcpy(t, s, len); 264 return t; 265 } 266 267 int 268 pci_lookup_method(char *name) 269 { 270 int i; 271 272 for (i=0; i<PCI_ACCESS_MAX; i++) 273 if (pci_methods[i] && !strcmp(pci_methods[i]->name, name)) 274 return i; 275 return -1; 276 } 277 278 char * 279 pci_get_method_name(int index) 280 { 281 if (index < 0 || index >= PCI_ACCESS_MAX) 282 return NULL; 283 else if (!pci_methods[index]) 284 return ""; 285 else 286 return pci_methods[index]->name; 287 } 288 289 #if defined(PCI_OS_WINDOWS) || defined(PCI_OS_DJGPP) 290 291 static void 292 pci_init_name_list_path(struct pci_access *a) 293 { 294 if ((PCI_PATH_IDS_DIR)[0]) 295 pci_set_name_list_path(a, PCI_PATH_IDS_DIR "\\" PCI_IDS, 0); 296 else 297 { 298 char *path, *sep; 299 size_t len; 300 301 #if defined(PCI_OS_WINDOWS) && (defined(_WIN32) || defined(_WINDLL) || defined(_WINDOWS)) 302 303 HMODULE module; 304 size_t size; 305 306 #if defined(_WIN32) 307 module = (HINSTANCE)&__ImageBase; 308 #elif defined(_WINDLL) 309 module = _hModule; 310 #elif defined(_WINDOWS) 311 module = _hInstance; 312 #endif 313 314 /* 315 * Module file name can have arbitrary length despite all MS examples say 316 * about MAX_PATH upper limit. This limit does not apply for example when 317 * executable is running from network disk with very long UNC paths or 318 * when using "\\??\\" prefix for specifying executable binary path. 319 * Function GetModuleFileName() returns passed size argument when passed 320 * buffer is too small and does not signal any error. In this case retry 321 * again with larger buffer. 322 */ 323 size = 256; /* initial buffer size (more than sizeof(PCI_IDS)-4) */ 324 retry: 325 path = pci_malloc(a, size); 326 len = GetModuleFileName(module, path, size-sizeof(PCI_IDS)-4); /* 4 for "\\\\?\\" */ 327 if (len >= size-sizeof(PCI_IDS)-4) 328 { 329 free(path); 330 size *= 2; 331 goto retry; 332 } 333 else if (len == 0) 334 path[0] = '\0'; 335 336 /* 337 * GetModuleFileName() has bugs. On Windows 10 it prepends current drive 338 * letter if path is just pure NT namespace (with "\\??\\" prefix). Such 339 * extra drive letter makes path fully invalid and unusable. So remove 340 * extra drive letter to make path valid again. 341 * Reproduce: CreateProcessW("\\??\\C:\\lspci.exe", ...) 342 */ 343 if (((path[0] >= 'a' && path[0] <= 'z') || 344 (path[0] >= 'A' && path[0] <= 'Z')) && 345 strncmp(path+1, ":\\??\\", 5) == 0) 346 { 347 memmove(path, path+2, len-2); 348 len -= 2; 349 path[len] = '\0'; 350 } 351 352 /* 353 * GetModuleFileName() has bugs. On Windows 10 it does not add "\\\\?\\" 354 * prefix when path is in native NT UNC namespace. Such path is treated by 355 * WinAPI/DOS functions as standard DOS path relative to the current 356 * directory, hence something completely different. So prepend missing 357 * "\\\\?\\" prefix to make path valid again. 358 * Reproduce: CreateProcessW("\\??\\UNC\\10.0.2.4\\qemu\\lspci.exe", ...) 359 * 360 * If path starts with DOS drive letter and with appended PCI_IDS is 361 * longer than 260 bytes and is without "\\\\?\\" prefix then append it. 362 * This prefix is required for paths and file names with DOS drive letter 363 * longer than 260 bytes. 364 */ 365 if (strncmp(path, "\\UNC\\", 5) == 0 || 366 strncmp(path, "UNC\\", 4) == 0 || 367 (((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) && 368 len + sizeof(PCI_IDS) >= 260)) 369 { 370 memmove(path+4, path, len); 371 memcpy(path, "\\\\?\\", 4); 372 len += 4; 373 path[len] = '\0'; 374 } 375 376 #elif defined(PCI_OS_DJGPP) || defined(PCI_OS_WINDOWS) 377 378 const char *exe_path; 379 380 #ifdef PCI_OS_DJGPP 381 exe_path = __dos_argv0; 382 #else 383 exe_path = _pgmptr; 384 #endif 385 386 len = strlen(exe_path); 387 path = pci_malloc(a, len+sizeof(PCI_IDS)); 388 memcpy(path, exe_path, len+1); 389 390 #endif 391 392 sep = strrchr(path, '\\'); 393 if (!sep) 394 { 395 /* 396 * If current module path (current executable for static builds or 397 * current DLL library for shared build) cannot be determined then 398 * fallback to the current directory. 399 */ 400 free(path); 401 pci_set_name_list_path(a, PCI_IDS, 0); 402 } 403 else 404 { 405 memcpy(sep+1, PCI_IDS, sizeof(PCI_IDS)); 406 pci_set_name_list_path(a, path, 1); 407 } 408 } 409 } 410 411 #elif defined PCI_OS_AMIGAOS 412 413 static void 414 pci_init_name_list_path(struct pci_access *a) 415 { 416 int len = strlen(PCI_PATH_IDS_DIR); 417 418 if (!len) 419 pci_set_name_list_path(a, PCI_IDS, 0); 420 else 421 { 422 char last_char = PCI_PATH_IDS_DIR[len - 1]; 423 if (last_char == ':' || last_char == '/') // root or parent char 424 pci_set_name_list_path(a, PCI_PATH_IDS_DIR PCI_IDS, 0); 425 else 426 pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0); 427 } 428 } 429 430 #else 431 432 static void 433 pci_init_name_list_path(struct pci_access *a) 434 { 435 pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0); 436 } 437 438 #endif 439 440 #ifdef PCI_USE_DNS 441 442 static void 443 pci_init_dns(struct pci_access *a) 444 { 445 pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's"); 446 a->id_lookup_mode = PCI_LOOKUP_CACHE; 447 448 char *cache_dir = getenv("XDG_CACHE_HOME"); 449 if (!cache_dir) 450 cache_dir = "~/.cache"; 451 452 int name_len = strlen(cache_dir) + 32; 453 char *cache_name = pci_malloc(NULL, name_len); 454 snprintf(cache_name, name_len, "%s/pci-ids", cache_dir); 455 struct pci_param *param = pci_define_param(a, "net.cache_name", cache_name, "Name of the ID cache file"); 456 param->value_malloced = 1; 457 } 458 459 #endif 460 461 struct pci_access * 462 pci_alloc(void) 463 { 464 struct pci_access *a = pci_malloc(NULL, sizeof(struct pci_access)); 465 int i; 466 467 memset(a, 0, sizeof(*a)); 468 pci_init_name_list_path(a); 469 #ifdef PCI_USE_DNS 470 pci_init_dns(a); 471 #endif 472 #ifdef PCI_HAVE_HWDB 473 pci_define_param(a, "hwdb.disable", "0", "Do not look up names in UDEV's HWDB if non-zero"); 474 #endif 475 for (i=0; i<PCI_ACCESS_MAX; i++) 476 if (pci_methods[i] && pci_methods[i]->config) 477 pci_methods[i]->config(a); 478 return a; 479 } 480 481 int 482 pci_init_internal(struct pci_access *a, int skip_method) 483 { 484 if (!a->error) 485 a->error = pci_generic_error; 486 if (!a->warning) 487 a->warning = pci_generic_warn; 488 if (!a->debug) 489 a->debug = pci_generic_debug; 490 if (!a->debugging) 491 a->debug = pci_null_debug; 492 493 if (a->method != PCI_ACCESS_AUTO) 494 { 495 if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method]) 496 a->error("This access method is not supported."); 497 a->methods = pci_methods[a->method]; 498 } 499 else 500 { 501 unsigned int i; 502 for (i=0; probe_sequence[i] >= 0; i++) 503 { 504 struct pci_methods *m = pci_methods[probe_sequence[i]]; 505 if (!m) 506 continue; 507 if (skip_method == probe_sequence[i]) 508 continue; 509 a->debug("Trying method %s...", m->name); 510 if (m->detect(a)) 511 { 512 a->debug("...OK\n"); 513 a->methods = m; 514 a->method = probe_sequence[i]; 515 break; 516 } 517 a->debug("...No.\n"); 518 } 519 if (!a->methods) 520 return 0; 521 } 522 a->debug("Decided to use %s\n", a->methods->name); 523 a->methods->init(a); 524 return 1; 525 } 526 527 void 528 pci_init_v35(struct pci_access *a) 529 { 530 if (!pci_init_internal(a, -1)) 531 a->error("Cannot find any working access method."); 532 } 533 534 STATIC_ALIAS(void pci_init(struct pci_access *a), pci_init_v35(a)); 535 DEFINE_ALIAS(void pci_init_v30(struct pci_access *a), pci_init_v35); 536 SYMBOL_VERSION(pci_init_v30, pci_init@LIBPCI_3.0); 537 SYMBOL_VERSION(pci_init_v35, pci_init@@LIBPCI_3.5); 538 539 struct pci_access * 540 pci_clone_access(struct pci_access *a) 541 { 542 struct pci_access *b = pci_alloc(); 543 544 b->writeable = a->writeable; 545 b->buscentric = a->buscentric; 546 b->debugging = a->debugging; 547 b->error = a->error; 548 b->warning = a->warning; 549 b->debug = a->debug; 550 551 return b; 552 } 553 554 void 555 pci_cleanup(struct pci_access *a) 556 { 557 struct pci_dev *d, *e; 558 559 for (d=a->devices; d; d=e) 560 { 561 e = d->next; 562 pci_free_dev(d); 563 } 564 if (a->methods) 565 a->methods->cleanup(a); 566 pci_free_name_list(a); 567 pci_free_params(a); 568 pci_set_name_list_path(a, NULL, 0); 569 pci_mfree(a); 570 } 571