From 005e71b7ec54bae2aa9d3a03fbae4f544d1e46ef Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Thu, 3 Dec 2009 21:53:54 +0100 Subject: [PATCH] acpi: Adding FACS, fixing DSDT detection Impact: Adding FACS, fixing DSDT detection Adding FACS, fixing DSDT detection via FADT --- com32/gplinclude/acpi/acpi.h | 3 +- com32/gplinclude/acpi/dsdt.h | 1 + com32/gplinclude/acpi/facs.h | 41 +++++++++++ com32/gpllib/acpi/dsdt.c | 46 +++++++++++++ com32/gpllib/acpi/facs.c | 50 ++++++++++++++ com32/gpllib/acpi/xsdt.c | 160 +++++++++++++++++++++++++++---------------- 6 files changed, 241 insertions(+), 60 deletions(-) create mode 100644 com32/gplinclude/acpi/facs.h create mode 100644 com32/gpllib/acpi/dsdt.c create mode 100644 com32/gpllib/acpi/facs.c diff --git a/com32/gplinclude/acpi/acpi.h b/com32/gplinclude/acpi/acpi.h index 0ce43f5..664306b 100644 --- a/com32/gplinclude/acpi/acpi.h +++ b/com32/gplinclude/acpi/acpi.h @@ -24,13 +24,13 @@ #include #include #include +#include enum { ACPI_FOUND, ENO_ACPI, MADT_FOUND, ENO_MADT }; #define MAX_SSDT 128 /* Some other description HEADERS : ACPI doc: 5.2.6*/ -#define FACS "FACS" #define OEMX "OEMx" #define SRAR "SRAT" #define BERT "BERT" @@ -69,6 +69,7 @@ typedef struct { uint8_t ssdt_count; s_sbst sbst; s_ecdt ecdt; + s_facs facs; } s_acpi; int parse_acpi(s_acpi * acpi); diff --git a/com32/gplinclude/acpi/dsdt.h b/com32/gplinclude/acpi/dsdt.h index 219cb1e..fcb6280 100644 --- a/com32/gplinclude/acpi/dsdt.h +++ b/com32/gplinclude/acpi/dsdt.h @@ -24,4 +24,5 @@ typedef struct { bool valid; } s_dsdt; +void parse_dsdt(s_dsdt *dsdt); #endif diff --git a/com32/gplinclude/acpi/facs.h b/com32/gplinclude/acpi/facs.h new file mode 100644 index 0000000..4435eab --- /dev/null +++ b/com32/gplinclude/acpi/facs.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#ifndef FACS_H +#define FACS_H +#include +#include + +#define FACS "FACS" + +/* Features Flags for "flags" */ +#define S4BIOS_F 1 + +/* Features flags for global_lock */ +#define PENDING 1 +#define OWNED 1<<1 + +typedef struct { + uint64_t address; + uint8_t signature[4+1]; + uint8_t length; + uint32_t hardware_signature; + uint32_t firmware_waking_vector; + uint32_t global_lock; + uint32_t flags; + uint64_t x_firmware_waking_vector; + uint8_t version; + bool valid; +} s_facs; + +void parse_facs(s_facs *facs); +#endif diff --git a/com32/gpllib/acpi/dsdt.c b/com32/gpllib/acpi/dsdt.c new file mode 100644 index 0000000..3c6e177 --- /dev/null +++ b/com32/gpllib/acpi/dsdt.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include "acpi/acpi.h" + +void parse_dsdt(s_dsdt * d) +{ + uint8_t *q; + q = (uint64_t *) (d->address+ACPI_HEADER_SIZE); + + /* Searching how much definition blocks we must copy */ + uint32_t definition_block_size=d->header.length-ACPI_HEADER_SIZE; + if ((d->definition_block=malloc(definition_block_size)) != NULL) { + memcpy(d->definition_block,(uint64_t *)(d->address+ACPI_HEADER_SIZE),definition_block_size); + } + +} diff --git a/com32/gpllib/acpi/facs.c b/com32/gpllib/acpi/facs.c new file mode 100644 index 0000000..0fc0b6b --- /dev/null +++ b/com32/gpllib/acpi/facs.c @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include "acpi/acpi.h" + +void parse_facs(s_facs * f) +{ + uint8_t *q; + q = (uint64_t *) (f->address + ACPI_HEADER_SIZE); + if (memcmp(q, FACS, sizeof(FACS) - 1) == 0) { + f->valid = true; + cp_str_struct(f->signature); + cp_struct(&f->length); + cp_struct(&f->hardware_signature); + cp_struct(&f->firmware_waking_vector); + cp_struct(&f->global_lock); + cp_struct(&f->flags); + cp_struct(&f->x_firmware_waking_vector); + cp_struct(&f->version); + } +} diff --git a/com32/gpllib/acpi/xsdt.c b/com32/gpllib/acpi/xsdt.c index d9e1b8c..ff222b0 100644 --- a/com32/gpllib/acpi/xsdt.c +++ b/com32/gpllib/acpi/xsdt.c @@ -41,7 +41,7 @@ int parse_xsdt(s_acpi * acpi) q = (uint64_t *) acpi->xsdt.address; /* Searching for MADT with APIC signature */ - if (memcmp(q, XSDT, sizeof(XSDT)-1) == 0) { + if (memcmp(q, XSDT, sizeof(XSDT) - 1) == 0) { s_xsdt *x = &acpi->xsdt; x->valid = true; get_acpi_description_header(q, &x->header); @@ -58,67 +58,109 @@ int parse_xsdt(s_acpi * acpi) get_acpi_description_header((uint8_t *) * p, &adh); /* Trying to determine the pointed table */ - /* Looking for MADT*/ - if (memcmp(adh.signature, FACP, sizeof(FACP)-1) == 0) { - s_fadt *f = &acpi->fadt; - /* This structure is valid, let's fill it */ - f->valid=true; - f->address=*p; - memcpy(&f->header,&adh,sizeof(adh)); - parse_fadt(f); - /* Looking for MADT */ - } else if (memcmp(adh.signature, APIC, sizeof(APIC)-1) == 0) { - s_madt *m = &acpi->madt; - /* This structure is valid, let's fill it */ - m->valid=true; - m->address=*p; - memcpy(&m->header,&adh,sizeof(adh)); - parse_madt(acpi); - } else if (memcmp(adh.signature, DSDT, sizeof(DSDT)-1) == 0) { - s_dsdt *d = &acpi->dsdt; - /* This structure is valid, let's fill it */ - d->valid=true; - d->address=*p; - memcpy(&d->header,&adh,sizeof(adh)); - /* Searching how much definition blocks we must copy */ - uint32_t definition_block_size=adh.length-ACPI_HEADER_SIZE; - if ((d->definition_block=malloc(definition_block_size)) != NULL) { - memcpy(d->definition_block,(uint64_t *)(d->address+ACPI_HEADER_SIZE),definition_block_size); - } - /* 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))) { - if ((acpi->ssdt_count >= MAX_SSDT-1)) break; + /* Looking for FADT */ + if (memcmp(adh.signature, FACP, sizeof(FACP) - 1) == 0) { + 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 = *p; + memcpy(&f->header, &adh, sizeof(adh)); + parse_fadt(f); - /* 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]; + /* FACS wasn't already detected + * FADT points to it, let's try to detect it */ + if (fa->valid == false) { + fa->address = f->x_firmware_ctrl; + parse_facs(fa); + if (fa->valid == false) { + /* Let's try again */ + fa->address = f->firmware_ctrl; + parse_facs(fa); + } + } - /* This structure is valid, let's fill it */ - s->valid=true; - s->address=*p; - 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,(uint64_t *)(s->address+ACPI_HEADER_SIZE),definition_block_size); + /* 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) { + d->valid = true; + d->address = 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) { + d->valid = true; + d->address = f->dsdt_address; + memcpy(&d->header, &new_adh, sizeof(new_adh)); + parse_dsdt(d); + } } - /* Increment the number of ssdt we have */ - acpi->ssdt_count++; - } else if (memcmp(adh.signature, SBST, sizeof(SBST)-1) == 0) { - s_sbst *s = &acpi->sbst; - /* This structure is valid, let's fill it */ - s->valid=true; - s->address=*p; - memcpy(&s->header,&adh,sizeof(adh)); - parse_sbst(s); - } else if (memcmp(adh.signature, ECDT, sizeof(ECDT)-1) == 0) { - s_ecdt *e = &acpi->ecdt; - /* This structure is valid, let's fill it */ - e->valid=true; - e->address=*p; - memcpy(&e->header,&adh,sizeof(adh)); - parse_ecdt(e); + } + } /* Looking for MADT */ + else if (memcmp(adh.signature, APIC, sizeof(APIC) - 1) == 0) { + s_madt *m = &acpi->madt; + /* This structure is valid, let's fill it */ + m->valid = true; + m->address = *p; + memcpy(&m->header, &adh, sizeof(adh)); + parse_madt(acpi); + } else if (memcmp(adh.signature, DSDT, sizeof(DSDT) - 1) == 0) { + s_dsdt *d = &acpi->dsdt; + /* This structure is valid, let's fill it */ + d->valid = true; + d->address = *p; + 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))) { + 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 = *p; + 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, + (uint64_t *) (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) { + s_sbst *s = &acpi->sbst; + /* This structure is valid, let's fill it */ + s->valid = true; + s->address = *p; + memcpy(&s->header, &adh, sizeof(adh)); + parse_sbst(s); + } else if (memcmp(adh.signature, ECDT, sizeof(ECDT) - 1) == 0) { + s_ecdt *e = &acpi->ecdt; + /* This structure is valid, let's fill it */ + e->valid = true; + e->address = *p; + memcpy(&e->header, &adh, sizeof(adh)); + parse_ecdt(e); } x->entry_count++; } -- 2.7.4