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