The ACPI RSDP table has a checksum and an extended checksum. At the moment 
if the ACPI rvision is zero, the checksum is checked and if the revision 
is more recent only the extended checksum field is checked.

However the spec says that the checksum field "...must sum to zero." At 
the moment this isn't being checked if the revision is >= 2. I checked 
intel's acpica implementation and it looks this is what they're doing 
too.

Patch below is for i386 and amd64. I tested on i386.

ok?

Index: i386//i386/acpi_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/arch/i386/i386/acpi_machdep.c,v
retrieving revision 1.53
diff -u -p -u -r1.53 acpi_machdep.c
--- i386//i386/acpi_machdep.c   25 Apr 2014 14:37:06 -0000      1.53
+++ i386//i386/acpi_machdep.c   23 May 2014 01:37:15 -0000
@@ -112,22 +112,23 @@ acpi_scan(struct acpi_mem_map *handle, p
 
        if (acpi_map(pa, len, handle))
                return (NULL);
-       for (ptr = handle->va, i = 0;
-            i < len;
-            ptr += 16, i += 16)
-               if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0) {
-                       rsdp = (struct acpi_rsdp1 *)ptr;
-                       /*
-                        * Only checksum whichever portion of the
-                        * RSDP that is actually present
-                        */
-                       if (rsdp->revision == 0 &&
-                           acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) == 0)
+       for (ptr = handle->va, i = 0; i < len; ptr += 16, i += 16) {
+               /* is there a valid signature? */
+               if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1))
+                       continue;
+
+               /* is the checksum valid? */
+               if (acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) != 0)
+                       continue;
+
+               /* check the extended checksum as needed */
+               rsdp = (struct acpi_rsdp1 *)ptr;
+               if (rsdp->revision == 0)
+                       return (ptr);
+               else if (rsdp->revision >= 2 && rsdp->revision <= 4)
+                       if (acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
                                return (ptr);
-                       else if (rsdp->revision >= 2 && rsdp->revision <= 4 &&
-                           acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
-                               return (ptr);
-               }
+       }
        acpi_unmap(handle);
 
        return (NULL);
Index: amd64//amd64/acpi_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/arch/amd64/amd64/acpi_machdep.c,v
retrieving revision 1.60
diff -u -p -u -r1.60 acpi_machdep.c
--- amd64//amd64/acpi_machdep.c 25 Apr 2014 14:37:06 -0000      1.60
+++ amd64//amd64/acpi_machdep.c 23 May 2014 01:37:45 -0000
@@ -106,22 +106,23 @@ acpi_scan(struct acpi_mem_map *handle, p
 
        if (acpi_map(pa, len, handle))
                return (NULL);
-       for (ptr = handle->va, i = 0;
-            i < len;
-            ptr += 16, i += 16)
-               if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0) {
-                       rsdp = (struct acpi_rsdp1 *)ptr;
-                       /*
-                        * Only checksum whichever portion of the
-                        * RSDP that is actually present
-                        */
-                       if (rsdp->revision == 0 &&
-                           acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) == 0)
+       for (ptr = handle->va, i = 0; i < len; ptr += 16, i += 16) {
+               /* is there a valid signature? */
+               if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1))
+                       continue;
+
+               /* is the checksum valid? */
+               if (acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) != 0)
+                       continue;
+
+               /* check the extended checksum as needed */
+               rsdp = (struct acpi_rsdp1 *)ptr;
+               if (rsdp->revision == 0)
+                       return (ptr);
+               else if (rsdp->revision >= 2 && rsdp->revision <= 4)
+                       if (acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
                                return (ptr);
-                       else if (rsdp->revision >= 2 && rsdp->revision <= 4 &&
-                           acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
-                               return (ptr);
-               }
+       }
        acpi_unmap(handle);
 
        return (NULL);

Reply via email to