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