#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;
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;
a->backend_data = NULL;
return 0;
}
- pci_mfree(eacc->mcfg);
- physmem_close(eacc->physmem);
- pci_mfree(eacc);
- a->backend_data = NULL;
}
if (use_addrs)
#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;
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));
+ 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));
+ 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;
+ eacc = pci_malloc(a, sizeof(*eacc));
+ eacc->mcfg = NULL;
+ eacc->cache = NULL;
+ eacc->physmem = physmem;
+ eacc->pagesize = pagesize;
+ a->backend_data = eacc;
+ }
if (!*addrs)
{
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.");
}
}
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,
};