]> mj.ucw.cz Git - pciutils.git/blob - lib/ecam.c
lspci: add VirtIO SharedMemory capability support
[pciutils.git] / lib / ecam.c
1 /*
2  *      The PCI Library -- Direct Configuration access via PCIe ECAM
3  *
4  *      Copyright (c) 2023 Pali Rohár <pali@kernel.org>
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 "internal.h"
12 #include "physmem.h"
13 #include "physmem-access.h"
14
15 #include <ctype.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <limits.h>
21
22 #ifndef PCI_OS_WINDOWS
23 #include <glob.h>
24 #include <unistd.h>
25 #endif
26
27 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
28 #include <sys/sysctl.h>
29 #endif
30
31 #if defined (__FreeBSD__) || defined (__DragonFly__)
32 #include <kenv.h>
33 #endif
34
35 #ifdef _WIN32
36 #include "win32-helpers.h"
37 #endif
38
39 struct acpi_rsdp {
40   char signature[8];
41   u8 checksum;
42   char oem_id[6];
43   u8 revision;
44   u32 rsdt_address;
45   struct {
46     u32 length;
47     u64 xsdt_address;
48     u8 ext_checksum;
49     u8 reserved[3];
50   } rsdp20[0];
51 } PCI_PACKED;
52
53 struct acpi_sdt {
54   char signature[4];
55   u32 length;
56   u8 revision;
57   u8 checksum;
58   char oem_id[6];
59   char oem_table_id[8];
60   u32 oem_revision;
61   char asl_compiler_id[4];
62   u32 asl_compiler_revision;
63 } PCI_PACKED;
64
65 struct acpi_rsdt {
66   struct acpi_sdt sdt;
67   u32 sdt_addresses[0];
68 } PCI_PACKED;
69
70 struct acpi_xsdt {
71   struct acpi_sdt sdt;
72   u64 sdt_addresses[0];
73 } PCI_PACKED;
74
75 struct acpi_mcfg {
76   struct acpi_sdt sdt;
77   u64 reserved;
78   struct {
79     u64 address;
80     u16 pci_segment;
81     u8 start_bus_number;
82     u8 end_bus_number;
83     u32 reserved;
84   } allocations[0];
85 } PCI_PACKED;
86
87 struct mmap_cache {
88   void *map;
89   u64 addr;
90   u32 length;
91   int domain;
92   u8 bus;
93   int w;
94 };
95
96 // Back-end data linked to struct pci_access
97 struct ecam_access {
98   struct acpi_mcfg *mcfg;
99   struct mmap_cache *cache;
100   struct physmem *physmem;
101   long pagesize;
102 };
103
104 static unsigned int
105 get_rsdt_addresses_count(struct acpi_rsdt *rsdt)
106 {
107   return (rsdt->sdt.length - ((unsigned char*)&rsdt->sdt_addresses - (unsigned char *)rsdt)) / sizeof(rsdt->sdt_addresses[0]);
108 }
109
110 static unsigned int
111 get_xsdt_addresses_count(struct acpi_xsdt *xsdt)
112 {
113   return (xsdt->sdt.length - ((unsigned char*)&xsdt->sdt_addresses - (unsigned char *)xsdt)) / sizeof(xsdt->sdt_addresses[0]);
114 }
115
116 static unsigned int
117 get_mcfg_allocations_count(struct acpi_mcfg *mcfg)
118 {
119   return (mcfg->sdt.length - ((unsigned char *)&mcfg->allocations - (unsigned char *)mcfg)) / sizeof(mcfg->allocations[0]);
120 }
121
122 static u8
123 calculate_checksum(const u8 *bytes, int len)
124 {
125   u8 checksum = 0;
126
127   while (len-- > 0)
128     checksum -= *(bytes++);
129   return checksum;
130 }
131
132 static struct acpi_sdt *
133 check_and_map_sdt(struct physmem *physmem, long pagesize, u64 addr, const char *signature, void **map_addr, u32 *map_length)
134 {
135   struct acpi_sdt *sdt;
136   char sdt_signature[sizeof(sdt->signature)];
137   u32 length;
138   void *map;
139
140   if (addr + sizeof(*sdt) < addr)
141     return NULL;
142
143   map = physmem_map(physmem, addr & ~(pagesize-1), sizeof(*sdt) + (addr & (pagesize-1)), 0);
144   if (map == (void *)-1)
145     return NULL;
146
147   sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
148   length = sdt->length;
149   memcpy(sdt_signature, sdt->signature, sizeof(sdt->signature));
150
151   physmem_unmap(physmem, map, sizeof(*sdt) + (addr & (pagesize-1)));
152
153   if (memcmp(sdt_signature, signature, sizeof(sdt_signature)) != 0)
154     return NULL;
155   if (length < sizeof(*sdt))
156     return NULL;
157
158   map = physmem_map(physmem, addr & ~(pagesize-1), length + (addr & (pagesize-1)), 0);
159   if (map == (void *)-1)
160     return NULL;
161
162   sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
163
164   if (calculate_checksum((u8 *)sdt, sdt->length) != 0)
165     {
166       physmem_unmap(physmem, map, length + (addr & (pagesize-1)));
167       return NULL;
168     }
169
170   *map_addr = map;
171   *map_length = length + (addr & (pagesize-1));
172   return sdt;
173 }
174
175 static int
176 check_rsdp(struct acpi_rsdp *rsdp)
177 {
178   if (memcmp(rsdp->signature, "RSD PTR ", sizeof(rsdp->signature)) != 0)
179     return 0;
180   if (calculate_checksum((u8 *)rsdp, sizeof(*rsdp)) != 0)
181     return 0;
182   return 1;
183 }
184
185 static int
186 check_and_parse_rsdp(struct physmem *physmem, long pagesize, u64 addr, u32 *rsdt_address, u64 *xsdt_address)
187 {
188   struct acpi_rsdp *rsdp;
189   unsigned char buf[sizeof(*rsdp) + sizeof(*rsdp->rsdp20)];
190   void *map;
191
192   map = physmem_map(physmem, addr & ~(pagesize-1), sizeof(buf) + (addr & (pagesize-1)), 0);
193   if (map == (void *)-1)
194     return 0;
195
196   rsdp = (struct acpi_rsdp *)buf;
197   memcpy(rsdp, (unsigned char *)map + (addr & (pagesize-1)), sizeof(buf));
198
199   physmem_unmap(physmem, map, sizeof(buf));
200
201   if (!check_rsdp(rsdp))
202     return 0;
203
204   *rsdt_address = rsdp->rsdt_address;
205
206   if (rsdp->revision != 0 &&
207       (*rsdp->rsdp20).length == sizeof(*rsdp) + sizeof(*rsdp->rsdp20) &&
208       calculate_checksum((u8 *)rsdp, (*rsdp->rsdp20).length) == 0)
209     *xsdt_address = (*rsdp->rsdp20).xsdt_address;
210   else
211     *xsdt_address = 0;
212
213   return 1;
214 }
215
216 static u64
217 find_rsdp_address(struct pci_access *a, const char *efisystab, int use_bsd UNUSED, int use_x86bios UNUSED)
218 {
219   u64 ullnum;
220 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
221   unsigned long ulnum;
222 #endif
223   char buf[1024];
224   char *endptr;
225   u64 acpi20;
226   u64 acpi;
227 #if defined(__amd64__) || defined(__i386__)
228   struct ecam_access *eacc = a->backend_data;
229   struct physmem *physmem = eacc->physmem;
230   long pagesize = eacc->pagesize;
231   u64 rsdp_addr;
232   u64 addr;
233   void *map;
234   u64 ebda;
235 #endif
236   size_t len;
237   FILE *f;
238
239   if (efisystab[0])
240     {
241       acpi = 0;
242       acpi20 = 0;
243       a->debug("reading EFI system table: %s...", efisystab);
244       f = fopen(efisystab, "r");
245       if (f)
246         {
247           while (fgets(buf, sizeof(buf), f))
248             {
249               len = strlen(buf);
250               while (len > 0 && buf[len-1] == '\n')
251                 buf[--len] = '\0';
252               if (strncmp(buf, "ACPI20=", 7) == 0 && isxdigit(buf[7]))
253                 {
254                   errno = 0;
255                   ullnum = strtoull(buf+7, &endptr, 16);
256                   if (!errno && !*endptr)
257                     acpi20 = ullnum;
258                 }
259               else if (strncmp(buf, "ACPI=", 5) == 0 && isxdigit(buf[5]))
260                 {
261                   errno = 0;
262                   ullnum = strtoull(buf+5, &endptr, 16);
263                   if (!errno && !*endptr)
264                     acpi = ullnum;
265                 }
266             }
267           fclose(f);
268         }
269       else
270         a->debug("opening failed: %s...", strerror(errno));
271
272       if (acpi20)
273         return acpi20;
274       else if (acpi)
275         return acpi;
276     }
277
278 #if defined (__FreeBSD__) || defined (__DragonFly__)
279   if (use_bsd)
280     {
281       /* First try FreeBSD kenv hint.acpi.0.rsdp */
282       a->debug("calling kenv hint.acpi.0.rsdp...");
283       if (kenv(KENV_GET, "hint.acpi.0.rsdp", buf, sizeof(buf)) > 0)
284         {
285           errno = 0;
286           ullnum = strtoull(buf, &endptr, 16);
287           if (!errno && !*endptr)
288             return ullnum;
289         }
290
291       /* Then try FreeBSD sysctl machdep.acpi_root */
292       a->debug("calling sysctl machdep.acpi_root...");
293       len = sizeof(ulnum);
294       if (sysctlbyname("machdep.acpi_root", &ulnum, &len, NULL, 0) == 0)
295         return ulnum;
296     }
297 #endif
298
299 #if defined(__NetBSD__)
300   if (use_bsd)
301     {
302       /* Try NetBSD sysctl hw.acpi.root */
303       a->debug("calling sysctl hw.acpi.root...");
304       len = sizeof(ulnum);
305       if (sysctlbyname("hw.acpi.root", &ulnum, &len, NULL, 0) == 0)
306         return ulnum;
307     }
308 #endif
309
310 #if defined(__amd64__) || defined(__i386__)
311   if (use_x86bios)
312     {
313       rsdp_addr = 0;
314
315       /* Scan first kB of Extended BIOS Data Area */
316       a->debug("reading EBDA location from BDA...");
317       map = physmem_map(physmem, 0, 0x40E + 2, 0);
318       if (map != (void *)-1)
319         {
320           ebda = (u64)physmem_readw((unsigned char *)map + 0x40E) << 4;
321           if (physmem_unmap(physmem, map, 0x40E + 2) != 0)
322             a->debug("unmapping of BDA failed: %s...", strerror(errno));
323           if (ebda >= 0x400)
324             {
325               a->debug("scanning first kB of EBDA at 0x%" PCI_U64_FMT_X "...", ebda);
326               map = physmem_map(physmem, ebda & ~(pagesize-1), 1024 + (ebda & (pagesize-1)), 0);
327               if (map != (void *)-1)
328                 {
329                   for (addr = ebda & (pagesize-1); addr < (ebda & (pagesize-1)) + 1024; addr += 16)
330                     {
331                       if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
332                         {
333                           rsdp_addr = (ebda & ~(pagesize-1)) + addr;
334                           break;
335                         }
336                     }
337                   if (physmem_unmap(physmem, map, 1024 + (ebda & (pagesize-1))) != 0)
338                     a->debug("unmapping of EBDA failed: %s...", strerror(errno));
339                 }
340               else
341                 a->debug("mapping of EBDA failed: %s...", strerror(errno));
342             }
343           else
344             a->debug("EBDA location 0x%" PCI_U64_FMT_X " is insane...", ebda);
345         }
346       else
347         a->debug("mapping of BDA failed: %s...", strerror(errno));
348
349
350       if (rsdp_addr)
351         return rsdp_addr;
352
353       /* Scan the main BIOS area below 1 MB */
354       a->debug("scanning BIOS below 1 MB...");
355       map = physmem_map(physmem, 0xE0000, 0x20000, 0);
356       if (map != (void *)-1)
357         {
358           for (addr = 0x0; addr < 0x20000; addr += 16)
359             {
360               if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
361                 {
362                   rsdp_addr = 0xE0000 + addr;
363                   break;
364                 }
365             }
366           if (physmem_unmap(physmem, map, 0x20000) != 0)
367             a->debug("unmapping of BIOS failed: %s...", strerror(errno));
368         }
369       else
370         a->debug("mapping of BIOS failed: %s...", strerror(errno));
371
372       if (rsdp_addr)
373         return rsdp_addr;
374     }
375 #endif
376
377   return 0;
378 }
379
380 #ifdef PCI_OS_WINDOWS
381 #ifndef ERROR_NOT_FOUND
382 #define ERROR_NOT_FOUND 1168
383 #endif
384 static struct acpi_mcfg *
385 get_system_firmware_table_acpi_mcfg(struct pci_access *a)
386 {
387   UINT (*WINAPI MyGetSystemFirmwareTable)(DWORD FirmwareTableProviderSignature, DWORD FirmwareTableID, PVOID pFirmwareTableBuffer, DWORD BufferSize);
388   struct acpi_mcfg *mcfg;
389   HMODULE kernel32;
390   DWORD error;
391   DWORD size;
392
393   kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
394   if (!kernel32)
395     return NULL;
396
397   /* Function GetSystemFirmwareTable() is available since Windows Vista. */
398   MyGetSystemFirmwareTable = (void *)GetProcAddress(kernel32, "GetSystemFirmwareTable");
399   if (!MyGetSystemFirmwareTable)
400     return NULL;
401
402   /* 0x41435049 = 'ACPI', 0x4746434D = 'MCFG' */
403   size = MyGetSystemFirmwareTable(0x41435049, 0x4746434D, NULL, 0);
404   if (size == 0)
405     {
406       error = GetLastError();
407       if (error == ERROR_INVALID_FUNCTION) /* ACPI is not present. */
408         return NULL;
409       else if (error == ERROR_NOT_FOUND) /* MCFG table is not present. */
410         return NULL;
411       a->debug("Cannot retrieve ACPI MCFG table: %s.\n", win32_strerror(error));
412       return NULL;
413     }
414
415   mcfg = pci_malloc(a, size);
416
417   if (MyGetSystemFirmwareTable(0x41435049, 0x4746434D, mcfg, size) != size)
418     {
419       error = GetLastError();
420       a->debug("Cannot retrieve ACPI MCFG table: %s.\n", win32_strerror(error));
421       pci_mfree(mcfg);
422       return NULL;
423     }
424
425   if (size < sizeof(*mcfg) || size < mcfg->sdt.length || calculate_checksum((u8 *)mcfg, mcfg->sdt.length) != 0)
426     {
427       a->debug("ACPI MCFG table is broken.\n");
428       pci_mfree(mcfg);
429       return NULL;
430     }
431
432   return mcfg;
433 }
434 #endif
435
436 static struct acpi_mcfg *
437 find_mcfg(struct pci_access *a, const char *acpimcfg, const char *efisystab, int use_bsd, int use_x86bios)
438 {
439   struct ecam_access *eacc = a->backend_data;
440   struct physmem *physmem = eacc->physmem;
441   long pagesize = eacc->pagesize;
442   struct acpi_xsdt *xsdt;
443   struct acpi_rsdt *rsdt;
444   struct acpi_mcfg *mcfg;
445   struct acpi_sdt *sdt;
446   unsigned int i, count;
447   u64 rsdp_address;
448   u64 xsdt_address;
449   u32 rsdt_address;
450   void *map_addr;
451   u32 map_length;
452   void *map2_addr;
453   u32 map2_length;
454   long length;
455   FILE *mcfg_file;
456   const char *path;
457 #ifndef PCI_OS_WINDOWS
458   glob_t mcfg_glob;
459   int ret;
460 #endif
461
462   if (acpimcfg[0])
463     {
464 #ifdef PCI_OS_WINDOWS
465       if (strcmp(acpimcfg, "GetSystemFirmwareTable()") == 0)
466         {
467           a->debug("reading acpi mcfg via GetSystemFirmwareTable()...");
468           mcfg = get_system_firmware_table_acpi_mcfg(a);
469           if (mcfg)
470             return mcfg;
471           a->debug("failed...");
472         }
473       else
474         {
475           path = acpimcfg;
476 #else
477       ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
478       if (ret != 0)
479         a->debug("glob(%s) failed: %d...", acpimcfg, ret);
480       else
481         {
482           path = mcfg_glob.gl_pathv[0];
483 #endif
484           a->debug("reading acpi mcfg file: %s...", path);
485           mcfg_file = fopen(path, "rb");
486 #ifndef PCI_OS_WINDOWS
487           globfree(&mcfg_glob);
488 #endif
489           if (mcfg_file)
490             {
491               if (fseek(mcfg_file, 0, SEEK_END) == 0)
492                 length = ftell(mcfg_file);
493               else
494                 length = -1;
495               if (length > 0 && (size_t)length > sizeof(*mcfg))
496                 {
497                   rewind(mcfg_file);
498                   mcfg = pci_malloc(a, length);
499                   if (fread(mcfg, 1, length, mcfg_file) == (size_t)length &&
500                       memcmp(mcfg->sdt.signature, "MCFG", 4) == 0 &&
501                       mcfg->sdt.length <= (size_t)length &&
502                       calculate_checksum((u8 *)mcfg, mcfg->sdt.length) == 0)
503                     {
504                       fclose(mcfg_file);
505                       return mcfg;
506                     }
507                 }
508               fclose(mcfg_file);
509             }
510           a->debug("failed...");
511         }
512     }
513
514   a->debug("searching for ACPI RSDP...");
515   rsdp_address = find_rsdp_address(a, efisystab, use_bsd, use_x86bios);
516   if (!rsdp_address)
517     {
518       a->debug("not found...");
519       return NULL;
520     }
521   a->debug("found at 0x%" PCI_U64_FMT_X "...", rsdp_address);
522
523   if (!check_and_parse_rsdp(physmem, pagesize, rsdp_address, &rsdt_address, &xsdt_address))
524     {
525       a->debug("invalid...");
526       return NULL;
527     }
528
529   mcfg = NULL;
530   a->debug("searching for ACPI MCFG (XSDT=0x%" PCI_U64_FMT_X ", RSDT=0x%lx)...", xsdt_address, (unsigned long)rsdt_address);
531
532   xsdt = xsdt_address ? (struct acpi_xsdt *)check_and_map_sdt(physmem, pagesize, xsdt_address, "XSDT", &map_addr, &map_length) : NULL;
533   if (xsdt)
534     {
535       a->debug("via XSDT...");
536       count = get_xsdt_addresses_count(xsdt);
537       for (i = 0; i < count; i++)
538         {
539           sdt = check_and_map_sdt(physmem, pagesize, xsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
540           if (sdt)
541             {
542               mcfg = pci_malloc(a, sdt->length);
543               memcpy(mcfg, sdt, sdt->length);
544               physmem_unmap(physmem, map2_addr, map2_length);
545               break;
546             }
547         }
548       physmem_unmap(physmem, map_addr, map_length);
549       if (mcfg)
550         {
551           a->debug("found...");
552           return mcfg;
553         }
554     }
555
556   rsdt = (struct acpi_rsdt *)check_and_map_sdt(physmem, pagesize, rsdt_address, "RSDT", &map_addr, &map_length);
557   if (rsdt)
558     {
559       a->debug("via RSDT...");
560       count = get_rsdt_addresses_count(rsdt);
561       for (i = 0; i < count; i++)
562         {
563           sdt = check_and_map_sdt(physmem, pagesize, rsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
564           if (sdt)
565             {
566               mcfg = pci_malloc(a, sdt->length);
567               memcpy(mcfg, sdt, sdt->length);
568               physmem_unmap(physmem, map2_addr, map2_length);
569               break;
570             }
571         }
572       physmem_unmap(physmem, map_addr, map_length);
573       if (mcfg)
574         {
575           a->debug("found...");
576           return mcfg;
577         }
578     }
579
580   a->debug("not found...");
581   return NULL;
582 }
583
584 static void
585 get_mcfg_allocation(struct acpi_mcfg *mcfg, unsigned int i, int *domain, u8 *start_bus, u8 *end_bus, u64 *addr, u32 *length)
586 {
587   int buses = (int)mcfg->allocations[i].end_bus_number - (int)mcfg->allocations[i].start_bus_number + 1;
588
589   if (domain)
590     *domain = mcfg->allocations[i].pci_segment;
591   if (start_bus)
592     *start_bus = mcfg->allocations[i].start_bus_number;
593   if (end_bus)
594     *end_bus = mcfg->allocations[i].end_bus_number;
595   if (addr)
596     *addr = mcfg->allocations[i].address;
597   if (length)
598     *length = (buses > 0) ? (buses * 32 * 8 * 4096) : 0;
599 }
600
601 static int
602 parse_next_addrs(const char *addrs, const char **next, int *domain, u8 *start_bus, u8 *end_bus, u64 *addr, u32 *length)
603 {
604   u64 ullnum;
605   const char *sep1, *sep2;
606   int addr_len;
607   char *endptr;
608   long num;
609   int buses;
610   u64 start_addr;
611
612   if (!*addrs)
613     {
614       if (next)
615         *next = NULL;
616       return 0;
617     }
618
619   endptr = strchr(addrs, ',');
620   if (endptr)
621     addr_len = endptr - addrs;
622   else
623     addr_len = strlen(addrs);
624
625   if (next)
626     *next = endptr ? (endptr+1) : NULL;
627
628   sep1 = memchr(addrs, ':', addr_len);
629   if (!sep1)
630     return 0;
631
632   sep2 = memchr(sep1+1, ':', addr_len - (sep1+1 - addrs));
633   if (!sep2)
634     {
635       sep2 = sep1;
636       sep1 = NULL;
637     }
638
639   if (!sep1)
640     {
641       if (domain)
642         *domain = 0;
643     }
644   else
645     {
646       if (!isxdigit(*addrs))
647         return 0;
648       errno = 0;
649       num = strtol(addrs, &endptr, 16);
650       if (errno || endptr != sep1 || num < 0 || num > INT_MAX)
651         return 0;
652       if (domain)
653         *domain = num;
654     }
655
656   errno = 0;
657   num = strtol(sep1 ? (sep1+1) : addrs, &endptr, 16);
658   if (errno || num < 0 || num > 0xff)
659     return 0;
660   if (start_bus)
661     *start_bus = num;
662
663   buses = -num;
664
665   if (endptr != sep2)
666     {
667       if (*endptr != '-')
668         return 0;
669       errno = 0;
670       num = strtol(endptr+1, &endptr, 16);
671       if (errno || endptr != sep2 || num < 0 || num > 0xff)
672         return 0;
673       buses = num - -buses + 1;
674       if (buses <= 0)
675         return 0;
676       if (end_bus)
677         *end_bus = num;
678     }
679
680   if (!isxdigit(*(sep2+1)))
681     return 0;
682
683   errno = 0;
684   ullnum = strtoull(sep2+1, &endptr, 16);
685   if (errno || (ullnum & 3))
686     return 0;
687   if (addr)
688     *addr = ullnum;
689   start_addr = ullnum;
690
691   if (endptr == addrs + addr_len)
692     {
693       if (buses <= 0)
694         {
695           buses = 0xff - -buses + 1;
696           if (end_bus)
697             *end_bus = 0xff;
698         }
699       if (start_addr + (unsigned)buses * 32 * 8 * 4096 < start_addr)
700         return 0;
701       if (length)
702         *length = buses * 32 * 8 * 4096;
703     }
704   else
705     {
706       if (*endptr != '+' || !isxdigit(*(endptr+1)))
707         return 0;
708       errno = 0;
709       ullnum = strtoull(endptr+1, &endptr, 16);
710       if (errno || endptr != addrs + addr_len || (ullnum & 3) || ullnum > 256 * 32 * 8 * 4096)
711         return 0;
712       if (start_addr + ullnum < start_addr)
713         return 0;
714       if (buses > 0 && ullnum > (unsigned)buses * 32 * 8 * 4096)
715         return 0;
716       if (buses <= 0 && ullnum > (0xff - (unsigned)-buses + 1) * 32 * 8 * 4096)
717         return 0;
718       if (length)
719         *length = ullnum;
720       if (buses <= 0 && end_bus)
721         *end_bus = -buses + (ullnum + 32 * 8 * 4096 - 1) / (32 * 8 * 4096);
722     }
723
724   return 1;
725 }
726
727 static int
728 validate_addrs(const char *addrs)
729 {
730   if (!*addrs)
731     return 1;
732
733   while (addrs)
734     if (!parse_next_addrs(addrs, &addrs, NULL, NULL, NULL, NULL, NULL))
735       return 0;
736
737   return 1;
738 }
739
740 static int
741 calculate_bus_addr(u8 start_bus, u64 start_addr, u32 total_length, u8 bus, u64 *addr, u32 *length)
742 {
743   u32 offset;
744
745   offset = 32*8*4096 * (bus - start_bus);
746   if (offset >= total_length)
747     return 0;
748
749   *addr = start_addr + offset;
750   *length = total_length - offset;
751
752   if (*length > 32*8*4096)
753     *length = 32*8*4096;
754
755   return 1;
756 }
757
758 static int
759 get_bus_addr(struct acpi_mcfg *mcfg, const char *addrs, int domain, u8 bus, u64 *addr, u32 *length)
760 {
761   int cur_domain;
762   u8 start_bus;
763   u8 end_bus;
764   u64 start_addr;
765   u32 total_length;
766   int i, count;
767
768   if (mcfg)
769     {
770       count = get_mcfg_allocations_count(mcfg);
771       for (i = 0; i < count; i++)
772         {
773           get_mcfg_allocation(mcfg, i, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length);
774           if (domain == cur_domain && bus >= start_bus && bus <= end_bus)
775             return calculate_bus_addr(start_bus, start_addr, total_length, bus, addr, length);
776         }
777       return 0;
778     }
779   else
780     {
781       while (addrs)
782         {
783           if (!parse_next_addrs(addrs, &addrs, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length))
784             return 0;
785           if (domain == cur_domain && bus >= start_bus && bus <= end_bus)
786             return calculate_bus_addr(start_bus, start_addr, total_length, bus, addr, length);
787         }
788       return 0;
789     }
790 }
791
792 static void
793 munmap_reg(struct pci_access *a)
794 {
795   struct ecam_access *eacc = a->backend_data;
796   struct mmap_cache *cache = eacc->cache;
797   struct physmem *physmem = eacc->physmem;
798   long pagesize = eacc->pagesize;
799
800   if (!cache)
801     return;
802
803   physmem_unmap(physmem, cache->map, cache->length + (cache->addr & (pagesize-1)));
804   pci_mfree(cache);
805   eacc->cache = NULL;
806 }
807
808 static int
809 mmap_reg(struct pci_access *a, int w, int domain, u8 bus, u8 dev, u8 func, int pos, volatile void **reg)
810 {
811   struct ecam_access *eacc = a->backend_data;
812   struct mmap_cache *cache = eacc->cache;
813   struct physmem *physmem = eacc->physmem;
814   long pagesize = eacc->pagesize;
815   const char *addrs;
816   void *map;
817   u64 addr;
818   u32 length;
819   u32 offset;
820
821   if (cache && cache->domain == domain && cache->bus == bus && !!cache->w == !!w)
822     {
823       map = cache->map;
824       addr = cache->addr;
825       length = cache->length;
826     }
827   else
828     {
829       addrs = pci_get_param(a, "ecam.addrs");
830       if (!get_bus_addr(eacc->mcfg, addrs, domain, bus, &addr, &length))
831         return 0;
832
833       map = physmem_map(physmem, addr & ~(pagesize-1), length + (addr & (pagesize-1)), w);
834       if (map == (void *)-1)
835         return 0;
836
837       if (cache)
838         physmem_unmap(physmem, cache->map, cache->length + (cache->addr & (pagesize-1)));
839       else
840         cache = eacc->cache = pci_malloc(a, sizeof(*cache));
841
842       cache->map = map;
843       cache->addr = addr;
844       cache->length = length;
845       cache->domain = domain;
846       cache->bus = bus;
847       cache->w = w;
848     }
849
850   /*
851    * Enhanced Configuration Access Mechanism (ECAM) offset according to:
852    * PCI Express Base Specification, Revision 5.0, Version 1.0, Section 7.2.2, Table 7-1, p. 677
853    */
854   offset = ((dev & 0x1f) << 15) | ((func & 0x7) << 12) | (pos & 0xfff);
855
856   if (offset + 4 > length)
857     return 0;
858
859   *reg = (unsigned char *)map + (addr & (pagesize-1)) + offset;
860   return 1;
861 }
862
863 static void
864 ecam_config(struct pci_access *a)
865 {
866   physmem_init_config(a);
867   pci_define_param(a, "ecam.acpimcfg", PCI_PATH_ACPI_MCFG, "Path to the ACPI MCFG table");
868   pci_define_param(a, "ecam.efisystab", PCI_PATH_EFI_SYSTAB, "Path to the EFI system table");
869 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
870   pci_define_param(a, "ecam.bsd", "1", "Use BSD kenv or sysctl to find ACPI MCFG table");
871 #endif
872 #if defined(__amd64__) || defined(__i386__)
873   pci_define_param(a, "ecam.x86bios", "1", "Scan x86 BIOS memory for ACPI MCFG table");
874 #endif
875   pci_define_param(a, "ecam.addrs", "", "Physical addresses of memory mapped PCIe ECAM interface"); /* format: [domain:]start_bus[-end_bus]:start_addr[+length],... */
876 }
877
878 static int
879 ecam_detect(struct pci_access *a)
880 {
881   int use_addrs = 1, use_acpimcfg = 1, use_efisystab = 1, use_bsd = 1, use_x86bios = 1;
882   const char *acpimcfg = pci_get_param(a, "ecam.acpimcfg");
883   const char *efisystab = pci_get_param(a, "ecam.efisystab");
884 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
885   const char *bsd = pci_get_param(a, "ecam.bsd");
886 #endif
887 #if defined(__amd64__) || defined(__i386__)
888   const char *x86bios = pci_get_param(a, "ecam.x86bios");
889 #endif
890   const char *addrs = pci_get_param(a, "ecam.addrs");
891   struct ecam_access *eacc;
892 #ifndef PCI_OS_WINDOWS
893   glob_t mcfg_glob;
894   int ret;
895 #endif
896
897   if (!*addrs)
898     {
899       a->debug("ecam.addrs was not specified...");
900       use_addrs = 0;
901     }
902
903   if (acpimcfg[0])
904     {
905 #ifndef PCI_OS_WINDOWS
906       ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
907       if (ret == 0)
908         {
909           if (access(mcfg_glob.gl_pathv[0], R_OK))
910             {
911               a->debug("cannot access acpimcfg: %s: %s...", mcfg_glob.gl_pathv[0], strerror(errno));
912               use_acpimcfg = 0;
913             }
914           globfree(&mcfg_glob);
915         }
916       else
917         {
918           a->debug("glob(%s) failed: %d...", acpimcfg, ret);
919           use_acpimcfg = 0;
920         }
921 #endif
922     }
923   else
924     use_acpimcfg = 0;
925
926 #ifndef PCI_OS_WINDOWS
927   if (!efisystab[0] || access(efisystab, R_OK))
928     {
929       if (efisystab[0])
930         a->debug("cannot access efisystab: %s: %s...", efisystab, strerror(errno));
931       use_efisystab = 0;
932     }
933 #endif
934
935 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
936   if (strcmp(bsd, "0") == 0)
937     {
938       a->debug("not using BSD kenv/sysctl...");
939       use_bsd = 0;
940     }
941 #else
942   use_bsd = 0;
943 #endif
944
945 #if defined(__amd64__) || defined(__i386__)
946   if (strcmp(x86bios, "0") == 0)
947     {
948       a->debug("not using x86 BIOS...");
949       use_x86bios = 0;
950     }
951 #else
952   use_x86bios = 0;
953 #endif
954
955   if (!use_addrs && !use_acpimcfg && !use_efisystab && !use_bsd && !use_x86bios)
956     {
957       a->debug("no ecam source provided");
958       return 0;
959     }
960
961   if (!validate_addrs(addrs))
962     {
963       a->debug("ecam.addrs has invalid format %s", addrs);
964       return 0;
965     }
966
967   if (physmem_access(a, 0))
968     {
969       a->debug("cannot access physical memory: %s", strerror(errno));
970       return 0;
971     }
972
973   if (!use_addrs)
974     {
975       eacc = pci_malloc(a, sizeof(*eacc));
976
977       eacc->physmem = physmem_open(a, a->writeable);
978       if (!eacc->physmem)
979         {
980           a->debug("cannot open physcal memory: %s.", strerror(errno));
981           pci_mfree(eacc);
982           return 0;
983         }
984
985       eacc->pagesize = physmem_get_pagesize(eacc->physmem);
986       if (eacc->pagesize <= 0)
987         {
988           a->debug("Cannot get page size: %s.", strerror(errno));
989           physmem_close(eacc->physmem);
990           pci_mfree(eacc);
991           return 0;
992         }
993
994       eacc->mcfg = NULL;
995       eacc->cache = NULL;
996       a->backend_data = eacc;
997       eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
998       if (!eacc->mcfg)
999         {
1000           physmem_close(eacc->physmem);
1001           pci_mfree(eacc);
1002           a->backend_data = NULL;
1003           return 0;
1004         }
1005     }
1006
1007   if (use_addrs)
1008     a->debug("using with ecam addresses %s", addrs);
1009   else
1010     a->debug("using with%s%s%s%s%s%s", use_acpimcfg ? " acpimcfg=" : "", use_acpimcfg ? acpimcfg : "", use_efisystab ? " efisystab=" : "", use_efisystab ? efisystab : "", use_bsd ? " bsd" : "", use_x86bios ? " x86bios" : "");
1011
1012   return 1;
1013 }
1014
1015 static void
1016 ecam_init(struct pci_access *a)
1017 {
1018   const char *acpimcfg = pci_get_param(a, "ecam.acpimcfg");
1019   const char *efisystab = pci_get_param(a, "ecam.efisystab");
1020 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
1021   const char *bsd = pci_get_param(a, "ecam.bsd");
1022 #endif
1023 #if defined(__amd64__) || defined(__i386__)
1024   const char *x86bios = pci_get_param(a, "ecam.x86bios");
1025 #endif
1026   const char *addrs = pci_get_param(a, "ecam.addrs");
1027   struct physmem *physmem = NULL;
1028   struct ecam_access *eacc = a->backend_data;
1029   long pagesize = 0;
1030   int use_bsd = 0;
1031   int use_x86bios = 0;
1032   int test_domain = 0;
1033   u8 test_bus = 0;
1034   volatile void *test_reg;
1035
1036   if (!validate_addrs(addrs))
1037     a->error("Option ecam.addrs has invalid address format \"%s\".", addrs);
1038
1039   if (!eacc)
1040     {
1041       physmem = physmem_open(a, a->writeable);
1042       if (!physmem)
1043         a->error("Cannot open physcal memory: %s.", strerror(errno));
1044
1045       pagesize = physmem_get_pagesize(physmem);
1046       if (pagesize <= 0)
1047         a->error("Cannot get page size: %s.", strerror(errno));
1048
1049       eacc = pci_malloc(a, sizeof(*eacc));
1050       eacc->mcfg = NULL;
1051       eacc->cache = NULL;
1052       eacc->physmem = physmem;
1053       eacc->pagesize = pagesize;
1054       a->backend_data = eacc;
1055     }
1056
1057   if (!*addrs)
1058     {
1059 #if defined (__FreeBSD__) || defined (__DragonFly__)
1060       if (strcmp(bsd, "0") != 0)
1061         use_bsd = 1;
1062 #endif
1063 #if defined(__amd64__) || defined(__i386__)
1064       if (strcmp(x86bios, "0") != 0)
1065         use_x86bios = 1;
1066 #endif
1067       if (!eacc->mcfg)
1068         eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
1069       if (!eacc->mcfg)
1070         a->error("Option ecam.addrs was not specified and ACPI MCFG table cannot be found.");
1071     }
1072
1073   if (eacc->mcfg)
1074     get_mcfg_allocation(eacc->mcfg, 0, &test_domain, &test_bus, NULL, NULL, NULL);
1075   else
1076     parse_next_addrs(addrs, NULL, &test_domain, &test_bus, NULL, NULL, NULL);
1077
1078   errno = 0;
1079   if (!mmap_reg(a, 0, test_domain, test_bus, 0, 0, 0, &test_reg))
1080     a->error("Cannot map ecam region: %s.", errno ? strerror(errno) : "Unknown error");
1081 }
1082
1083 static void
1084 ecam_cleanup(struct pci_access *a)
1085 {
1086   struct ecam_access *eacc = a->backend_data;
1087
1088   munmap_reg(a);
1089   physmem_close(eacc->physmem);
1090   pci_mfree(eacc->mcfg);
1091   pci_mfree(eacc);
1092   a->backend_data = NULL;
1093 }
1094
1095 static void
1096 ecam_scan(struct pci_access *a)
1097 {
1098   const char *addrs = pci_get_param(a, "ecam.addrs");
1099   struct ecam_access *eacc = a->backend_data;
1100   u32 *segments;
1101   int i, j, count;
1102   int domain;
1103
1104   segments = pci_malloc(a, 0xFFFF/8);
1105   memset(segments, 0, 0xFFFF/8);
1106
1107   if (eacc->mcfg)
1108     {
1109       count = get_mcfg_allocations_count(eacc->mcfg);
1110       for (i = 0; i < count; i++)
1111         segments[eacc->mcfg->allocations[i].pci_segment / 32] |= 1 << (eacc->mcfg->allocations[i].pci_segment % 32);
1112     }
1113   else
1114     {
1115       while (addrs)
1116         {
1117           if (parse_next_addrs(addrs, &addrs, &domain, NULL, NULL, NULL, NULL))
1118             segments[domain / 32] |= 1 << (domain % 32);
1119         }
1120     }
1121
1122   for (i = 0; i < 0xFFFF/32; i++)
1123     {
1124       if (!segments[i])
1125         continue;
1126       for (j = 0; j < 32; j++)
1127         if (segments[i] & (1 << j))
1128           pci_generic_scan_domain(a, 32*i + j);
1129     }
1130
1131   pci_mfree(segments);
1132 }
1133
1134 static int
1135 ecam_read(struct pci_dev *d, int pos, byte *buf, int len)
1136 {
1137   volatile void *reg;
1138
1139   if (pos >= 4096)
1140     return 0;
1141
1142   if (len != 1 && len != 2 && len != 4)
1143     return pci_generic_block_read(d, pos, buf, len);
1144
1145   if (!mmap_reg(d->access, 0, d->domain, d->bus, d->dev, d->func, pos, &reg))
1146     return 0;
1147
1148   switch (len)
1149     {
1150     case 1:
1151       buf[0] = physmem_readb(reg);
1152       break;
1153     case 2:
1154       ((u16 *) buf)[0] = physmem_readw(reg);
1155       break;
1156     case 4:
1157       ((u32 *) buf)[0] = physmem_readl(reg);
1158       break;
1159     }
1160
1161   return 1;
1162 }
1163
1164 static int
1165 ecam_write(struct pci_dev *d, int pos, byte *buf, int len)
1166 {
1167   volatile void *reg;
1168
1169   if (pos >= 4096)
1170     return 0;
1171
1172   if (len != 1 && len != 2 && len != 4)
1173     return pci_generic_block_read(d, pos, buf, len);
1174
1175   if (!mmap_reg(d->access, 1, d->domain, d->bus, d->dev, d->func, pos, &reg))
1176     return 0;
1177
1178   switch (len)
1179     {
1180     case 1:
1181       physmem_writeb(buf[0], reg);
1182       break;
1183     case 2:
1184       physmem_writew(((u16 *) buf)[0], reg);
1185       break;
1186     case 4:
1187       physmem_writel(((u32 *) buf)[0], reg);
1188       break;
1189     }
1190
1191   return 1;
1192 }
1193
1194 struct pci_methods pm_ecam = {
1195   .name = "ecam",
1196   .help = "Raw memory mapped access using PCIe ECAM interface",
1197   .config = ecam_config,
1198   .detect = ecam_detect,
1199   .init = ecam_init,
1200   .cleanup = ecam_cleanup,
1201   .scan = ecam_scan,
1202   .fill_info = pci_generic_fill_info,
1203   .read = ecam_read,
1204   .write = ecam_write,
1205 };