PCI/x86: try ACPI Root pointer from boot loader

to find the RSDP, also try to find it in the EBDA area.
Fix trace build.

Change-Id: I94c3fbec9ea97b9187bf6b2c634298f6ae5b413c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4981
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Jérôme Duval
2022-02-19 19:59:54 +00:00
parent acb424c8b7
commit 50507c9527
@@ -16,15 +16,17 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <boot_item.h>
#include <arch/x86/arch_acpi.h> #include <arch/x86/arch_acpi.h>
//#define TRACE_ACPI //#define TRACE_ACPI
#ifdef TRACE_ACPI #ifdef TRACE_ACPI
# define TRACE(x) dprintf x # define TRACE(x...) dprintf(x)
#else #else
# define TRACE(x) ; # define TRACE(x...) ;
#endif #endif
#define ERROR(x...) dprintf(x)
static struct scan_spots_struct acpi_scan_spots[] = { static struct scan_spots_struct acpi_scan_spots[] = {
{ 0x0, 0x1000, 0x1000 }, { 0x0, 0x1000, 0x1000 },
@@ -48,7 +50,7 @@ acpi_validate_rsdp(acpi_rsdp* rsdp)
checksum += data[i]; checksum += data[i];
if ((checksum & 0xff) != 0) { if ((checksum & 0xff) != 0) {
TRACE(("acpi: rsdp failed basic checksum\n")); TRACE("acpi: rsdp failed basic checksum\n");
return B_BAD_DATA; return B_BAD_DATA;
} }
@@ -60,7 +62,7 @@ acpi_validate_rsdp(acpi_rsdp* rsdp)
} }
if ((checksum & 0xff) != 0) { if ((checksum & 0xff) != 0) {
TRACE(("acpi: rsdp failed extended checksum\n")); ERROR("acpi: rsdp failed extended checksum\n");
return B_BAD_DATA; return B_BAD_DATA;
} }
} }
@@ -89,9 +91,9 @@ acpi_check_rsdt(acpi_rsdp* rsdp)
bool usingXsdt = false; bool usingXsdt = false;
TRACE(("acpi: found rsdp at %p oem id: %.6s, rev %d\n", TRACE("acpi: found rsdp at %p oem id: %.6s, rev %d\n",
rsdp, rsdp->oem_id, rsdp->revision)); rsdp, rsdp->oem_id, rsdp->revision);
TRACE(("acpi: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address)); TRACE("acpi: rsdp points to rsdt at 0x%" B_PRIx32 "\n", rsdp->rsdt_address);
uint32 length = 0; uint32 length = 0;
acpi_descriptor_header* rsdt = NULL; acpi_descriptor_header* rsdt = NULL;
@@ -105,7 +107,7 @@ acpi_check_rsdt(acpi_rsdp* rsdp)
&& strncmp(rsdt->signature, ACPI_XSDT_SIGNATURE, 4) != 0) { && strncmp(rsdt->signature, ACPI_XSDT_SIGNATURE, 4) != 0) {
delete_area(rsdtArea); delete_area(rsdtArea);
rsdt = NULL; rsdt = NULL;
TRACE(("acpi: invalid extended system description table\n")); ERROR("acpi: invalid extended system description table\n");
} else } else
usingXsdt = true; usingXsdt = true;
} }
@@ -118,19 +120,19 @@ acpi_check_rsdt(acpi_rsdp* rsdp)
rsdp->rsdt_address, sizeof(acpi_descriptor_header), rsdp->rsdt_address, sizeof(acpi_descriptor_header),
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&rsdt); B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&rsdt);
if (rsdt == NULL) { if (rsdt == NULL) {
TRACE(("acpi: couldn't map rsdt header\n")); ERROR("acpi: couldn't map rsdt header\n");
return B_ERROR; return B_ERROR;
} }
if (strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) { if (strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) {
delete_area(rsdtArea); delete_area(rsdtArea);
rsdt = NULL; rsdt = NULL;
TRACE(("acpi: invalid root system description table\n")); ERROR("acpi: invalid root system description table\n");
return B_ERROR; return B_ERROR;
} }
length = rsdt->length; length = rsdt->length;
// Map the whole table, not just the header // Map the whole table, not just the header
TRACE(("acpi: rsdt length: %lu\n", length)); TRACE("acpi: rsdt length: %" B_PRIu32 "\n", length);
delete_area(rsdtArea); delete_area(rsdtArea);
rsdtArea = map_physical_memory("rsdt acpi", rsdtArea = map_physical_memory("rsdt acpi",
rsdp->rsdt_address, length, B_ANY_KERNEL_ADDRESS, rsdp->rsdt_address, length, B_ANY_KERNEL_ADDRESS,
@@ -139,7 +141,7 @@ acpi_check_rsdt(acpi_rsdp* rsdp)
if (rsdt != NULL) { if (rsdt != NULL) {
if (acpi_validate_rsdt(rsdt) != B_OK) { if (acpi_validate_rsdt(rsdt) != B_OK) {
TRACE(("acpi: rsdt failed checksum validation\n")); TRACE("acpi: rsdt failed checksum validation\n");
delete_area(rsdtArea); delete_area(rsdtArea);
return B_ERROR; return B_ERROR;
} else { } else {
@@ -147,9 +149,9 @@ acpi_check_rsdt(acpi_rsdp* rsdp)
sAcpiXsdt = rsdt; sAcpiXsdt = rsdt;
else else
sAcpiRsdt = rsdt; sAcpiRsdt = rsdt;
TRACE(("acpi: found valid %s at %p\n", TRACE("acpi: found valid %s at %p\n",
usingXsdt ? ACPI_XSDT_SIGNATURE : ACPI_RSDT_SIGNATURE, usingXsdt ? ACPI_XSDT_SIGNATURE : ACPI_RSDT_SIGNATURE,
rsdt)); rsdt);
} }
} else } else
return B_ERROR; return B_ERROR;
@@ -173,12 +175,12 @@ acpi_find_table_generic(const char* signature, acpi_descriptor_header* acpiSdt)
} }
if (sNumEntries <= 0) { if (sNumEntries <= 0) {
TRACE(("acpi: root system description table is empty\n")); ERROR("acpi: root system description table is empty\n");
return NULL; return NULL;
} }
TRACE(("acpi: searching %ld entries for table '%.4s'\n", sNumEntries, TRACE("acpi: searching %" B_PRId32 " entries for table '%.4s'\n", sNumEntries,
signature)); signature);
PointerType* pointer = (PointerType*)((uint8*)acpiSdt PointerType* pointer = (PointerType*)((uint8*)acpiSdt
+ sizeof(acpi_descriptor_header)); + sizeof(acpi_descriptor_header));
@@ -193,8 +195,8 @@ acpi_find_table_generic(const char* signature, acpi_descriptor_header* acpiSdt)
if (header == NULL if (header == NULL
|| strncmp(header->signature, signature, 4) != 0) { || strncmp(header->signature, signature, 4) != 0) {
// not interesting for us // not interesting for us
TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n", TRACE("acpi: Looking for '%.4s'. Skipping '%.4s'\n",
signature, header != NULL ? header->signature : "null")); signature, header != NULL ? header->signature : "null");
if (header != NULL) { if (header != NULL) {
delete_area(headerArea); delete_area(headerArea);
@@ -204,7 +206,7 @@ acpi_find_table_generic(const char* signature, acpi_descriptor_header* acpiSdt)
continue; continue;
} }
TRACE(("acpi: Found '%.4s' @ %p\n", signature, pointer)); TRACE("acpi: Found '%.4s' @ %p\n", signature, pointer);
break; break;
} }
@@ -238,27 +240,65 @@ acpi_find_table(const char* signature)
void void
acpi_init() acpi_init()
{ {
// Try pointer from boot loader, if any
phys_addr_t* acpiRootPointer = (phys_addr_t*)get_boot_item("ACPI_ROOT_POINTER", NULL);
if (acpiRootPointer != NULL) {
acpi_rsdp* rsdp = NULL;
area_id rsdpArea = map_physical_memory("acpi rsdp",
*acpiRootPointer, B_PAGE_SIZE,
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&rsdp);
if (rsdpArea < B_OK) {
ERROR("acpi_init: couldn't map %s\n", strerror(rsdpArea));
} else {
status_t status = B_ERROR;
if (strncmp((char*)rsdp, ACPI_RSDP_SIGNATURE, 8) == 0)
status = acpi_check_rsdt(rsdp);
delete_area(rsdpArea);
if (status == B_OK)
return;
}
}
// Try to find the ACPI RSDP in EBDA
uint8* start = NULL;
area_id ebdaArea = map_physical_memory("ebda", 0, B_PAGE_SIZE,
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&start);
if (ebdaArea < 0) {
ERROR("acpi_init: couldn't map 1K: %s\n", strerror(ebdaArea));
} else {
phys_addr_t ebda = *(uint16*)&start[0x40e];
ebda <<= 4;
TRACE("acpi_init: 0x%lx\n", ebda);
delete_area(ebdaArea);
if (ebda > 0x400) {
acpi_scan_spots[0].start = ebda;
acpi_scan_spots[0].stop = ebda + 0x1000;
acpi_scan_spots[0].length = 0x1000;
// will be scanned first
}
}
// Try to find the ACPI RSDP. // Try to find the ACPI RSDP.
for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) { for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) {
acpi_rsdp* rsdp = NULL; acpi_rsdp* rsdp = NULL;
TRACE(("acpi_init: entry base 0x%lx, limit 0x%lx\n", TRACE("acpi_init: entry base 0x%" B_PRIx32 ", limit 0x%" B_PRIx32 "\n",
acpi_scan_spots[i].start, acpi_scan_spots[i].stop)); acpi_scan_spots[i].start, acpi_scan_spots[i].stop);
char* start = NULL; char* start = NULL;
area_id rsdpArea = map_physical_memory("acpi rsdp", area_id rsdpArea = map_physical_memory("acpi rsdp",
acpi_scan_spots[i].start, acpi_scan_spots[i].length, acpi_scan_spots[i].start, acpi_scan_spots[i].length,
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&start); B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&start);
if (rsdpArea < B_OK) { if (rsdpArea < B_OK) {
TRACE(("acpi_init: couldn't map %s\n", strerror(rsdpArea))); ERROR("acpi_init: couldn't map %s\n", strerror(rsdpArea));
break; break;
} }
for (char *pointer = start; for (char *pointer = start;
(addr_t)pointer < (addr_t)start + acpi_scan_spots[i].length; (addr_t)pointer < (addr_t)start + acpi_scan_spots[i].length;
pointer += 16) { pointer += 16) {
if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) { if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) {
TRACE(("acpi_init: found ACPI RSDP signature at %p\n", TRACE("acpi_init: found ACPI RSDP signature at %p\n",
pointer)); pointer);
rsdp = (acpi_rsdp*)pointer; rsdp = (acpi_rsdp*)pointer;
} }
} }