summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwan Velu <erwanaliasr1@gmail.com>2011-01-31 16:32:25 +0100
committerErwan Velu <erwanaliasr1@gmail.com>2011-01-31 16:32:25 +0100
commite5aa41f5789f760b9056908633664ff9d57c4893 (patch)
tree4cb2988f3ec32b8b472a4ecc33d22802232141c5
parent7cb79745098c7b84888646b36bdc1c8a2cf99d85 (diff)
downloadsyslinux-e5aa41f5789f760b9056908633664ff9d57c4893.tar.gz
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.
-rw-r--r--com32/gplinclude/acpi/acpi.h1
-rw-r--r--com32/gpllib/acpi/acpi.c136
-rw-r--r--com32/gpllib/acpi/rsdp.c3
-rw-r--r--com32/gpllib/acpi/rsdt.c23
-rw-r--r--com32/gpllib/acpi/xsdt.c130
5 files changed, 163 insertions, 130 deletions
diff --git a/com32/gplinclude/acpi/acpi.h b/com32/gplinclude/acpi/acpi.h
index db4adc73..1d9a5a06 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 b75647ad..b763e0ba 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 ef5e7dcc..72ea56bc 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 d93a8c20..c9522502 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 f1a6e21a..208abc67 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;
}