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:
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user