1 /* 2 * The PCI Library -- Configuration Access via /sys/bus/pci 3 * 4 * Copyright (c) 2003 Matthew Wilcox <[email protected]> 5 * Copyright (c) 1997--2023 Martin Mares <[email protected]> 6 * 7 * Can be freely distributed and used under the terms of the GNU GPL v2+. 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 */ 11 12 #define _GNU_SOURCE 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <stdarg.h> 18 #include <unistd.h> 19 #include <errno.h> 20 #include <dirent.h> 21 #include <fcntl.h> 22 #include <sys/types.h> 23 24 #include "internal.h" 25 26 static void 27 sysfs_config(struct pci_access *a) 28 { 29 pci_define_param(a, "sysfs.path", PCI_PATH_SYS_BUS_PCI, "Path to the sysfs device tree"); 30 } 31 32 static inline char * 33 sysfs_name(struct pci_access *a) 34 { 35 return pci_get_param(a, "sysfs.path"); 36 } 37 38 static int 39 sysfs_detect(struct pci_access *a) 40 { 41 if (access(sysfs_name(a), R_OK)) 42 { 43 a->debug("...cannot open %s", sysfs_name(a)); 44 return 0; 45 } 46 a->debug("...using %s", sysfs_name(a)); 47 return 1; 48 } 49 50 static void 51 sysfs_init(struct pci_access *a) 52 { 53 a->fd = -1; 54 a->fd_vpd = -1; 55 } 56 57 static void 58 sysfs_flush_cache(struct pci_access *a) 59 { 60 if (a->fd >= 0) 61 { 62 close(a->fd); 63 a->fd = -1; 64 } 65 if (a->fd_vpd >= 0) 66 { 67 close(a->fd_vpd); 68 a->fd_vpd = -1; 69 } 70 a->cached_dev = NULL; 71 } 72 73 static void 74 sysfs_cleanup(struct pci_access *a) 75 { 76 sysfs_flush_cache(a); 77 } 78 79 #define OBJNAMELEN 1024 80 static void 81 sysfs_obj_name(struct pci_dev *d, char *object, char *buf) 82 { 83 int n = snprintf(buf, OBJNAMELEN, "%s/devices/%04x:%02x:%02x.%d/%s", 84 sysfs_name(d->access), d->domain, d->bus, d->dev, d->func, object); 85 if (n < 0 || n >= OBJNAMELEN) 86 d->access->error("File name too long"); 87 } 88 89 #define OBJBUFSIZE 1024 90 91 static int 92 sysfs_get_string(struct pci_dev *d, char *object, char *buf, int mandatory) 93 { 94 struct pci_access *a = d->access; 95 int fd, n; 96 char namebuf[OBJNAMELEN]; 97 void (*warn)(char *msg, ...) = (mandatory ? a->error : a->warning); 98 99 sysfs_obj_name(d, object, namebuf); 100 fd = open(namebuf, O_RDONLY); 101 if (fd < 0) 102 { 103 if (mandatory || errno != ENOENT) 104 warn("Cannot open %s: %s", namebuf, strerror(errno)); 105 return 0; 106 } 107 n = read(fd, buf, OBJBUFSIZE); 108 close(fd); 109 if (n < 0) 110 { 111 warn("Error reading %s: %s", namebuf, strerror(errno)); 112 return 0; 113 } 114 if (n >= OBJBUFSIZE) 115 { 116 warn("Value in %s too long", namebuf); 117 return 0; 118 } 119 buf[n] = 0; 120 return 1; 121 } 122 123 static char * 124 sysfs_deref_link(struct pci_dev *d, char *link_name) 125 { 126 char path[2*OBJNAMELEN], rel_path[OBJNAMELEN]; 127 128 sysfs_obj_name(d, link_name, path); 129 memset(rel_path, 0, sizeof(rel_path)); 130 131 if (readlink(path, rel_path, sizeof(rel_path)) < 0) 132 return NULL; 133 134 sysfs_obj_name(d, "", path); 135 strcat(path, rel_path); 136 137 // Returns a pointer to malloc'ed memory 138 return realpath(path, NULL); 139 } 140 141 static int 142 sysfs_get_value(struct pci_dev *d, char *object, int mandatory) 143 { 144 char buf[OBJBUFSIZE]; 145 146 if (sysfs_get_string(d, object, buf, mandatory)) 147 return strtol(buf, NULL, 0); 148 else 149 return -1; 150 } 151 152 static void 153 sysfs_get_resources(struct pci_dev *d) 154 { 155 struct pci_access *a = d->access; 156 char namebuf[OBJNAMELEN], buf[256]; 157 struct { pciaddr_t flags, base_addr, size; } lines[10]; 158 int have_bar_bases, have_rom_base, have_bridge_bases; 159 FILE *file; 160 int i; 161 162 have_bar_bases = have_rom_base = have_bridge_bases = 0; 163 sysfs_obj_name(d, "resource", namebuf); 164 file = fopen(namebuf, "r"); 165 if (!file) 166 a->error("Cannot open %s: %s", namebuf, strerror(errno)); 167 for (i = 0; i < 7+6+4+1; i++) 168 { 169 unsigned long long start, end, size, flags; 170 if (!fgets(buf, sizeof(buf), file)) 171 break; 172 if (sscanf(buf, "%llx %llx %llx", &start, &end, &flags) != 3) 173 a->error("Syntax error in %s", namebuf); 174 if (end > start) 175 size = end - start + 1; 176 else 177 size = 0; 178 if (i < 6) 179 { 180 d->flags[i] = flags; 181 flags &= PCI_ADDR_FLAG_MASK; 182 d->base_addr[i] = start | flags; 183 d->size[i] = size; 184 have_bar_bases = 1; 185 } 186 else if (i == 6) 187 { 188 d->rom_flags = flags; 189 flags &= PCI_ADDR_FLAG_MASK; 190 d->rom_base_addr = start | flags; 191 d->rom_size = size; 192 have_rom_base = 1; 193 } 194 else if (i < 7+6+4) 195 { 196 /* 197 * If kernel was compiled without CONFIG_PCI_IOV option then after 198 * the ROM line for configured bridge device (that which had set 199 * subordinary bus number to non-zero value) are four additional lines 200 * which describe resources behind bridge. For PCI-to-PCI bridges they 201 * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0, 202 * IO1, MEM0 and MEM1. For unconfigured bridges and other devices 203 * there is no additional line after the ROM line. If kernel was 204 * compiled with CONFIG_PCI_IOV option then after the ROM line and 205 * before the first bridge resource line are six additional lines 206 * which describe IOV resources. Read all remaining lines in resource 207 * file and based on the number of remaining lines (0, 4, 6, 10) parse 208 * resources behind bridge. 209 */ 210 lines[i-7].flags = flags; 211 lines[i-7].base_addr = start; 212 lines[i-7].size = size; 213 } 214 } 215 if (i == 7+4 || i == 7+6+4) 216 { 217 int offset = (i == 7+6+4) ? 6 : 0; 218 for (i = 0; i < 4; i++) 219 { 220 d->bridge_flags[i] = lines[offset+i].flags; 221 d->bridge_base_addr[i] = lines[offset+i].base_addr; 222 d->bridge_size[i] = lines[offset+i].size; 223 } 224 have_bridge_bases = 1; 225 } 226 fclose(file); 227 if (!have_bar_bases) 228 clear_fill(d, PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS); 229 if (!have_rom_base) 230 clear_fill(d, PCI_FILL_ROM_BASE); 231 if (!have_bridge_bases) 232 clear_fill(d, PCI_FILL_BRIDGE_BASES); 233 } 234 235 static void sysfs_scan(struct pci_access *a) 236 { 237 char dirname[1024]; 238 DIR *dir; 239 struct dirent *entry; 240 int n; 241 242 n = snprintf(dirname, sizeof(dirname), "%s/devices", sysfs_name(a)); 243 if (n < 0 || n >= (int) sizeof(dirname)) 244 a->error("Directory name too long"); 245 dir = opendir(dirname); 246 if (!dir) 247 a->error("Cannot open %s", dirname); 248 while ((entry = readdir(dir))) 249 { 250 struct pci_dev *d; 251 unsigned int dom, bus, dev, func; 252 253 /* ".", ".." or a special non-device perhaps */ 254 if (entry->d_name[0] == '.') 255 continue; 256 257 d = pci_alloc_dev(a); 258 if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4) 259 a->error("sysfs_scan: Couldn't parse entry name %s", entry->d_name); 260 261 /* Ensure kernel provided domain that fits in a signed integer */ 262 if (dom > 0x7fffffff) 263 a->error("sysfs_scan: Invalid domain %x", dom); 264 265 d->domain = dom; 266 d->bus = bus; 267 d->dev = dev; 268 d->func = func; 269 pci_link_dev(a, d); 270 } 271 closedir(dir); 272 } 273 274 static void 275 sysfs_fill_slots(struct pci_access *a) 276 { 277 char dirname[1024]; 278 DIR *dir; 279 struct dirent *entry; 280 int n; 281 282 n = snprintf(dirname, sizeof(dirname), "%s/slots", sysfs_name(a)); 283 if (n < 0 || n >= (int) sizeof(dirname)) 284 a->error("Directory name too long"); 285 dir = opendir(dirname); 286 if (!dir) 287 return; 288 289 while (entry = readdir(dir)) 290 { 291 char namebuf[OBJNAMELEN], buf[16]; 292 FILE *file; 293 unsigned int dom, bus, dev; 294 int res = 0; 295 struct pci_dev *d; 296 297 /* ".", ".." or a special non-device perhaps */ 298 if (entry->d_name[0] == '.') 299 continue; 300 301 n = snprintf(namebuf, OBJNAMELEN, "%s/%s/%s", dirname, entry->d_name, "address"); 302 if (n < 0 || n >= OBJNAMELEN) 303 a->error("File name too long"); 304 file = fopen(namebuf, "r"); 305 /* 306 * Old versions of Linux had a fakephp which didn't have an 'address' 307 * file. There's no useful information to be gleaned from these 308 * devices, pretend they're not there. 309 */ 310 if (!file) 311 continue; 312 313 if (!fgets(buf, sizeof(buf), file) || (res = sscanf(buf, "%x:%x:%x", &dom, &bus, &dev)) < 3) 314 { 315 /* 316 * In some cases, the slot is not tied to a specific device before 317 * a card gets inserted. This happens for example on IBM pSeries 318 * and we need not warn about it. 319 */ 320 if (res != 2) 321 a->warning("sysfs_fill_slots: Couldn't parse entry address %s", buf); 322 } 323 else 324 { 325 for (d = a->devices; d; d = d->next) 326 if (dom == (unsigned)d->domain && bus == d->bus && dev == d->dev && !d->phy_slot) 327 d->phy_slot = pci_set_property(d, PCI_FILL_PHYS_SLOT, entry->d_name); 328 } 329 fclose(file); 330 } 331 closedir(dir); 332 } 333 334 static void 335 sysfs_fill_info(struct pci_dev *d, unsigned int flags) 336 { 337 int value, want_class, want_class_ext; 338 339 if (!d->access->buscentric) 340 { 341 /* 342 * These fields can be read from the config registers, but we want to show 343 * the kernel's view, which has regions and IRQs remapped and other fields 344 * (most importantly classes) possibly fixed if the device is known broken. 345 */ 346 if (want_fill(d, flags, PCI_FILL_IDENT)) 347 { 348 d->vendor_id = sysfs_get_value(d, "vendor", 1); 349 d->device_id = sysfs_get_value(d, "device", 1); 350 } 351 want_class = want_fill(d, flags, PCI_FILL_CLASS); 352 want_class_ext = want_fill(d, flags, PCI_FILL_CLASS_EXT); 353 if (want_class || want_class_ext) 354 { 355 value = sysfs_get_value(d, "class", 1); 356 if (want_class) 357 d->device_class = value >> 8; 358 if (want_class_ext) 359 { 360 d->prog_if = value & 0xff; 361 value = sysfs_get_value(d, "revision", 0); 362 if (value < 0) 363 value = pci_read_byte(d, PCI_REVISION_ID); 364 if (value >= 0) 365 d->rev_id = value; 366 } 367 } 368 if (want_fill(d, flags, PCI_FILL_SUBSYS)) 369 { 370 value = sysfs_get_value(d, "subsystem_vendor", 0); 371 if (value >= 0) 372 { 373 d->subsys_vendor_id = value; 374 value = sysfs_get_value(d, "subsystem_device", 0); 375 if (value >= 0) 376 d->subsys_id = value; 377 } 378 else 379 clear_fill(d, PCI_FILL_SUBSYS); 380 } 381 if (want_fill(d, flags, PCI_FILL_IRQ)) 382 d->irq = sysfs_get_value(d, "irq", 1); 383 if (want_fill(d, flags, PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS | PCI_FILL_BRIDGE_BASES)) 384 sysfs_get_resources(d); 385 if (want_fill(d, flags, PCI_FILL_PARENT)) 386 { 387 unsigned int domain, bus, dev, func; 388 char *path_abs, *path_canon, *name; 389 char path_rel[OBJNAMELEN]; 390 struct pci_dev *parent; 391 392 /* Construct sysfs path for parent device */ 393 sysfs_obj_name(d, "..", path_rel); 394 path_abs = realpath(path_rel, NULL); 395 name = path_abs ? strrchr(path_abs, '/') : NULL; 396 name = name ? name+1 : name; 397 parent = NULL; 398 399 if (name && sscanf(name, "%x:%x:%x.%d", &domain, &bus, &dev, &func) == 4 && domain <= 0x7fffffff) 400 for (parent = d->access->devices; parent; parent = parent->next) 401 if (parent->domain == (int)domain && parent->bus == bus && parent->dev == dev && parent->func == func) 402 break; 403 404 if (parent) 405 { 406 /* Check if parsed BDF address from parent sysfs device is really expected PCI device */ 407 sysfs_obj_name(parent, ".", path_rel); 408 path_canon = realpath(path_rel, NULL); 409 if (!path_canon || strcmp(path_canon, path_abs) != 0) 410 parent = NULL; 411 412 if (path_canon) 413 free(path_canon); 414 } 415 416 if (parent) 417 d->parent = parent; 418 else 419 clear_fill(d, PCI_FILL_PARENT); 420 421 if (path_abs) 422 free(path_abs); 423 } 424 } 425 426 if (want_fill(d, flags, PCI_FILL_PHYS_SLOT)) 427 { 428 struct pci_dev *pd; 429 sysfs_fill_slots(d->access); 430 for (pd = d->access->devices; pd; pd = pd->next) 431 pd->known_fields |= PCI_FILL_PHYS_SLOT; 432 } 433 434 if (want_fill(d, flags, PCI_FILL_MODULE_ALIAS)) 435 { 436 char buf[OBJBUFSIZE]; 437 if (sysfs_get_string(d, "modalias", buf, 0)) 438 d->module_alias = pci_set_property(d, PCI_FILL_MODULE_ALIAS, buf); 439 } 440 441 if (want_fill(d, flags, PCI_FILL_LABEL)) 442 { 443 char buf[OBJBUFSIZE]; 444 if (sysfs_get_string(d, "label", buf, 0)) 445 d->label = pci_set_property(d, PCI_FILL_LABEL, buf); 446 } 447 448 if (want_fill(d, flags, PCI_FILL_NUMA_NODE)) 449 d->numa_node = sysfs_get_value(d, "numa_node", 0); 450 451 if (want_fill(d, flags, PCI_FILL_IOMMU_GROUP)) 452 { 453 char *group_link = sysfs_deref_link(d, "iommu_group"); 454 if (group_link) 455 { 456 pci_set_property(d, PCI_FILL_IOMMU_GROUP, basename(group_link)); 457 free(group_link); 458 } 459 } 460 461 if (want_fill(d, flags, PCI_FILL_DT_NODE)) 462 { 463 char *node = sysfs_deref_link(d, "of_node"); 464 if (node) 465 { 466 pci_set_property(d, PCI_FILL_DT_NODE, node); 467 free(node); 468 } 469 } 470 471 if (want_fill(d, flags, PCI_FILL_DRIVER)) 472 { 473 char *driver_path = sysfs_deref_link(d, "driver"); 474 if (driver_path) 475 { 476 char *driver = strrchr(driver_path, '/'); 477 driver = driver ? driver+1 : driver_path; 478 pci_set_property(d, PCI_FILL_DRIVER, driver); 479 free(driver_path); 480 } 481 else 482 clear_fill(d, PCI_FILL_DRIVER); 483 } 484 485 pci_generic_fill_info(d, flags); 486 } 487 488 /* Intent of the sysfs_setup() caller */ 489 enum 490 { 491 SETUP_READ_CONFIG = 0, 492 SETUP_WRITE_CONFIG = 1, 493 SETUP_READ_VPD = 2 494 }; 495 496 static int 497 sysfs_setup(struct pci_dev *d, int intent) 498 { 499 struct pci_access *a = d->access; 500 char namebuf[OBJNAMELEN]; 501 502 if (a->cached_dev != d || (intent == SETUP_WRITE_CONFIG && !a->fd_rw)) 503 { 504 sysfs_flush_cache(a); 505 a->cached_dev = d; 506 } 507 508 if (intent == SETUP_READ_VPD) 509 { 510 if (a->fd_vpd < 0) 511 { 512 sysfs_obj_name(d, "vpd", namebuf); 513 a->fd_vpd = open(namebuf, O_RDONLY); 514 /* No warning on error; vpd may be absent or accessible only to root */ 515 } 516 return a->fd_vpd; 517 } 518 519 if (a->fd < 0) 520 { 521 sysfs_obj_name(d, "config", namebuf); 522 a->fd_rw = a->writeable || intent == SETUP_WRITE_CONFIG; 523 a->fd = open(namebuf, a->fd_rw ? O_RDWR : O_RDONLY); 524 if (a->fd < 0) 525 a->warning("Cannot open %s", namebuf); 526 } 527 return a->fd; 528 } 529 530 static int sysfs_read(struct pci_dev *d, int pos, byte *buf, int len) 531 { 532 int fd = sysfs_setup(d, SETUP_READ_CONFIG); 533 int res; 534 535 if (fd < 0) 536 return 0; 537 res = pread(fd, buf, len, pos); 538 if (res < 0) 539 { 540 d->access->warning("sysfs_read: read failed: %s", strerror(errno)); 541 return 0; 542 } 543 else if (res != len) 544 return 0; 545 return 1; 546 } 547 548 static int sysfs_write(struct pci_dev *d, int pos, byte *buf, int len) 549 { 550 int fd = sysfs_setup(d, SETUP_WRITE_CONFIG); 551 int res; 552 553 if (fd < 0) 554 return 0; 555 res = pwrite(fd, buf, len, pos); 556 if (res < 0) 557 { 558 d->access->warning("sysfs_write: write failed: %s", strerror(errno)); 559 return 0; 560 } 561 else if (res != len) 562 { 563 d->access->warning("sysfs_write: tried to write %d bytes at %d, but only %d succeeded", len, pos, res); 564 return 0; 565 } 566 return 1; 567 } 568 569 static int sysfs_read_vpd(struct pci_dev *d, int pos, byte *buf, int len) 570 { 571 int fd = sysfs_setup(d, SETUP_READ_VPD); 572 int res; 573 574 if (fd < 0) 575 return 0; 576 res = pread(fd, buf, len, pos); 577 if (res < 0) 578 { 579 d->access->warning("sysfs_read_vpd: read failed: %s", strerror(errno)); 580 return 0; 581 } 582 else if (res != len) 583 return 0; 584 return 1; 585 } 586 587 static void sysfs_cleanup_dev(struct pci_dev *d) 588 { 589 struct pci_access *a = d->access; 590 591 if (a->cached_dev == d) 592 sysfs_flush_cache(a); 593 } 594 595 struct pci_methods pm_linux_sysfs = { 596 "linux-sysfs", 597 "The sys filesystem on Linux", 598 sysfs_config, 599 sysfs_detect, 600 sysfs_init, 601 sysfs_cleanup, 602 sysfs_scan, 603 sysfs_fill_info, 604 sysfs_read, 605 sysfs_write, 606 sysfs_read_vpd, 607 NULL, /* init_dev */ 608 sysfs_cleanup_dev 609 }; 610