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:
parent
462d9019a5
commit
c4b692da1a
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user