[syslinux:master] ACPI: Improving tables detection

syslinux-bot for Erwan Velu erwanaliasr1 at gmail.com
Sun Feb 6 14:07:49 PST 2011


Commit-ID:  e5aa41f5789f760b9056908633664ff9d57c4893
Gitweb:     http://syslinux.zytor.com/commit/e5aa41f5789f760b9056908633664ff9d57c4893
Author:     Erwan Velu <erwanaliasr1 at gmail.com>
AuthorDate: Mon, 31 Jan 2011 16:32:25 +0100
Committer:  Erwan Velu <erwanaliasr1 at gmail.com>
CommitDate: Mon, 31 Jan 2011 16:32:25 +0100

ACPI: Improving tables detection

In some conditions, XSDT pointer could be null. In such conditions, we
have to parse tables pointed by RSDP.

This patch remove the table parsing from xsdt to acpi.c.
If the XSDT detection fails, let's switch back to the RSDP entries.

This was the case under KVM whereas VirtualBox features an XSDT.


---
 com32/gplinclude/acpi/acpi.h |    1 +
 com32/gpllib/acpi/acpi.c     |  136 ++++++++++++++++++++++++++++++++++++++++-
 com32/gpllib/acpi/rsdp.c     |    3 +
 com32/gpllib/acpi/rsdt.c     |   23 ++++++--
 com32/gpllib/acpi/xsdt.c     |  130 +++-------------------------------------
 5 files changed, 163 insertions(+), 130 deletions(-)

diff --git a/com32/gplinclude/acpi/acpi.h b/com32/gplinclude/acpi/acpi.h
index db4adc7..1d9a5a0 100644
--- a/com32/gplinclude/acpi/acpi.h
+++ b/com32/gplinclude/acpi/acpi.h
@@ -83,4 +83,5 @@ int parse_xsdt(s_acpi * acpi);
 void parse_madt(s_acpi * acpi);
 int search_rsdp(s_acpi *acpi);
 void get_acpi_description_header(uint8_t *q, s_acpi_description_header * adh);
+bool parse_header(uint64_t *address, s_acpi *acpi);
 #endif
diff --git a/com32/gpllib/acpi/acpi.c b/com32/gpllib/acpi/acpi.c
index b75647a..b763e0b 100644
--- a/com32/gpllib/acpi/acpi.c
+++ b/com32/gpllib/acpi/acpi.c
@@ -27,6 +27,7 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <memory.h>
 #include "acpi/acpi.h"
@@ -53,12 +54,15 @@ int parse_acpi(s_acpi * acpi)
     if ((ret_val = search_rsdp(acpi)) != RSDP_TABLE_FOUND)
 	return ret_val;
 
-    /* Let's seach for RSDT table 
+    /* Let's seach for RSDT table
      * That's not a big deal not having it, XSDT is far more relevant */
     parse_rsdt(&acpi->rsdt);
-    if ((ret_val = parse_xsdt(acpi)) != XSDT_TABLE_FOUND)
-	return ret_val;
-
+    if (parse_xsdt(acpi) != XSDT_TABLE_FOUND) {
+	    DEBUG_PRINT(("XSDT Detection failed\n"));
+	    for (int table=0; table <acpi->rsdt.entry_count; table++) {
+		parse_header((uint64_t *)acpi->rsdt.entry[table],acpi);
+	    }
+    }
     return ACPI_FOUND;
 }
 
@@ -75,3 +79,127 @@ void get_acpi_description_header(uint8_t * q, s_acpi_description_header * adh)
     cp_struct(&adh->creator_revision);
     DEBUG_PRINT(("acpi_header at %p = %s | %s | %s\n", q, adh->signature,adh->oem_id, adh->creator_id ));
 }
+
+bool parse_header(uint64_t *address, s_acpi *acpi) {
+	    s_acpi_description_header adh;
+	    memset(&adh, 0, sizeof(adh));
+
+	    get_acpi_description_header((uint8_t *)address, &adh);
+
+	    /* Trying to determine the pointed table */
+	    /* Looking for FADT */
+	    if (memcmp(adh.signature, FACP, sizeof(FACP) - 1) == 0) {
+		DEBUG_PRINT(("FACP table found\n"));
+		s_fadt *f = &acpi->fadt;
+		s_facs *fa = &acpi->facs;
+		s_dsdt *d = &acpi->dsdt;
+		/* This structure is valid, let's fill it */
+		f->valid = true;
+		f->address = address;
+		memcpy(&f->header, &adh, sizeof(adh));
+		parse_fadt(f);
+
+		/* FACS wasn't already detected
+		 * FADT points to it, let's try to detect it */
+		if (fa->valid == false) {
+		    fa->address = (uint64_t *)f->x_firmware_ctrl;
+		    parse_facs(fa);
+		    if (fa->valid == false) {
+			/* Let's try again */
+			fa->address = (uint64_t *)f->firmware_ctrl;
+			parse_facs(fa);
+		    }
+		}
+
+		/* DSDT wasn't already detected
+		 * FADT points to it, let's try to detect it */
+		if (d->valid == false) {
+		    s_acpi_description_header new_adh;
+		    get_acpi_description_header((uint8_t *)f->x_dsdt,
+						&new_adh);
+		    if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
+			DEBUG_PRINT(("DSDT table found via x_dsdt\n"));
+			d->valid = true;
+			d->address = (uint64_t *)f->x_dsdt;
+			memcpy(&d->header, &new_adh, sizeof(new_adh));
+			parse_dsdt(d);
+		    } else {
+			/* Let's try again */
+			get_acpi_description_header((uint8_t *)f->dsdt_address,
+						    &new_adh);
+			if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) ==
+			    0) {
+			    DEBUG_PRINT(("DSDT table found via dsdt_address\n"));
+			    d->valid = true;
+			    d->address = (uint64_t *)f->dsdt_address;
+			    memcpy(&d->header, &new_adh, sizeof(new_adh));
+			    parse_dsdt(d);
+			}
+		    }
+		}
+	    } /* Looking for MADT */
+	    else if (memcmp(adh.signature, APIC, sizeof(APIC) - 1) == 0) {
+		DEBUG_PRINT(("MADT table found\n"));
+		s_madt *m = &acpi->madt;
+		/* This structure is valid, let's fill it */
+		m->valid = true;
+		m->address =address;
+		memcpy(&m->header, &adh, sizeof(adh));
+		parse_madt(acpi);
+	    } else if (memcmp(adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
+		DEBUG_PRINT(("DSDT table found\n"));
+		s_dsdt *d = &acpi->dsdt;
+		/* This structure is valid, let's fill it */
+		d->valid = true;
+		d->address = address;
+		memcpy(&d->header, &adh, sizeof(adh));
+		parse_dsdt(d);
+		/* PSDT have to be considered as SSDT. Intel ACPI Spec @ 5.2.11.3 */
+	    } else if ((memcmp(adh.signature, SSDT, sizeof(SSDT) - 1) == 0)
+		       || (memcmp(adh.signature, PSDT, sizeof(PSDT) - 1) == 0)) {
+		
+		DEBUG_PRINT(("SSDT table found with %s \n",adh.signature));
+
+		if ((acpi->ssdt_count >= MAX_SSDT - 1))
+		    return false;
+
+		/* We can have many SSDT, so let's allocate a new one */
+		if ((acpi->ssdt[acpi->ssdt_count] =
+		     malloc(sizeof(s_ssdt))) == NULL)
+		    return false;
+		s_ssdt *s = acpi->ssdt[acpi->ssdt_count];
+
+		/* This structure is valid, let's fill it */
+		s->valid = true;
+		s->address = address;
+		memcpy(&s->header, &adh, sizeof(adh));
+
+		/* Searching how much definition blocks we must copy */
+		uint32_t definition_block_size = adh.length - ACPI_HEADER_SIZE;
+		if ((s->definition_block =
+		     malloc(definition_block_size)) != NULL) {
+		    memcpy(s->definition_block,
+			   (s->address + ACPI_HEADER_SIZE),
+			   definition_block_size);
+		}
+		/* Increment the number of ssdt we have */
+		acpi->ssdt_count++;
+	    } else if (memcmp(adh.signature, SBST, sizeof(SBST) - 1) == 0) {
+		DEBUG_PRINT(("SBST table found\n"));
+		s_sbst *s = &acpi->sbst;
+		/* This structure is valid, let's fill it */
+		s->valid = true;
+		s->address = address;
+		memcpy(&s->header, &adh, sizeof(adh));
+		parse_sbst(s);
+	    } else if (memcmp(adh.signature, ECDT, sizeof(ECDT) - 1) == 0) {
+		DEBUG_PRINT(("ECDT table found\n"));
+		s_ecdt *e = &acpi->ecdt;
+		/* This structure is valid, let's fill it */
+		e->valid = true;
+		e->address = address;
+		memcpy(&e->header, &adh, sizeof(adh));
+		parse_ecdt(e);
+	    }
+	    return true;
+}
diff --git a/com32/gpllib/acpi/rsdp.c b/com32/gpllib/acpi/rsdp.c
index ef5e7dc..72ea56b 100644
--- a/com32/gpllib/acpi/rsdp.c
+++ b/com32/gpllib/acpi/rsdp.c
@@ -27,6 +27,7 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <memory.h>
 #include <dprintf.h>
@@ -55,6 +56,8 @@ int search_rsdp(s_acpi * acpi)
 	    q += 3;		/* reserved field */
 	    acpi->rsdt.address = r->rsdt_address;
 	    acpi->xsdt.address = r->xsdt_address;
+	    DEBUG_PRINT(("RSDT should be at %p\n",r->rsdt_address));
+	    DEBUG_PRINT(("XSDT should be at %p\n",r->xsdt_address));
 	    return RSDP_TABLE_FOUND;
 	}
     }
diff --git a/com32/gpllib/acpi/rsdt.c b/com32/gpllib/acpi/rsdt.c
index d93a8c2..c952250 100644
--- a/com32/gpllib/acpi/rsdt.c
+++ b/com32/gpllib/acpi/rsdt.c
@@ -27,6 +27,7 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <memory.h>
 #include <dprintf.h>
@@ -40,16 +41,28 @@ int parse_rsdt(s_rsdt *r)
     /* Let's start for the base address */
     q = r->address;
 
+    DEBUG_PRINT(("Searching for RSDT at %p\n",q));
     /* Searching for MADT with APIC signature */
     if (memcmp(q, RSDT, sizeof(RSDT)-1) == 0) {
-	DEBUG_PRINT(("RSDT table found\n"));
+//        DEBUG_PRINT(("RSDT : %c %c %c %c\n",q[0], q[1], q[2], q[3]));
 	r->valid = true;
+	DEBUG_PRINT(("Before \n"));
 	get_acpi_description_header(q, &r->header);
+	DEBUG_PRINT(("RSDT table at %p found with %d bytes long with %d items\n",r->address, r->header.length,(r->header.length-ACPI_HEADER_SIZE)/4));
 
-	uint8_t *p = NULL;
-	for (p = (r->address + ACPI_HEADER_SIZE);
-	     p < (r->address + r->header.length); p++) {
-	    r->entry[r->entry_count] = p;
+	uint32_t *start = (uint32_t *)r->address;
+	start += (ACPI_HEADER_SIZE / 4);
+	uint32_t *max = (uint32_t *)r->address;
+	max += (r->header.length / 4);
+	DEBUG_PRINT(("Searching starting at %p till %p\n",start,max));
+	uint32_t *p;
+	for (p = start ; p < max; p++) {
+            /* Let's grab the pointed table header */
+            char address[16] = { 0 };
+            sprintf(address, "%x", *p);
+            uint32_t *pointed_address = (uint32_t *)strtoul(address, NULL, 16);
+	    r->entry[r->entry_count] = (uint8_t *)pointed_address;
+	    DEBUG_PRINT(("%d : %p\n",r->entry_count, r->entry[r->entry_count]));
 	    r->entry_count++;
 	}
 	return RSDT_TABLE_FOUND;
diff --git a/com32/gpllib/acpi/xsdt.c b/com32/gpllib/acpi/xsdt.c
index f1a6e21..208abc6 100644
--- a/com32/gpllib/acpi/xsdt.c
+++ b/com32/gpllib/acpi/xsdt.c
@@ -40,6 +40,13 @@ int parse_xsdt(s_acpi * acpi)
     /* Let's start for the base address */
     q = acpi->xsdt.address;
 
+    /* If address is null return an error */
+    if (q == 0 ) {
+	DEBUG_PRINT(("XSDT is null, exiting\n"));
+    	return -XSDT_TABLE_FOUND;
+    }
+
+    DEBUG_PRINT(("Searching XSDT at %p",q));
     /* Searching for MADT with APIC signature */
     if (memcmp(q, XSDT, sizeof(XSDT) - 1) == 0) {
 	s_xsdt *x = &acpi->xsdt;
@@ -53,9 +60,6 @@ int parse_xsdt(s_acpi * acpi)
 	for (p = ((uint64_t *)(x->address + ACPI_HEADER_SIZE));
 	     p < ((uint64_t *)(x->address + x->header.length)); p++) {
 	    DEBUG_PRINT((" Looking for HEADER at %p = %x\n",p,*p));
-	    
-	    s_acpi_description_header adh;
-	    memset(&adh, 0, sizeof(adh));
 
 	    /* Let's grab the pointed table header */
 	    char address[16] = { 0 };
@@ -63,127 +67,11 @@ int parse_xsdt(s_acpi * acpi)
 	    uint64_t *pointed_address = (uint64_t *)strtoul(address, NULL, 16);
 
 	    x->entry[x->entry_count] = pointed_address;
-	    get_acpi_description_header((uint8_t *)pointed_address, &adh);
-
-	    /* Trying to determine the pointed table */
-	    /* Looking for FADT */
-	    if (memcmp(adh.signature, FACP, sizeof(FACP) - 1) == 0) {
-		DEBUG_PRINT(("FACP table found\n"));
-		s_fadt *f = &acpi->fadt;
-		s_facs *fa = &acpi->facs;
-		s_dsdt *d = &acpi->dsdt;
-		/* This structure is valid, let's fill it */
-		f->valid = true;
-		f->address = pointed_address;
-		memcpy(&f->header, &adh, sizeof(adh));
-		parse_fadt(f);
-
-		/* FACS wasn't already detected
-		 * FADT points to it, let's try to detect it */
-		if (fa->valid == false) {
-		    fa->address = (uint64_t *)f->x_firmware_ctrl;
-		    parse_facs(fa);
-		    if (fa->valid == false) {
-			/* Let's try again */
-			fa->address = (uint64_t *)f->firmware_ctrl;
-			parse_facs(fa);
-		    }
-		}
-
-		/* DSDT wasn't already detected
-		 * FADT points to it, let's try to detect it */
-		if (d->valid == false) {
-		    s_acpi_description_header new_adh;
-		    get_acpi_description_header((uint8_t *)f->x_dsdt,
-						&new_adh);
-		    if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
-			DEBUG_PRINT(("DSDT table found via x_dsdt\n"));
-			d->valid = true;
-			d->address = (uint64_t *)f->x_dsdt;
-			memcpy(&d->header, &new_adh, sizeof(new_adh));
-			parse_dsdt(d);
-		    } else {
-			/* Let's try again */
-			get_acpi_description_header((uint8_t *)f->dsdt_address,
-						    &new_adh);
-			if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) ==
-			    0) {
-			    DEBUG_PRINT(("DSDT table found via dsdt_address\n"));
-			    d->valid = true;
-			    d->address = (uint64_t *)f->dsdt_address;
-			    memcpy(&d->header, &new_adh, sizeof(new_adh));
-			    parse_dsdt(d);
-			}
-		    }
-		}
-	    } /* Looking for MADT */
-	    else if (memcmp(adh.signature, APIC, sizeof(APIC) - 1) == 0) {
-		DEBUG_PRINT(("MADT table found\n"));
-		s_madt *m = &acpi->madt;
-		/* This structure is valid, let's fill it */
-		m->valid = true;
-		m->address = pointed_address;
-		memcpy(&m->header, &adh, sizeof(adh));
-		parse_madt(acpi);
-	    } else if (memcmp(adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
-		DEBUG_PRINT(("DSDT table found\n"));
-		s_dsdt *d = &acpi->dsdt;
-		/* This structure is valid, let's fill it */
-		d->valid = true;
-		d->address = pointed_address;
-		memcpy(&d->header, &adh, sizeof(adh));
-		parse_dsdt(d);
-		/* PSDT have to be considered as SSDT. Intel ACPI Spec @ 5.2.11.3 */
-	    } else if ((memcmp(adh.signature, SSDT, sizeof(SSDT) - 1) == 0)
-		       || (memcmp(adh.signature, PSDT, sizeof(PSDT) - 1) == 0)) {
-		
-		DEBUG_PRINT(("SSDT table found with %s \n",adh.signature));
-
-		if ((acpi->ssdt_count >= MAX_SSDT - 1))
-		    break;
-
-		/* We can have many SSDT, so let's allocate a new one */
-		if ((acpi->ssdt[acpi->ssdt_count] =
-		     malloc(sizeof(s_ssdt))) == NULL)
-		    break;
-		s_ssdt *s = acpi->ssdt[acpi->ssdt_count];
-
-		/* This structure is valid, let's fill it */
-		s->valid = true;
-		s->address = pointed_address;
-		memcpy(&s->header, &adh, sizeof(adh));
-
-		/* Searching how much definition blocks we must copy */
-		uint32_t definition_block_size = adh.length - ACPI_HEADER_SIZE;
-		if ((s->definition_block =
-		     malloc(definition_block_size)) != NULL) {
-		    memcpy(s->definition_block,
-			   (s->address + ACPI_HEADER_SIZE),
-			   definition_block_size);
-		}
-		/* Increment the number of ssdt we have */
-		acpi->ssdt_count++;
-	    } else if (memcmp(adh.signature, SBST, sizeof(SBST) - 1) == 0) {
-		DEBUG_PRINT(("SBST table found\n"));
-		s_sbst *s = &acpi->sbst;
-		/* This structure is valid, let's fill it */
-		s->valid = true;
-		s->address = pointed_address;
-		memcpy(&s->header, &adh, sizeof(adh));
-		parse_sbst(s);
-	    } else if (memcmp(adh.signature, ECDT, sizeof(ECDT) - 1) == 0) {
-		DEBUG_PRINT(("ECDT table found\n"));
-		s_ecdt *e = &acpi->ecdt;
-		/* This structure is valid, let's fill it */
-		e->valid = true;
-		e->address = pointed_address;
-		memcpy(&e->header, &adh, sizeof(adh));
-		parse_ecdt(e);
+	    if (parse_header(pointed_address, acpi)) {
+		x->entry_count++;
 	    }
-	    x->entry_count++;
 	}
 	return XSDT_TABLE_FOUND;
     }
-
     return -XSDT_TABLE_FOUND;
 }



More information about the Syslinux-commits mailing list