Revert r42105. The rsdt_length field on the rsdp structure we have declared is

actually misleading, since it specifies the length of the xsdt rather than the rsdt. Furthermore, it is only available if the BIOS reports ACPI version 2.0 or greater. Since we don't currently support the XSDT, we can't rely on that field and have to resort to the previous approach of mapping the RSDT header in order to determine the length of the RSDT itself.

Also add validation of the RSDT's checksum so we don't get tripped up by BIOS's with broken tables.

Should fix boot problems that were introduced by r42105.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42118 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent 2011-06-12 01:56:29 +00:00
parent 462d9019a5
commit c4b692da1a

View File

@ -36,27 +36,55 @@ static acpi_descriptor_header* sAcpiRsdt; // System Description Table
static int32 sNumEntries = -1; static int32 sNumEntries = -1;
static status_t
acpi_validate_rsdt(acpi_descriptor_header* rsdt)
{
const char* data = (const char*)rsdt;
unsigned char checksum = 0;
for (uint32 i = 0; i < rsdt->length; i++)
checksum += data[i];
return checksum == 0 ? B_OK : B_BAD_DATA;
}
static status_t static status_t
acpi_check_rsdt(acpi_rsdp* rsdp) acpi_check_rsdt(acpi_rsdp* rsdp)
{ {
TRACE(("acpi: found rsdp at %p oem id: %.6s\n, rev %d", 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%lx\n", rsdp->rsdt_address));
// map and validate the root system description table // map and validate the root system description table
acpi_descriptor_header* rsdt acpi_descriptor_header* rsdt
= (acpi_descriptor_header*)mmu_map_physical_memory( = (acpi_descriptor_header*)mmu_map_physical_memory(
rsdp->rsdt_address, rsdp->rsdt_length, rsdp->rsdt_address, sizeof(acpi_descriptor_header),
kDefaultPageFlags); kDefaultPageFlags);
if (rsdt == NULL if (rsdt == NULL
|| strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) { || strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) {
if (rsdt != NULL) if (rsdt != NULL)
mmu_free(rsdt, rsdp->rsdt_length); mmu_free(rsdt, sizeof(acpi_descriptor_header));
TRACE(("acpi: invalid root system description table\n")); TRACE(("acpi: invalid root system description table\n"));
return B_ERROR; return B_ERROR;
} }
sAcpiRsdt = rsdt; // Map the whole table, not just the header
uint32 length = rsdt->length;
TRACE(("acpi: rsdt length: %lu\n", length));
mmu_free(rsdt, sizeof(acpi_descriptor_header));
sAcpiRsdt = (acpi_descriptor_header*)mmu_map_physical_memory(rsdp->rsdt_address,
length, kDefaultPageFlags);
if (sAcpiRsdt != NULL) {
if (acpi_validate_rsdt(sAcpiRsdt) != B_OK) {
TRACE(("acpi: rsdt failed validation\n"));
mmu_free(sAcpiRsdt, length);
sAcpiRsdt = NULL;
return B_ERROR;
}
} else
return B_ERROR;
return B_OK; return B_OK;
} }