]> mj.ucw.cz Git - pciutils.git/blob - lib/sysfs.c
lspci: add VirtIO SharedMemory capability support
[pciutils.git] / lib / sysfs.c
1 /*
2  *      The PCI Library -- Configuration Access via /sys/bus/pci
3  *
4  *      Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx>
5  *      Copyright (c) 1997--2024 Martin Mares <mj@ucw.cz>
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   if (want_fill(d, flags, PCI_FILL_RCD_LNK))
488     {
489       char buf[OBJBUFSIZE];
490       if (sysfs_get_string(d, "rcd_link_cap", buf, 0))
491         d->rcd_link_cap = strtoul(buf, NULL, 16);
492       if (sysfs_get_string(d, "rcd_link_ctrl", buf, 0))
493         d->rcd_link_ctrl = strtoul(buf, NULL, 16);
494       if (sysfs_get_string(d, "rcd_link_status", buf, 0))
495         d->rcd_link_status = strtoul(buf, NULL, 16);
496     }
497
498   pci_generic_fill_info(d, flags);
499 }
500
501 /* Intent of the sysfs_setup() caller */
502 enum
503   {
504     SETUP_READ_CONFIG = 0,
505     SETUP_WRITE_CONFIG = 1,
506     SETUP_READ_VPD = 2
507   };
508
509 static int
510 sysfs_setup(struct pci_dev *d, int intent)
511 {
512   struct pci_access *a = d->access;
513   char namebuf[OBJNAMELEN];
514
515   if (a->cached_dev != d || (intent == SETUP_WRITE_CONFIG && !a->fd_rw))
516     {
517       sysfs_flush_cache(a);
518       a->cached_dev = d;
519     }
520
521   if (intent == SETUP_READ_VPD)
522     {
523       if (a->fd_vpd < 0)
524         {
525           sysfs_obj_name(d, "vpd", namebuf);
526           a->fd_vpd = open(namebuf, O_RDONLY);
527           /* No warning on error; vpd may be absent or accessible only to root */
528         }
529       return a->fd_vpd;
530     }
531
532   if (a->fd < 0)
533     {
534       sysfs_obj_name(d, "config", namebuf);
535       a->fd_rw = a->writeable || intent == SETUP_WRITE_CONFIG;
536       a->fd = open(namebuf, a->fd_rw ? O_RDWR : O_RDONLY);
537       if (a->fd < 0)
538         a->warning("Cannot open %s", namebuf);
539     }
540   return a->fd;
541 }
542
543 static int sysfs_read(struct pci_dev *d, int pos, byte *buf, int len)
544 {
545   int fd = sysfs_setup(d, SETUP_READ_CONFIG);
546   int res;
547
548   if (fd < 0)
549     return 0;
550   res = pread(fd, buf, len, pos);
551   if (res < 0)
552     {
553       d->access->warning("sysfs_read: read failed: %s", strerror(errno));
554       return 0;
555     }
556   else if (res != len)
557     return 0;
558   return 1;
559 }
560
561 static int sysfs_write(struct pci_dev *d, int pos, byte *buf, int len)
562 {
563   int fd = sysfs_setup(d, SETUP_WRITE_CONFIG);
564   int res;
565
566   if (fd < 0)
567     return 0;
568   res = pwrite(fd, buf, len, pos);
569   if (res < 0)
570     {
571       d->access->warning("sysfs_write: write failed: %s", strerror(errno));
572       return 0;
573     }
574   else if (res != len)
575     {
576       d->access->warning("sysfs_write: tried to write %d bytes at %d, but only %d succeeded", len, pos, res);
577       return 0;
578     }
579   return 1;
580 }
581
582 static int sysfs_read_vpd(struct pci_dev *d, int pos, byte *buf, int len)
583 {
584   int fd = sysfs_setup(d, SETUP_READ_VPD);
585   int res;
586
587   if (fd < 0)
588     return 0;
589   res = pread(fd, buf, len, pos);
590   if (res < 0)
591     {
592       d->access->warning("sysfs_read_vpd: read failed: %s", strerror(errno));
593       return 0;
594     }
595   else if (res != len)
596     return 0;
597   return 1;
598 }
599
600 static void sysfs_cleanup_dev(struct pci_dev *d)
601 {
602   struct pci_access *a = d->access;
603
604   if (a->cached_dev == d)
605     sysfs_flush_cache(a);
606 }
607
608 struct pci_methods pm_linux_sysfs = {
609   .name = "linux-sysfs",
610   .help = "The sys filesystem on Linux",
611   .config = sysfs_config,
612   .detect = sysfs_detect,
613   .init = sysfs_init,
614   .cleanup = sysfs_cleanup,
615   .scan = sysfs_scan,
616   .fill_info = sysfs_fill_info,
617   .read = sysfs_read,
618   .write = sysfs_write,
619   .read_vpd = sysfs_read_vpd,
620   .cleanup_dev = sysfs_cleanup_dev,
621 };