From c4b692da1a8d2839b26596c54d0a0833dc15f7c2 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 12 Jun 2011 01:56:29 +0000 Subject: [PATCH] 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 --- src/system/boot/platform/bios_ia32/acpi.cpp | 38 ++++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/acpi.cpp b/src/system/boot/platform/bios_ia32/acpi.cpp index 403a69d4ea..f58ac13c3f 100644 --- a/src/system/boot/platform/bios_ia32/acpi.cpp +++ b/src/system/boot/platform/bios_ia32/acpi.cpp @@ -36,28 +36,56 @@ static acpi_descriptor_header* sAcpiRsdt; // System Description Table 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 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)); TRACE(("acpi: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address)); // map and validate the root system description table acpi_descriptor_header* rsdt = (acpi_descriptor_header*)mmu_map_physical_memory( - rsdp->rsdt_address, rsdp->rsdt_length, + rsdp->rsdt_address, sizeof(acpi_descriptor_header), kDefaultPageFlags); if (rsdt == NULL || strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) { if (rsdt != NULL) - mmu_free(rsdt, rsdp->rsdt_length); + mmu_free(rsdt, sizeof(acpi_descriptor_header)); TRACE(("acpi: invalid root system description table\n")); 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; }