]> mj.ucw.cz Git - pciutils.git/blobdiff - lib/ecam.c
RCD: Cleanup
[pciutils.git] / lib / ecam.c
index cb479c6b8fc833aa954287e0955b08fdcc7a0ac9..fdeec0786f6978891564f8d6db0e303894e2c8ed 100644 (file)
@@ -221,9 +221,11 @@ find_rsdp_address(struct pci_access *a, const char *efisystab, int use_bsd UNUSE
 #if defined(__amd64__) || defined(__i386__)
   struct ecam_access *eacc = a->backend_data;
   struct physmem *physmem = eacc->physmem;
+  long pagesize = eacc->pagesize;
   u64 rsdp_addr;
   u64 addr;
   void *map;
+  u64 ebda;
 #endif
   size_t len;
   FILE *f;
@@ -305,23 +307,39 @@ find_rsdp_address(struct pci_access *a, const char *efisystab, int use_bsd UNUSE
       rsdp_addr = 0;
 
       /* Scan first kB of Extended BIOS Data Area */
-      a->debug("scanning first kB of EBDA...");
-      map = physmem_map(physmem, 0, 0x40E + 1024, 0);
+      a->debug("reading EBDA location from BDA...");
+      map = physmem_map(physmem, 0, 0x40E + 2, 0);
       if (map != (void *)-1)
         {
-          for (addr = 0x40E; addr < 0x40E + 1024; addr += 16)
+          ebda = (u64)physmem_readw((unsigned char *)map + 0x40E) << 4;
+          if (physmem_unmap(physmem, map, 0x40E + 2) != 0)
+            a->debug("unmapping of BDA failed: %s...", strerror(errno));
+          if (ebda >= 0x400)
             {
-              if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
+              a->debug("scanning first kB of EBDA at 0x%" PCI_U64_FMT_X "...", ebda);
+              map = physmem_map(physmem, ebda & ~(pagesize-1), 1024 + (ebda & (pagesize-1)), 0);
+              if (map != (void *)-1)
                 {
-                  rsdp_addr = addr;
-                  break;
+                  for (addr = ebda & (pagesize-1); addr < (ebda & (pagesize-1)) + 1024; addr += 16)
+                    {
+                      if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
+                        {
+                          rsdp_addr = (ebda & ~(pagesize-1)) + addr;
+                          break;
+                        }
+                    }
+                  if (physmem_unmap(physmem, map, 1024 + (ebda & (pagesize-1))) != 0)
+                    a->debug("unmapping of EBDA failed: %s...", strerror(errno));
                 }
+              else
+                a->debug("mapping of EBDA failed: %s...", strerror(errno));
             }
-          if (physmem_unmap(physmem, map, 0x40E + 1024) != 0)
-            a->debug("unmapping of EBDA failed: %s...", strerror(errno));
+          else
+            a->debug("EBDA location 0x%" PCI_U64_FMT_X " is insane...", ebda);
         }
       else
-        a->debug("mapping of EBDA failed: %s...", strerror(errno));
+        a->debug("mapping of BDA failed: %s...", strerror(errno));
+
 
       if (rsdp_addr)
         return rsdp_addr;
@@ -790,6 +808,7 @@ ecam_detect(struct pci_access *a)
   const char *x86bios = pci_get_param(a, "ecam.x86bios");
 #endif
   const char *addrs = pci_get_param(a, "ecam.addrs");
+  struct ecam_access *eacc;
   glob_t mcfg_glob;
   int ret;
 
@@ -865,6 +884,40 @@ ecam_detect(struct pci_access *a)
       return 0;
     }
 
+  if (!use_addrs)
+    {
+      eacc = pci_malloc(a, sizeof(*eacc));
+
+      eacc->physmem = physmem_open(a, a->writeable);
+      if (!eacc->physmem)
+        {
+          a->debug("cannot open physcal memory: %s.", strerror(errno));
+          pci_mfree(eacc);
+          return 0;
+        }
+
+      eacc->pagesize = physmem_get_pagesize(eacc->physmem);
+      if (eacc->pagesize <= 0)
+        {
+          a->debug("Cannot get page size: %s.", strerror(errno));
+          physmem_close(eacc->physmem);
+          pci_mfree(eacc);
+          return 0;
+        }
+
+      eacc->mcfg = NULL;
+      eacc->cache = NULL;
+      a->backend_data = eacc;
+      eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
+      if (!eacc->mcfg)
+        {
+          physmem_close(eacc->physmem);
+          pci_mfree(eacc);
+          a->backend_data = NULL;
+          return 0;
+        }
+    }
+
   if (use_addrs)
     a->debug("using with ecam addresses %s", addrs);
   else
@@ -886,7 +939,7 @@ ecam_init(struct pci_access *a)
 #endif
   const char *addrs = pci_get_param(a, "ecam.addrs");
   struct physmem *physmem = NULL;
-  struct ecam_access *eacc = NULL;
+  struct ecam_access *eacc = a->backend_data;
   long pagesize = 0;
   int use_bsd = 0;
   int use_x86bios = 0;
@@ -897,20 +950,23 @@ ecam_init(struct pci_access *a)
   if (!validate_addrs(addrs))
     a->error("Option ecam.addrs has invalid address format \"%s\".", addrs);
 
-  physmem = physmem_open(a, a->writeable);
-  if (!physmem)
-    a->error("Cannot open physcal memory: %s.", strerror(errno));
-
-  pagesize = physmem_get_pagesize(physmem);
-  if (pagesize <= 0)
-    a->error("Cannot get page size: %s.", strerror(errno));
-
-  eacc = pci_malloc(a, sizeof(*eacc));
-  eacc->mcfg = NULL;
-  eacc->cache = NULL;
-  eacc->physmem = physmem;
-  eacc->pagesize = pagesize;
-  a->backend_data = eacc;
+  if (!eacc)
+    {
+      physmem = physmem_open(a, a->writeable);
+      if (!physmem)
+        a->error("Cannot open physcal memory: %s.", strerror(errno));
+
+      pagesize = physmem_get_pagesize(physmem);
+      if (pagesize <= 0)
+        a->error("Cannot get page size: %s.", strerror(errno));
+
+      eacc = pci_malloc(a, sizeof(*eacc));
+      eacc->mcfg = NULL;
+      eacc->cache = NULL;
+      eacc->physmem = physmem;
+      eacc->pagesize = pagesize;
+      a->backend_data = eacc;
+    }
 
   if (!*addrs)
     {
@@ -922,7 +978,8 @@ ecam_init(struct pci_access *a)
       if (strcmp(x86bios, "0") != 0)
         use_x86bios = 1;
 #endif
-      eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
+      if (!eacc->mcfg)
+        eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
       if (!eacc->mcfg)
         a->error("Option ecam.addrs was not specified and ACPI MCFG table cannot be found.");
     }
@@ -1049,17 +1106,14 @@ ecam_write(struct pci_dev *d, int pos, byte *buf, int len)
 }
 
 struct pci_methods pm_ecam = {
-  "ecam",
-  "Raw memory mapped access using PCIe ECAM interface",
-  ecam_config,
-  ecam_detect,
-  ecam_init,
-  ecam_cleanup,
-  ecam_scan,
-  pci_generic_fill_info,
-  ecam_read,
-  ecam_write,
-  NULL,                                        /* read_vpd */
-  NULL,                                        /* init_dev */
-  NULL                                 /* cleanup_dev */
+  .name = "ecam",
+  .help = "Raw memory mapped access using PCIe ECAM interface",
+  .config = ecam_config,
+  .detect = ecam_detect,
+  .init = ecam_init,
+  .cleanup = ecam_cleanup,
+  .scan = ecam_scan,
+  .fill_info = pci_generic_fill_info,
+  .read = ecam_read,
+  .write = ecam_write,
 };